diff src/keyboard.c @ 85106:fd282fb888de

Add new `input-decode-map' keymap and use it for temrinal escape sequences. * keyboard.h (struct kboard): Add Vinput_decode_map. Remove Vlocal_key_translation_map. * keyboard.c (read_key_sequence): Add support for input-decode-map. (init_kboard): Init input-decode-map. Replace local-key-translation-map back with key-translation-map. (syms_of_keyboard): Declare input-decode-map. Remove local-key-translation-map. Update docstrings. (mark_kboards): Mark Vinput_decode_map. Don't mark Vlocal_key_translation_map. * keymap.c (Fdescribe_buffer_bindings): Describe input-decode-map. Replace local-key-translation-map back with key-translation-map. * term.c (term_get_fkeys_1, CONDITIONAL_REASSIGN): Bind in input-decode-map rather than function-key-map.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Tue, 09 Oct 2007 05:05:39 +0000
parents 4ed0cd5e3dee
children 5039706521c9
line wrap: on
line diff
--- a/src/keyboard.c	Tue Oct 09 04:28:00 2007 +0000
+++ b/src/keyboard.c	Tue Oct 09 05:05:39 2007 +0000
@@ -445,7 +445,7 @@
 /* Parent keymap of terminal-local function-key-map instances.  */
 Lisp_Object Vfunction_key_map;
 
-/* Parent keymap of terminal-local key-translation-map instances.  */
+/* Keymap of key translations that can override keymaps.  */
 Lisp_Object Vkey_translation_map;
 
 /* List of deferred actions to be performed at a later time.
@@ -9131,8 +9131,8 @@
      key's again in Vfunction_key_map.  */
   volatile keyremap fkey;
 
-  /* Likewise, for key_translation_map.  */
-  volatile keyremap keytran;
+  /* Likewise, for key_translation_map and input-decode-map.  */
+  volatile keyremap keytran, indec;
 
   /* If we receive a `switch-frame' or `select-window' event in the middle of
      a key sequence, we put it off for later.
@@ -9209,8 +9209,10 @@
 
   /* We may switch keyboards between rescans, so we need to
      reinitialize fkey and keytran before each replay.  */
+  indec.map = indec.parent = current_kboard->Vinput_decode_map;
   fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map;
-  keytran.map = keytran.parent = current_kboard->Vlocal_key_translation_map;
+  keytran.map = keytran.parent = Vkey_translation_map;
+  indec.start = indec.end = 0;
   fkey.start = fkey.end = 0;
   keytran.start = keytran.end = 0;
 
@@ -9299,7 +9301,7 @@
 	    Thus, if ESC O a has a function-key-map translation
 	    and ESC o has a binding, don't return after ESC O,
 	    so that we can translate ESC O plus the next character.  */
