Mercurial > hg > xemacs-beta
diff src/event-Xt.c @ 2828:a25c824ed558
[xemacs-hg @ 2005-06-26 18:04:49 by aidan]
Rename the ascii-character property, support more keysyms.
author | aidan |
---|---|
date | Sun, 26 Jun 2005 18:05:05 +0000 |
parents | 96036853a107 |
children | c1ec282bb160 |
line wrap: on
line diff
--- a/src/event-Xt.c Sat Jun 25 21:51:12 2005 +0000 +++ b/src/event-Xt.c Sun Jun 26 18:05:05 2005 +0000 @@ -71,7 +71,9 @@ extern int mswindows_is_blocking; #endif -EXFUN (Funicode_to_char, 2); /* In unicode.c. */ +/* For Russian C-x processing. */ +#define FIRST_ALPHABETIC_QWERTY_KEYCODE 24 +#define LAST_ALPHABETIC_QWERTY_KEYCODE 58 /* used in glyphs-x.c */ void enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p); @@ -136,204 +138,26 @@ /* 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.) - */ - -/* 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; - - /* The spec says keysyms in the range #x01000100 to #x0110FFFF and - only those should correspond directly to Unicode code points, in - the range #x100-#x10FFFF; actual implementations can have the Latin - 1 code points do the same thing with keysyms - #x010000A0-#x01000100. Oops. */ - - if (keysym >= 0x010000A0 && keysym <= 0x0110FFFF) - return Funicode_to_char (make_int(keysym & 0xffffff), 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(). -*/ +/* See comment near character_to_event(). */ static void -maybe_define_x_key_as_self_inserting_character (KeySym keysym, Lisp_Object symbol) +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; + extern Lisp_Object Qcharacter_of_keysym; if (NILP (Flookup_key (Vcurrent_global_map, symbol, Qnil))) { - Fput (symbol, Qascii_character, character); + Fput (symbol, Qcharacter_of_keysym, character); Fdefine_key (Vcurrent_global_map, symbol, Qself_insert_command); } } } -static void +void x_has_keysym (KeySym keysym, Lisp_Object hash_table, int with_modifiers) { KeySym upper_lower[2]; @@ -355,7 +179,7 @@ for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++) { - char *name; + Extbyte *name; keysym = upper_lower[j]; name = XKeysymToString (keysym); @@ -371,7 +195,8 @@ EQ (new_value, Qt))) { maybe_define_x_key_as_self_inserting_character (keysym, sym); - Fputhash (build_ext_string (name, Qbinary), new_value, hash_table); + Fputhash (build_ext_string (name, Qbinary), new_value, + hash_table); Fputhash (sym, new_value, hash_table); } } @@ -426,7 +251,7 @@ } } -static const char * +static const Ascbyte * index_to_name (int indice) { switch (indice) @@ -443,18 +268,43 @@ } } -/* 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; -}; +/* 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 + gives a warning. */ static void x_reset_modifier_mapping (struct device *d) @@ -581,7 +431,7 @@ be totally wrong. */ if (mode_bit) { - const char *warn = 0; + const Ascbyte *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; @@ -893,7 +743,9 @@ static Lisp_Object x_keysym_to_emacs_keysym (KeySym keysym, int simple_p) { - char *name; + Extbyte *name; + DECLARE_EISTRING(einame); + 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. */ @@ -914,7 +766,6 @@ case 0: return Qnil; default: if (simple_p) return Qnil; - /* !!#### not Mule-ized */ name = XKeysymToString (keysym); if (!name || !name[0]) /* This happens if there is a mismatch between the Xlib of @@ -942,35 +793,40 @@ case 0x1005FF11: return KEYSYM ("SunF37"); /* labeled F12 */ default: { - char buf [64]; + 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[1]) - return make_char (name[0]); + return make_char ((Ichar)name[0]); + + /* In theory the Host Portable Character Set is just ASCII, but + trusting X11 implementors to get that right is likely to lead to + tears. */ + eicpy_ext(einame, name, Qbinary); /* 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. - */ + The case of the other character sets is significant, however. */ if ((((unsigned int) keysym) & (~0x1FF)) == ((unsigned int) 0xFE00)) { - char buf [255]; - char *s1, *s2; - for (s1 = name, s2 = buf; *s1; s1++, s2++) { - if (*s1 == '_') { - *s2 = '-'; - } else { - *s2 = tolower (* (unsigned char *) s1); + Ibyte *iname; + eilwr(einame); + + for (iname = eidata(einame); *iname != '\0';) + { + if (*iname == '_') + { + *iname = '-'; + } + INC_IBYTEPTR(iname); } - } - *s2 = 0; - return KEYSYM (buf); } - return KEYSYM (name); + return KEYSYM (eidata(einame)); } } @@ -1139,8 +995,14 @@ struct x_device *xd = DEVICE_X_DATA (d); if (DEVICE_X_BEING_DELETED (d)) - /* #### Uh, is this 0 correct? */ - return 0; + { + /* [[ Uh, is this 0 correct? ]] + + Yup--it means emacs_Xt_event_handler, the only place that calls + this, doesn't queue the emacs_event dispatch, instead immediately + deallocating it. */ + return 0; + } set_last_server_timestamp (d, x_event); @@ -1243,9 +1105,22 @@ the keysym) if the keysym isn't a dual-case alphabetic, and if the caps lock key was down but the shift key wasn't, then turn off the shift modifier. Gag barf */ + /* #### type lossage: assuming equivalence of emacs and - X keysyms */ - /* !!#### maybe fix for Mule */ + X keysyms + + The right thing to do here is to have pass a third, pointer, + argument to x_to_emacs_keysym, where it should store the + intermediate KeySym it used to calculate the string XEmacs + keysym. Then we can call keysym_obeys_caps_lock_p with + exactly the right argument. */ + /* !!#### maybe fix for Mule + + Hard, in the absence of a full case infrastructure for + Mule characters. When + (downcase (make-char 'cyrillic-iso8859-5 73)) + works, we should revisit it. */ + if (lock_p && !shift_p && ! (CHAR_OR_CHAR_INTP (keysym) && keysym_obeys_caps_lock_p @@ -1274,6 +1149,29 @@ SET_EVENT_TIMESTAMP (emacs_event, ev->time); SET_EVENT_KEY_MODIFIERS (emacs_event, modifiers); SET_EVENT_KEY_KEYSYM (emacs_event, keysym); + + if (ev->keycode >= FIRST_ALPHABETIC_QWERTY_KEYCODE + && ev->keycode <= LAST_ALPHABETIC_QWERTY_KEYCODE) + { + /* This correspondence isn't guaranteed by the standards, to + my knowledge. Also, it's incomplete--doesn't include the + upper-case characters, etc--I need to get some feedback + on it once this is out in the world and actually being + used by Russians. */ + static const Ascbyte qwerty_map[] = + { 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', + '[', ']', '\015', '\014', + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', + ';', '\'', '`', 0, '\\', + 'z', 'x', 'c', 'v', 'b', 'n', 'm' }; + Ichar val = qwerty_map + [ev->keycode - FIRST_ALPHABETIC_QWERTY_KEYCODE]; + if (val) + { + SET_EVENT_KEY_ALT_KEYCHARS(emacs_event, KEYCHAR_QWERTY, + val); + } + } } else /* Mouse press/release event */ {