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