X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/fe088644a609a9319c53a0d221e63dc7c552d1f1..536d6baa1d78235e4aeb3283d271d9c7a6812638:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index 3b9447f24b..9ce832ea42 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1928,7 +1928,12 @@ adjust_point_for_property (last_pt, modified) : (PT < last_pt ? beg : end)); check_composition = check_display = 1; } +#if 0 /* This assertion isn't correct, because SET_PT may end up setting + the point to something other than its argument, due to + point-motion hooks, intangibility, etc. */ xassert (PT == beg || PT == end); +#endif + /* Pretend the area doesn't exist if the buffer is not modified. */ if (!modified && !ellipsis && beg < end) @@ -3518,10 +3523,33 @@ event_to_kboard (event) void kbd_buffer_store_event (event) register struct input_event *event; +{ + kbd_buffer_store_event_hold (event, 0); +} + +/* Store EVENT obtained at interrupt level into kbd_buffer, fifo. + + If HOLD_QUIT is 0, just stuff EVENT into the fifo. + Else, if HOLD_QUIT.kind != NO_EVENT, discard EVENT. + Else, if EVENT is a quit event, store the quit event + in HOLD_QUIT, and return (thus ignoring further events). + + This is used in read_avail_input to postpone the processing + of the quit event until all subsequent input events have been + parsed (and discarded). + */ + +void +kbd_buffer_store_event_hold (event, hold_quit) + register struct input_event *event; + struct input_event *hold_quit; { if (event->kind == NO_EVENT) abort (); + if (hold_quit && hold_quit->kind != NO_EVENT) + return; + if (event->kind == ASCII_KEYSTROKE_EVENT) { register int c = event->code & 0377; @@ -3563,6 +3591,12 @@ kbd_buffer_store_event (event) } #endif + if (hold_quit) + { + bcopy (event, (char *) hold_quit, sizeof (*event)); + return; + } + /* If this results in a quit_char being returned to Emacs as input, set Vlast_event_frame properly. If this doesn't get returned to Emacs as an event, the next event read @@ -3592,7 +3626,9 @@ kbd_buffer_store_event (event) Just ignore the second one. */ else if (event->kind == BUFFER_SWITCH_EVENT && kbd_fetch_ptr != kbd_store_ptr - && kbd_store_ptr->kind == BUFFER_SWITCH_EVENT) + && ((kbd_store_ptr == kbd_buffer + ? kbd_buffer + KBD_BUFFER_SIZE - 1 + : kbd_store_ptr - 1)->kind) == BUFFER_SWITCH_EVENT) return; if (kbd_store_ptr - kbd_buffer == KBD_BUFFER_SIZE) @@ -3651,24 +3687,22 @@ kbd_buffer_store_event (event) Value is the number of input_events generated. */ -int -gen_help_event (bufp, size, help, frame, window, object, pos) - struct input_event *bufp; - int size; +void +gen_help_event (help, frame, window, object, pos) Lisp_Object help, frame, object, window; int pos; { - if (size >= 1) - { - bufp->kind = HELP_EVENT; - bufp->frame_or_window = frame; - bufp->arg = object; - bufp->x = WINDOWP (window) ? window : frame; - bufp->y = help; - bufp->code = pos; - return 1; - } - return 0; + struct input_event event; + + EVENT_INIT (event); + + event.kind = HELP_EVENT; + event.frame_or_window = frame; + event.arg = object; + event.x = WINDOWP (window) ? window : frame; + event.y = help; + event.code = pos; + kbd_buffer_store_event (&event); } @@ -4985,7 +5019,7 @@ make_lispy_position (f, x, y, time) { Lisp_Object string; int charpos; - + posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin; rx = wx, ry = wy; string = marginal_area_string (w, part, &rx, &ry, &charpos, @@ -5468,7 +5502,7 @@ make_lispy_event (event) { Lisp_Object position; Lisp_Object head; - + /* Build the position as appropriate for this mouse click. */ struct frame *f = XFRAME (event->frame_or_window); @@ -6556,11 +6590,6 @@ record_asynch_buffer_change () #ifndef VMS -/* This remembers the last number of characters read, so we could - avoid zeroing out the whole struct input_event buf and instead zero - out only its used slots. */ -static int prev_read = KBD_BUFFER_SIZE; - /* Read any terminal input already buffered up by the system into the kbd_buffer, but do not wait. @@ -6577,16 +6606,27 @@ static int read_avail_input (expected) int expected; { - struct input_event buf[KBD_BUFFER_SIZE]; register int i; - int nread; - - for (i = 0; i < prev_read; i++) - EVENT_INIT (buf[i]); + int nread = 0; if (read_socket_hook) - /* No need for FIONREAD or fcntl; just say don't wait. */ - nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE, expected); + { + int discard = 0; + int nr; + struct input_event hold_quit; + + EVENT_INIT (hold_quit); + hold_quit.kind = NO_EVENT; + + /* No need for FIONREAD or fcntl; just say don't wait. */ + while (nr = (*read_socket_hook) (input_fd, expected, &hold_quit), nr > 0) + { + nread += nr; + expected = 0; + } + if (hold_quit.kind != NO_EVENT) + kbd_buffer_store_event (&hold_quit); + } else { /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than @@ -6597,12 +6637,12 @@ read_avail_input (expected) /* Determine how many characters we should *try* to read. */ #ifdef WINDOWSNT - return (prev_read = 0); + return 0; #else /* not WINDOWSNT */ #ifdef MSDOS n_to_read = dos_keysns (); if (n_to_read == 0) - return (prev_read = 0); + return 0; #else /* not MSDOS */ #ifdef FIONREAD /* Find out how much input is available. */ @@ -6620,7 +6660,7 @@ read_avail_input (expected) n_to_read = 0; } if (n_to_read == 0) - return (prev_read = 0); + return 0; if (n_to_read > sizeof cbuf) n_to_read = sizeof cbuf; #else /* no FIONREAD */ @@ -6687,31 +6727,29 @@ read_avail_input (expected) #endif /* no FIONREAD */ for (i = 0; i < nread; i++) { - buf[i].kind = ASCII_KEYSTROKE_EVENT; - buf[i].modifiers = 0; + struct input_event buf; + EVENT_INIT (buf); + buf.kind = ASCII_KEYSTROKE_EVENT; + buf.modifiers = 0; if (meta_key == 1 && (cbuf[i] & 0x80)) - buf[i].modifiers = meta_modifier; + buf.modifiers = meta_modifier; if (meta_key != 2) cbuf[i] &= ~0x80; - buf[i].code = cbuf[i]; - buf[i].frame_or_window = selected_frame; - buf[i].arg = Qnil; - } - } + buf.code = cbuf[i]; + buf.frame_or_window = selected_frame; + buf.arg = Qnil; - /* Scan the chars for C-g and store them in kbd_buffer. */ - for (i = 0; i < nread; i++) - { - kbd_buffer_store_event (&buf[i]); - /* Don't look at input that follows a C-g too closely. - This reduces lossage due to autorepeat on C-g. */ - if (buf[i].kind == ASCII_KEYSTROKE_EVENT - && buf[i].code == quit_char) - break; + 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. */ + if (buf.kind == ASCII_KEYSTROKE_EVENT + && buf.code == quit_char) + break; + } } - return (prev_read = nread); + return nread; } #endif /* not VMS */ @@ -7369,7 +7407,7 @@ parse_menu_item (item, notreal, inmenubar) newcache = chkcache; if (chkcache) { - tem = Fkey_description (tem); + tem = Fkey_description (tem, Qnil); if (CONSP (prefix)) { if (STRINGP (XCAR (prefix))) @@ -8243,7 +8281,7 @@ access_keymap_keyremap (map, key, prompt, do_funcall) int do_funcall; { Lisp_Object next; - + next = access_keymap (map, key, 1, 0, 1); /* Handle symbol with autoload definition. */ @@ -8258,7 +8296,7 @@ access_keymap_keyremap (map, key, prompt, do_funcall) && (!NILP (Farrayp (XSYMBOL (next)->function)) || KEYMAPP (XSYMBOL (next)->function))) next = XSYMBOL (next)->function; - + /* If the keymap gives a function, not an array, then call the function with one arg and use its value instead. */ @@ -9272,7 +9310,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* Adjust the function-key-map counters. */ fkey.end += diff; fkey.start += diff; - + goto replay_sequence; } } @@ -9768,7 +9806,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_ int count = SPECPDL_INDEX (); record_unwind_protect (pop_message_unwind, Qnil); - binding = Fkey_description (bindings); + binding = Fkey_description (bindings, Qnil); newmessage = (char *) alloca (SCHARS (SYMBOL_NAME (function)) @@ -10451,6 +10489,61 @@ The elements of this list correspond to the arguments of return Flist (sizeof (val) / sizeof (val[0]), val); } +DEFUN ("posn-at-x-y", Fposn_at_x_y, Sposn_at_x_y, 2, 3, 0, + doc: /* Return position information for pixel coordinates X and Y. +By default, X and Y are relative to text area of the selected window. +Optional third arg FRAME_OR_WINDOW non-nil specifies frame or window. + +The return value is similar to a mouse click position: + (WINDOW AREA-OR-POS (X . Y) TIMESTAMP OBJECT POS (COL . ROW) + IMAGE (DX . DY) (WIDTH . HEIGHT)) +The `posn-' functions access elements of such lists. */) + (x, y, frame_or_window) + Lisp_Object x, y, frame_or_window; +{ + if (NILP (frame_or_window)) + frame_or_window = selected_window; + + if (WINDOWP (frame_or_window)) + { + struct window *w; + + CHECK_LIVE_WINDOW (frame_or_window); + + w = XWINDOW (frame_or_window); + XSETINT (x, (WINDOW_TO_FRAME_PIXEL_X (w, XINT (x)) + + window_box_left_offset (w, TEXT_AREA))); + XSETINT (y, WINDOW_TO_FRAME_PIXEL_Y (w, XINT (y))); + frame_or_window = w->frame; + } + + CHECK_LIVE_FRAME (frame_or_window); + + return make_lispy_position (XFRAME (frame_or_window), &x, &y, 0); +} + +DEFUN ("posn-at-point", Fposn_at_point, Sposn_at_point, 0, 2, 0, + doc: /* Return position information for buffer POS in WINDOW. +POS defaults to point in WINDOW; WINDOW defaults to the selected window. + +Return nil if position is not visible in window. Otherwise, +the return value is similar to that returned by event-start for +a mouse click at the upper left corner of the glyph corresponding +to the given buffer position: + (WINDOW AREA-OR-POS (X . Y) TIMESTAMP OBJECT POS (COL . ROW) + IMAGE (DX . DY) (WIDTH . HEIGHT)) +The `posn-' functions access elements of such lists. */*/) + (pos, window) + Lisp_Object pos, window; +{ + Lisp_Object tem; + + tem = Fpos_visible_in_window_p (pos, window, Qt); + if (!NILP (tem)) + tem = Fposn_at_x_y (XCAR (tem), XCAR (XCDR (tem)), window); + return tem; +} + /* * Set up a new kboard object with reasonable initial values. @@ -10874,6 +10967,8 @@ syms_of_keyboard () defsubr (&Sset_input_mode); defsubr (&Scurrent_input_mode); defsubr (&Sexecute_extended_command); + defsubr (&Sposn_at_point); + defsubr (&Sposn_at_x_y); DEFVAR_LISP ("last-command-char", &last_command_char, doc: /* Last input event that was part of a command. */); @@ -11280,7 +11375,7 @@ keys_of_keyboard () /* Handling it at such a low-level causes read_key_sequence to get * confused because it doesn't realize that the current_buffer was * changed by read_char. - * + * * initial_define_lispy_key (Vspecial_event_map, "select-window", * "handle-select-window"); */ initial_define_lispy_key (Vspecial_event_map, "save-session",