]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
Merge from emacs--rel--22
[gnu-emacs] / src / keyboard.c
index 527a4151ba9de15d7e8bca305941465358fe7436..8afc81554aef917fcf77172805575af80c2420ca 100644 (file)
@@ -1,7 +1,7 @@
 /* Keyboard and mouse input; editor command loop.
    Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995,
                  1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007 Free Software Foundation, Inc.
+                 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -95,33 +95,7 @@ volatile int interrupt_input_blocked;
    during the current critical section.  */
 int interrupt_input_pending;
 
-
-#ifdef HAVE_WINDOW_SYSTEM
-/* Make all keyboard buffers much bigger when using X windows.  */
-#ifdef MAC_OS8
-/* But not too big (local data > 32K error) if on Mac OS Classic.  */
-#define KBD_BUFFER_SIZE 512
-#else
 #define KBD_BUFFER_SIZE 4096
-#endif
-#else  /* No X-windows, character input */
-#define KBD_BUFFER_SIZE 4096
-#endif /* No X-windows */
-
-/* Following definition copied from eval.c */
-
-struct backtrace
-  {
-    struct backtrace *next;
-    Lisp_Object *function;
-    Lisp_Object *args; /* Points to vector of args. */
-    int nargs;         /* length of vector.  If nargs is UNEVALLED,
-                          args points to slot holding list of
-                          unevalled args */
-    char evalargs;
-    /* Nonzero means call value of debugger when done with this operation. */
-    char debug_on_exit;
-  };
 
 #ifdef MULTI_KBOARD
 KBOARD *initial_kboard;
@@ -175,8 +149,6 @@ extern int minbuf_level;
 
 extern int message_enable_multibyte;
 
-extern struct backtrace *backtrace_list;
-
 /* If non-nil, the function that implements the display of help.
    It's called with one argument, the help string to display.  */
 
@@ -514,7 +486,9 @@ Lisp_Object Qsave_session;
 #ifdef MAC_OS
 Lisp_Object Qmac_apple_event;
 #endif
-
+#ifdef HAVE_DBUS
+Lisp_Object Qdbus_event;
+#endif
 /* Lisp_Object Qmouse_movement; - also an event header */
 
 /* Properties of event headers.  */
@@ -1563,14 +1537,13 @@ command_loop_1 ()
   int nonundocount;
   Lisp_Object keybuf[30];
   int i;
-  int no_direct;
   int prev_modiff = 0;
   struct buffer *prev_buffer = NULL;
 #if 0 /* This shouldn't be necessary anymore.  --lorentey  */
 #ifdef MULTI_KBOARD
   int was_locked = single_kboard;
 #endif
-#endif  
+#endif
   int already_adjusted = 0;
 
   current_kboard->Vprefix_arg = Qnil;
@@ -1623,8 +1596,6 @@ command_loop_1 ()
       while (pending_malloc_warning)
        display_malloc_warning ();
 
-      no_direct = 0;
-
       Vdeactivate_mark = Qnil;
 
       /* If minibuffer on and echo area in use,
@@ -1785,7 +1756,7 @@ command_loop_1 ()
        }
       else
        {
-         if (NILP (current_kboard->Vprefix_arg) && ! no_direct)
+         if (NILP (current_kboard->Vprefix_arg))
            {
              /* In case we jump to directly_done.  */
              Vcurrent_prefix_arg = current_kboard->Vprefix_arg;
@@ -2383,6 +2354,9 @@ make_ctrl_char (c)
   /* Save the upper bits here.  */
   int upper = c & ~0177;
 
+  if (! ASCII_BYTE_P (c))
+    return c |= ctrl_modifier;
+
   c &= 0177;
 
   /* Everything in the columns containing the upper-case letters
@@ -2566,7 +2540,7 @@ do { if (polling_stopped_here) start_polling ();  \
    USED_MOUSE_MENU is null, we don't dereference it.
 
    Value is -2 when we find input on another keyboard.  A second call
-   to read_char will read it. 
+   to read_char will read it.
 
    If END_TIME is non-null, it is a pointer to an EMACS_TIME
    specifying the maximum time to wait until.  If no input arrives by
@@ -2733,6 +2707,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
   /* if redisplay was requested */
   if (commandflag >= 0)
     {
+      int echo_current = EQ (echo_message_buffer, echo_area_buffer[0]);
+
        /* If there is pending input, process any events which are not
           user-visible, such as X selection_request events.  */
       if (input_pending
@@ -2756,6 +2732,12 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
          swallow_events (0);
          /* If that cleared input_pending, try again to redisplay.  */
        }
+
+      /* Prevent the redisplay we just did
+        from messing up echoing of the input after the prompt.  */
+      if (commandflag == 0 && echo_current)
+       echo_message_buffer = echo_area_buffer[0];
+
     }
 
   /* Message turns off echoing unless more keystrokes turn it on again.
@@ -3181,7 +3163,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
       int count = SPECPDL_INDEX ();
       record_single_kboard_state ();
 #endif
-      
+
       last_input_char = c;
       Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
 
@@ -4097,7 +4079,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
         events.  */
       if (CONSP (Vunread_command_events))
        break;
