1 /* Events: printing them, converting them to and from characters.
2 Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
5 This file is part of SXEmacs
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 /* Synched up with: Not in FSF. */
23 /* This file has been Mule-ized. */
28 #include "ui/console.h"
29 #include "ui/TTY/console-tty.h" /* for stuff in
30 character_to_event. needs
32 #include "ui/device.h"
33 #include "ui/X11/console-x.h" /* for x_event_name prototype in
34 format_event_object. Needs refactoring */
35 #include "ui/Gtk/console-gtk.h" /* for gtk_event_name prototype. Same
37 #include "extents.h" /* Just for the EXTENTP abort check... */
38 #define INCLUDE_EVENTS_H_PRIVATE_SPHERE
41 #include "ui/glyphs.h"
42 #include "ui/keymap.h" /* for key_desc_list_to_event() */
43 #include "ui/redisplay.h"
44 #include "ui/window.h"
45 #include "events-mod.h"
47 /* Where old events go when they are explicitly deallocated.
48 The event chain here is cut loose before GC, so these will be freed
51 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
52 static Lisp_Object Vevent_resource;
54 static sxe_mutex_t Vevent_resource_mtx;
55 #endif /* EF_USE_ASYNEQ */
59 Lisp_Object Qevent_live_p;
60 Lisp_Object Qkey_press_event_p;
61 Lisp_Object Qbutton_event_p;
62 Lisp_Object Qmouse_event_p;
63 Lisp_Object Qprocess_event_p;
65 Lisp_Object Qkey_press, Qbutton_press, Qbutton_release, Qmisc_user;
66 Lisp_Object Qascii_character;
68 EXFUN(Fevent_x_pixel, 1);
69 EXFUN(Fevent_y_pixel, 1);
72 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
74 init_Vevent_resource(void)
80 fini_Vevent_resource(void)
86 lock_Vevent_resource(void)
92 unlock_Vevent_resource(void)
96 #elif defined EF_USE_ASYNEQ
98 init_Vevent_resource(void)
100 Vevent_resource = Qnil;
101 SXE_MUTEX_INIT(&Vevent_resource_mtx);
105 fini_Vevent_resource(void)
107 SXE_MUTEX_FINI(&Vevent_resource_mtx);
108 Vevent_resource = Qnil;
112 lock_Vevent_resource(void)
114 SXE_MUTEX_LOCK(&Vevent_resource_mtx);
118 unlock_Vevent_resource(void)
120 SXE_MUTEX_UNLOCK(&Vevent_resource_mtx);
125 init_Vevent_resource(void)
127 Vevent_resource = Qnil;
131 fini_Vevent_resource(void)
133 Vevent_resource = Qnil;
137 lock_Vevent_resource(void)
142 unlock_Vevent_resource(void)
147 /* #### Ad-hoc hack. Should be part of define_lrecord_implementation */
148 void clear_event_resource(void)
150 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
151 lock_Vevent_resource();
152 Vevent_resource = Qnil;
153 unlock_Vevent_resource();
157 /* Make sure we lose quickly if we try to use this event */
158 static void deinitialize_event(Lisp_Object ev)
160 Lisp_Event *event = XEVENT(ev);
162 for (sxe_index_t i = 0; i < (sizeof(Lisp_Event) / sizeof(int)); i++) {
163 ((int*)event)[i] = 0xdeadbeef;
165 event->event_type = dead_event;
166 event->channel = Qnil;
167 set_lheader_implementation(&event->lheader, &lrecord_event);
168 XSET_EVENT_NEXT(ev, Qnil);
171 /* Set everything to zero or nil so that it's predictable. */
172 void zero_event(Lisp_Event * e)
175 set_lheader_implementation(&e->lheader, &lrecord_event);
176 e->event_type = empty_event;
181 static Lisp_Object mark_event(Lisp_Object obj)
183 Lisp_Event *event = XEVENT(obj);
185 switch (event->event_type) {
186 case key_press_event:
187 mark_object(event->event.key.keysym);
190 mark_object(event->event.process.process);
193 mark_object(event->event.timeout.function);
194 mark_object(event->event.timeout.object);
197 case misc_user_event:
198 mark_object(event->event.eval.function);
199 mark_object(event->event.eval.object);
201 case magic_eval_event:
202 mark_object(event->event.magic_eval.object);
205 case work_started_event:
206 if (event->event.work_started.job)
207 mark_object(event->event.work_started.job);
209 case work_finished_event:
210 if (event->event.work_finished.job)
211 mark_object(event->event.work_finished.job);
213 case eaten_myself_event:
215 case button_press_event:
216 case button_release_event:
217 case pointer_motion_event:
225 mark_object(event->channel);
230 print_event_1(const char *str, Lisp_Object obj, Lisp_Object printcharfun)
233 write_c_string(str, printcharfun);
234 format_event_object(buf, XEVENT(obj), 0);
235 write_c_string(buf, printcharfun);
239 print_event(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
242 error("Printing unreadable object #<event>");
244 switch (XEVENT(obj)->event_type) {
245 case key_press_event:
246 print_event_1("#<keypress-event ", obj, printcharfun);
248 case button_press_event:
249 print_event_1("#<buttondown-event ", obj, printcharfun);
251 case button_release_event:
252 print_event_1("#<buttonup-event ", obj, printcharfun);
255 case magic_eval_event:
256 print_event_1("#<magic-event ", obj, printcharfun);
258 case pointer_motion_event: {
260 Vx = Fevent_x_pixel(obj);
262 Vy = Fevent_y_pixel(obj);
264 write_fmt_str(printcharfun, "#<motion-event %ld, %ld", (long)XINT(Vx),
269 write_c_string("#<process-event ", printcharfun);
270 print_internal(XEVENT(obj)->event.process.process, printcharfun,
274 write_c_string("#<timeout-event ", printcharfun);
275 print_internal(XEVENT(obj)->event.timeout.object, printcharfun,
279 write_c_string("#<empty-event", printcharfun);
281 case misc_user_event:
282 write_c_string("#<misc-user-event (", printcharfun);
283 print_internal(XEVENT(obj)->event.misc.function, printcharfun,
285 write_c_string(" ", printcharfun);
286 print_internal(XEVENT(obj)->event.misc.object, printcharfun, 1);
287 write_c_string(")", printcharfun);
290 write_c_string("#<eval-event (", printcharfun);
291 print_internal(XEVENT(obj)->event.eval.function, printcharfun,
293 write_c_string(" ", printcharfun);
294 print_internal(XEVENT(obj)->event.eval.object, printcharfun, 1);
295 write_c_string(")", printcharfun);
298 write_c_string("#<DEALLOCATED-EVENT", printcharfun);
301 case eaten_myself_event:
302 write_c_string("#<worker-suidice-event", printcharfun);
304 case work_started_event:
305 write_c_string("#<worker-work-started-event", printcharfun);
307 case work_finished_event:
308 write_c_string("#<worker-work-finished-event", printcharfun);
310 #endif /* EF_USE_ASYNEQ */
312 write_c_string("#<UNKNOWN-EVENT-TYPE", printcharfun);
315 write_c_string(">", printcharfun);
319 event_equal(Lisp_Object obj1, Lisp_Object obj2, int depth)
321 Lisp_Event *e1 = XEVENT(obj1);
322 Lisp_Event *e2 = XEVENT(obj2);
324 if (e1->event_type != e2->event_type)
326 if (!EQ(e1->channel, e2->channel))
328 /* if (e1->timestamp != e2->timestamp) return 0; */
329 switch (e1->event_type) {
334 return EQ(e1->event.process.process, e2->event.process.process);
337 return (internal_equal(e1->event.timeout.function,
338 e2->event.timeout.function, 0) &&
339 internal_equal(e1->event.timeout.object,
340 e2->event.timeout.object, 0));
342 case key_press_event:
343 return (EQ(e1->event.key.keysym, e2->event.key.keysym) &&
344 (e1->event.key.modifiers == e2->event.key.modifiers));
346 case button_press_event:
347 case button_release_event:
348 return (e1->event.button.button == e2->event.button.button &&
349 e1->event.button.modifiers ==
350 e2->event.button.modifiers);
352 case pointer_motion_event:
353 return (e1->event.motion.x == e2->event.motion.x &&
354 e1->event.motion.y == e2->event.motion.y);
356 case misc_user_event:
357 return (internal_equal(e1->event.eval.function,
358 e2->event.eval.function, 0) &&
359 internal_equal(e1->event.eval.object,
360 e2->event.eval.object, 0) &&
361 /* is this really needed for equality
362 or is x and y also important? */
363 e1->event.misc.button == e2->event.misc.button &&
364 e1->event.misc.modifiers == e2->event.misc.modifiers);
367 return (internal_equal(e1->event.eval.function,
368 e2->event.eval.function, 0) &&
369 internal_equal(e1->event.eval.object,
370 e2->event.eval.object, 0));
372 case magic_eval_event:
373 return (e1->event.magic_eval.internal_function ==
374 e2->event.magic_eval.internal_function &&
375 internal_equal(e1->event.magic_eval.object,
376 e2->event.magic_eval.object, 0));
379 struct console *con =
380 XCONSOLE(CDFW_CONSOLE(e1->channel));
383 if (CONSOLE_GTK_P(con))
385 (&e1->event.magic.underlying_gdk_event,
386 &e2->event.magic.underlying_gdk_event,
389 #ifdef HAVE_X_WINDOWS
390 if (CONSOLE_X_P(con))
391 return (e1->event.magic.underlying_x_event.xany.
393 e2->event.magic.underlying_x_event.xany.
397 if (CONSOLE_TTY_P(con))
398 return (e1->event.magic.underlying_tty_event ==
399 e2->event.magic.underlying_tty_event);
402 return 1; /* not reached */
406 /* worker thread mumbo jumbo is never equal */
407 case eaten_myself_event:
408 case work_started_event:
409 case work_finished_event:
411 #endif /* EF_USE_ASYNEQ */
413 /* Empty and deallocated events are equal. */
421 event_hash(Lisp_Object obj, int depth)
423 Lisp_Event *e = XEVENT(obj);
426 hash = HASH2(e->event_type, LISP_HASH(e->channel));
427 switch (e->event_type) {
429 return HASH2(hash, LISP_HASH(e->event.process.process));
433 internal_hash(e->event.timeout.function,
435 internal_hash(e->event.timeout.object, depth + 1));
437 case key_press_event:
438 return HASH3(hash, LISP_HASH(e->event.key.keysym),
439 e->event.key.modifiers);
441 case button_press_event:
442 case button_release_event:
443 return HASH3(hash, e->event.button.button,
444 e->event.button.modifiers);
446 case pointer_motion_event:
447 return HASH3(hash, e->event.motion.x, e->event.motion.y);
449 case misc_user_event:
451 internal_hash(e->event.misc.function, depth + 1),
452 internal_hash(e->event.misc.object, depth + 1),
453 e->event.misc.button, e->event.misc.modifiers);
457 internal_hash(e->event.eval.function, depth + 1),
458 internal_hash(e->event.eval.object, depth + 1));
460 case magic_eval_event:
462 (unsigned long)e->event.magic_eval.
464 internal_hash(e->event.magic_eval.object,
468 struct console *con =
469 XCONSOLE(CDFW_CONSOLE(EVENT_CHANNEL(e)));
471 if (CONSOLE_GTK_P(con))
474 underlying_gdk_event.type);
476 #ifdef HAVE_X_WINDOWS
477 if (CONSOLE_X_P(con))
479 e->event.magic.underlying_x_event.
483 if (CONSOLE_TTY_P(con))
486 underlying_tty_event);
493 case eaten_myself_event:
494 case work_started_event:
495 case work_finished_event:
496 return (long unsigned int)obj;
497 #endif /* EF_USE_ASYNEQ */
507 return 0; /* unreached */
510 DEFINE_BASIC_LRECORD_IMPLEMENTATION("event", event,
511 mark_event, print_event, 0, event_equal,
512 event_hash, 0, Lisp_Event);
515 make_empty_event(void)
517 Lisp_Object event = Qnil;
520 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
522 event = allocate_event();
528 lock_Vevent_resource();
529 if (!NILP(Vevent_resource)) {
530 event = Vevent_resource;
531 Vevent_resource = XEVENT_NEXT(event);
533 event = allocate_event();
535 unlock_Vevent_resource();
540 e->event_type = empty_event;
542 EVENT_CHANNEL(e) = Qnil;
549 make_noseeum_event(emacs_event_type event_type)
551 sxe_event_t res = xnew_and_zero(Lisp_Event);
553 res->event_type = event_type;
555 EVENT_CHANNEL(res) = Qnil;
559 DEFUN("make-event", Fmake_event, 0, 2, 0, /*
560 Return a new event of type TYPE, with properties described by PLIST.
562 TYPE is a symbol, either `empty', `key-press', `button-press',
563 `button-release', `misc-user' or `motion'. If TYPE is nil, it
566 PLIST is a property list, the properties being compatible to those
567 returned by `event-properties'. The following properties are
570 channel -- The event channel, a frame or a console. For
571 button-press, button-release, misc-user and motion events,
572 this must be a frame. For key-press events, it must be
573 a console. If channel is unspecified, it will be set to
574 the selected frame or selected console, as appropriate.
575 key -- The event key, a symbol or character. Allowed only for
577 button -- The event button, integer 1, 2 or 3. Allowed for
578 button-press, button-release and misc-user events.
579 modifiers -- The event modifiers, a list of modifier symbols. Allowed
580 for key-press, button-press, button-release, motion and
582 function -- Function. Allowed for misc-user events only.
583 object -- An object, function's parameter. Allowed for misc-user
585 x -- The event X coordinate, an integer. This is relative
586 to the left of CHANNEL's root window. Allowed for
587 motion, button-press, button-release and misc-user events.
588 y -- The event Y coordinate, an integer. This is relative
589 to the top of CHANNEL's root window. Allowed for
590 motion, button-press, button-release and misc-user events.
591 timestamp -- The event timestamp, a non-negative integer. Allowed for
592 all types of events. If unspecified, it will be set to 0
595 For event type `empty', PLIST must be nil.
596 `button-release', or `motion'. If TYPE is left out, it defaults to
598 PLIST is a list of properties, as returned by `event-properties'. Not
599 all properties are allowed for all kinds of events, and some are
602 WARNING: the event object returned may be a reused one; see the function
607 Lisp_Object event = Qnil;
609 EMACS_INT coord_x = 0, coord_y = 0;
614 return make_empty_event();
617 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
618 event = allocate_event();
622 lock_Vevent_resource();
623 if (!NILP(Vevent_resource)) {
624 event = Vevent_resource;
625 Vevent_resource = XEVENT_NEXT(event);
627 event = allocate_event();
629 unlock_Vevent_resource();
634 if (EQ(type, Qempty)) {
635 /* For empty event, we return immediately, without processing
636 PLIST. In fact, processing PLIST would be wrong, because the
637 sanitizing process would fill in the properties
638 (e.g. CHANNEL), which we don't want in empty events. */
639 e->event_type = empty_event;
641 syntax_error("Cannot set properties of empty event",
645 } else if (EQ(type, Qkey_press)) {
646 e->event_type = key_press_event;
647 e->event.key.keysym = Qunbound;
648 } else if (EQ(type, Qbutton_press)) {
649 e->event_type = button_press_event;
650 } else if (EQ(type, Qbutton_release)) {
651 e->event_type = button_release_event;
652 } else if (EQ(type, Qmotion)) {
653 e->event_type = pointer_motion_event;
654 } else if (EQ(type, Qmisc_user)) {
655 e->event_type = misc_user_event;
656 e->event.eval.function = e->event.eval.object = Qnil;
659 Qprocess, Qtimeout, Qmagic, Qeval, Qmagic_eval. */
660 invalid_argument("Invalid event type", type);
663 EVENT_CHANNEL(e) = Qnil;
665 plist = Fcopy_sequence(plist);
666 Fcanonicalize_plist(plist, Qnil);
668 #define WRONG_EVENT_TYPE_FOR_PROPERTY(event_type, prop) \
669 syntax_error_2 ("Invalid property for event type", prop, event_type)
672 EXTERNAL_PROPERTY_LIST_LOOP_3(keyword, value, plist) {
673 if (EQ(keyword, Qchannel)) {
674 if (e->event_type == key_press_event) {
675 if (!CONSOLEP(value))
682 wrong_type_argument(Qframep,
685 EVENT_CHANNEL(e) = value;
686 } else if (EQ(keyword, Qkey)) {
687 switch (e->event_type) {
688 case key_press_event:
689 if (!SYMBOLP(value) && !CHARP(value))
691 ("Invalid event key",
693 e->event.key.keysym = value;
698 case button_press_event:
699 case button_release_event:
700 case pointer_motion_event:
704 case magic_eval_event:
706 case misc_user_event:
708 case eaten_myself_event:
709 case work_started_event:
710 case work_finished_event:
711 #endif /* EF_USE_ASYNEQ */
714 WRONG_EVENT_TYPE_FOR_PROPERTY(type,
718 } else if (EQ(keyword, Qbutton)) {
720 check_int_range(XINT(value), 0, 7);
722 switch (e->event_type) {
723 case button_press_event:
724 case button_release_event:
725 e->event.button.button = XINT(value);
727 case misc_user_event:
728 e->event.misc.button = XINT(value);
731 /* and the rest of that lot */
733 case key_press_event:
734 case pointer_motion_event:
738 case magic_eval_event:
741 case eaten_myself_event:
742 case work_started_event:
743 case work_finished_event:
744 #endif /* EF_USE_ASYNEQ */
747 WRONG_EVENT_TYPE_FOR_PROPERTY(type,
751 } else if (EQ(keyword, Qmodifiers)) {
754 EXTERNAL_LIST_LOOP_2(sym, value) {
755 if (EQ(sym, Qcontrol))
756 modifiers |= XEMACS_MOD_CONTROL;
757 else if (EQ(sym, Qmeta))
758 modifiers |= XEMACS_MOD_META;
759 else if (EQ(sym, Qsuper))
760 modifiers |= XEMACS_MOD_SUPER;
761 else if (EQ(sym, Qhyper))
762 modifiers |= XEMACS_MOD_HYPER;
763 else if (EQ(sym, Qalt))
764 modifiers |= XEMACS_MOD_ALT;
765 else if (EQ(sym, Qsymbol))
766 modifiers |= XEMACS_MOD_ALT;
767 else if (EQ(sym, Qshift))
768 modifiers |= XEMACS_MOD_SHIFT;
769 else if (EQ(sym, Qbutton1))
770 modifiers |= XEMACS_MOD_BUTTON1;
771 else if (EQ(sym, Qbutton2))
772 modifiers |= XEMACS_MOD_BUTTON2;
773 else if (EQ(sym, Qbutton3))
774 modifiers |= XEMACS_MOD_BUTTON3;
775 else if (EQ(sym, Qbutton4))
776 modifiers |= XEMACS_MOD_BUTTON4;
777 else if (EQ(sym, Qbutton5))
778 modifiers |= XEMACS_MOD_BUTTON5;
781 ("Invalid key modifier",
785 switch (e->event_type) {
786 case key_press_event:
787 e->event.key.modifiers = modifiers;
789 case button_press_event:
790 case button_release_event:
791 e->event.button.modifiers = modifiers;
793 case pointer_motion_event:
794 e->event.motion.modifiers = modifiers;
796 case misc_user_event:
797 e->event.misc.modifiers = modifiers;
800 /* here come the rest */
805 case magic_eval_event:
808 case eaten_myself_event:
809 case work_started_event:
810 case work_finished_event:
811 #endif /* EF_USE_ASYNEQ */
814 WRONG_EVENT_TYPE_FOR_PROPERTY(type,
818 } else if (EQ(keyword, Qx)) {
819 switch (e->event_type) {
820 case pointer_motion_event:
821 case button_press_event:
822 case button_release_event:
823 case misc_user_event:
824 /* Allow negative values, so we can specify toolbar
827 coord_x = XINT(value);
832 case key_press_event:
836 case magic_eval_event:
839 case eaten_myself_event:
840 case work_started_event:
841 case work_finished_event:
842 #endif /* EF_USE_ASYNEQ */
845 WRONG_EVENT_TYPE_FOR_PROPERTY(type,
849 } else if (EQ(keyword, Qy)) {
850 switch (e->event_type) {
851 case pointer_motion_event:
852 case button_press_event:
853 case button_release_event:
854 case misc_user_event:
855 /* Allow negative values; see above. */
857 coord_y = XINT(value);
862 case key_press_event:
866 case magic_eval_event:
869 case eaten_myself_event:
870 case work_started_event:
871 case work_finished_event:
872 #endif /* EF_USE_ASYNEQ */
875 WRONG_EVENT_TYPE_FOR_PROPERTY(type,
879 } else if (EQ(keyword, Qtimestamp)) {
881 e->timestamp = XINT(value);
882 } else if (EQ(keyword, Qfunction)) {
883 switch (e->event_type) {
884 case misc_user_event:
885 e->event.eval.function = value;
890 case key_press_event:
891 case button_press_event:
892 case button_release_event:
893 case pointer_motion_event:
897 case magic_eval_event:
900 case eaten_myself_event:
901 case work_started_event:
902 case work_finished_event:
903 #endif /* EF_USE_ASYNEQ */
906 WRONG_EVENT_TYPE_FOR_PROPERTY(type,
910 } else if (EQ(keyword, Qobject)) {
911 switch (e->event_type) {
912 case misc_user_event:
913 e->event.eval.object = value;
918 case key_press_event:
919 case button_press_event:
920 case button_release_event:
921 case pointer_motion_event:
925 case magic_eval_event:
928 case eaten_myself_event:
929 case work_started_event:
930 case work_finished_event:
931 #endif /* EF_USE_ASYNEQ */
934 WRONG_EVENT_TYPE_FOR_PROPERTY(type,
939 syntax_error_2("Invalid property", keyword,
944 /* Insert the channel, if missing. */
945 if (NILP(EVENT_CHANNEL(e))) {
946 if (e->event_type == key_press_event)
947 EVENT_CHANNEL(e) = Vselected_console;
949 EVENT_CHANNEL(e) = Fselected_frame(Qnil);
952 /* Fevent_properties, Fevent_x_pixel, etc. work with pixels relative
953 to the frame, so we must adjust accordingly. */
954 if (FRAMEP(EVENT_CHANNEL(e))) {
956 FRAME_REAL_LEFT_TOOLBAR_WIDTH(XFRAME(EVENT_CHANNEL(e)));
958 FRAME_REAL_TOP_TOOLBAR_HEIGHT(XFRAME(EVENT_CHANNEL(e)));
960 switch (e->event_type) {
961 case pointer_motion_event:
962 e->event.motion.x = coord_x;
963 e->event.motion.y = coord_y;
965 case button_press_event:
966 case button_release_event:
967 e->event.button.x = coord_x;
968 e->event.button.y = coord_y;
970 case misc_user_event:
971 e->event.misc.x = coord_x;
972 e->event.misc.y = coord_y;
977 case key_press_event:
981 case magic_eval_event:
984 case eaten_myself_event:
985 case work_started_event:
986 case work_finished_event:
987 #endif /* EF_USE_ASYNEQ */
994 /* Finally, do some more validation. */
995 switch (e->event_type) {
996 case key_press_event:
997 if (UNBOUNDP(e->event.key.keysym))
999 ("A key must be specified to make a "
1000 "keypress event", plist);
1002 case button_press_event:
1003 if (!e->event.button.button)
1005 ("A button must be specified to make a "
1006 "button-press event", plist);
1008 case button_release_event:
1009 if (!e->event.button.button)
1011 ("A button must be specified to make a "
1012 "button-release event", plist);
1014 case misc_user_event:
1015 if (NILP(e->event.misc.function))
1017 ("A function must be specified to make a "
1018 "misc-user event", plist);
1022 case pointer_motion_event:
1026 case magic_eval_event:
1028 #ifdef EF_USE_ASYNEQ
1029 case eaten_myself_event:
1030 case work_started_event:
1031 case work_finished_event:
1032 #endif /* EF_USE_ASYNEQ */
1042 DEFUN("deallocate-event", Fdeallocate_event, 1, 1, 0, /*
1043 Allow the given event structure to be reused.
1044 You MUST NOT use this event object after calling this function with it.
1045 You will lose. It is not necessary to call this function, as event
1046 objects are garbage-collected like all other objects; however, it may
1047 be more efficient to explicitly deallocate events when you are sure
1048 that it is safe to do so.
1054 if (XEVENT_TYPE(event) == dead_event)
1055 error("this event is already deallocated!");
1057 assert(XEVENT_TYPE(event) <= last_event_type);
1063 if (EQ(event, Vlast_command_event) ||
1064 EQ(event, Vlast_input_event) ||
1065 EQ(event, Vunread_command_event))
1068 len = XVECTOR_LENGTH(Vthis_command_keys);
1069 for (i = 0; i < len; i++)
1070 if (EQ(event, XVECTOR_DATA(Vthis_command_keys)[i]))
1072 if (!NILP(Vrecent_keys_ring)) {
1073 int recent_ring_len = XVECTOR_LENGTH(Vrecent_keys_ring);
1074 for (i = 0; i < recent_ring_len; i++)
1076 (event, XVECTOR_DATA(Vrecent_keys_ring)[i]))
1082 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
1083 lock_Vevent_resource();
1084 assert(!EQ(event, Vevent_resource));
1085 unlock_Vevent_resource();
1087 deinitialize_event(event);
1088 #if !defined ALLOC_NO_POOLS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
1089 lock_Vevent_resource();
1090 XSET_EVENT_NEXT(event, Vevent_resource);
1091 Vevent_resource = event;
1092 unlock_Vevent_resource();
1097 DEFUN("copy-event", Fcopy_event, 1, 2, 0, /*
1098 Make a copy of the event object EVENT1.
1099 If a second event argument EVENT2 is given, EVENT1 is copied into
1100 EVENT2 and EVENT2 is returned. If EVENT2 is not supplied (or is nil)
1101 then a new event will be made as with `make-event'. See also the
1102 function `deallocate-event'.
1106 CHECK_LIVE_EVENT(event1);
1108 event2 = Fmake_event(Qnil, Qnil);
1110 CHECK_LIVE_EVENT(event2);
1111 if (EQ(event1, event2))
1112 return signal_simple_continuable_error_2
1113 ("copy-event called with `eq' events", event1,
1117 assert(XEVENT_TYPE(event1) <= last_event_type);
1118 assert(XEVENT_TYPE(event2) <= last_event_type);
1121 Lisp_Event *ev2 = XEVENT(event2);
1122 Lisp_Event *ev1 = XEVENT(event1);
1124 ev2->event_type = ev1->event_type;
1125 ev2->channel = ev1->channel;
1126 ev2->timestamp = ev1->timestamp;
1127 ev2->event = ev1->event;
1133 /* Given a chain of events (or possibly nil), deallocate them all. */
1135 void deallocate_event_chain(Lisp_Object event_chain)
1137 while (!NILP(event_chain)) {
1138 Lisp_Object next = XEVENT_NEXT(event_chain);
1139 Fdeallocate_event(event_chain);
1144 /* Return the last event in a chain.
1145 NOTE: You cannot pass nil as a value here! The routine will
1148 Lisp_Object event_chain_tail(Lisp_Object event_chain)
1151 Lisp_Object next = XEVENT_NEXT(event_chain);
1158 /* Enqueue a single event onto the end of a chain of events.
1159 HEAD points to the first event in the chain, TAIL to the last event.
1160 If the chain is empty, both values should be nil. */
1162 void enqueue_event(Lisp_Object event, Lisp_Object * head, Lisp_Object * tail)
1164 assert(NILP(XEVENT_NEXT(event)));
1165 assert(!EQ(*tail, event));
1168 XSET_EVENT_NEXT(*tail, event);
1173 assert(!EQ(event, XEVENT_NEXT(event)));
1176 /* Remove an event off the head of a chain of events and return it.
1177 HEAD points to the first event in the chain, TAIL to the last event. */
1179 Lisp_Object dequeue_event(Lisp_Object * head, Lisp_Object * tail)
1184 *head = XEVENT_NEXT(event);
1185 XSET_EVENT_NEXT(event, Qnil);
1191 /* Enqueue a chain of events (or possibly nil) onto the end of another
1192 chain of events. HEAD points to the first event in the chain being
1193 queued onto, TAIL to the last event. If the chain is empty, both values
1197 enqueue_event_chain(Lisp_Object event_chain, Lisp_Object * head,
1200 if (NILP(event_chain))
1204 *head = event_chain;
1205 *tail = event_chain;
1207 XSET_EVENT_NEXT(*tail, event_chain);
1208 *tail = event_chain_tail(event_chain);
1212 /* Return the number of events (possibly 0) on an event chain. */
1214 int event_chain_count(Lisp_Object event_chain)
1219 EVENT_CHAIN_LOOP(event, event_chain) {
1226 /* Find the event before EVENT in an event chain. This aborts
1227 if the event is not in the chain. */
1230 event_chain_find_previous(Lisp_Object event_chain, Lisp_Object event)
1232 Lisp_Object previous = Qnil;
1234 while (!NILP(event_chain)) {
1235 if (EQ(event_chain, event)) {
1238 previous = event_chain;
1239 event_chain = XEVENT_NEXT(event_chain);
1246 Lisp_Object event_chain_nth(Lisp_Object event_chain, int n)
1249 EVENT_CHAIN_LOOP(event, event_chain) {
1258 Lisp_Object copy_event_chain(Lisp_Object event_chain)
1260 Lisp_Object new_chain = Qnil;
1261 Lisp_Object new_chain_tail = Qnil;
1264 EVENT_CHAIN_LOOP(event, event_chain) {
1265 Lisp_Object copy = Fcopy_event(event, Qnil);
1266 enqueue_event(copy, &new_chain, &new_chain_tail);
1272 Lisp_Object QKbackspace, QKtab, QKlinefeed, QKreturn, QKescape,
1275 int command_event_p(Lisp_Object event)
1277 switch (XEVENT_TYPE(event)) {
1278 case key_press_event:
1279 case button_press_event:
1280 case button_release_event:
1281 case misc_user_event:
1285 case pointer_motion_event:
1289 case magic_eval_event:
1291 #ifdef EF_USE_ASYNEQ
1292 case eaten_myself_event:
1293 case work_started_event:
1294 case work_finished_event:
1295 #endif /* EF_USE_ASYNEQ */
1303 character_to_event(Emchar c, Lisp_Event * event, struct console *con,
1304 int use_console_meta_flag, int do_backspace_mapping)
1306 Lisp_Object k = Qnil;
1308 if (event->event_type == dead_event)
1309 error("character-to-event called with a deallocated event!");
1314 if (c > 127 && c <= 255) {
1317 if (use_console_meta_flag && CONSOLE_TTY_P(con)) {
1318 meta_flag = TTY_FLAGS(con).meta_key;
1320 switch (meta_flag) {
1321 case 0: /* ignore top bit; it's parity */
1324 case 1: /* top bit is meta */
1326 m = XEMACS_MOD_META;
1328 default: /* this is a real character */
1333 c += '@', m |= XEMACS_MOD_CONTROL;
1334 if (m & XEMACS_MOD_CONTROL) {
1338 m &= ~XEMACS_MOD_CONTROL;
1342 m &= ~XEMACS_MOD_CONTROL;
1346 m &= ~XEMACS_MOD_CONTROL;
1350 m &= ~XEMACS_MOD_CONTROL;
1353 #if defined(HAVE_TTY)
1354 if (do_backspace_mapping &&
1355 CHARP(con->tty_erase_char) &&
1356 c - '@' == XCHAR(con->tty_erase_char)) {
1358 m &= ~XEMACS_MOD_CONTROL;
1360 #endif /* defined(HAVE_TTY) */
1363 if (c >= 'A' && c <= 'Z')
1366 #if defined(HAVE_TTY)
1367 else if (do_backspace_mapping &&
1368 CHARP(con->tty_erase_char) && c == XCHAR(con->tty_erase_char))
1370 #endif /* defined(HAVE_TTY) */
1376 event->event_type = key_press_event;
1377 event->timestamp = 0; /* #### */
1378 event->channel = make_console(con);
1379 event->event.key.keysym = (!NILP(k) ? k : make_char(c));
1380 event->event.key.modifiers = m;
1383 /* This variable controls what character name -> character code mapping
1384 we are using. Window-system-specific code sets this to some symbol,
1385 and we use that symbol as the plist key to convert keysyms into 8-bit
1386 codes. In this way one can have several character sets predefined and
1387 switch them by changing this.
1389 #### This is utterly bogus and should be removed.
1391 Lisp_Object Vcharacter_set_property;
1394 event_to_character(Lisp_Event * event,
1395 int allow_extra_modifiers,
1396 int allow_meta, int allow_non_ascii)
1401 if (event->event_type != key_press_event) {
1402 assert(event->event_type != dead_event);
1405 if (!allow_extra_modifiers &&
1407 modifiers & (XEMACS_MOD_SUPER | XEMACS_MOD_HYPER | XEMACS_MOD_ALT))
1409 if (CHAR_OR_CHAR_INTP(event->event.key.keysym))
1410 c = XCHAR_OR_CHAR_INT(event->event.key.keysym);
1411 else if (!SYMBOLP(event->event.key.keysym))
1413 else if (allow_non_ascii && !NILP(Vcharacter_set_property)
1414 /* Allow window-system-specific extensibility of
1415 keysym->code mapping */
1416 && CHAR_OR_CHAR_INTP(code = Fget(event->event.key.keysym,
1417 Vcharacter_set_property,
1419 c = XCHAR_OR_CHAR_INT(code);
1420 else if (CHAR_OR_CHAR_INTP(code = Fget(event->event.key.keysym,
1421 Qascii_character, Qnil)))
1422 c = XCHAR_OR_CHAR_INT(code);
1426 if (event->event.key.modifiers & XEMACS_MOD_CONTROL) {
1427 if (c >= 'a' && c <= 'z')
1430 /* reject Control-Shift- keys */
1431 if (c >= 'A' && c <= 'Z' && !allow_extra_modifiers)
1434 if (c >= '@' && c <= '_')
1436 else if (c == ' ') /* C-space and C-@ are the same. */
1439 /* reject keys that can't take Control- modifiers */
1440 if (!allow_extra_modifiers)
1444 if (event->event.key.modifiers & XEMACS_MOD_META) {
1448 return -1; /* don't allow M-oslash (overlap) */
1458 DEFUN("event-to-character", Fevent_to_character, 1, 4, 0, /*
1459 Return the closest ASCII approximation to the given event object.
1460 If the event isn't a keypress, this returns nil.
1461 If the ALLOW-EXTRA-MODIFIERS argument is non-nil, then this is lenient in
1462 its translation; it will ignore modifier keys other than control and meta,
1463 and will ignore the shift modifier on those characters which have no
1464 shifted ASCII equivalent (Control-Shift-A for example, will be mapped to
1465 the same ASCII code as Control-A).
1466 If the ALLOW-META argument is non-nil, then the Meta modifier will be
1467 represented by turning on the high bit of the byte returned; otherwise, nil
1468 will be returned for events containing the Meta modifier.
1469 If the ALLOW-NON-ASCII argument is non-nil, then characters which are
1470 present in the prevailing character set (see the `character-set-property'
1471 variable) will be returned as their code in that character set, instead of
1472 the return value being restricted to ASCII.
1473 Note that specifying both ALLOW-META and ALLOW-NON-ASCII is ambiguous, as
1474 both use the high bit; `M-x' and `oslash' will be indistinguishable.
1476 (event, allow_extra_modifiers, allow_meta, allow_non_ascii))
1479 CHECK_LIVE_EVENT(event);
1480 c = event_to_character(XEVENT(event),
1481 !NILP(allow_extra_modifiers),
1482 !NILP(allow_meta), !NILP(allow_non_ascii));
1483 return c < 0 ? Qnil : make_char(c);
1486 DEFUN("character-to-event", Fcharacter_to_event, 1, 4, 0, /*
1487 Convert KEY-DESCRIPTION into an event structure, replete with bucky bits.
1489 KEY-DESCRIPTION is the first argument, and the event to fill in is the
1490 second. This function contains knowledge about what various kinds of
1491 arguments ``mean'' -- for example, the number 9 is converted to the
1492 character ``Tab'', not the distinct character ``Control-I''.
1494 KEY-DESCRIPTION can be an integer, a character, a symbol such as 'clear,
1495 or a list such as '(control backspace).
1497 If the optional second argument EVENT is an event, it is modified and
1498 returned; otherwise, a new event object is created and returned.
1500 Optional third arg CONSOLE is the console to store in the event, and
1501 defaults to the selected console.
1503 If KEY-DESCRIPTION is an integer or character, the high bit may be
1504 interpreted as the meta key. (This is done for backward compatibility
1505 in lots of places.) If USE-CONSOLE-META-FLAG is nil, this will always
1506 be the case. If USE-CONSOLE-META-FLAG is non-nil, the `meta' flag for
1507 CONSOLE affects whether the high bit is interpreted as a meta
1508 key. (See `set-input-mode'.) If you don't want this silly meta
1509 interpretation done, you should pass in a list containing the
1512 Beware that character-to-event and event-to-character are not strictly
1513 inverse functions, since events contain much more information than the
1514 Lisp character object type can encode.
1516 (keystroke, event, console, use_console_meta_flag))
1518 struct console *con = decode_console(console);
1520 event = Fmake_event(Qnil, Qnil);
1522 CHECK_LIVE_EVENT(event);
1523 if (CONSP(keystroke) || SYMBOLP(keystroke))
1524 key_desc_list_to_event(keystroke, event, 1);
1526 CHECK_CHAR_COERCE_INT(keystroke);
1527 character_to_event(XCHAR(keystroke), XEVENT(event), con,
1528 !NILP(use_console_meta_flag), 1);
1533 void nth_of_key_sequence_as_event(Lisp_Object seq, int n, Lisp_Object event)
1535 assert(STRINGP(seq) || VECTORP(seq));
1536 assert(n < XINT(Flength(seq)));
1539 Emchar ch = string_char(XSTRING(seq), n);
1540 Fcharacter_to_event(make_char(ch), event, Qnil, Qnil);
1542 Lisp_Object keystroke = XVECTOR_DATA(seq)[n];
1543 if (EVENTP(keystroke))
1544 Fcopy_event(keystroke, event);
1546 Fcharacter_to_event(keystroke, event, Qnil, Qnil);
1550 Lisp_Object key_sequence_to_event_chain(Lisp_Object seq)
1552 int len = XINT(Flength(seq));
1554 Lisp_Object head = Qnil, tail = Qnil;
1556 for (i = 0; i < len; i++) {
1557 Lisp_Object event = Fmake_event(Qnil, Qnil);
1558 nth_of_key_sequence_as_event(seq, i, event);
1559 enqueue_event(event, &head, &tail);
1565 void format_event_object(char *buf, Lisp_Event * event, int brief)
1571 switch (event->event_type) {
1572 case key_press_event: {
1573 mod = event->event.key.modifiers;
1574 key = event->event.key.keysym;
1576 if (!brief && CHARP(key) &&
1577 mod & (XEMACS_MOD_CONTROL | XEMACS_MOD_META |
1578 XEMACS_MOD_SUPER | XEMACS_MOD_HYPER)) {
1580 if (k >= 'a' && k <= 'z')
1581 key = make_char(k - ('a' - 'A'));
1582 else if (k >= 'A' && k <= 'Z')
1583 mod |= XEMACS_MOD_SHIFT;
1587 case button_release_event:
1590 case button_press_event: {
1592 mod = event->event.button.modifiers;
1593 key = make_char(event->event.button.button + '0');
1597 const char *name = NULL;
1600 Lisp_Object console = CDFW_CONSOLE(EVENT_CHANNEL(event));
1601 if (CONSOLE_GTK_P(XCONSOLE(console))) {
1602 name = gtk_event_name(event->event.magic.
1603 underlying_gdk_event.
1607 #ifdef HAVE_X_WINDOWS
1608 Lisp_Object console = CDFW_CONSOLE(EVENT_CHANNEL(event));
1609 if (CONSOLE_X_P(XCONSOLE(console))) {
1610 name = x_event_name(event->event.magic.
1614 #endif /* HAVE_X_WINDOWS */
1623 case magic_eval_event:
1624 strcpy(buf, "magic-eval");
1626 case pointer_motion_event:
1627 strcpy(buf, "motion");
1629 case misc_user_event:
1630 strcpy(buf, "misc-user");
1633 strcpy(buf, "eval");
1636 strcpy(buf, "process");
1639 strcpy(buf, "timeout");
1642 strcpy(buf, "empty");
1645 strcpy(buf, "DEAD-EVENT");
1647 #ifdef EF_USE_ASYNEQ
1648 case eaten_myself_event:
1649 strcpy(buf, "suicide");
1651 case work_started_event:
1652 strcpy(buf, "started-work");
1654 case work_finished_event:
1655 strcpy(buf, "finished-work");
1657 #endif /* EF_USE_ASYNEQ */
1663 #define modprint1(x) do { strcpy (buf, (x)); buf += sizeof (x)-1; } while (0)
1664 #define modprint(x,y) do { if (brief) modprint1 (y); else modprint1 (x); } while (0)
1665 if (mod & XEMACS_MOD_CONTROL)
1666 modprint("control-", "C-");
1667 if (mod & XEMACS_MOD_META)
1668 modprint("meta-", "M-");
1669 if (mod & XEMACS_MOD_SUPER)
1670 modprint("super-", "S-");
1671 if (mod & XEMACS_MOD_HYPER)
1672 modprint("hyper-", "H-");
1673 if (mod & XEMACS_MOD_ALT)
1674 modprint("alt-", "A-");
1675 if (mod & XEMACS_MOD_SHIFT)
1676 modprint("shift-", "Sh-");
1678 modprint1("button");
1685 buf += set_charptr_emchar((Bufbyte *) buf, XCHAR(key));
1687 } else if (SYMBOLP(key)) {
1688 const char *str = 0;
1690 if (EQ(key, QKlinefeed))
1692 else if (EQ(key, QKtab))
1694 else if (EQ(key, QKreturn))
1696 else if (EQ(key, QKescape))
1698 else if (EQ(key, QKdelete))
1700 else if (EQ(key, QKspace))
1702 else if (EQ(key, QKbackspace))
1706 int i = strlen(str);
1707 memcpy(buf, str, i + 1);
1710 Lisp_String *name = XSYMBOL(key)->name;
1711 memcpy(buf, string_data(name), string_length(name) + 1);
1712 str += string_length(name);
1717 strncpy(buf, "up", 4);
1720 DEFUN("eventp", Feventp, 1, 1, 0, /*
1721 True if OBJECT is an event object.
1725 return EVENTP(object) ? Qt : Qnil;
1728 DEFUN("event-live-p", Fevent_live_p, 1, 1, 0, /*
1729 True if OBJECT is an event object that has not been deallocated.
1733 return EVENTP(object) && XEVENT(object)->event_type != dead_event ?
1737 #if 0 /* debugging functions */
1739 xxDEFUN("event-next", Fevent_next, 1, 1, 0, /*
1740 Return the event object's `next' event, or nil if it has none.
1741 The `next-event' field is changed by calling `set-next-event'.
1746 CHECK_LIVE_EVENT(event);
1748 return XEVENT_NEXT(event);
1751 xxDEFUN("set-event-next", Fset_event_next, 2, 2, 0, /*
1752 Set the `next event' of EVENT to NEXT-EVENT.
1753 NEXT-EVENT must be an event object or nil.
1755 (event, next_event))
1759 CHECK_LIVE_EVENT(event);
1760 if (NILP(next_event)) {
1761 XSET_EVENT_NEXT(event, Qnil);
1765 CHECK_LIVE_EVENT(next_event);
1767 EVENT_CHAIN_LOOP(ev, XEVENT_NEXT(event)) {
1770 signal_error(Qerror,
1771 list3(build_string("Cyclic event-next"),
1772 event, next_event));
1774 XSET_EVENT_NEXT(event, next_event);
1780 DEFUN("event-type", Fevent_type, 1, 1, 0, /*
1781 Return the type of EVENT.
1782 This will be a symbol; one of
1784 key-press A key was pressed.
1785 button-press A mouse button was pressed.
1786 button-release A mouse button was released.
1787 misc-user Some other user action happened; typically, this is
1788 a menu selection or scrollbar action.
1789 motion The mouse moved.
1790 process Input is available from a subprocess.
1791 timeout A timeout has expired.
1792 eval This causes a specified action to occur when dispatched.
1793 magic Some window-system-specific event has occurred.
1794 empty The event has been allocated but not assigned.
1799 CHECK_LIVE_EVENT(event);
1800 switch (XEVENT(event)->event_type) {
1801 case key_press_event:
1803 case button_press_event:
1804 return Qbutton_press;
1805 case button_release_event:
1806 return Qbutton_release;
1807 case misc_user_event:
1809 case pointer_motion_event:
1818 case magic_eval_event:
1821 #ifdef EF_USE_ASYNEQ
1822 case eaten_myself_event:
1823 return Qworker_suicide;
1824 case work_started_event:
1825 return Qworker_started_work;
1826 case work_finished_event:
1827 return Qworker_finished_work;
1828 #endif /* EF_USE_ASYNEQ */
1840 DEFUN("event-timestamp", Fevent_timestamp, 1, 1, 0, /*
1841 Return the timestamp of the event object EVENT.
1842 Timestamps are measured in milliseconds since the start of the window system.
1843 They are NOT related to any current time measurement.
1844 They should be compared with `event-timestamp<'.
1845 See also `current-event-timestamp'.
1849 CHECK_LIVE_EVENT(event);
1850 /* This junk is so that timestamps don't get to be negative, but contain
1851 as many bits as this particular emacs will allow.
1853 return make_int(EMACS_INT_MAX & XEVENT(event)->timestamp);
1856 #define TIMESTAMP_HALFSPACE (1L << (INT_VALBITS - 2))
1858 DEFUN("event-timestamp<", Fevent_timestamp_lessp, 2, 2, 0, /*
1859 Return true if timestamp TIME1 is earlier than timestamp TIME2.
1860 This correctly handles timestamp wrap.
1861 See also `event-timestamp' and `current-event-timestamp'.
1867 CHECK_NATNUM(time1);
1868 CHECK_NATNUM(time2);
1873 return t2 - t1 < TIMESTAMP_HALFSPACE ? Qt : Qnil;
1875 return t1 - t2 < TIMESTAMP_HALFSPACE ? Qnil : Qt;
1878 #define CHECK_EVENT_TYPE(e,t1,sym) do { \
1879 CHECK_LIVE_EVENT (e); \
1880 if (XEVENT(e)->event_type != (t1)) \
1881 e = wrong_type_argument (sym,e); \
1884 #define CHECK_EVENT_TYPE2(e,t1,t2,sym) do { \
1885 CHECK_LIVE_EVENT (e); \
1887 emacs_event_type CET_type = XEVENT (e)->event_type; \
1888 if (CET_type != (t1) && \
1890 e = wrong_type_argument (sym,e); \
1894 #define CHECK_EVENT_TYPE3(e,t1,t2,t3,sym) do { \
1895 CHECK_LIVE_EVENT (e); \
1897 emacs_event_type CET_type = XEVENT (e)->event_type; \
1898 if (CET_type != (t1) && \
1899 CET_type != (t2) && \
1901 e = wrong_type_argument (sym,e); \
1905 DEFUN("event-key", Fevent_key, 1, 1, 0, /*
1906 Return the Keysym of the key-press event EVENT.
1907 This will be a character if the event is associated with one, else a symbol.
1911 CHECK_EVENT_TYPE(event, key_press_event, Qkey_press_event_p);
1912 return XEVENT(event)->event.key.keysym;
1915 DEFUN("event-button", Fevent_button, 1, 1, 0, /*
1916 Return the button-number of the button-press or button-release event EVENT.
1921 CHECK_EVENT_TYPE3(event, button_press_event, button_release_event,
1922 misc_user_event, Qbutton_event_p);
1923 #ifdef HAVE_WINDOW_SYSTEM
1924 if (XEVENT(event)->event_type == misc_user_event)
1925 return make_int(XEVENT(event)->event.misc.button);
1927 return make_int(XEVENT(event)->event.button.button);
1928 #else /* !HAVE_WINDOW_SYSTEM */
1930 #endif /* !HAVE_WINDOW_SYSTEM */
1934 DEFUN("event-modifier-bits", Fevent_modifier_bits, 1, 1, 0, /*
1935 Return a number representing the modifier keys and buttons which were down
1936 when the given mouse or keyboard event was produced.
1937 See also the function `event-modifiers'.
1942 CHECK_LIVE_EVENT(event);
1943 switch (XEVENT(event)->event_type) {
1944 case key_press_event:
1945 return make_int(XEVENT(event)->event.key.modifiers);
1946 case button_press_event:
1947 case button_release_event:
1948 return make_int(XEVENT(event)->event.button.modifiers);
1949 case pointer_motion_event:
1950 return make_int(XEVENT(event)->event.motion.modifiers);
1951 case misc_user_event:
1952 return make_int(XEVENT(event)->event.misc.modifiers);
1958 case magic_eval_event:
1960 #ifdef EF_USE_ASYNEQ
1961 case eaten_myself_event:
1962 case work_started_event:
1963 case work_finished_event:
1964 #endif /* EF_USE_ASYNEQ */
1967 event = wrong_type_argument(
1968 intern("key-or-mouse-event-p"), event);
1973 DEFUN("event-modifiers", Fevent_modifiers, 1, 1, 0, /*
1974 Return a list of symbols, the names of the modifier keys and buttons
1975 which were down when the given mouse or keyboard event was produced.
1976 See also the function `event-modifier-bits'.
1978 The possible symbols in the list are
1980 `shift': The Shift key. Will not appear, in general, on key events
1981 where the keysym is an ASCII character, because using Shift
1982 on such a character converts it into another character rather
1983 than actually just adding a Shift modifier.
1985 `control': The Control key.
1987 `meta': The Meta key. On PC's and PC-style keyboards, this is generally
1988 labelled \"Alt\"; Meta is a holdover from early Lisp Machines and
1989 such, propagated through the X Window System. On Sun keyboards,
1990 this key is labelled with a diamond.
1992 `alt': The \"Alt\" key. Alt is in quotes because this does not refer
1993 to what it obviously should refer to, namely the Alt key on PC
1994 keyboards. Instead, it refers to the key labelled Alt on Sun
1995 keyboards, and to no key at all on PC keyboards.
1997 `super': The Super key. Most keyboards don't have any such key, but
1998 under X Windows using `xmodmap' you can assign any key (such as
1999 an underused right-shift, right-control, or right-alt key) to
2002 `hyper': The Hyper key. Works just like the Super key.
2004 `button1': The mouse buttons. This means that the specified button was held
2005 `button2': down at the time the event occurred. NOTE: For button-press
2006 `button3': events, the button that was just pressed down does NOT appear in
2007 `button4': the modifiers.
2010 Button modifiers are currently ignored when defining and looking up key and
2011 mouse strokes in keymaps. This could be changed, which would allow a user to
2012 create button-chord actions, use a button as a key modifier and do other
2017 int mod = XINT(Fevent_modifier_bits(event));
2018 Lisp_Object result = Qnil;
2019 struct gcpro gcpro1;
2022 if (mod & XEMACS_MOD_SHIFT)
2023 result = Fcons(Qshift, result);
2024 if (mod & XEMACS_MOD_ALT)
2025 result = Fcons(Qalt, result);
2026 if (mod & XEMACS_MOD_HYPER)
2027 result = Fcons(Qhyper, result);
2028 if (mod & XEMACS_MOD_SUPER)
2029 result = Fcons(Qsuper, result);
2030 if (mod & XEMACS_MOD_META)
2031 result = Fcons(Qmeta, result);
2032 if (mod & XEMACS_MOD_CONTROL)
2033 result = Fcons(Qcontrol, result);
2034 if (mod & XEMACS_MOD_BUTTON1)
2035 result = Fcons(Qbutton1, result);
2036 if (mod & XEMACS_MOD_BUTTON2)
2037 result = Fcons(Qbutton2, result);
2038 if (mod & XEMACS_MOD_BUTTON3)
2039 result = Fcons(Qbutton3, result);
2040 if (mod & XEMACS_MOD_BUTTON4)
2041 result = Fcons(Qbutton4, result);
2042 if (mod & XEMACS_MOD_BUTTON5)
2043 result = Fcons(Qbutton5, result);
2044 RETURN_UNGCPRO(Fnreverse(result));
2048 event_x_y_pixel_internal(Lisp_Object event, int *x, int *y, int relative)
2053 if (XEVENT(event)->event_type == pointer_motion_event) {
2054 *x = XEVENT(event)->event.motion.x;
2055 *y = XEVENT(event)->event.motion.y;
2056 } else if (XEVENT(event)->event_type == button_press_event ||
2057 XEVENT(event)->event_type == button_release_event) {
2058 *x = XEVENT(event)->event.button.x;
2059 *y = XEVENT(event)->event.button.y;
2060 } else if (XEVENT(event)->event_type == misc_user_event) {
2061 *x = XEVENT(event)->event.misc.x;
2062 *y = XEVENT(event)->event.misc.y;
2066 f = XFRAME(EVENT_CHANNEL(XEVENT(event)));
2069 w = find_window_by_pixel_pos(*x, *y, f->root_window);
2072 return 1; /* #### What should really happen here? */
2074 *x -= w->pixel_left;
2077 *y -= FRAME_REAL_TOP_TOOLBAR_HEIGHT(f) -
2078 FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH(f);
2079 *x -= FRAME_REAL_LEFT_TOOLBAR_WIDTH(f) -
2080 FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH(f);
2086 DEFUN("event-window-x-pixel", Fevent_window_x_pixel, 1, 1, 0, /*
2087 Return the X position in pixels of mouse event EVENT.
2088 The value returned is relative to the window the event occurred in.
2089 This will signal an error if the event is not a mouse event.
2090 See also `mouse-event-p' and `event-x-pixel'.
2096 CHECK_LIVE_EVENT(event);
2098 if (!event_x_y_pixel_internal(event, &x, &y, 1))
2099 return wrong_type_argument(Qmouse_event_p, event);
2104 DEFUN("event-window-y-pixel", Fevent_window_y_pixel, 1, 1, 0, /*
2105 Return the Y position in pixels of mouse event EVENT.
2106 The value returned is relative to the window the event occurred in.
2107 This will signal an error if the event is not a mouse event.
2108 See also `mouse-event-p' and `event-y-pixel'.
2114 CHECK_LIVE_EVENT(event);
2116 if (!event_x_y_pixel_internal(event, &x, &y, 1))
2117 return wrong_type_argument(Qmouse_event_p, event);
2122 DEFUN("event-x-pixel", Fevent_x_pixel, 1, 1, 0, /*
2123 Return the X position in pixels of mouse event EVENT.
2124 The value returned is relative to the frame the event occurred in.
2125 This will signal an error if the event is not a mouse event.
2126 See also `mouse-event-p' and `event-window-x-pixel'.
2132 CHECK_LIVE_EVENT(event);
2134 if (!event_x_y_pixel_internal(event, &x, &y, 0))
2135 return wrong_type_argument(Qmouse_event_p, event);
2140 DEFUN("event-y-pixel", Fevent_y_pixel, 1, 1, 0, /*
2141 Return the Y position in pixels of mouse event EVENT.
2142 The value returned is relative to the frame the event occurred in.
2143 This will signal an error if the event is not a mouse event.
2144 See also `mouse-event-p' `event-window-y-pixel'.
2150 CHECK_LIVE_EVENT(event);
2152 if (!event_x_y_pixel_internal(event, &x, &y, 0))
2153 return wrong_type_argument(Qmouse_event_p, event);
2158 /* Given an event, return a value:
2160 OVER_TOOLBAR: over one of the 4 frame toolbars
2161 OVER_MODELINE: over a modeline
2162 OVER_BORDER: over an internal border
2163 OVER_NOTHING: over the text area, but not over text
2164 OVER_OUTSIDE: outside of the frame border
2165 OVER_TEXT: over text in the text area
2166 OVER_V_DIVIDER: over windows vertical divider
2170 The X char position in CHAR_X, if not a null pointer.
2171 The Y char position in CHAR_Y, if not a null pointer.
2172 (These last two values are relative to the window the event is over.)
2173 The window it's over in W, if not a null pointer.
2174 The buffer position it's over in BUFP, if not a null pointer.
2175 The closest buffer position in CLOSEST, if not a null pointer.
2177 OBJ_X, OBJ_Y, OBJ1, and OBJ2 are as in pixel_to_glyph_translation().
2181 event_pixel_translation(Lisp_Object event, int *char_x, int *char_y,
2182 int *obj_x, int *obj_y,
2183 struct window **w, Bufpos * bufp, Bufpos * closest,
2184 Charcount * modeline_closest,
2185 Lisp_Object * obj1, Lisp_Object * obj2)
2192 int ret_x, ret_y, ret_obj_x, ret_obj_y;
2193 struct window *ret_w;
2194 Bufpos ret_bufp, ret_closest;
2195 Charcount ret_modeline_closest;
2196 Lisp_Object ret_obj1, ret_obj2;
2198 CHECK_LIVE_EVENT(event);
2199 frame = XEVENT(event)->channel;
2200 switch (XEVENT(event)->event_type) {
2201 case pointer_motion_event:
2202 pix_x = XEVENT(event)->event.motion.x;
2203 pix_y = XEVENT(event)->event.motion.y;
2205 case button_press_event:
2206 case button_release_event:
2207 pix_x = XEVENT(event)->event.button.x;
2208 pix_y = XEVENT(event)->event.button.y;
2210 case misc_user_event:
2211 pix_x = XEVENT(event)->event.misc.x;
2212 pix_y = XEVENT(event)->event.misc.y;
2216 case key_press_event:
2220 case magic_eval_event:
2222 #ifdef EF_USE_ASYNEQ
2223 case eaten_myself_event:
2224 case work_started_event:
2225 case work_finished_event:
2226 #endif /* EF_USE_ASYNEQ */
2229 dead_wrong_type_argument(Qmouse_event_p, event);
2232 result = pixel_to_glyph_translation(XFRAME(frame), pix_x, pix_y,
2233 &ret_x, &ret_y, &ret_obj_x,
2234 &ret_obj_y, &ret_w, &ret_bufp,
2235 &ret_closest, &ret_modeline_closest,
2236 &ret_obj1, &ret_obj2);
2238 if (result == OVER_NOTHING || result == OVER_OUTSIDE)
2240 else if (ret_w && NILP(ret_w->buffer))
2241 /* Why does this happen? (Does it still happen?)
2242 I guess the window has gotten reused as a non-leaf... */
2245 /* #### pixel_to_glyph_translation() sometimes returns garbage...
2246 The word has type Lisp_Type_Record (presumably meaning `extent') but the
2247 pointer points to random memory, often filled with 0, sometimes not.
2249 /* #### Chuck, do we still need this crap? */
2250 if (!NILP(ret_obj1) && !(GLYPHP(ret_obj1)
2251 #ifdef HAVE_TOOLBARS
2252 || TOOLBAR_BUTTONP(ret_obj1)
2256 if (!NILP(ret_obj2) && !(EXTENTP(ret_obj2) || CONSP(ret_obj2)))
2272 *closest = ret_closest;
2273 if (modeline_closest)
2274 *modeline_closest = ret_modeline_closest;
2283 DEFUN("event-over-text-area-p", Fevent_over_text_area_p, 1, 1, 0, /*
2284 Return t if the mouse event EVENT occurred over the text area of a window.
2285 The modeline is not considered to be part of the text area.
2290 event_pixel_translation(event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
2292 return result == OVER_TEXT || result == OVER_NOTHING ? Qt : Qnil;
2295 DEFUN("event-over-modeline-p", Fevent_over_modeline_p, 1, 1, 0, /*
2296 Return t if the mouse event EVENT occurred over the modeline of a window.
2301 event_pixel_translation(event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
2303 return result == OVER_MODELINE ? Qt : Qnil;
2306 DEFUN("event-over-border-p", Fevent_over_border_p, 1, 1, 0, /*
2307 Return t if the mouse event EVENT occurred over an internal border.
2312 event_pixel_translation(event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
2314 return result == OVER_BORDER ? Qt : Qnil;
2317 DEFUN("event-over-toolbar-p", Fevent_over_toolbar_p, 1, 1, 0, /*
2318 Return t if the mouse event EVENT occurred over a toolbar.
2323 event_pixel_translation(event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
2325 return result == OVER_TOOLBAR ? Qt : Qnil;
2328 DEFUN("event-over-vertical-divider-p", Fevent_over_vertical_divider_p, 1, 1, 0, /*
2329 Return t if the mouse event EVENT occurred over a window divider.
2334 event_pixel_translation(event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
2336 return result == OVER_V_DIVIDER ? Qt : Qnil;
2339 struct console *event_console_or_selected(Lisp_Object event)
2341 Lisp_Object channel = EVENT_CHANNEL(XEVENT(event));
2342 Lisp_Object console = CDFW_CONSOLE(channel);
2345 console = Vselected_console;
2347 return XCONSOLE(console);
2350 DEFUN("event-channel", Fevent_channel, 1, 1, 0, /*
2351 Return the channel that the event EVENT occurred on.
2352 This will be a frame, device, console, or nil for some types
2353 of events (e.g. eval events).
2357 CHECK_LIVE_EVENT(event);
2358 return EVENT_CHANNEL(XEVENT(event));
2361 DEFUN("event-window", Fevent_window, 1, 1, 0, /*
2362 Return the window over which mouse event EVENT occurred.
2363 This may be nil if the event occurred in the border or over a toolbar.
2364 The modeline is considered to be within the window it describes.
2370 event_pixel_translation(event, 0, 0, 0, 0, &w, 0, 0, 0, 0, 0);
2377 XSETWINDOW(window, w);
2382 DEFUN("event-point", Fevent_point, 1, 1, 0, /*
2383 Return the character position of the mouse event EVENT.
2384 If the event did not occur over a window, or did not occur over text,
2385 then this returns nil. Otherwise, it returns a position in the buffer
2386 visible in the event's window.
2393 event_pixel_translation(event, 0, 0, 0, 0, &w, &bufp, 0, 0, 0, 0);
2395 return w && bufp ? make_int(bufp) : Qnil;
2398 DEFUN("event-closest-point", Fevent_closest_point, 1, 1, 0, /*
2399 Return the character position closest to the mouse event EVENT.
2400 If the event did not occur over a window or over text, return the
2401 closest point to the location of the event. If the Y pixel position
2402 overlaps a window and the X pixel position is to the left of that
2403 window, the closest point is the beginning of the line containing the
2404 Y position. If the Y pixel position overlaps a window and the X pixel
2405 position is to the right of that window, the closest point is the end
2406 of the line containing the Y position. If the Y pixel position is
2407 above a window, return 0. If it is below the last character in a window,
2408 return the value of (window-end).
2414 event_pixel_translation(event, 0, 0, 0, 0, 0, 0, &bufp, 0, 0, 0);
2416 return bufp ? make_int(bufp) : Qnil;
2419 DEFUN("event-x", Fevent_x, 1, 1, 0, /*
2420 Return the X position of the mouse event EVENT in characters.
2421 This is relative to the window the event occurred over.
2427 event_pixel_translation(event, &char_x, 0, 0, 0, 0, 0, 0, 0, 0, 0);
2429 return make_int(char_x);
2432 DEFUN("event-y", Fevent_y, 1, 1, 0, /*
2433 Return the Y position of the mouse event EVENT in characters.
2434 This is relative to the window the event occurred over.
2440 event_pixel_translation(event, 0, &char_y, 0, 0, 0, 0, 0, 0, 0, 0);
2442 return make_int(char_y);
2445 DEFUN("event-modeline-position", Fevent_modeline_position, 1, 1, 0, /*
2446 Return the character position in the modeline that EVENT occurred over.
2447 EVENT should be a mouse event. If EVENT did not occur over a modeline,
2448 nil is returned. You can determine the actual character that the
2449 event occurred over by looking in `generated-modeline-string' at the
2450 returned character position. Note that `generated-modeline-string'
2451 is buffer-local, and you must use EVENT's buffer when retrieving
2452 `generated-modeline-string' in order to get accurate results.
2460 event_pixel_translation(event, 0, 0, 0, 0, 0, 0, 0, &mbufp, 0, 0);
2462 return (mbufp < 0 || where != OVER_MODELINE) ? Qnil : make_int(mbufp);
2465 DEFUN("event-glyph", Fevent_glyph, 1, 1, 0, /*
2466 Return the glyph that the mouse event EVENT occurred over, or nil.
2473 event_pixel_translation(event, 0, 0, 0, 0, &w, 0, 0, 0, &glyph, 0);
2475 return w && GLYPHP(glyph) ? glyph : Qnil;
2478 DEFUN("event-glyph-extent", Fevent_glyph_extent, 1, 1, 0, /*
2479 Return the extent of the glyph that the mouse event EVENT occurred over.
2480 If the event did not occur over a glyph, nil is returned.
2487 event_pixel_translation(event, 0, 0, 0, 0, &w, 0, 0, 0, 0, &extent);
2489 return w && EXTENTP(extent) ? extent : Qnil;
2492 DEFUN("event-glyph-x-pixel", Fevent_glyph_x_pixel, 1, 1, 0, /*
2493 Return the X pixel position of EVENT relative to the glyph it occurred over.
2494 EVENT should be a mouse event. If the event did not occur over a glyph,
2503 event_pixel_translation(event, 0, 0, &obj_x, 0, &w, 0, 0, 0, 0,
2506 return w && EXTENTP(extent) ? make_int(obj_x) : Qnil;
2509 DEFUN("event-glyph-y-pixel", Fevent_glyph_y_pixel, 1, 1, 0, /*
2510 Return the Y pixel position of EVENT relative to the glyph it occurred over.
2511 EVENT should be a mouse event. If the event did not occur over a glyph,
2520 event_pixel_translation(event, 0, 0, 0, &obj_y, &w, 0, 0, 0, 0,
2523 return w && EXTENTP(extent) ? make_int(obj_y) : Qnil;
2526 DEFUN("event-toolbar-button", Fevent_toolbar_button, 1, 1, 0, /*
2527 Return the toolbar button that the mouse event EVENT occurred over.
2528 If the event did not occur over a toolbar button, nil is returned.
2532 #ifdef HAVE_TOOLBARS
2536 event_pixel_translation(event, 0, 0, 0, 0, 0, 0, 0, 0, &button, 0);
2538 return result == OVER_TOOLBAR
2539 && TOOLBAR_BUTTONP(button) ? button : Qnil;
2545 DEFUN("event-process", Fevent_process, 1, 1, 0, /*
2546 Return the process of the process-output event EVENT.
2550 CHECK_EVENT_TYPE(event, process_event, Qprocess_event_p);
2551 return XEVENT(event)->event.process.process;
2554 DEFUN("event-function", Fevent_function, 1, 1, 0, /*
2555 Return the callback function of EVENT.
2556 EVENT should be a timeout, misc-user, or eval event.
2561 CHECK_LIVE_EVENT(event);
2562 switch (XEVENT(event)->event_type) {
2564 return XEVENT(event)->event.timeout.function;
2565 case misc_user_event:
2566 return XEVENT(event)->event.misc.function;
2568 return XEVENT(event)->event.eval.function;
2571 case key_press_event:
2572 case button_press_event:
2573 case button_release_event:
2574 case pointer_motion_event:
2577 case magic_eval_event:
2578 #ifdef EF_USE_ASYNEQ
2579 case eaten_myself_event:
2580 case work_started_event:
2581 case work_finished_event:
2582 #endif /* EF_USE_ASYNEQ */
2586 wrong_type_argument(intern("timeout-or-eval-event-p"),
2592 DEFUN("event-object", Fevent_object, 1, 1, 0, /*
2593 Return the callback function argument of EVENT.
2594 EVENT should be a timeout, misc-user, or eval event.
2599 CHECK_LIVE_EVENT(event);
2600 switch (XEVENT(event)->event_type) {
2602 return XEVENT(event)->event.timeout.object;
2603 case misc_user_event:
2604 return XEVENT(event)->event.misc.object;
2606 return XEVENT(event)->event.eval.object;
2609 case key_press_event:
2610 case button_press_event:
2611 case button_release_event:
2612 case pointer_motion_event:
2615 case magic_eval_event:
2616 #ifdef EF_USE_ASYNEQ
2617 case eaten_myself_event:
2618 case work_started_event:
2619 case work_finished_event:
2620 #endif /* EF_USE_ASYNEQ */
2623 event = wrong_type_argument(
2624 intern("timeout-or-eval-event-p"), event);
2629 DEFUN("event-properties", Fevent_properties, 1, 1, 0, /*
2630 Return a list of all of the properties of EVENT.
2631 This is in the form of a property list (alternating keyword/value pairs).
2635 Lisp_Object props = Qnil;
2637 struct gcpro gcpro1;
2639 CHECK_LIVE_EVENT(event);
2643 props = cons3(Qtimestamp, Fevent_timestamp(event), props);
2645 switch (e->event_type) {
2650 props = cons3(Qprocess, e->event.process.process, props);
2654 props = cons3(Qobject, Fevent_object(event), props);
2655 props = cons3(Qfunction, Fevent_function(event), props);
2656 props = cons3(Qid, make_int(e->event.timeout.id_number), props);
2659 case key_press_event:
2660 props = cons3(Qmodifiers, Fevent_modifiers(event), props);
2661 props = cons3(Qkey, Fevent_key(event), props);
2664 case button_press_event:
2665 case button_release_event:
2666 props = cons3(Qy, Fevent_y_pixel(event), props);
2667 props = cons3(Qx, Fevent_x_pixel(event), props);
2668 props = cons3(Qmodifiers, Fevent_modifiers(event), props);
2669 props = cons3(Qbutton, Fevent_button(event), props);
2672 case pointer_motion_event:
2673 props = cons3(Qmodifiers, Fevent_modifiers(event), props);
2674 props = cons3(Qy, Fevent_y_pixel(event), props);
2675 props = cons3(Qx, Fevent_x_pixel(event), props);
2678 case misc_user_event:
2679 props = cons3(Qobject, Fevent_object(event), props);
2680 props = cons3(Qfunction, Fevent_function(event), props);
2681 props = cons3(Qy, Fevent_y_pixel(event), props);
2682 props = cons3(Qx, Fevent_x_pixel(event), props);
2683 props = cons3(Qmodifiers, Fevent_modifiers(event), props);
2684 props = cons3(Qbutton, Fevent_button(event), props);
2688 props = cons3(Qobject, Fevent_object(event), props);
2689 props = cons3(Qfunction, Fevent_function(event), props);
2692 #ifdef EF_USE_ASYNEQ
2693 /* are these right here? */
2694 case eaten_myself_event:
2695 case work_started_event:
2696 case work_finished_event:
2697 #endif /* EF_USE_ASYNEQ */
2700 case magic_eval_event:
2705 RETURN_UNGCPRO(Qnil);
2709 props = cons3(Qchannel, Fevent_channel(event), props);
2715 /************************************************************************/
2716 /* initialization */
2717 /************************************************************************/
2719 void syms_of_events(void)
2721 INIT_LRECORD_IMPLEMENTATION(event);
2723 DEFSUBR(Fcharacter_to_event);
2724 DEFSUBR(Fevent_to_character);
2726 DEFSUBR(Fmake_event);
2727 DEFSUBR(Fdeallocate_event);
2728 DEFSUBR(Fcopy_event);
2730 DEFSUBR(Fevent_live_p);
2731 DEFSUBR(Fevent_type);
2732 DEFSUBR(Fevent_properties);
2734 DEFSUBR(Fevent_timestamp);
2735 DEFSUBR(Fevent_timestamp_lessp);
2736 DEFSUBR(Fevent_key);
2737 DEFSUBR(Fevent_button);
2738 DEFSUBR(Fevent_modifier_bits);
2739 DEFSUBR(Fevent_modifiers);
2740 DEFSUBR(Fevent_x_pixel);
2741 DEFSUBR(Fevent_y_pixel);
2742 DEFSUBR(Fevent_window_x_pixel);
2743 DEFSUBR(Fevent_window_y_pixel);
2744 DEFSUBR(Fevent_over_text_area_p);
2745 DEFSUBR(Fevent_over_modeline_p);
2746 DEFSUBR(Fevent_over_border_p);
2747 DEFSUBR(Fevent_over_toolbar_p);
2748 DEFSUBR(Fevent_over_vertical_divider_p);
2749 DEFSUBR(Fevent_channel);
2750 DEFSUBR(Fevent_window);
2751 DEFSUBR(Fevent_point);
2752 DEFSUBR(Fevent_closest_point);
2755 DEFSUBR(Fevent_modeline_position);
2756 DEFSUBR(Fevent_glyph);
2757 DEFSUBR(Fevent_glyph_extent);
2758 DEFSUBR(Fevent_glyph_x_pixel);
2759 DEFSUBR(Fevent_glyph_y_pixel);
2760 DEFSUBR(Fevent_toolbar_button);
2761 DEFSUBR(Fevent_process);
2762 DEFSUBR(Fevent_function);
2763 DEFSUBR(Fevent_object);
2765 defsymbol(&Qeventp, "eventp");
2766 defsymbol(&Qevent_live_p, "event-live-p");
2767 defsymbol(&Qkey_press_event_p, "key-press-event-p");
2768 defsymbol(&Qbutton_event_p, "button-event-p");
2769 defsymbol(&Qmouse_event_p, "mouse-event-p");
2770 defsymbol(&Qprocess_event_p, "process-event-p");
2771 defsymbol(&Qkey_press, "key-press");
2772 defsymbol(&Qbutton_press, "button-press");
2773 defsymbol(&Qbutton_release, "button-release");
2774 defsymbol(&Qmisc_user, "misc-user");
2775 defsymbol(&Qascii_character, "ascii-character");
2777 defsymbol(&QKbackspace, "backspace");
2778 defsymbol(&QKtab, "tab");
2779 defsymbol(&QKlinefeed, "linefeed");
2780 defsymbol(&QKreturn, "return");
2781 defsymbol(&QKescape, "escape");
2782 defsymbol(&QKspace, "space");
2783 defsymbol(&QKdelete, "delete");
2786 void reinit_vars_of_events(void)
2788 init_Vevent_resource();
2791 void vars_of_events(void)
2793 reinit_vars_of_events();
2795 DEFVAR_LISP("character-set-property", &Vcharacter_set_property /*
2796 A symbol used to look up the 8-bit character of a keysym.
2797 To convert a keysym symbol to an 8-bit code, as when that key is
2798 bound to self-insert-command, we will look up the property that this
2799 variable names on the property list of the keysym-symbol. The window-
2800 system-specific code will set up appropriate properties and set this
2803 Vcharacter_set_property = Qnil;