Fix previous commit for bug #13675.
[bpt/emacs.git] / src / keyboard.c
index 60e6d71..ca7be56 100644 (file)
@@ -1,6 +1,7 @@
 /* Keyboard and mouse input; editor command loop.
 
-Copyright (C) 1985-1989, 1993-1997, 1999-2012  Free Software Foundation, Inc.
+Copyright (C) 1985-1989, 1993-1997, 1999-2013 Free Software Foundation,
+Inc.
 
 This file is part of GNU Emacs.
 
@@ -313,12 +314,18 @@ static Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
 #ifdef HAVE_NTGUI
 Lisp_Object Qlanguage_change;
+#ifdef WINDOWSNT
+Lisp_Object Qfile_w32notify;
+#endif
 #endif
 static Lisp_Object Qdrag_n_drop;
 static Lisp_Object Qsave_session;
 #ifdef HAVE_DBUS
 static Lisp_Object Qdbus_event;
 #endif
+#ifdef HAVE_INOTIFY
+static Lisp_Object Qfile_inotify;
+#endif /* HAVE_INOTIFY */
 static Lisp_Object Qconfig_changed_event;
 
 /* Lisp_Object Qmouse_movement; - also an event header */
@@ -490,97 +497,103 @@ kset_system_key_syms (struct kboard *kb, Lisp_Object val)
 }
 
 \f
-/* Add C to the echo string, if echoing is going on.
-   C can be a character, which is printed prettily ("M-C-x" and all that
-   jazz), or a symbol, whose name is printed.  */
+/* Add C to the echo string, without echoing it immediately.  C can be
+   a character, which is pretty-printed, or a symbol, whose name is
+   printed.  */
 
 static void