-	 : (fkey.start < t || keytran.start < t))
+	 : (/* indec.start < t || fkey.start < t || */ keytran.start < t))
     {
       Lisp_Object key;
       int used_mouse_menu = 0;
@@ -9317,13 +9319,17 @@
 	 just one key.  */
       volatile int echo_local_start, keys_local_start, local_first_binding;
 
-      eassert (fkey.end == t || (fkey.end > t && fkey.end <= mock_input));
+      eassert (indec.end == t || (indec.end > t && indec.end <= mock_input));
+      eassert (indec.start <= indec.end);
       eassert (fkey.start <= fkey.end);
       eassert (keytran.start <= keytran.end);
-      /* key-translation-map is applied *after* function-key-map.  */
+      /* key-translation-map is applied *after* function-key-map
+	 which is itself applied *after* input-decode-map.  */
+      eassert (fkey.end <= indec.start);
       eassert (keytran.end <= fkey.start);
 
-      if (first_unbound < fkey.start && first_unbound < keytran.start)
+      if (/* first_unbound < indec.start && first_unbound < fkey.start && */
+	  first_unbound < keytran.start)
 	{ /* The prefix upto first_unbound has no binding and has
 	     no translation left to do either, so we know it's unbound.
 	     If we don't stop now, we risk staying here indefinitely
@@ -9333,6 +9339,8 @@
 	  for (i = first_unbound + 1; i < t; i++)
 	    keybuf[i - first_unbound - 1] = keybuf[i];
 	  mock_input = t - first_unbound - 1;
+	  indec.end = indec.start -= first_unbound + 1;
+	  indec.map = indec.parent;
 	  fkey.end = fkey.start -= first_unbound + 1;
 	  fkey.map = fkey.parent;
 	  keytran.end = keytran.start -= first_unbound + 1;
@@ -9758,15 +9766,15 @@
 	/* This is needed for the following scenario:
 	   event 0: a down-event that gets dropped by calling replay_key.
 	   event 1: some normal prefix like C-h.
-	   After event 0, first_unbound is 0, after event 1 fkey.start
-	   and keytran.start are both 1, so when we see that C-h is bound,
-	   we need to update first_unbound.  */
+	   After event 0, first_unbound is 0, after event 1 indec.start,
+	   fkey.start, and keytran.start are all 1, so when we see that
+	   C-h is bound, we need to update first_unbound.  */
 	first_unbound = max (t + 1, first_unbound);
       else
 	{
 	  Lisp_Object head;
 
-	  /* Remember the position to put an upper bound on fkey.start.  */
+	  /* Remember the position to put an upper bound on indec.start.  */
 	  first_unbound = min (t, first_unbound);
 
 	  head = EVENT_HEAD (key);
@@ -9851,21 +9859,27 @@
 			  /* If mock_input > t + 1, the above simplification
 			     will actually end up dropping keys on the floor.
 			     This is probably OK for now, but even
-			     if mock_input <= t + 1, we need to adjust fkey
-			     and keytran.
+			     if mock_input <= t + 1, we need to adjust indec,
+			     fkey, and keytran.
 			     Typical case [header-line down-mouse-N]:
 			     mock_input = 2, t = 1, fkey.end = 1,
 			     last_real_key_start = 0.  */
-			  if (fkey.end > last_real_key_start)
+			  if (indec.end > last_real_key_start)
 			    {
-			      fkey.end = fkey.start
-				= min (last_real_key_start, fkey.start);
-			      fkey.map = fkey.parent;
-			      if (keytran.end > last_real_key_start)
+			      indec.end = indec.start
+				= min (last_real_key_start, indec.start);
+			      indec.map = indec.parent;
+			      if (fkey.end > last_real_key_start)
 				{
-				  keytran.end = keytran.start
-				    = min (last_real_key_start, keytran.start);
-				  keytran.map = keytran.parent;
+				  fkey.end = fkey.start
+				    = min (last_real_key_start, fkey.start);
+				  fkey.map = fkey.parent;
+				  if (keytran.end > last_real_key_start)
+				    {
+				      keytran.end = keytran.start
+					= min (last_real_key_start, keytran.start);
+				      keytran.map = keytran.parent;
+				    }
 				}
 			    }
 			  if (t == last_real_key_start)
@@ -9919,8 +9933,28 @@
       /* Record what part of this_command_keys is the current key sequence.  */
       this_single_command_key_start = this_command_key_count - t;
 
-      if (first_binding < nmaps && NILP (submaps[first_binding]))
+      /* Look for this sequence in input-decode-map.
+	 Scan from indec.end until we find a bound suffix.  */
+      while (indec.end < t)
+	{
+	  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+	  int done, diff;
+
+	  GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
+	  done = keyremap_step (keybuf, bufsize, &indec, max (t, mock_input),
+				1, &diff, prompt);
+	  UNGCPRO;
+	  if (done)
+	    {
+	      mock_input = diff + max (t, mock_input);
+	      goto replay_sequence;
+	    }
+	}
+
+      if (first_binding < nmaps && NILP (submaps[first_binding])
+	  && indec.start >= t)
 	/* There is a binding and it's not a prefix.
+	   (and it doesn't have any input-decode-map translation pending).
 	   There is thus no function-key in this sequence.
 	   Moving fkey.start is important in this case to allow keytran.start
 	   to go over the sequence before we return (since we keep the
@@ -9933,12 +9967,12 @@
 	/* If the sequence is unbound, see if we can hang a function key
 	   off the end of it.  */
 	/* Continue scan from fkey.end until we find a bound suffix.  */
-	while (fkey.end < t)
+	while (fkey.end < indec.start)
 	  {
-	    struct gcpro gcpro1, gcpro2, gcpro3;
+	    struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 	    int done, diff;
 
-	    GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
+	    GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
 	    done = keyremap_step (keybuf, bufsize, &fkey,
 				  max (t, mock_input),
 				  /* If there's a binding (i.e.
@@ -9950,6 +9984,10 @@
 	    if (done)
 	      {
 		mock_input = diff + max (t, mock_input);
+		/* Adjust the input-decode-map counters.  */
+		indec.end += diff;
+		indec.start += diff;
+
 		goto replay_sequence;
 	      }
 	  }
@@ -9958,17 +9996,19 @@
 	 Scan from keytran.end until we find a bound suffix.  */
       while (keytran.end < fkey.start)
 	{
-	  struct gcpro gcpro1, gcpro2, gcpro3;
+	  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 	  int done, diff;
 
-	  GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
+	  GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
 	  done = keyremap_step (keybuf, bufsize, &keytran, max (t, mock_input),
 				1, &diff, prompt);
 	  UNGCPRO;
 	  if (done)
 	    {
 	      mock_input = diff + max (t, mock_input);
-	      /* Adjust the function-key-map counters.  */
+	      /* Adjust the function-key-map and input-decode-map counters.  */
+	      indec.end += diff;
+	      indec.start += diff;
 	      fkey.end += diff;
 	      fkey.start += diff;
 
@@ -9981,7 +10021,7 @@
 	 and is an upper case letter
 	 use the corresponding lower-case letter instead.  */
       if (first_binding >= nmaps
-	  && fkey.start >= t && keytran.start >= t
+	  && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
 	  && INTEGERP (key)
 	  && ((((XINT (key) & 0x3ffff)
 		< XCHAR_TABLE (current_buffer->downcase_table)->size)
@@ -10012,7 +10052,7 @@
 	 and is a shifted function key,
 	 use the corresponding unshifted function key instead.  */
       if (first_binding >= nmaps
-	  && fkey.start >= t && keytran.start >= t
+	  && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
 	  && SYMBOLP (key))
 	{
 	  Lisp_Object breakdown;
@@ -10033,9 +10073,6 @@
 
 	      keybuf[t - 1] = new_key;
 	      mock_input = max (t, mock_input);
-	      fkey.start = fkey.end = 0;
-	      keytran.start = keytran.end = 0;
-
 	      goto replay_sequence;
 	    }
 	}
@@ -11460,10 +11497,9 @@
   kb->reference_count = 0;
   kb->Vsystem_key_alist = Qnil;
   kb->system_key_syms = Qnil;
+  kb->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
   kb->Vlocal_function_key_map = Fmake_sparse_keymap (Qnil);
   Fset_keymap_parent (kb->Vlocal_function_key_map, Vfunction_key_map);
-  kb->Vlocal_key_translation_map = Fmake_sparse_keymap (Qnil);
-  Fset_keymap_parent (kb->Vlocal_key_translation_map, Vkey_translation_map);
   kb->Vdefault_minibuffer_frame = Qnil;
 }
 
@@ -12196,8 +12232,8 @@
 
   DEFVAR_KBOARD ("local-function-key-map", Vlocal_function_key_map,
                  doc: /* Keymap that translates key sequences to key sequences during input.
-This is used mainly for mapping ASCII function key sequences into
-real Emacs function key events (symbols).
+This is used mainly for mapping key sequences into some preferred
+key events (symbols).
 
 The `read-key-sequence' function replaces any subsequence bound by
 `local-function-key-map' with its binding.  More precisely, when the
@@ -12223,6 +12259,25 @@
 instead.  Initially, `local-function-key-map' is an empty keymap that
 has `function-key-map' as its parent on all terminal devices.  */);
 
+  DEFVAR_KBOARD ("input-decode-map", Vinput_decode_map,
+		 doc: /* Keymap that decodes input escape sequences.
+This is used mainly for mapping ASCII function key sequences into
+real Emacs function key events (symbols).
+
+The `read-key-sequence' function replaces any subsequence bound by
+`local-function-key-map' with its binding.  Contrary to `function-key-map',
+this map applies its rebinding regardless of the presence of an ordinary
+binding.  So it is more like `key-translation-map' except that it applies
+before `function-key-map' rather than after.
+
+If the binding is a function, it is called with one argument (the prompt)
+and its return value (a key sequence) is used.
+
+The events that come from bindings in `input-decode-map' are not
+themselves looked up in `input-decode-map'.
+
+This variable is keyboard-local.  */);
+
   DEFVAR_LISP ("function-key-map", &Vfunction_key_map,
                doc: /* The parent keymap of all `local-function-key-map' instances.
 Function key definitions that apply to all terminal devices should go
@@ -12231,18 +12286,11 @@
 definition will take precendence.  */);
   Vfunction_key_map = Fmake_sparse_keymap (Qnil);
                     
-  DEFVAR_KBOARD ("local-key-translation-map", Vlocal_key_translation_map,
-	       doc: /* Keymap of key translations that can override keymaps.
+  DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
+               doc: /* Keymap of key translations that can override keymaps.
 This keymap works like `function-key-map', but comes after that,
 and its non-prefix bindings override ordinary bindings.
-
-`key-translation-map' has a separate binding for each terminal device.
-(See Info node `(elisp)Multiple displays'.)  If you need to set a key
-translation on all terminals, change `global-key-translation-map' instead.  */);
-
-  DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
-               doc: /* The parent keymap of all `local-key-translation-map' instances.
-Key translations that apply to all terminal devices should go here.  */);
+Another difference is that it is global rather than keyboard-local.  */);
   Vkey_translation_map = Fmake_sparse_keymap (Qnil);
 
   DEFVAR_LISP ("deferred-action-list", &Vdeferred_action_list,
@@ -12420,8 +12468,8 @@
       mark_object (kb->Vlast_kbd_macro);
       mark_object (kb->Vsystem_key_alist);
       mark_object (kb->system_key_syms);
+      mark_object (kb->Vinput_decode_map);
       mark_object (kb->Vlocal_function_key_map);
-      mark_object (kb->Vlocal_key_translation_map);
       mark_object (kb->Vdefault_minibuffer_frame);
       mark_object (kb->echo_string);
     }