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