-echo_char (Lisp_Object c)
+echo_add_key (Lisp_Object c)
 {
-  if (current_kboard->immediate_echo)
-    {
-      int size = KEY_DESCRIPTION_SIZE + 100;
-      char *buffer = alloca (size);
-      char *ptr = buffer;
-      Lisp_Object echo_string;
+  int size = KEY_DESCRIPTION_SIZE + 100;
+  char *buffer = alloca (size);
+  char *ptr = buffer;
+  Lisp_Object echo_string;
 
-      echo_string = KVAR (current_kboard, echo_string);
+  echo_string = KVAR (current_kboard, echo_string);
 
-      /* If someone has passed us a composite event, use its head symbol.  */
-      c = EVENT_HEAD (c);
+  /* If someone has passed us a composite event, use its head symbol.  */
+  c = EVENT_HEAD (c);
 
-      if (INTEGERP (c))
+  if (INTEGERP (c))
+    ptr = push_key_description (XINT (c), ptr);
+  else if (SYMBOLP (c))
+    {
+      Lisp_Object name = SYMBOL_NAME (c);
+      int nbytes = SBYTES (name);
+
+      if (size - (ptr - buffer) < nbytes)
        {
-         ptr = push_key_description (XINT (c), ptr);
+         int offset = ptr - buffer;
+         size = max (2 * size, size + nbytes);
+         buffer = alloca (size);
+         ptr = buffer + offset;
        }
-      else if (SYMBOLP (c))
-       {
-         Lisp_Object name = SYMBOL_NAME (c);
-         int nbytes = SBYTES (name);
 
-         if (size - (ptr - buffer) < nbytes)
-           {
-             int offset = ptr - buffer;
-             size = max (2 * size, size + nbytes);
-             buffer = alloca (size);
-             ptr = buffer + offset;
-           }
+      ptr += copy_text (SDATA (name), (unsigned char *) ptr, nbytes,
+                       STRING_MULTIBYTE (name), 1);
+    }
 
-         ptr += copy_text (SDATA (name), (unsigned char *) ptr, nbytes,
-                           STRING_MULTIBYTE (name), 1);
-       }
+  if ((NILP (echo_string) || SCHARS (echo_string) == 0)
+      && help_char_p (c))
+    {
+      const char *text = " (Type ? for further options)";
+      int len = strlen (text);
 
-      if ((NILP (echo_string) || SCHARS (echo_string) == 0)
-         && help_char_p (c))
+      if (size - (ptr - buffer) < len)
        {
-         const char *text = " (Type ? for further options)";
-         int len = strlen (text);
-
-         if (size - (ptr - buffer) < len)
-           {
-             int offset = ptr - buffer;
-             size += len;
-             buffer = alloca (size);
-             ptr = buffer + offset;
-           }
-
-         memcpy (ptr, text, len);
-         ptr += len;
+         int offset = ptr - buffer;
+         size += len;
+         buffer = alloca (size);
+         ptr = buffer + offset;
        }
 
-      /* Replace a dash from echo_dash with a space, otherwise
-        add a space at the end as a separator between keys.  */
-      if (STRINGP (echo_string)
-         && SCHARS (echo_string) > 1)
-       {
-         Lisp_Object last_char, prev_char, idx;
+      memcpy (ptr, text, len);
+      ptr += len;
+    }
+
+  /* Replace a dash from echo_dash with a space, otherwise add a space
+     at the end as a separator between keys.  */
+  if (STRINGP (echo_string) && SCHARS (echo_string) > 1)
+    {
+      Lisp_Object last_char, prev_char, idx;
 
-         idx = make_number (SCHARS (echo_string) - 2);
-         prev_char = Faref (echo_string, idx);
+      idx = make_number (SCHARS (echo_string) - 2);
+      prev_char = Faref (echo_string, idx);
 
-         idx = make_number (SCHARS (echo_string) - 1);
-         last_char = Faref (echo_string, idx);
+      idx = make_number (SCHARS (echo_string) - 1);
+      last_char = Faref (echo_string, idx);
 
-         /* We test PREV_CHAR to make sure this isn't the echoing
-            of a minus-sign.  */
-         if (XINT (last_char) == '-' && XINT (prev_char) != ' ')
-           Faset (echo_string, idx, make_number (' '));
-         else
-           echo_string = concat2 (echo_string, build_string (" "));
-       }
-      else if (STRINGP (echo_string))
+      /* We test PREV_CHAR to make sure this isn't the echoing of a
+        minus-sign.  */
+      if (XINT (last_char) == '-' && XINT (prev_char) != ' ')
+       Faset (echo_string, idx, make_number (' '));
+      else
        echo_string = concat2 (echo_string, build_string (" "));
+    }
+  else if (STRINGP (echo_string) && SCHARS (echo_string) > 0)
+    echo_string = concat2 (echo_string, build_string (" "));
+
+  kset_echo_string
+    (current_kboard,
+     concat2 (echo_string, make_string (buffer, ptr - buffer)));
+}
 
-      kset_echo_string
-       (current_kboard,
-        concat2 (echo_string, make_string (buffer, ptr - buffer)));
+/* Add C to the echo string, if echoing is going on.  C can be a
+   character or a symbol.  */
 
+static void
+echo_char (Lisp_Object c)
+{
+  if (current_kboard->immediate_echo)
+    {
+      echo_add_key (c);
       echo_now ();
     }
 }
 
 /* Temporarily add a dash to the end of the echo string if it's not
-   empty, so that it serves as a mini-prompt for the very next character.  */
+   empty, so that it serves as a mini-prompt for the very next
+   character.  */
 
 static void
 echo_dash (void)
@@ -662,9 +675,8 @@ echo_now (void)
     }
 
   echoing = 1;
-  message3_nolog (KVAR (current_kboard, echo_string),
-                 SBYTES (KVAR (current_kboard, echo_string)),
-                 STRING_MULTIBYTE (KVAR (current_kboard, echo_string)));
+  /* FIXME: Use call (Qmessage) so it can be advised (e.g. emacspeak).  */
+  message3_nolog (KVAR (current_kboard, echo_string));
   echoing = 0;
 
   /* Record in what buffer we echoed, and from which kboard.  */
@@ -1116,8 +1128,7 @@ cmd_error_internal (Lisp_Object data, const char *context)
 
   Vsignaling_function = Qnil;
 }
-\f
-Lisp_Object command_loop_1 (void);
+
 static Lisp_Object command_loop_2 (Lisp_Object);
 static Lisp_Object top_level_1 (Lisp_Object);
 
@@ -1154,7 +1165,7 @@ command_loop (void)
    value to us.  A value of nil means that command_loop_1 itself
    returned due to end of file (or end of kbd macro).  */
 
-Lisp_Object
+static Lisp_Object
 command_loop_2 (Lisp_Object ignore)
 {
   register Lisp_Object val;
@@ -1172,7 +1183,7 @@ top_level_2 (void)
   return Feval (Vtop_level, Qnil);
 }
 
-Lisp_Object
+static Lisp_Object
 top_level_1 (Lisp_Object ignore)
 {
   /* On entry to the outer level, run the startup file */
@@ -1417,7 +1428,7 @@ command_loop_1 (void)
          sit_for (Vminibuffer_message_timeout, 0, 2);
 
          /* Clear the echo area.  */
-         message2 (0, 0, 0);
+         message1 (0);
          safe_run_hooks (Qecho_area_clear_hook);
 
          unbind_to (count, Qnil);
@@ -3904,6 +3915,18 @@ kbd_buffer_get_event (KBOARD **kbp,
                              make_number (event->modifiers)));
          kbd_fetch_ptr = event + 1;
        }
