X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/a64bfdfa5a90731b804c057f2bcc74a8ba02937c..b948ce8b0244181c9e08d6bfc635ead24b4e9742:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index 11c37d14f6..9ff19d61d4 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,6 +1,6 @@ /* Keyboard and mouse input; editor command loop. -Copyright (C) 1985-1989, 1993-1997, 1999-2011 Free Software Foundation, Inc. +Copyright (C) 1985-1989, 1993-1997, 1999-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -241,6 +241,7 @@ Lisp_Object internal_last_event_frame; Time last_event_timestamp; static Lisp_Object Qx_set_selection, Qhandle_switch_frame; +static Lisp_Object Qhandle_select_window; Lisp_Object QPRIMARY; static Lisp_Object Qself_insert_command; @@ -464,7 +465,8 @@ static void input_available_signal (int signo); static Lisp_Object (Fcommand_execute) (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); static void handle_interrupt (void); -static void quit_throw_to_read_char (void) NO_RETURN; +static void quit_throw_to_read_char (int) NO_RETURN; +static void process_special_events (void); static void timer_start_idle (void); static void timer_stop_idle (void); static void timer_resume_idle (void); @@ -653,7 +655,7 @@ echo_now (void) echo_kboard = current_kboard; if (waiting_for_input && !NILP (Vquit_flag)) - quit_throw_to_read_char (); + quit_throw_to_read_char (0); } /* Turn off echoing, for the start of a new command. */ @@ -932,7 +934,7 @@ pop_kboard (void) state later. If Emacs is already in single_kboard mode, and F's keyboard is - locked, then this function will throw an errow. */ + locked, then this function will throw an error. */ void temporarily_switch_to_single_kboard (struct frame *f) @@ -1060,7 +1062,7 @@ cmd_error_internal (Lisp_Object data, const char *context) struct frame *sf = SELECTED_FRAME (); /* The immediate context is not interesting for Quits, - since they are asyncronous. */ + since they are asynchronous. */ if (EQ (XCAR (data), Qquit)) Vsignaling_function = Qnil; @@ -1646,7 +1648,8 @@ command_loop_1 (void) ? EQ (CAR_SAFE (Vtransient_mark_mode), Qonly) : (!NILP (Vselect_active_regions) && !NILP (Vtransient_mark_mode))) - && !EQ (Vthis_command, Qhandle_switch_frame)) + && NILP (Fmemq (Vthis_command, + Vselection_inhibit_update_commands))) { EMACS_INT beg = XINT (Fmarker_position (BVAR (current_buffer, mark))); @@ -1748,7 +1751,9 @@ adjust_point_for_property (EMACS_INT last_pt, int modified) { xassert (end > PT); SET_PT (PT < last_pt - ? (STRINGP (val) && SCHARS (val) == 0 ? beg - 1 : beg) + ? (STRINGP (val) && SCHARS (val) == 0 + ? max (beg - 1, BEGV) + : beg) : end); check_composition = check_invisible = 1; } @@ -1876,7 +1881,7 @@ safe_run_hooks_error (Lisp_Object error_data) = CONSP (Vinhibit_quit) ? XCAR (Vinhibit_quit) : Vinhibit_quit; Lisp_Object fun = CONSP (Vinhibit_quit) ? XCDR (Vinhibit_quit) : Qnil; Lisp_Object args[4]; - args[0] = build_string ("Error in %s (%s): %s"); + args[0] = build_string ("Error in %s (%s): %S"); args[1] = hook; args[2] = fun; args[3] = error_data; @@ -2238,8 +2243,8 @@ do { if (polling_stopped_here) start_polling (); \ polling_stopped_here = 0; } while (0) /* read a character from the keyboard; call the redisplay if needed */ -/* commandflag 0 means do not do auto-saving, but do do redisplay. - -1 means do not do redisplay, but do do autosaving. +/* commandflag 0 means do not autosave, but do redisplay. + -1 means do not redisplay, but do autosave. 1 means do both. */ /* The arguments MAPS and NMAPS are for menu prompting. @@ -2998,7 +3003,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, { Lisp_Object keys; int key_count, key_count_reset; - struct gcpro inner_gcpro1; + struct gcpro gcpro1; int count = SPECPDL_INDEX (); /* Save the echo status. */ @@ -3026,7 +3031,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, keys = Fcopy_sequence (this_command_keys); else keys = Qnil; - GCPRO1_VAR (keys, inner_gcpro); + GCPRO1 (keys); /* Clear out this_command_keys. */ this_command_key_count = 0; @@ -3064,7 +3069,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps, if (saved_immediate_echo) echo_now (); - UNGCPRO_VAR (inner_gcpro); + UNGCPRO; /* The input method can return no events. */ if (! CONSP (tem)) @@ -3817,7 +3822,7 @@ kbd_buffer_get_event (KBOARD **kbp, /* If the quit flag is set, then read_char will return quit_char, so that counts as "available input." */ if (!NILP (Vquit_flag)) - quit_throw_to_read_char (); + quit_throw_to_read_char (0); /* One way or another, wait until input is available; then, if interrupt handlers have not read it, read it now. */ @@ -4145,37 +4150,61 @@ kbd_buffer_get_event (KBOARD **kbp, return (obj); } -/* Process any events that are not user-visible, - then return, without reading any user-visible events. */ +/* Process any non-user-visible events (currently X selection events), + without reading any user-visible events. */ -void -swallow_events (int do_display) +static void +process_special_events (void) { - int old_timers_run; + struct input_event *event; - while (kbd_fetch_ptr != kbd_store_ptr) + for (event = kbd_fetch_ptr; event != kbd_store_ptr; ++event) { - struct input_event *event; - - event = ((kbd_fetch_ptr < kbd_buffer + KBD_BUFFER_SIZE) - ? kbd_fetch_ptr - : kbd_buffer); - - last_event_timestamp = event->timestamp; + if (event == kbd_buffer + KBD_BUFFER_SIZE) + { + event = kbd_buffer; + if (event == kbd_store_ptr) + break; + } - /* These two kinds of events get special handling - and don't actually appear to the command loop. */ + /* If we find a stored X selection request, handle it now. */ if (event->kind == SELECTION_REQUEST_EVENT || event->kind == SELECTION_CLEAR_EVENT) { #ifdef HAVE_X11 - struct input_event copy; - /* Remove it from the buffer before processing it, - since otherwise swallow_events called recursively could see it - and process it again. */ - copy = *event; - kbd_fetch_ptr = event + 1; + /* Remove the event from the fifo buffer before processing; + otherwise swallow_events called recursively could see it + and process it again. To do this, we move the events + between kbd_fetch_ptr and EVENT one slot to the right, + cyclically. */ + + struct input_event copy = *event; + struct input_event *beg + = (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE) + ? kbd_buffer : kbd_fetch_ptr; + + if (event > beg) + memmove (beg + 1, beg, (event - beg) * sizeof (struct input_event)); + else if (event < beg) + { + if (event > kbd_buffer) + memmove (kbd_buffer + 1, kbd_buffer, + (event - kbd_buffer) * sizeof (struct input_event)); + *kbd_buffer = *(kbd_buffer + KBD_BUFFER_SIZE - 1); + if (beg < kbd_buffer + KBD_BUFFER_SIZE - 1) + memmove (beg + 1, beg, + (kbd_buffer + KBD_BUFFER_SIZE - 1 - beg) + * sizeof (struct input_event)); + } + + if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE) + kbd_fetch_ptr = kbd_buffer + 1; + else + kbd_fetch_ptr++; + + /* X wants last_event_timestamp for selection ownership. */ + last_event_timestamp = copy.timestamp; input_pending = readable_events (0); x_handle_selection_event (©); #else @@ -4184,9 +4213,18 @@ swallow_events (int do_display) abort (); #endif } - else - break; } +} + +/* Process any events that are not user-visible, run timer events that + are ripe, and return, without reading any user-visible events. */ + +void +swallow_events (int do_display) +{ + int old_timers_run; + + process_special_events (); old_timers_run = timers_run; get_input_pending (&input_pending, READABLE_EVENTS_DO_TIMERS_NOW); @@ -4813,7 +4851,7 @@ const char *const lispy_function_keys[] = "ico-00", /* VK_ICO_00 0xE4 */ 0, /* VK_PROCESSKEY 0xE5 - used by IME */ "ico-clear", /* VK_ICO_CLEAR 0xE6 */ - 0, /* VK_PACKET 0xE7 - used to pass unicode chars */ + 0, /* VK_PACKET 0xE7 - used to pass Unicode chars */ 0, /* 0xE8 */ "reset", /* VK_OEM_RESET 0xE9 */ "jump", /* VK_OEM_JUMP 0xEA */ @@ -5123,7 +5161,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, if (WINDOWP (window)) { - /* It's a click in window window at frame coordinates (x,y) */ + /* It's a click in window WINDOW at frame coordinates (X,Y) */ struct window *w = XWINDOW (window); Lisp_Object string_info = Qnil; EMACS_INT textpos = -1; @@ -5393,7 +5431,7 @@ make_lispy_event (struct input_event *event) || !lispy_function_keys[event->code - FUNCTION_KEY_OFFSET]) { /* We need to use an alist rather than a vector as the cache - since we can't make a vector long enuf. */ + since we can't make a vector long enough. */ if (NILP (KVAR (current_kboard, system_key_syms))) KVAR (current_kboard, system_key_syms) = Fcons (Qnil, Qnil); return modify_event_symbol (event->code, @@ -8133,7 +8171,7 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item) Lisp_Object caption; int i, have_label = 0; - /* Defininition looks like `(menu-item CAPTION BINDING PROPS...)'. + /* Definition looks like `(menu-item CAPTION BINDING PROPS...)'. Rule out items that aren't lists, don't start with `menu-item' or whose rest following `tool-bar-item' is not a list. */ @@ -8782,7 +8820,7 @@ typedef struct keyremap /* Positions [START, END) in the key sequence buffer are the key that we have scanned so far. Those events are the ones that we will replace - if PAREHT maps them into a key sequence. */ + if PARENT maps them into a key sequence. */ int start, end; } keyremap; @@ -9053,9 +9091,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, int junk; #endif - struct gcpro outer_gcpro1; + struct gcpro gcpro1; - GCPRO1_VAR (fake_prefixed_keys, outer_gcpro); + GCPRO1 (fake_prefixed_keys); raw_keybuf_count = 0; last_nonmenu_event = Qnil; @@ -9351,7 +9389,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, if (EQ (key, Qt)) { unbind_to (count, Qnil); - UNGCPRO_VAR (outer_gcpro); + UNGCPRO; return -1; } @@ -10049,7 +10087,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, add_command_key (keybuf[t]); } - UNGCPRO_VAR (outer_gcpro); + UNGCPRO; return t; } @@ -10137,7 +10175,7 @@ will read just one key sequence. */) ! NILP (can_return_switch_frame), 0); #if 0 /* The following is fine for code reading a key sequence and - then proceeding with a lenghty computation, but it's not good + then proceeding with a lengthy computation, but it's not good for code reading keys in a loop, like an input method. */ #ifdef HAVE_WINDOW_SYSTEM if (display_hourglass_p) @@ -10175,7 +10213,7 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector, memset (keybuf, 0, sizeof keybuf); GCPRO1 (keybuf[0]); - gcpro1.nvars = (sizeof keybuf/sizeof (keybuf[0])); + gcpro1.nvars = (sizeof keybuf / sizeof (keybuf[0])); if (NILP (continue_echo)) { @@ -10189,7 +10227,7 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector, 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); @@ -10522,6 +10560,9 @@ if there is a doubt, the value is t. */) || !NILP (Vunread_input_method_events)) return (Qt); + /* Process non-user-visible events (Bug#10195). */ + process_special_events (); + get_input_pending (&input_pending, READABLE_EVENTS_DO_TIMERS_NOW | READABLE_EVENTS_FILTER_EVENTS); @@ -10824,7 +10865,7 @@ set_waiting_for_input (struct timeval *time_to_clear) /* If handle_interrupt was called before and buffered a C-g, make it run again now, to avoid timing error. */ if (!NILP (Vquit_flag)) - quit_throw_to_read_char (); + quit_throw_to_read_char (0); } void @@ -10839,7 +10880,7 @@ clear_waiting_for_input (void) If we have a frame on the controlling tty, we assume that the SIGINT was generated by C-g, so we call handle_interrupt. - Otherwise, the handler kills Emacs. */ + Otherwise, tell QUIT to kill Emacs. */ static void interrupt_signal (int signalnum) /* If we don't have an argument, some */ @@ -10856,12 +10897,10 @@ interrupt_signal (int signalnum) /* If we don't have an argument, some */ if (!terminal) { /* If there are no frames there, let's pretend that we are a - well-behaving UN*X program and quit. We cannot do that while - GC is in progress, though. */ - if (!gc_in_progress) - Fkill_emacs (Qnil); - else - Vquit_flag = Qt; + well-behaving UN*X program and quit. We must not call Lisp + in a signal handler, so tell QUIT to exit when it is + safe. */ + Vquit_flag = Qkill_emacs; } else { @@ -10879,6 +10918,11 @@ interrupt_signal (int signalnum) /* If we don't have an argument, some */ errno = old_errno; } +/* If Emacs is stuck because `inhibit-quit' is true, then keep track + of the number of times C-g has been requested. If C-g is pressed + enough times, then quit anyway. See bug#6585. */ +static int force_quit_count; + /* This routine is called at interrupt level in response to C-g. It is called from the SIGINT handler or kbd_buffer_store_event. @@ -10997,8 +11041,16 @@ handle_interrupt (void) UNGCPRO; } else - /* Else request quit when it's safe */ - Vquit_flag = Qt; + { /* Else request quit when it's safe. */ + if (NILP (Vquit_flag)) + force_quit_count = 0; + if (++force_quit_count == 3) + { + immediate_quit = 1; + Vinhibit_quit = Qnil; + } + Vquit_flag = Qt; + } } /* TODO: The longjmp in this call throws the NS event loop integration off, @@ -11010,15 +11062,20 @@ handle_interrupt (void) separate event loop thread like W32. */ #ifndef HAVE_NS if (waiting_for_input && !echoing) - quit_throw_to_read_char (); + quit_throw_to_read_char (1); #endif } /* Handle a C-g by making read_char return C-g. */ static void -quit_throw_to_read_char (void) +quit_throw_to_read_char (int from_signal) { + /* When not called from a signal handler it is safe to call + Lisp. */ + if (!from_signal && EQ (Vquit_flag, Qkill_emacs)) + Fkill_emacs (Qnil); + sigfree (); /* Prevent another signal from doing this before we finish. */ clear_waiting_for_input (); @@ -11607,6 +11664,7 @@ syms_of_keyboard (void) DEFSYM (Qx_set_selection, "x-set-selection"); DEFSYM (QPRIMARY, "PRIMARY"); DEFSYM (Qhandle_switch_frame, "handle-switch-frame"); + DEFSYM (Qhandle_select_window, "handle-select-window"); DEFSYM (Qinput_method_function, "input-method-function"); DEFSYM (Qinput_method_exit_on_first_char, "input-method-exit-on-first-char"); @@ -11819,38 +11877,39 @@ result of looking up the original command in the active keymaps. */); Vthis_original_command = Qnil; DEFVAR_INT ("auto-save-interval", auto_save_interval, - doc: /* *Number of input events between auto-saves. + doc: /* Number of input events between auto-saves. Zero means disable autosaving due to number of characters typed. */); auto_save_interval = 300; DEFVAR_LISP ("auto-save-timeout", Vauto_save_timeout, - doc: /* *Number of seconds idle time before auto-save. + doc: /* Number of seconds idle time before auto-save. Zero or nil means disable auto-saving due to idleness. After auto-saving due to this many seconds of idle time, Emacs also does a garbage collection if that seems to be warranted. */); XSETFASTINT (Vauto_save_timeout, 30); DEFVAR_LISP ("echo-keystrokes", Vecho_keystrokes, - doc: /* *Nonzero means echo unfinished commands after this many seconds of pause. -The value may be integer or floating point. */); + doc: /* Nonzero means echo unfinished commands after this many seconds of pause. +The value may be integer or floating point. +If the value is zero, don't echo at all. */); Vecho_keystrokes = make_number (1); DEFVAR_INT ("polling-period", polling_period, - doc: /* *Interval between polling for input during Lisp execution. + doc: /* Interval between polling for input during Lisp execution. The reason for polling is to make C-g work to stop a running program. Polling is needed only when using X windows and SIGIO does not work. Polling is automatically disabled in all other cases. */); polling_period = 2; DEFVAR_LISP ("double-click-time", Vdouble_click_time, - doc: /* *Maximum time between mouse clicks to make a double-click. + doc: /* Maximum time between mouse clicks to make a double-click. Measured in milliseconds. The value nil means disable double-click recognition; t means double-clicks have no time limit and are detected by position only. */); Vdouble_click_time = make_number (500); DEFVAR_INT ("double-click-fuzz", double_click_fuzz, - doc: /* *Maximum mouse movement between clicks to make a double-click. + doc: /* Maximum mouse movement between clicks to make a double-click. On window-system frames, value is the number of pixels the mouse may have moved horizontally or vertically between two clicks to make a double-click. On non window-system frames, value is interpreted in units of 1/8 characters @@ -11861,7 +11920,7 @@ to count as a drag. */); double_click_fuzz = 3; DEFVAR_BOOL ("inhibit-local-menu-bar-menus", inhibit_local_menu_bar_menus, - doc: /* *Non-nil means inhibit local map menu bar menus. */); + doc: /* Non-nil means inhibit local map menu bar menus. */); inhibit_local_menu_bar_menus = 0; DEFVAR_INT ("num-input-keys", num_input_keys, @@ -12036,7 +12095,7 @@ and the minor mode maps regardless of `overriding-local-map'. */); Vspecial_event_map = Fcons (intern_c_string ("keymap"), Qnil); DEFVAR_LISP ("track-mouse", do_mouse_tracking, - doc: /* *Non-nil means generate motion events for mouse motion. */); + doc: /* Non-nil means generate motion events for mouse motion. */); DEFVAR_KBOARD ("system-key-alist", Vsystem_key_alist, doc: /* Alist of system-specific X windows key symbols. @@ -12100,7 +12159,7 @@ This variable is keyboard-local. */); Function key definitions that apply to all terminal devices should go 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. */); +definition will take precedence. */); Vfunction_key_map = Fmake_sparse_keymap (Qnil); DEFVAR_LISP ("key-translation-map", Vkey_translation_map, @@ -12122,7 +12181,7 @@ whenever `deferred-action-list' is non-nil. */); Vdeferred_action_function = Qnil; DEFVAR_LISP ("delayed-warnings-list", Vdelayed_warnings_list, - doc: /* List of warnings to be displayed as soon as possible. + doc: /* List of warnings to be displayed after this command. Each element must be a list (TYPE MESSAGE [LEVEL [BUFFER-NAME]]), as per the args of `display-warning' (which see). If this variable is non-nil, `delayed-warnings-hook' will be run @@ -12130,7 +12189,7 @@ immediately after running `post-command-hook'. */); Vdelayed_warnings_list = Qnil; DEFVAR_LISP ("suggest-key-bindings", Vsuggest_key_bindings, - doc: /* *Non-nil means show the equivalent key-binding when M-x command has one. + doc: /* Non-nil means show the equivalent key-binding when M-x command has one. The value can be a length of time to show the message for. If the value is non-nil and not a number, we wait 2 seconds. */); Vsuggest_key_bindings = Qt; @@ -12190,7 +12249,7 @@ just after executing the command. */); DEFVAR_LISP ("global-disable-point-adjustment", Vglobal_disable_point_adjustment, - doc: /* *If non-nil, always suppress point adjustment. + doc: /* If non-nil, always suppress point adjustment. The default value is nil, in which case, point adjustment are suppressed only after special commands that set @@ -12198,7 +12257,7 @@ suppressed only after special commands that set Vglobal_disable_point_adjustment = Qnil; DEFVAR_LISP ("minibuffer-message-timeout", Vminibuffer_message_timeout, - doc: /* *How long to display an echo-area message when the minibuffer is active. + doc: /* How long to display an echo-area message when the minibuffer is active. If the value is not a number, such messages don't time out. */); Vminibuffer_message_timeout = make_number (2); @@ -12242,10 +12301,20 @@ text in the region before modifying the buffer. The next `deactivate-mark' call uses this to set the window selection. */); Vsaved_region_selection = Qnil; + DEFVAR_LISP ("selection-inhibit-update-commands", + Vselection_inhibit_update_commands, + doc: /* List of commands which should not update the selection. +Normally, if `select-active-regions' is non-nil and the mark remains +active after a command (i.e. the mark was not deactivated), the Emacs +command loop sets the selection to the text in the region. However, +if the command is in this list, the selection is not updated. */); + Vselection_inhibit_update_commands + = list2 (Qhandle_switch_frame, Qhandle_select_window); + DEFVAR_LISP ("debug-on-event", Vdebug_on_event, doc: /* Enter debugger on this event. When Emacs -receives the special event specifed by this variable, it will try to +receives the special event specified by this variable, it will try to break into the debugger as soon as possible instead of processing the event normally through `special-event-map'.