XEmacs 21.2.7
[chise/xemacs-chise.git.1] / src / events.c
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, void (*markobj) (Lisp_Object))
107 {
108   struct Lisp_Event *event = XEVENT (obj);
109
110   switch (event->event_type)
111     {
112     case key_press_event:
113       markobj (event->event.key.keysym);
114       break;
115     case process_event:
116       markobj (event->event.process.process);
117       break;
118     case timeout_event:
119       markobj (event->event.timeout.function);
120       markobj (event->event.timeout.object);
121       break;
122     case eval_event:
123     case misc_user_event:
124       markobj (event->event.eval.function);
125       markobj (event->event.eval.object);
126       break;
127     case magic_eval_event:
128       markobj (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   markobj (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, struct Lisp_Event);
379
380 \f
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 \f
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 \f
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 \f
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
2234 void
2235 vars_of_events (void)
2236 {
2237   DEFVAR_LISP ("character-set-property", &Vcharacter_set_property /*
2238 A symbol used to look up the 8-bit character of a keysym.
2239 To convert a keysym symbol to an 8-bit code, as when that key is
2240 bound to self-insert-command, we will look up the property that this
2241 variable names on the property list of the keysym-symbol.  The window-
2242 system-specific code will set up appropriate properties and set this
2243 variable.
2244 */ );
2245   Vcharacter_set_property = Qnil;
2246
2247   Vevent_resource = Qnil;
2248
2249   QKbackspace = KEYSYM ("backspace");
2250   QKtab       = KEYSYM ("tab");
2251   QKlinefeed  = KEYSYM ("linefeed");
2252   QKreturn    = KEYSYM ("return");
2253   QKescape    = KEYSYM ("escape");
2254   QKspace     = KEYSYM ("space");
2255   QKdelete    = KEYSYM ("delete");
2256
2257   staticpro (&QKbackspace);
2258   staticpro (&QKtab);
2259   staticpro (&QKlinefeed);
2260   staticpro (&QKreturn);
2261   staticpro (&QKescape);
2262   staticpro (&QKspace);
2263   staticpro (&QKdelete);
2264 }