+#endif
+#ifdef WINDOWSNT
+      else if (event->kind == FILE_NOTIFY_EVENT)
+       {
+         /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK).  */
+         obj = Fcons (Qfile_w32notify,
+                      list2 (list3 (make_number (event->code),
+                                    XCAR (event->arg),
+                                    XCDR (event->arg)),
+                             event->frame_or_window));
+         kbd_fetch_ptr = event + 1;
+       }
 #endif
       else if (event->kind == SAVE_SESSION_EVENT)
         {
@@ -3961,6 +3984,13 @@ kbd_buffer_get_event (KBOARD **kbp,
          obj = make_lispy_event (event);
          kbd_fetch_ptr = event + 1;
        }
+#endif
+#ifdef HAVE_INOTIFY
+      else if (event->kind == FILE_NOTIFY_EVENT)
+        {
+          obj = make_lispy_event (event);
+          kbd_fetch_ptr = event + 1;
+        }
 #endif
       else if (event->kind == CONFIG_CHANGED_EVENT)
        {
@@ -5114,7 +5144,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
            string_info = Fcons (string, make_number (charpos));
          textpos = (w == XWINDOW (selected_window)
                     && current_buffer == XBUFFER (w->buffer))
-           ? PT : XMARKER (w->pointm)->charpos;
+           ? PT : marker_position (w->pointm);
 
          xret = wx;
          yret = wy;
@@ -5875,6 +5905,13 @@ make_lispy_event (struct input_event *event)
       }
 #endif /* HAVE_DBUS */
 
+#ifdef HAVE_INOTIFY
+    case FILE_NOTIFY_EVENT:
+      {
+        return Fcons (Qfile_inotify, event->arg);
+      }
+#endif /* HAVE_INOTIFY */
+
     case CONFIG_CHANGED_EVENT:
        return Fcons (Qconfig_changed_event,
                       Fcons (event->arg,
@@ -6669,37 +6706,35 @@ get_input_pending (int flags)
 void
 record_asynch_buffer_change (void)
 {
-  struct input_event event;
-  Lisp_Object tem;
-  EVENT_INIT (event);
-
-  event.kind = BUFFER_SWITCH_EVENT;
-  event.frame_or_window = Qnil;
-  event.arg = Qnil;
-
   /* We don't need a buffer-switch event unless Emacs is waiting for input.
      The purpose of the event is to make read_key_sequence look up the
      keymaps again.  If we aren't in read_key_sequence, we don't need one,
      and the event could cause trouble by messing up (input-pending-p).
      Note: Fwaiting_for_user_input_p always returns nil when async
      subprocesses aren't supported.  */
-  tem = Fwaiting_for_user_input_p ();
-  if (NILP (tem))
-    return;
+  if (!NILP (Fwaiting_for_user_input_p ()))
+    {
+      struct input_event event;
+
+      EVENT_INIT (event);
+      event.kind = BUFFER_SWITCH_EVENT;
+      event.frame_or_window = Qnil;
+      event.arg = Qnil;
 
-  /* Make sure no interrupt happens while storing the event.  */
+      /* Make sure no interrupt happens while storing the event.  */
 #ifdef USABLE_SIGIO
-  if (interrupt_input)
-    kbd_buffer_store_event (&event);
-  else
+      if (interrupt_input)
+       kbd_buffer_store_event (&event);
+      else
 #endif
-    {
-      stop_polling ();
-      kbd_buffer_store_event (&event);
-      start_polling ();
+       {
+         stop_polling ();
+         kbd_buffer_store_event (&event);
+         start_polling ();
+       }
     }
 }
-\f
+
 /* Read any terminal input already buffered up by the system
    into the kbd_buffer, but do not wait.
 
@@ -8398,12 +8433,6 @@ read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps,
   return Qnil ;
 }
 
-/* Buffer in use so far for the minibuf prompts for menu keymaps.
-   We make this bigger when necessary, and never free it.  */
-static char *read_char_minibuf_menu_text;
-/* Size of that buffer.  */
-static ptrdiff_t read_char_minibuf_menu_width;
-
 static Lisp_Object
 read_char_minibuf_menu_prompt (int commandflag,
                               ptrdiff_t nmaps, Lisp_Object *maps)
@@ -8416,7 +8445,7 @@ read_char_minibuf_menu_prompt (int commandflag,
   ptrdiff_t idx = -1;
   bool nobindings = 1;
   Lisp_Object rest, vector;
-  char *menu;
+  Lisp_Object prompt_strings = Qnil;
 
   vector = Qnil;
   name = Qnil;
@@ -8436,24 +8465,13 @@ read_char_minibuf_menu_prompt (int commandflag,
   if (!STRINGP (name))
     return Qnil;
 
-  /* Make sure we have a big enough buffer for the menu text.  */
-  width = max (width, SBYTES (name));
-  if (STRING_BYTES_BOUND - 4 < width)
-    memory_full (SIZE_MAX);
-  if (width + 4 > read_char_minibuf_menu_width)
-    {
-      read_char_minibuf_menu_text
-       = xrealloc (read_char_minibuf_menu_text, width + 4);
-      read_char_minibuf_menu_width = width + 4;
-    }
-  menu = read_char_minibuf_menu_text;
-
+#define PUSH_C_STR(str, listvar) \
+  listvar = Fcons (make_unibyte_string (str, strlen (str)), listvar)
+  
   /* Prompt string always starts with map's prompt, and a space.  */
-  strcpy (menu, SSDATA (name));
-  nlength = SBYTES (name);
-  menu[nlength++] = ':';
-  menu[nlength++] = ' ';
-  menu[nlength] = 0;
+  prompt_strings = Fcons (name, prompt_strings);
+  PUSH_C_STR (": ", prompt_strings);
+  nlength = SCHARS (name) + 2;
 
   /* Start prompting at start of first map.  */
   mapno = 0;
@@ -8463,6 +8481,7 @@ read_char_minibuf_menu_prompt (int commandflag,
   while (1)
     {
       bool notfirst = 0;
+      Lisp_Object menu_strings = prompt_strings;
       ptrdiff_t i = nlength;
       Lisp_Object obj;
       Lisp_Object orig_defn_macro;
@@ -8472,6 +8491,8 @@ read_char_minibuf_menu_prompt (int commandflag,
        {
          Lisp_Object elt;
 
+         /* FIXME: Use map_keymap to handle new keymap formats.  */
+
          /* If reached end of map, start at beginning of next map.  */
          if (NILP (rest))
            {
@@ -8567,7 +8588,7 @@ read_char_minibuf_menu_prompt (int commandflag,
                      /* Punctuate between strings.  */
                      if (notfirst)
                        {
-                         strcpy (menu + i, ", ");
+                         PUSH_C_STR (", ", menu_strings);
                          i += 2;
                        }
                      notfirst = 1;
@@ -8579,23 +8600,28 @@ read_char_minibuf_menu_prompt (int commandflag,
                        {
                          /* Add as much of string as fits.  */
                          thiswidth = min (SCHARS (desc), width - i);
-                         memcpy (menu + i, SDATA (desc), thiswidth);
+                         menu_strings
+                           = Fcons (Fsubstring (desc, make_number (0),
+                                                make_number (thiswidth)),
+                                    menu_strings);
                          i += thiswidth;
-                         strcpy (menu + i, " = ");
+                         PUSH_C_STR (" = ", menu_strings);
                          i += 3;
                        }
 
                      /* Add as much of string as fits.  */
                      thiswidth = min (SCHARS (s), width - i);
-                     memcpy (menu + i, SDATA (s), thiswidth);
+                     menu_strings
+                       = Fcons (Fsubstring (s, make_number (0),
+                                            make_number (thiswidth)),
+                                menu_strings);
                      i += thiswidth;
-                     menu[i] = 0;
                    }
                  else
                    {
                      /* If this element does not fit, end the line now,
                         and save the element for the next line.  */
-                     strcpy (menu + i, "...");
+                     PUSH_C_STR ("...", menu_strings);
                      break;
                    }
                }
@@ -8612,13 +8638,11 @@ read_char_minibuf_menu_prompt (int commandflag,
        }
 
       /* Prompt with that and read response.  */
-      message2_nolog (menu, strlen (menu),
-                     ! NILP (BVAR (current_buffer, enable_multibyte_characters)));
+      message3_nolog (apply1 (intern ("concat"), menu_strings));
 
-      /* Make believe its not a keyboard macro in case the help char
+      /* Make believe it's not a keyboard macro in case the help char
         is pressed.  Help characters are not recorded because menu prompting
-        is not used on replay.
-        */
+        is not used on replay.  */
       orig_defn_macro = KVAR (current_kboard, defining_kbd_macro);
       kset_defining_kbd_macro (current_kboard, Qnil);
       do
@@ -8626,9 +8650,7 @@ read_char_minibuf_menu_prompt (int commandflag,
       while (BUFFERP (obj));
       kset_defining_kbd_macro (current_kboard, orig_defn_macro);
 
-      if (!INTEGERP (obj))
-       return obj;
-      else if (XINT (obj) == -2)
+      if (!INTEGERP (obj) || XINT (obj) == -2)
         return obj;
 
       if (! EQ (obj, menu_prompt_more_char)
@@ -8639,7 +8661,7 @@ read_char_minibuf_menu_prompt (int commandflag,
            store_kbd_macro_char (obj);
          return obj;
        }
-      /* Help char - go round again */
+      /* Help char - go round again */
     }
 }
 \f
@@ -9188,8 +9210,12 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
          key = keybuf[t];
          add_command_key (key);
          if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
-             && NILP (Fzerop (Vecho_keystrokes)))
-           echo_char (key);
+             && NILP (Fzerop (Vecho_keystrokes))
+             && current_kboard->immediate_echo)
+           {
+             echo_add_key (key);
+             echo_dash ();
+           }
        }
 
       /* If not, we should actually read a character.  */
@@ -10051,7 +10077,7 @@ will read just one key sequence.  */)
     cancel_hourglass ();
 #endif
 
-  i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
+  i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
                         prompt, ! NILP (dont_downcase_last),
                         ! NILP (can_return_switch_frame), 0);
 
@@ -10130,7 +10156,7 @@ DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 0,
        doc: /* Execute CMD as an editor command.
 CMD must be a symbol that satisfies the `commandp' predicate.
 Optional second arg RECORD-FLAG non-nil
-means unconditionally put this command in `command-history'.
+means unconditionally put this command in the variable `command-history'.
 Otherwise, that is done only if an arg is read using the minibuffer.
 The argument KEYS specifies the value to use instead of (this-command-keys)
 when reading the arguments; if it is nil, (this-command-keys) is used.
@@ -10689,7 +10715,7 @@ handle_interrupt (bool in_signal_handler)
       fflush (stdout);
       reset_all_sys_modes ();
 
-#ifdef SIGTSTP                 /* Support possible in later USG versions */
+#ifdef SIGTSTP
 /*
  * On systems which can suspend the current process and return to the original
  * shell, this command causes the user to end up back at the shell.
@@ -11334,10 +11360,18 @@ syms_of_keyboard (void)
   DEFSYM (Qlanguage_change, "language-change");
 #endif
 
+#ifdef WINDOWSNT
+  DEFSYM (Qfile_w32notify, "file-w32notify");
+#endif
+
 #ifdef HAVE_DBUS
   DEFSYM (Qdbus_event, "dbus-event");
 #endif
 
+#ifdef HAVE_INOTIFY
+  DEFSYM (Qfile_inotify, "file-inotify");
+#endif /* HAVE_INOTIFY */
+
   DEFSYM (QCenable, ":enable");
   DEFSYM (QCvisible, ":visible");
   DEFSYM (QChelp, ":help");
@@ -12007,8 +12041,8 @@ This takes effect only when Transient Mark mode is enabled.  */);
               Vsaved_region_selection,
               doc: /* Contents of active region prior to buffer modification.
 If `select-active-regions' is non-nil, Emacs sets this to the
-text in the region before modifying the buffer.  The next
-`deactivate-mark' call uses this to set the window selection.  */);
+text in the region before modifying the buffer.  The next call to
+the function `deactivate-mark' uses this to set the window selection.  */);
   Vsaved_region_selection = Qnil;
 
   DEFVAR_LISP ("selection-inhibit-update-commands",
@@ -12094,11 +12128,20 @@ keys_of_keyboard (void)
                            "dbus-handle-event");
 #endif
 
+#ifdef HAVE_INOTIFY
+  /* Define a special event which is raised for inotify callback
+     functions.  */
+  initial_define_lispy_key (Vspecial_event_map, "file-inotify",
+                            "inotify-handle-event");
+#endif /* HAVE_INOTIFY */
+
   initial_define_lispy_key (Vspecial_event_map, "config-changed-event",
                            "ignore");
 #if defined (WINDOWSNT)
   initial_define_lispy_key (Vspecial_event_map, "language-change",
                            "ignore");
+  initial_define_lispy_key (Vspecial_event_map, "file-w32notify",
+                           "w32notify-handle-event");
 #endif
 }