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 */
 	  {