comparison src/event-stream.c @ 1268:fffe735e63ee

[xemacs-hg @ 2003-02-07 11:50:50 by ben] fixes for menu crashes + better preemption behavior This contains two related changes: (1) Fix problems with reentrant calling of lwlib and associated crashes when selecting menu items. (2) Improve redisplay handling of preemption. Turn on lazy lock and hold down page-down or page-up and you'll see what I mean. They are related because they both touch on the code that retrieves events and handles the internal queues. console-msw.h, event-msw.c, event-stream.c, events.h, menubar-msw.c, menubar-x.c, menubar.h: mswindows_protect_modal_loop() has been generalized to event_stream_protect_modal_loop(), and moved to event-stream.c. mswindows_in_modal_loop ->in_modal_loop likewise. Changes in event-msw.c and menubar-msw.c for the new names and calling format (use structures instead of static variables in menubar-msw.c). Delete former in_menu_callback and use in_modal_loop in its place. Remove emacs_mswindows_quit_check_disallowed_p(), superseded by in_modal_loop. Use event_stream_protect_modal_loop() in pre_activate_callback() so that we get no lwlib reentrancy. Rearrange some of the code in event-msw.c to be grouped better. Make mswindows_drain_windows_queue() respect in_modal_loop and do nothing if so. cmdloop.c, event-stream.c: Don't conditionalize on LWLIB_MENUBARS_LUCID when giving error when in_modal_loop, and give better error. event-Xt.c, event-gtk.c: If in_modal_loop, only retrieve process and timeout events. Don't retrieve any X events because processing them can lead to reentrancy in lwlib -> death. event-stream.c: Remove unused parameter to check_event_stream_ok() and change all callers. lisp.h, event-stream.c: Rearrange some functions for increased clarity -- in particular, group all the input-pending/QUIT-related stuff together, and put right next to next-event stuff, to which it's related. Add the concept of "HOW_MANY" -- when asking whether user input is pending, you can ask if at least HOW_MANY events are pending, not just if any are. Add parameter to detect_input_pending() for this. Change recursive_sit_for from a Lisp_Object (which could only be Qt or Qnil) to an int, like it should be. event-Xt.c, event-gtk.c, event-xlike-inc.c: New file. Abstract out similar code in event_{Xt/gtk}_pending_p() and write only once, using include-file tricks. Rewrite this function to implement HOW_MANY and only process events when not in_modal_loop. event-msw.c: Implement HOW_MANY and only process events when not in_modal_loop. event-tty.c: Implement HOW_MANY. redisplay.c: Add var `max-preempts' to control maximum number of preempts. (#### perhaps not useful) Rewrite preemption check so that, rather than preempting when any user events are available, only preempt when a certain number (currently 4) of them are backed up. This effectively allows redisplay to proceed to completion in the presence of a fast auto-repeat (usually the auto-repeating is generated dynamically as necessary), and you get much better display behavior with lazy-lock active. event-unixoid.c: Comment changes. event-stream.c: Rewrite discard-input much more simply and safely using the drain-queue functions. I think the old version might loop forever if called when in_modal_loop. SEMI-UNRELATED CHANGES: ----------------------- event-stream.c: Turn QUIT-checking back on when running the pre-idle hook so it can be quit out of. indent.c: Document exact functioning of `vertical-motion' better, and its differences from GNU Emacs.
author ben
date Fri, 07 Feb 2003 11:50:54 +0000
parents e22b0213b713
children cd0abfdb9e9d
comparison
equal deleted inserted replaced
1267:c57f32e44416 1268:fffe735e63ee
1 /* The portable interface to event streams. 1 /* The portable interface to event streams.
2 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. 2 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Copyright (C) 1995 Board of Trustees, University of Illinois. 3 Copyright (C) 1995 Board of Trustees, University of Illinois.
4 Copyright (C) 1995 Sun Microsystems, Inc. 4 Copyright (C) 1995 Sun Microsystems, Inc.
5 Copyright (C) 1995, 1996, 2001, 2002 Ben Wing. 5 Copyright (C) 1995, 1996, 2001, 2002, 2003 Ben Wing.
6 6
7 This file is part of XEmacs. 7 This file is part of XEmacs.
8 8
9 XEmacs is free software; you can redistribute it and/or modify it 9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the 10 under the terms of the GNU General Public License as published by the
138 138
139 /* Non-nil disable property on a command means 139 /* Non-nil disable property on a command means
140 do not execute it; call disabled-command-hook's value instead. */ 140 do not execute it; call disabled-command-hook's value instead. */
141 Lisp_Object Qdisabled; 141 Lisp_Object Qdisabled;
142 142
143 EXFUN (Fnext_command_event, 2);
144
145 static void pre_command_hook (void);
146 static void post_command_hook (void);
147
148 /* Last keyboard or mouse input event read as a command. */ 143 /* Last keyboard or mouse input event read as a command. */
149 Lisp_Object Vlast_command_event; 144 Lisp_Object Vlast_command_event;
150 145
151 /* The nearest ASCII equivalent of the above. */ 146 /* The nearest ASCII equivalent of the above. */
152 Lisp_Object Vlast_command_char; 147 Lisp_Object Vlast_command_char;
247 recent-keys. */ 242 recent-keys. */
248 int inhibit_input_event_recording; 243 int inhibit_input_event_recording;
249 244
250 Lisp_Object Qself_insert_defer_undo; 245 Lisp_Object Qself_insert_defer_undo;
251 246
252 /* this is in keymap.c */ 247 int in_modal_loop;
253 extern Lisp_Object Fmake_keymap (Lisp_Object name); 248
249 /* the number of keyboard characters read. callint.c wants this. */
250 Charcount num_input_chars;
254 251
255 #ifdef DEBUG_XEMACS 252 #ifdef DEBUG_XEMACS
256 Fixnum debug_emacs_events; 253 Fixnum debug_emacs_events;
257 254
258 static void 255 static void
274 271
275 272
276 /* The callback routines for the window system or terminal driver */ 273 /* The callback routines for the window system or terminal driver */
277 struct event_stream *event_stream; 274 struct event_stream *event_stream;
278 275
279 static void echo_key_event (struct command_builder *, Lisp_Object event);
280 static void maybe_kbd_translate (Lisp_Object event);
281
282 /* There are two event queues here -- the command event queue (#### which 276 /* There are two event queues here -- the command event queue (#### which
283 should be called "deferred event queue" and is in my glyph ws) and the 277 should be called "deferred event queue" and is in my glyph ws) and the
284 dispatch event queue (#### MS Windows actually has an extra dispatch 278 dispatch event queue. (MS Windows actually has an extra dispatch
285 queue for non-user events and uses the generic one only for user events; 279 queue for non-user events and uses the generic one only for user events.
286 we should probably generalize this). 280 This is because user and non-user events in Windows come through the
281 same place -- the window procedure -- but under X, it's possible to
282 selectively process events such that we take all the user events before
283 the non-user ones. #### In fact, given the way we now drain the queue,
284 we might need two separate queues, like under Windows. Need to think
285 carefully exactly how this works, and should certainly generalize the
286 two different queues.
287 287
288 The dispatch queue (which used to occur duplicated inside of each event 288 The dispatch queue (which used to occur duplicated inside of each event
289 implementation) is used for events that have been read from the 289 implementation) is used for events that have been read from the
290 window-system event queue(s) and not yet process by 290 window-system event queue(s) and not yet process by
291 next_event_internal(). It exists for two reasons: (1) because in many 291 next_event_internal(). It exists for two reasons: (1) because in many
341 341
342 /* Handlers which run during sit-for, sleep-for and accept-process-output 342 /* Handlers which run during sit-for, sleep-for and accept-process-output
343 are not allowed to recursively call these routines. We record here 343 are not allowed to recursively call these routines. We record here
344 if we are in that situation. */ 344 if we are in that situation. */
345 345
346 static Lisp_Object recursive_sit_for; 346 static int recursive_sit_for;
347 347
348 static void pre_command_hook (void);
349 static void post_command_hook (void);
350 static void maybe_kbd_translate (Lisp_Object event);
351 static void push_this_command_keys (Lisp_Object event);
352 static void push_recent_keys (Lisp_Object event);
353 static void dribble_out_event (Lisp_Object event);
354 static void execute_internal_event (Lisp_Object event);
355 static int is_scrollbar_event (Lisp_Object event);
348 356
349 357
350 /**********************************************************************/ 358 /**********************************************************************/
351 /* Command-builder object */ 359 /* Command-builder object */
352 /**********************************************************************/ 360 /**********************************************************************/
511 519
512 /**********************************************************************/ 520 /**********************************************************************/
513 /* Low-level interfaces onto event methods */ 521 /* Low-level interfaces onto event methods */
514 /**********************************************************************/ 522 /**********************************************************************/
515 523
516 enum event_stream_operation
517 {
518 EVENT_STREAM_PROCESS,
519 EVENT_STREAM_TIMEOUT,
520 EVENT_STREAM_CONSOLE,
521 EVENT_STREAM_READ,
522 EVENT_STREAM_NOTHING,
523 };
524
525 static void 524 static void
526 check_event_stream_ok (enum event_stream_operation op) 525 check_event_stream_ok (void)
527 { 526 {
528 if (!event_stream && noninteractive) 527 if (!event_stream && noninteractive)
529 /* See comment in init_event_stream() */ 528 /* See comment in init_event_stream() */
530 init_event_stream (); 529 init_event_stream ();
531 else assert (event_stream); 530 else assert (event_stream);
532 } 531 }
533 532
534 static int
535 event_stream_event_pending_p (int user)
536 {
537 /* #### Hmmm ... There may be some duplication in "drain queue" and
538 "event pending". Couldn't we just drain the queue and see what's in
539 it, and not maybe need a separate event method for this? Would this
540 work when USER is 0? Maybe this would be slow? */
541 return event_stream && event_stream->event_pending_p (user);
542 }
543
544 static void
545 event_stream_force_event_pending (struct frame *f)
546 {
547 if (event_stream->force_event_pending_cb)
548 event_stream->force_event_pending_cb (f);
549 }
550
551 static int
552 maybe_read_quit_event (Lisp_Event *event)
553 {
554 /* A C-g that came from `sigint_happened' will always come from the
555 controlling terminal. If that doesn't exist, however, then the
556 user manually sent us a SIGINT, and we pretend the C-g came from
557 the selected console. */
558 struct console *con;
559
560 if (CONSOLEP (Vcontrolling_terminal) &&
561 CONSOLE_LIVE_P (XCONSOLE (Vcontrolling_terminal)))
562 con = XCONSOLE (Vcontrolling_terminal);
563 else
564 con = XCONSOLE (Fselected_console ());
565
566 if (sigint_happened)
567 {
568 sigint_happened = 0;
569 Vquit_flag = Qnil;
570 Fcopy_event (CONSOLE_QUIT_EVENT (con), wrap_event (event));
571 return 1;
572 }
573 return 0;
574 }
575
576 static void
577 event_stream_next_event (Lisp_Event *event)
578 {
579 Lisp_Object event_obj;
580
581 check_event_stream_ok (EVENT_STREAM_READ);
582
583 event_obj = wrap_event (event);
584 zero_event (event);
585 /* SIGINT occurs when C-g was pressed on a TTY. (SIGINT might have
586 been sent manually by the user, but we don't care; we treat it
587 the same.)
588
589 The SIGINT signal handler sets Vquit_flag as well as sigint_happened
590 and write a byte on our "fake pipe", which unblocks us when we are
591 waiting for an event. */
592
593 /* If SIGINT was received after we disabled quit checking (because
594 we want to read C-g's as characters), but before we got a chance
595 to start reading, notice it now and treat it as a character to be
596 read. If above callers wanted this to be QUIT, they can
597 determine this by comparing the event against quit-char. */
598
599 if (maybe_read_quit_event (event))
600 {
601 DEBUG_PRINT_EMACS_EVENT ("SIGINT", event_obj);
602 return;
603 }
604
605 /* If a longjmp() happens in the callback, we're screwed.
606 Let's hope it doesn't. I think the code here is fairly
607 clean and doesn't do this. */
608 emacs_is_blocking = 1;
609 event_stream->next_event_cb (event);
610 emacs_is_blocking = 0;
611
612 /* Now check to see if C-g was pressed while we were blocking.
613 We treat it as an event, just like above. */
614 if (maybe_read_quit_event (event))
615 {
616 DEBUG_PRINT_EMACS_EVENT ("SIGINT", event_obj);
617 return;
618 }
619
620 #ifdef DEBUG_XEMACS
621 /* timeout events have more info set later, so
622 print the event out in next_event_internal(). */
623 if (event->event_type != timeout_event)
624 DEBUG_PRINT_EMACS_EVENT ("real", event_obj);
625 #endif
626 maybe_kbd_translate (event_obj);
627 }
628
629 void 533 void
630 event_stream_handle_magic_event (Lisp_Event *event) 534 event_stream_handle_magic_event (Lisp_Event *event)
631 { 535 {
632 check_event_stream_ok (EVENT_STREAM_READ); 536 check_event_stream_ok ();
633 event_stream->handle_magic_event_cb (event); 537 event_stream->handle_magic_event_cb (event);
634 } 538 }
635 539
636 void 540 void
637 event_stream_format_magic_event (Lisp_Event *event, Lisp_Object pstream) 541 event_stream_format_magic_event (Lisp_Event *event, Lisp_Object pstream)
638 { 542 {
639 check_event_stream_ok (EVENT_STREAM_NOTHING); 543 check_event_stream_ok ();
640 event_stream->format_magic_event_cb (event, pstream); 544 event_stream->format_magic_event_cb (event, pstream);
641 } 545 }
642 546
643 int 547 int
644 event_stream_compare_magic_event (Lisp_Event *e1, Lisp_Event *e2) 548 event_stream_compare_magic_event (Lisp_Event *e1, Lisp_Event *e2)
645 { 549 {
646 check_event_stream_ok (EVENT_STREAM_NOTHING); 550 check_event_stream_ok ();
647 return event_stream->compare_magic_event_cb (e1, e2); 551 return event_stream->compare_magic_event_cb (e1, e2);
648 } 552 }
649 553
650 Hashcode 554 Hashcode
651 event_stream_hash_magic_event (Lisp_Event *e) 555 event_stream_hash_magic_event (Lisp_Event *e)
652 { 556 {
653 check_event_stream_ok (EVENT_STREAM_NOTHING); 557 check_event_stream_ok ();
654 return event_stream->hash_magic_event_cb (e); 558 return event_stream->hash_magic_event_cb (e);
655 } 559 }
656 560
657 static int 561 static int
658 event_stream_add_timeout (EMACS_TIME timeout) 562 event_stream_add_timeout (EMACS_TIME timeout)
659 { 563 {
660 check_event_stream_ok (EVENT_STREAM_TIMEOUT); 564 check_event_stream_ok ();
661 return event_stream->add_timeout_cb (timeout); 565 return event_stream->add_timeout_cb (timeout);
662 } 566 }
663 567
664 static void 568 static void
665 event_stream_remove_timeout (int id) 569 event_stream_remove_timeout (int id)
666 { 570 {
667 check_event_stream_ok (EVENT_STREAM_TIMEOUT); 571 check_event_stream_ok ();
668 event_stream->remove_timeout_cb (id); 572 event_stream->remove_timeout_cb (id);
669 } 573 }
670 574
671 void 575 void
672 event_stream_select_console (struct console *con) 576 event_stream_select_console (struct console *con)
673 { 577 {
674 check_event_stream_ok (EVENT_STREAM_CONSOLE); 578 check_event_stream_ok ();
675 if (!con->input_enabled) 579 if (!con->input_enabled)
676 { 580 {
677 event_stream->select_console_cb (con); 581 event_stream->select_console_cb (con);
678 con->input_enabled = 1; 582 con->input_enabled = 1;
679 } 583 }
680 } 584 }
681 585
682 void 586 void
683 event_stream_unselect_console (struct console *con) 587 event_stream_unselect_console (struct console *con)
684 { 588 {
685 check_event_stream_ok (EVENT_STREAM_CONSOLE); 589 check_event_stream_ok ();
686 if (con->input_enabled) 590 if (con->input_enabled)
687 { 591 {
688 event_stream->unselect_console_cb (con); 592 event_stream->unselect_console_cb (con);
689 con->input_enabled = 0; 593 con->input_enabled = 0;
690 } 594 }
693 void 597 void
694 event_stream_select_process (Lisp_Process *proc, int doin, int doerr) 598 event_stream_select_process (Lisp_Process *proc, int doin, int doerr)
695 { 599 {
696 int cur_in, cur_err; 600 int cur_in, cur_err;
697 601
698 check_event_stream_ok (EVENT_STREAM_PROCESS); 602 check_event_stream_ok ();
699 603
700 cur_in = get_process_selected_p (proc, 0); 604 cur_in = get_process_selected_p (proc, 0);
701 if (cur_in) 605 if (cur_in)
702 doin = 0; 606 doin = 0;
703 607
723 void 627 void
724 event_stream_unselect_process (Lisp_Process *proc, int doin, int doerr) 628 event_stream_unselect_process (Lisp_Process *proc, int doin, int doerr)
725 { 629 {
726 int cur_in, cur_err; 630 int cur_in, cur_err;
727 631
728 check_event_stream_ok (EVENT_STREAM_PROCESS); 632 check_event_stream_ok ();
729 633
730 cur_in = get_process_selected_p (proc, 0); 634 cur_in = get_process_selected_p (proc, 0);
731 if (!cur_in) 635 if (!cur_in)
732 doin = 0; 636 doin = 0;
733 637
757 Lisp_Object *errstream, 661 Lisp_Object *errstream,
758 USID *in_usid, 662 USID *in_usid,
759 USID *err_usid, 663 USID *err_usid,
760 int flags) 664 int flags)
761 { 665 {
762 check_event_stream_ok (EVENT_STREAM_PROCESS); 666 check_event_stream_ok ();
763 event_stream->create_io_streams_cb 667 event_stream->create_io_streams_cb
764 (inhandle, outhandle, errhandle, instream, outstream, errstream, 668 (inhandle, outhandle, errhandle, instream, outstream, errstream,
765 in_usid, err_usid, flags); 669 in_usid, err_usid, flags);
766 } 670 }
767 671
770 Lisp_Object outstream, 674 Lisp_Object outstream,
771 Lisp_Object errstream, 675 Lisp_Object errstream,
772 USID *in_usid, 676 USID *in_usid,
773 USID *err_usid) 677 USID *err_usid)
774 { 678 {
775 check_event_stream_ok (EVENT_STREAM_PROCESS); 679 check_event_stream_ok ();
776 event_stream->delete_io_streams_cb (instream, outstream, errstream, 680 event_stream->delete_io_streams_cb (instream, outstream, errstream,
777 in_usid, err_usid); 681 in_usid, err_usid);
778 }
779
780 static void
781 event_stream_drain_queue (void)
782 {
783 if (event_stream && event_stream->drain_queue_cb)
784 event_stream->drain_queue_cb ();
785 }
786
787 struct remove_quit_p_data
788 {
789 int critical;
790 };
791
792 static int
793 remove_quit_p_event (Lisp_Object ev, void *the_data)
794 {
795 struct remove_quit_p_data *data = (struct remove_quit_p_data *) the_data;
796 struct console *con = event_console_or_selected (ev);
797
798 if (XEVENT_TYPE (ev) == key_press_event)
799 {
800 if (event_matches_key_specifier_p (ev, CONSOLE_QUIT_EVENT (con)))
801 return 1;
802 if (event_matches_key_specifier_p (ev,
803 CONSOLE_CRITICAL_QUIT_EVENT (con)))
804 {
805 data->critical = 1;
806 return 1;
807 }
808 }
809
810 return 0;
811 }
812
813 static int
814 event_stream_quit_check_disallowed_p (void)
815 {
816 if (event_stream && event_stream->quit_check_disallowed_p_cb)
817 return event_stream->quit_check_disallowed_p_cb ();
818 else
819 return 0;
820 }
821
822 void
823 event_stream_quit_p (void)
824 {
825 struct remove_quit_p_data data;
826
827 if (event_stream_quit_check_disallowed_p ())
828 return;
829
830 /* Drain queue so we can check for pending C-g events. */
831 event_stream_drain_queue ();
832 data.critical = 0;
833
834 if (map_event_chain_remove (remove_quit_p_event,
835 &dispatch_event_queue,
836 &dispatch_event_queue_tail,
837 &data, MECR_DEALLOCATE_EVENT))
838 Vquit_flag = data.critical ? Qcritical : Qt;
839 } 682 }
840 683
841 static int 684 static int
842 event_stream_current_event_timestamp (struct console *c) 685 event_stream_current_event_timestamp (struct console *c)
843 { 686 {
961 804
962 /**********************************************************************/ 805 /**********************************************************************/
963 /* random junk */ 806 /* random junk */
964 /**********************************************************************/ 807 /**********************************************************************/
965 808
966 static void
967 maybe_kbd_translate (Lisp_Object event)
968 {
969 Ichar c;
970 int did_translate = 0;
971
972 if (XEVENT_TYPE (event) != key_press_event)
973 return;
974 if (!HASH_TABLEP (Vkeyboard_translate_table))
975 return;
976 if (EQ (Fhash_table_count (Vkeyboard_translate_table), Qzero))
977 return;
978
979 c = event_to_character (event, 0, 0, 0);
980 if (c != -1)
981 {
982 Lisp_Object traduit = Fgethash (make_char (c), Vkeyboard_translate_table,
983 Qnil);
984 if (!NILP (traduit) && SYMBOLP (traduit))
985 {
986 XSET_EVENT_KEY_KEYSYM (event, traduit);
987 XSET_EVENT_KEY_MODIFIERS (event, 0);
988 did_translate = 1;
989 }
990 else if (CHARP (traduit))
991 {
992 /* This used to call Fcharacter_to_event() directly into EVENT,
993 but that can eradicate timestamps and other such stuff.
994 This way is safer. */
995 Lisp_Object ev2 = Fmake_event (Qnil, Qnil);
996
997 character_to_event (XCHAR (traduit), XEVENT (ev2),
998 XCONSOLE (XEVENT_CHANNEL (event)), 0, 1);
999 XSET_EVENT_KEY_KEYSYM (event, XEVENT_KEY_KEYSYM (ev2));
1000 XSET_EVENT_KEY_MODIFIERS (event, XEVENT_KEY_MODIFIERS (ev2));
1001 Fdeallocate_event (ev2);
1002 did_translate = 1;
1003 }
1004 }
1005
1006 if (!did_translate)
1007 {
1008 Lisp_Object traduit = Fgethash (XEVENT_KEY_KEYSYM (event),
1009 Vkeyboard_translate_table, Qnil);
1010 if (!NILP (traduit) && SYMBOLP (traduit))
1011 {
1012 XSET_EVENT_KEY_KEYSYM (event, traduit);
1013 did_translate = 1;
1014 }
1015 else if (CHARP (traduit))
1016 {
1017 /* This used to call Fcharacter_to_event() directly into EVENT,
1018 but that can eradicate timestamps and other such stuff.
1019 This way is safer. */
1020 Lisp_Object ev2 = Fmake_event (Qnil, Qnil);
1021
1022 character_to_event (XCHAR (traduit), XEVENT (ev2),
1023 XCONSOLE (XEVENT_CHANNEL (event)), 0, 1);
1024 XSET_EVENT_KEY_KEYSYM (event, XEVENT_KEY_KEYSYM (ev2));
1025 XSET_EVENT_KEY_MODIFIERS (event,
1026 XEVENT_KEY_MODIFIERS (event) |
1027 XEVENT_KEY_MODIFIERS (ev2));
1028
1029 Fdeallocate_event (ev2);
1030 did_translate = 1;
1031 }
1032 }
1033
1034 #ifdef DEBUG_XEMACS
1035 if (did_translate)
1036 DEBUG_PRINT_EMACS_EVENT ("->keyboard-translate-table", event);
1037 #endif
1038 }
1039
1040 /* NB: The following auto-save stuff is in keyboard.c in FSFmacs, and 809 /* NB: The following auto-save stuff is in keyboard.c in FSFmacs, and
1041 keystrokes_since_auto_save is equivalent to the difference between 810 keystrokes_since_auto_save is equivalent to the difference between
1042 num_nonmacro_input_chars and last_auto_save. */ 811 num_nonmacro_input_chars and last_auto_save. */
1043 812
1044 /* When an auto-save happens, record the number of keystrokes, and 813 /* When an auto-save happens, record the number of keystrokes, and
1063 { 832 {
1064 /* This function can call lisp */ 833 /* This function can call lisp */
1065 keystrokes_since_auto_save++; 834 keystrokes_since_auto_save++;
1066 if (auto_save_interval > 0 && 835 if (auto_save_interval > 0 &&
1067 keystrokes_since_auto_save > max (auto_save_interval, 20) && 836 keystrokes_since_auto_save > max (auto_save_interval, 20) &&
1068 !detect_input_pending ()) 837 !detect_input_pending (1))
1069 { 838 {
1070 Fdo_auto_save (Qnil, Qnil); 839 Fdo_auto_save (Qnil, Qnil);
1071 record_auto_save (); 840 record_auto_save ();
1072 } 841 }
1073 } 842 }
1130 command_builder->echo_buf_index = buf_index; 899 command_builder->echo_buf_index = buf_index;
1131 if (buf_index > 0) 900 if (buf_index > 0)
1132 memcpy (command_builder->echo_buf, 901 memcpy (command_builder->echo_buf,
1133 XSTRING_DATA (echo), buf_index + 1); /* terminating 0 */ 902 XSTRING_DATA (echo), buf_index + 1); /* terminating 0 */
1134 UNGCPRO; 903 UNGCPRO;
1135 }
1136
1137
1138 /**********************************************************************/
1139 /* input pending */
1140 /**********************************************************************/
1141
1142 int
1143 detect_input_pending (void)
1144 {
1145 /* Always call the event_pending_p hook even if there's an unread
1146 character, because that might do some needed ^G detection (on
1147 systems without SIGIO, for example).
1148 */
1149 if (event_stream_event_pending_p (1))
1150 return 1;
1151 if (!NILP (Vunread_command_events) || !NILP (Vunread_command_event))
1152 return 1;
1153 if (!NILP (command_event_queue))
1154 {
1155 Lisp_Object event;
1156
1157 EVENT_CHAIN_LOOP (event, command_event_queue)
1158 {
1159 if (XEVENT_TYPE (event) != eval_event
1160 && XEVENT_TYPE (event) != magic_eval_event)
1161 return 1;
1162 }
1163 }
1164 return 0;
1165 }
1166
1167 DEFUN ("input-pending-p", Finput_pending_p, 0, 0, 0, /*
1168 Return t if command input is currently available with no waiting.
1169 Actually, the value is nil only if we can be sure that no input is available.
1170 */
1171 ())
1172 {
1173 return detect_input_pending () ? Qt : Qnil;
1174 } 904 }
1175 905
1176 906
1177 /**********************************************************************/ 907 /**********************************************************************/
1178 /* timeouts */ 908 /* timeouts */
2119 } 1849 }
2120 } 1850 }
2121 1851
2122 1852
2123 /**********************************************************************/ 1853 /**********************************************************************/
1854 /* input pending/quit checking */
1855 /**********************************************************************/
1856
1857 /* If HOW_MANY is 0, return true if there are any user or non-user events
1858 pending. If HOW_MANY is > 0, return true if there are that many *user*
1859 events pending, irrespective of non-user events. */
1860
1861 static int
1862 event_stream_event_pending_p (int how_many)
1863 {
1864 /* #### Hmmm ... There may be some duplication in "drain queue" and
1865 "event pending". Couldn't we just drain the queue and see what's in
1866 it, and not maybe need a separate event method for this? Would this
1867 work when HOW_MANY is 0? Maybe this would be slow? */
1868 return event_stream && event_stream->event_pending_p (how_many);
1869 }
1870
1871 static void
1872 event_stream_force_event_pending (struct frame *f)
1873 {
1874 if (event_stream->force_event_pending_cb)
1875 event_stream->force_event_pending_cb (f);
1876 }
1877
1878 void
1879 event_stream_drain_queue (void)
1880 {
1881 if (event_stream && event_stream->drain_queue_cb)
1882 event_stream->drain_queue_cb ();
1883 }
1884
1885 /* Return non-zero if at least HOW_MANY user events are pending. */
1886 int
1887 detect_input_pending (int how_many)
1888 {
1889 Lisp_Object event;
1890
1891 if (!NILP (Vunread_command_event))
1892 how_many--;
1893
1894 how_many -= XINT (Fsafe_length (Vunread_command_events));
1895
1896 if (how_many <= 0)
1897 return 1;
1898
1899 EVENT_CHAIN_LOOP (event, command_event_queue)
1900 {
1901 if (XEVENT_TYPE (event) != eval_event
1902 && XEVENT_TYPE (event) != magic_eval_event)
1903 {
1904 how_many--;
1905 if (how_many <= 0)
1906 return 1;
1907 }
1908 }
1909
1910 return event_stream_event_pending_p (how_many);
1911 }
1912
1913 DEFUN ("input-pending-p", Finput_pending_p, 0, 0, 0, /*
1914 Return t if command input is currently available with no waiting.
1915 Actually, the value is nil only if we can be sure that no input is available.
1916 */
1917 ())
1918 {
1919 return detect_input_pending (1) ? Qt : Qnil;
1920 }
1921
1922 static int
1923 maybe_read_quit_event (Lisp_Event *event)
1924 {
1925 /* A C-g that came from `sigint_happened' will always come from the
1926 controlling terminal. If that doesn't exist, however, then the
1927 user manually sent us a SIGINT, and we pretend the C-g came from
1928 the selected console. */
1929 struct console *con;
1930
1931 if (CONSOLEP (Vcontrolling_terminal) &&
1932 CONSOLE_LIVE_P (XCONSOLE (Vcontrolling_terminal)))
1933 con = XCONSOLE (Vcontrolling_terminal);
1934 else
1935 con = XCONSOLE (Fselected_console ());
1936
1937 if (sigint_happened)
1938 {
1939 sigint_happened = 0;
1940 Vquit_flag = Qnil;
1941 Fcopy_event (CONSOLE_QUIT_EVENT (con), wrap_event (event));
1942 return 1;
1943 }
1944 return 0;
1945 }
1946
1947 struct remove_quit_p_data
1948 {
1949 int critical;
1950 };
1951
1952 static int
1953 remove_quit_p_event (Lisp_Object ev, void *the_data)
1954 {
1955 struct remove_quit_p_data *data = (struct remove_quit_p_data *) the_data;
1956 struct console *con = event_console_or_selected (ev);
1957
1958 if (XEVENT_TYPE (ev) == key_press_event)
1959 {
1960 if (event_matches_key_specifier_p (ev, CONSOLE_QUIT_EVENT (con)))
1961 return 1;
1962 if (event_matches_key_specifier_p (ev,
1963 CONSOLE_CRITICAL_QUIT_EVENT (con)))
1964 {
1965 data->critical = 1;
1966 return 1;
1967 }
1968 }
1969
1970 return 0;
1971 }
1972
1973 void
1974 event_stream_quit_p (void)
1975 {
1976 struct remove_quit_p_data data;
1977
1978 /* Quit checking cannot happen in modal loop. Because it attempts to
1979 retrieve and dispatch events, it will cause lots of problems if we try
1980 to do this when already in the process of doing this -- deadlocking
1981 under Windows, crashes in lwlib etc. under X due to non-reentrant
1982 code. This is automatically caught, however, in
1983 event_stream_drain_queue() (checks for in_modal_loop in the
1984 event-specific code). */
1985
1986 /* Drain queue so we can check for pending C-g events. */
1987 event_stream_drain_queue ();
1988 data.critical = 0;
1989
1990 if (map_event_chain_remove (remove_quit_p_event,
1991 &dispatch_event_queue,
1992 &dispatch_event_queue_tail,
1993 &data, MECR_DEALLOCATE_EVENT))
1994 Vquit_flag = data.critical ? Qcritical : Qt;
1995 }
1996
1997 Lisp_Object
1998 event_stream_protect_modal_loop (const char *error_string,
1999 Lisp_Object (*bfun) (void *barg),
2000 void *barg, int flags)
2001 {
2002 Lisp_Object tmp;
2003
2004 ++in_modal_loop;
2005 tmp = call_trapping_problems (Qevent, error_string, flags, 0, bfun, barg);
2006 --in_modal_loop;
2007
2008 return tmp;
2009 }
2010
2011
2012 /**********************************************************************/
2124 /* retrieving the next event */ 2013 /* retrieving the next event */
2125 /**********************************************************************/ 2014 /**********************************************************************/
2126 2015
2127 static int in_single_console; 2016 static int in_single_console;
2128 2017
2143 in_single_console_state (void) 2032 in_single_console_state (void)
2144 { 2033 {
2145 return in_single_console; 2034 return in_single_console;
2146 } 2035 }
2147 2036
2148 /* the number of keyboard characters read. callint.c wants this. */ 2037 static void
2149 Charcount num_input_chars; 2038 event_stream_next_event (Lisp_Event *event)
2039 {
2040 Lisp_Object event_obj;
2041
2042 check_event_stream_ok ();
2043
2044 event_obj = wrap_event (event);
2045 zero_event (event);
2046 /* SIGINT occurs when C-g was pressed on a TTY. (SIGINT might have
2047 been sent manually by the user, but we don't care; we treat it
2048 the same.)
2049
2050 The SIGINT signal handler sets Vquit_flag as well as sigint_happened
2051 and write a byte on our "fake pipe", which unblocks us when we are
2052 waiting for an event. */
2053
2054 /* If SIGINT was received after we disabled quit checking (because
2055 we want to read C-g's as characters), but before we got a chance
2056 to start reading, notice it now and treat it as a character to be
2057 read. If above callers wanted this to be QUIT, they can
2058 determine this by comparing the event against quit-char. */
2059
2060 if (maybe_read_quit_event (event))
2061 {
2062 DEBUG_PRINT_EMACS_EVENT ("SIGINT", event_obj);
2063 return;
2064 }
2065
2066 /* If a longjmp() happens in the callback, we're screwed.
2067 Let's hope it doesn't. I think the code here is fairly
2068 clean and doesn't do this. */
2069 emacs_is_blocking = 1;
2070 event_stream->next_event_cb (event);
2071 emacs_is_blocking = 0;
2072
2073 /* Now check to see if C-g was pressed while we were blocking.
2074 We treat it as an event, just like above. */
2075 if (maybe_read_quit_event (event))
2076 {
2077 DEBUG_PRINT_EMACS_EVENT ("SIGINT", event_obj);
2078 return;
2079 }
2080
2081 #ifdef DEBUG_XEMACS
2082 /* timeout events have more info set later, so
2083 print the event out in next_event_internal(). */
2084 if (event->event_type != timeout_event)
2085 DEBUG_PRINT_EMACS_EVENT ("real", event_obj);
2086 #endif
2087 maybe_kbd_translate (event_obj);
2088 }
2150 2089
2151 /* Read an event from the window system (or tty). If ALLOW_QUEUED is 2090 /* Read an event from the window system (or tty). If ALLOW_QUEUED is
2152 non-zero, read from the command-event queue first. 2091 non-zero, read from the command-event queue first.
2153 2092
2154 If C-g was pressed, this function will attempt to QUIT. If you want 2093 If C-g was pressed, this function will attempt to QUIT. If you want
2223 2162
2224 void 2163 void
2225 run_pre_idle_hook (void) 2164 run_pre_idle_hook (void)
2226 { 2165 {
2227 if (!NILP (Vpre_idle_hook) 2166 if (!NILP (Vpre_idle_hook)
2228 && !detect_input_pending ()) 2167 && !detect_input_pending (1))
2229 safe_run_hook_trapping_problems 2168 safe_run_hook_trapping_problems
2230 ("Error in `pre-idle-hook' (setting hook to nil)", 2169 ("Error in `pre-idle-hook' (setting hook to nil)",
2231 Qpre_idle_hook, INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); 2170 Qpre_idle_hook,
2232 } 2171 /* Quit is inhibited as a result of being within next-event so
2233 2172 we need to fix that. */
2234 static void push_this_command_keys (Lisp_Object event); 2173 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION | UNINHIBIT_QUIT);
2235 static void push_recent_keys (Lisp_Object event); 2174 }
2236 static void dribble_out_event (Lisp_Object event);
2237 static void execute_internal_event (Lisp_Object event);
2238 static int is_scrollbar_event (Lisp_Object event);
2239 2175
2240 DEFUN ("next-event", Fnext_event, 0, 2, 0, /* 2176 DEFUN ("next-event", Fnext_event, 0, 2, 0, /*
2241 Return the next available event. 2177 Return the next available event.
2242 Pass this object to `dispatch-event' to handle it. 2178 Pass this object to `dispatch-event' to handle it.
2243 In most cases, you will want to use `next-command-event', which returns 2179 In most cases, you will want to use `next-command-event', which returns
2293 struct gcpro gcpro1; 2229 struct gcpro gcpro1;
2294 int depth; 2230 int depth;
2295 2231
2296 GCPRO1 (event); 2232 GCPRO1 (event);
2297 2233
2234 /* This is not strictly necessary. Trying to retrieve an event inside of
2235 a modal loop can cause major problems (see event_stream_quit_p()), but
2236 the event-specific code knows about this and will make sure we don't
2237 do anything dangerous. However, if we've gotten here, it's highly
2238 likely that some code is trying to fetch user events (e.g. in custom
2239 dialog-box code), and will almost certainly deadlock, so it's probably
2240 best to error out. #### This could cause problems because there are
2241 (potentially, at least) legitimate reasons for calling next-event
2242 inside of a modal loop, in particular if the code is trying to search
2243 for a timeout event, which will still get retrieved in such a case.
2244 However, the code to error in such a case has already been present for
2245 a long time without obvious problems so leaving it in isn't so
2246 bad. --ben */
2247 if (in_modal_loop)
2248 invalid_operation ("Attempt to call next-event inside modal loop",
2249 Qunbound);
2250
2298 depth = begin_dont_check_for_quit (); 2251 depth = begin_dont_check_for_quit ();
2299
2300 #ifdef LWLIB_MENUBARS_LUCID
2301 /*
2302 * #### Fix the menu code so this isn't necessary.
2303 *
2304 * We cannot allow the lwmenu code to be reentered, because the
2305 * code is not written to be reentrant and will crash. Therefore
2306 * paths from the menu callbacks back into the menu code have to
2307 * be blocked. Fnext_event is the normal path into the menu code,
2308 * so we signal an error here.
2309 */
2310 if (in_menu_callback)
2311 invalid_operation ("Attempt to call next-event inside menu callback",
2312 Qunbound);
2313 #endif /* LWLIB_MENUBARS_LUCID */
2314 2252
2315 if (NILP (event)) 2253 if (NILP (event))
2316 event = Fmake_event (Qnil, Qnil); 2254 event = Fmake_event (Qnil, Qnil);
2317 else 2255 else
2318 CHECK_LIVE_EVENT (event); 2256 CHECK_LIVE_EVENT (event);
2640 reset_command_builder_event_chain (command_builder); 2578 reset_command_builder_event_chain (command_builder);
2641 if (EVENTP (event)) 2579 if (EVENTP (event))
2642 deallocate_event_chain (event); 2580 deallocate_event_chain (event);
2643 } 2581 }
2644 2582
2583 static int
2584 command_event_p_cb (Lisp_Object ev, void *the_data)
2585 {
2586 return command_event_p (ev);
2587 }
2588
2645 DEFUN ("discard-input", Fdiscard_input, 0, 0, 0, /* 2589 DEFUN ("discard-input", Fdiscard_input, 0, 0, 0, /*
2646 Discard any pending "user" events. 2590 Discard any pending "user" events.
2647 Also cancel any kbd macro being defined. 2591 Also cancel any kbd macro being defined.
2648 A user event is a key press, button press, button release, or 2592 A user event is a key press, button press, button release, or
2649 "misc-user" event (menu selection or scrollbar action). 2593 "misc-user" event (menu selection or scrollbar action).
2650 */ 2594 */
2651 ()) 2595 ())
2652 { 2596 {
2653 /* This throws away user-input on the queue, but doesn't process any 2597 Lisp_Object concons;
2654 events. Calling dispatch_event() here leads to a race condition. 2598
2655 */ 2599 CONSOLE_LOOP (concons)
2656 Lisp_Object event = Fmake_event (Qnil, Qnil); 2600 {
2657 Lisp_Object head = Qnil, tail = Qnil; 2601 struct console *con = XCONSOLE (XCAR (concons));
2658 struct gcpro gcpro1; 2602
2659 /* #### not correct here with Vselected_console? Should 2603 /* If a macro was being defined then we have to mark the modeline
2660 discard-input take a console argument, or maybe map over 2604 has changed to ensure that it gets updated correctly. */
2661 all consoles? */ 2605 if (!NILP (con->defining_kbd_macro))
2662 struct console *con = XCONSOLE (Vselected_console); 2606 MARK_MODELINE_CHANGED;
2663 2607 con->defining_kbd_macro = Qnil;
2664 /* next_event_internal() can cause arbitrary Lisp code to be evalled */ 2608 reset_current_events (XCOMMAND_BUILDER (con->command_builder));
2665 GCPRO1 (event); 2609 }
2666 /* If a macro was being defined then we have to mark the modeline 2610
2667 has changed to ensure that it gets updated correctly. */ 2611 /* This function used to be a lot more complicated. Now, we just
2668 if (!NILP (con->defining_kbd_macro)) 2612 drain the pending queue and discard all user events from the
2669 MARK_MODELINE_CHANGED; 2613 command and dispatch queues. */
2670 con->defining_kbd_macro = Qnil; 2614 event_stream_drain_queue ();
2671 reset_current_events (XCOMMAND_BUILDER (con->command_builder)); 2615
2672 2616 map_event_chain_remove (command_event_p_cb,
2673 while (!NILP (command_event_queue) 2617 &dispatch_event_queue, &dispatch_event_queue_tail,
2674 || event_stream_event_pending_p (1)) 2618 0, MECR_DEALLOCATE_EVENT);
2675 { 2619 map_event_chain_remove (command_event_p_cb,
2676 /* We want to ignore C-g's along with all other keypresses. */ 2620 &command_event_queue, &command_event_queue_tail,
2677 int depth = begin_dont_check_for_quit (); 2621 0, MECR_DEALLOCATE_EVENT);
2678 /* This will take stuff off the command_event_queue, or read it
2679 from the event_stream, but it will not block.
2680 */
2681 next_event_internal (event, 1);
2682 /* The following comment used to be here:
2683
2684 [[Treat C-g as a user event (ignore it). It is vitally
2685 important that we reset Vquit_flag here. Otherwise, if we're
2686 reading from a TTY console, maybe_read_quit_event() will
2687 notice that C-g has been set and send us another C-g. That
2688 will cause us to get right back here, and read another C-g,
2689 ad infinitum ...]]
2690
2691 but I don't think this is correct; maybe_read_quit_event()
2692 checks and resets sigint_happened. It shouldn't matter if we
2693 reset here or outside of the while loop. --ben */
2694 Vquit_flag = Qnil; /* see begin_dont_check_for_quit() */
2695
2696 unbind_to (depth);
2697
2698 /* If the event is a user event, ignore it. */
2699 if (!command_event_p (event))
2700 {
2701 /* Otherwise, chain the event onto our list of events not to ignore,
2702 and keep reading until the queue is empty. This does not mean
2703 that if a subprocess is generating an infinite amount of output,
2704 we will never terminate (*provided* that the behavior of
2705 next_event_cb() is correct -- see the comment in events.h),
2706 because this loop ends as soon as there are no more user events
2707 on the command_event_queue or event_stream.
2708 */
2709 enqueue_event (Fcopy_event (event, Qnil), &head, &tail);
2710 }
2711 }
2712
2713 if (!NILP (command_event_queue) || !NILP (command_event_queue_tail))
2714 abort ();
2715
2716 /* Now tack our chain of events back on to the front of the queue.
2717 Actually, since the queue is now drained, we can just replace it.
2718 The effect of this will be that we have deleted all user events
2719 from the input stream without changing the relative ordering of
2720 any other events. (Some events may have been taken from the
2721 event_stream and added to the command_event_queue, however.)
2722
2723 At this time, the command_event_queue will contain only eval_events.
2724 */
2725
2726 command_event_queue = head;
2727 command_event_queue_tail = tail;
2728
2729 Fdeallocate_event (event);
2730 UNGCPRO;
2731 2622
2732 return Qnil; 2623 return Qnil;
2733 } 2624 }
2734 2625
2735 2626
2737 /* pausing until an action occurs */ 2628 /* pausing until an action occurs */
2738 /**********************************************************************/ 2629 /**********************************************************************/
2739 2630
2740 /* This is used in accept-process-output, sleep-for and sit-for. 2631 /* This is used in accept-process-output, sleep-for and sit-for.
2741 Before running any process_events in these routines, we set 2632 Before running any process_events in these routines, we set
2742 recursive_sit_for to Qt, and use this unwind protect to reset it to 2633 recursive_sit_for to 1, and use this unwind protect to reset it to
2743 Qnil upon exit. When recursive_sit_for is Qt, calling sit-for will 2634 Qnil upon exit. When recursive_sit_for is 1, calling sit-for will
2744 cause it to return immediately. 2635 cause it to return immediately.
2745 2636
2746 All of these routines install timeouts, so we clear the installed 2637 All of these routines install timeouts, so we clear the installed
2747 timeout as well. 2638 timeout as well.
2748 2639
2755 sit_for_unwind (Lisp_Object timeout_id) 2646 sit_for_unwind (Lisp_Object timeout_id)
2756 { 2647 {
2757 if (!NILP(timeout_id)) 2648 if (!NILP(timeout_id))
2758 Fdisable_timeout (timeout_id); 2649 Fdisable_timeout (timeout_id);
2759 2650
2760 recursive_sit_for = Qnil; 2651 recursive_sit_for = 0;
2761 return Qnil; 2652 return Qnil;
2762 } 2653 }
2763 2654
2764 /* #### Is (accept-process-output nil 3) supposed to be like (sleep-for 3)? 2655 /* #### Is (accept-process-output nil 3) supposed to be like (sleep-for 3)?
2765 */ 2656 */
2820 event = Fmake_event (Qnil, Qnil); 2711 event = Fmake_event (Qnil, Qnil);
2821 2712
2822 count = specpdl_depth (); 2713 count = specpdl_depth ();
2823 record_unwind_protect (sit_for_unwind, 2714 record_unwind_protect (sit_for_unwind,
2824 timeout_enabled ? make_int (timeout_id) : Qnil); 2715 timeout_enabled ? make_int (timeout_id) : Qnil);
2825 recursive_sit_for = Qt; 2716 recursive_sit_for = 1;
2826 2717
2827 while (!done && 2718 while (!done &&
2828 ((NILP (process) && timeout_enabled) || 2719 ((NILP (process) && timeout_enabled) ||
2829 (NILP (process) && event_stream_event_pending_p (0)) || 2720 (NILP (process) && event_stream_event_pending_p (0)) ||
2830 (!NILP (process)))) 2721 (!NILP (process))))
2917 id = event_stream_generate_wakeup (msecs, 0, Qnil, Qnil, 0); 2808 id = event_stream_generate_wakeup (msecs, 0, Qnil, Qnil, 0);
2918 event = Fmake_event (Qnil, Qnil); 2809 event = Fmake_event (Qnil, Qnil);
2919 2810
2920 count = specpdl_depth (); 2811 count = specpdl_depth ();
2921 record_unwind_protect (sit_for_unwind, make_int (id)); 2812 record_unwind_protect (sit_for_unwind, make_int (id));
2922 recursive_sit_for = Qt; 2813 recursive_sit_for = 1;
2923 2814
2924 while (1) 2815 while (1)
2925 { 2816 {
2926 /* If our timeout has arrived, we move along. */ 2817 /* If our timeout has arrived, we move along. */
2927 if (!event_stream_wakeup_pending_p (id, 0)) 2818 if (!event_stream_wakeup_pending_p (id, 0))
2998 don't wait. */ 2889 don't wait. */
2999 if (noninteractive || !NILP (Vexecuting_macro)) 2890 if (noninteractive || !NILP (Vexecuting_macro))
3000 return Qnil; 2891 return Qnil;
3001 2892
3002 /* Recursive call from a filter function or timeout handler. */ 2893 /* Recursive call from a filter function or timeout handler. */
3003 if (!NILP (recursive_sit_for)) 2894 if (recursive_sit_for)
3004 { 2895 {
3005 if (!event_stream_event_pending_p (1) && NILP (nodisplay)) 2896 if (!event_stream_event_pending_p (1) && NILP (nodisplay))
3006 redisplay (); 2897 redisplay ();
3007 return Qnil; 2898 return Qnil;
3008 } 2899 }
3023 2914
3024 id = event_stream_generate_wakeup (msecs, 0, Qnil, Qnil, 0); 2915 id = event_stream_generate_wakeup (msecs, 0, Qnil, Qnil, 0);
3025 2916
3026 count = specpdl_depth (); 2917 count = specpdl_depth ();
3027 record_unwind_protect (sit_for_unwind, make_int (id)); 2918 record_unwind_protect (sit_for_unwind, make_int (id));
3028 recursive_sit_for = Qt; 2919 recursive_sit_for = 1;
3029 2920
3030 while (1) 2921 while (1)
3031 { 2922 {
3032 /* If there is no user input pending, then redisplay. 2923 /* If there is no user input pending, then redisplay.
3033 */ 2924 */
3307 return Qnil; 3198 return Qnil;
3308 3199
3309 return event_binding (event0, 1); 3200 return event_binding (event0, 1);
3310 } 3201 }
3311 3202
3203 static void
3204 maybe_kbd_translate (Lisp_Object event)
3205 {
3206 Ichar c;
3207 int did_translate = 0;
3208
3209 if (XEVENT_TYPE (event) != key_press_event)
3210 return;
3211 if (!HASH_TABLEP (Vkeyboard_translate_table))
3212 return;
3213 if (EQ (Fhash_table_count (Vkeyboard_translate_table), Qzero))
3214 return;
3215
3216 c = event_to_character (event, 0, 0, 0);
3217 if (c != -1)
3218 {
3219 Lisp_Object traduit = Fgethash (make_char (c), Vkeyboard_translate_table,
3220 Qnil);
3221 if (!NILP (traduit) && SYMBOLP (traduit))
3222 {
3223 XSET_EVENT_KEY_KEYSYM (event, traduit);
3224 XSET_EVENT_KEY_MODIFIERS (event, 0);
3225 did_translate = 1;
3226 }
3227 else if (CHARP (traduit))
3228 {
3229 /* This used to call Fcharacter_to_event() directly into EVENT,
3230 but that can eradicate timestamps and other such stuff.
3231 This way is safer. */
3232 Lisp_Object ev2 = Fmake_event (Qnil, Qnil);
3233
3234 character_to_event (XCHAR (traduit), XEVENT (ev2),
3235 XCONSOLE (XEVENT_CHANNEL (event)), 0, 1);
3236 XSET_EVENT_KEY_KEYSYM (event, XEVENT_KEY_KEYSYM (ev2));
3237 XSET_EVENT_KEY_MODIFIERS (event, XEVENT_KEY_MODIFIERS (ev2));
3238 Fdeallocate_event (ev2);
3239 did_translate = 1;
3240 }
3241 }
3242
3243 if (!did_translate)
3244 {
3245 Lisp_Object traduit = Fgethash (XEVENT_KEY_KEYSYM (event),
3246 Vkeyboard_translate_table, Qnil);
3247 if (!NILP (traduit) && SYMBOLP (traduit))
3248 {
3249 XSET_EVENT_KEY_KEYSYM (event, traduit);
3250 did_translate = 1;
3251 }
3252 else if (CHARP (traduit))
3253 {
3254 /* This used to call Fcharacter_to_event() directly into EVENT,
3255 but that can eradicate timestamps and other such stuff.
3256 This way is safer. */
3257 Lisp_Object ev2 = Fmake_event (Qnil, Qnil);
3258
3259 character_to_event (XCHAR (traduit), XEVENT (ev2),
3260 XCONSOLE (XEVENT_CHANNEL (event)), 0, 1);
3261 XSET_EVENT_KEY_KEYSYM (event, XEVENT_KEY_KEYSYM (ev2));
3262 XSET_EVENT_KEY_MODIFIERS (event,
3263 XEVENT_KEY_MODIFIERS (event) |
3264 XEVENT_KEY_MODIFIERS (ev2));
3265
3266 Fdeallocate_event (ev2);
3267 did_translate = 1;
3268 }
3269 }
3270
3271 #ifdef DEBUG_XEMACS
3272 if (did_translate)
3273 DEBUG_PRINT_EMACS_EVENT ("->keyboard-translate-table", event);
3274 #endif
3275 }
3276
3312 /* See if we can do function-key-map or key-translation-map translation 3277 /* See if we can do function-key-map or key-translation-map translation
3313 on the current events in the command builder. If so, do this, and 3278 on the current events in the command builder. If so, do this, and
3314 return the resulting binding, if any. 3279 return the resulting binding, if any.
3315 3280
3316 DID_MUNGE must be initialized before calling this function. If munging 3281 DID_MUNGE must be initialized before calling this function. If munging
3422 events */ 3387 events */
3423 /* #### fuck me! who wrote this crap? think "abstraction", baby. */ 3388 /* #### fuck me! who wrote this crap? think "abstraction", baby. */
3424 /* #### this horribly-written crap can mess with global state, which 3389 /* #### this horribly-written crap can mess with global state, which
3425 this function should not do. i'm not fixing it now. someone 3390 this function should not do. i'm not fixing it now. someone
3426 needs to go and rewrite that shit correctly. --ben */ 3391 needs to go and rewrite that shit correctly. --ben */
3427 #if defined(HAVE_X_WINDOWS) && defined(LWLIB_MENUBARS_LUCID) 3392 #if defined (HAVE_X_WINDOWS) && defined (LWLIB_MENUBARS_LUCID)
3428 if (x_kludge_lw_menu_active ()) 3393 if (x_kludge_lw_menu_active ())
3429 { 3394 {
3430 return command_builder_operate_menu_accelerator (builder); 3395 return command_builder_operate_menu_accelerator (builder);
3431 } 3396 }
3432 else 3397 else
3435 if (EQ (Vmenu_accelerator_enabled, Qmenu_force)) 3400 if (EQ (Vmenu_accelerator_enabled, Qmenu_force))
3436 result = command_builder_find_menu_accelerator (builder); 3401 result = command_builder_find_menu_accelerator (builder);
3437 if (NILP (result)) 3402 if (NILP (result))
3438 #endif 3403 #endif
3439 result = command_builder_find_leaf_1 (builder); 3404 result = command_builder_find_leaf_1 (builder);
3440 #if defined(HAVE_X_WINDOWS) && defined(LWLIB_MENUBARS_LUCID) 3405 #if defined (HAVE_X_WINDOWS) && defined (LWLIB_MENUBARS_LUCID)
3441 if (NILP (result) 3406 if (NILP (result)
3442 && EQ (Vmenu_accelerator_enabled, Qmenu_fallback)) 3407 && EQ (Vmenu_accelerator_enabled, Qmenu_fallback))
3443 result = command_builder_find_menu_accelerator (builder); 3408 result = command_builder_find_menu_accelerator (builder);
3444 } 3409 }
3445 #endif 3410 #endif
4865 &lrecord_command_builder); 4830 &lrecord_command_builder);
4866 staticpro_nodump (&Vcommand_builder_free_list); 4831 staticpro_nodump (&Vcommand_builder_free_list);
4867 the_low_level_timeout_blocktype = 4832 the_low_level_timeout_blocktype =
4868 Blocktype_new (struct low_level_timeout_blocktype); 4833 Blocktype_new (struct low_level_timeout_blocktype);
4869 something_happened = 0; 4834 something_happened = 0;
4870 recursive_sit_for = Qnil; 4835 recursive_sit_for = 0;
4836 in_modal_loop = 0;
4871 } 4837 }
4872 4838
4873 void 4839 void
4874 vars_of_event_stream (void) 4840 vars_of_event_stream (void)
4875 { 4841 {