diff options
| author | Richard M. Stallman | 1996-01-29 04:53:02 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1996-01-29 04:53:02 +0000 |
| commit | c04cbc3b12665ec8f06c12f6c0be2680523c39c1 (patch) | |
| tree | 44fd83fc4c61362f07e89e3e44b1b9a05ecb8584 /src | |
| parent | 038328930df6c0bf12eea61e5ab6ed57b6e94b40 (diff) | |
| download | emacs-c04cbc3b12665ec8f06c12f6c0be2680523c39c1.tar.gz emacs-c04cbc3b12665ec8f06c12f6c0be2680523c39c1.zip | |
(Qtimer_event): New symbol.
(read_char, kbd_buffer_get_event): Don't sleep past the next timer.
(readable_events, kbd_buffer_get_event): Check for timer events.
(make_lispy_event): Handle timer events.
(timer_check): New function.
(Vtimer_list): New variable.
(syms_of_keyboard): Set up Qtimer_event and Vtimer_list.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keyboard.c | 128 |
1 files changed, 124 insertions, 4 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index f12da3ad580..3dd9304a577 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Keyboard and mouse input; editor command loop. | 1 | /* Keyboard and mouse input; editor command loop. |
| 2 | Copyright (C) 1985,86,87,88,89,93,94,95 Free Software Foundation, Inc. | 2 | Copyright (C) 1985,86,87,88,89,93,94,95,96 Free Software Foundation, Inc. |
| 3 | 3 | ||
| 4 | This file is part of GNU Emacs. | 4 | This file is part of GNU Emacs. |
| 5 | 5 | ||
| @@ -435,6 +435,7 @@ Lisp_Object Qmake_frame_visible; | |||
| 435 | /* Symbols to denote kinds of events. */ | 435 | /* Symbols to denote kinds of events. */ |
| 436 | Lisp_Object Qfunction_key; | 436 | Lisp_Object Qfunction_key; |
| 437 | Lisp_Object Qmouse_click; | 437 | Lisp_Object Qmouse_click; |
| 438 | Lisp_Object Qtimer_event; | ||
| 438 | /* Lisp_Object Qmouse_movement; - also an event header */ | 439 | /* Lisp_Object Qmouse_movement; - also an event header */ |
| 439 | 440 | ||
| 440 | /* Properties of event headers. */ | 441 | /* Properties of event headers. */ |
| @@ -467,11 +468,15 @@ extern Lisp_Object Qmenu_enable; | |||
| 467 | Lisp_Object recursive_edit_unwind (), command_loop (); | 468 | Lisp_Object recursive_edit_unwind (), command_loop (); |
| 468 | Lisp_Object Fthis_command_keys (); | 469 | Lisp_Object Fthis_command_keys (); |
| 469 | Lisp_Object Qextended_command_history; | 470 | Lisp_Object Qextended_command_history; |
| 471 | EMACS_TIME timer_check (); | ||
| 470 | 472 | ||
| 471 | extern char *x_get_keysym_name (); | 473 | extern char *x_get_keysym_name (); |
| 472 | 474 | ||
| 473 | Lisp_Object Qpolling_period; | 475 | Lisp_Object Qpolling_period; |
| 474 | 476 | ||
| 477 | /* List of active timers. Appears in order of next scheduled event. */ | ||
| 478 | Lisp_Object Vtimer_list; | ||
| 479 | |||
| 475 | extern Lisp_Object Vprint_level, Vprint_length; | 480 | extern Lisp_Object Vprint_level, Vprint_length; |
| 476 | 481 | ||
| 477 | /* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt | 482 | /* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt |
| @@ -1883,11 +1888,25 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) | |||
| 1883 | && XINT (Vauto_save_timeout) > 0) | 1888 | && XINT (Vauto_save_timeout) > 0) |
| 1884 | { | 1889 | { |
| 1885 | Lisp_Object tem0; | 1890 | Lisp_Object tem0; |
| 1886 | int delay = delay_level * XFASTINT (Vauto_save_timeout) / 4; | 1891 | EMACS_TIME timer_delay; |
| 1892 | EMACS_TIME delay, difference; | ||
| 1893 | |||
| 1894 | EMACS_SET_SECS (delay, | ||
| 1895 | delay_level * XFASTINT (Vauto_save_timeout) / 4); | ||
| 1896 | EMACS_SET_USECS (delay, 0); | ||
| 1897 | |||
| 1898 | /* Don't wait longer than until the next timer will fire. */ | ||
| 1899 | timer_delay = timer_check (0); | ||
| 1900 | if (! EMACS_TIME_NEG_P (timer_delay)) | ||
| 1901 | { | ||
| 1902 | EMACS_SUB_TIME (difference, timer_delay, delay); | ||
| 1903 | if (EMACS_TIME_NEG_P (difference)) | ||
| 1904 | delay = timer_delay; | ||
| 1905 | } | ||
| 1887 | 1906 | ||
| 1888 | save_getcjmp (save_jump); | 1907 | save_getcjmp (save_jump); |
| 1889 | restore_getcjmp (local_getcjmp); | 1908 | restore_getcjmp (local_getcjmp); |
| 1890 | tem0 = sit_for (delay, 0, 1, 1); | 1909 | tem0 = sit_for (EMACS_SECS (delay), EMACS_USECS (delay), 1, 1); |
| 1891 | restore_getcjmp (save_jump); | 1910 | restore_getcjmp (save_jump); |
| 1892 | 1911 | ||
| 1893 | if (EQ (tem0, Qt)) | 1912 | if (EQ (tem0, Qt)) |
| @@ -2322,6 +2341,7 @@ some_mouse_moved () | |||
| 2322 | static int | 2341 | static int |
| 2323 | readable_events () | 2342 | readable_events () |
| 2324 | { | 2343 | { |
| 2344 | timer_check (0); | ||
| 2325 | if (kbd_fetch_ptr != kbd_store_ptr) | 2345 | if (kbd_fetch_ptr != kbd_store_ptr) |
| 2326 | return 1; | 2346 | return 1; |
| 2327 | #ifdef HAVE_MOUSE | 2347 | #ifdef HAVE_MOUSE |
| @@ -2501,6 +2521,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu) | |||
| 2501 | { | 2521 | { |
| 2502 | register int c; | 2522 | register int c; |
| 2503 | Lisp_Object obj; | 2523 | Lisp_Object obj; |
| 2524 | EMACS_TIME next_timer_delay; | ||
| 2504 | 2525 | ||
| 2505 | if (noninteractive) | 2526 | if (noninteractive) |
| 2506 | { | 2527 | { |
| @@ -2520,6 +2541,17 @@ kbd_buffer_get_event (kbp, used_mouse_menu) | |||
| 2520 | break; | 2541 | break; |
| 2521 | #endif | 2542 | #endif |
| 2522 | 2543 | ||
| 2544 | /* Check when the next timer fires. */ | ||
| 2545 | next_timer_delay = timer_check (0); | ||
| 2546 | if (EMACS_SECS (next_timer_delay) == 0 | ||
| 2547 | && EMACS_USECS (next_timer_delay) == 0) | ||
| 2548 | break; | ||
| 2549 | if (EMACS_TIME_NEG_P (next_timer_delay)) | ||
| 2550 | { | ||
| 2551 | EMACS_SET_SECS (next_timer_delay, 0); | ||
| 2552 | EMACS_SET_USECS (next_timer_delay, 0); | ||
| 2553 | } | ||
| 2554 | |||
| 2523 | /* If the quit flag is set, then read_char will return | 2555 | /* If the quit flag is set, then read_char will return |
| 2524 | quit_char, so that counts as "available input." */ | 2556 | quit_char, so that counts as "available input." */ |
| 2525 | if (!NILP (Vquit_flag)) | 2557 | if (!NILP (Vquit_flag)) |
| @@ -2545,7 +2577,9 @@ kbd_buffer_get_event (kbp, used_mouse_menu) | |||
| 2545 | Lisp_Object minus_one; | 2577 | Lisp_Object minus_one; |
| 2546 | 2578 | ||
| 2547 | XSETINT (minus_one, -1); | 2579 | XSETINT (minus_one, -1); |
| 2548 | wait_reading_process_input (0, 0, minus_one, 1); | 2580 | wait_reading_process_input (EMACS_SECS (next_timer_delay), |
| 2581 | EMACS_USECS (next_timer_delay), | ||
| 2582 | minus_one, 1); | ||
| 2549 | 2583 | ||
| 2550 | if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr) | 2584 | if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr) |
| 2551 | /* Pass 1 for EXPECT since we just waited to have input. */ | 2585 | /* Pass 1 for EXPECT since we just waited to have input. */ |
| @@ -2830,6 +2864,83 @@ swallow_events () | |||
| 2830 | get_input_pending (&input_pending); | 2864 | get_input_pending (&input_pending); |
| 2831 | } | 2865 | } |
| 2832 | 2866 | ||
| 2867 | /* Check whether a timer has fired. To prevent larger problems we simply | ||
| 2868 | disregard elements that are not proper timers. Do not make a circular | ||
| 2869 | timer list for the time being. | ||
| 2870 | |||
| 2871 | Returns the number of seconds to wait until the next timer fires. If a | ||
| 2872 | timer is triggering now, return zero seconds. | ||
| 2873 | If no timer is active, return -1 seconds. | ||
| 2874 | |||
| 2875 | If a timer is triggering now, either queue a timer-event | ||
| 2876 | or run the timer's handler function if DO_IT_NOW is nonzero. */ | ||
| 2877 | |||
| 2878 | EMACS_TIME | ||
| 2879 | timer_check (do_it_now) | ||
| 2880 | int do_it_now; | ||
| 2881 | { | ||
| 2882 | EMACS_TIME nexttime; | ||
| 2883 | EMACS_TIME now; | ||
| 2884 | Lisp_Object timers = Vtimer_list; | ||
| 2885 | |||
| 2886 | EMACS_GET_TIME (now); | ||
| 2887 | EMACS_SET_SECS (nexttime, -1); | ||
| 2888 | EMACS_SET_USECS (nexttime, -1); | ||
| 2889 | |||
| 2890 | while (CONSP (timers)) | ||
| 2891 | { | ||
| 2892 | int triggertime; | ||
| 2893 | Lisp_Object timer, *vector; | ||
| 2894 | EMACS_TIME timer_time; | ||
| 2895 | EMACS_TIME difference; | ||
| 2896 | |||
| 2897 | timer = XCONS (timers)->car; | ||
| 2898 | timers = XCONS (timers)->cdr; | ||
| 2899 | |||
| 2900 | if (!VECTORP (timer) || XVECTOR (timer)->size != 7) | ||
| 2901 | continue; | ||
| 2902 | vector = XVECTOR (timer)->contents; | ||
| 2903 | |||
| 2904 | if (!INTEGERP (vector[1]) || !INTEGERP (vector[2]) | ||
| 2905 | || !INTEGERP (vector[3])) | ||
| 2906 | continue; | ||
| 2907 | |||
| 2908 | EMACS_SET_SECS (timer_time, | ||
| 2909 | (XINT (vector[1]) << 16) | (XINT (vector[2]))); | ||
| 2910 | EMACS_SET_USECS (timer_time, XINT (vector[3])); | ||
| 2911 | EMACS_SUB_TIME (difference, timer_time, now); | ||
| 2912 | if (EMACS_TIME_NEG_P (difference)) | ||
| 2913 | { | ||
| 2914 | if (NILP (vector[0])) | ||
| 2915 | { | ||
| 2916 | if (do_it_now) | ||
| 2917 | apply1 (vector[5], vector[6]); | ||
| 2918 | else | ||
| 2919 | { | ||
| 2920 | struct input_event event; | ||
| 2921 | |||
| 2922 | event.kind = timer_event; | ||
| 2923 | event.modifiers = 0; | ||
| 2924 | event.x = event.y = Qnil; | ||
| 2925 | event.timestamp = triggertime; | ||
| 2926 | /* Store the timer in the frame slot. */ | ||
| 2927 | event.frame_or_window = Fcons (Fselected_frame (), timer); | ||
| 2928 | kbd_buffer_store_event (&event); | ||
| 2929 | |||
| 2930 | /* Mark the timer as triggered to prevent problems if the lisp | ||
| 2931 | code fails to reschedule it right. */ | ||
| 2932 | vector[0] = Qt; | ||
| 2933 | EMACS_SET_SECS (nexttime, 0); | ||
| 2934 | EMACS_SET_USECS (nexttime, 0); | ||
| 2935 | } | ||
| 2936 | } | ||
| 2937 | } | ||
| 2938 | else | ||
| 2939 | return difference; | ||
| 2940 | } | ||
| 2941 | return nexttime; | ||
| 2942 | } | ||
| 2943 | |||
| 2833 | /* Caches for modify_event_symbol. */ | 2944 | /* Caches for modify_event_symbol. */ |
| 2834 | static Lisp_Object accent_key_syms; | 2945 | static Lisp_Object accent_key_syms; |
| 2835 | static Lisp_Object func_key_syms; | 2946 | static Lisp_Object func_key_syms; |
| @@ -3297,6 +3408,9 @@ make_lispy_event (event) | |||
| 3297 | / sizeof (lispy_function_keys[0]))); | 3408 | / sizeof (lispy_function_keys[0]))); |
| 3298 | break; | 3409 | break; |
| 3299 | 3410 | ||
| 3411 | case timer_event: | ||
| 3412 | return Fcons (Qtimer_event, Fcdr (event->frame_or_window)); | ||
| 3413 | |||
| 3300 | #ifdef HAVE_MOUSE | 3414 | #ifdef HAVE_MOUSE |
| 3301 | /* A mouse click. Figure out where it is, decide whether it's | 3415 | /* A mouse click. Figure out where it is, decide whether it's |
| 3302 | a press, click or drag, and build the appropriate structure. */ | 3416 | a press, click or drag, and build the appropriate structure. */ |
| @@ -7299,6 +7413,8 @@ syms_of_keyboard () | |||
| 7299 | staticpro (&Qfunction_key); | 7413 | staticpro (&Qfunction_key); |
| 7300 | Qmouse_click = intern ("mouse-click"); | 7414 | Qmouse_click = intern ("mouse-click"); |
| 7301 | staticpro (&Qmouse_click); | 7415 | staticpro (&Qmouse_click); |
| 7416 | Qtimer_event = intern ("timer-event"); | ||
| 7417 | staticpro (&Qtimer_event); | ||
| 7302 | 7418 | ||
| 7303 | Qmenu_enable = intern ("menu-enable"); | 7419 | Qmenu_enable = intern ("menu-enable"); |
| 7304 | staticpro (&Qmenu_enable); | 7420 | staticpro (&Qmenu_enable); |
| @@ -7664,6 +7780,10 @@ If the value is non-nil and not a number, we wait 2 seconds."); | |||
| 7664 | DEFVAR_LISP ("column-number-mode", &Vcolumn_number_mode, | 7780 | DEFVAR_LISP ("column-number-mode", &Vcolumn_number_mode, |
| 7665 | "Non-nil enables display of the current column number in the mode line."); | 7781 | "Non-nil enables display of the current column number in the mode line."); |
| 7666 | Vcolumn_number_mode = Qnil; | 7782 | Vcolumn_number_mode = Qnil; |
| 7783 | |||
| 7784 | DEFVAR_LISP ("timer-list", &Vtimer_list, | ||
| 7785 | "List of active timers in order of increasing time"); | ||
| 7786 | Vtimer_list = Qnil; | ||
| 7667 | } | 7787 | } |
| 7668 | 7788 | ||
| 7669 | keys_of_keyboard () | 7789 | keys_of_keyboard () |