6fe8e6e7e55fc92e6f26820d20e7b7a8dfdc2476
[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   if (XEVENT(e)->event_type != (t1) &&          \
1464       XEVENT(e)->event_type != (t2))            \
1465     e = wrong_type_argument ((sym),(e));        \
1466 } while (0)
1467
1468 #define CHECK_EVENT_TYPE3(e,t1,t2,t3,sym) do {  \
1469   CHECK_LIVE_EVENT (e);                         \
1470   if (XEVENT(e)->event_type != (t1) &&          \
1471       XEVENT(e)->event_type != (t2) &&          \
1472       XEVENT(e)->event_type != (t3))            \
1473     e = wrong_type_argument ((sym),(e));        \
1474 } while (0)
1475
1476 DEFUN ("event-key", Fevent_key, 1, 1, 0, /*
1477 Return the Keysym of the key-press event EVENT.
1478 This will be a character if the event is associated with one, else a symbol.
1479 */
1480        (event))
1481 {
1482   CHECK_EVENT_TYPE (event, key_press_event, Qkey_press_event_p);
1483   return XEVENT (event)->event.key.keysym;
1484 }
1485
1486 DEFUN ("event-button", Fevent_button, 1, 1, 0, /*
1487 Return the button-number of the given button-press or button-release event.
1488 */
1489        (event))
1490 {
1491
1492   CHECK_EVENT_TYPE3 (event, button_press_event, button_release_event,
1493                      misc_user_event, Qbutton_event_p);
1494 #ifdef HAVE_WINDOW_SYSTEM
1495   if ( XEVENT (event)->event_type == misc_user_event)
1496     return make_int (XEVENT (event)->event.misc.button);
1497   else
1498     return make_int (XEVENT (event)->event.button.button);
1499 #else /* !HAVE_WINDOW_SYSTEM */
1500   return Qzero;
1501 #endif /* !HAVE_WINDOW_SYSTEM */
1502
1503 }
1504
1505 DEFUN ("event-modifier-bits", Fevent_modifier_bits, 1, 1, 0, /*
1506 Return a number representing the modifier keys which were down
1507 when the given mouse or keyboard event was produced.
1508 See also the function event-modifiers.
1509 */
1510        (event))
1511 {
1512  again:
1513   CHECK_LIVE_EVENT (event);
1514   switch (XEVENT (event)->event_type)
1515     {
1516     case key_press_event:
1517       return make_int (XEVENT (event)->event.key.modifiers);
1518     case button_press_event:
1519     case button_release_event:
1520       return make_int (XEVENT (event)->event.button.modifiers);
1521     case pointer_motion_event:
1522       return make_int (XEVENT (event)->event.motion.modifiers);
1523     case misc_user_event:
1524       return make_int (XEVENT (event)->event.misc.modifiers);
1525     default:
1526       event = wrong_type_argument (intern ("key-or-mouse-event-p"), event);
1527       goto again;
1528     }
1529 }
1530
1531 DEFUN ("event-modifiers", Fevent_modifiers, 1, 1, 0, /*
1532 Return a list of symbols, the names of the modifier keys
1533 which were down when the given mouse or keyboard event was produced.
1534 See also the function event-modifier-bits.
1535 */
1536        (event))
1537 {
1538   int mod = XINT (Fevent_modifier_bits (event));
1539   Lisp_Object result = Qnil;
1540   if (mod & MOD_SHIFT)   result = Fcons (Qshift, result);
1541   if (mod & MOD_ALT)     result = Fcons (Qalt, result);
1542   if (mod & MOD_HYPER)   result = Fcons (Qhyper, result);
1543   if (mod & MOD_SUPER)   result = Fcons (Qsuper, result);
1544   if (mod & MOD_META)    result = Fcons (Qmeta, result);
1545   if (mod & MOD_CONTROL) result = Fcons (Qcontrol, result);
1546   return result;
1547 }
1548
1549 static int
1550 event_x_y_pixel_internal (Lisp_Object event, int *x, int *y, int relative)
1551 {
1552   struct window *w;
1553   struct frame *f;
1554
1555   if (XEVENT (event)->event_type == pointer_motion_event)
1556     {
1557       *x = XEVENT (event)->event.motion.x;
1558       *y = XEVENT (event)->event.motion.y;
1559     }
1560   else if (XEVENT (event)->event_type == button_press_event ||
1561            XEVENT (event)->event_type == button_release_event)
1562     {
1563       *x = XEVENT (event)->event.button.x;
1564       *y = XEVENT (event)->event.button.y;
1565     }
1566   else if (XEVENT (event)->event_type == misc_user_event)
1567     {
1568       *x = XEVENT (event)->event.misc.x;
1569       *y = XEVENT (event)->event.misc.y;
1570     }
1571   else
1572     return 0;
1573
1574   f = XFRAME (EVENT_CHANNEL (XEVENT (event)));
1575
1576   if (relative)
1577     {
1578       w = find_window_by_pixel_pos (*x, *y, f->root_window);
1579
1580       if (!w)
1581         return 1;       /* #### What should really happen here. */
1582
1583       *x -= w->pixel_left;
1584       *y -= w->pixel_top;
1585     }
1586   else
1587     {
1588       *y -= FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) -
1589         FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f);
1590       *x -= FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) -
1591         FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f);
1592     }
1593
1594   return 1;
1595 }
1596
1597 DEFUN ("event-window-x-pixel", Fevent_window_x_pixel, 1, 1, 0, /*
1598 Return the X position in pixels of mouse event EVENT.
1599 The value returned is relative to the window the event occurred in.
1600 This will signal an error if the event is not a mouse event.
1601 See also `mouse-event-p' and `event-x-pixel'.
1602 */
1603        (event))
1604 {
1605   int x, y;
1606
1607   CHECK_LIVE_EVENT (event);
1608
1609   if (!event_x_y_pixel_internal (event, &x, &y, 1))
1610     return wrong_type_argument (Qmouse_event_p, event);
1611   else
1612     return make_int (x);
1613 }
1614
1615 DEFUN ("event-window-y-pixel", Fevent_window_y_pixel, 1, 1, 0, /*
1616 Return the Y position in pixels of mouse event EVENT.
1617 The value returned is relative to the window the event occurred in.
1618 This will signal an error if the event is not a mouse event.
1619 See also `mouse-event-p' and `event-y-pixel'.
1620 */
1621        (event))
1622 {
1623   int x, y;
1624
1625   CHECK_LIVE_EVENT (event);
1626
1627   if (!event_x_y_pixel_internal (event, &x, &y, 1))
1628     return wrong_type_argument (Qmouse_event_p, event);
1629   else
1630     return make_int (y);
1631 }
1632
1633 DEFUN ("event-x-pixel", Fevent_x_pixel, 1, 1, 0, /*
1634 Return the X position in pixels of mouse event EVENT.
1635 The value returned is relative to the frame the event occurred in.
1636 This will signal an error if the event is not a mouse event.
1637 See also `mouse-event-p' and `event-window-x-pixel'.
1638 */
1639        (event))
1640 {
1641   int x, y;
1642
1643   CHECK_LIVE_EVENT (event);
1644
1645   if (!event_x_y_pixel_internal (event, &x, &y, 0))
1646     return wrong_type_argument (Qmouse_event_p, event);
1647   else
1648     return make_int (x);
1649 }
1650
1651 DEFUN ("event-y-pixel", Fevent_y_pixel, 1, 1, 0, /*
1652 Return the Y position in pixels of mouse event EVENT.
1653 The value returned is relative to the frame the event occurred in.
1654 This will signal an error if the event is not a mouse event.
1655 See also `mouse-event-p' `event-window-y-pixel'.
1656 */
1657        (event))
1658 {
1659   int x, y;
1660
1661   CHECK_LIVE_EVENT (event);
1662
1663   if (!event_x_y_pixel_internal (event, &x, &y, 0))
1664     return wrong_type_argument (Qmouse_event_p, event);
1665   else
1666     return make_int (y);
1667 }
1668
1669 /* Given an event, return a value:
1670
1671      OVER_TOOLBAR:      over one of the 4 frame toolbars
1672      OVER_MODELINE:     over a modeline
1673      OVER_BORDER:       over an internal border
1674      OVER_NOTHING:      over the text area, but not over text
1675      OVER_OUTSIDE:      outside of the frame border
1676      OVER_TEXT:         over text in the text area
1677      OVER_V_DIVIDER:    over windows vertical divider
1678
1679    and return:
1680
1681    The X char position in CHAR_X, if not a null pointer.
1682    The Y char position in CHAR_Y, if not a null pointer.
1683    (These last two values are relative to the window the event is over.)
1684    The window it's over in W, if not a null pointer.
1685    The buffer position it's over in BUFP, if not a null pointer.
1686    The closest buffer position in CLOSEST, if not a null pointer.
1687
1688    OBJ_X, OBJ_Y, OBJ1, and OBJ2 are as in pixel_to_glyph_translation().
1689 */
1690
1691 static int
1692 event_pixel_translation (Lisp_Object event, int *char_x, int *char_y,
1693                          int *obj_x, int *obj_y,
1694                          struct window **w, Bufpos *bufp, Bufpos *closest,
1695                          Charcount *modeline_closest,
1696                          Lisp_Object *obj1, Lisp_Object *obj2)
1697 {
1698   int pix_x = 0;
1699   int pix_y = 0;
1700   int result;
1701   Lisp_Object frame;
1702
1703   int ret_x, ret_y, ret_obj_x, ret_obj_y;
1704   struct window *ret_w;
1705   Bufpos ret_bufp, ret_closest;
1706   Charcount ret_modeline_closest;
1707   Lisp_Object ret_obj1, ret_obj2;
1708
1709   CHECK_LIVE_EVENT (event);
1710   frame = XEVENT (event)->channel;
1711   switch (XEVENT (event)->event_type)
1712     {
1713     case pointer_motion_event :
1714       pix_x = XEVENT (event)->event.motion.x;
1715       pix_y = XEVENT (event)->event.motion.y;
1716       break;
1717     case button_press_event :
1718     case button_release_event :
1719       pix_x = XEVENT (event)->event.button.x;
1720       pix_y = XEVENT (event)->event.button.y;
1721       break;
1722     case misc_user_event :
1723       pix_x = XEVENT (event)->event.misc.x;
1724       pix_y = XEVENT (event)->event.misc.y;
1725       break;
1726     default:
1727       dead_wrong_type_argument (Qmouse_event_p, event);
1728     }
1729
1730   result = pixel_to_glyph_translation (XFRAME (frame), pix_x, pix_y,
1731                                        &ret_x, &ret_y, &ret_obj_x, &ret_obj_y,
1732                                        &ret_w, &ret_bufp, &ret_closest,
1733                                        &ret_modeline_closest,
1734                                        &ret_obj1, &ret_obj2);
1735
1736   if (result == OVER_NOTHING || result == OVER_OUTSIDE)
1737     ret_bufp = 0;
1738   else if (ret_w && NILP (ret_w->buffer))
1739     /* Why does this happen?  (Does it still happen?)
1740        I guess the window has gotten reused as a non-leaf... */
1741     ret_w = 0;
1742
1743   /* #### pixel_to_glyph_translation() sometimes returns garbage...
1744      The word has type Lisp_Type_Record (presumably meaning `extent') but the
1745      pointer points to random memory, often filled with 0, sometimes not.
1746    */
1747   /* #### Chuck, do we still need this crap? */
1748   if (!NILP (ret_obj1) && !(GLYPHP (ret_obj1)
1749 #ifdef HAVE_TOOLBARS
1750                             || TOOLBAR_BUTTONP (ret_obj1)
1751 #endif
1752      ))
1753     abort ();
1754   if (!NILP (ret_obj2) && !(EXTENTP (ret_obj2) || CONSP (ret_obj2)))
1755     abort ();
1756
1757   if (char_x)
1758     *char_x = ret_x;
1759   if (char_y)
1760     *char_y = ret_y;
1761   if (obj_x)
1762     *obj_x = ret_obj_x;
1763   if (obj_y)
1764     *obj_y = ret_obj_y;
1765   if (w)
1766     *w = ret_w;
1767   if (bufp)
1768     *bufp = ret_bufp;
1769   if (closest)
1770     *closest = ret_closest;
1771   if (modeline_closest)
1772     *modeline_closest = ret_modeline_closest;
1773   if (obj1)
1774     *obj1 = ret_obj1;
1775   if (obj2)
1776     *obj2 = ret_obj2;
1777
1778   return result;
1779 }
1780
1781 DEFUN ("event-over-text-area-p", Fevent_over_text_area_p, 1, 1, 0, /*
1782 Return t if the mouse event EVENT occurred over the text area of a window.
1783 The modeline is not considered to be part of the text area.
1784 */
1785        (event))
1786 {
1787   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1788
1789   return result == OVER_TEXT || result == OVER_NOTHING ? Qt : Qnil;
1790 }
1791
1792 DEFUN ("event-over-modeline-p", Fevent_over_modeline_p, 1, 1, 0, /*
1793 Return t if the mouse event EVENT occurred over the modeline of a window.
1794 */
1795        (event))
1796 {
1797   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1798
1799   return result == OVER_MODELINE ? Qt : Qnil;
1800 }
1801
1802 DEFUN ("event-over-border-p", Fevent_over_border_p, 1, 1, 0, /*
1803 Return t if the mouse event EVENT occurred over an internal border.
1804 */
1805        (event))
1806 {
1807   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1808
1809   return result == OVER_BORDER ? Qt : Qnil;
1810 }
1811
1812 DEFUN ("event-over-toolbar-p", Fevent_over_toolbar_p, 1, 1, 0, /*
1813 Return t if the mouse event EVENT occurred over a toolbar.
1814 */
1815        (event))
1816 {
1817   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1818
1819   return result == OVER_TOOLBAR ? Qt : Qnil;
1820 }
1821
1822 DEFUN ("event-over-vertical-divider-p", Fevent_over_vertical_divider_p, 1, 1, 0, /*
1823 Return t if the mouse event EVENT occurred over a window divider.
1824 */
1825        (event))
1826 {
1827   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1828
1829   return result == OVER_V_DIVIDER ? Qt : Qnil;
1830 }
1831
1832 struct console *
1833 event_console_or_selected (Lisp_Object event)
1834 {
1835   Lisp_Object channel = EVENT_CHANNEL (XEVENT (event));
1836   Lisp_Object console = CDFW_CONSOLE (channel);
1837
1838   if (NILP (console))
1839     console = Vselected_console;
1840
1841   return XCONSOLE (console);
1842 }
1843
1844 DEFUN ("event-channel", Fevent_channel, 1, 1, 0, /*
1845 Return the channel that the event EVENT occurred on.
1846 This will be a frame, device, console, or nil for some types
1847 of events (e.g. eval events).
1848 */
1849        (event))
1850 {
1851   CHECK_LIVE_EVENT (event);
1852   return EVENT_CHANNEL (XEVENT (event));
1853 }
1854
1855 DEFUN ("event-window", Fevent_window, 1, 1, 0, /*
1856 Return the window over which mouse event EVENT occurred.
1857 This may be nil if the event occurred in the border or over a toolbar.
1858 The modeline is considered to be within the window it describes.
1859 */
1860        (event))
1861 {
1862   struct window *w;
1863
1864   event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, 0, 0, 0);
1865
1866   if (!w)
1867     return Qnil;
1868   else
1869     {
1870       Lisp_Object window;
1871
1872       XSETWINDOW (window, w);
1873       return window;
1874     }
1875 }
1876
1877 DEFUN ("event-point", Fevent_point, 1, 1, 0, /*
1878 Return the character position of the mouse event EVENT.
1879 If the event did not occur over a window, or did not occur over text,
1880 then this returns nil.  Otherwise, it returns a position in the buffer
1881 visible in the event's window.
1882 */
1883        (event))
1884 {
1885   Bufpos bufp;
1886   struct window *w;
1887
1888   event_pixel_translation (event, 0, 0, 0, 0, &w, &bufp, 0, 0, 0, 0);
1889
1890   return w && bufp ? make_int (bufp) : Qnil;
1891 }
1892
1893 DEFUN ("event-closest-point", Fevent_closest_point, 1, 1, 0, /*
1894 Return the character position closest to the mouse event EVENT.
1895 If the event did not occur over a window or over text, return the
1896 closest point to the location of the event.  If the Y pixel position
1897 overlaps a window and the X pixel position is to the left of that
1898 window, the closest point is the beginning of the line containing the
1899 Y position.  If the Y pixel position overlaps a window and the X pixel
1900 position is to the right of that window, the closest point is the end
1901 of the line containing the Y position.  If the Y pixel position is
1902 above a window, return 0.  If it is below the last character in a window,
1903 return the value of (window-end).
1904 */
1905        (event))
1906 {
1907   Bufpos bufp;
1908
1909   event_pixel_translation (event, 0, 0, 0, 0, 0, 0, &bufp, 0, 0, 0);
1910
1911   return bufp ? make_int (bufp) : Qnil;
1912 }
1913
1914 DEFUN ("event-x", Fevent_x, 1, 1, 0, /*
1915 Return the X position of the mouse event EVENT in characters.
1916 This is relative to the window the event occurred over.
1917 */
1918        (event))
1919 {
1920   int char_x;
1921
1922   event_pixel_translation (event, &char_x, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1923
1924   return make_int (char_x);
1925 }
1926
1927 DEFUN ("event-y", Fevent_y, 1, 1, 0, /*
1928 Return the Y position of the mouse event EVENT in characters.
1929 This is relative to the window the event occurred over.
1930 */
1931        (event))
1932 {
1933   int char_y;
1934
1935   event_pixel_translation (event, 0, &char_y, 0, 0, 0, 0, 0, 0, 0, 0);
1936
1937   return make_int (char_y);
1938 }
1939
1940 DEFUN ("event-modeline-position", Fevent_modeline_position, 1, 1, 0, /*
1941 Return the character position in the modeline that EVENT occurred over.
1942 EVENT should be a mouse event.  If EVENT did not occur over a modeline,
1943 nil is returned.  You can determine the actual character that the
1944 event occurred over by looking in `generated-modeline-string' at the
1945 returned character position.  Note that `generated-modeline-string'
1946 is buffer-local, and you must use EVENT's buffer when retrieving
1947 `generated-modeline-string' in order to get accurate results.
1948 */
1949        (event))
1950 {
1951   Charcount mbufp;
1952   int where;
1953
1954   where = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, &mbufp, 0, 0);
1955
1956   return (mbufp < 0 || where != OVER_MODELINE) ? Qnil : make_int (mbufp);
1957 }
1958
1959 DEFUN ("event-glyph", Fevent_glyph, 1, 1, 0, /*
1960 Return the glyph that the mouse event EVENT occurred over, or nil.
1961 */
1962        (event))
1963 {
1964   Lisp_Object glyph;
1965   struct window *w;
1966
1967   event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, 0, &glyph, 0);
1968
1969   return w && GLYPHP (glyph) ? glyph : Qnil;
1970 }
1971
1972 DEFUN ("event-glyph-extent", Fevent_glyph_extent, 1, 1, 0, /*
1973 Return the extent of the glyph that the mouse event EVENT occurred over.
1974 If the event did not occur over a glyph, nil is returned.
1975 */
1976        (event))
1977 {
1978   Lisp_Object extent;
1979   struct window *w;
1980
1981   event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, 0, 0, &extent);
1982
1983   return w && EXTENTP (extent) ? extent : Qnil;
1984 }
1985
1986 DEFUN ("event-glyph-x-pixel", Fevent_glyph_x_pixel, 1, 1, 0, /*
1987 Return the X pixel position of EVENT relative to the glyph it occurred over.
1988 EVENT should be a mouse event.  If the event did not occur over a glyph,
1989 nil is returned.
1990 */
1991        (event))
1992 {
1993   Lisp_Object extent;
1994   struct window *w;
1995   int obj_x;
1996
1997   event_pixel_translation (event, 0, 0, &obj_x, 0, &w, 0, 0, 0, 0, &extent);
1998
1999   return w && EXTENTP (extent) ? make_int (obj_x) : Qnil;
2000 }
2001
2002 DEFUN ("event-glyph-y-pixel", Fevent_glyph_y_pixel, 1, 1, 0, /*
2003 Return the Y pixel position of EVENT relative to the glyph it occurred over.
2004 EVENT should be a mouse event.  If the event did not occur over a glyph,
2005 nil is returned.
2006 */
2007        (event))
2008 {
2009   Lisp_Object extent;
2010   struct window *w;
2011   int obj_y;
2012
2013   event_pixel_translation (event, 0, 0, 0, &obj_y, &w, 0, 0, 0, 0, &extent);
2014
2015   return w && EXTENTP (extent) ? make_int (obj_y) : Qnil;
2016 }
2017
2018 DEFUN ("event-toolbar-button", Fevent_toolbar_button, 1, 1, 0, /*
2019 Return the toolbar button that the mouse event EVENT occurred over.
2020 If the event did not occur over a toolbar button, nil is returned.
2021 */
2022        (event))
2023 {
2024 #ifdef HAVE_TOOLBARS
2025   Lisp_Object button;
2026
2027   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, &button, 0);
2028
2029   return result == OVER_TOOLBAR && TOOLBAR_BUTTONP (button) ? button : Qnil;
2030 #else
2031   return Qnil;
2032 #endif
2033 }
2034
2035 DEFUN ("event-process", Fevent_process, 1, 1, 0, /*
2036 Return the process of the given process-output event.
2037 */
2038        (event))
2039 {
2040   CHECK_EVENT_TYPE (event, process_event, Qprocess_event_p);
2041   return XEVENT (event)->event.process.process;
2042 }
2043
2044 DEFUN ("event-function", Fevent_function, 1, 1, 0, /*
2045 Return the callback function of EVENT.
2046 EVENT should be a timeout, misc-user, or eval event.
2047 */
2048        (event))
2049 {
2050  again:
2051   CHECK_LIVE_EVENT (event);
2052   switch (XEVENT (event)->event_type)
2053     {
2054     case timeout_event:
2055       return XEVENT (event)->event.timeout.function;
2056     case misc_user_event:
2057       return XEVENT (event)->event.misc.function;
2058     case eval_event:
2059       return XEVENT (event)->event.eval.function;
2060     default:
2061       event = wrong_type_argument (intern ("timeout-or-eval-event-p"), event);
2062       goto again;
2063     }
2064 }
2065
2066 DEFUN ("event-object", Fevent_object, 1, 1, 0, /*
2067 Return the callback function argument of EVENT.
2068 EVENT should be a timeout, misc-user, or eval event.
2069 */
2070        (event))
2071 {
2072  again:
2073   CHECK_LIVE_EVENT (event);
2074   switch (XEVENT (event)->event_type)
2075     {
2076     case timeout_event:
2077       return XEVENT (event)->event.timeout.object;
2078     case misc_user_event:
2079       return XEVENT (event)->event.misc.object;
2080     case eval_event:
2081       return XEVENT (event)->event.eval.object;
2082     default:
2083       event = wrong_type_argument (intern ("timeout-or-eval-event-p"), event);
2084       goto again;
2085     }
2086 }
2087
2088 DEFUN ("event-properties", Fevent_properties, 1, 1, 0, /*
2089 Return a list of all of the properties of EVENT.
2090 This is in the form of a property list (alternating keyword/value pairs).
2091 */
2092        (event))
2093 {
2094   Lisp_Object props = Qnil;
2095   struct Lisp_Event *e;
2096   struct gcpro gcpro1;
2097
2098   CHECK_LIVE_EVENT (event);
2099   e = XEVENT (event);
2100   GCPRO1 (props);
2101
2102   props = cons3 (Qtimestamp, Fevent_timestamp (event), props);
2103
2104   switch (e->event_type)
2105     {
2106     default: abort ();
2107
2108     case process_event:
2109       props = cons3 (Qprocess, e->event.process.process, props);
2110       break;
2111
2112     case timeout_event:
2113       props = cons3 (Qobject,   Fevent_object   (event), props);
2114       props = cons3 (Qfunction, Fevent_function (event), props);
2115       props = cons3 (Qid, make_int (e->event.timeout.id_number), props);
2116       break;
2117
2118     case key_press_event:
2119       props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2120       props = cons3 (Qkey,       Fevent_key       (event), props);
2121       break;
2122
2123     case button_press_event:
2124     case button_release_event:
2125       props = cons3 (Qy,         Fevent_y_pixel   (event), props);
2126       props = cons3 (Qx,         Fevent_x_pixel   (event), props);
2127       props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2128       props = cons3 (Qbutton,    Fevent_button    (event), props);
2129       break;
2130
2131     case pointer_motion_event:
2132       props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2133       props = cons3 (Qy,         Fevent_y_pixel   (event), props);
2134       props = cons3 (Qx,         Fevent_x_pixel   (event), props);
2135       break;
2136
2137     case misc_user_event:
2138       props = cons3 (Qobject,    Fevent_object  (event), props);
2139       props = cons3 (Qfunction,  Fevent_function (event), props);
2140       props = cons3 (Qy,         Fevent_y_pixel   (event), props);
2141       props = cons3 (Qx,         Fevent_x_pixel   (event), props);
2142       props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2143       props = cons3 (Qbutton,    Fevent_button    (event), props);
2144       break;
2145
2146     case eval_event:
2147       props = cons3 (Qobject,   Fevent_object   (event), props);
2148       props = cons3 (Qfunction, Fevent_function (event), props);
2149       break;
2150
2151     case magic_eval_event:
2152     case magic_event:
2153       break;
2154
2155     case empty_event:
2156       RETURN_UNGCPRO (Qnil);
2157       break;
2158     }
2159
2160   props = cons3 (Qchannel, Fevent_channel (event), props);
2161   UNGCPRO;
2162
2163   return props;
2164 }
2165
2166 \f
2167 /************************************************************************/
2168 /*                            initialization                            */
2169 /************************************************************************/
2170
2171 void
2172 syms_of_events (void)
2173 {
2174   DEFSUBR (Fcharacter_to_event);
2175   DEFSUBR (Fevent_to_character);
2176
2177   DEFSUBR (Fmake_event);
2178   DEFSUBR (Fdeallocate_event);
2179   DEFSUBR (Fcopy_event);
2180   DEFSUBR (Feventp);
2181   DEFSUBR (Fevent_live_p);
2182   DEFSUBR (Fevent_type);
2183   DEFSUBR (Fevent_properties);
2184
2185   DEFSUBR (Fevent_timestamp);
2186   DEFSUBR (Fevent_key);
2187   DEFSUBR (Fevent_button);
2188   DEFSUBR (Fevent_modifier_bits);
2189   DEFSUBR (Fevent_modifiers);
2190   DEFSUBR (Fevent_x_pixel);
2191   DEFSUBR (Fevent_y_pixel);
2192   DEFSUBR (Fevent_window_x_pixel);
2193   DEFSUBR (Fevent_window_y_pixel);
2194   DEFSUBR (Fevent_over_text_area_p);
2195   DEFSUBR (Fevent_over_modeline_p);
2196   DEFSUBR (Fevent_over_border_p);
2197   DEFSUBR (Fevent_over_toolbar_p);
2198   DEFSUBR (Fevent_over_vertical_divider_p);
2199   DEFSUBR (Fevent_channel);
2200   DEFSUBR (Fevent_window);
2201   DEFSUBR (Fevent_point);
2202   DEFSUBR (Fevent_closest_point);
2203   DEFSUBR (Fevent_x);
2204   DEFSUBR (Fevent_y);
2205   DEFSUBR (Fevent_modeline_position);
2206   DEFSUBR (Fevent_glyph);
2207   DEFSUBR (Fevent_glyph_extent);
2208   DEFSUBR (Fevent_glyph_x_pixel);
2209   DEFSUBR (Fevent_glyph_y_pixel);
2210   DEFSUBR (Fevent_toolbar_button);
2211   DEFSUBR (Fevent_process);
2212   DEFSUBR (Fevent_function);
2213   DEFSUBR (Fevent_object);
2214
2215   defsymbol (&Qeventp, "eventp");
2216   defsymbol (&Qevent_live_p, "event-live-p");
2217   defsymbol (&Qkey_press_event_p, "key-press-event-p");
2218   defsymbol (&Qbutton_event_p, "button-event-p");
2219   defsymbol (&Qmouse_event_p, "mouse-event-p");
2220   defsymbol (&Qprocess_event_p, "process-event-p");
2221   defsymbol (&Qkey_press, "key-press");
2222   defsymbol (&Qbutton_press, "button-press");
2223   defsymbol (&Qbutton_release, "button-release");
2224   defsymbol (&Qmisc_user, "misc-user");
2225   defsymbol (&Qascii_character, "ascii-character");
2226 }
2227
2228 void
2229 vars_of_events (void)
2230 {
2231   DEFVAR_LISP ("character-set-property", &Vcharacter_set_property /*
2232 A symbol used to look up the 8-bit character of a keysym.
2233 To convert a keysym symbol to an 8-bit code, as when that key is
2234 bound to self-insert-command, we will look up the property that this
2235 variable names on the property list of the keysym-symbol.  The window-
2236 system-specific code will set up appropriate properties and set this
2237 variable.
2238 */ );
2239   Vcharacter_set_property = Qnil;
2240
2241   Vevent_resource = Qnil;
2242
2243   QKbackspace = KEYSYM ("backspace");
2244   QKtab       = KEYSYM ("tab");
2245   QKlinefeed  = KEYSYM ("linefeed");
2246   QKreturn    = KEYSYM ("return");
2247   QKescape    = KEYSYM ("escape");
2248   QKspace     = KEYSYM ("space");
2249   QKdelete    = KEYSYM ("delete");
2250
2251   staticpro (&QKbackspace);
2252   staticpro (&QKtab);
2253   staticpro (&QKlinefeed);
2254   staticpro (&QKreturn);
2255   staticpro (&QKescape);
2256   staticpro (&QKspace);
2257   staticpro (&QKdelete);
2258 }