Merge from trunk.
[bpt/emacs.git] / src / keyboard.c
index bffe2b0..51eac36 100644 (file)
@@ -44,7 +44,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "process.h"
 #include <errno.h>
 
-#ifdef HAVE_GTK_AND_PTHREAD
+#ifdef HAVE_PTHREAD
 #include <pthread.h>
 #endif
 #ifdef MSDOS
@@ -196,7 +196,7 @@ int immediate_quit;
 int quit_char;
 
 /* Current depth in recursive edits.  */
-int command_loop_level;
+EMACS_INT command_loop_level;
 
 /* If not Qnil, this is a switch-frame event which we decided to put
    off until the end of a key sequence.  This should be read as the
@@ -210,8 +210,8 @@ Lisp_Object unread_switch_frame;
 /* Last size recorded for a current buffer which is not a minibuffer.  */
 static EMACS_INT last_non_minibuf_size;
 
-/* Total number of times read_char has returned, modulo SIZE_MAX + 1.  */
-size_t num_input_events;
+/* Total number of times read_char has returned, modulo UINTMAX_MAX + 1.  */
+uintmax_t num_input_events;
 
 /* Value of num_nonmacro_input_events as of last auto save.  */
 
@@ -435,16 +435,16 @@ static void (*keyboard_init_hook) (void);
 static int read_avail_input (int);
 static void get_input_pending (int *, int);
 static int readable_events (int);
