comparison src/events.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children a5df635868b2
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
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.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* Synched up with: Not in FSF. */
23
24 /* This file has been Mule-ized. */
25
26 #include <config.h>
27 #include "lisp.h"
28 #include "buffer.h"
29 #include "console.h"
30 #include "console-tty.h" /* for stuff in character_to_event */
31 #include "device.h"
32 #include "console-x.h" /* for x_event_name prototype */
33 #include "extents.h" /* Just for the EXTENTP abort check... */
34 #include "events.h"
35 #include "frame.h"
36 #include "glyphs.h"
37 #include "keymap.h" /* for key_desc_list_to_event() */
38 #include "redisplay.h"
39 #include "window.h"
40
41 #ifdef WINDOWSNT
42 /* Hmm, under unix we want X modifiers, under NT we want X modifiers if
43 we are running X and Windows modifiers otherwise.
44 gak. This is a kludge until we support multiple native GUIs!
45 */
46 #undef MOD_ALT
47 #undef MOD_CONTROL
48 #undef MOD_SHIFT
49 #endif
50
51 #include "events-mod.h"
52
53 /* Where old events go when they are explicitly deallocated.
54 The event chain here is cut loose before GC, so these will be freed
55 eventually.
56 */
57 static Lisp_Object Vevent_resource;
58
59 Lisp_Object Qeventp;
60 Lisp_Object Qevent_live_p;
61 Lisp_Object Qkey_press_event_p;
62 Lisp_Object Qbutton_event_p;
63 Lisp_Object Qmouse_event_p;
64 Lisp_Object Qprocess_event_p;
65
66 Lisp_Object Qkey_press, Qbutton_press, Qbutton_release, Qmisc_user;
67 Lisp_Object Qascii_character;
68
69 EXFUN (Fevent_x_pixel, 1);
70 EXFUN (Fevent_y_pixel, 1);
71
72 /* #### Ad-hoc hack. Should be part of define_lrecord_implementation */
73 void
74 clear_event_resource (void)
75 {
76 Vevent_resource = Qnil;
77 }
78
79 /* Make sure we lose quickly if we try to use this event */
80 static void
81 deinitialize_event (Lisp_Object ev)
82 {
83 int i;
84 struct Lisp_Event *event = XEVENT (ev);
85
86 for (i = 0; i < (int) (sizeof (struct Lisp_Event) / sizeof (int)); i++)
87 ((int *) event) [i] = 0xdeadbeef;
88 event->event_type = dead_event;
89 event->channel = Qnil;
90 set_lheader_implementation (&(event->lheader), &lrecord_event);
91 XSET_EVENT_NEXT (ev, Qnil);
92 }
93
94 /* Set everything to zero or nil so that it's predictable. */
95 void
96 zero_event (struct Lisp_Event *e)
97 {
98 xzero (*e);
99 set_lheader_implementation (&(e->lheader), &lrecord_event);
100 e->event_type = empty_event;
101 e->next = Qnil;
102 e->channel = Qnil;
103 }
104
105 static Lisp_Object
106 mark_event (Lisp_Object obj)
107 {
108 struct Lisp_Event *event = XEVENT (obj);
109
110 switch (event->event_type)
111 {
112 case key_press_event:
113 mark_object (event->event.key.keysym);
114 break;
115 case process_event:
116 mark_object (event->event.process.process);
117 break;
118 case timeout_event:
119 mark_object (event->event.timeout.function);
120 mark_object (event->event.timeout.object);
121 break;
122 case eval_event:
123 case misc_user_event:
124 mark_object (event->event.eval.function);
125 mark_object (event->event.eval.object);
126 break;
127 case magic_eval_event:
128 mark_object (event->event.magic_eval.object);
129 break;
130 case button_press_event:
131 case button_release_event:
132 case pointer_motion_event:
133 case magic_event:
134 case empty_event:
135 case dead_event:
136 break;
137 default:
138 abort ();
139 }
140 mark_object (event->channel);
141 return event->next;
142 }
143
144 static void
145 print_event_1 (CONST char *str, Lisp_Object obj, Lisp_Object printcharfun)
146 {
147 char buf[255];
148 write_c_string (str, printcharfun);
149 format_event_object (buf, XEVENT (obj), 0);
150 write_c_string (buf, printcharfun);
151 }
152
153 static void
154 print_event (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
155 {
156 if (print_readably)
157 error ("Printing unreadable object #<event>");
158
159 switch (XEVENT (obj)->event_type)
160 {
161 case key_press_event:
162 print_event_1 ("#<keypress-event ", obj, printcharfun);
163 break;
164 case button_press_event:
165 print_event_1 ("#<buttondown-event ", obj, printcharfun);
166 break;
167 case button_release_event:
168 print_event_1 ("#<buttonup-event ", obj, printcharfun);
169 break;
170 case magic_event:
171 case magic_eval_event:
172 print_event_1 ("#<magic-event ", obj, printcharfun);
173 break;
174 case pointer_motion_event:
175 {
176 char buf[64];
177 Lisp_Object Vx, Vy;
178 Vx = Fevent_x_pixel (obj);
179 assert (INTP (Vx));
180 Vy = Fevent_y_pixel (obj);
181 assert (INTP (Vy));
182 sprintf (buf, "#<motion-event %ld, %ld", (long) XINT (Vx), (long) XINT (Vy));
183 write_c_string (buf, printcharfun);
184 break;
185 }
186 case process_event:
187 write_c_string ("#<process-event ", printcharfun);
188 print_internal (XEVENT (obj)->event.process.process, printcharfun, 1);
189 break;
190 case timeout_event:
191 write_c_string ("#<timeout-event ", printcharfun);
192 print_internal (XEVENT (obj)->event.timeout.object, printcharfun, 1);
193 break;
194 case empty_event:
195 write_c_string ("#<empty-event", printcharfun);
196 break;
197 case misc_user_event:
198 write_c_string ("#<misc-user-event (", printcharfun);
199 print_internal (XEVENT (obj)->event.misc.function, printcharfun, 1);
200 write_c_string (" ", printcharfun);
201 print_internal (XEVENT (obj)->event.misc.object, printcharfun, 1);
202 write_c_string (")", printcharfun);
203 break;
204 case eval_event:
205 write_c_string ("#<eval-event (", printcharfun);
206 print_internal (XEVENT (obj)->event.eval.function, printcharfun, 1);
207 write_c_string (" ", printcharfun);
208 print_internal (XEVENT (obj)->event.eval.object, printcharfun, 1);
209 write_c_string (")", printcharfun);
210 break;
211 case dead_event:
212 write_c_string ("#<DEALLOCATED-EVENT", printcharfun);
213 break;
214 default:
215 write_c_string ("#<UNKNOWN-EVENT-TYPE", printcharfun);
216 break;
217 }
218 write_c_string (">", printcharfun);
219 }
220
221 static int
222 event_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
223 {
224 struct Lisp_Event *e1 = XEVENT (obj1);
225 struct Lisp_Event *e2 = XEVENT (obj2);
226
227 if (e1->event_type != e2->event_type) return 0;
228 if (!EQ (e1->channel, e2->channel)) return 0;
229 /* if (e1->timestamp != e2->timestamp) return 0; */
230 switch (e1->event_type)
231 {
232 default: abort ();
233
234 case process_event:
235 return EQ (e1->event.process.process, e2->event.process.process);
236
237 case timeout_event:
238 return (internal_equal (e1->event.timeout.function,
239 e2->event.timeout.function, 0) &&
240 internal_equal (e1->event.timeout.object,
241 e2->event.timeout.object, 0));
242
243 case key_press_event:
244 return (EQ (e1->event.key.keysym, e2->event.key.keysym) &&
245 (e1->event.key.modifiers == e2->event.key.modifiers));
246
247 case button_press_event:
248 case button_release_event:
249 return (e1->event.button.button == e2->event.button.button &&
250 e1->event.button.modifiers == e2->event.button.modifiers);
251
252 case pointer_motion_event:
253 return (e1->event.motion.x == e2->event.motion.x &&
254 e1->event.motion.y == e2->event.motion.y);
255
256 case misc_user_event:
257 return (internal_equal (e1->event.eval.function,
258 e2->event.eval.function, 0) &&
259 internal_equal (e1->event.eval.object,
260 e2->event.eval.object, 0) &&
261 /* is this really needed for equality
262 or is x and y also important? */
263 e1->event.misc.button == e2->event.misc.button &&
264 e1->event.misc.modifiers == e2->event.misc.modifiers);
265
266 case eval_event:
267 return (internal_equal (e1->event.eval.function,
268 e2->event.eval.function, 0) &&
269 internal_equal (e1->event.eval.object,
270 e2->event.eval.object, 0));
271
272 case magic_eval_event:
273 return (e1->event.magic_eval.internal_function ==
274 e2->event.magic_eval.internal_function &&
275 internal_equal (e1->event.magic_eval.object,
276 e2->event.magic_eval.object, 0));
277
278 case magic_event:
279 {
280 struct console *con = XCONSOLE (CDFW_CONSOLE (e1->channel));
281
282 #ifdef HAVE_X_WINDOWS
283 if (CONSOLE_X_P (con))
284 return (e1->event.magic.underlying_x_event.xany.serial ==
285 e2->event.magic.underlying_x_event.xany.serial);
286 #endif
287 #ifdef HAVE_TTY
288 if (CONSOLE_TTY_P (con))
289 return (e1->event.magic.underlying_tty_event ==
290 e2->event.magic.underlying_tty_event);
291 #endif
292 #ifdef HAVE_MS_WINDOWS
293 if (CONSOLE_MSWINDOWS_P (con))
294 return (!memcmp(&e1->event.magic.underlying_mswindows_event,
295 &e2->event.magic.underlying_mswindows_event,
296 sizeof(union magic_data)));
297 #endif
298 return 1; /* not reached */
299 }
300
301 case empty_event: /* Empty and deallocated events are equal. */
302 case dead_event:
303 return 1;
304 }
305 }
306
307 static unsigned long
308 event_hash (Lisp_Object obj, int depth)
309 {
310 struct Lisp_Event *e = XEVENT (obj);
311 unsigned long hash;
312
313 hash = HASH2 (e->event_type, LISP_HASH (e->channel));
314 switch (e->event_type)
315 {
316 case process_event:
317 return HASH2 (hash, LISP_HASH (e->event.process.process));
318
319 case timeout_event:
320 return HASH3 (hash, internal_hash (e->event.timeout.function, depth + 1),
321 internal_hash (e->event.timeout.object, depth + 1));
322
323 case key_press_event:
324 return HASH3 (hash, LISP_HASH (e->event.key.keysym),
325 e->event.key.modifiers);
326
327 case button_press_event:
328 case button_release_event:
329 return HASH3 (hash, e->event.button.button, e->event.button.modifiers);
330
331 case pointer_motion_event:
332 return HASH3 (hash, e->event.motion.x, e->event.motion.y);
333
334 case misc_user_event:
335 return HASH5 (hash, internal_hash (e->event.misc.function, depth + 1),
336 internal_hash (e->event.misc.object, depth + 1),
337 e->event.misc.button, e->event.misc.modifiers);
338
339 case eval_event:
340 return HASH3 (hash, internal_hash (e->event.eval.function, depth + 1),
341 internal_hash (e->event.eval.object, depth + 1));
342
343 case magic_eval_event:
344 return HASH3 (hash,
345 (unsigned long) e->event.magic_eval.internal_function,
346 internal_hash (e->event.magic_eval.object, depth + 1));
347
348 case magic_event:
349 {
350 struct console *con = XCONSOLE (CDFW_CONSOLE (EVENT_CHANNEL (e)));
351 #ifdef HAVE_X_WINDOWS
352 if (CONSOLE_X_P (con))
353 return HASH2 (hash, e->event.magic.underlying_x_event.xany.serial);
354 #endif
355 #ifdef HAVE_TTY
356 if (CONSOLE_TTY_P (con))
357 return HASH2 (hash, e->event.magic.underlying_tty_event);
358 #endif
359 #ifdef HAVE_MS_WINDOWS
360 if (CONSOLE_MSWINDOWS_P (con))
361 return HASH2 (hash, e->event.magic.underlying_mswindows_event);
362 #endif
363 }
364
365 case empty_event:
366 case dead_event:
367 return hash;
368
369 default:
370 abort ();
371 }
372
373 return 0; /* unreached */
374 }
375
376 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("event", event,
377 mark_event, print_event, 0, event_equal,
378 event_hash, 0, struct Lisp_Event);
379
380
381 DEFUN ("make-event", Fmake_event, 0, 2, 0, /*
382 Return a new event of type TYPE, with properties described by PLIST.
383
384 TYPE is a symbol, either `empty', `key-press', `button-press',
385 `button-release', `misc-user' or `motion'. If TYPE is nil, it
386 defaults to `empty'.
387
388 PLIST is a property list, the properties being compatible to those
389 returned by `event-properties'. The following properties are
390 allowed:
391
392 channel -- The event channel, a frame or a console. For
393 button-press, button-release, misc-user and motion events,
394 this must be a frame. For key-press events, it must be
395 a console. If channel is unspecified, it will be set to
396 the selected frame or selected console, as appropriate.
397 key -- The event key, a symbol or character. Allowed only for
398 keypress events.
399 button -- The event button, integer 1, 2 or 3. Allowed for
400 button-press, button-release and misc-user events.
401 modifiers -- The event modifiers, a list of modifier symbols. Allowed
402 for key-press, button-press, button-release, motion and
403 misc-user events.
404 function -- Function. Allowed for misc-user events only.
405 object -- An object, function's parameter. Allowed for misc-user
406 events only.
407 x -- The event X coordinate, an integer. This is relative
408 to the left of CHANNEL's root window. Allowed for
409 motion, button-press, button-release and misc-user events.
410 y -- The event Y coordinate, an integer. This is relative
411 to the top of CHANNEL's root window. Allowed for
412 motion, button-press, button-release and misc-user events.
413 timestamp -- The event timestamp, a non-negative integer. Allowed for
414 all types of events. If unspecified, it will be set to 0
415 by default.
416
417 For event type `empty', PLIST must be nil.
418 `button-release', or `motion'. If TYPE is left out, it defaults to
419 `empty'.
420 PLIST is a list of properties, as returned by `event-properties'. Not
421 all properties are allowed for all kinds of events, and some are
422 required.
423
424 WARNING: the event object returned may be a reused one; see the function
425 `deallocate-event'.
426 */
427 (type, plist))
428 {
429 Lisp_Object tail, keyword, value;
430 Lisp_Object event = Qnil;
431 struct Lisp_Event *e;
432 EMACS_INT coord_x = 0, coord_y = 0;
433 struct gcpro gcpro1;
434
435 GCPRO1 (event);
436
437 if (NILP (type))
438 type = Qempty;
439
440 if (!NILP (Vevent_resource))
441 {
442 event = Vevent_resource;
443 Vevent_resource = XEVENT_NEXT (event);
444 }
445 else
446 {
447 event = allocate_event ();
448 }
449 e = XEVENT (event);
450 zero_event (e);
451
452 if (EQ (type, Qempty))
453 {
454 /* For empty event, we return immediately, without processing
455 PLIST. In fact, processing PLIST would be wrong, because the
456 sanitizing process would fill in the properties
457 (e.g. CHANNEL), which we don't want in empty events. */
458 e->event_type = empty_event;
459 if (!NILP (plist))
460 error ("Cannot set properties of empty event");
461 UNGCPRO;
462 return event;
463 }
464 else if (EQ (type, Qkey_press))
465 {
466 e->event_type = key_press_event;
467 e->event.key.keysym = Qunbound;
468 }
469 else if (EQ (type, Qbutton_press))
470 e->event_type = button_press_event;
471 else if (EQ (type, Qbutton_release))
472 e->event_type = button_release_event;
473 else if (EQ (type, Qmotion))
474 e->event_type = pointer_motion_event;
475 else if (EQ (type, Qmisc_user))
476 {
477 e->event_type = misc_user_event;
478 e->event.eval.function = e->event.eval.object = Qnil;
479 }
480 else
481 {
482 /* Not allowed: Qprocess, Qtimeout, Qmagic, Qeval, Qmagic_eval. */
483 signal_simple_error ("Invalid event type", type);
484 }
485
486 EVENT_CHANNEL (e) = Qnil;
487
488 plist = Fcopy_sequence (plist);
489 Fcanonicalize_plist (plist, Qnil);
490
491 #define WRONG_EVENT_TYPE_FOR_PROPERTY(type, prop) \
492 error_with_frob (prop, "Invalid property for %s event", \
493 string_data (symbol_name (XSYMBOL (type))))
494
495 EXTERNAL_PROPERTY_LIST_LOOP (tail, keyword, value, plist)
496 {
497 if (EQ (keyword, Qchannel))
498 {
499 if (e->event_type == key_press_event)
500 {
501 if (!CONSOLEP (value))
502 value = wrong_type_argument (Qconsolep, value);
503 }
504 else
505 {
506 if (!FRAMEP (value))
507 value = wrong_type_argument (Qframep, value);
508 }
509 EVENT_CHANNEL (e) = value;
510 }
511 else if (EQ (keyword, Qkey))
512 {
513 switch (e->event_type)
514 {
515 case key_press_event:
516 if (!SYMBOLP (value) && !CHARP (value))
517 signal_simple_error ("Invalid event key", value);
518 e->event.key.keysym = value;
519 break;
520 default:
521 WRONG_EVENT_TYPE_FOR_PROPERTY (type, keyword);
522 break;
523 }
524 }
525 else if (EQ (keyword, Qbutton))
526 {
527 CHECK_NATNUM (value);
528 check_int_range (XINT (value), 0, 7);
529
530 switch (e->event_type)
531 {
532 case button_press_event:
533 case button_release_event:
534 e->event.button.button = XINT (value);
535 break;
536 case misc_user_event:
537 e->event.misc.button = XINT (value);
538 break;
539 default:
540 WRONG_EVENT_TYPE_FOR_PROPERTY (type, keyword);
541 break;
542 }
543 }
544 else if (EQ (keyword, Qmodifiers))
545 {
546 int modifiers = 0;
547 Lisp_Object sym;
548
549 EXTERNAL_LIST_LOOP_2 (sym, value)
550 {
551 if (EQ (sym, Qcontrol)) modifiers |= MOD_CONTROL;
552 else if (EQ (sym, Qmeta)) modifiers |= MOD_META;
553 else if (EQ (sym, Qsuper)) modifiers |= MOD_SUPER;
554 else if (EQ (sym, Qhyper)) modifiers |= MOD_HYPER;
555 else if (EQ (sym, Qalt)) modifiers |= MOD_ALT;
556 else if (EQ (sym, Qsymbol)) modifiers |= MOD_ALT;
557 else if (EQ (sym, Qshift)) modifiers |= MOD_SHIFT;
558 else
559 signal_simple_error ("Invalid key modifier", sym);
560 }
561
562 switch (e->event_type)
563 {
564 case key_press_event:
565 e->event.key.modifiers = modifiers;
566 break;
567 case button_press_event:
568 case button_release_event:
569 e->event.button.modifiers = modifiers;
570 break;
571 case pointer_motion_event:
572 e->event.motion.modifiers = modifiers;
573 break;
574 case misc_user_event:
575 e->event.misc.modifiers = modifiers;
576 break;
577 default:
578 WRONG_EVENT_TYPE_FOR_PROPERTY (type, keyword);
579 break;
580 }
581 }
582 else if (EQ (keyword, Qx))
583 {
584 switch (e->event_type)
585 {
586 case pointer_motion_event:
587 case button_press_event:
588 case button_release_event:
589 case misc_user_event:
590 /* Allow negative values, so we can specify toolbar
591 positions. */
592 CHECK_INT (value);
593 coord_x = XINT (value);
594 break;
595 default:
596 WRONG_EVENT_TYPE_FOR_PROPERTY (type, keyword);
597 break;
598 }
599 }
600 else if (EQ (keyword, Qy))
601 {
602 switch (e->event_type)
603 {
604 case pointer_motion_event:
605 case button_press_event:
606 case button_release_event:
607 case misc_user_event:
608 /* Allow negative values; see above. */
609 CHECK_INT (value);
610 coord_y = XINT (value);
611 break;
612 default:
613 WRONG_EVENT_TYPE_FOR_PROPERTY (type, keyword);
614 break;
615 }
616 }
617 else if (EQ (keyword, Qtimestamp))
618 {
619 CHECK_NATNUM (value);
620 e->timestamp = XINT (value);
621 }
622 else if (EQ (keyword, Qfunction))
623 {
624 switch (e->event_type)
625 {
626 case misc_user_event:
627 e->event.eval.function = value;
628 break;
629 default:
630 WRONG_EVENT_TYPE_FOR_PROPERTY (type, keyword);
631 break;
632 }
633 }
634 else if (EQ (keyword, Qobject))
635 {
636 switch (e->event_type)
637 {
638 case misc_user_event:
639 e->event.eval.object = value;
640 break;
641 default:
642 WRONG_EVENT_TYPE_FOR_PROPERTY (type, keyword);
643 break;
644 }
645 }
646 else
647 signal_simple_error_2 ("Invalid property", keyword, value);
648 }
649
650 /* Insert the channel, if missing. */
651 if (NILP (EVENT_CHANNEL (e)))
652 {
653 if (e->event_type == key_press_event)
654 EVENT_CHANNEL (e) = Vselected_console;
655 else
656 EVENT_CHANNEL (e) = Fselected_frame (Qnil);
657 }
658
659 /* Fevent_properties, Fevent_x_pixel, etc. work with pixels relative
660 to the frame, so we must adjust accordingly. */
661 if (FRAMEP (EVENT_CHANNEL (e)))
662 {
663 coord_x += FRAME_REAL_LEFT_TOOLBAR_WIDTH (XFRAME (EVENT_CHANNEL (e)));
664 coord_y += FRAME_REAL_TOP_TOOLBAR_HEIGHT (XFRAME (EVENT_CHANNEL (e)));
665
666 switch (e->event_type)
667 {
668 case pointer_motion_event:
669 e->event.motion.x = coord_x;
670 e->event.motion.y = coord_y;
671 break;
672 case button_press_event:
673 case button_release_event:
674 e->event.button.x = coord_x;
675 e->event.button.y = coord_y;
676 break;
677 case misc_user_event:
678 e->event.misc.x = coord_x;
679 e->event.misc.y = coord_y;
680 break;
681 default:
682 abort();
683 }
684 }
685
686 /* Finally, do some more validation. */
687 switch (e->event_type)
688 {
689 case key_press_event:
690 if (UNBOUNDP (e->event.key.keysym))
691 error ("A key must be specified to make a keypress event");
692 break;
693 case button_press_event:
694 if (!e->event.button.button)
695 error ("A button must be specified to make a button-press event");
696 break;
697 case button_release_event:
698 if (!e->event.button.button)
699 error ("A button must be specified to make a button-release event");
700 break;
701 case misc_user_event:
702 if (NILP (e->event.misc.function))
703 error ("A function must be specified to make a misc-user event");
704 break;
705 default:
706 break;
707 }
708
709 UNGCPRO;
710 return event;
711 }
712
713 DEFUN ("deallocate-event", Fdeallocate_event, 1, 1, 0, /*
714 Allow the given event structure to be reused.
715 You MUST NOT use this event object after calling this function with it.
716 You will lose. It is not necessary to call this function, as event
717 objects are garbage-collected like all other objects; however, it may
718 be more efficient to explicitly deallocate events when you are sure
719 that it is safe to do so.
720 */
721 (event))
722 {
723 CHECK_EVENT (event);
724
725 if (XEVENT_TYPE (event) == dead_event)
726 error ("this event is already deallocated!");
727
728 assert (XEVENT_TYPE (event) <= last_event_type);
729
730 #if 0
731 {
732 int i, len;
733
734 if (EQ (event, Vlast_command_event) ||
735 EQ (event, Vlast_input_event) ||
736 EQ (event, Vunread_command_event))
737 abort ();
738
739 len = XVECTOR_LENGTH (Vthis_command_keys);
740 for (i = 0; i < len; i++)
741 if (EQ (event, XVECTOR_DATA (Vthis_command_keys) [i]))
742 abort ();
743 if (!NILP (Vrecent_keys_ring))
744 {
745 int recent_ring_len = XVECTOR_LENGTH (Vrecent_keys_ring);
746 for (i = 0; i < recent_ring_len; i++)
747 if (EQ (event, XVECTOR_DATA (Vrecent_keys_ring) [i]))
748 abort ();
749 }
750 }
751 #endif /* 0 */
752
753 assert (!EQ (event, Vevent_resource));
754 deinitialize_event (event);
755 #ifndef ALLOC_NO_POOLS
756 XSET_EVENT_NEXT (event, Vevent_resource);
757 Vevent_resource = event;
758 #endif
759 return Qnil;
760 }
761
762 DEFUN ("copy-event", Fcopy_event, 1, 2, 0, /*
763 Make a copy of the given event object.
764 If a second argument is given, the first event is copied into the second
765 and the second is returned. If the second argument is not supplied (or
766 is nil) then a new event will be made as with `allocate-event.' See also
767 the function `deallocate-event'.
768 */
769 (event1, event2))
770 {
771 CHECK_LIVE_EVENT (event1);
772 if (NILP (event2))
773 event2 = Fmake_event (Qnil, Qnil);
774 else CHECK_LIVE_EVENT (event2);
775 if (EQ (event1, event2))
776 return signal_simple_continuable_error_2
777 ("copy-event called with `eq' events", event1, event2);
778
779 assert (XEVENT_TYPE (event1) <= last_event_type);
780 assert (XEVENT_TYPE (event2) <= last_event_type);
781
782 {
783 Lisp_Object save_next = XEVENT_NEXT (event2);
784
785 *XEVENT (event2) = *XEVENT (event1);
786 XSET_EVENT_NEXT (event2, save_next);
787 return event2;
788 }
789 }
790
791
792
793 /* Given a chain of events (or possibly nil), deallocate them all. */
794
795 void
796 deallocate_event_chain (Lisp_Object event_chain)
797 {
798 while (!NILP (event_chain))
799 {
800 Lisp_Object next = XEVENT_NEXT (event_chain);
801 Fdeallocate_event (event_chain);
802 event_chain = next;
803 }
804 }
805
806 /* Return the last event in a chain.
807 NOTE: You cannot pass nil as a value here! The routine will
808 abort if you do. */
809
810 Lisp_Object
811 event_chain_tail (Lisp_Object event_chain)
812 {
813 while (1)
814 {
815 Lisp_Object next = XEVENT_NEXT (event_chain);
816 if (NILP (next))
817 return event_chain;
818 event_chain = next;
819 }
820 }
821
822 /* Enqueue a single event onto the end of a chain of events.
823 HEAD points to the first event in the chain, TAIL to the last event.
824 If the chain is empty, both values should be nil. */
825
826 void
827 enqueue_event (Lisp_Object event, Lisp_Object *head, Lisp_Object *tail)
828 {
829 assert (NILP (XEVENT_NEXT (event)));
830 assert (!EQ (*tail, event));
831
832 if (!NILP (*tail))
833 XSET_EVENT_NEXT (*tail, event);
834 else
835 *head = event;
836 *tail = event;
837
838 assert (!EQ (event, XEVENT_NEXT (event)));
839 }
840
841 /* Remove an event off the head of a chain of events and return it.
842 HEAD points to the first event in the chain, TAIL to the last event. */
843
844 Lisp_Object
845 dequeue_event (Lisp_Object *head, Lisp_Object *tail)
846 {
847 Lisp_Object event;
848
849 event = *head;
850 *head = XEVENT_NEXT (event);
851 XSET_EVENT_NEXT (event, Qnil);
852 if (NILP (*head))
853 *tail = Qnil;
854 return event;
855 }
856
857 /* Enqueue a chain of events (or possibly nil) onto the end of another
858 chain of events. HEAD points to the first event in the chain being
859 queued onto, TAIL to the last event. If the chain is empty, both values
860 should be nil. */
861
862 void
863 enqueue_event_chain (Lisp_Object event_chain, Lisp_Object *head,
864 Lisp_Object *tail)
865 {
866 if (NILP (event_chain))
867 return;
868
869 if (NILP (*head))
870 {
871 *head = event_chain;
872 *tail = event_chain;
873 }
874 else
875 {
876 XSET_EVENT_NEXT (*tail, event_chain);
877 *tail = event_chain_tail (event_chain);
878 }
879 }
880
881 /* Return the number of events (possibly 0) on an event chain. */
882
883 int
884 event_chain_count (Lisp_Object event_chain)
885 {
886 Lisp_Object event;
887 int n = 0;
888
889 EVENT_CHAIN_LOOP (event, event_chain)
890 n++;
891
892 return n;
893 }
894
895 /* Find the event before EVENT in an event chain. This aborts
896 if the event is not in the chain. */
897
898 Lisp_Object
899 event_chain_find_previous (Lisp_Object event_chain, Lisp_Object event)
900 {
901 Lisp_Object previous = Qnil;
902
903 while (!NILP (event_chain))
904 {
905 if (EQ (event_chain, event))
906 return previous;
907 previous = event_chain;
908 event_chain = XEVENT_NEXT (event_chain);
909 }
910
911 abort ();
912 return Qnil;
913 }
914
915 Lisp_Object
916 event_chain_nth (Lisp_Object event_chain, int n)
917 {
918 Lisp_Object event;
919 EVENT_CHAIN_LOOP (event, event_chain)
920 {
921 if (!n)
922 return event;
923 n--;
924 }
925 return Qnil;
926 }
927
928 Lisp_Object
929 copy_event_chain (Lisp_Object event_chain)
930 {
931 Lisp_Object new_chain = Qnil;
932 Lisp_Object new_chain_tail = Qnil;
933 Lisp_Object event;
934
935 EVENT_CHAIN_LOOP (event, event_chain)
936 {
937 Lisp_Object copy = Fcopy_event (event, Qnil);
938 enqueue_event (copy, &new_chain, &new_chain_tail);
939 }
940
941 return new_chain;
942 }
943
944
945
946 Lisp_Object QKbackspace, QKtab, QKlinefeed, QKreturn, QKescape,
947 QKspace, QKdelete;
948
949 int
950 command_event_p (Lisp_Object event)
951 {
952 switch (XEVENT_TYPE (event))
953 {
954 case key_press_event:
955 case button_press_event:
956 case button_release_event:
957 case misc_user_event:
958 return 1;
959 default:
960 return 0;
961 }
962 }
963
964
965 void
966 character_to_event (Emchar c, struct Lisp_Event *event, struct console *con,
967 int use_console_meta_flag, int do_backspace_mapping)
968 {
969 Lisp_Object k = Qnil;
970 unsigned int m = 0;
971 if (event->event_type == dead_event)
972 error ("character-to-event called with a deallocated event!");
973
974 #ifndef MULE
975 c &= 255;
976 #endif
977 if (c > 127 && c <= 255)
978 {
979 int meta_flag = 1;
980 if (use_console_meta_flag && CONSOLE_TTY_P (con))
981 meta_flag = TTY_FLAGS (con).meta_key;
982 switch (meta_flag)
983 {
984 case 0: /* ignore top bit; it's parity */
985 c -= 128;
986 break;
987 case 1: /* top bit is meta */
988 c -= 128;
989 m = MOD_META;
990 break;
991 default: /* this is a real character */
992 break;
993 }
994 }
995 if (c < ' ') c += '@', m |= MOD_CONTROL;
996 if (m & MOD_CONTROL)
997 {
998 switch (c)
999 {
1000 case 'I': k = QKtab; m &= ~MOD_CONTROL; break;
1001 case 'J': k = QKlinefeed; m &= ~MOD_CONTROL; break;
1002 case 'M': k = QKreturn; m &= ~MOD_CONTROL; break;
1003 case '[': k = QKescape; m &= ~MOD_CONTROL; break;
1004 default:
1005 #if defined(HAVE_TTY)
1006 if (do_backspace_mapping &&
1007 CHARP (con->tty_erase_char) &&
1008 c - '@' == XCHAR (con->tty_erase_char))
1009 {
1010 k = QKbackspace;
1011 m &= ~MOD_CONTROL;
1012 }
1013 #endif /* defined(HAVE_TTY) && !defined(__CYGWIN32__) */
1014 break;
1015 }
1016 if (c >= 'A' && c <= 'Z') c -= 'A'-'a';
1017 }
1018 #if defined(HAVE_TTY)
1019 else if (do_backspace_mapping &&
1020 CHARP (con->tty_erase_char) && c == XCHAR (con->tty_erase_char))
1021 k = QKbackspace;
1022 #endif /* defined(HAVE_TTY) && !defined(__CYGWIN32__) */
1023 else if (c == 127)
1024 k = QKdelete;
1025 else if (c == ' ')
1026 k = QKspace;
1027
1028 event->event_type = key_press_event;
1029 event->timestamp = 0; /* #### */
1030 event->channel = make_console (con);
1031 event->event.key.keysym = (!NILP (k) ? k : make_char (c));
1032 event->event.key.modifiers = m;
1033 }
1034
1035
1036 /* This variable controls what character name -> character code mapping
1037 we are using. Window-system-specific code sets this to some symbol,
1038 and we use that symbol as the plist key to convert keysyms into 8-bit
1039 codes. In this way one can have several character sets predefined and
1040 switch them by changing this.
1041 */
1042 Lisp_Object Vcharacter_set_property;
1043
1044 Emchar
1045 event_to_character (struct Lisp_Event *event,
1046 int allow_extra_modifiers,
1047 int allow_meta,
1048 int allow_non_ascii)
1049 {
1050 Emchar c = 0;
1051 Lisp_Object code;
1052
1053 if (event->event_type != key_press_event)
1054 {
1055 if (event->event_type == dead_event) abort ();
1056 return -1;
1057 }
1058 if (!allow_extra_modifiers &&
1059 event->event.key.modifiers & (MOD_SUPER|MOD_HYPER|MOD_ALT))
1060 return -1;
1061 if (CHAR_OR_CHAR_INTP (event->event.key.keysym))
1062 c = XCHAR_OR_CHAR_INT (event->event.key.keysym);
1063 else if (!SYMBOLP (event->event.key.keysym))
1064 abort ();
1065 else if (allow_non_ascii && !NILP (Vcharacter_set_property)
1066 /* Allow window-system-specific extensibility of
1067 keysym->code mapping */
1068 && CHAR_OR_CHAR_INTP (code = Fget (event->event.key.keysym,
1069 Vcharacter_set_property,
1070 Qnil)))
1071 c = XCHAR_OR_CHAR_INT (code);
1072 else if (CHAR_OR_CHAR_INTP (code = Fget (event->event.key.keysym,
1073 Qascii_character, Qnil)))
1074 c = XCHAR_OR_CHAR_INT (code);
1075 else
1076 return -1;
1077
1078 if (event->event.key.modifiers & MOD_CONTROL)
1079 {
1080 if (c >= 'a' && c <= 'z')
1081 c -= ('a' - 'A');
1082 else
1083 /* reject Control-Shift- keys */
1084 if (c >= 'A' && c <= 'Z' && !allow_extra_modifiers)
1085 return -1;
1086
1087 if (c >= '@' && c <= '_')
1088 c -= '@';
1089 else if (c == ' ') /* C-space and C-@ are the same. */
1090 c = 0;
1091 else
1092 /* reject keys that can't take Control- modifiers */
1093 if (! allow_extra_modifiers) return -1;
1094 }
1095
1096 if (event->event.key.modifiers & MOD_META)
1097 {
1098 if (! allow_meta) return -1;
1099 if (c & 0200) return -1; /* don't allow M-oslash (overlap) */
1100 #ifdef MULE
1101 if (c >= 256) return -1;
1102 #endif
1103 c |= 0200;
1104 }
1105 return c;
1106 }
1107
1108 DEFUN ("event-to-character", Fevent_to_character, 1, 4, 0, /*
1109 Return the closest ASCII approximation to the given event object.
1110 If the event isn't a keypress, this returns nil.
1111 If the ALLOW-EXTRA-MODIFIERS argument is non-nil, then this is lenient in
1112 its translation; it will ignore modifier keys other than control and meta,
1113 and will ignore the shift modifier on those characters which have no
1114 shifted ASCII equivalent (Control-Shift-A for example, will be mapped to
1115 the same ASCII code as Control-A).
1116 If the ALLOW-META argument is non-nil, then the Meta modifier will be
1117 represented by turning on the high bit of the byte returned; otherwise, nil
1118 will be returned for events containing the Meta modifier.
1119 If the ALLOW-NON-ASCII argument is non-nil, then characters which are
1120 present in the prevailing character set (see the `character-set-property'
1121 variable) will be returned as their code in that character set, instead of
1122 the return value being restricted to ASCII.
1123 Note that specifying both ALLOW-META and ALLOW-NON-ASCII is ambiguous, as
1124 both use the high bit; `M-x' and `oslash' will be indistinguishable.
1125 */
1126 (event, allow_extra_modifiers, allow_meta, allow_non_ascii))
1127 {
1128 Emchar c;
1129 CHECK_LIVE_EVENT (event);
1130 c = event_to_character (XEVENT (event),
1131 !NILP (allow_extra_modifiers),
1132 !NILP (allow_meta),
1133 !NILP (allow_non_ascii));
1134 return c < 0 ? Qnil : make_char (c);
1135 }
1136
1137 DEFUN ("character-to-event", Fcharacter_to_event, 1, 4, 0, /*
1138 Convert keystroke CH into an event structure ,replete with bucky bits.
1139 The keystroke is the first argument, and the event to fill
1140 in is the second. This function contains knowledge about what the codes
1141 ``mean'' -- for example, the number 9 is converted to the character ``Tab'',
1142 not the distinct character ``Control-I''.
1143
1144 Note that CH (the keystroke specifier) can be an integer, a character,
1145 a symbol such as 'clear, or a list such as '(control backspace).
1146
1147 If the optional second argument is an event, it is modified;
1148 otherwise, a new event object is created.
1149
1150 Optional third arg CONSOLE is the console to store in the event, and
1151 defaults to the selected console.
1152
1153 If CH is an integer or character, the high bit may be interpreted as the
1154 meta key. (This is done for backward compatibility in lots of places.)
1155 If USE-CONSOLE-META-FLAG is nil, this will always be the case. If
1156 USE-CONSOLE-META-FLAG is non-nil, the `meta' flag for CONSOLE affects
1157 whether the high bit is interpreted as a meta key. (See `set-input-mode'.)
1158 If you don't want this silly meta interpretation done, you should pass
1159 in a list containing the character.
1160
1161 Beware that character-to-event and event-to-character are not strictly
1162 inverse functions, since events contain much more information than the
1163 ASCII character set can encode.
1164 */
1165 (ch, event, console, use_console_meta_flag))
1166 {
1167 struct console *con = decode_console (console);
1168 if (NILP (event))
1169 event = Fmake_event (Qnil, Qnil);
1170 else
1171 CHECK_LIVE_EVENT (event);
1172 if (CONSP (ch) || SYMBOLP (ch))
1173 key_desc_list_to_event (ch, event, 1);
1174 else
1175 {
1176 CHECK_CHAR_COERCE_INT (ch);
1177 character_to_event (XCHAR (ch), XEVENT (event), con,
1178 !NILP (use_console_meta_flag), 1);
1179 }
1180 return event;
1181 }
1182
1183 void
1184 nth_of_key_sequence_as_event (Lisp_Object seq, int n, Lisp_Object event)
1185 {
1186 assert (STRINGP (seq) || VECTORP (seq));
1187 assert (n < XINT (Flength (seq)));
1188
1189 if (STRINGP (seq))
1190 {
1191 Emchar ch = string_char (XSTRING (seq), n);
1192 Fcharacter_to_event (make_char (ch), event, Qnil, Qnil);
1193 }
1194 else
1195 {
1196 Lisp_Object keystroke = XVECTOR_DATA (seq)[n];
1197 if (EVENTP (keystroke))
1198 Fcopy_event (keystroke, event);
1199 else
1200 Fcharacter_to_event (keystroke, event, Qnil, Qnil);
1201 }
1202 }
1203
1204 Lisp_Object
1205 key_sequence_to_event_chain (Lisp_Object seq)
1206 {
1207 int len = XINT (Flength (seq));
1208 int i;
1209 Lisp_Object head = Qnil, tail = Qnil;
1210
1211 for (i = 0; i < len; i++)
1212 {
1213 Lisp_Object event = Fmake_event (Qnil, Qnil);
1214 nth_of_key_sequence_as_event (seq, i, event);
1215 enqueue_event (event, &head, &tail);
1216 }
1217
1218 return head;
1219 }
1220
1221 void
1222 format_event_object (char *buf, struct Lisp_Event *event, int brief)
1223 {
1224 int mouse_p = 0;
1225 int mod = 0;
1226 Lisp_Object key;
1227
1228 switch (event->event_type)
1229 {
1230 case key_press_event:
1231 {
1232 mod = event->event.key.modifiers;
1233 key = event->event.key.keysym;
1234 /* Hack. */
1235 if (! brief && CHARP (key) &&
1236 mod & (MOD_CONTROL | MOD_META | MOD_SUPER | MOD_HYPER))
1237 {
1238 int k = XCHAR (key);
1239 if (k >= 'a' && k <= 'z')
1240 key = make_char (k - ('a' - 'A'));
1241 else if (k >= 'A' && k <= 'Z')
1242 mod |= MOD_SHIFT;
1243 }
1244 break;
1245 }
1246 case button_release_event:
1247 mouse_p++;
1248 /* Fall through */
1249 case button_press_event:
1250 {
1251 mouse_p++;
1252 mod = event->event.button.modifiers;
1253 key = make_char (event->event.button.button + '0');
1254 break;
1255 }
1256 case magic_event:
1257 {
1258 CONST char *name = NULL;
1259
1260 #ifdef HAVE_X_WINDOWS
1261 {
1262 Lisp_Object console = CDFW_CONSOLE (EVENT_CHANNEL (event));
1263 if (CONSOLE_X_P (XCONSOLE (console)))
1264 name = x_event_name (event->event.magic.underlying_x_event.type);
1265 }
1266 #endif /* HAVE_X_WINDOWS */
1267 if (name) strcpy (buf, name);
1268 else strcpy (buf, "???");
1269 return;
1270 }
1271 case magic_eval_event: strcpy (buf, "magic-eval"); return;
1272 case pointer_motion_event: strcpy (buf, "motion"); return;
1273 case misc_user_event: strcpy (buf, "misc-user"); return;
1274 case eval_event: strcpy (buf, "eval"); return;
1275 case process_event: strcpy (buf, "process"); return;
1276 case timeout_event: strcpy (buf, "timeout"); return;
1277 case empty_event: strcpy (buf, "empty"); return;
1278 case dead_event: strcpy (buf, "DEAD-EVENT"); return;
1279 default:
1280 abort ();
1281 }
1282 #define modprint1(x) do { strcpy (buf, (x)); buf += sizeof (x)-1; } while (0)
1283 #define modprint(x,y) do { if (brief) modprint1 (y); else modprint1 (x); } while (0)
1284 if (mod & MOD_CONTROL) modprint ("control-", "C-");
1285 if (mod & MOD_META) modprint ("meta-", "M-");
1286 if (mod & MOD_SUPER) modprint ("super-", "S-");
1287 if (mod & MOD_HYPER) modprint ("hyper-", "H-");
1288 if (mod & MOD_ALT) modprint ("alt-", "A-");
1289 if (mod & MOD_SHIFT) modprint ("shift-", "Sh-");
1290 if (mouse_p)
1291 {
1292 modprint1 ("button");
1293 --mouse_p;
1294 }
1295
1296 #undef modprint
1297 #undef modprint1
1298
1299 if (CHARP (key))
1300 {
1301 buf += set_charptr_emchar ((Bufbyte *) buf, XCHAR (key));
1302 *buf = 0;
1303 }
1304 else if (SYMBOLP (key))
1305 {
1306 CONST char *str = 0;
1307 if (brief)
1308 {
1309 if (EQ (key, QKlinefeed)) str = "LFD";
1310 else if (EQ (key, QKtab)) str = "TAB";
1311 else if (EQ (key, QKreturn)) str = "RET";
1312 else if (EQ (key, QKescape)) str = "ESC";
1313 else if (EQ (key, QKdelete)) str = "DEL";
1314 else if (EQ (key, QKspace)) str = "SPC";
1315 else if (EQ (key, QKbackspace)) str = "BS";
1316 }
1317 if (str)
1318 {
1319 int i = strlen (str);
1320 memcpy (buf, str, i+1);
1321 str += i;
1322 }
1323 else
1324 {
1325 struct Lisp_String *name = XSYMBOL (key)->name;
1326 memcpy (buf, string_data (name), string_length (name) + 1);
1327 str += string_length (name);
1328 }
1329 }
1330 else
1331 abort ();
1332 if (mouse_p)
1333 strncpy (buf, "up", 4);
1334 }
1335
1336 DEFUN ("eventp", Feventp, 1, 1, 0, /*
1337 True if OBJECT is an event object.
1338 */
1339 (object))
1340 {
1341 return EVENTP (object) ? Qt : Qnil;
1342 }
1343
1344 DEFUN ("event-live-p", Fevent_live_p, 1, 1, 0, /*
1345 True if OBJECT is an event object that has not been deallocated.
1346 */
1347 (object))
1348 {
1349 return EVENTP (object) && XEVENT (object)->event_type != dead_event ?
1350 Qt : Qnil;
1351 }
1352
1353 #if 0 /* debugging functions */
1354
1355 xxDEFUN ("event-next", Fevent_next, 1, 1, 0, /*
1356 Return the event object's `next' event, or nil if it has none.
1357 The `next-event' field is changed by calling `set-next-event'.
1358 */
1359 (event))
1360 {
1361 struct Lisp_Event *e;
1362 CHECK_LIVE_EVENT (event);
1363
1364 return XEVENT_NEXT (event);
1365 }
1366
1367 xxDEFUN ("set-event-next", Fset_event_next, 2, 2, 0, /*
1368 Set the `next event' of EVENT to NEXT-EVENT.
1369 NEXT-EVENT must be an event object or nil.
1370 */
1371 (event, next_event))
1372 {
1373 Lisp_Object ev;
1374
1375 CHECK_LIVE_EVENT (event);
1376 if (NILP (next_event))
1377 {
1378 XSET_EVENT_NEXT (event, Qnil);
1379 return Qnil;
1380 }
1381
1382 CHECK_LIVE_EVENT (next_event);
1383
1384 EVENT_CHAIN_LOOP (ev, XEVENT_NEXT (event))
1385 {
1386 QUIT;
1387 if (EQ (ev, event))
1388 signal_error (Qerror,
1389 list3 (build_string ("Cyclic event-next"),
1390 event,
1391 next_event));
1392 }
1393 XSET_EVENT_NEXT (event, next_event);
1394 return next_event;
1395 }
1396
1397 #endif /* 0 */
1398
1399 DEFUN ("event-type", Fevent_type, 1, 1, 0, /*
1400 Return the type of EVENT.
1401 This will be a symbol; one of
1402
1403 key-press A key was pressed.
1404 button-press A mouse button was pressed.
1405 button-release A mouse button was released.
1406 misc-user Some other user action happened; typically, this is
1407 a menu selection or scrollbar action.
1408 motion The mouse moved.
1409 process Input is available from a subprocess.
1410 timeout A timeout has expired.
1411 eval This causes a specified action to occur when dispatched.
1412 magic Some window-system-specific event has occurred.
1413 empty The event has been allocated but not assigned.
1414
1415 */
1416 (event))
1417 {
1418 CHECK_LIVE_EVENT (event);
1419 switch (XEVENT (event)->event_type)
1420 {
1421 case key_press_event: return Qkey_press;
1422 case button_press_event: return Qbutton_press;
1423 case button_release_event: return Qbutton_release;
1424 case misc_user_event: return Qmisc_user;
1425 case pointer_motion_event: return Qmotion;
1426 case process_event: return Qprocess;
1427 case timeout_event: return Qtimeout;
1428 case eval_event: return Qeval;
1429 case magic_event:
1430 case magic_eval_event:
1431 return Qmagic;
1432
1433 case empty_event:
1434 return Qempty;
1435
1436 default:
1437 abort ();
1438 return Qnil;
1439 }
1440 }
1441
1442 DEFUN ("event-timestamp", Fevent_timestamp, 1, 1, 0, /*
1443 Return the timestamp of the event object EVENT.
1444 */
1445 (event))
1446 {
1447 CHECK_LIVE_EVENT (event);
1448 /* This junk is so that timestamps don't get to be negative, but contain
1449 as many bits as this particular emacs will allow.
1450 */
1451 return make_int (((1L << (VALBITS - 1)) - 1) &
1452 XEVENT (event)->timestamp);
1453 }
1454
1455 #define CHECK_EVENT_TYPE(e,t1,sym) do { \
1456 CHECK_LIVE_EVENT (e); \
1457 if (XEVENT(e)->event_type != (t1)) \
1458 e = wrong_type_argument (sym,e); \
1459 } while (0)
1460
1461 #define CHECK_EVENT_TYPE2(e,t1,t2,sym) do { \
1462 CHECK_LIVE_EVENT (e); \
1463 { \
1464 emacs_event_type CET_type = XEVENT (e)->event_type; \
1465 if (CET_type != (t1) && \
1466 CET_type != (t2)) \
1467 e = wrong_type_argument (sym,e); \
1468 } \
1469 } while (0)
1470
1471 #define CHECK_EVENT_TYPE3(e,t1,t2,t3,sym) do { \
1472 CHECK_LIVE_EVENT (e); \
1473 { \
1474 emacs_event_type CET_type = XEVENT (e)->event_type; \
1475 if (CET_type != (t1) && \
1476 CET_type != (t2) && \
1477 CET_type != (t3)) \
1478 e = wrong_type_argument (sym,e); \
1479 } \
1480 } while (0)
1481
1482 DEFUN ("event-key", Fevent_key, 1, 1, 0, /*
1483 Return the Keysym of the key-press event EVENT.
1484 This will be a character if the event is associated with one, else a symbol.
1485 */
1486 (event))
1487 {
1488 CHECK_EVENT_TYPE (event, key_press_event, Qkey_press_event_p);
1489 return XEVENT (event)->event.key.keysym;
1490 }
1491
1492 DEFUN ("event-button", Fevent_button, 1, 1, 0, /*
1493 Return the button-number of the given button-press or button-release event.
1494 */
1495 (event))
1496 {
1497
1498 CHECK_EVENT_TYPE3 (event, button_press_event, button_release_event,
1499 misc_user_event, Qbutton_event_p);
1500 #ifdef HAVE_WINDOW_SYSTEM
1501 if ( XEVENT (event)->event_type == misc_user_event)
1502 return make_int (XEVENT (event)->event.misc.button);
1503 else
1504 return make_int (XEVENT (event)->event.button.button);
1505 #else /* !HAVE_WINDOW_SYSTEM */
1506 return Qzero;
1507 #endif /* !HAVE_WINDOW_SYSTEM */
1508
1509 }
1510
1511 DEFUN ("event-modifier-bits", Fevent_modifier_bits, 1, 1, 0, /*
1512 Return a number representing the modifier keys which were down
1513 when the given mouse or keyboard event was produced.
1514 See also the function event-modifiers.
1515 */
1516 (event))
1517 {
1518 again:
1519 CHECK_LIVE_EVENT (event);
1520 switch (XEVENT (event)->event_type)
1521 {
1522 case key_press_event:
1523 return make_int (XEVENT (event)->event.key.modifiers);
1524 case button_press_event:
1525 case button_release_event:
1526 return make_int (XEVENT (event)->event.button.modifiers);
1527 case pointer_motion_event:
1528 return make_int (XEVENT (event)->event.motion.modifiers);
1529 case misc_user_event:
1530 return make_int (XEVENT (event)->event.misc.modifiers);
1531 default:
1532 event = wrong_type_argument (intern ("key-or-mouse-event-p"), event);
1533 goto again;
1534 }
1535 }
1536
1537 DEFUN ("event-modifiers", Fevent_modifiers, 1, 1, 0, /*
1538 Return a list of symbols, the names of the modifier keys
1539 which were down when the given mouse or keyboard event was produced.
1540 See also the function event-modifier-bits.
1541 */
1542 (event))
1543 {
1544 int mod = XINT (Fevent_modifier_bits (event));
1545 Lisp_Object result = Qnil;
1546 if (mod & MOD_SHIFT) result = Fcons (Qshift, result);
1547 if (mod & MOD_ALT) result = Fcons (Qalt, result);
1548 if (mod & MOD_HYPER) result = Fcons (Qhyper, result);
1549 if (mod & MOD_SUPER) result = Fcons (Qsuper, result);
1550 if (mod & MOD_META) result = Fcons (Qmeta, result);
1551 if (mod & MOD_CONTROL) result = Fcons (Qcontrol, result);
1552 return result;
1553 }
1554
1555 static int
1556 event_x_y_pixel_internal (Lisp_Object event, int *x, int *y, int relative)
1557 {
1558 struct window *w;
1559 struct frame *f;
1560
1561 if (XEVENT (event)->event_type == pointer_motion_event)
1562 {
1563 *x = XEVENT (event)->event.motion.x;
1564 *y = XEVENT (event)->event.motion.y;
1565 }
1566 else if (XEVENT (event)->event_type == button_press_event ||
1567 XEVENT (event)->event_type == button_release_event)
1568 {
1569 *x = XEVENT (event)->event.button.x;
1570 *y = XEVENT (event)->event.button.y;
1571 }
1572 else if (XEVENT (event)->event_type == misc_user_event)
1573 {
1574 *x = XEVENT (event)->event.misc.x;
1575 *y = XEVENT (event)->event.misc.y;
1576 }
1577 else
1578 return 0;
1579
1580 f = XFRAME (EVENT_CHANNEL (XEVENT (event)));
1581
1582 if (relative)
1583 {
1584 w = find_window_by_pixel_pos (*x, *y, f->root_window);
1585
1586 if (!w)
1587 return 1; /* #### What should really happen here. */
1588
1589 *x -= w->pixel_left;
1590 *y -= w->pixel_top;
1591 }
1592 else
1593 {
1594 *y -= FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) -
1595 FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f);
1596 *x -= FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) -
1597 FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f);
1598 }
1599
1600 return 1;
1601 }
1602
1603 DEFUN ("event-window-x-pixel", Fevent_window_x_pixel, 1, 1, 0, /*
1604 Return the X position in pixels of mouse event EVENT.
1605 The value returned is relative to the window the event occurred in.
1606 This will signal an error if the event is not a mouse event.
1607 See also `mouse-event-p' and `event-x-pixel'.
1608 */
1609 (event))
1610 {
1611 int x, y;
1612
1613 CHECK_LIVE_EVENT (event);
1614
1615 if (!event_x_y_pixel_internal (event, &x, &y, 1))
1616 return wrong_type_argument (Qmouse_event_p, event);
1617 else
1618 return make_int (x);
1619 }
1620
1621 DEFUN ("event-window-y-pixel", Fevent_window_y_pixel, 1, 1, 0, /*
1622 Return the Y position in pixels of mouse event EVENT.
1623 The value returned is relative to the window the event occurred in.
1624 This will signal an error if the event is not a mouse event.
1625 See also `mouse-event-p' and `event-y-pixel'.
1626 */
1627 (event))
1628 {
1629 int x, y;
1630
1631 CHECK_LIVE_EVENT (event);
1632
1633 if (!event_x_y_pixel_internal (event, &x, &y, 1))
1634 return wrong_type_argument (Qmouse_event_p, event);
1635 else
1636 return make_int (y);
1637 }
1638
1639 DEFUN ("event-x-pixel", Fevent_x_pixel, 1, 1, 0, /*
1640 Return the X position in pixels of mouse event EVENT.
1641 The value returned is relative to the frame the event occurred in.
1642 This will signal an error if the event is not a mouse event.
1643 See also `mouse-event-p' and `event-window-x-pixel'.
1644 */
1645 (event))
1646 {
1647 int x, y;
1648
1649 CHECK_LIVE_EVENT (event);
1650
1651 if (!event_x_y_pixel_internal (event, &x, &y, 0))
1652 return wrong_type_argument (Qmouse_event_p, event);
1653 else
1654 return make_int (x);
1655 }
1656
1657 DEFUN ("event-y-pixel", Fevent_y_pixel, 1, 1, 0, /*
1658 Return the Y position in pixels of mouse event EVENT.
1659 The value returned is relative to the frame the event occurred in.
1660 This will signal an error if the event is not a mouse event.
1661 See also `mouse-event-p' `event-window-y-pixel'.
1662 */
1663 (event))
1664 {
1665 int x, y;
1666
1667 CHECK_LIVE_EVENT (event);
1668
1669 if (!event_x_y_pixel_internal (event, &x, &y, 0))
1670 return wrong_type_argument (Qmouse_event_p, event);
1671 else
1672 return make_int (y);
1673 }
1674
1675 /* Given an event, return a value:
1676
1677 OVER_TOOLBAR: over one of the 4 frame toolbars
1678 OVER_MODELINE: over a modeline
1679 OVER_BORDER: over an internal border
1680 OVER_NOTHING: over the text area, but not over text
1681 OVER_OUTSIDE: outside of the frame border
1682 OVER_TEXT: over text in the text area
1683 OVER_V_DIVIDER: over windows vertical divider
1684
1685 and return:
1686
1687 The X char position in CHAR_X, if not a null pointer.
1688 The Y char position in CHAR_Y, if not a null pointer.
1689 (These last two values are relative to the window the event is over.)
1690 The window it's over in W, if not a null pointer.
1691 The buffer position it's over in BUFP, if not a null pointer.
1692 The closest buffer position in CLOSEST, if not a null pointer.
1693
1694 OBJ_X, OBJ_Y, OBJ1, and OBJ2 are as in pixel_to_glyph_translation().
1695 */
1696
1697 static int
1698 event_pixel_translation (Lisp_Object event, int *char_x, int *char_y,
1699 int *obj_x, int *obj_y,
1700 struct window **w, Bufpos *bufp, Bufpos *closest,
1701 Charcount *modeline_closest,
1702 Lisp_Object *obj1, Lisp_Object *obj2)
1703 {
1704 int pix_x = 0;
1705 int pix_y = 0;
1706 int result;
1707 Lisp_Object frame;
1708
1709 int ret_x, ret_y, ret_obj_x, ret_obj_y;
1710 struct window *ret_w;
1711 Bufpos ret_bufp, ret_closest;
1712 Charcount ret_modeline_closest;
1713 Lisp_Object ret_obj1, ret_obj2;
1714
1715 CHECK_LIVE_EVENT (event);
1716 frame = XEVENT (event)->channel;
1717 switch (XEVENT (event)->event_type)
1718 {
1719 case pointer_motion_event :
1720 pix_x = XEVENT (event)->event.motion.x;
1721 pix_y = XEVENT (event)->event.motion.y;
1722 break;
1723 case button_press_event :
1724 case button_release_event :
1725 pix_x = XEVENT (event)->event.button.x;
1726 pix_y = XEVENT (event)->event.button.y;
1727 break;
1728 case misc_user_event :
1729 pix_x = XEVENT (event)->event.misc.x;
1730 pix_y = XEVENT (event)->event.misc.y;
1731 break;
1732 default:
1733 dead_wrong_type_argument (Qmouse_event_p, event);
1734 }
1735
1736 result = pixel_to_glyph_translation (XFRAME (frame), pix_x, pix_y,
1737 &ret_x, &ret_y, &ret_obj_x, &ret_obj_y,
1738 &ret_w, &ret_bufp, &ret_closest,
1739 &ret_modeline_closest,
1740 &ret_obj1, &ret_obj2);
1741
1742 if (result == OVER_NOTHING || result == OVER_OUTSIDE)
1743 ret_bufp = 0;
1744 else if (ret_w && NILP (ret_w->buffer))
1745 /* Why does this happen? (Does it still happen?)
1746 I guess the window has gotten reused as a non-leaf... */
1747 ret_w = 0;
1748
1749 /* #### pixel_to_glyph_translation() sometimes returns garbage...
1750 The word has type Lisp_Type_Record (presumably meaning `extent') but the
1751 pointer points to random memory, often filled with 0, sometimes not.
1752 */
1753 /* #### Chuck, do we still need this crap? */
1754 if (!NILP (ret_obj1) && !(GLYPHP (ret_obj1)
1755 #ifdef HAVE_TOOLBARS
1756 || TOOLBAR_BUTTONP (ret_obj1)
1757 #endif
1758 ))
1759 abort ();
1760 if (!NILP (ret_obj2) && !(EXTENTP (ret_obj2) || CONSP (ret_obj2)))
1761 abort ();
1762
1763 if (char_x)
1764 *char_x = ret_x;
1765 if (char_y)
1766 *char_y = ret_y;
1767 if (obj_x)
1768 *obj_x = ret_obj_x;
1769 if (obj_y)
1770 *obj_y = ret_obj_y;
1771 if (w)
1772 *w = ret_w;
1773 if (bufp)
1774 *bufp = ret_bufp;
1775 if (closest)
1776 *closest = ret_closest;
1777 if (modeline_closest)
1778 *modeline_closest = ret_modeline_closest;
1779 if (obj1)
1780 *obj1 = ret_obj1;
1781 if (obj2)
1782 *obj2 = ret_obj2;
1783
1784 return result;
1785 }
1786
1787 DEFUN ("event-over-text-area-p", Fevent_over_text_area_p, 1, 1, 0, /*
1788 Return t if the mouse event EVENT occurred over the text area of a window.
1789 The modeline is not considered to be part of the text area.
1790 */
1791 (event))
1792 {
1793 int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1794
1795 return result == OVER_TEXT || result == OVER_NOTHING ? Qt : Qnil;
1796 }
1797
1798 DEFUN ("event-over-modeline-p", Fevent_over_modeline_p, 1, 1, 0, /*
1799 Return t if the mouse event EVENT occurred over the modeline of a window.
1800 */
1801 (event))
1802 {
1803 int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1804
1805 return result == OVER_MODELINE ? Qt : Qnil;
1806 }
1807
1808 DEFUN ("event-over-border-p", Fevent_over_border_p, 1, 1, 0, /*
1809 Return t if the mouse event EVENT occurred over an internal border.
1810 */
1811 (event))
1812 {
1813 int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1814
1815 return result == OVER_BORDER ? Qt : Qnil;
1816 }
1817
1818 DEFUN ("event-over-toolbar-p", Fevent_over_toolbar_p, 1, 1, 0, /*
1819 Return t if the mouse event EVENT occurred over a toolbar.
1820 */
1821 (event))
1822 {
1823 int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1824
1825 return result == OVER_TOOLBAR ? Qt : Qnil;
1826 }
1827
1828 DEFUN ("event-over-vertical-divider-p", Fevent_over_vertical_divider_p, 1, 1, 0, /*
1829 Return t if the mouse event EVENT occurred over a window divider.
1830 */
1831 (event))
1832 {
1833 int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1834
1835 return result == OVER_V_DIVIDER ? Qt : Qnil;
1836 }
1837
1838 struct console *
1839 event_console_or_selected (Lisp_Object event)
1840 {
1841 Lisp_Object channel = EVENT_CHANNEL (XEVENT (event));
1842 Lisp_Object console = CDFW_CONSOLE (channel);
1843
1844 if (NILP (console))
1845 console = Vselected_console;
1846
1847 return XCONSOLE (console);
1848 }
1849
1850 DEFUN ("event-channel", Fevent_channel, 1, 1, 0, /*
1851 Return the channel that the event EVENT occurred on.
1852 This will be a frame, device, console, or nil for some types
1853 of events (e.g. eval events).
1854 */
1855 (event))
1856 {
1857 CHECK_LIVE_EVENT (event);
1858 return EVENT_CHANNEL (XEVENT (event));
1859 }
1860
1861 DEFUN ("event-window", Fevent_window, 1, 1, 0, /*
1862 Return the window over which mouse event EVENT occurred.
1863 This may be nil if the event occurred in the border or over a toolbar.
1864 The modeline is considered to be within the window it describes.
1865 */
1866 (event))
1867 {
1868 struct window *w;
1869
1870 event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, 0, 0, 0);
1871
1872 if (!w)
1873 return Qnil;
1874 else
1875 {
1876 Lisp_Object window;
1877
1878 XSETWINDOW (window, w);
1879 return window;
1880 }
1881 }
1882
1883 DEFUN ("event-point", Fevent_point, 1, 1, 0, /*
1884 Return the character position of the mouse event EVENT.
1885 If the event did not occur over a window, or did not occur over text,
1886 then this returns nil. Otherwise, it returns a position in the buffer
1887 visible in the event's window.
1888 */
1889 (event))
1890 {
1891 Bufpos bufp;
1892 struct window *w;
1893
1894 event_pixel_translation (event, 0, 0, 0, 0, &w, &bufp, 0, 0, 0, 0);
1895
1896 return w && bufp ? make_int (bufp) : Qnil;
1897 }
1898
1899 DEFUN ("event-closest-point", Fevent_closest_point, 1, 1, 0, /*
1900 Return the character position closest to the mouse event EVENT.
1901 If the event did not occur over a window or over text, return the
1902 closest point to the location of the event. If the Y pixel position
1903 overlaps a window and the X pixel position is to the left of that
1904 window, the closest point is the beginning of the line containing the
1905 Y position. If the Y pixel position overlaps a window and the X pixel
1906 position is to the right of that window, the closest point is the end
1907 of the line containing the Y position. If the Y pixel position is
1908 above a window, return 0. If it is below the last character in a window,
1909 return the value of (window-end).
1910 */
1911 (event))
1912 {
1913 Bufpos bufp;
1914
1915 event_pixel_translation (event, 0, 0, 0, 0, 0, 0, &bufp, 0, 0, 0);
1916
1917 return bufp ? make_int (bufp) : Qnil;
1918 }
1919
1920 DEFUN ("event-x", Fevent_x, 1, 1, 0, /*
1921 Return the X position of the mouse event EVENT in characters.
1922 This is relative to the window the event occurred over.
1923 */
1924 (event))
1925 {
1926 int char_x;
1927
1928 event_pixel_translation (event, &char_x, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1929
1930 return make_int (char_x);
1931 }
1932
1933 DEFUN ("event-y", Fevent_y, 1, 1, 0, /*
1934 Return the Y position of the mouse event EVENT in characters.
1935 This is relative to the window the event occurred over.
1936 */
1937 (event))
1938 {
1939 int char_y;
1940
1941 event_pixel_translation (event, 0, &char_y, 0, 0, 0, 0, 0, 0, 0, 0);
1942
1943 return make_int (char_y);
1944 }
1945
1946 DEFUN ("event-modeline-position", Fevent_modeline_position, 1, 1, 0, /*
1947 Return the character position in the modeline that EVENT occurred over.
1948 EVENT should be a mouse event. If EVENT did not occur over a modeline,
1949 nil is returned. You can determine the actual character that the
1950 event occurred over by looking in `generated-modeline-string' at the
1951 returned character position. Note that `generated-modeline-string'
1952 is buffer-local, and you must use EVENT's buffer when retrieving
1953 `generated-modeline-string' in order to get accurate results.
1954 */
1955 (event))
1956 {
1957 Charcount mbufp;
1958 int where;
1959
1960 where = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, &mbufp, 0, 0);
1961
1962 return (mbufp < 0 || where != OVER_MODELINE) ? Qnil : make_int (mbufp);
1963 }
1964
1965 DEFUN ("event-glyph", Fevent_glyph, 1, 1, 0, /*
1966 Return the glyph that the mouse event EVENT occurred over, or nil.
1967 */
1968 (event))
1969 {
1970 Lisp_Object glyph;
1971 struct window *w;
1972
1973 event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, 0, &glyph, 0);
1974
1975 return w && GLYPHP (glyph) ? glyph : Qnil;
1976 }
1977
1978 DEFUN ("event-glyph-extent", Fevent_glyph_extent, 1, 1, 0, /*
1979 Return the extent of the glyph that the mouse event EVENT occurred over.
1980 If the event did not occur over a glyph, nil is returned.
1981 */
1982 (event))
1983 {
1984 Lisp_Object extent;
1985 struct window *w;
1986
1987 event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, 0, 0, &extent);
1988
1989 return w && EXTENTP (extent) ? extent : Qnil;
1990 }
1991
1992 DEFUN ("event-glyph-x-pixel", Fevent_glyph_x_pixel, 1, 1, 0, /*
1993 Return the X pixel position of EVENT relative to the glyph it occurred over.
1994 EVENT should be a mouse event. If the event did not occur over a glyph,
1995 nil is returned.
1996 */
1997 (event))
1998 {
1999 Lisp_Object extent;
2000 struct window *w;
2001 int obj_x;
2002
2003 event_pixel_translation (event, 0, 0, &obj_x, 0, &w, 0, 0, 0, 0, &extent);
2004
2005 return w && EXTENTP (extent) ? make_int (obj_x) : Qnil;
2006 }
2007
2008 DEFUN ("event-glyph-y-pixel", Fevent_glyph_y_pixel, 1, 1, 0, /*
2009 Return the Y pixel position of EVENT relative to the glyph it occurred over.
2010 EVENT should be a mouse event. If the event did not occur over a glyph,
2011 nil is returned.
2012 */
2013 (event))
2014 {
2015 Lisp_Object extent;
2016 struct window *w;
2017 int obj_y;
2018
2019 event_pixel_translation (event, 0, 0, 0, &obj_y, &w, 0, 0, 0, 0, &extent);
2020
2021 return w && EXTENTP (extent) ? make_int (obj_y) : Qnil;
2022 }
2023
2024 DEFUN ("event-toolbar-button", Fevent_toolbar_button, 1, 1, 0, /*
2025 Return the toolbar button that the mouse event EVENT occurred over.
2026 If the event did not occur over a toolbar button, nil is returned.
2027 */
2028 (event))
2029 {
2030 #ifdef HAVE_TOOLBARS
2031 Lisp_Object button;
2032
2033 int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, &button, 0);
2034
2035 return result == OVER_TOOLBAR && TOOLBAR_BUTTONP (button) ? button : Qnil;
2036 #else
2037 return Qnil;
2038 #endif
2039 }
2040
2041 DEFUN ("event-process", Fevent_process, 1, 1, 0, /*
2042 Return the process of the given process-output event.
2043 */
2044 (event))
2045 {
2046 CHECK_EVENT_TYPE (event, process_event, Qprocess_event_p);
2047 return XEVENT (event)->event.process.process;
2048 }
2049
2050 DEFUN ("event-function", Fevent_function, 1, 1, 0, /*
2051 Return the callback function of EVENT.
2052 EVENT should be a timeout, misc-user, or eval event.
2053 */
2054 (event))
2055 {
2056 again:
2057 CHECK_LIVE_EVENT (event);
2058 switch (XEVENT (event)->event_type)
2059 {
2060 case timeout_event:
2061 return XEVENT (event)->event.timeout.function;
2062 case misc_user_event:
2063 return XEVENT (event)->event.misc.function;
2064 case eval_event:
2065 return XEVENT (event)->event.eval.function;
2066 default:
2067 event = wrong_type_argument (intern ("timeout-or-eval-event-p"), event);
2068 goto again;
2069 }
2070 }
2071
2072 DEFUN ("event-object", Fevent_object, 1, 1, 0, /*
2073 Return the callback function argument of EVENT.
2074 EVENT should be a timeout, misc-user, or eval event.
2075 */
2076 (event))
2077 {
2078 again:
2079 CHECK_LIVE_EVENT (event);
2080 switch (XEVENT (event)->event_type)
2081 {
2082 case timeout_event:
2083 return XEVENT (event)->event.timeout.object;
2084 case misc_user_event:
2085 return XEVENT (event)->event.misc.object;
2086 case eval_event:
2087 return XEVENT (event)->event.eval.object;
2088 default:
2089 event = wrong_type_argument (intern ("timeout-or-eval-event-p"), event);
2090 goto again;
2091 }
2092 }
2093
2094 DEFUN ("event-properties", Fevent_properties, 1, 1, 0, /*
2095 Return a list of all of the properties of EVENT.
2096 This is in the form of a property list (alternating keyword/value pairs).
2097 */
2098 (event))
2099 {
2100 Lisp_Object props = Qnil;
2101 struct Lisp_Event *e;
2102 struct gcpro gcpro1;
2103
2104 CHECK_LIVE_EVENT (event);
2105 e = XEVENT (event);
2106 GCPRO1 (props);
2107
2108 props = cons3 (Qtimestamp, Fevent_timestamp (event), props);
2109
2110 switch (e->event_type)
2111 {
2112 default: abort ();
2113
2114 case process_event:
2115 props = cons3 (Qprocess, e->event.process.process, props);
2116 break;
2117
2118 case timeout_event:
2119 props = cons3 (Qobject, Fevent_object (event), props);
2120 props = cons3 (Qfunction, Fevent_function (event), props);
2121 props = cons3 (Qid, make_int (e->event.timeout.id_number), props);
2122 break;
2123
2124 case key_press_event:
2125 props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2126 props = cons3 (Qkey, Fevent_key (event), props);
2127 break;
2128
2129 case button_press_event:
2130 case button_release_event:
2131 props = cons3 (Qy, Fevent_y_pixel (event), props);
2132 props = cons3 (Qx, Fevent_x_pixel (event), props);
2133 props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2134 props = cons3 (Qbutton, Fevent_button (event), props);
2135 break;
2136
2137 case pointer_motion_event:
2138 props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2139 props = cons3 (Qy, Fevent_y_pixel (event), props);
2140 props = cons3 (Qx, Fevent_x_pixel (event), props);
2141 break;
2142
2143 case misc_user_event:
2144 props = cons3 (Qobject, Fevent_object (event), props);
2145 props = cons3 (Qfunction, Fevent_function (event), props);
2146 props = cons3 (Qy, Fevent_y_pixel (event), props);
2147 props = cons3 (Qx, Fevent_x_pixel (event), props);
2148 props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2149 props = cons3 (Qbutton, Fevent_button (event), props);
2150 break;
2151
2152 case eval_event:
2153 props = cons3 (Qobject, Fevent_object (event), props);
2154 props = cons3 (Qfunction, Fevent_function (event), props);
2155 break;
2156
2157 case magic_eval_event:
2158 case magic_event:
2159 break;
2160
2161 case empty_event:
2162 RETURN_UNGCPRO (Qnil);
2163 break;
2164 }
2165
2166 props = cons3 (Qchannel, Fevent_channel (event), props);
2167 UNGCPRO;
2168
2169 return props;
2170 }
2171
2172
2173 /************************************************************************/
2174 /* initialization */
2175 /************************************************************************/
2176
2177 void
2178 syms_of_events (void)
2179 {
2180 DEFSUBR (Fcharacter_to_event);
2181 DEFSUBR (Fevent_to_character);
2182
2183 DEFSUBR (Fmake_event);
2184 DEFSUBR (Fdeallocate_event);
2185 DEFSUBR (Fcopy_event);
2186 DEFSUBR (Feventp);
2187 DEFSUBR (Fevent_live_p);
2188 DEFSUBR (Fevent_type);
2189 DEFSUBR (Fevent_properties);
2190
2191 DEFSUBR (Fevent_timestamp);
2192 DEFSUBR (Fevent_key);
2193 DEFSUBR (Fevent_button);
2194 DEFSUBR (Fevent_modifier_bits);
2195 DEFSUBR (Fevent_modifiers);
2196 DEFSUBR (Fevent_x_pixel);
2197 DEFSUBR (Fevent_y_pixel);
2198 DEFSUBR (Fevent_window_x_pixel);
2199 DEFSUBR (Fevent_window_y_pixel);
2200 DEFSUBR (Fevent_over_text_area_p);
2201 DEFSUBR (Fevent_over_modeline_p);
2202 DEFSUBR (Fevent_over_border_p);
2203 DEFSUBR (Fevent_over_toolbar_p);
2204 DEFSUBR (Fevent_over_vertical_divider_p);
2205 DEFSUBR (Fevent_channel);
2206 DEFSUBR (Fevent_window);
2207 DEFSUBR (Fevent_point);
2208 DEFSUBR (Fevent_closest_point);
2209 DEFSUBR (Fevent_x);
2210 DEFSUBR (Fevent_y);
2211 DEFSUBR (Fevent_modeline_position);
2212 DEFSUBR (Fevent_glyph);
2213 DEFSUBR (Fevent_glyph_extent);
2214 DEFSUBR (Fevent_glyph_x_pixel);
2215 DEFSUBR (Fevent_glyph_y_pixel);
2216 DEFSUBR (Fevent_toolbar_button);
2217 DEFSUBR (Fevent_process);
2218 DEFSUBR (Fevent_function);
2219 DEFSUBR (Fevent_object);
2220
2221 defsymbol (&Qeventp, "eventp");
2222 defsymbol (&Qevent_live_p, "event-live-p");
2223 defsymbol (&Qkey_press_event_p, "key-press-event-p");
2224 defsymbol (&Qbutton_event_p, "button-event-p");
2225 defsymbol (&Qmouse_event_p, "mouse-event-p");
2226 defsymbol (&Qprocess_event_p, "process-event-p");
2227 defsymbol (&Qkey_press, "key-press");
2228 defsymbol (&Qbutton_press, "button-press");
2229 defsymbol (&Qbutton_release, "button-release");
2230 defsymbol (&Qmisc_user, "misc-user");
2231 defsymbol (&Qascii_character, "ascii-character");
2232
2233 defsymbol (&QKbackspace, "backspace");
2234 defsymbol (&QKtab, "tab");
2235 defsymbol (&QKlinefeed, "linefeed");
2236 defsymbol (&QKreturn, "return");
2237 defsymbol (&QKescape, "escape");
2238 defsymbol (&QKspace, "space");
2239 defsymbol (&QKdelete, "delete");
2240 }
2241
2242
2243 void
2244 reinit_vars_of_events (void)
2245 {
2246 Vevent_resource = Qnil;
2247 }
2248
2249 void
2250 vars_of_events (void)
2251 {
2252 reinit_vars_of_events ();
2253
2254 DEFVAR_LISP ("character-set-property", &Vcharacter_set_property /*
2255 A symbol used to look up the 8-bit character of a keysym.
2256 To convert a keysym symbol to an 8-bit code, as when that key is
2257 bound to self-insert-command, we will look up the property that this
2258 variable names on the property list of the keysym-symbol. The window-
2259 system-specific code will set up appropriate properties and set this
2260 variable.
2261 */ );
2262 Vcharacter_set_property = Qnil;
2263 }