X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/01103c441a5c97c734c087fa074a941082fd0adb..fd09688b0bbd5ee8011e78a1f4e794603e27232f:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index 20ad7d0ce9..51eac369e7 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -44,7 +44,7 @@ along with GNU Emacs. If not, see . */ #include "process.h" #include -#ifdef HAVE_GTK_AND_PTHREAD +#ifdef HAVE_PTHREAD #include #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 { @@ -1901,7 +1913,7 @@ safe_run_hooks_error (Lisp_Object error_data) } static Lisp_Object -safe_run_hook_funcall (size_t nargs, Lisp_Object *args) +safe_run_hook_funcall (ptrdiff_t nargs, Lisp_Object *args) { eassert (nargs == 1); if (CONSP (Vinhibit_quit)) @@ -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; @@ -8225,7 +8242,7 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item) /* `:label LABEL-STRING'. */ PROP (TOOL_BAR_ITEM_LABEL) = STRINGP (value) ? value - : make_string (bad_label, strlen (bad_label)); + : build_string (bad_label); have_label = 1; } else if (EQ (ikey, QCfilter)) @@ -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); @@ -8291,7 +8309,7 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item) else label = ""; - new_lbl = Fupcase_initials (make_string (label, strlen (label))); + new_lbl = Fupcase_initials (build_string (label)); if (SCHARS (new_lbl) <= tool_bar_max_label_size) PROP (TOOL_BAR_ITEM_LABEL) = new_lbl; else @@ -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)