-static Lisp_Object read_char_x_menu_prompt (int, Lisp_Object *,
+static Lisp_Object read_char_x_menu_prompt (ptrdiff_t, Lisp_Object *,
                                             Lisp_Object, int *);
-static Lisp_Object read_char_minibuf_menu_prompt (int, int,
+static Lisp_Object read_char_minibuf_menu_prompt (int, ptrdiff_t,
                                                   Lisp_Object *);
 static Lisp_Object make_lispy_event (struct input_event *);
 #if defined (HAVE_MOUSE) || defined (HAVE_GPM)
 static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object,
                                         enum scroll_bar_part,
                                         Lisp_Object, Lisp_Object,
-                                        unsigned long);
+                                       Time);
 #endif
 static Lisp_Object modify_event_symbol (EMACS_INT, unsigned, Lisp_Object,
                                         Lisp_Object, const char *const *,
@@ -998,7 +998,8 @@ static Lisp_Object
 cmd_error (Lisp_Object data)
 {
   Lisp_Object old_level, old_length;
-  char macroerror[50];
+  char macroerror[sizeof "After..kbd macro iterations: "
+                 + INT_STRLEN_BOUND (EMACS_INT)];
 
 #ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
@@ -1010,7 +1011,7 @@ cmd_error (Lisp_Object data)
       if (executing_kbd_macro_iterations == 1)
        sprintf (macroerror, "After 1 kbd macro iteration: ");
       else
-       sprintf (macroerror, "After %d kbd macro iterations: ",
+       sprintf (macroerror, "After %"pI"d kbd macro iterations: ",
                 executing_kbd_macro_iterations);
     }
   else
@@ -1300,7 +1301,7 @@ some_mouse_moved (void)
 /* This is the actual command reading loop,
    sans error-handling encapsulation.  */
 
-static int read_key_sequence (Lisp_Object *, size_t, Lisp_Object,
+static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
                               int, int, int);
 void safe_run_hooks (Lisp_Object);
 static void adjust_point_for_property (EMACS_INT, int);
@@ -1539,7 +1540,18 @@ command_loop_1 (void)
          message_with_string ("%s is undefined", keys, 0);
          KVAR (current_kboard, defining_kbd_macro) = Qnil;
          update_mode_lines = 1;
-         KVAR (current_kboard, Vprefix_arg) = Qnil;
+         /* If this is a down-mouse event, don't reset prefix-arg;
+            pass it to the command run by the up event.  */
+         if (EVENT_HAS_PARAMETERS (last_command_event))
+           {
+             Lisp_Object breakdown
+               = parse_modifiers (EVENT_HEAD (last_command_event));
+             int modifiers = XINT (XCAR (XCDR (breakdown)));
+             if (!(modifiers & down_modifier))
+               KVAR (current_kboard, Vprefix_arg) = Qnil;
+           }
+         else
+           KVAR (current_kboard, Vprefix_arg) = Qnil;
        }
       else
        {
@@ -2256,7 +2268,8 @@ do { if (polling_stopped_here) start_polling ();  \
    Value is t if we showed a menu and the user rejected it.  */
 
 Lisp_Object
-read_char (int commandflag, int nmaps, Lisp_Object *maps, Lisp_Object prev_event,
+read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
+          Lisp_Object prev_event,
           int *used_mouse_menu, struct timeval *end_time)
 {
   volatile Lisp_Object c;
@@ -6451,11 +6464,15 @@ modify_event_symbol (EMACS_INT symbol_num, unsigned int modifiers, Lisp_Object s
        value = Fcdr_safe (Fassq (symbol_int, name_alist_or_stem));
       else if (STRINGP (name_alist_or_stem))
        {
-         int len = SBYTES (name_alist_or_stem);
-         char *buf = (char *) alloca (len + 50);
-          sprintf (buf, "%s-%"pI"d", SDATA (name_alist_or_stem),
-                   XINT (symbol_int) + 1);
+         char *buf;
+         ptrdiff_t len = (SBYTES (name_alist_or_stem)
+                          + sizeof "-" + INT_STRLEN_BOUND (EMACS_INT));
+         USE_SAFE_ALLOCA;
+         SAFE_ALLOCA (buf, char *, len);
+         esprintf (buf, "%s-%"pI"d", SDATA (name_alist_or_stem),
+                   XINT (symbol_int) + 1);
          value = intern (buf);
+         SAFE_FREE ();
        }
       else if (name_table != 0 && name_table[symbol_num])
        value = intern (name_table[symbol_num]);
@@ -6471,7 +6488,7 @@ modify_event_symbol (EMACS_INT symbol_num, unsigned int modifiers, Lisp_Object s
 
       if (NILP (value))
        {
-         char buf[20];
+         char buf[sizeof "key-" + INT_STRLEN_BOUND (EMACS_INT)];
          sprintf (buf, "key-%"pI"d", symbol_num);
          value = intern (buf);
        }
@@ -7394,7 +7411,7 @@ menu_bar_items (Lisp_Object old)
 {
   /* The number of keymaps we're scanning right now, and the number of
      keymaps we have allocated space for.  */
-  int nmaps;
+  ptrdiff_t nmaps;
 
   /* maps[0..nmaps-1] are the prefix definitions of KEYBUF[0..t-1]
      in the current keymaps, or nil where it is not a prefix.  */
@@ -7402,7 +7419,7 @@ menu_bar_items (Lisp_Object old)
 
   Lisp_Object def, tail;
 
-  int mapno;
+  ptrdiff_t mapno;
   Lisp_Object oquit;
 
   /* In order to build the menus, we need to call the keymap
@@ -7447,7 +7464,7 @@ menu_bar_items (Lisp_Object old)
           recognized when the menu-bar (or mode-line) is updated,
           which does not normally happen after every command.  */
        Lisp_Object tem;
-       int nminor;
+       ptrdiff_t nminor;
        nminor = current_minor_maps (NULL, &tmaps);
        maps = (Lisp_Object *) alloca ((nminor + 3) * sizeof (maps[0]));
        nmaps = 0;
@@ -7470,7 +7487,7 @@ menu_bar_items (Lisp_Object old)
        if (CONSP (def))
          {
            menu_bar_one_keymap_changed_items = Qnil;
-           map_keymap (def, menu_bar_item, Qnil, NULL, 1);
+           map_keymap_canonical (def, menu_bar_item, Qnil, NULL);
          }
       }
 
@@ -7811,7 +7828,7 @@ parse_menu_item (Lisp_Object item, int inmenubar)
   /* If we got no definition, this item is just unselectable text which
      is OK in a submenu but not in the menubar.  */
   if (NILP (def))
-    return (inmenubar ? 0 : 1);
+    return (!inmenubar);
 
   /* See if this is a separate pane or a submenu.  */
   def = AREF (item_properties, ITEM_PROPERTY_DEF);
@@ -7951,7 +7968,7 @@ Lisp_Object
 tool_bar_items (Lisp_Object reuse, int *nitems)
 {
   Lisp_Object *maps;
-  int nmaps, i;
+  ptrdiff_t nmaps, i;
   Lisp_Object oquit;
   Lisp_Object *tmaps;
 
@@ -7991,7 +8008,7 @@ tool_bar_items (Lisp_Object reuse, int *nitems)
         recognized when the tool-bar (or mode-line) is updated,
         which does not normally happen after every command.  */
       Lisp_Object tem;
-      int nminor;
+      ptrdiff_t nminor;
       nminor = current_minor_maps (NULL, &tmaps);
       maps = (Lisp_Object *) alloca ((nminor + 3) * sizeof (maps[0]));
       nmaps = 0;
@@ -8263,10 +8280,11 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
       Lisp_Object tcapt = PROP (TOOL_BAR_ITEM_CAPTION);
       const char *label = SYMBOLP (tkey) ? SSDATA (SYMBOL_NAME (tkey)) : "";
       const char *capt = STRINGP (tcapt) ? SSDATA (tcapt) : "";
-      EMACS_INT max_lbl = 2 * tool_bar_max_label_size;
+      ptrdiff_t max_lbl =
+       2 * max (0, min (tool_bar_max_label_size, STRING_BYTES_BOUND / 2));
       char *buf = (char *) xmalloc (max_lbl + 1);
       Lisp_Object new_lbl;
-      size_t caption_len = strlen (capt);
+      ptrdiff_t caption_len = strlen (capt);
 
       if (caption_len <= max_lbl && capt[0] != '\0')
         {
@@ -8279,7 +8297,7 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
 
       if (strlen (label) <= max_lbl && label[0] != '\0')
         {
-          int j;
+          ptrdiff_t j;
           if (label != buf)
            strcpy (buf, label);
 
@@ -8388,10 +8406,10 @@ append_tool_bar_item (void)
    and do auto-saving in the inner call of read_char. */
 
 static Lisp_Object
-read_char_x_menu_prompt (int nmaps, Lisp_Object *maps, Lisp_Object prev_event,
-                        int *used_mouse_menu)
+read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps,
+                        Lisp_Object prev_event, int *used_mouse_menu)
 {
-  int mapno;
+  ptrdiff_t mapno;
 
   if (used_mouse_menu)
     *used_mouse_menu = 0;
@@ -8419,7 +8437,7 @@ read_char_x_menu_prompt (int nmaps, Lisp_Object *maps, Lisp_Object prev_event,
       Lisp_Object *realmaps
        = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
       Lisp_Object value;
-      int nmaps1 = 0;
+      ptrdiff_t nmaps1 = 0;
 
       /* Use the maps that are not nil.  */
       for (mapno = 0; mapno < nmaps; mapno++)
@@ -8470,17 +8488,18 @@ read_char_x_menu_prompt (int nmaps, Lisp_Object *maps, Lisp_Object prev_event,
    We make this bigger when necessary, and never free it.  */
 static char *read_char_minibuf_menu_text;
 /* Size of that buffer.  */
-static int read_char_minibuf_menu_width;
+static ptrdiff_t read_char_minibuf_menu_width;
 
 static Lisp_Object
-read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps)
+read_char_minibuf_menu_prompt (int commandflag,
+                              ptrdiff_t nmaps, Lisp_Object *maps)
 {
-  int mapno;
+  ptrdiff_t mapno;
   register Lisp_Object name;
-  int nlength;
+  ptrdiff_t nlength;
   /* FIXME: Use the minibuffer's frame width.  */
-  int width = FRAME_COLS (SELECTED_FRAME ()) - 4;
-  int idx = -1;
+  ptrdiff_t width = FRAME_COLS (SELECTED_FRAME ()) - 4;
+  ptrdiff_t idx = -1;
   int nobindings = 1;
   Lisp_Object rest, vector;
   char *menu;
@@ -8505,16 +8524,13 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps)
 
   /* Make sure we have a big enough buffer for the menu text.  */
   width = max (width, SBYTES (name));
-  if (read_char_minibuf_menu_text == 0)
+  if (STRING_BYTES_BOUND - 4 < width)
+    memory_full (SIZE_MAX);
+  if (width + 4 > read_char_minibuf_menu_width)
     {
-      read_char_minibuf_menu_width = width + 4;
-      read_char_minibuf_menu_text = (char *) xmalloc (width + 4);
-    }
-  else if (width + 4 > read_char_minibuf_menu_width)
-    {
-      read_char_minibuf_menu_width = width + 4;
       read_char_minibuf_menu_text
        = (char *) xrealloc (read_char_minibuf_menu_text, width + 4);
+      read_char_minibuf_menu_width = width + 4;
     }
   menu = read_char_minibuf_menu_text;
 
@@ -8533,7 +8549,7 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps)
   while (1)
     {
       int notfirst = 0;
-      int i = nlength;
+      ptrdiff_t i = nlength;
       Lisp_Object obj;
       Lisp_Object orig_defn_macro;
 
@@ -8632,7 +8648,7 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps)
                      < width
                      || !notfirst)
                    {
-                     int thiswidth;
+                     ptrdiff_t thiswidth;
 
                      /* Punctuate between strings.  */
                      if (notfirst)
@@ -8648,9 +8664,7 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps)
                      if (! char_matches)
                        {
                          /* Add as much of string as fits.  */
-                         thiswidth = SCHARS (desc);
-                         if (thiswidth + i > width)
-                           thiswidth = width - i;
+                         thiswidth = min (SCHARS (desc), width - i);
                          memcpy (menu + i, SDATA (desc), thiswidth);
                          i += thiswidth;
                          strcpy (menu + i, " = ");
@@ -8658,9 +8672,7 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps)
                        }
 
                      /* Add as much of string as fits.  */
-                     thiswidth = SCHARS (s);
-                     if (thiswidth + i > width)
-                       thiswidth = width - i;
+                     thiswidth = min (SCHARS (s), width - i);
                      memcpy (menu + i, SDATA (s), thiswidth);
                      i += thiswidth;
                      menu[i] = 0;
@@ -8735,10 +8747,10 @@ read_char_minibuf_menu_prompt (int commandflag, int nmaps, Lisp_Object *maps)
    NEXT may be the same array as CURRENT.  */
 
 static int
-follow_key (Lisp_Object key, int nmaps, Lisp_Object *current, Lisp_Object *defs,
-           Lisp_Object *next)
+follow_key (Lisp_Object key, ptrdiff_t nmaps, Lisp_Object *current,
+           Lisp_Object *defs, Lisp_Object *next)
 {
-  int i, first_binding;
+  ptrdiff_t i, first_binding;
 
   first_binding = nmaps;
   for (i = nmaps - 1; i >= 0; i--)
@@ -8838,7 +8850,7 @@ access_keymap_keyremap (Lisp_Object map, Lisp_Object key, Lisp_Object prompt,
    The return value is non-zero if the remapping actually took place.  */
 
 static int
-keyremap_step (Lisp_Object *keybuf, size_t bufsize, volatile keyremap *fkey,
+keyremap_step (Lisp_Object *keybuf, int bufsize, volatile keyremap *fkey,
               int input, int doit, int *diff, Lisp_Object prompt)
 {
   Lisp_Object next, key;
@@ -8860,7 +8872,7 @@ keyremap_step (Lisp_Object *keybuf, size_t bufsize, volatile keyremap *fkey,
 
       *diff = len - (fkey->end - fkey->start);
 
-      if (input + *diff >= bufsize)
+      if (bufsize - input <= *diff)
        error ("Key sequence too long");
 
       /* Shift the keys that follow fkey->end.  */
@@ -8931,7 +8943,7 @@ keyremap_step (Lisp_Object *keybuf, size_t bufsize, volatile keyremap *fkey,
    from the selected window's buffer.  */
 
 static int
-read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt,
+read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                   int dont_downcase_last, int can_return_switch_frame,
                   int fix_current_buffer)
 {
@@ -8948,8 +8960,8 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt,
 
   /* The number of keymaps we're scanning right now, and the number of
      keymaps we have allocated space for.  */
-  int nmaps;
-  int nmaps_allocated = 0;
+  ptrdiff_t nmaps;
+  ptrdiff_t nmaps_allocated = 0;
 
   /* defs[0..nmaps-1] are the definitions of KEYBUF[0..t-1] in
      the current keymaps.  */
@@ -8973,7 +8985,7 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt,
   /* The index in submaps[] of the first keymap that has a binding for
      this key sequence.  In other words, the lowest i such that
      submaps[i] is non-nil.  */
-  int first_binding;
+  ptrdiff_t first_binding;
   /* Index of the first key that has no binding.
      It is useless to try fkey.start larger than that.  */
   int first_unbound;
@@ -9134,8 +9146,8 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt,
     }
   else
     {
-      int nminor;
-      int total;
+      ptrdiff_t nminor;
+      ptrdiff_t total;
       Lisp_Object *maps;
 
       nminor = current_minor_maps (0, &maps);
@@ -9201,7 +9213,8 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt,
         echo_local_start and keys_local_start allow us to throw away
         just one key.  */
       int echo_local_start IF_LINT (= 0);
-      int keys_local_start, local_first_binding;
+      int keys_local_start;
+      ptrdiff_t local_first_binding;
 
       eassert (indec.end == t || (indec.end > t && indec.end <= mock_input));
       eassert (indec.start <= indec.end);
@@ -9538,7 +9551,7 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt,
                  && (NILP (fake_prefixed_keys)
                      || NILP (Fmemq (key, fake_prefixed_keys))))
                {
-                 if (t + 1 >= bufsize)
+                 if (bufsize - t <= 1)
                    error ("Key sequence too long");
 
                  keybuf[t]     = posn;
@@ -9619,7 +9632,7 @@ read_key_sequence (Lisp_Object *keybuf, size_t bufsize, Lisp_Object prompt,
                 insert the dummy prefix event `menu-bar'.  */
              if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
                {
-                 if (t + 1 >= bufsize)
+                 if (bufsize - t <= 1)
                    error ("Key sequence too long");
                  keybuf[t] = posn;
                  keybuf[t+1] = key;
@@ -10374,19 +10387,21 @@ give to the command you invoke, if it asks for an argument.  */)
          char *newmessage;
          int message_p = push_message ();
          int count = SPECPDL_INDEX ();
+         ptrdiff_t newmessage_len, newmessage_alloc;
+         USE_SAFE_ALLOCA;
 
          record_unwind_protect (pop_message_unwind, Qnil);
          binding = Fkey_description (bindings, Qnil);
-
-         newmessage
-           = (char *) alloca (SCHARS (SYMBOL_NAME (function))
-                              + SBYTES (binding)
-                              + 100);
-         sprintf (newmessage, "You can run the command `%s' with %s",
-                  SDATA (SYMBOL_NAME (function)),
-                  SDATA (binding));
+         newmessage_alloc =
+           (sizeof "You can run the command `' with "
+            + SBYTES (SYMBOL_NAME (function)) + SBYTES (binding));
+         SAFE_ALLOCA (newmessage, char *, newmessage_alloc);
+         newmessage_len =
+           esprintf (newmessage, "You can run the command `%s' with %s",
+                     SDATA (SYMBOL_NAME (function)),
+                     SDATA (binding));
          message2 (newmessage,
-                   strlen (newmessage),
+                   newmessage_len,
                    STRING_MULTIBYTE (binding));
          if (NUMBERP (Vsuggest_key_bindings))
            waited = sit_for (Vsuggest_key_bindings, 0, 2);
@@ -10396,6 +10411,7 @@ give to the command you invoke, if it asks for an argument.  */)
          if (!NILP (waited) && message_p)
            restore_message ();
 
+         SAFE_FREE ();
          unbind_to (count, Qnil);
        }
     }
@@ -10625,14 +10641,17 @@ DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0,
   (void)
 {
   Lisp_Object temp;
-  XSETFASTINT (temp, command_loop_level + minibuf_level);
+  /* Wrap around reliably on integer overflow.  */
+  EMACS_INT sum = (command_loop_level & INTMASK) + (minibuf_level & INTMASK);
+  XSETINT (temp, sum);
   return temp;
 }
 
 DEFUN ("open-dribble-file", Fopen_dribble_file, Sopen_dribble_file, 1, 1,
        "FOpen dribble file: ",
        doc: /* Start writing all keyboard characters to a dribble file called FILE.
-If FILE is nil, close any open dribble file.  */)
+If FILE is nil, close any open dribble file.
+The file will be closed when Emacs exits.  */)
   (Lisp_Object file)
 {
   if (dribble)