-      
+
       if (kbd_fetch_ptr != kbd_store_ptr)
        break;
 #if defined (HAVE_MOUSE) || defined (HAVE_GPM)
@@ -4309,6 +4291,13 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
          internal_last_event_frame = frame;
          kbd_fetch_ptr = event + 1;
        }
+#ifdef HAVE_DBUS
+      else if (event->kind == DBUS_EVENT)
+       {
+         obj = make_lispy_event (event);
+         kbd_fetch_ptr = event + 1;
+       }
+#endif
       else
        {
          /* If this event is on a different frame, return a switch-frame this
@@ -5549,41 +5538,32 @@ make_lispy_event (event)
     {
       /* A simple keystroke.  */
     case ASCII_KEYSTROKE_EVENT:
-      {
-       Lisp_Object lispy_c;
-       int c = event->code & 0377;
-       /* Turn ASCII characters into control characters
-          when proper.  */
-       if (event->modifiers & ctrl_modifier)
-         c = make_ctrl_char (c);
-
-       /* Add in the other modifier bits.  We took care of ctrl_modifier
-          just above, and the shift key was taken care of by the X code,
-          and applied to control characters by make_ctrl_char.  */
-       c |= (event->modifiers
-             & (meta_modifier | alt_modifier
-                | hyper_modifier | super_modifier));
-       /* Distinguish Shift-SPC from SPC.  */
-       if ((event->code & 0377) == 040
-           && event->modifiers & shift_modifier)
-         c |= shift_modifier;
-       button_down_time = 0;
-       XSETFASTINT (lispy_c, c);
-       return lispy_c;
-      }
-
     case MULTIBYTE_CHAR_KEYSTROKE_EVENT:
       {
        Lisp_Object lispy_c;
        int c = event->code;
+       if (event->kind == ASCII_KEYSTROKE_EVENT)
+         {
+           c &= 0377;
+           eassert (c == event->code);
+           /* Turn ASCII characters into control characters
+              when proper.  */
+           if (event->modifiers & ctrl_modifier)
+             {
+               c = make_ctrl_char (c);
+               event->modifiers &= ~ctrl_modifier;
+             }
+         }
 
-       /* Add in the other modifier bits.  We took care of ctrl_modifier
-          just above, and the shift key was taken care of by the X code,
-          and applied to control characters by make_ctrl_char.  */
+       /* Add in the other modifier bits.  The shift key was taken care
+          of by the X code.  */
        c |= (event->modifiers
              & (meta_modifier | alt_modifier
                 | hyper_modifier | super_modifier | ctrl_modifier));
-       /* What about the `shift' modifier ?  */
+       /* Distinguish Shift-SPC from SPC.  */
+       if ((event->code) == 040
+           && event->modifiers & shift_modifier)
+         c |= shift_modifier;
        button_down_time = 0;
        XSETFASTINT (lispy_c, c);
        return lispy_c;
@@ -6187,6 +6167,13 @@ make_lispy_event (event)
       }
 #endif
 
+#ifdef HAVE_DBUS
+    case DBUS_EVENT:
+      {
+       return Fcons (Qdbus_event, event->arg);
+      }
+#endif /* HAVE_DBUS */
+
 #ifdef HAVE_GPM
     case GPM_CLICK_EVENT:
       {
@@ -6505,12 +6492,21 @@ lispy_modifier_list (modifiers)
    SYMBOL's Qevent_symbol_element_mask property, and maintains the
    Qevent_symbol_elements property.  */
 
+#define KEY_TO_CHAR(k) (XINT (k) & ((1 << CHARACTERBITS) - 1))
+
 Lisp_Object
 parse_modifiers (symbol)
      Lisp_Object symbol;
 {
   Lisp_Object elements;
 
+  if (INTEGERP (symbol))
+    return (Fcons (make_number (KEY_TO_CHAR (symbol)),
+                  Fcons (make_number (XINT (symbol) & CHAR_MODIFIER_MASK),
+                         Qnil)));
+  else if (!SYMBOLP (symbol))
+    return Qnil;
+
   elements = Fget (symbol, Qevent_symbol_element_mask);
   if (CONSP (elements))
     return elements;
@@ -6578,6 +6574,9 @@ apply_modifiers (modifiers, base)
   /* Mask out upper bits.  We don't know where this value's been.  */
   modifiers &= INTMASK;
 
+  if (INTEGERP (base))
+    return make_number (XINT (base) | modifiers);
+
   /* The click modifier never figures into cache indices.  */
   cache = Fget (base, Qmodifier_cache);
   XSETFASTINT (index, (modifiers & ~click_modifier));
@@ -6989,6 +6988,11 @@ void
 gobble_input (expected)
      int expected;
 {
+#ifdef HAVE_DBUS
+  /* Check whether a D-Bus message has arrived.  */
+  xd_read_queued_messages ();
+#endif /* HAVE_DBUS */
+
 #ifndef VMS
 #ifdef SIGIO
   if (interrupt_input)
@@ -7108,7 +7112,7 @@ read_avail_input (expected)
               nread += nr;
               expected = 0;
             }
-          
+
           if (nr == -1)          /* Not OK to read input now. */
             {
               err = 1;
@@ -7116,7 +7120,7 @@ read_avail_input (expected)
           else if (nr == -2)          /* Non-transient error. */
             {
               /* The terminal device terminated; it should be closed. */
-              
+
               /* Kill Emacs if this was our last terminal. */
               if (!terminal_list->next_terminal)
                 /* Formerly simply reported no input, but that
@@ -7128,7 +7132,7 @@ read_avail_input (expected)
                    group?  Perhaps on systems with FIONREAD Emacs is
                    alone in its group.  */
                 kill (getpid (), SIGHUP);
-              
+
               /* XXX Is calling delete_terminal safe here?  It calls Fdelete_frame. */
               if (t->delete_terminal_hook)
                 (*t->delete_terminal_hook) (t);
@@ -7230,7 +7234,7 @@ tty_read_avail_input (struct terminal *terminal,
   if (n_to_read > sizeof cbuf)
     n_to_read = sizeof cbuf;
 #else /* no FIONREAD */
-#if defined (USG) || defined (DGUX) || defined(CYGWIN)
+#if defined (USG) || defined(CYGWIN)
   /* Read some input if available, but don't wait.  */
   n_to_read = sizeof cbuf;
   fcntl (fileno (tty->input), F_SETFL, O_NDELAY);
@@ -7280,9 +7284,9 @@ tty_read_avail_input (struct terminal *terminal,
          );
 
 #ifndef FIONREAD
-#if defined (USG) || defined (DGUX) || defined (CYGWIN)
+#if defined (USG) || defined (CYGWIN)
   fcntl (fileno (tty->input), F_SETFL, 0);
-#endif /* USG or DGUX or CYGWIN */
+#endif /* USG or CYGWIN */
 #endif /* no FIONREAD */
 
   if (nread <= 0)
@@ -7301,14 +7305,14 @@ tty_read_avail_input (struct terminal *terminal,
         buf.modifiers = meta_modifier;
       if (tty->meta_key != 2)
         cbuf[i] &= ~0x80;
-      
+
       buf.code = cbuf[i];
       /* Set the frame corresponding to the active tty.  Note that the
          value of selected_frame is not reliable here, redisplay tends
          to temporarily change it. */
       buf.frame_or_window = tty->top_frame;
       buf.arg = Qnil;
-      
+
       kbd_buffer_store_event (&buf);
       /* Don't look at input that follows a C-g too closely.
          This reduces lossage due to autorepeat on C-g.  */
@@ -8106,7 +8110,8 @@ parse_menu_item (item, notreal, inmenubar)
   tem = XCDR (cachelist);
   if (newcache && !NILP (tem))
     {
-      tem = concat3 (build_string ("  ("), tem, build_string (")"));
+      tem = concat2 (build_string ("  "), tem);
+      // tem = concat3 (build_string ("  ("), tem, build_string (")"));
       XSETCDR (cachelist, tem);
     }
 
@@ -9224,7 +9229,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   last_nonmenu_event = Qnil;
 
   delayed_switch_frame = Qnil;
-  
+
   if (INTERACTIVE)
     {
       if (!NILP (prompt))
@@ -9586,7 +9591,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
            }
 
          GROW_RAW_KEYBUF;
-         XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
+         ASET (raw_keybuf, raw_keybuf_count++, key);
        }
 
       /* Clicks in non-text areas get prefixed by the symbol
@@ -10083,66 +10088,47 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 
       /* If KEY is not defined in any of the keymaps,
         and cannot be part of a function key or translation,
-        and is an upper case letter
-        use the corresponding lower-case letter instead.  */
+        and is an upper case letter or shifted key,
+        use the corresponding lower-case/unshifted key instead.  */
       if (first_binding >= nmaps
-         && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
-         && INTEGERP (key)
-         && ((((XINT (key) & 0x3ffff)
-               < XCHAR_TABLE (current_buffer->downcase_table)->size)
-              && UPPERCASEP (XINT (key) & 0x3ffff))
-             || (XINT (key) & shift_modifier)))
-       {
-         Lisp_Object new_key;
-
-         original_uppercase = key;
-         original_uppercase_position = t - 1;
-
-         if (XINT (key) & shift_modifier)
-           XSETINT (new_key, XINT (key) & ~shift_modifier);
-         else
-           XSETINT (new_key, (DOWNCASE (XINT (key) & 0x3ffff)
-                              | (XINT (key) & ~0x3ffff)));
-
-         /* We have to do this unconditionally, regardless of whether
-            the lower-case char is defined in the keymaps, because they
-            might get translated through function-key-map.  */
-         keybuf[t - 1] = new_key;
-         mock_input = max (t, mock_input);
-
-         goto replay_sequence;
-       }
-      /* If KEY is not defined in any of the keymaps,
-        and cannot be part of a function key or translation,
-        and is a shifted function key,
-        use the corresponding unshifted function key instead.  */
-      if (first_binding >= nmaps
-         && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
-         && SYMBOLP (key))
-       {
-         Lisp_Object breakdown;
-         int modifiers;
-
-         breakdown = parse_modifiers (key);
-         modifiers = XINT (XCAR (XCDR (breakdown)));
-         if (modifiers & shift_modifier)
+         && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t)
+       {
+         Lisp_Object breakdown = parse_modifiers (key);
+         int modifiers
+           = CONSP (breakdown) ? (XINT (XCAR (XCDR (breakdown)))) : 0;
+
+         if (modifiers & shift_modifier
+             /* Treat uppercase keys as shifted.  */
+             || (INTEGERP (key)
+                 && (KEY_TO_CHAR (key)
+                     < XCHAR_TABLE (current_buffer->downcase_table)->size)
+                 && UPPERCASEP (KEY_TO_CHAR (key))))
            {
-             Lisp_Object new_key;
+             Lisp_Object new_key
+               = (modifiers & shift_modifier
+                  ? apply_modifiers (modifiers & ~shift_modifier,
+                                     XCAR (breakdown))
+                  : make_number (DOWNCASE (KEY_TO_CHAR (key)) | modifiers));
 
              original_uppercase = key;
              original_uppercase_position = t - 1;
 
-             modifiers &= ~shift_modifier;
-             new_key = apply_modifiers (modifiers,
-                                        XCAR (breakdown));
-
+             /* We have to do this unconditionally, regardless of whether
+                the lower-case char is defined in the keymaps, because they
+                might get translated through function-key-map.  */
              keybuf[t - 1] = new_key;
              mock_input = max (t, mock_input);
+             /* Reset fkey (and consequently keytran) to apply
+                function-key-map on the result, so that S-backspace is
+                correctly mapped to DEL (via backspace).  OTOH,
+                input-decode-map doesn't need to go through it again.  */
+             fkey.start = fkey.end = 0;
+             keytran.start = keytran.end = 0;
+
              goto replay_sequence;
            }
        }
     }
-
   if (!dummyflag)
     read_key_sequence_cmd = (first_binding < nmaps
                             ? defs[first_binding]
@@ -10357,7 +10343,6 @@ a special event, so ignore the prefix argument and don't clear it.  */)
   register Lisp_Object final;
   register Lisp_Object tem;
   Lisp_Object prefixarg;
-  struct backtrace backtrace;
   extern int debug_on_next_call;
 
   debug_on_next_call = 0;
@@ -10423,20 +10408,11 @@ a special event, so ignore the prefix argument and don't clear it.  */)
     }
 
   if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
-    {
-      backtrace.next = backtrace_list;
-      backtrace_list = &backtrace;
-      backtrace.function = &Qcall_interactively;
-      backtrace.args = &cmd;
-      backtrace.nargs = 1;
-      backtrace.evalargs = 0;
-      backtrace.debug_on_exit = 0;
+    /* Don't call Fcall_interactively directly because we want to make
+       sure the backtrace has an entry for `call-interactively'.
+       For the same reason, pass `cmd' rather than `final'.  */
+      return call3 (Qcall_interactively, cmd, record_flag, keys);
 
-      tem = Fcall_interactively (cmd, record_flag, keys);
-
-      backtrace_list = backtrace.next;
-      return tem;
-    }
   return Qnil;
 }
 
@@ -10547,7 +10523,7 @@ give to the command you invoke, if it asks for an argument.  */)
     bindings = Qnil;
 
   value = Qnil;
-  GCPRO2 (bindings, value);
+  GCPRO3 (bindings, value, function);
   value = Fcommand_execute (function, Qt, Qnil, Qnil);
 
   /* If the command has a key binding, print it now.  */
@@ -11259,7 +11235,7 @@ See also `current-input-mode'.  */)
   new_interrupt_input = 1;
 #endif
 
-  if (new_interrupt_input != interrupt_input) 
+  if (new_interrupt_input != interrupt_input)
     {
 #ifdef POLL_FOR_INPUT
       stop_polling ();
@@ -11339,7 +11315,7 @@ See also `current-input-mode'.  */)
   struct terminal *t = get_terminal (terminal, 1);
   struct tty_display_info *tty;
   int new_meta;
-  
+
   if (t == NULL || t->type != output_termcap)
     return Qnil;
   tty = t->display_info.tty;
@@ -11351,7 +11327,7 @@ See also `current-input-mode'.  */)
   else
     new_meta = 2;
 
-  if (tty->meta_key != new_meta) 
+  if (tty->meta_key != new_meta)
     {
 #ifndef DOS_NT
       /* this causes startup screen to be restored and messes with the mouse */
@@ -11359,7 +11335,7 @@ See also `current-input-mode'.  */)
 #endif
 
       tty->meta_key = new_meta;
-  
+
 #ifndef DOS_NT
       init_sys_modes (tty);
 #endif
@@ -11391,7 +11367,7 @@ See also `current-input-mode'.  */)
   /* this causes startup screen to be restored and messes with the mouse */
   reset_sys_modes (tty);
 #endif
-  
+
   /* Don't let this value be out of range.  */
   quit_char = XINT (quit) & (tty->meta_key == 0 ? 0177 : 0377);
 
@@ -11401,7 +11377,7 @@ See also `current-input-mode'.  */)
 
   return Qnil;
 }
-       
+
 DEFUN ("set-input-mode", Fset_input_mode, Sset_input_mode, 3, 4, 0,
        doc: /* Set mode of reading keyboard input.
 First arg INTERRUPT non-nil means use input interrupts;
@@ -11800,6 +11776,11 @@ syms_of_keyboard ()
   staticpro (&Qmac_apple_event);
 #endif
 
+#ifdef HAVE_DBUS
+  Qdbus_event = intern ("dbus-event");
+  staticpro (&Qdbus_event);
+#endif
+
   Qmenu_enable = intern ("menu-enable");
   staticpro (&Qmenu_enable);
   Qmenu_alias = intern ("menu-alias");
@@ -12362,7 +12343,7 @@ here.  If a mapping is defined in both the current
 `local-function-key-map' binding and this variable, then the local
 definition will take precendence.  */);
   Vfunction_key_map = Fmake_sparse_keymap (Qnil);
-                    
+
   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,
@@ -12484,7 +12465,7 @@ and tool-bar buttons.  */);
   /* Vwindow_system is left at t for now.  */
   initial_kboard->next_kboard = all_kboards;
   all_kboards = initial_kboard;
-#endif  
+#endif
 }
 
 void
@@ -12529,6 +12510,13 @@ keys_of_keyboard ()
    *                       "handle-select-window"); */
   initial_define_lispy_key (Vspecial_event_map, "save-session",
                            "handle-save-session");
+
+#ifdef HAVE_DBUS
+  /* Define a special event which is raised for dbus callback
+     functions.  */
+  initial_define_lispy_key (Vspecial_event_map, "dbus-event",
+                           "dbus-handle-event");
+#endif
 }
 
 /* Mark the pointers in the kboard objects.