diff src/event-stream.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 6fa9919a9a0b
children d7505a1267a4
line wrap: on
line diff
--- a/src/event-stream.c	Sat Jun 25 21:51:12 2005 +0000
+++ b/src/event-stream.c	Sun Jun 26 18:05:05 2005 +0000
@@ -128,6 +128,9 @@
 /* Modifier keys are sticky for this many milliseconds. */
 Lisp_Object Vmodifier_keys_sticky_time;
 
+/* If true, "Russian C-x processing" is enabled. */
+int try_alternate_layouts_for_commands;
+
 /* Here FSF Emacs 20.7 defines Vpost_command_idle_hook,
    post_command_idle_delay, Vdeferred_action_list, and
    Vdeferred_action_function, but we don't because that stuff is crap,
@@ -215,11 +218,6 @@
 Lisp_Object Vretry_undefined_key_binding_unshifted;
 Lisp_Object Qretry_undefined_key_binding_unshifted;
 
-#ifdef MULE
-/* If composed input is undefined, use self-insert-char */
-Lisp_Object Vcomposed_character_default_binding;
-#endif
-
 /* Console that corresponds to our controlling terminal */
 Lisp_Object Vcontrolling_terminal;
 
@@ -2364,7 +2362,7 @@
      Note that last-input-char will never have its high-bit set, in an
      effort to sidestep the ambiguity between M-x and oslash.
      */
