XEmacs 21.2.27 "Hera".
[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)
107 {
108   struct Lisp_Event *event = XEVENT (obj);
109
110   switch (event->event_type)
111     {
112     case key_press_event:
113       mark_object (event->event.key.keysym);
114       break;
115     case process_event:
116       mark_object (event->event.process.process);
117       break;
118     case timeout_event:
119       mark_object (event->event.timeout.function);
120       mark_object (event->event.timeout.object);
121       break;
122     case eval_event:
123     case misc_user_event:
124       mark_object (event->event.eval.function);
125       mark_object (event->event.eval.object);
126       break;
127     case magic_eval_event:
128       mark_object (event->event.magic_eval.object);
129       break;
130     case button_press_event:
131     case button_release_event:
132     case pointer_motion_event:
133     case magic_event:
134     case empty_event:
135     case dead_event:
136       break;
137     default:
138       abort ();
139     }
140   mark_object (event->channel);
141   return event->next;
142 }
143
144 static void
145 print_event_1 (CONST char *str, Lisp_Object obj, Lisp_Object printcharfun)
146 {
147   char buf[255];
148   write_c_string (str, printcharfun);
149   format_event_object (buf, XEVENT (obj), 0);
150   write_c_string (buf, printcharfun);
151 }
152
153 static void
154 print_event (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
155 {
156   if (print_readably)
157     error ("Printing unreadable object #<event>");
158
159   switch (XEVENT (obj)->event_type)
160     {
161     case key_press_event:
162       print_event_1 ("#<keypress-event ", obj, printcharfun);
163       break;
164     case button_press_event:
165       print_event_1 ("#<buttondown-event ", obj, printcharfun);
166       break;
167     case button_release_event:
168       print_event_1 ("#<buttonup-event ", obj, printcharfun);
169       break;
170     case magic_event:
171     case magic_eval_event:
172       print_event_1 ("#<magic-event ", obj, printcharfun);
173       break;
174     case pointer_motion_event:
175       {
176         char buf[64];
177         Lisp_Object Vx, Vy;
178         Vx = Fevent_x_pixel (obj);
179         assert (INTP (Vx));
180         Vy = Fevent_y_pixel (obj);
181         assert (INTP (Vy));
182         sprintf (buf, "#<motion-event %ld, %ld", (long) XINT (Vx), (long) XINT (Vy));
183         write_c_string (buf, printcharfun);
184         break;
185       }
186     case process_event:
187         write_c_string ("#<process-event ", printcharfun);
188         print_internal (XEVENT (obj)->event.process.process, printcharfun, 1);
189         break;
190     case timeout_event:
191         write_c_string ("#<timeout-event ", printcharfun);
192         print_internal (XEVENT (obj)->event.timeout.object, printcharfun, 1);
193         break;
194     case empty_event:
195         write_c_string ("#<empty-event", printcharfun);
196         break;
197     case misc_user_event:
198         write_c_string ("#<misc-user-event (", printcharfun);
199         print_internal (XEVENT (obj)->event.misc.function, printcharfun, 1);
200         write_c_string (" ", printcharfun);
201         print_internal (XEVENT (obj)->event.misc.object, printcharfun, 1);
202         write_c_string (")", printcharfun);
203         break;
204     case eval_event:
205         write_c_string ("#<eval-event (", printcharfun);
206         print_internal (XEVENT (obj)->event.eval.function, printcharfun, 1);
207         write_c_string (" ", printcharfun);
208         print_internal (XEVENT (obj)->event.eval.object, printcharfun, 1);
209         write_c_string (")", printcharfun);
210         break;
211     case dead_event:
212         write_c_string ("#<DEALLOCATED-EVENT", printcharfun);
213         break;
214     default:
215         write_c_string ("#<UNKNOWN-EVENT-TYPE", printcharfun);
216         break;
217       }
218   write_c_string (">", printcharfun);
219 }
220
221 static int
222 event_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
223 {
224   struct Lisp_Event *e1 = XEVENT (obj1);
225   struct Lisp_Event *e2 = XEVENT (obj2);
226
227   if (e1->event_type != e2->event_type) return 0;
228   if (!EQ (e1->channel, e2->channel)) return 0;
229 /*  if (e1->timestamp != e2->timestamp) return 0; */
230   switch (e1->event_type)
231     {
232     default: abort ();
233
234     case process_event:
235       return EQ (e1->event.process.process, e2->event.process.process);
236
237     case timeout_event:
238       return (internal_equal (e1->event.timeout.function,
239                               e2->event.timeout.function, 0) &&
240               internal_equal (e1->event.timeout.object,
241                               e2->event.timeout.object, 0));
242
243     case key_press_event:
244       return (EQ (e1->event.key.keysym, e2->event.key.keysym) &&
245               (e1->event.key.modifiers == e2->event.key.modifiers));
246
247     case button_press_event:
248     case button_release_event:
249       return (e1->event.button.button    == e2->event.button.button &&
250               e1->event.button.modifiers == e2->event.button.modifiers);
251
252     case pointer_motion_event:
253       return (e1->event.motion.x == e2->event.motion.x &&
254               e1->event.motion.y == e2->event.motion.y);
255
256     case misc_user_event:
257       return (internal_equal (e1->event.eval.function,
258                               e2->event.eval.function, 0) &&
259               internal_equal (e1->event.eval.object,
260                               e2->event.eval.object, 0) &&
261               /* is this really needed for equality
262                  or is x and y also important? */
263               e1->event.misc.button    == e2->event.misc.button &&
264               e1->event.misc.modifiers == e2->event.misc.modifiers);
265
266     case eval_event:
267       return (internal_equal (e1->event.eval.function,
268                               e2->event.eval.function, 0) &&
269               internal_equal (e1->event.eval.object,
270                               e2->event.eval.object, 0));
271
272     case magic_eval_event:
273       return (e1->event.magic_eval.internal_function ==
274               e2->event.magic_eval.internal_function &&
275               internal_equal (e1->event.magic_eval.object,
276                               e2->event.magic_eval.object, 0));
277
278     case magic_event:
279       {
280         struct console *con = XCONSOLE (CDFW_CONSOLE (e1->channel));
281
282 #ifdef HAVE_X_WINDOWS
283         if (CONSOLE_X_P (con))
284           return (e1->event.magic.underlying_x_event.xany.serial ==
285                   e2->event.magic.underlying_x_event.xany.serial);
286 #endif
287 #ifdef HAVE_TTY
288         if (CONSOLE_TTY_P (con))
289           return (e1->event.magic.underlying_tty_event ==
290                   e2->event.magic.underlying_tty_event);
291 #endif
292 #ifdef HAVE_MS_WINDOWS
293         if (CONSOLE_MSWINDOWS_P (con))
294           return (!memcmp(&e1->event.magic.underlying_mswindows_event,
295                           &e2->event.magic.underlying_mswindows_event,
296                           sizeof(union magic_data)));
297 #endif
298         return 1; /* not reached */
299       }
300
301     case empty_event:      /* Empty and deallocated events are equal. */
302     case dead_event:
303       return 1;
304     }
305 }
306
307 static unsigned long
308 event_hash (Lisp_Object obj, int depth)
309 {
310   struct Lisp_Event *e = XEVENT (obj);
311   unsigned long hash;
312
313   hash = HASH2 (e->event_type, LISP_HASH (e->channel));
314   switch (e->event_type)
315     {
316     case process_event:
317       return HASH2 (hash, LISP_HASH (e->event.process.process));
318
319     case timeout_event:
320       return HASH3 (hash, internal_hash (e->event.timeout.function, depth + 1),
321                     internal_hash (e->event.timeout.object, depth + 1));
322
323     case key_press_event:
324       return HASH3 (hash, LISP_HASH (e->event.key.keysym),
325                     e->event.key.modifiers);
326
327     case button_press_event:
328     case button_release_event:
329       return HASH3 (hash, e->event.button.button, e->event.button.modifiers);
330
331     case pointer_motion_event:
332       return HASH3 (hash, e->event.motion.x, e->event.motion.y);
333
334     case misc_user_event:
335       return HASH5 (hash, internal_hash (e->event.misc.function, depth + 1),
336                     internal_hash (e->event.misc.object, depth + 1),
337                     e->event.misc.button, e->event.misc.modifiers);
338
339     case eval_event:
340       return HASH3 (hash, internal_hash (e->event.eval.function, depth + 1),
341                     internal_hash (e->event.eval.object, depth + 1));
342
343     case magic_eval_event:
344       return HASH3 (hash,
345                     (unsigned long) e->event.magic_eval.internal_function,
346                     internal_hash (e->event.magic_eval.object, depth + 1));
347
348     case magic_event:
349       {
350         struct console *con = XCONSOLE (CDFW_CONSOLE (EVENT_CHANNEL (e)));
351 #ifdef HAVE_X_WINDOWS
352         if (CONSOLE_X_P (con))
353           return HASH2 (hash, e->event.magic.underlying_x_event.xany.serial);
354 #endif
355 #ifdef HAVE_TTY
356         if (CONSOLE_TTY_P (con))
357           return HASH2 (hash, e->event.magic.underlying_tty_event);
358 #endif
359 #ifdef HAVE_MS_WINDOWS
360         if (CONSOLE_MSWINDOWS_P (con))
361           return HASH2 (hash, e->event.magic.underlying_mswindows_event);
362 #endif
363       }
364
365     case empty_event:
366     case dead_event:
367       return hash;
368
369     default:
370       abort ();
371     }
372
373   return 0; /* unreached */
374 }
375
376 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("event", event,
377                                      mark_event, print_event, 0, event_equal,
378                                      event_hash, 0, struct Lisp_Event);
379
380 \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 `make-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
775     {
776       CHECK_LIVE_EVENT (event2);
777       if (EQ (event1, event2))
778         return signal_simple_continuable_error_2
779           ("copy-event called with `eq' events", event1, event2);
780     }
781
782   assert (XEVENT_TYPE (event1) <= last_event_type);
783   assert (XEVENT_TYPE (event2) <= last_event_type);
784
785   {
786     Lisp_Event *ev2 = XEVENT (event2);
787     Lisp_Event *ev1 = XEVENT (event1);
788
789     ev2->event_type = ev1->event_type;
790     ev2->channel    = ev1->channel;
791     ev2->timestamp  = ev1->timestamp;
792     ev2->event      = ev1->event;
793
794     return event2;
795   }
796 }
797
798 \f
799
800 /* Given a chain of events (or possibly nil), deallocate them all. */
801
802 void
803 deallocate_event_chain (Lisp_Object event_chain)
804 {
805   while (!NILP (event_chain))
806     {
807       Lisp_Object next = XEVENT_NEXT (event_chain);
808       Fdeallocate_event (event_chain);
809       event_chain = next;
810     }
811 }
812
813 /* Return the last event in a chain.
814    NOTE: You cannot pass nil as a value here!  The routine will
815    abort if you do. */
816
817 Lisp_Object
818 event_chain_tail (Lisp_Object event_chain)
819 {
820   while (1)
821     {
822       Lisp_Object next = XEVENT_NEXT (event_chain);
823       if (NILP (next))
824         return event_chain;
825       event_chain = next;
826     }
827 }
828
829 /* Enqueue a single event onto the end of a chain of events.
830    HEAD points to the first event in the chain, TAIL to the last event.
831    If the chain is empty, both values should be nil. */
832
833 void
834 enqueue_event (Lisp_Object event, Lisp_Object *head, Lisp_Object *tail)
835 {
836   assert (NILP (XEVENT_NEXT (event)));
837   assert (!EQ (*tail, event));
838
839   if (!NILP (*tail))
840     XSET_EVENT_NEXT (*tail, event);
841   else
842    *head = event;
843   *tail = event;
844
845   assert (!EQ (event, XEVENT_NEXT (event)));
846 }
847
848 /* Remove an event off the head of a chain of events and return it.
849    HEAD points to the first event in the chain, TAIL to the last event. */
850
851 Lisp_Object
852 dequeue_event (Lisp_Object *head, Lisp_Object *tail)
853 {
854   Lisp_Object event;
855
856   event = *head;
857   *head = XEVENT_NEXT (event);
858   XSET_EVENT_NEXT (event, Qnil);
859   if (NILP (*head))
860     *tail = Qnil;
861   return event;
862 }
863
864 /* Enqueue a chain of events (or possibly nil) onto the end of another
865    chain of events.  HEAD points to the first event in the chain being
866    queued onto, TAIL to the last event.  If the chain is empty, both values
867    should be nil. */
868
869 void
870 enqueue_event_chain (Lisp_Object event_chain, Lisp_Object *head,
871                      Lisp_Object *tail)
872 {
873   if (NILP (event_chain))
874     return;
875
876   if (NILP (*head))
877     {
878       *head = event_chain;
879       *tail = event_chain;
880     }
881   else
882     {
883       XSET_EVENT_NEXT (*tail, event_chain);
884       *tail = event_chain_tail (event_chain);
885     }
886 }
887
888 /* Return the number of events (possibly 0) on an event chain. */
889
890 int
891 event_chain_count (Lisp_Object event_chain)
892 {
893   Lisp_Object event;
894   int n = 0;
895
896   EVENT_CHAIN_LOOP (event, event_chain)
897     n++;
898
899   return n;
900 }
901
902 /* Find the event before EVENT in an event chain.  This aborts
903    if the event is not in the chain. */
904
905 Lisp_Object
906 event_chain_find_previous (Lisp_Object event_chain, Lisp_Object event)
907 {
908   Lisp_Object previous = Qnil;
909
910   while (!NILP (event_chain))
911     {
912       if (EQ (event_chain, event))
913         return previous;
914       previous = event_chain;
915       event_chain = XEVENT_NEXT (event_chain);
916     }
917
918   abort ();
919   return Qnil;
920 }
921
922 Lisp_Object
923 event_chain_nth (Lisp_Object event_chain, int n)
924 {
925   Lisp_Object event;
926   EVENT_CHAIN_LOOP (event, event_chain)
927     {
928       if (!n)
929         return event;
930       n--;
931     }
932   return Qnil;
933 }
934
935 Lisp_Object
936 copy_event_chain (Lisp_Object event_chain)
937 {
938   Lisp_Object new_chain = Qnil;
939   Lisp_Object new_chain_tail = Qnil;
940   Lisp_Object event;
941
942   EVENT_CHAIN_LOOP (event, event_chain)
943     {
944       Lisp_Object copy = Fcopy_event (event, Qnil);
945       enqueue_event (copy, &new_chain, &new_chain_tail);
946     }
947
948   return new_chain;
949 }
950
951 \f
952
953 Lisp_Object QKbackspace, QKtab, QKlinefeed, QKreturn, QKescape,
954  QKspace, QKdelete;
955
956 int
957 command_event_p (Lisp_Object event)
958 {
959   switch (XEVENT_TYPE (event))
960     {
961     case key_press_event:
962     case button_press_event:
963     case button_release_event:
964     case misc_user_event:
965       return 1;
966     default:
967       return 0;
968     }
969 }
970
971
972 void
973 character_to_event (Emchar c, struct Lisp_Event *event, struct console *con,
974                     int use_console_meta_flag, int do_backspace_mapping)
975 {
976   Lisp_Object k = Qnil;
977   unsigned int m = 0;
978   if (event->event_type == dead_event)
979     error ("character-to-event called with a deallocated event!");
980
981 #ifndef MULE
982   c &= 255;
983 #endif
984   if (c > 127 && c <= 255)
985     {
986       int meta_flag = 1;
987       if (use_console_meta_flag && CONSOLE_TTY_P (con))
988         meta_flag = TTY_FLAGS (con).meta_key;
989       switch (meta_flag)
990         {
991         case 0: /* ignore top bit; it's parity */
992           c -= 128;
993           break;
994         case 1: /* top bit is meta */
995           c -= 128;
996           m = MOD_META;
997           break;
998         default: /* this is a real character */
999           break;
1000         }
1001     }
1002   if (c < ' ') c += '@', m |= MOD_CONTROL;
1003   if (m & MOD_CONTROL)
1004     {
1005       switch (c)
1006         {
1007         case 'I': k = QKtab;      m &= ~MOD_CONTROL; break;
1008         case 'J': k = QKlinefeed; m &= ~MOD_CONTROL; break;
1009         case 'M': k = QKreturn;   m &= ~MOD_CONTROL; break;
1010         case '[': k = QKescape;   m &= ~MOD_CONTROL; break;
1011         default:
1012 #if defined(HAVE_TTY)
1013           if (do_backspace_mapping &&
1014               CHARP (con->tty_erase_char) &&
1015               c - '@' == XCHAR (con->tty_erase_char))
1016             {
1017               k = QKbackspace;
1018               m &= ~MOD_CONTROL;
1019             }
1020 #endif /* defined(HAVE_TTY) && !defined(__CYGWIN32__) */
1021           break;
1022         }
1023       if (c >= 'A' && c <= 'Z') c -= 'A'-'a';
1024     }
1025 #if defined(HAVE_TTY)
1026   else if (do_backspace_mapping &&
1027            CHARP (con->tty_erase_char) && c == XCHAR (con->tty_erase_char))
1028     k = QKbackspace;
1029 #endif /* defined(HAVE_TTY) && !defined(__CYGWIN32__) */
1030   else if (c == 127)
1031     k = QKdelete;
1032   else if (c == ' ')
1033     k = QKspace;
1034
1035   event->event_type          = key_press_event;
1036   event->timestamp           = 0; /* #### */
1037   event->channel             = make_console (con);
1038   event->event.key.keysym    = (!NILP (k) ? k : make_char (c));
1039   event->event.key.modifiers = m;
1040 }
1041
1042
1043 /* This variable controls what character name -> character code mapping
1044    we are using.  Window-system-specific code sets this to some symbol,
1045    and we use that symbol as the plist key to convert keysyms into 8-bit
1046    codes.  In this way one can have several character sets predefined and
1047    switch them by changing this.
1048  */
1049 Lisp_Object Vcharacter_set_property;
1050
1051 Emchar
1052 event_to_character (struct Lisp_Event *event,
1053                     int allow_extra_modifiers,
1054                     int allow_meta,
1055                     int allow_non_ascii)
1056 {
1057   Emchar c = 0;
1058   Lisp_Object code;
1059
1060   if (event->event_type != key_press_event)
1061     {
1062       assert (event->event_type != dead_event);
1063       return -1;
1064     }
1065   if (!allow_extra_modifiers &&
1066       event->event.key.modifiers & (MOD_SUPER|MOD_HYPER|MOD_ALT))
1067     return -1;
1068   if (CHAR_OR_CHAR_INTP (event->event.key.keysym))
1069     c = XCHAR_OR_CHAR_INT (event->event.key.keysym);
1070   else if (!SYMBOLP (event->event.key.keysym))
1071     abort ();
1072   else if (allow_non_ascii && !NILP (Vcharacter_set_property)
1073            /* Allow window-system-specific extensibility of
1074               keysym->code mapping */
1075            && CHAR_OR_CHAR_INTP (code = Fget (event->event.key.keysym,
1076                                               Vcharacter_set_property,
1077                                               Qnil)))
1078     c = XCHAR_OR_CHAR_INT (code);
1079   else if (CHAR_OR_CHAR_INTP (code = Fget (event->event.key.keysym,
1080                                            Qascii_character, Qnil)))
1081     c = XCHAR_OR_CHAR_INT (code);
1082   else
1083     return -1;
1084
1085   if (event->event.key.modifiers & MOD_CONTROL)
1086     {
1087       if (c >= 'a' && c <= 'z')
1088         c -= ('a' - 'A');
1089       else
1090         /* reject Control-Shift- keys */
1091         if (c >= 'A' && c <= 'Z' && !allow_extra_modifiers)
1092           return -1;
1093
1094       if (c >= '@' && c <= '_')
1095         c -= '@';
1096       else if (c == ' ')  /* C-space and C-@ are the same. */
1097         c = 0;
1098       else
1099         /* reject keys that can't take Control- modifiers */
1100         if (! allow_extra_modifiers) return -1;
1101     }
1102
1103   if (event->event.key.modifiers & MOD_META)
1104     {
1105       if (! allow_meta) return -1;
1106       if (c & 0200) return -1;          /* don't allow M-oslash (overlap) */
1107 #ifdef MULE
1108       if (c >= 256) return -1;
1109 #endif
1110       c |= 0200;
1111     }
1112   return c;
1113 }
1114
1115 DEFUN ("event-to-character", Fevent_to_character, 1, 4, 0, /*
1116 Return the closest ASCII approximation to the given event object.
1117 If the event isn't a keypress, this returns nil.
1118 If the ALLOW-EXTRA-MODIFIERS argument is non-nil, then this is lenient in
1119  its translation; it will ignore modifier keys other than control and meta,
1120  and will ignore the shift modifier on those characters which have no
1121  shifted ASCII equivalent (Control-Shift-A for example, will be mapped to
1122  the same ASCII code as Control-A).
1123 If the ALLOW-META argument is non-nil, then the Meta modifier will be
1124  represented by turning on the high bit of the byte returned; otherwise, nil
1125  will be returned for events containing the Meta modifier.
1126 If the ALLOW-NON-ASCII argument is non-nil, then characters which are
1127  present in the prevailing character set (see the `character-set-property'
1128  variable) will be returned as their code in that character set, instead of
1129  the return value being restricted to ASCII.
1130 Note that specifying both ALLOW-META and ALLOW-NON-ASCII is ambiguous, as
1131  both use the high bit; `M-x' and `oslash' will be indistinguishable.
1132 */
1133      (event, allow_extra_modifiers, allow_meta, allow_non_ascii))
1134 {
1135   Emchar c;
1136   CHECK_LIVE_EVENT (event);
1137   c = event_to_character (XEVENT (event),
1138                           !NILP (allow_extra_modifiers),
1139                           !NILP (allow_meta),
1140                           !NILP (allow_non_ascii));
1141   return c < 0 ? Qnil : make_char (c);
1142 }
1143
1144 DEFUN ("character-to-event", Fcharacter_to_event, 1, 4, 0, /*
1145 Convert keystroke CH into an event structure ,replete with bucky bits.
1146 The keystroke is the first argument, and the event to fill
1147 in is the second.  This function contains knowledge about what the codes
1148 ``mean'' -- for example, the number 9 is converted to the character ``Tab'',
1149 not the distinct character ``Control-I''.
1150
1151 Note that CH (the keystroke specifier) can be an integer, a character,
1152 a symbol such as 'clear, or a list such as '(control backspace).
1153
1154 If the optional second argument is an event, it is modified;
1155 otherwise, a new event object is created.
1156
1157 Optional third arg CONSOLE is the console to store in the event, and
1158 defaults to the selected console.
1159
1160 If CH is an integer or character, the high bit may be interpreted as the
1161 meta key. (This is done for backward compatibility in lots of places.)
1162 If USE-CONSOLE-META-FLAG is nil, this will always be the case.  If
1163 USE-CONSOLE-META-FLAG is non-nil, the `meta' flag for CONSOLE affects
1164 whether the high bit is interpreted as a meta key. (See `set-input-mode'.)
1165 If you don't want this silly meta interpretation done, you should pass
1166 in a list containing the character.
1167
1168 Beware that character-to-event and event-to-character are not strictly
1169 inverse functions, since events contain much more information than the
1170 ASCII character set can encode.
1171 */
1172        (ch, event, console, use_console_meta_flag))
1173 {
1174   struct console *con = decode_console (console);
1175   if (NILP (event))
1176     event = Fmake_event (Qnil, Qnil);
1177   else
1178     CHECK_LIVE_EVENT (event);
1179   if (CONSP (ch) || SYMBOLP (ch))
1180     key_desc_list_to_event (ch, event, 1);
1181   else
1182     {
1183       CHECK_CHAR_COERCE_INT (ch);
1184       character_to_event (XCHAR (ch), XEVENT (event), con,
1185                           !NILP (use_console_meta_flag), 1);
1186     }
1187   return event;
1188 }
1189
1190 void
1191 nth_of_key_sequence_as_event (Lisp_Object seq, int n, Lisp_Object event)
1192 {
1193   assert (STRINGP (seq) || VECTORP (seq));
1194   assert (n < XINT (Flength (seq)));
1195
1196   if (STRINGP (seq))
1197     {
1198       Emchar ch = string_char (XSTRING (seq), n);
1199       Fcharacter_to_event (make_char (ch), event, Qnil, Qnil);
1200     }
1201   else
1202     {
1203       Lisp_Object keystroke = XVECTOR_DATA (seq)[n];
1204       if (EVENTP (keystroke))
1205         Fcopy_event (keystroke, event);
1206       else
1207         Fcharacter_to_event (keystroke, event, Qnil, Qnil);
1208     }
1209 }
1210
1211 Lisp_Object
1212 key_sequence_to_event_chain (Lisp_Object seq)
1213 {
1214   int len = XINT (Flength (seq));
1215   int i;
1216   Lisp_Object head = Qnil, tail = Qnil;
1217
1218   for (i = 0; i < len; i++)
1219     {
1220       Lisp_Object event = Fmake_event (Qnil, Qnil);
1221       nth_of_key_sequence_as_event (seq, i, event);
1222       enqueue_event (event, &head, &tail);
1223     }
1224
1225   return head;
1226 }
1227
1228 void
1229 format_event_object (char *buf, struct Lisp_Event *event, int brief)
1230 {
1231   int mouse_p = 0;
1232   int mod = 0;
1233   Lisp_Object key;
1234
1235   switch (event->event_type)
1236     {
1237     case key_press_event:
1238       {
1239         mod = event->event.key.modifiers;
1240         key = event->event.key.keysym;
1241         /* Hack. */
1242         if (! brief && CHARP (key) &&
1243             mod & (MOD_CONTROL | MOD_META | MOD_SUPER | MOD_HYPER))
1244         {
1245           int k = XCHAR (key);
1246           if (k >= 'a' && k <= 'z')
1247             key = make_char (k - ('a' - 'A'));
1248           else if (k >= 'A' && k <= 'Z')
1249             mod |= MOD_SHIFT;
1250         }
1251         break;
1252       }
1253     case button_release_event:
1254       mouse_p++;
1255       /* Fall through */
1256     case button_press_event:
1257       {
1258         mouse_p++;
1259         mod = event->event.button.modifiers;
1260         key = make_char (event->event.button.button + '0');
1261         break;
1262       }
1263     case magic_event:
1264       {
1265         CONST char *name = NULL;
1266
1267 #ifdef HAVE_X_WINDOWS
1268         {
1269           Lisp_Object console = CDFW_CONSOLE (EVENT_CHANNEL (event));
1270           if (CONSOLE_X_P (XCONSOLE (console)))
1271             name = x_event_name (event->event.magic.underlying_x_event.type);
1272         }
1273 #endif /* HAVE_X_WINDOWS */
1274         if (name) strcpy (buf, name);
1275         else strcpy (buf, "???");
1276         return;
1277       }
1278     case magic_eval_event:      strcpy (buf, "magic-eval"); return;
1279     case pointer_motion_event:  strcpy (buf, "motion");     return;
1280     case misc_user_event:       strcpy (buf, "misc-user");  return;
1281     case eval_event:            strcpy (buf, "eval");       return;
1282     case process_event:         strcpy (buf, "process");    return;
1283     case timeout_event:         strcpy (buf, "timeout");    return;
1284     case empty_event:           strcpy (buf, "empty");      return;
1285     case dead_event:            strcpy (buf, "DEAD-EVENT"); return;
1286     default:
1287       abort ();
1288     }
1289 #define modprint1(x)  do { strcpy (buf, (x)); buf += sizeof (x)-1; } while (0)
1290 #define modprint(x,y) do { if (brief) modprint1 (y); else modprint1 (x); } while (0)
1291   if (mod & MOD_CONTROL) modprint ("control-", "C-");
1292   if (mod & MOD_META)    modprint ("meta-",    "M-");
1293   if (mod & MOD_SUPER)   modprint ("super-",   "S-");
1294   if (mod & MOD_HYPER)   modprint ("hyper-",   "H-");
1295   if (mod & MOD_ALT)     modprint ("alt-",     "A-");
1296   if (mod & MOD_SHIFT)   modprint ("shift-",   "Sh-");
1297   if (mouse_p)
1298     {
1299       modprint1 ("button");
1300       --mouse_p;
1301     }
1302
1303 #undef modprint
1304 #undef modprint1
1305
1306   if (CHARP (key))
1307     {
1308       buf += set_charptr_emchar ((Bufbyte *) buf, XCHAR (key));
1309       *buf = 0;
1310     }
1311   else if (SYMBOLP (key))
1312     {
1313       CONST char *str = 0;
1314       if (brief)
1315         {
1316           if      (EQ (key, QKlinefeed))  str = "LFD";
1317           else if (EQ (key, QKtab))       str = "TAB";
1318           else if (EQ (key, QKreturn))    str = "RET";
1319           else if (EQ (key, QKescape))    str = "ESC";
1320           else if (EQ (key, QKdelete))    str = "DEL";
1321           else if (EQ (key, QKspace))     str = "SPC";
1322           else if (EQ (key, QKbackspace)) str = "BS";
1323         }
1324       if (str)
1325         {
1326           int i = strlen (str);
1327           memcpy (buf, str, i+1);
1328           str += i;
1329         }
1330       else
1331         {
1332           struct Lisp_String *name = XSYMBOL (key)->name;
1333           memcpy (buf, string_data (name), string_length (name) + 1);
1334           str += string_length (name);
1335         }
1336     }
1337   else
1338     abort ();
1339   if (mouse_p)
1340     strncpy (buf, "up", 4);
1341 }
1342
1343 DEFUN ("eventp", Feventp, 1, 1, 0, /*
1344 True if OBJECT is an event object.
1345 */
1346        (object))
1347 {
1348   return EVENTP (object) ? Qt : Qnil;
1349 }
1350
1351 DEFUN ("event-live-p", Fevent_live_p, 1, 1, 0, /*
1352 True if OBJECT is an event object that has not been deallocated.
1353 */
1354        (object))
1355 {
1356   return EVENTP (object) && XEVENT (object)->event_type != dead_event ?
1357     Qt : Qnil;
1358 }
1359
1360 #if 0 /* debugging functions */
1361
1362 xxDEFUN ("event-next", Fevent_next, 1, 1, 0, /*
1363 Return the event object's `next' event, or nil if it has none.
1364 The `next-event' field is changed by calling `set-next-event'.
1365 */
1366          (event))
1367 {
1368   struct Lisp_Event *e;
1369   CHECK_LIVE_EVENT (event);
1370
1371   return XEVENT_NEXT (event);
1372 }
1373
1374 xxDEFUN ("set-event-next", Fset_event_next, 2, 2, 0, /*
1375 Set the `next event' of EVENT to NEXT-EVENT.
1376 NEXT-EVENT must be an event object or nil.
1377 */
1378          (event, next_event))
1379 {
1380   Lisp_Object ev;
1381
1382   CHECK_LIVE_EVENT (event);
1383   if (NILP (next_event))
1384     {
1385       XSET_EVENT_NEXT (event, Qnil);
1386       return Qnil;
1387     }
1388
1389   CHECK_LIVE_EVENT (next_event);
1390
1391   EVENT_CHAIN_LOOP (ev, XEVENT_NEXT (event))
1392     {
1393       QUIT;
1394       if (EQ (ev, event))
1395         signal_error (Qerror,
1396                       list3 (build_string ("Cyclic event-next"),
1397                              event,
1398                              next_event));
1399     }
1400   XSET_EVENT_NEXT (event, next_event);
1401   return next_event;
1402 }
1403
1404 #endif /* 0 */
1405
1406 DEFUN ("event-type", Fevent_type, 1, 1, 0, /*
1407 Return the type of EVENT.
1408 This will be a symbol; one of
1409
1410 key-press       A key was pressed.
1411 button-press    A mouse button was pressed.
1412 button-release  A mouse button was released.
1413 misc-user       Some other user action happened; typically, this is
1414                 a menu selection or scrollbar action.
1415 motion          The mouse moved.
1416 process         Input is available from a subprocess.
1417 timeout         A timeout has expired.
1418 eval            This causes a specified action to occur when dispatched.
1419 magic           Some window-system-specific event has occurred.
1420 empty           The event has been allocated but not assigned.
1421
1422 */
1423        (event))
1424 {
1425   CHECK_LIVE_EVENT (event);
1426   switch (XEVENT (event)->event_type)
1427     {
1428     case key_press_event:       return Qkey_press;
1429     case button_press_event:    return Qbutton_press;
1430     case button_release_event:  return Qbutton_release;
1431     case misc_user_event:       return Qmisc_user;
1432     case pointer_motion_event:  return Qmotion;
1433     case process_event:         return Qprocess;
1434     case timeout_event:         return Qtimeout;
1435     case eval_event:            return Qeval;
1436     case magic_event:
1437     case magic_eval_event:
1438       return Qmagic;
1439
1440     case empty_event:
1441       return Qempty;
1442
1443     default:
1444       abort ();
1445       return Qnil;
1446     }
1447 }
1448
1449 DEFUN ("event-timestamp", Fevent_timestamp, 1, 1, 0, /*
1450 Return the timestamp of the event object EVENT.
1451 */
1452        (event))
1453 {
1454   CHECK_LIVE_EVENT (event);
1455   /* This junk is so that timestamps don't get to be negative, but contain
1456      as many bits as this particular emacs will allow.
1457    */
1458   return make_int (((1L << (VALBITS - 1)) - 1) &
1459                       XEVENT (event)->timestamp);
1460 }
1461
1462 #define CHECK_EVENT_TYPE(e,t1,sym) do {         \
1463   CHECK_LIVE_EVENT (e);                         \
1464   if (XEVENT(e)->event_type != (t1))            \
1465     e = wrong_type_argument (sym,e);            \
1466 } while (0)
1467
1468 #define CHECK_EVENT_TYPE2(e,t1,t2,sym) do {             \
1469   CHECK_LIVE_EVENT (e);                                 \
1470   {                                                     \
1471     emacs_event_type CET_type = XEVENT (e)->event_type; \
1472     if (CET_type != (t1) &&                             \
1473         CET_type != (t2))                               \
1474       e = wrong_type_argument (sym,e);                  \
1475   }                                                     \
1476 } while (0)
1477
1478 #define CHECK_EVENT_TYPE3(e,t1,t2,t3,sym) do {          \
1479   CHECK_LIVE_EVENT (e);                                 \
1480   {                                                     \
1481     emacs_event_type CET_type = XEVENT (e)->event_type; \
1482     if (CET_type != (t1) &&                             \
1483         CET_type != (t2) &&                             \
1484         CET_type != (t3))                               \
1485       e = wrong_type_argument (sym,e);                  \
1486   }                                                     \
1487 } while (0)
1488
1489 DEFUN ("event-key", Fevent_key, 1, 1, 0, /*
1490 Return the Keysym of the key-press event EVENT.
1491 This will be a character if the event is associated with one, else a symbol.
1492 */
1493        (event))
1494 {
1495   CHECK_EVENT_TYPE (event, key_press_event, Qkey_press_event_p);
1496   return XEVENT (event)->event.key.keysym;
1497 }
1498
1499 DEFUN ("event-button", Fevent_button, 1, 1, 0, /*
1500 Return the button-number of the given button-press or button-release event.
1501 */
1502        (event))
1503 {
1504
1505   CHECK_EVENT_TYPE3 (event, button_press_event, button_release_event,
1506                      misc_user_event, Qbutton_event_p);
1507 #ifdef HAVE_WINDOW_SYSTEM
1508   if ( XEVENT (event)->event_type == misc_user_event)
1509     return make_int (XEVENT (event)->event.misc.button);
1510   else
1511     return make_int (XEVENT (event)->event.button.button);
1512 #else /* !HAVE_WINDOW_SYSTEM */
1513   return Qzero;
1514 #endif /* !HAVE_WINDOW_SYSTEM */
1515
1516 }
1517
1518 DEFUN ("event-modifier-bits", Fevent_modifier_bits, 1, 1, 0, /*
1519 Return a number representing the modifier keys which were down
1520 when the given mouse or keyboard event was produced.
1521 See also the function event-modifiers.
1522 */
1523        (event))
1524 {
1525  again:
1526   CHECK_LIVE_EVENT (event);
1527   switch (XEVENT (event)->event_type)
1528     {
1529     case key_press_event:
1530       return make_int (XEVENT (event)->event.key.modifiers);
1531     case button_press_event:
1532     case button_release_event:
1533       return make_int (XEVENT (event)->event.button.modifiers);
1534     case pointer_motion_event:
1535       return make_int (XEVENT (event)->event.motion.modifiers);
1536     case misc_user_event:
1537       return make_int (XEVENT (event)->event.misc.modifiers);
1538     default:
1539       event = wrong_type_argument (intern ("key-or-mouse-event-p"), event);
1540       goto again;
1541     }
1542 }
1543
1544 DEFUN ("event-modifiers", Fevent_modifiers, 1, 1, 0, /*
1545 Return a list of symbols, the names of the modifier keys
1546 which were down when the given mouse or keyboard event was produced.
1547 See also the function event-modifier-bits.
1548 */
1549        (event))
1550 {
1551   int mod = XINT (Fevent_modifier_bits (event));
1552   Lisp_Object result = Qnil;
1553   if (mod & MOD_SHIFT)   result = Fcons (Qshift, result);
1554   if (mod & MOD_ALT)     result = Fcons (Qalt, result);
1555   if (mod & MOD_HYPER)   result = Fcons (Qhyper, result);
1556   if (mod & MOD_SUPER)   result = Fcons (Qsuper, result);
1557   if (mod & MOD_META)    result = Fcons (Qmeta, result);
1558   if (mod & MOD_CONTROL) result = Fcons (Qcontrol, result);
1559   return result;
1560 }
1561
1562 static int
1563 event_x_y_pixel_internal (Lisp_Object event, int *x, int *y, int relative)
1564 {
1565   struct window *w;
1566   struct frame *f;
1567
1568   if (XEVENT (event)->event_type == pointer_motion_event)
1569     {
1570       *x = XEVENT (event)->event.motion.x;
1571       *y = XEVENT (event)->event.motion.y;
1572     }
1573   else if (XEVENT (event)->event_type == button_press_event ||
1574            XEVENT (event)->event_type == button_release_event)
1575     {
1576       *x = XEVENT (event)->event.button.x;
1577       *y = XEVENT (event)->event.button.y;
1578     }
1579   else if (XEVENT (event)->event_type == misc_user_event)
1580     {
1581       *x = XEVENT (event)->event.misc.x;
1582       *y = XEVENT (event)->event.misc.y;
1583     }
1584   else
1585     return 0;
1586
1587   f = XFRAME (EVENT_CHANNEL (XEVENT (event)));
1588
1589   if (relative)
1590     {
1591       w = find_window_by_pixel_pos (*x, *y, f->root_window);
1592
1593       if (!w)
1594         return 1;       /* #### What should really happen here. */
1595
1596       *x -= w->pixel_left;
1597       *y -= w->pixel_top;
1598     }
1599   else
1600     {
1601       *y -= FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) -
1602         FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f);
1603       *x -= FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) -
1604         FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f);
1605     }
1606
1607   return 1;
1608 }
1609
1610 DEFUN ("event-window-x-pixel", Fevent_window_x_pixel, 1, 1, 0, /*
1611 Return the X position in pixels of mouse event EVENT.
1612 The value returned is relative to the window the event occurred in.
1613 This will signal an error if the event is not a mouse event.
1614 See also `mouse-event-p' and `event-x-pixel'.
1615 */
1616        (event))
1617 {
1618   int x, y;
1619
1620   CHECK_LIVE_EVENT (event);
1621
1622   if (!event_x_y_pixel_internal (event, &x, &y, 1))
1623     return wrong_type_argument (Qmouse_event_p, event);
1624   else
1625     return make_int (x);
1626 }
1627
1628 DEFUN ("event-window-y-pixel", Fevent_window_y_pixel, 1, 1, 0, /*
1629 Return the Y position in pixels of mouse event EVENT.
1630 The value returned is relative to the window the event occurred in.
1631 This will signal an error if the event is not a mouse event.
1632 See also `mouse-event-p' and `event-y-pixel'.
1633 */
1634        (event))
1635 {
1636   int x, y;
1637
1638   CHECK_LIVE_EVENT (event);
1639
1640   if (!event_x_y_pixel_internal (event, &x, &y, 1))
1641     return wrong_type_argument (Qmouse_event_p, event);
1642   else
1643     return make_int (y);
1644 }
1645
1646 DEFUN ("event-x-pixel", Fevent_x_pixel, 1, 1, 0, /*
1647 Return the X position in pixels of mouse event EVENT.
1648 The value returned is relative to the frame the event occurred in.
1649 This will signal an error if the event is not a mouse event.
1650 See also `mouse-event-p' and `event-window-x-pixel'.
1651 */
1652        (event))
1653 {
1654   int x, y;
1655
1656   CHECK_LIVE_EVENT (event);
1657
1658   if (!event_x_y_pixel_internal (event, &x, &y, 0))
1659     return wrong_type_argument (Qmouse_event_p, event);
1660   else
1661     return make_int (x);
1662 }
1663
1664 DEFUN ("event-y-pixel", Fevent_y_pixel, 1, 1, 0, /*
1665 Return the Y position in pixels of mouse event EVENT.
1666 The value returned is relative to the frame the event occurred in.
1667 This will signal an error if the event is not a mouse event.
1668 See also `mouse-event-p' `event-window-y-pixel'.
1669 */
1670        (event))
1671 {
1672   int x, y;
1673
1674   CHECK_LIVE_EVENT (event);
1675
1676   if (!event_x_y_pixel_internal (event, &x, &y, 0))
1677     return wrong_type_argument (Qmouse_event_p, event);
1678   else
1679     return make_int (y);
1680 }
1681
1682 /* Given an event, return a value:
1683
1684      OVER_TOOLBAR:      over one of the 4 frame toolbars
1685      OVER_MODELINE:     over a modeline
1686      OVER_BORDER:       over an internal border
1687      OVER_NOTHING:      over the text area, but not over text
1688      OVER_OUTSIDE:      outside of the frame border
1689      OVER_TEXT:         over text in the text area
1690      OVER_V_DIVIDER:    over windows vertical divider
1691
1692    and return:
1693
1694    The X char position in CHAR_X, if not a null pointer.
1695    The Y char position in CHAR_Y, if not a null pointer.
1696    (These last two values are relative to the window the event is over.)
1697    The window it's over in W, if not a null pointer.
1698    The buffer position it's over in BUFP, if not a null pointer.
1699    The closest buffer position in CLOSEST, if not a null pointer.
1700
1701    OBJ_X, OBJ_Y, OBJ1, and OBJ2 are as in pixel_to_glyph_translation().
1702 */
1703
1704 static int
1705 event_pixel_translation (Lisp_Object event, int *char_x, int *char_y,
1706                          int *obj_x, int *obj_y,
1707                          struct window **w, Bufpos *bufp, Bufpos *closest,
1708                          Charcount *modeline_closest,
1709                          Lisp_Object *obj1, Lisp_Object *obj2)
1710 {
1711   int pix_x = 0;
1712   int pix_y = 0;
1713   int result;
1714   Lisp_Object frame;
1715
1716   int ret_x, ret_y, ret_obj_x, ret_obj_y;
1717   struct window *ret_w;
1718   Bufpos ret_bufp, ret_closest;
1719   Charcount ret_modeline_closest;
1720   Lisp_Object ret_obj1, ret_obj2;
1721
1722   CHECK_LIVE_EVENT (event);
1723   frame = XEVENT (event)->channel;
1724   switch (XEVENT (event)->event_type)
1725     {
1726     case pointer_motion_event :
1727       pix_x = XEVENT (event)->event.motion.x;
1728       pix_y = XEVENT (event)->event.motion.y;
1729       break;
1730     case button_press_event :
1731     case button_release_event :
1732       pix_x = XEVENT (event)->event.button.x;
1733       pix_y = XEVENT (event)->event.button.y;
1734       break;
1735     case misc_user_event :
1736       pix_x = XEVENT (event)->event.misc.x;
1737       pix_y = XEVENT (event)->event.misc.y;
1738       break;
1739     default:
1740       dead_wrong_type_argument (Qmouse_event_p, event);
1741     }
1742
1743   result = pixel_to_glyph_translation (XFRAME (frame), pix_x, pix_y,
1744                                        &ret_x, &ret_y, &ret_obj_x, &ret_obj_y,
1745                                        &ret_w, &ret_bufp, &ret_closest,
1746                                        &ret_modeline_closest,
1747                                        &ret_obj1, &ret_obj2);
1748
1749   if (result == OVER_NOTHING || result == OVER_OUTSIDE)
1750     ret_bufp = 0;
1751   else if (ret_w && NILP (ret_w->buffer))
1752     /* Why does this happen?  (Does it still happen?)
1753        I guess the window has gotten reused as a non-leaf... */
1754     ret_w = 0;
1755
1756   /* #### pixel_to_glyph_translation() sometimes returns garbage...
1757      The word has type Lisp_Type_Record (presumably meaning `extent') but the
1758      pointer points to random memory, often filled with 0, sometimes not.
1759    */
1760   /* #### Chuck, do we still need this crap? */
1761   if (!NILP (ret_obj1) && !(GLYPHP (ret_obj1)
1762 #ifdef HAVE_TOOLBARS
1763                             || TOOLBAR_BUTTONP (ret_obj1)
1764 #endif
1765      ))
1766     abort ();
1767   if (!NILP (ret_obj2) && !(EXTENTP (ret_obj2) || CONSP (ret_obj2)))
1768     abort ();
1769
1770   if (char_x)
1771     *char_x = ret_x;
1772   if (char_y)
1773     *char_y = ret_y;
1774   if (obj_x)
1775     *obj_x = ret_obj_x;
1776   if (obj_y)
1777     *obj_y = ret_obj_y;
1778   if (w)
1779     *w = ret_w;
1780   if (bufp)
1781     *bufp = ret_bufp;
1782   if (closest)
1783     *closest = ret_closest;
1784   if (modeline_closest)
1785     *modeline_closest = ret_modeline_closest;
1786   if (obj1)
1787     *obj1 = ret_obj1;
1788   if (obj2)
1789     *obj2 = ret_obj2;
1790
1791   return result;
1792 }
1793
1794 DEFUN ("event-over-text-area-p", Fevent_over_text_area_p, 1, 1, 0, /*
1795 Return t if the mouse event EVENT occurred over the text area of a window.
1796 The modeline is not considered to be part of the text area.
1797 */
1798        (event))
1799 {
1800   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1801
1802   return result == OVER_TEXT || result == OVER_NOTHING ? Qt : Qnil;
1803 }
1804
1805 DEFUN ("event-over-modeline-p", Fevent_over_modeline_p, 1, 1, 0, /*
1806 Return t if the mouse event EVENT occurred over the modeline of a window.
1807 */
1808        (event))
1809 {
1810   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1811
1812   return result == OVER_MODELINE ? Qt : Qnil;
1813 }
1814
1815 DEFUN ("event-over-border-p", Fevent_over_border_p, 1, 1, 0, /*
1816 Return t if the mouse event EVENT occurred over an internal border.
1817 */
1818        (event))
1819 {
1820   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1821
1822   return result == OVER_BORDER ? Qt : Qnil;
1823 }
1824
1825 DEFUN ("event-over-toolbar-p", Fevent_over_toolbar_p, 1, 1, 0, /*
1826 Return t if the mouse event EVENT occurred over a toolbar.
1827 */
1828        (event))
1829 {
1830   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1831
1832   return result == OVER_TOOLBAR ? Qt : Qnil;
1833 }
1834
1835 DEFUN ("event-over-vertical-divider-p", Fevent_over_vertical_divider_p, 1, 1, 0, /*
1836 Return t if the mouse event EVENT occurred over a window divider.
1837 */
1838        (event))
1839 {
1840   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1841
1842   return result == OVER_V_DIVIDER ? Qt : Qnil;
1843 }
1844
1845 struct console *
1846 event_console_or_selected (Lisp_Object event)
1847 {
1848   Lisp_Object channel = EVENT_CHANNEL (XEVENT (event));
1849   Lisp_Object console = CDFW_CONSOLE (channel);
1850
1851   if (NILP (console))
1852     console = Vselected_console;
1853
1854   return XCONSOLE (console);
1855 }
1856
1857 DEFUN ("event-channel", Fevent_channel, 1, 1, 0, /*
1858 Return the channel that the event EVENT occurred on.
1859 This will be a frame, device, console, or nil for some types
1860 of events (e.g. eval events).
1861 */
1862        (event))
1863 {
1864   CHECK_LIVE_EVENT (event);
1865   return EVENT_CHANNEL (XEVENT (event));
1866 }
1867
1868 DEFUN ("event-window", Fevent_window, 1, 1, 0, /*
1869 Return the window over which mouse event EVENT occurred.
1870 This may be nil if the event occurred in the border or over a toolbar.
1871 The modeline is considered to be within the window it describes.
1872 */
1873        (event))
1874 {
1875   struct window *w;
1876
1877   event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, 0, 0, 0);
1878
1879   if (!w)
1880     return Qnil;
1881   else
1882     {
1883       Lisp_Object window;
1884
1885       XSETWINDOW (window, w);
1886       return window;
1887     }
1888 }
1889
1890 DEFUN ("event-point", Fevent_point, 1, 1, 0, /*
1891 Return the character position of the mouse event EVENT.
1892 If the event did not occur over a window, or did not occur over text,
1893 then this returns nil.  Otherwise, it returns a position in the buffer
1894 visible in the event's window.
1895 */
1896        (event))
1897 {
1898   Bufpos bufp;
1899   struct window *w;
1900
1901   event_pixel_translation (event, 0, 0, 0, 0, &w, &bufp, 0, 0, 0, 0);
1902
1903   return w && bufp ? make_int (bufp) : Qnil;
1904 }
1905
1906 DEFUN ("event-closest-point", Fevent_closest_point, 1, 1, 0, /*
1907 Return the character position closest to the mouse event EVENT.
1908 If the event did not occur over a window or over text, return the
1909 closest point to the location of the event.  If the Y pixel position
1910 overlaps a window and the X pixel position is to the left of that
1911 window, the closest point is the beginning of the line containing the
1912 Y position.  If the Y pixel position overlaps a window and the X pixel
1913 position is to the right of that window, the closest point is the end
1914 of the line containing the Y position.  If the Y pixel position is
1915 above a window, return 0.  If it is below the last character in a window,
1916 return the value of (window-end).
1917 */
1918        (event))
1919 {
1920   Bufpos bufp;
1921
1922   event_pixel_translation (event, 0, 0, 0, 0, 0, 0, &bufp, 0, 0, 0);
1923
1924   return bufp ? make_int (bufp) : Qnil;
1925 }
1926
1927 DEFUN ("event-x", Fevent_x, 1, 1, 0, /*
1928 Return the X 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_x;
1934
1935   event_pixel_translation (event, &char_x, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1936
1937   return make_int (char_x);
1938 }
1939
1940 DEFUN ("event-y", Fevent_y, 1, 1, 0, /*
1941 Return the Y position of the mouse event EVENT in characters.
1942 This is relative to the window the event occurred over.
1943 */
1944        (event))
1945 {
1946   int char_y;
1947
1948   event_pixel_translation (event, 0, &char_y, 0, 0, 0, 0, 0, 0, 0, 0);
1949
1950   return make_int (char_y);
1951 }
1952
1953 DEFUN ("event-modeline-position", Fevent_modeline_position, 1, 1, 0, /*
1954 Return the character position in the modeline that EVENT occurred over.
1955 EVENT should be a mouse event.  If EVENT did not occur over a modeline,
1956 nil is returned.  You can determine the actual character that the
1957 event occurred over by looking in `generated-modeline-string' at the
1958 returned character position.  Note that `generated-modeline-string'
1959 is buffer-local, and you must use EVENT's buffer when retrieving
1960 `generated-modeline-string' in order to get accurate results.
1961 */
1962        (event))
1963 {
1964   Charcount mbufp;
1965   int where;
1966
1967   where = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, &mbufp, 0, 0);
1968
1969   return (mbufp < 0 || where != OVER_MODELINE) ? Qnil : make_int (mbufp);
1970 }
1971
1972 DEFUN ("event-glyph", Fevent_glyph, 1, 1, 0, /*
1973 Return the glyph that the mouse event EVENT occurred over, or nil.
1974 */
1975        (event))
1976 {
1977   Lisp_Object glyph;
1978   struct window *w;
1979
1980   event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, 0, &glyph, 0);
1981
1982   return w && GLYPHP (glyph) ? glyph : Qnil;
1983 }
1984
1985 DEFUN ("event-glyph-extent", Fevent_glyph_extent, 1, 1, 0, /*
1986 Return the extent of the glyph that the mouse event EVENT occurred over.
1987 If the event did not occur over a glyph, nil is returned.
1988 */
1989        (event))
1990 {
1991   Lisp_Object extent;
1992   struct window *w;
1993
1994   event_pixel_translation (event, 0, 0, 0, 0, &w, 0, 0, 0, 0, &extent);
1995
1996   return w && EXTENTP (extent) ? extent : Qnil;
1997 }
1998
1999 DEFUN ("event-glyph-x-pixel", Fevent_glyph_x_pixel, 1, 1, 0, /*
2000 Return the X pixel position of EVENT relative to the glyph it occurred over.
2001 EVENT should be a mouse event.  If the event did not occur over a glyph,
2002 nil is returned.
2003 */
2004        (event))
2005 {
2006   Lisp_Object extent;
2007   struct window *w;
2008   int obj_x;
2009
2010   event_pixel_translation (event, 0, 0, &obj_x, 0, &w, 0, 0, 0, 0, &extent);
2011
2012   return w && EXTENTP (extent) ? make_int (obj_x) : Qnil;
2013 }
2014
2015 DEFUN ("event-glyph-y-pixel", Fevent_glyph_y_pixel, 1, 1, 0, /*
2016 Return the Y pixel position of EVENT relative to the glyph it occurred over.
2017 EVENT should be a mouse event.  If the event did not occur over a glyph,
2018 nil is returned.
2019 */
2020        (event))
2021 {
2022   Lisp_Object extent;
2023   struct window *w;
2024   int obj_y;
2025
2026   event_pixel_translation (event, 0, 0, 0, &obj_y, &w, 0, 0, 0, 0, &extent);
2027
2028   return w && EXTENTP (extent) ? make_int (obj_y) : Qnil;
2029 }
2030
2031 DEFUN ("event-toolbar-button", Fevent_toolbar_button, 1, 1, 0, /*
2032 Return the toolbar button that the mouse event EVENT occurred over.
2033 If the event did not occur over a toolbar button, nil is returned.
2034 */
2035        (event))
2036 {
2037 #ifdef HAVE_TOOLBARS
2038   Lisp_Object button;
2039
2040   int result = event_pixel_translation (event, 0, 0, 0, 0, 0, 0, 0, 0, &button, 0);
2041
2042   return result == OVER_TOOLBAR && TOOLBAR_BUTTONP (button) ? button : Qnil;
2043 #else
2044   return Qnil;
2045 #endif
2046 }
2047
2048 DEFUN ("event-process", Fevent_process, 1, 1, 0, /*
2049 Return the process of the given process-output event.
2050 */
2051        (event))
2052 {
2053   CHECK_EVENT_TYPE (event, process_event, Qprocess_event_p);
2054   return XEVENT (event)->event.process.process;
2055 }
2056
2057 DEFUN ("event-function", Fevent_function, 1, 1, 0, /*
2058 Return the callback function of EVENT.
2059 EVENT should be a timeout, misc-user, or eval event.
2060 */
2061        (event))
2062 {
2063  again:
2064   CHECK_LIVE_EVENT (event);
2065   switch (XEVENT (event)->event_type)
2066     {
2067     case timeout_event:
2068       return XEVENT (event)->event.timeout.function;
2069     case misc_user_event:
2070       return XEVENT (event)->event.misc.function;
2071     case eval_event:
2072       return XEVENT (event)->event.eval.function;
2073     default:
2074       event = wrong_type_argument (intern ("timeout-or-eval-event-p"), event);
2075       goto again;
2076     }
2077 }
2078
2079 DEFUN ("event-object", Fevent_object, 1, 1, 0, /*
2080 Return the callback function argument of EVENT.
2081 EVENT should be a timeout, misc-user, or eval event.
2082 */
2083        (event))
2084 {
2085  again:
2086   CHECK_LIVE_EVENT (event);
2087   switch (XEVENT (event)->event_type)
2088     {
2089     case timeout_event:
2090       return XEVENT (event)->event.timeout.object;
2091     case misc_user_event:
2092       return XEVENT (event)->event.misc.object;
2093     case eval_event:
2094       return XEVENT (event)->event.eval.object;
2095     default:
2096       event = wrong_type_argument (intern ("timeout-or-eval-event-p"), event);
2097       goto again;
2098     }
2099 }
2100
2101 DEFUN ("event-properties", Fevent_properties, 1, 1, 0, /*
2102 Return a list of all of the properties of EVENT.
2103 This is in the form of a property list (alternating keyword/value pairs).
2104 */
2105        (event))
2106 {
2107   Lisp_Object props = Qnil;
2108   struct Lisp_Event *e;
2109   struct gcpro gcpro1;
2110
2111   CHECK_LIVE_EVENT (event);
2112   e = XEVENT (event);
2113   GCPRO1 (props);
2114
2115   props = cons3 (Qtimestamp, Fevent_timestamp (event), props);
2116
2117   switch (e->event_type)
2118     {
2119     default: abort ();
2120
2121     case process_event:
2122       props = cons3 (Qprocess, e->event.process.process, props);
2123       break;
2124
2125     case timeout_event:
2126       props = cons3 (Qobject,   Fevent_object   (event), props);
2127       props = cons3 (Qfunction, Fevent_function (event), props);
2128       props = cons3 (Qid, make_int (e->event.timeout.id_number), props);
2129       break;
2130
2131     case key_press_event:
2132       props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2133       props = cons3 (Qkey,       Fevent_key       (event), props);
2134       break;
2135
2136     case button_press_event:
2137     case button_release_event:
2138       props = cons3 (Qy,         Fevent_y_pixel   (event), props);
2139       props = cons3 (Qx,         Fevent_x_pixel   (event), props);
2140       props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2141       props = cons3 (Qbutton,    Fevent_button    (event), props);
2142       break;
2143
2144     case pointer_motion_event:
2145       props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2146       props = cons3 (Qy,         Fevent_y_pixel   (event), props);
2147       props = cons3 (Qx,         Fevent_x_pixel   (event), props);
2148       break;
2149
2150     case misc_user_event:
2151       props = cons3 (Qobject,    Fevent_object  (event), props);
2152       props = cons3 (Qfunction,  Fevent_function (event), props);
2153       props = cons3 (Qy,         Fevent_y_pixel   (event), props);
2154       props = cons3 (Qx,         Fevent_x_pixel   (event), props);
2155       props = cons3 (Qmodifiers, Fevent_modifiers (event), props);
2156       props = cons3 (Qbutton,    Fevent_button    (event), props);
2157       break;
2158
2159     case eval_event:
2160       props = cons3 (Qobject,   Fevent_object   (event), props);
2161       props = cons3 (Qfunction, Fevent_function (event), props);
2162       break;
2163
2164     case magic_eval_event:
2165     case magic_event:
2166       break;
2167
2168     case empty_event:
2169       RETURN_UNGCPRO (Qnil);
2170       break;
2171     }
2172
2173   props = cons3 (Qchannel, Fevent_channel (event), props);
2174   UNGCPRO;
2175
2176   return props;
2177 }
2178
2179 \f
2180 /************************************************************************/
2181 /*                            initialization                            */
2182 /************************************************************************/
2183
2184 void
2185 syms_of_events (void)
2186 {
2187   DEFSUBR (Fcharacter_to_event);
2188   DEFSUBR (Fevent_to_character);
2189
2190   DEFSUBR (Fmake_event);
2191   DEFSUBR (Fdeallocate_event);
2192   DEFSUBR (Fcopy_event);
2193   DEFSUBR (Feventp);
2194   DEFSUBR (Fevent_live_p);
2195   DEFSUBR (Fevent_type);
2196   DEFSUBR (Fevent_properties);
2197
2198   DEFSUBR (Fevent_timestamp);
2199   DEFSUBR (Fevent_key);
2200   DEFSUBR (Fevent_button);
2201   DEFSUBR (Fevent_modifier_bits);
2202   DEFSUBR (Fevent_modifiers);
2203   DEFSUBR (Fevent_x_pixel);
2204   DEFSUBR (Fevent_y_pixel);
2205   DEFSUBR (Fevent_window_x_pixel);
2206   DEFSUBR (Fevent_window_y_pixel);
2207   DEFSUBR (Fevent_over_text_area_p);
2208   DEFSUBR (Fevent_over_modeline_p);
2209   DEFSUBR (Fevent_over_border_p);
2210   DEFSUBR (Fevent_over_toolbar_p);
2211   DEFSUBR (Fevent_over_vertical_divider_p);
2212   DEFSUBR (Fevent_channel);
2213   DEFSUBR (Fevent_window);
2214   DEFSUBR (Fevent_point);
2215   DEFSUBR (Fevent_closest_point);
2216   DEFSUBR (Fevent_x);
2217   DEFSUBR (Fevent_y);
2218   DEFSUBR (Fevent_modeline_position);
2219   DEFSUBR (Fevent_glyph);
2220   DEFSUBR (Fevent_glyph_extent);
2221   DEFSUBR (Fevent_glyph_x_pixel);
2222   DEFSUBR (Fevent_glyph_y_pixel);
2223   DEFSUBR (Fevent_toolbar_button);
2224   DEFSUBR (Fevent_process);
2225   DEFSUBR (Fevent_function);
2226   DEFSUBR (Fevent_object);
2227
2228   defsymbol (&Qeventp, "eventp");
2229   defsymbol (&Qevent_live_p, "event-live-p");
2230   defsymbol (&Qkey_press_event_p, "key-press-event-p");
2231   defsymbol (&Qbutton_event_p, "button-event-p");
2232   defsymbol (&Qmouse_event_p, "mouse-event-p");
2233   defsymbol (&Qprocess_event_p, "process-event-p");
2234   defsymbol (&Qkey_press, "key-press");
2235   defsymbol (&Qbutton_press, "button-press");
2236   defsymbol (&Qbutton_release, "button-release");
2237   defsymbol (&Qmisc_user, "misc-user");
2238   defsymbol (&Qascii_character, "ascii-character");
2239
2240   defsymbol (&QKbackspace, "backspace");
2241   defsymbol (&QKtab, "tab");
2242   defsymbol (&QKlinefeed, "linefeed");
2243   defsymbol (&QKreturn, "return");
2244   defsymbol (&QKescape, "escape");
2245   defsymbol (&QKspace, "space");
2246   defsymbol (&QKdelete, "delete");
2247 }
2248
2249
2250 void
2251 reinit_vars_of_events (void)
2252 {
2253   Vevent_resource = Qnil;
2254 }
2255
2256 void
2257 vars_of_events (void)
2258 {
2259   reinit_vars_of_events ();
2260
2261   DEFVAR_LISP ("character-set-property", &Vcharacter_set_property /*
2262 A symbol used to look up the 8-bit character of a keysym.
2263 To convert a keysym symbol to an 8-bit code, as when that key is
2264 bound to self-insert-command, we will look up the property that this
2265 variable names on the property list of the keysym-symbol.  The window-
2266 system-specific code will set up appropriate properties and set this
2267 variable.
2268 */ );
2269   Vcharacter_set_property = Qnil;
2270 }