Mercurial > hg > xemacs-beta
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 { |