-  Vlast_input_char = Fevent_to_character (Vlast_input_event, Qnil, Qnil, Qnil);
+  Vlast_input_char = Fevent_to_character (Vlast_input_event, Qnil, Qnil);
   {
     EMACS_TIME t;
     EMACS_GET_TIME (t);
@@ -3169,7 +3167,7 @@
   if (EQ (Fhash_table_count (Vkeyboard_translate_table), Qzero))
     return;
 
-  c = event_to_character (event, 0, 0, 0);
+  c = event_to_character (event, 0, 0);
   if (c != -1)
     {
       Lisp_Object traduit = Fgethash (make_char (c), Vkeyboard_translate_table,
@@ -3315,12 +3313,14 @@
   return Qnil;
 }
 
-/* Same as command_builder_find_leaf() below but no Russian C-x
-   processing and no defaulting to self-insert-command.
- */
+/* Same as command_builder_find_leaf() below, but without offering the
+   platform-specific event code the opportunity to give a default binding of
+   an unseen keysym to self-insert-command, and without the fallback to
+   other keymaps for lookups that allows someone with a Cyrillic keyboard
+   to pretend it's Qwerty for C-x C-f, for example. */
 
 static Lisp_Object
-command_builder_find_leaf_no_mule_processing (struct command_builder *builder,
+command_builder_find_leaf_no_jit_binding (struct command_builder *builder,
 					      int allow_misc_user_events_p,
 					      int *did_munge)
 {
@@ -3397,7 +3397,7 @@
 	  GCPRO1 (neubauten);
 	  downshift_event (event_chain_tail (neub->current_events));
           result =
-	    command_builder_find_leaf_no_mule_processing
+	    command_builder_find_leaf_no_jit_binding
 	      (neub, allow_misc_user_events_p, did_munge);
 
           if (!NILP (result))
@@ -3442,7 +3442,42 @@
 
    DID_MUNGE must be initialized before calling this function.  If munging
    happened, DID_MUNGE will be non-zero; otherwise, it will be left alone.
- */
+
+   (The above was Ben, I think.)
+
+   It might be nice to have lookup-key call this function, directly or
+   indirectly. Though it is arguably the right thing if lookup-key fails on
+   a keysym that the X11 event code hasn't seen. There's no way to know if
+   that keysym is generatable by the keyboard until it's generated,
+   therefore there's no reasonable expectation that it be bound before it's
+   generated--all the other default bindings depend on our knowing the
+   keyboard layout and relying on it. And describe-key works without it, so
+   I think we're fine.
+
+   Some weirdness with this code--try this on a keyboard where X11 will
+   produce ediaeresis with dead-diaeresis and e, but it's not produced by
+   any other combination of keys on the keyboard;
+
+   (defun ding-command ()
+     (interactive)
+     (ding))
+
+   (define-key global-map 'ediaeresis 'ding-command)
+
+   Now, pressing dead-diaeresis and then e will ding. Next; 
+
+   (define-key global-map 'ediaeresis 'self-insert-command) 
+   
+   and press dead-diaeresis and then e. It'll give you "Invalid argument:
+   typed key has no ASCII equivalent" Then; 
+
+   (define-key global-map 'ediaeresis nil)
+
+   and press the combination again; it'll self-insert. The moral of the
+   story is, if you want to suppress all bindings to a non-ASCII X11 key,
+   bind it to a trivial no-op command, because the automatic mapping to
+   self-insert-command will happen if there's no existing binding for the
+   symbol. I can't see a way around this. -- Aidan Kehoe, 2005-05-14 */
 
 static Lisp_Object
 command_builder_find_leaf (struct command_builder *builder,
@@ -3450,24 +3485,141 @@
 			   int *did_munge)
 {
   Lisp_Object result =
-    command_builder_find_leaf_no_mule_processing
+    command_builder_find_leaf_no_jit_binding
       (builder, allow_misc_user_events_p, did_munge);
+  Lisp_Object event, console, channel, lookup_res;
+  int redolookup = 0, i;
 
   if (!NILP (result))
     return result;
 
-#ifdef MULE
-  /* #### Do Russian C-x processing here */
-
-  /* If keysym is a non-ASCII char, bind it to self-insert-char by default. */
-  if (XEVENT_TYPE (builder->most_current_event) == key_press_event
-      && !NILP (Vcomposed_character_default_binding))
+  /* If some of the events are keyboard events, and this is the first time
+     the platform event code has seen their keysyms--which will be the case
+     the first time we see a composed keysym on X11, for example--offer it
+     the chance to define them as a self-insert-command, and do the lookup
+     again.
+
+     This isn't Mule-specific; in a world where x-iso8859-1.el is gone, it's
+     needed for non-Mule too.
+
+     Probably this can just be limited to the checking the last
+     keypress. */
+
+  EVENT_CHAIN_LOOP (event, builder->current_events)
+    {
+      /* We can ignore key release events because the preceding presses will
+     	 have initiated the mapping. */
+      if (key_press_event != XEVENT_TYPE (event))
+     	continue;
+
+      channel = XEVENT_CHANNEL (event);
+      if (object_dead_p (channel))
+	continue;
+
+      console = CDFW_CONSOLE (channel);
+      if (NILP (console))
+     	console = Vselected_console;
+
+      if (CONSOLE_LIVE_P(XCONSOLE(console)))
+	{
+	  lookup_res = MAYBE_LISP_CONMETH(XCONSOLE(console), 
+					  perhaps_init_unseen_key_defaults, 
+					  (XCONSOLE(console),
+					   XEVENT_KEY_KEYSYM(event)));
+	  if (EQ(lookup_res, Qt))
+	    {
+	      redolookup += 1;
+	    }
+	}
+    }
+
+  if (redolookup)
     {
-      Lisp_Object keysym = XEVENT_KEY_KEYSYM (builder->most_current_event);
-      if (CHARP (keysym) && !ichar_ascii_p (XCHAR (keysym)))
-        return Vcomposed_character_default_binding;
+      result = command_builder_find_leaf_no_jit_binding
+	(builder, allow_misc_user_events_p, did_munge);
+      if (!NILP (result))
+	{
+	  return result;
+	}
+    }
+
+  /* The old composed-character-default-binding handling that used to be
+     here was wrong--if a user wants to bind a given key to something other
+     than self-insert-command, then they should go ahead and do it, we won't
+     override it, and the sane thing to do with any key that has a known
+     character correspondence is _always_ to default it to
+     self-insert-command, nothing else.
+
+     I'm adding the variable to control whether "Russian C-x processing" is
+     used because I have a feeling that it's not always the most appropriate
+     thing to do--in cases where people are using a non-Qwerty
+     Roman-alphabet layout, do they really want C-x with some random letter
+     to call `switch-to-buffer'? I can imagine that being very confusing,
+     certainly for new users, and it might be that defaulting the value for
+     `try-alternate-layouts-for-commands' as part of the language
+     environment is the right thing to do, only defaulting to `t' for those
+     languages that don't use the Roman alphabet. 
+
+     Much of that reasoning is tentative on my part, and feel free to change
+     this code if you have more experience with the problem and an intuition
+     that differs from mine. (Aidan Kehoe, 2005-05-29)*/ 
+
+  if (!try_alternate_layouts_for_commands)
+    {
+      return Qnil; 
     }
-#endif
+
+  if (key_press_event == XEVENT_TYPE (builder->most_current_event))
+    {
+      Lisp_Object ev = builder->most_current_event, newbuilder;
+      Ichar this_alternative;
+
+      struct command_builder *newb;
+      struct gcpro gcpro1;
+
+      /* Ignore the value for CURRENT_LANGENV, because we've checked it
+	 already, above. */
+      for (i = KEYCHAR_CURRENT_LANGENV, ++i; i < KEYCHAR_LAST; ++i)
+	{
+	  this_alternative = XEVENT_KEY_ALT_KEYCHARS(ev, i);
+
+	  if (0 == this_alternative)
+	    continue;
+
+	  newbuilder = copy_command_builder(builder, 0);
+	  GCPRO1(newbuilder);
+
+	  newb = XCOMMAND_BUILDER(newbuilder);
+
+	  XSET_EVENT_KEY_KEYSYM(event_chain_tail (newbuilder->current_events), 
+				make_char(this_alternative));
+
+	  result = command_builder_find_leaf_no_jit_binding
+	    (newb, allow_misc_user_events_p, did_munge);
+
+	  if (!NILP (result))
+	    {
+	      copy_command_builder (newb, builder);
+	      *did_munge = 1;
+	    }
+	  else if (event_upshifted_p (newbuilder->most_current_event) &&
+		   !NILP (Vretry_undefined_key_binding_unshifted)
+		   && isascii(this_alternative))
+	    {
+	      downshift_event (event_chain_tail (newbuilder->current_events));
+	      XSET_EVENT_KEY_KEYSYM(event_chain_tail (newb->current_events), 
+				    make_char(tolower(this_alternative)));
+	      result = command_builder_find_leaf_no_jit_binding
+		(newb, allow_misc_user_events_p, did_munge);
+	    }
+
+	  free_command_builder (newb);
+	  UNGCPRO;
+
+	  if (!NILP (result))
+	    return result;
+	}
+    }
 
   return Qnil;
 }
@@ -4096,7 +4248,7 @@
   /* Note that last-command-char will never have its high-bit set, in
      an effort to sidestep the ambiguity between M-x and oslash. */
   Vlast_command_char = Fevent_to_character (Vlast_command_event,
-					    Qnil, Qnil, Qnil);
+					    Qnil, Qnil);
 
   /* Actually call the command, with all sorts of hair to preserve or clear
      the echo-area and region as appropriate and call the pre- and post-
@@ -5062,17 +5214,6 @@
 */ );
   Vmodifier_keys_sticky_time = make_int (500);
 
-#ifdef MULE
-  DEFVAR_LISP ("composed-character-default-binding",
-               &Vcomposed_character_default_binding /*
-The default keybinding to use for key events from composed input.
-Window systems frequently have ways to allow the user to compose
-single characters in a language using multiple keystrokes.
-XEmacs sees these as single character keypress events.
-*/ );
-  Vcomposed_character_default_binding = Qself_insert_command;
-#endif
-
   Vcontrolling_terminal = Qnil;
   staticpro (&Vcontrolling_terminal);
 
@@ -5118,13 +5259,32 @@
   debug_emacs_events = 0;
 #endif
 
-  DEFVAR_BOOL ("inhibit-input-event-recording", &inhibit_input_event_recording /*
+  DEFVAR_BOOL ("inhibit-input-event-recording",
+	       &inhibit_input_event_recording /*
 Non-nil inhibits recording of input-events to recent-keys ring.
 */ );
   inhibit_input_event_recording = 0;
 
   Vkeyboard_translate_table =
     make_lisp_hash_table (100, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
+
+  DEFVAR_BOOL ("try-alternate-layouts-for-commands",
+	       &try_alternate_layouts_for_commands /*
+Non-nil means that if looking up a command from a sequence of keys typed by
+the user would otherwise fail, try it again with some other keyboard
+layout. On X11, the only alternative to the default mapping is American
+QWERTY; on Windows, other mappings may be available, depending on things
+like the default language environment for the current user, for the system,
+&c.
+
+With a Russian keyboard layout on X11, for example, this means that
+C-Cyrillic_che C-Cyrillic_a, if you haven't given that sequence a binding
+yourself, will invoke `find-file.' This is because `Cyrillic_che' is
+physically where `x' is, and `Cyrillic_a' is where `f' is, on an American
+Qwerty layout, and, of course, C-x C-f is a default emacs binding for that
+command.
+*/ );
+  try_alternate_layouts_for_commands = 1;
 }
 
 void