Mercurial > hg > xemacs-beta
diff src/event-xlike.c @ 2586:196ee3cd1ac5
[xemacs-hg @ 2005-02-15 01:19:48 by ben]
first check-in of ben-fixup branch
author | ben |
---|---|
date | Tue, 15 Feb 2005 01:21:24 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/event-xlike.c Tue Feb 15 01:21:24 2005 +0000 @@ -0,0 +1,664 @@ +/* Shared event code between X and GTK. + Copyright (C) 1991-5, 1997 Free Software Foundation, Inc. + Copyright (C) 1995 Sun Microsystems, Inc. + Copyright (C) 1996, 2001, 2002, 2003 Ben Wing. + +This file is part of XEmacs. + +XEmacs is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +XEmacs is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with XEmacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Synched up with: Not in FSF. */ + +#include <config.h> +#include "lisp.h" + +#include "charset.h" +#include "elhash.h" +#include "events.h" + +#ifdef HAVE_GTK +#include "console-gtk-impl.h" +#include <gdk/gdkx.h> +#endif +/* Unfortunately GTK currently needs to use some X-specific stuff so we + can't conditionalize the following on HAVE_X_WINDOWS, like we should. + + #### BILL!!! Fix this please! */ +#include "console-x-impl.h" + +#include "device-impl.h" + +#include "toolbar-common.h" + +Lisp_Object Qkey_mapping; +Lisp_Object Qsans_modifiers; + + +/************************************************************************/ +/* keymap handling */ +/************************************************************************/ + +/* X bogusly doesn't define the interpretations of any bits besides + ModControl, ModShift, and ModLock; so the Interclient Communication + Conventions Manual says that we have to bend over backwards to figure + out what the other modifier bits mean. According to ICCCM: + + - Any keycode which is assigned ModControl is a "control" key. + + - Any modifier bit which is assigned to a keycode which generates Meta_L + or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper, + etc. + + - Any keypress event which contains ModControl in its state should be + interpreted as a "control" character. + + - Any keypress event which contains a modifier bit in its state which is + generated by a keycode whose corresponding keysym is Meta_L or Meta_R + should be interpreted as a "meta" character. Likewise for Super, Hyper, + etc. + + - It is illegal for a keysym to be associated with more than one modifier + bit. + + This means that the only thing that emacs can reasonably interpret as a + "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates + one of the modifier bits Mod1-Mod5. + + Unfortunately, many keyboards don't have Meta keys in their default + configuration. So, if there are no Meta keys, but there are "Alt" keys, + emacs will interpret Alt as Meta. If there are both Meta and Alt keys, + then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to + mean "Symbol," but that just confused the hell out of way too many people). + + This works with the default configurations of the 19 keyboard-types I've + checked. + + Emacs detects keyboard configurations which violate the above rules, and + prints an error message on the standard-error-output. (Perhaps it should + use a pop-up-window instead.) + */ + +static Display * +xlike_device_to_display (struct device *d) +{ +#ifdef HAVE_GTK + if (DEVICE_GTK_P (d)) + return GDK_DISPLAY (); +#endif /* HAVE_GTK */ +#ifdef HAVE_X_WINDOWS + if (DEVICE_GTK_P (d)) + return DEVICE_X_DISPLAY (d); +#endif /* HAVE_X_WINDOWS */ + ABORT (); + return NULL; +} + +/* For every key on the keyboard that has a known character correspondence, + we define the ascii-character property of the keysym, and make the + default binding for the key be self-insert-command. + + The following magic is basically intimate knowledge of X11/keysymdef.h. + The keysym mappings defined by X11 are based on the iso8859 standards, + except for Cyrillic and Greek. + + In a non-Mule world, a user can still have a multi-lingual editor, by doing + (set-face-font "...-iso8859-2" (current-buffer)) + for all their Latin-2 buffers, etc. */ + +static Lisp_Object +x_keysym_to_character (KeySym keysym) +{ +#ifdef MULE + Lisp_Object charset = Qzero; +#define USE_CHARSET(var,cs) \ + ((var) = charset_by_leading_byte (LEADING_BYTE_##cs)) +#else +#define USE_CHARSET(var,lb) +#endif /* MULE */ + int code = 0; + + if ((keysym & 0xff) < 0xa0) + return Qnil; + + switch (keysym >> 8) + { + case 0: /* ASCII + Latin1 */ + USE_CHARSET (charset, LATIN_ISO8859_1); + code = keysym & 0x7f; + break; + case 1: /* Latin2 */ + USE_CHARSET (charset, LATIN_ISO8859_2); + code = keysym & 0x7f; + break; + case 2: /* Latin3 */ + USE_CHARSET (charset, LATIN_ISO8859_3); + code = keysym & 0x7f; + break; + case 3: /* Latin4 */ + USE_CHARSET (charset, LATIN_ISO8859_4); + code = keysym & 0x7f; + break; + case 4: /* Katakana */ + USE_CHARSET (charset, KATAKANA_JISX0201); + if ((keysym & 0xff) > 0xa0) + code = keysym & 0x7f; + break; + case 5: /* Arabic */ + USE_CHARSET (charset, ARABIC_ISO8859_6); + code = keysym & 0x7f; + break; + case 6: /* Cyrillic */ + { + static unsigned char const cyrillic[] = /* 0x20 - 0x7f */ + {0x00, 0x72, 0x73, 0x71, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x00, 0x7e, 0x7f, + 0x70, 0x22, 0x23, 0x21, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x00, 0x2e, 0x2f, + 0x6e, 0x50, 0x51, 0x66, 0x54, 0x55, 0x64, 0x53, + 0x65, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, + 0x5f, 0x6f, 0x60, 0x61, 0x62, 0x63, 0x56, 0x52, + 0x6c, 0x6b, 0x57, 0x68, 0x6d, 0x69, 0x67, 0x6a, + 0x4e, 0x30, 0x31, 0x46, 0x34, 0x35, 0x44, 0x33, + 0x45, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x4f, 0x40, 0x41, 0x42, 0x43, 0x36, 0x32, + 0x4c, 0x4b, 0x37, 0x48, 0x4d, 0x49, 0x47, 0x4a}; + USE_CHARSET (charset, CYRILLIC_ISO8859_5); + code = cyrillic[(keysym & 0x7f) - 0x20]; + break; + } + case 7: /* Greek */ + { + static unsigned char const greek[] = /* 0x20 - 0x7f */ + {0x00, 0x36, 0x38, 0x39, 0x3a, 0x5a, 0x00, 0x3c, + 0x3e, 0x5b, 0x00, 0x3f, 0x00, 0x00, 0x35, 0x2f, + 0x00, 0x5c, 0x5d, 0x5e, 0x5f, 0x7a, 0x40, 0x7c, + 0x7d, 0x7b, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x53, 0x00, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x73, 0x72, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + USE_CHARSET (charset, GREEK_ISO8859_7); + code = greek[(keysym & 0x7f) - 0x20]; + break; + } + case 8: /* Technical */ + break; + case 9: /* Special */ + break; + case 10: /* Publishing */ + break; + case 11: /* APL */ + break; + case 12: /* Hebrew */ + USE_CHARSET (charset, HEBREW_ISO8859_8); + code = keysym & 0x7f; + break; + case 13: /* Thai */ + /* #### This needs to deal with character composition. */ + USE_CHARSET (charset, THAI_TIS620); + code = keysym & 0x7f; + break; + case 14: /* Korean Hangul */ + break; + case 19: /* Latin 9 - ISO8859-15 - unsupported charset. */ + break; + case 32: /* Currency */ + break; + default: + break; + } + + if (code == 0) + return Qnil; + +#ifdef MULE + return make_char (make_ichar (charset, code, 0)); +#else + return make_char (code + 0x80); +#endif +} + +/* See comment near character_to_event(). +*/ +static void +maybe_define_x_key_as_self_inserting_character (KeySym keysym, + Lisp_Object symbol) +{ + Lisp_Object character = x_keysym_to_character (keysym); + + if (CHARP (character)) + { + extern Lisp_Object Vcurrent_global_map; + extern Lisp_Object Qascii_character; + if (NILP (Flookup_key (Vcurrent_global_map, symbol, Qnil))) + { + Fput (symbol, Qascii_character, character); + Fdefine_key (Vcurrent_global_map, symbol, Qself_insert_command); + } + } +} + +/* Currently, GDK keysyms are exactly like X keysyms. If this ever + changes, we should rewrite this, but currently there's no point. */ + +Lisp_Object +xlike_keysym_to_emacs_keysym (long keysym, int simple_p) +{ + Ibyte *name; + if (keysym >= XK_exclam && keysym <= XK_asciitilde) + /* We must assume that the X keysym numbers for the ASCII graphic + characters are the same as their ASCII codes. */ + return make_char (keysym); + + switch (keysym) + { + /* These would be handled correctly by the default case, but by + special-casing them here we don't garbage a string or call + intern(). */ + case XK_BackSpace: return QKbackspace; + case XK_Tab: return QKtab; + case XK_Linefeed: return QKlinefeed; + case XK_Return: return QKreturn; + case XK_Escape: return QKescape; + case XK_space: return QKspace; + case XK_Delete: return QKdelete; + case 0: return Qnil; + default: + if (simple_p) return Qnil; + name = NEW_EXTERNAL_TO_C_STRING (XKeysymToString (keysym), + Qx_keysym_encoding); + if (!name || !name[0]) + /* This happens if there is a mismatch between the Xlib of + XEmacs and the Xlib of the X server... + + Let's hard-code in some knowledge of common keysyms introduced + in recent X11 releases. Snarfed from X11/keysymdef.h + + Probably we should add some stuff here for X11R6. */ + switch (keysym) + { + case 0xFF95: return KEYSYM ("kp-home"); + case 0xFF96: return KEYSYM ("kp-left"); + case 0xFF97: return KEYSYM ("kp-up"); + case 0xFF98: return KEYSYM ("kp-right"); + case 0xFF99: return KEYSYM ("kp-down"); + case 0xFF9A: return KEYSYM ("kp-prior"); + case 0xFF9B: return KEYSYM ("kp-next"); + case 0xFF9C: return KEYSYM ("kp-end"); + case 0xFF9D: return KEYSYM ("kp-begin"); + case 0xFF9E: return KEYSYM ("kp-insert"); + case 0xFF9F: return KEYSYM ("kp-delete"); + + case 0x1005FF10: return KEYSYM ("SunF36"); /* labeled F11 */ + case 0x1005FF11: return KEYSYM ("SunF37"); /* labeled F12 */ + default: + { + Ascbyte buf[64]; + sprintf (buf, "unknown-keysym-0x%X", (int) keysym); + return KEYSYM (buf); + } + } + /* If it's got a one-character name, that's good enough. */ + if (!* (name + itext_ichar_len (name))) + return make_char (itext_ichar (name)); + + /* If it's in the "Keyboard" character set, downcase it. + The case of those keysyms is too totally random for us to + force anyone to remember them. + The case of the other character sets is significant, however. + */ + if ((((unsigned int) keysym) & (~0x1FF)) == ((unsigned int) 0xFE00)) + { + Ibyte *buf, *s1; + + IBYTE_STRING_TO_ALLOCA (name, buf); + for (s1 = buf; *s1; s1++) + if (*s1 == '_') + *s1 = '-'; + return LISP_STRING_TO_KEYSYM (Fdowncase (build_intstring (buf), + Qnil)); + } + return KEYSYM ((CIbyte *) name); + } +} + +static void +xlike_has_keysym (KeySym keysym, Lisp_Object hash_table, int with_modifiers) +{ + KeySym upper_lower[2]; + int j; + + if (keysym < 0x80) /* Optimize for ASCII keysyms */ + return; + + /* If you execute: + xmodmap -e 'keysym NN = scaron' + and then press (Shift scaron), X11 will return the different + keysym `Scaron', but `xmodmap -pke' might not even mention `Scaron'. + So we "register" both `scaron' and `Scaron'. */ +#ifdef HAVE_XCONVERTCASE + XConvertCase (keysym, &upper_lower[0], &upper_lower[1]); +#else + upper_lower[0] = upper_lower[1] = keysym; +#endif + + for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++) + { + Extbyte *name = XKeysymToString (keysym); + keysym = upper_lower[j]; + + if (name) + { + /* X guarantees NAME to be in the Host Portable Character Encoding */ + Lisp_Object sym = xlike_keysym_to_emacs_keysym (keysym, 0); + Lisp_Object new_value = with_modifiers ? Qt : Qsans_modifiers; + Lisp_Object old_value = Fgethash (sym, hash_table, Qnil); + + if (! EQ (old_value, new_value) + && ! (EQ (old_value, Qsans_modifiers) && + EQ (new_value, Qt))) + { + maybe_define_x_key_as_self_inserting_character (keysym, sym); + Fputhash (build_ext_string (name, Qx_keysym_encoding), new_value, + hash_table); + Fputhash (sym, new_value, hash_table); + } + } + } +} + +void +xlike_reset_key_mapping (struct device *d, struct xlike_event_key_data *xd) +{ + KeySym *keysym, *keysym_end; + Lisp_Object hash_table; + int key_code_count, keysyms_per_code; + Display *display = xlike_device_to_display (d); + + if (xd->x_keysym_map) + XFree ((char *) xd->x_keysym_map); + XDisplayKeycodes (display, + &xd->x_keysym_map_min_code, + &xd->x_keysym_map_max_code); + key_code_count = xd->x_keysym_map_max_code - xd->x_keysym_map_min_code + 1; + xd->x_keysym_map = + (KeySym *) + XGetKeyboardMapping (display, xd->x_keysym_map_min_code, key_code_count, + &xd->x_keysym_map_keysyms_per_code); + + hash_table = xd->x_keysym_map_hash_table; + if (HASH_TABLEP (hash_table)) + Fclrhash (hash_table); + else + xd->x_keysym_map_hash_table = hash_table = + make_lisp_hash_table (128, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL); + + for (keysym = xd->x_keysym_map, + keysyms_per_code = xd->x_keysym_map_keysyms_per_code, + keysym_end = keysym + (key_code_count * keysyms_per_code); + keysym < keysym_end; + keysym += keysyms_per_code) + { + int j; + if (keysym[0] == NoSymbol) + continue; + + xlike_has_keysym (keysym[0], hash_table, 0); + + for (j = 1; j < keysyms_per_code; j++) + { + if (keysym[j] != keysym[0] && + keysym[j] != NoSymbol) + xlike_has_keysym (keysym[j], hash_table, 1); + } + } +} + +static const char * +index_to_name (int indice) +{ + switch (indice) + { + case ShiftMapIndex: return "ModShift"; + case LockMapIndex: return "ModLock"; + case ControlMapIndex: return "ModControl"; + case Mod1MapIndex: return "Mod1"; + case Mod2MapIndex: return "Mod2"; + case Mod3MapIndex: return "Mod3"; + case Mod4MapIndex: return "Mod4"; + case Mod5MapIndex: return "Mod5"; + default: return "???"; + } +} + +/* Boy, I really wish C had local functions... */ +struct c_doesnt_have_closures /* #### not yet used */ +{ + int warned_about_overlapping_modifiers; + int warned_about_predefined_modifiers; + int warned_about_duplicate_modifiers; + int meta_bit; + int hyper_bit; + int super_bit; + int alt_bit; + int mode_bit; +}; + +void +xlike_reset_modifier_mapping (struct device *d, + struct xlike_event_key_data *xd) +{ + int modifier_index, modifier_key, column, mkpm; + int warned_about_overlapping_modifiers = 0; + int warned_about_predefined_modifiers = 0; + int warned_about_duplicate_modifiers = 0; + int meta_bit = 0; + int hyper_bit = 0; + int super_bit = 0; + int alt_bit = 0; + int mode_bit = 0; + Display *display = xlike_device_to_display (d); + + xd->lock_interpretation = 0; + + if (xd->x_modifier_keymap) + XFreeModifiermap (xd->x_modifier_keymap); + + xlike_reset_key_mapping (d, xd); + + xd->x_modifier_keymap = (XModifierKeymap *) XGetModifierMapping (display); + + /* Boy, I really wish C had local functions... + */ + + /* The call to warn_when_safe must be on the same line as the string or + make-msgfile won't pick it up properly (the newline doesn't confuse + it, but the backslash does). */ + +#define modwarn(name,old,other) \ + warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates %s, which is generated by %s.", \ + name, code, index_to_name (old), other), \ + warned_about_overlapping_modifiers = 1 + +#define modbarf(name,other) \ + warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates %s, which is nonsensical.", \ + name, code, other), \ + warned_about_predefined_modifiers = 1 + +#define check_modifier(name,mask) \ + if ((1<<modifier_index) != mask) \ + warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates %s, which is nonsensical.", \ + name, code, index_to_name (modifier_index)), \ + warned_about_predefined_modifiers = 1 + +#define store_modifier(name,old) \ + if (old && old != modifier_index) \ + warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates both %s and %s, which is nonsensical.",\ + name, code, index_to_name (old), \ + index_to_name (modifier_index)), \ + warned_about_duplicate_modifiers = 1; \ + if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \ + else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \ + else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \ + else if (sym == XK_Mode_switch) \ + mode_bit = modifier_index; /* Mode_switch is special, see below... */ \ + else if (modifier_index == meta_bit && old != meta_bit) \ + modwarn (name, meta_bit, "Meta"); \ + else if (modifier_index == super_bit && old != super_bit) \ + modwarn (name, super_bit, "Super"); \ + else if (modifier_index == hyper_bit && old != hyper_bit) \ + modwarn (name, hyper_bit, "Hyper"); \ + else if (modifier_index == alt_bit && old != alt_bit) \ + modwarn (name, alt_bit, "Alt"); \ + else \ + old = modifier_index; + + mkpm = (xd->x_modifier_keymap)->max_keypermod; + for (modifier_index = 0; modifier_index < 8; modifier_index++) + for (modifier_key = 0; modifier_key < mkpm; modifier_key++) { + KeySym last_sym = 0; + for (column = 0; column < 4; column += 2) { + KeyCode code = + (xd->x_modifier_keymap) + ->modifiermap[modifier_index * mkpm + modifier_key]; + KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0); + if (sym == last_sym) continue; + last_sym = sym; + switch (sym) { + case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break; + case XK_Meta_L: store_modifier ("Meta_L", meta_bit); break; + case XK_Meta_R: store_modifier ("Meta_R", meta_bit); break; + case XK_Super_L: store_modifier ("Super_L", super_bit); break; + case XK_Super_R: store_modifier ("Super_R", super_bit); break; + case XK_Hyper_L: store_modifier ("Hyper_L", hyper_bit); break; + case XK_Hyper_R: store_modifier ("Hyper_R", hyper_bit); break; + case XK_Alt_L: store_modifier ("Alt_L", alt_bit); break; + case XK_Alt_R: store_modifier ("Alt_R", alt_bit); break; + case XK_Control_L: check_modifier ("Control_L", ControlMask); break; + case XK_Control_R: check_modifier ("Control_R", ControlMask); break; + case XK_Shift_L: check_modifier ("Shift_L", ShiftMask); break; + case XK_Shift_R: check_modifier ("Shift_R", ShiftMask); break; + case XK_Shift_Lock: check_modifier ("Shift_Lock", LockMask); + xd->lock_interpretation = XK_Shift_Lock; break; + case XK_Caps_Lock: check_modifier ("Caps_Lock", LockMask); + xd->lock_interpretation = XK_Caps_Lock; break; + + /* It probably doesn't make any sense for a modifier bit to be + assigned to a key that is not one of the above, but OpenWindows + assigns modifier bits to a couple of random function keys for + no reason that I can discern, so printing a warning here would + be annoying. */ + } + } + } +#undef store_modifier +#undef check_modifier +#undef modwarn +#undef modbarf + + /* If there was no Meta key, then try using the Alt key instead. + If there is both a Meta key and an Alt key, then the Alt key + is not disturbed and remains an Alt key. */ + if (! meta_bit && alt_bit) + meta_bit = alt_bit, alt_bit = 0; + + /* mode_bit overrides everything, since it's processed down inside of + XLookupString() instead of by us. If Meta and Mode_switch both + generate the same modifier bit (which is an error), then we don't + interpret that bit as Meta, because we can't make XLookupString() + not interpret it as Mode_switch; and interpreting it as both would + be totally wrong. */ + if (mode_bit) + { + const char *warn = 0; + if (mode_bit == meta_bit) warn = "Meta", meta_bit = 0; + else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0; + else if (mode_bit == super_bit) warn = "Super", super_bit = 0; + else if (mode_bit == alt_bit) warn = "Alt", alt_bit = 0; + if (warn) + { + warn_when_safe + (Qkey_mapping, Qwarning, + "XEmacs: %s is being used for both Mode_switch and %s.", + index_to_name (mode_bit), warn), + warned_about_overlapping_modifiers = 1; + } + } +#undef index_to_name + + xd->MetaMask = (meta_bit ? (1 << meta_bit) : 0); + xd->HyperMask = (hyper_bit ? (1 << hyper_bit) : 0); + xd->SuperMask = (super_bit ? (1 << super_bit) : 0); + xd->AltMask = (alt_bit ? (1 << alt_bit) : 0); + xd->ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */ + + if (warned_about_overlapping_modifiers) + warn_when_safe (Qkey_mapping, Qwarning, "\n" +" Two distinct modifier keys (such as Meta and Hyper) cannot generate\n" +" the same modifier bit, because Emacs won't be able to tell which\n" +" modifier was actually held down when some other key is pressed. It\n" +" won't be able to tell Meta-x and Hyper-x apart, for example. Change\n" +" one of these keys to use some other modifier bit. If you intend for\n" +" these keys to have the same behavior, then change them to have the\n" +" same keysym as well as the same modifier bit."); + + if (warned_about_predefined_modifiers) + warn_when_safe (Qkey_mapping, Qwarning, "\n" +" The semantics of the modifier bits ModShift, ModLock, and ModControl\n" +" are predefined. It does not make sense to assign ModControl to any\n" +" keysym other than Control_L or Control_R, or to assign any modifier\n" +" bits to the \"control\" keysyms other than ModControl. You can't\n" +" turn a \"control\" key into a \"meta\" key (or vice versa) by simply\n" +" assigning the key a different modifier bit. You must also make that\n" +" key generate an appropriate keysym (Control_L, Meta_L, etc)."); + + /* No need to say anything more for warned_about_duplicate_modifiers. */ + + if (warned_about_overlapping_modifiers || warned_about_predefined_modifiers) + warn_when_safe (Qkey_mapping, Qwarning, "\n" +" The meanings of the modifier bits Mod1 through Mod5 are determined\n" +" by the keysyms used to control those bits. Mod1 does NOT always\n" +" mean Meta, although some non-ICCCM-compliant programs assume that."); +} + +void +xlike_init_modifier_mapping (struct device *d, struct xlike_event_key_data *xd) +{ + xd->x_keysym_map_hash_table = Qnil; + xd->x_keysym_map = NULL; + xd->x_modifier_keymap = NULL; + xlike_reset_modifier_mapping (d, xd); +} + +void +free_xlike_event_key_data (struct xlike_event_key_data *xd) +{ + if (xd->x_modifier_keymap) + XFreeModifiermap (xd->x_modifier_keymap); + if (xd->x_keysym_map) + XFree ((char *) xd->x_keysym_map); +} + +void +syms_of_event_xlike (void) +{ + DEFSYMBOL (Qkey_mapping); + DEFSYMBOL (Qsans_modifiers); +}