XEmacs 21.2.33 "Melpomene".
[chise/xemacs-chise.git.1] / src / event-Xt.c
1 /* The event_stream interface for X11 with Xt, and/or tty frames.
2    Copyright (C) 1991-5, 1997 Free Software Foundation, Inc.
3    Copyright (C) 1995 Sun Microsystems, Inc.
4    Copyright (C) 1996 Ben Wing.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Synched up with: Not in FSF. */
24
25 #include <config.h>
26 #include "lisp.h"
27
28 #include "console-x.h"
29 #include "../lwlib/lwlib.h"
30 #include "EmacsFrame.h"
31
32 #include "blocktype.h"
33 #include "buffer.h"
34 #include "console.h"
35 #include "console-tty.h"
36 #include "events.h"
37 #include "frame.h"
38 #include "objects-x.h"
39 #include "process.h"
40 #include "redisplay.h"
41 #include "elhash.h"
42
43 #include "systime.h"
44 #include "sysproc.h" /* for MAXDESC */
45
46 #include "xintrinsicp.h"        /* CoreP.h needs this */
47 #include <X11/CoreP.h>          /* Numerous places access the fields of
48                                    a core widget directly.  We could
49                                    use XtGetValues(), but ... */
50 #include <X11/ShellP.h>
51
52 #ifdef HAVE_XIM
53 #ifdef XIM_MOTIF
54 #include <Xm/Xm.h>
55 #endif
56 #include "lstream.h"
57 #include "file-coding.h"
58 #endif
59
60 #ifdef HAVE_DRAGNDROP
61 #include "dragdrop.h"
62 #endif
63
64 #if defined (HAVE_OFFIX_DND)
65 #include "offix.h"
66 #endif
67
68 #include "events-mod.h"
69
70 static void handle_focus_event_1 (struct frame *f, int in_p);
71
72 static struct event_stream *Xt_event_stream;
73
74 /* With the new event model, all events go through XtDispatchEvent()
75    and are picked up by an event handler that is added to each frame
76    widget. (This is how it's supposed to be.) In the old method,
77    Emacs sucks out events directly from XtNextEvent() and only
78    dispatches the events that it doesn't need to deal with.  This
79    old way has lots of corresponding junk that is no longer
80    necessary: lwlib extensions, synthetic XAnyEvents, unnecessary
81    magic events, etc. */
82
83 /* The one and only one application context that Emacs uses. */
84 XtAppContext Xt_app_con;
85
86 /* Do we accept events sent by other clients? */
87 int x_allow_sendevents;
88
89 int modifier_keys_are_sticky;
90
91 #ifdef DEBUG_XEMACS
92 int x_debug_events;
93 #endif
94
95 static int process_events_occurred;
96 static int tty_events_occurred;
97
98 /* Mask of bits indicating the descriptors that we wait for input on */
99 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
100
101 static const String x_fallback_resources[] =
102 {
103   /* This file is automatically generated from the app-defaults file
104      in ../etc/Emacs.ad.  These resources are consulted only if no
105      app-defaults file is found at all.
106    */
107 #include <Emacs.ad.h>
108   0
109 };
110
111 static Lisp_Object x_keysym_to_emacs_keysym (KeySym keysym, int simple_p);
112 void emacs_Xt_mapping_action (Widget w, XEvent *event);
113 void debug_process_finalization (Lisp_Process *p);
114 void emacs_Xt_event_handler (Widget wid, XtPointer closure, XEvent *event,
115                              Boolean *continue_to_dispatch);
116
117 static int last_quit_check_signal_tick_count;
118
119 Lisp_Object Qkey_mapping;
120 Lisp_Object Qsans_modifiers;
121
122 \f
123 /************************************************************************/
124 /*                            keymap handling                           */
125 /************************************************************************/
126
127 /* X bogusly doesn't define the interpretations of any bits besides
128    ModControl, ModShift, and ModLock; so the Interclient Communication
129    Conventions Manual says that we have to bend over backwards to figure
130    out what the other modifier bits mean.  According to ICCCM:
131
132    - Any keycode which is assigned ModControl is a "control" key.
133
134    - Any modifier bit which is assigned to a keycode which generates Meta_L
135      or Meta_R is the modifier bit meaning "meta".  Likewise for Super, Hyper,
136      etc.
137
138    - Any keypress event which contains ModControl in its state should be
139      interpreted as a "control" character.
140
141    - Any keypress event which contains a modifier bit in its state which is
142      generated by a keycode whose corresponding keysym is Meta_L or Meta_R
143      should be interpreted as a "meta" character.  Likewise for Super, Hyper,
144      etc.
145
146    - It is illegal for a keysym to be associated with more than one modifier
147      bit.
148
149    This means that the only thing that emacs can reasonably interpret as a
150    "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
151    one of the modifier bits Mod1-Mod5.
152
153    Unfortunately, many keyboards don't have Meta keys in their default
154    configuration.  So, if there are no Meta keys, but there are "Alt" keys,
155    emacs will interpret Alt as Meta.  If there are both Meta and Alt keys,
156    then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
157    mean "Symbol," but that just confused the hell out of way too many people).
158
159    This works with the default configurations of the 19 keyboard-types I've
160    checked.
161
162    Emacs detects keyboard configurations which violate the above rules, and
163    prints an error message on the standard-error-output.  (Perhaps it should
164    use a pop-up-window instead.)
165  */
166
167 /* For every key on the keyboard that has a known character correspondence,
168    we define the ascii-character property of the keysym, and make the
169    default binding for the key be self-insert-command.
170
171    The following magic is basically intimate knowledge of X11/keysymdef.h.
172    The keysym mappings defined by X11 are based on the iso8859 standards,
173    except for Cyrillic and Greek.
174
175    In a non-Mule world, a user can still have a multi-lingual editor, by doing
176    (set-face-font "...-iso8859-2" (current-buffer))
177    for all their Latin-2 buffers, etc.  */
178
179 static Lisp_Object
180 x_keysym_to_character (KeySym keysym)
181 {
182 #ifdef MULE
183   Lisp_Object charset = Qzero;
184 #define USE_CHARSET(var,cs) \
185   ((var) = CHARSET_BY_LEADING_BYTE (LEADING_BYTE_##cs))
186 #else
187 #define USE_CHARSET(var,lb)
188 #endif /* MULE */
189   int code = 0;
190
191   if ((keysym & 0xff) < 0xa0)
192     return Qnil;
193
194   switch (keysym >> 8)
195     {
196     case 0: /* ASCII + Latin1 */
197       USE_CHARSET (charset, LATIN_ISO8859_1);
198       code = keysym & 0x7f;
199       break;
200     case 1: /* Latin2 */
201       USE_CHARSET (charset, LATIN_ISO8859_2);
202       code = keysym & 0x7f;
203       break;
204     case 2: /* Latin3 */
205       USE_CHARSET (charset, LATIN_ISO8859_3);
206       code = keysym & 0x7f;
207       break;
208     case 3: /* Latin4 */
209       USE_CHARSET (charset, LATIN_ISO8859_4);
210       code = keysym & 0x7f;
211       break;
212     case 4: /* Katakana */
213       USE_CHARSET (charset, KATAKANA_JISX0201);
214       if ((keysym & 0xff) > 0xa0)
215         code = keysym & 0x7f;
216       break;
217     case 5: /* Arabic */
218       USE_CHARSET (charset, ARABIC_ISO8859_6);
219       code = keysym & 0x7f;
220       break;
221     case 6: /* Cyrillic */
222       {
223         static unsigned char const cyrillic[] = /* 0x20 - 0x7f */
224         {0x00, 0x72, 0x73, 0x71, 0x74, 0x75, 0x76, 0x77,
225          0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x00, 0x7e, 0x7f,
226          0x70, 0x22, 0x23, 0x21, 0x24, 0x25, 0x26, 0x27,
227          0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x00, 0x2e, 0x2f,
228          0x6e, 0x50, 0x51, 0x66, 0x54, 0x55, 0x64, 0x53,
229          0x65, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
230          0x5f, 0x6f, 0x60, 0x61, 0x62, 0x63, 0x56, 0x52,
231          0x6c, 0x6b, 0x57, 0x68, 0x6d, 0x69, 0x67, 0x6a,
232          0x4e, 0x30, 0x31, 0x46, 0x34, 0x35, 0x44, 0x33,
233          0x45, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
234          0x3f, 0x4f, 0x40, 0x41, 0x42, 0x43, 0x36, 0x32,
235          0x4c, 0x4b, 0x37, 0x48, 0x4d, 0x49, 0x47, 0x4a};
236         USE_CHARSET (charset, CYRILLIC_ISO8859_5);
237         code = cyrillic[(keysym & 0x7f) - 0x20];
238         break;
239       }
240     case 7: /* Greek */
241       {
242         static unsigned char const greek[] = /* 0x20 - 0x7f */
243         {0x00, 0x36, 0x38, 0x39, 0x3a, 0x5a, 0x00, 0x3c,
244          0x3e, 0x5b, 0x00, 0x3f, 0x00, 0x00, 0x35, 0x2f,
245          0x00, 0x5c, 0x5d, 0x5e, 0x5f, 0x7a, 0x40, 0x7c,
246          0x7d, 0x7b, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00,
247          0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
248          0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
249          0x50, 0x51, 0x53, 0x00, 0x54, 0x55, 0x56, 0x57,
250          0x58, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251          0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
252          0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
253          0x70, 0x71, 0x73, 0x72, 0x74, 0x75, 0x76, 0x77,
254          0x78, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
255         USE_CHARSET (charset, GREEK_ISO8859_7);
256         code = greek[(keysym & 0x7f) - 0x20];
257         break;
258       }
259     case 8: /* Technical */
260       break;
261     case 9: /* Special */
262       break;
263     case 10: /* Publishing */
264       break;
265     case 11: /* APL */
266       break;
267     case 12: /* Hebrew */
268       USE_CHARSET (charset, HEBREW_ISO8859_8);
269       code = keysym & 0x7f;
270       break;
271     case 13: /* Thai */
272       /* #### This needs to deal with character composition. */
273       USE_CHARSET (charset, THAI_TIS620);
274       code = keysym & 0x7f;
275       break;
276     case 14: /* Korean Hangul */
277       break;
278     case 19: /* Latin 9 - ISO8859-15 - unsupported charset. */
279       break;
280     case 32: /* Currency */
281       break;
282     default:
283       break;
284     }
285
286   if (code == 0)
287     return Qnil;
288
289 #ifdef MULE
290   return make_char (MAKE_CHAR (charset, code, 0));
291 #else
292   return make_char (code + 0x80);
293 #endif
294 }
295
296 /* #### The way that keysym correspondence to characters should work:
297    - a Lisp_Event should contain a keysym AND a character slot.
298    - keybindings are tried with the keysym.  If no binding can be found,
299    and there is a corresponding character, call self-insert-command.
300
301    #### Nuke x-iso8859-1.el.
302    #### Nuke the Qascii_character property.
303    #### Nuke Vcharacter_set_property.
304 */
305 static void
306 maybe_define_x_key_as_self_inserting_character (KeySym keysym, Lisp_Object symbol)
307 {
308   Lisp_Object character = x_keysym_to_character (keysym);
309
310   if (CHARP (character))
311     {
312       extern Lisp_Object Vcurrent_global_map;
313       extern Lisp_Object Qascii_character;
314       Fput (symbol, Qascii_character, character);
315       if (NILP (Flookup_key (Vcurrent_global_map, symbol, Qnil)))
316         Fdefine_key (Vcurrent_global_map, symbol, Qself_insert_command);
317     }
318 }
319
320 static void
321 x_has_keysym (KeySym keysym, Lisp_Object hash_table, int with_modifiers)
322 {
323   KeySym upper_lower[2];
324   int j;
325
326   if (keysym < 0x80) /* Optimize for ASCII keysyms */
327     return;
328
329   /* If you execute:
330      xmodmap -e 'keysym NN = scaron'
331      and then press (Shift scaron), X11 will return the different
332      keysym `Scaron', but  `xmodmap -pke'  might not even mention `Scaron'.
333      So we "register" both `scaron' and `Scaron'. */
334 #ifdef HAVE_XCONVERTCASE
335   XConvertCase (keysym, &upper_lower[0], &upper_lower[1]);
336 #else
337   upper_lower[0] = upper_lower[1] = keysym;
338 #endif
339
340   for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++)
341     {
342       char *name;
343       keysym = upper_lower[j];
344
345       name = XKeysymToString (keysym);
346       if (name)
347         {
348           /* X guarantees NAME to be in the Host Portable Character Encoding */
349           Lisp_Object sym = x_keysym_to_emacs_keysym (keysym, 0);
350           Lisp_Object new_value = with_modifiers ? Qt : Qsans_modifiers;
351           Lisp_Object old_value = Fgethash (sym, hash_table, Qnil);
352
353           if (! EQ (old_value, new_value)
354               && ! (EQ (old_value, Qsans_modifiers) &&
355                     EQ (new_value, Qt)))
356             {
357               maybe_define_x_key_as_self_inserting_character (keysym, sym);
358               Fputhash (build_ext_string (name, Qbinary), new_value, hash_table);
359               Fputhash (sym, new_value, hash_table);
360             }
361         }
362     }
363 }
364
365 static void
366 x_reset_key_mapping (struct device *d)
367 {
368   Display *display = DEVICE_X_DISPLAY (d);
369   struct x_device *xd = DEVICE_X_DATA (d);
370   KeySym *keysym, *keysym_end;
371   Lisp_Object hash_table;
372   int key_code_count, keysyms_per_code;
373
374   if (xd->x_keysym_map)
375     XFree ((char *) xd->x_keysym_map);
376   XDisplayKeycodes (display,
377                     &xd->x_keysym_map_min_code,
378                     &xd->x_keysym_map_max_code);
379   key_code_count = xd->x_keysym_map_max_code - xd->x_keysym_map_min_code + 1;
380   xd->x_keysym_map =
381     XGetKeyboardMapping (display, xd->x_keysym_map_min_code, key_code_count,
382                          &xd->x_keysym_map_keysyms_per_code);
383
384   hash_table = xd->x_keysym_map_hash_table;
385   if (HASH_TABLEP (hash_table))
386     Fclrhash (hash_table);
387   else
388     xd->x_keysym_map_hash_table = hash_table =
389       make_lisp_hash_table (128, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
390
391   for (keysym = xd->x_keysym_map,
392          keysyms_per_code = xd->x_keysym_map_keysyms_per_code,
393          keysym_end = keysym + (key_code_count * keysyms_per_code);
394        keysym < keysym_end;
395        keysym += keysyms_per_code)
396     {
397       int j;
398
399       if (keysym[0] == NoSymbol)
400         continue;
401
402       x_has_keysym (keysym[0], hash_table, 0);
403
404       for (j = 1; j < keysyms_per_code; j++)
405         {
406           if (keysym[j] != keysym[0] &&
407               keysym[j] != NoSymbol)
408             x_has_keysym (keysym[j], hash_table, 1);
409         }
410     }
411 }
412
413 static const char *
414 index_to_name (int indice)
415 {
416   switch (indice)
417     {
418     case ShiftMapIndex:   return "ModShift";
419     case LockMapIndex:    return "ModLock";
420     case ControlMapIndex: return "ModControl";
421     case Mod1MapIndex:    return "Mod1";
422     case Mod2MapIndex:    return "Mod2";
423     case Mod3MapIndex:    return "Mod3";
424     case Mod4MapIndex:    return "Mod4";
425     case Mod5MapIndex:    return "Mod5";
426     default:              return "???";
427     }
428 }
429
430 /* Boy, I really wish C had local functions... */
431 struct c_doesnt_have_closures   /* #### not yet used */
432 {
433   int warned_about_overlapping_modifiers;
434   int warned_about_predefined_modifiers;
435   int warned_about_duplicate_modifiers;
436   int meta_bit;
437   int hyper_bit;
438   int super_bit;
439   int alt_bit;
440   int mode_bit;
441 };
442
443 static void
444 x_reset_modifier_mapping (struct device *d)
445 {
446   Display *display = DEVICE_X_DISPLAY (d);
447   struct x_device *xd = DEVICE_X_DATA (d);
448   int modifier_index, modifier_key, column, mkpm;
449   int warned_about_overlapping_modifiers = 0;
450   int warned_about_predefined_modifiers  = 0;
451   int warned_about_duplicate_modifiers   = 0;
452   int meta_bit  = 0;
453   int hyper_bit = 0;
454   int super_bit = 0;
455   int alt_bit   = 0;
456   int mode_bit  = 0;
457
458   xd->lock_interpretation = 0;
459
460   if (xd->x_modifier_keymap)
461     XFreeModifiermap (xd->x_modifier_keymap);
462
463   x_reset_key_mapping (d);
464
465   xd->x_modifier_keymap = XGetModifierMapping (display);
466
467   /* Boy, I really wish C had local functions...
468    */
469
470   /* The call to warn_when_safe must be on the same line as the string or
471      make-msgfile won't pick it up properly (the newline doesn't confuse
472      it, but the backslash does). */
473
474 #define modwarn(name,old,other)                                         \
475   warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates %s, which is generated by %s.", \
476                   name, code, index_to_name (old), other),              \
477   warned_about_overlapping_modifiers = 1
478
479 #define modbarf(name,other)                                                 \
480   warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates %s, which is nonsensical.", \
481                   name, code, other),                                       \
482   warned_about_predefined_modifiers = 1
483
484 #define check_modifier(name,mask)                                             \
485   if ((1<<modifier_index) != mask)                                            \
486     warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates %s, which is nonsensical.", \
487                     name, code, index_to_name (modifier_index)),              \
488     warned_about_predefined_modifiers = 1
489
490 #define store_modifier(name,old)                                           \
491   if (old && old != modifier_index)                                        \
492     warn_when_safe (Qkey_mapping, Qwarning, "XEmacs:  %s (0x%x) generates both %s and %s, which is nonsensical.",\
493                     name, code, index_to_name (old),                       \
494                     index_to_name (modifier_index)),                       \
495     warned_about_duplicate_modifiers = 1;                                  \
496   if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift");          \
497   else if (modifier_index == LockMapIndex) modbarf (name,"ModLock");       \
498   else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
499   else if (sym == XK_Mode_switch)                                          \
500     mode_bit = modifier_index; /* Mode_switch is special, see below... */  \
501   else if (modifier_index == meta_bit && old != meta_bit)                  \
502     modwarn (name, meta_bit, "Meta");                                      \
503   else if (modifier_index == super_bit && old != super_bit)                \
504     modwarn (name, super_bit, "Super");                                    \
505   else if (modifier_index == hyper_bit && old != hyper_bit)                \
506     modwarn (name, hyper_bit, "Hyper");                                    \
507   else if (modifier_index == alt_bit && old != alt_bit)                    \
508     modwarn (name, alt_bit, "Alt");                                        \
509   else                                                                     \
510     old = modifier_index;
511
512   mkpm = xd->x_modifier_keymap->max_keypermod;
513   for (modifier_index = 0; modifier_index < 8; modifier_index++)
514     for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
515       KeySym last_sym = 0;
516       for (column = 0; column < 4; column += 2) {
517         KeyCode code = xd->x_modifier_keymap->modifiermap[modifier_index * mkpm
518                                                           + modifier_key];
519         KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0);
520         if (sym == last_sym) continue;
521         last_sym = sym;
522         switch (sym) {
523         case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break;
524         case XK_Meta_L:     store_modifier ("Meta_L", meta_bit); break;
525         case XK_Meta_R:     store_modifier ("Meta_R", meta_bit); break;
526         case XK_Super_L:    store_modifier ("Super_L", super_bit); break;
527         case XK_Super_R:    store_modifier ("Super_R", super_bit); break;
528         case XK_Hyper_L:    store_modifier ("Hyper_L", hyper_bit); break;
529         case XK_Hyper_R:    store_modifier ("Hyper_R", hyper_bit); break;
530         case XK_Alt_L:      store_modifier ("Alt_L", alt_bit); break;
531         case XK_Alt_R:      store_modifier ("Alt_R", alt_bit); break;
532         case XK_Control_L:  check_modifier ("Control_L", ControlMask); break;
533         case XK_Control_R:  check_modifier ("Control_R", ControlMask); break;
534         case XK_Shift_L:    check_modifier ("Shift_L", ShiftMask); break;
535         case XK_Shift_R:    check_modifier ("Shift_R", ShiftMask); break;
536         case XK_Shift_Lock: check_modifier ("Shift_Lock", LockMask);
537           xd->lock_interpretation = XK_Shift_Lock; break;
538         case XK_Caps_Lock:  check_modifier ("Caps_Lock", LockMask);
539           xd->lock_interpretation = XK_Caps_Lock; break;
540
541         /* It probably doesn't make any sense for a modifier bit to be
542            assigned to a key that is not one of the above, but OpenWindows
543            assigns modifier bits to a couple of random function keys for
544            no reason that I can discern, so printing a warning here would
545            be annoying. */
546         }
547       }
548     }
549 #undef store_modifier
550 #undef check_modifier
551 #undef modwarn
552 #undef modbarf
553
554   /* If there was no Meta key, then try using the Alt key instead.
555      If there is both a Meta key and an Alt key, then the Alt key
556      is not disturbed and remains an Alt key. */
557   if (! meta_bit && alt_bit)
558     meta_bit = alt_bit, alt_bit = 0;
559
560   /* mode_bit overrides everything, since it's processed down inside of
561      XLookupString() instead of by us.  If Meta and Mode_switch both
562      generate the same modifier bit (which is an error), then we don't
563      interpret that bit as Meta, because we can't make XLookupString()
564      not interpret it as Mode_switch; and interpreting it as both would
565      be totally wrong. */
566   if (mode_bit)
567     {
568       const char *warn = 0;
569       if      (mode_bit == meta_bit)  warn = "Meta",  meta_bit  = 0;
570       else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
571       else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
572       else if (mode_bit == alt_bit)   warn = "Alt",   alt_bit   = 0;
573       if (warn)
574         {
575           warn_when_safe
576             (Qkey_mapping, Qwarning,
577              "XEmacs:  %s is being used for both Mode_switch and %s.",
578              index_to_name (mode_bit), warn),
579             warned_about_overlapping_modifiers = 1;
580         }
581     }
582 #undef index_to_name
583
584   xd->MetaMask   = (meta_bit   ? (1 << meta_bit)  : 0);
585   xd->HyperMask  = (hyper_bit  ? (1 << hyper_bit) : 0);
586   xd->SuperMask  = (super_bit  ? (1 << super_bit) : 0);
587   xd->AltMask    = (alt_bit    ? (1 << alt_bit)   : 0);
588   xd->ModeMask   = (mode_bit   ? (1 << mode_bit)  : 0); /* unused */
589
590
591   if (warned_about_overlapping_modifiers)
592     warn_when_safe (Qkey_mapping, Qwarning, "\n"
593 "       Two distinct modifier keys (such as Meta and Hyper) cannot generate\n"
594 "       the same modifier bit, because Emacs won't be able to tell which\n"
595 "       modifier was actually held down when some other key is pressed.  It\n"
596 "       won't be able to tell Meta-x and Hyper-x apart, for example.  Change\n"
597 "       one of these keys to use some other modifier bit.  If you intend for\n"
598 "       these keys to have the same behavior, then change them to have the\n"
599 "       same keysym as well as the same modifier bit.");
600
601   if (warned_about_predefined_modifiers)
602     warn_when_safe (Qkey_mapping, Qwarning, "\n"
603 "       The semantics of the modifier bits ModShift, ModLock, and ModControl\n"
604 "       are predefined.  It does not make sense to assign ModControl to any\n"
605 "       keysym other than Control_L or Control_R, or to assign any modifier\n"
606 "       bits to the \"control\" keysyms other than ModControl.  You can't\n"
607 "       turn a \"control\" key into a \"meta\" key (or vice versa) by simply\n"
608 "       assigning the key a different modifier bit.  You must also make that\n"
609 "       key generate an appropriate keysym (Control_L, Meta_L, etc).");
610
611   /* No need to say anything more for warned_about_duplicate_modifiers. */
612
613   if (warned_about_overlapping_modifiers || warned_about_predefined_modifiers)
614     warn_when_safe (Qkey_mapping, Qwarning, "\n"
615 "       The meanings of the modifier bits Mod1 through Mod5 are determined\n"
616 "       by the keysyms used to control those bits.  Mod1 does NOT always\n"
617 "       mean Meta, although some non-ICCCM-compliant programs assume that.");
618 }
619
620 void
621 x_init_modifier_mapping (struct device *d)
622 {
623   struct x_device *xd = DEVICE_X_DATA (d);
624   xd->x_keysym_map_hash_table = Qnil;
625   xd->x_keysym_map = NULL;
626   xd->x_modifier_keymap = NULL;
627   x_reset_modifier_mapping (d);
628 }
629
630 static int
631 x_key_is_modifier_p (KeyCode keycode, struct device *d)
632 {
633   struct x_device *xd = DEVICE_X_DATA (d);
634   KeySym *syms;
635   int i;
636
637   if (keycode < xd->x_keysym_map_min_code ||
638       keycode > xd->x_keysym_map_max_code)
639     return 0;
640
641   syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) *
642                            xd->x_keysym_map_keysyms_per_code];
643   for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
644     if (IsModifierKey (syms [i]) ||
645         syms [i] == XK_Mode_switch) /* why doesn't IsModifierKey count this? */
646       return 1;
647   return 0;
648 }
649
650 /* key-handling code is always ugly.  It just ends up working out
651    that way.
652
653    Here are some pointers:
654
655    -- DOWN_MASK indicates which modifiers should be treated as "down"
656       when the corresponding upstroke happens.  It gets reset for
657       a particular modifier when that modifier goes up, and reset
658       for all modifiers when a non-modifier key is pressed.  Example:
659
660       I press Control-A-Shift and then release Control-A-Shift.
661       I want the Shift key to be sticky but not the Control key.
662
663    -- LAST_DOWNKEY and RELEASE_TIME are used to keep track of
664       auto-repeat -- see below.
665
666    -- If a modifier key is sticky, I can unstick it by pressing
667       the modifier key again. */
668
669 static void
670 x_handle_sticky_modifiers (XEvent *ev, struct device *d)
671 {
672   struct x_device *xd;
673   KeyCode keycode;
674   int type;
675
676   if (!modifier_keys_are_sticky) /* Optimize for non-sticky modifiers */
677     return;
678
679   xd = DEVICE_X_DATA (d);
680   keycode = ev->xkey.keycode;
681   type = ev->type;
682
683   if (keycode < xd->x_keysym_map_min_code ||
684       keycode > xd->x_keysym_map_max_code)
685     return;
686
687   if (! ((type == KeyPress || type == KeyRelease) &&
688          x_key_is_modifier_p (keycode, d)))
689     { /* Not a modifier key */
690       Bool key_event_p = (type == KeyPress || type == KeyRelease);
691
692       if (type == KeyPress && !xd->last_downkey)
693         xd->last_downkey = keycode;
694       else if (type == ButtonPress ||
695                (type == KeyPress && xd->last_downkey &&
696                 (keycode != xd->last_downkey ||
697                  ev->xkey.time != xd->release_time)))
698         {
699           xd->need_to_add_mask = 0;
700           xd->last_downkey = 0;
701         }
702       if (type == KeyPress)
703         xd->release_time = 0;
704       if (type == KeyPress || type == ButtonPress)
705         xd->down_mask = 0;
706
707       if (key_event_p)
708         ev->xkey.state    |= xd->need_to_add_mask;
709       else
710         ev->xbutton.state |= xd->need_to_add_mask;
711
712       if (type == KeyRelease && keycode == xd->last_downkey)
713         /* If I hold press-and-release the Control key and then press
714            and hold down the right arrow, I want it to auto-repeat
715            Control-Right.  On the other hand, if I do the same but
716            manually press the Right arrow a bunch of times, I want
717            to see one Control-Right and then a bunch of Rights.
718            This means that we need to distinguish between an
719            auto-repeated key and a key pressed and released a bunch
720            of times.
721
722            Naturally, the designers of the X spec didn't see fit
723            to provide an obvious way to distinguish these cases.
724            So we assume that if the release and the next press
725            occur at the same time, the key was actually auto-
726            repeated.  Under Open-Windows, at least, this works. */
727         xd->release_time = key_event_p ? ev->xkey.time : ev->xbutton.time;
728     }
729   else                          /* Modifier key pressed */
730     {
731       int i;
732       KeySym *syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) *
733                                         xd->x_keysym_map_keysyms_per_code];
734
735       /* If a non-modifier key was pressed in the middle of a bunch
736          of modifiers, then it unsticks all the modifiers that were
737          previously pressed.  We cannot unstick the modifiers until
738          now because we want to check for auto-repeat of the
739          non-modifier key. */
740
741       if (xd->last_downkey)
742         {
743           xd->last_downkey = 0;
744           xd->need_to_add_mask = 0;
745         }
746
747 #define FROB(mask)                              \
748 do {                                            \
749   if (type == KeyPress)                         \
750     {                                           \
751       /* If modifier key is already sticky,     \
752          then unstick it.  Note that we do      \
753          not test down_mask to deal with the    \
754          unlikely but possible case that the    \
755          modifier key auto-repeats. */          \
756       if (xd->need_to_add_mask & mask)          \
757         {                                       \
758           xd->need_to_add_mask &= ~mask;        \
759           xd->down_mask &= ~mask;               \
760         }                                       \
761       else                                      \
762         xd->down_mask |= mask;                  \
763     }                                           \
764   else                                          \
765     {                                           \
766       if (xd->down_mask & mask)                 \
767         {                                       \
768           xd->down_mask &= ~mask;               \
769           xd->need_to_add_mask |= mask;         \
770         }                                       \
771     }                                           \
772 } while (0)
773
774       for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
775         switch (syms[i])
776           {
777           case XK_Control_L: case XK_Control_R: FROB (ControlMask);   break;
778           case XK_Shift_L:   case XK_Shift_R:   FROB (ShiftMask);     break;
779           case XK_Meta_L:    case XK_Meta_R:    FROB (xd->MetaMask);  break;
780           case XK_Super_L:   case XK_Super_R:   FROB (xd->SuperMask); break;
781           case XK_Hyper_L:   case XK_Hyper_R:   FROB (xd->HyperMask); break;
782           case XK_Alt_L:     case XK_Alt_R:     FROB (xd->AltMask);   break;
783           }
784     }
785 #undef FROB
786 }
787
788 static void
789 clear_sticky_modifiers (struct device *d)
790 {
791   struct x_device *xd = DEVICE_X_DATA (d);
792
793   xd->need_to_add_mask = 0;
794   xd->last_downkey     = 0;
795   xd->release_time     = 0;
796   xd->down_mask        = 0;
797 }
798
799 static int
800 keysym_obeys_caps_lock_p (KeySym sym, struct device *d)
801 {
802   struct x_device *xd = DEVICE_X_DATA (d);
803   /* Eeeeevil hack.  Don't apply Caps_Lock to things that aren't alphabetic
804      characters, where "alphabetic" means something more than simply A-Z.
805      That is, if Caps_Lock is down, typing ESC doesn't produce Shift-ESC.
806      But if shift-lock is down, then it does. */
807   if (xd->lock_interpretation == XK_Shift_Lock)
808     return 1;
809
810   return
811     ((sym >= XK_A)        && (sym <= XK_Z))          ||
812     ((sym >= XK_a)        && (sym <= XK_z))          ||
813     ((sym >= XK_Agrave)   && (sym <= XK_Odiaeresis)) ||
814     ((sym >= XK_agrave)   && (sym <= XK_odiaeresis)) ||
815     ((sym >= XK_Ooblique) && (sym <= XK_Thorn))      ||
816     ((sym >= XK_oslash)   && (sym <= XK_thorn));
817 }
818
819 /* called from EmacsFrame.c (actually from Xt itself) when a
820    MappingNotify event is received.  In its infinite wisdom, Xt
821    decided that Xt event handlers never get MappingNotify events.
822    O'Reilly Xt Programming Manual 9.1.2 says:
823
824    MappingNotify is automatically handled by Xt, so it isn't passed
825    to event handlers and you don't need to worry about it.
826
827    Of course, we DO worry about it, so we need a special translation. */
828 void
829 emacs_Xt_mapping_action (Widget w, XEvent* event)
830 {
831   struct device *d = get_device_from_display (event->xany.display);
832
833   if (DEVICE_X_BEING_DELETED (d))
834     return;
835 #if 0
836   /* nyet.  Now this is handled by Xt. */
837   XRefreshKeyboardMapping (&event->xmapping);
838 #endif
839   /* xmodmap generates about a billion MappingKeyboard events, followed
840      by a single MappingModifier event, so it might be worthwhile to
841      take extra MappingKeyboard events out of the queue before requesting
842      the current keymap from the server. */
843   switch (event->xmapping.request)
844     {
845     case MappingKeyboard:  x_reset_key_mapping      (d); break;
846     case MappingModifier:  x_reset_modifier_mapping (d); break;
847     case MappingPointer:   /* Do something here? */      break;
848     default: abort();
849     }
850 }
851
852 \f
853 /************************************************************************/
854 /*                  X to Emacs event conversion                         */
855 /************************************************************************/
856
857 static Lisp_Object
858 x_keysym_to_emacs_keysym (KeySym keysym, int simple_p)
859 {
860   char *name;
861   if (keysym >= XK_exclam && keysym <= XK_asciitilde)
862     /* We must assume that the X keysym numbers for the ASCII graphic
863        characters are the same as their ASCII codes.  */
864     return make_char (keysym);
865
866   switch (keysym)
867     {
868       /* These would be handled correctly by the default case, but by
869          special-casing them here we don't garbage a string or call
870          intern().  */
871     case XK_BackSpace:  return QKbackspace;
872     case XK_Tab:        return QKtab;
873     case XK_Linefeed:   return QKlinefeed;
874     case XK_Return:     return QKreturn;
875     case XK_Escape:     return QKescape;
876     case XK_space:      return QKspace;
877     case XK_Delete:     return QKdelete;
878     case 0:             return Qnil;
879     default:
880       if (simple_p) return Qnil;
881       /* !!#### not Mule-ized */
882       name = XKeysymToString (keysym);
883       if (!name || !name[0])
884         /* This happens if there is a mismatch between the Xlib of
885            XEmacs and the Xlib of the X server...
886
887            Let's hard-code in some knowledge of common keysyms introduced
888            in recent X11 releases.  Snarfed from X11/keysymdef.h
889
890            Probably we should add some stuff here for X11R6. */
891         switch (keysym)
892           {
893           case 0xFF95: return KEYSYM ("kp-home");
894           case 0xFF96: return KEYSYM ("kp-left");
895           case 0xFF97: return KEYSYM ("kp-up");
896           case 0xFF98: return KEYSYM ("kp-right");
897           case 0xFF99: return KEYSYM ("kp-down");
898           case 0xFF9A: return KEYSYM ("kp-prior");
899           case 0xFF9B: return KEYSYM ("kp-next");
900           case 0xFF9C: return KEYSYM ("kp-end");
901           case 0xFF9D: return KEYSYM ("kp-begin");
902           case 0xFF9E: return KEYSYM ("kp-insert");
903           case 0xFF9F: return KEYSYM ("kp-delete");
904
905           case 0x1005FF10: return KEYSYM ("SunF36"); /* labeled F11 */
906           case 0x1005FF11: return KEYSYM ("SunF37"); /* labeled F12 */
907           default:
908             {
909               char buf [64];
910               sprintf (buf, "unknown-keysym-0x%X", (int) keysym);
911               return KEYSYM (buf);
912             }
913           }
914       /* If it's got a one-character name, that's good enough. */
915       if (!name[1])
916         return make_char (name[0]);
917
918       /* If it's in the "Keyboard" character set, downcase it.
919          The case of those keysyms is too totally random for us to
920          force anyone to remember them.
921          The case of the other character sets is significant, however.
922          */
923       if ((((unsigned int) keysym) & (~0x1FF)) == ((unsigned int) 0xFE00))
924         {
925           char buf [255];
926           char *s1, *s2;
927           for (s1 = name, s2 = buf; *s1; s1++, s2++) {
928             if (*s1 == '_') {
929               *s2 = '-';
930             } else {
931               *s2 = tolower (* (unsigned char *) s1);
932             }
933           }
934           *s2 = 0;
935           return KEYSYM (buf);
936         }
937       return KEYSYM (name);
938     }
939 }
940
941 static Lisp_Object
942 x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p)
943      /* simple_p means don't try too hard (ASCII only) */
944 {
945   KeySym keysym = 0;
946
947 #ifdef HAVE_XIM
948   int len;
949   char buffer[64];
950   char *bufptr = buffer;
951   int   bufsiz = sizeof (buffer);
952   Status status;
953 #ifdef XIM_XLIB
954   XIC xic = FRAME_X_XIC (x_any_window_to_frame
955                          (get_device_from_display (event->display),
956                           event->window));
957 #endif /* XIM_XLIB */
958 #endif /* HAVE_XIM */
959
960   /* We use XLookupString if we're not using XIM, or are using
961      XIM_XLIB but input context creation failed. */
962 #if ! (defined (HAVE_XIM) && defined (XIM_MOTIF))
963 #if defined (HAVE_XIM) && defined (XIM_XLIB)
964      if (!xic)
965 #endif /* XIM_XLIB */
966     {
967       /* Apparently it's necessary to specify a dummy here (rather
968          than passing in 0) to avoid crashes on German IRIX */
969       char dummy[256];
970       XLookupString (event, dummy, 200, &keysym, 0);
971       return (IsModifierKey (keysym) || keysym == XK_Mode_switch )
972         ? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p);
973     }
974 #endif /* ! XIM_MOTIF */
975
976 #ifdef HAVE_XIM
977  Lookup_String: /* Come-From XBufferOverflow */
978 #ifdef XIM_MOTIF
979   len = XmImMbLookupString (XtWindowToWidget (event->display, event->window),
980                             event, bufptr, bufsiz, &keysym, &status);
981 #else /* XIM_XLIB */
982   if (xic)
983     len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status);
984 #endif /* HAVE_XIM */
985
986 #ifdef DEBUG_XEMACS
987   if (x_debug_events > 0)
988     {
989       stderr_out ("   status=");
990 #define print_status_when(S) if (status == S) stderr_out (#S)
991       print_status_when (XLookupKeySym);
992       print_status_when (XLookupBoth);
993       print_status_when (XLookupChars);
994       print_status_when (XLookupNone);
995       print_status_when (XBufferOverflow);
996
997       if (status == XLookupKeySym || status == XLookupBoth)
998         stderr_out (" keysym=%s",  XKeysymToString (keysym));
999       if (status == XLookupChars  || status == XLookupBoth)
1000         {
1001           if (len != 1)
1002             {
1003               int j;
1004               stderr_out (" chars=\"");
1005               for (j=0; j<len; j++)
1006                 stderr_out ("%c", bufptr[j]);
1007               stderr_out ("\"");
1008             }
1009           else if (bufptr[0] <= 32 || bufptr[0] >= 127)
1010             stderr_out (" char=0x%x", bufptr[0]);
1011           else
1012             stderr_out (" char=%c", bufptr[0]);
1013         }
1014       stderr_out ("\n");
1015     }
1016 #endif /* DEBUG_XEMACS */
1017
1018   switch (status)
1019     {
1020     case XLookupKeySym:
1021     case XLookupBoth:
1022       return (IsModifierKey (keysym) || keysym == XK_Mode_switch )
1023         ? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p);
1024
1025     case XLookupChars:
1026       {
1027         /* Generate multiple emacs events */
1028         struct device *d = get_device_from_display (event->display);
1029         Emchar ch;
1030         Lisp_Object instream, fb_instream;
1031         Lstream *istr;
1032         struct gcpro gcpro1, gcpro2;
1033
1034         fb_instream = make_fixed_buffer_input_stream (bufptr, len);
1035
1036         /* #### Use Fget_coding_system (Vcomposed_input_coding_system) */
1037         instream =
1038           make_decoding_input_stream (XLSTREAM (fb_instream),
1039                                       Fget_coding_system (Qundecided));
1040
1041         istr = XLSTREAM (instream);
1042
1043         GCPRO2 (instream, fb_instream);
1044         while ((ch = Lstream_get_emchar (istr)) != EOF)
1045           {
1046             Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
1047             Lisp_Event *ev          = XEVENT (emacs_event);
1048             ev->channel             = DEVICE_CONSOLE (d);
1049             ev->event_type          = key_press_event;
1050             ev->timestamp           = event->time;
1051             ev->event.key.modifiers = 0;
1052             ev->event.key.keysym    = make_char (ch);
1053             enqueue_Xt_dispatch_event (emacs_event);
1054           }
1055         Lstream_close (istr);
1056         UNGCPRO;
1057         Lstream_delete (istr);
1058         Lstream_delete (XLSTREAM (fb_instream));
1059         return Qnil;
1060       }
1061     case XLookupNone: return Qnil;
1062     case XBufferOverflow:
1063       bufptr = (char *) alloca (len+1);
1064       bufsiz = len+1;
1065       goto Lookup_String;
1066     }
1067   return Qnil; /* not reached */
1068 #endif /* HAVE_XIM */
1069 }
1070
1071 static void
1072 set_last_server_timestamp (struct device *d, XEvent *x_event)
1073 {
1074   Time t;
1075   switch (x_event->type)
1076     {
1077     case KeyPress:
1078     case KeyRelease:       t = x_event->xkey.time;              break;
1079     case ButtonPress:
1080     case ButtonRelease:    t = x_event->xbutton.time;           break;
1081     case EnterNotify:
1082     case LeaveNotify:      t = x_event->xcrossing.time;         break;
1083     case MotionNotify:     t = x_event->xmotion.time;           break;
1084     case PropertyNotify:   t = x_event->xproperty.time;         break;
1085     case SelectionClear:   t = x_event->xselectionclear.time;   break;
1086     case SelectionRequest: t = x_event->xselectionrequest.time; break;
1087     case SelectionNotify:  t = x_event->xselection.time;        break;
1088     default: return;
1089     }
1090   DEVICE_X_LAST_SERVER_TIMESTAMP (d) = t;
1091 }
1092
1093 static int
1094 x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
1095 {
1096   Display *display    = x_event->xany.display;
1097   struct device *d    = get_device_from_display (display);
1098   struct x_device *xd = DEVICE_X_DATA (d);
1099
1100   if (DEVICE_X_BEING_DELETED (d))
1101      /* #### Uh, is this 0 correct? */
1102      return 0;
1103
1104   set_last_server_timestamp (d, x_event);
1105
1106   switch (x_event->type)
1107     {
1108     case KeyRelease:
1109       x_handle_sticky_modifiers (x_event, d);
1110       return 0;
1111
1112     case KeyPress:
1113     case ButtonPress:
1114     case ButtonRelease:
1115       {
1116         int modifiers = 0;
1117         int shift_p, lock_p;
1118         Bool key_event_p = (x_event->type == KeyPress);
1119         unsigned int *state =
1120           key_event_p ? &x_event->xkey.state : &x_event->xbutton.state;
1121
1122         /* If this is a synthetic KeyPress or Button event, and the user
1123            has expressed a disinterest in this security hole, then drop
1124            it on the floor. */
1125         if ((key_event_p
1126              ? x_event->xkey.send_event
1127              : x_event->xbutton.send_event)
1128 #ifdef EXTERNAL_WIDGET
1129             /* ben: events get sent to an ExternalShell using XSendEvent.
1130                This is not a perfect solution. */
1131             && !FRAME_X_EXTERNAL_WINDOW_P
1132             (x_any_window_to_frame (d, x_event->xany.window))
1133 #endif
1134             && !x_allow_sendevents)
1135           return 0;
1136
1137         DEVICE_X_MOUSE_TIMESTAMP (d) =
1138           DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d) =
1139           key_event_p ? x_event->xkey.time : x_event->xbutton.time;
1140
1141         x_handle_sticky_modifiers (x_event, d);
1142
1143         if (*state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
1144         if (*state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
1145         if (*state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
1146         if (*state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
1147         if (*state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
1148
1149         /* Ignore the Caps_Lock key if:
1150            - any other modifiers are down, so that Caps_Lock doesn't
1151              turn C-x into C-X, which would suck.
1152            - the event was a mouse event. */
1153         if (modifiers || ! key_event_p)
1154           *state &= (~LockMask);
1155
1156         shift_p = *state & ShiftMask;
1157         lock_p  = *state & LockMask;
1158
1159         if (shift_p || lock_p)
1160           modifiers |= XEMACS_MOD_SHIFT;
1161
1162         if (key_event_p)
1163           {
1164             Lisp_Object keysym;
1165             XKeyEvent *ev = &x_event->xkey;
1166             /* This used to compute the frame from the given X window and
1167                store it here, but we really don't care about the frame. */
1168             emacs_event->channel = DEVICE_CONSOLE (d);
1169             keysym = x_to_emacs_keysym (&x_event->xkey, 0);
1170
1171             /* If the emacs keysym is nil, then that means that the X
1172                keysym was either a Modifier or NoSymbol, which
1173                probably means that we're in the midst of reading a
1174                Multi_key sequence, or a "dead" key prefix, or XIM
1175                input. Ignore it. */
1176             if (NILP (keysym))
1177               return 0;
1178
1179             /* More Caps_Lock garbage: Caps_Lock should *only* add the
1180                shift modifier to two-case keys (that is, A-Z and
1181                related characters). So at this point (after looking up
1182                the keysym) if the keysym isn't a dual-case alphabetic,
1183                and if the caps lock key was down but the shift key
1184                wasn't, then turn off the shift modifier.  Gag barf */
1185             /* #### type lossage: assuming equivalence of emacs and
1186                X keysyms */
1187             /* !!#### maybe fix for Mule */
1188             if (lock_p && !shift_p &&
1189                 ! (CHAR_OR_CHAR_INTP (keysym)
1190                    && keysym_obeys_caps_lock_p
1191                    ((KeySym) XCHAR_OR_CHAR_INT (keysym), d)))
1192               modifiers &= (~XEMACS_MOD_SHIFT);
1193
1194             /* If this key contains two distinct keysyms, that is,
1195                "shift" generates a different keysym than the
1196                non-shifted key, then don't apply the shift modifier
1197                bit: it's implicit.  Otherwise, if there would be no
1198                other way to tell the difference between the shifted
1199                and unshifted version of this key, apply the shift bit.
1200                Non-graphics, like Backspace and F1 get the shift bit
1201                in the modifiers slot.  Neither the characters "a",
1202                "A", "2", nor "@" normally have the shift bit set.
1203                However, "F1" normally does. */
1204             if (modifiers & XEMACS_MOD_SHIFT)
1205               {
1206                 int Mode_switch_p = *state & xd->ModeMask;
1207                 KeySym bot = XLookupKeysym (ev, Mode_switch_p ? 2 : 0);
1208                 KeySym top = XLookupKeysym (ev, Mode_switch_p ? 3 : 1);
1209                 if (top && bot && top != bot)
1210                   modifiers &= ~XEMACS_MOD_SHIFT;
1211               }
1212             emacs_event->event_type          = key_press_event;
1213             emacs_event->timestamp           = ev->time;
1214             emacs_event->event.key.modifiers = modifiers;
1215             emacs_event->event.key.keysym    = keysym;
1216           }
1217         else                    /* Mouse press/release event */
1218           {
1219             XButtonEvent *ev = &x_event->xbutton;
1220             struct frame *frame = x_window_to_frame (d, ev->window);
1221
1222             if (! frame)
1223               return 0; /* not for us */
1224             XSETFRAME (emacs_event->channel, frame);
1225
1226             emacs_event->event_type = (x_event->type == ButtonPress) ?
1227               button_press_event : button_release_event;
1228
1229             emacs_event->event.button.modifiers = modifiers;
1230             emacs_event->timestamp              = ev->time;
1231             emacs_event->event.button.button    = ev->button;
1232             emacs_event->event.button.x         = ev->x;
1233             emacs_event->event.button.y         = ev->y;
1234             /* because we don't seem to get a FocusIn event for button clicks
1235                when a widget-glyph is selected we will assume that we want the
1236                focus if a button gets pressed. */
1237             if (x_event->type == ButtonPress)
1238               handle_focus_event_1 (frame, 1);
1239           }
1240       }
1241     break;
1242
1243     case MotionNotify:
1244       {
1245         XMotionEvent *ev = &x_event->xmotion;
1246         struct frame *frame = x_window_to_frame (d, ev->window);
1247         int modifiers = 0;
1248         XMotionEvent event2;
1249
1250         if (! frame)
1251           return 0; /* not for us */
1252
1253         /* We use MotionHintMask, so we will get only one motion event
1254            until the next time we call XQueryPointer or the user
1255            clicks the mouse.  So call XQueryPointer now (meaning that
1256            the event will be in sync with the server just before
1257            Fnext_event() returns).  If the mouse is still in motion,
1258            then the server will immediately generate exactly one more
1259            motion event, which will be on the queue waiting for us
1260            next time around. */
1261         event2 = *ev;
1262         if (XQueryPointer (event2.display, event2.window,
1263                            &event2.root,   &event2.subwindow,
1264                            &event2.x_root, &event2.y_root,
1265                            &event2.x,      &event2.y,
1266                            &event2.state))
1267           ev = &event2; /* only one structure copy */
1268
1269         DEVICE_X_MOUSE_TIMESTAMP (d) = ev->time;
1270
1271         XSETFRAME (emacs_event->channel, frame);
1272         emacs_event->event_type     = pointer_motion_event;
1273         emacs_event->timestamp      = ev->time;
1274         emacs_event->event.motion.x = ev->x;
1275         emacs_event->event.motion.y = ev->y;
1276         if (ev->state & ShiftMask)      modifiers |= XEMACS_MOD_SHIFT;
1277         if (ev->state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
1278         if (ev->state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
1279         if (ev->state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
1280         if (ev->state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
1281         if (ev->state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
1282         /* Currently ignores Shift_Lock but probably shouldn't
1283            (but it definitely should ignore Caps_Lock). */
1284         emacs_event->event.motion.modifiers = modifiers;
1285       }
1286     break;
1287
1288     case ClientMessage:
1289       {
1290         /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is
1291            passed as the timestamp of the TAKE_FOCUS, which the ICCCM
1292            explicitly prohibits. */
1293         XClientMessageEvent *ev = &x_event->xclient;
1294 #ifdef HAVE_OFFIX_DND
1295         if (DndIsDropMessage(x_event))
1296           {
1297             unsigned int state;
1298             int modifiers = 0;
1299             unsigned int button=0;
1300             struct frame *frame = x_any_window_to_frame (d, ev->window);
1301             Extbyte *data;
1302             unsigned long size, dtype;
1303             Lisp_Object l_type = Qnil, l_data = Qnil;
1304             Lisp_Object l_dndlist = Qnil, l_item = Qnil;
1305             struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1306
1307             GCPRO4 (l_type, l_data, l_dndlist, l_item);
1308
1309             if (! frame)
1310               return 0; /* not for us */
1311             XSETFRAME (emacs_event->channel, frame);
1312
1313             emacs_event->event_type = misc_user_event;
1314             emacs_event->timestamp  = DEVICE_X_LAST_SERVER_TIMESTAMP (d);
1315
1316             state=DndDragButtons(x_event);
1317
1318             if (state & ShiftMask)      modifiers |= XEMACS_MOD_SHIFT;
1319             if (state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
1320             if (state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
1321             if (state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
1322             if (state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
1323             if (state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
1324
1325             if (state & Button5Mask)    button = Button5;
1326             if (state & Button4Mask)    button = Button4;
1327             if (state & Button3Mask)    button = Button3;
1328             if (state & Button2Mask)    button = Button2;
1329             if (state & Button1Mask)    button = Button1;
1330
1331             emacs_event->event.misc.modifiers = modifiers;
1332             emacs_event->event.misc.button    = button;
1333
1334             DndDropCoordinates(FRAME_X_TEXT_WIDGET(frame), x_event,
1335                                &(emacs_event->event.misc.x),
1336                                &(emacs_event->event.misc.y) );
1337
1338             DndGetData(x_event,&data,&size);
1339
1340             dtype=DndDataType(x_event);
1341             switch (dtype)
1342               {
1343               case DndFiles: /* null terminated strings, end null */
1344                 {
1345                   int len;
1346                   char *hurl = NULL;
1347
1348                   while (*data)
1349                     {
1350                       len = strlen ((char*)data);
1351                       hurl = dnd_url_hexify_string ((char *)data, "file:");
1352                       l_item = make_string ((Bufbyte *)hurl, strlen (hurl));
1353                       l_dndlist = Fcons (l_item, l_dndlist);
1354                       data += len + 1;
1355                       xfree (hurl);
1356                     }
1357                   l_type = Qdragdrop_URL;
1358                 }
1359                 break;
1360               case DndText:
1361                 l_type = Qdragdrop_MIME;
1362                 l_dndlist = list1 ( list3 ( list1 ( make_string ((Bufbyte *)"text/plain", 10) ),
1363                                             make_string ((Bufbyte *)"8bit", 4),
1364                                             make_ext_string ((Extbyte *)data,
1365                                                              strlen((char *)data),
1366                                                              Qctext) ) );
1367                 break;
1368               case DndMIME:
1369                 /* we have to parse this in some way to extract
1370                    content-type and params (in the tm way) and
1371                    content encoding.
1372                    OR: if data is string, let tm do the job
1373                        if data is list[2], give the first two
1374                        to tm...
1375                 */
1376                 l_type = Qdragdrop_MIME;
1377                 l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
1378                                                      strlen((char *)data),
1379                                                      Qbinary) );
1380                 break;
1381               case DndFile:
1382               case DndDir:
1383               case DndLink:
1384               case DndExe:
1385                 {
1386                   char *hurl = dnd_url_hexify_string ((char *) data, "file:");
1387
1388                   l_dndlist = list1 ( make_string ((Bufbyte *)hurl,
1389                                                    strlen (hurl)) );
1390                   l_type = Qdragdrop_URL;
1391
1392                   xfree (hurl);
1393                 }
1394                 break;
1395               case DndURL:
1396                 /* as it is a real URL it should already be escaped
1397                    and escaping again will break them (cause % is unsave) */
1398                 l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
1399                                                      strlen ((char *)data),
1400                                                      Qfile_name) );
1401                 l_type = Qdragdrop_URL;
1402                 break;
1403               default: /* Unknown, RawData and any other type */
1404                 l_dndlist = list1 ( list3 ( list1 ( make_string ((Bufbyte *)"application/octet-stream", 24) ),
1405                                             make_string ((Bufbyte *)"8bit", 4),
1406                                             make_ext_string ((Extbyte *)data,
1407                                                              size,
1408                                                              Qbinary) ) );
1409                 l_type = Qdragdrop_MIME;
1410                 break;
1411               }
1412
1413             emacs_event->event.misc.function = Qdragdrop_drop_dispatch;
1414             emacs_event->event.misc.object = Fcons (l_type, l_dndlist);
1415
1416             UNGCPRO;
1417
1418             break;
1419           }
1420 #endif /* HAVE_OFFIX_DND */
1421         if (ev->message_type == DEVICE_XATOM_WM_PROTOCOLS (d)
1422             && (Atom) (ev->data.l[0]) == DEVICE_XATOM_WM_TAKE_FOCUS (d)
1423             && (Atom) (ev->data.l[1]) == 0)
1424           {
1425             ev->data.l[1] = DEVICE_X_LAST_SERVER_TIMESTAMP (d);
1426           }
1427       }
1428     /* fall through */
1429
1430     default: /* it's a magic event */
1431       {
1432         struct frame *frame;
1433         Window w;
1434         XEvent *x_event_copy = &emacs_event->event.magic.underlying_x_event;
1435
1436 #define FROB(event_member, window_member) \
1437         x_event_copy->event_member = x_event->event_member; \
1438         w = x_event->event_member.window_member
1439
1440         switch (x_event->type)
1441           {
1442           case SelectionRequest: FROB(xselectionrequest, owner);  break;
1443           case SelectionClear:   FROB(xselectionclear, window);   break;
1444           case SelectionNotify:  FROB(xselection, requestor);     break;
1445           case PropertyNotify:   FROB(xproperty, window);         break;
1446           case ClientMessage:    FROB(xclient, window);           break;
1447           case ConfigureNotify:  FROB(xconfigure, window);        break;
1448           case Expose:
1449           case GraphicsExpose:   FROB(xexpose, window);           break;
1450           case MapNotify:
1451           case UnmapNotify:      FROB(xmap, window);              break;
1452           case EnterNotify:
1453           case LeaveNotify:      FROB(xcrossing, window);         break;
1454           case FocusIn:
1455           case FocusOut:         FROB(xfocus, window);            break;
1456           case VisibilityNotify: FROB(xvisibility, window);       break;
1457           case CreateNotify: FROB(xcreatewindow, window);         break;
1458           default:
1459             w = x_event->xany.window;
1460             *x_event_copy = *x_event;
1461             break;
1462           }
1463 #undef FROB
1464         frame = x_any_window_to_frame (d, w);
1465
1466         if (!frame)
1467           return 0;
1468
1469         emacs_event->event_type = magic_event;
1470         XSETFRAME (emacs_event->channel, frame);
1471
1472         break;
1473       }
1474     }
1475   return 1;
1476 }
1477
1478
1479 \f
1480 /************************************************************************/
1481 /*                           magic-event handling                       */
1482 /************************************************************************/
1483
1484 static void
1485 handle_focus_event_1 (struct frame *f, int in_p)
1486 {
1487 #if XtSpecificationRelease > 5
1488   Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
1489 #endif
1490 #ifdef HAVE_XIM
1491   XIM_focus_event (f, in_p);
1492 #endif /* HAVE_XIM */
1493   /* On focus change, clear all memory of sticky modifiers
1494      to avoid non-intuitive behavior. */
1495   clear_sticky_modifiers (XDEVICE (FRAME_DEVICE (f)));
1496
1497   /* We don't want to handle the focus change now, because we might
1498      be in an accept-process-output, sleep-for, or sit-for.  So
1499      we enqueue it.
1500
1501      Actually, we half handle it: we handle it as far as changing the
1502      box cursor for redisplay, but we don't call any hooks or do any
1503      select-frame stuff until after the sit-for.
1504
1505      Unfortunately native widgets break the model because they grab
1506      the keyboard focus and nothing sets it back again. I cannot find
1507      any reasonable way to do this elsewhere so we assert here that
1508      the keyboard focus is on the emacs text widget. Menus and dialogs
1509      do this in their selection callback, but we don't want that since
1510      a button having focus is legitimate. An edit field having focus
1511      is mandatory. Weirdly you get a FocusOut event when you click in
1512      a widget-glyph but you don't get a correspondng FocusIn when you
1513      click in the frame. Why is this?  */
1514   if (in_p
1515 #if XtSpecificationRelease > 5
1516       && FRAME_X_TEXT_WIDGET (f) != focus_widget
1517 #endif
1518       )
1519     {
1520       lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f),
1521                              FRAME_X_TEXT_WIDGET (f));
1522     }
1523   /* do the generic event-stream stuff. */
1524   {
1525     Lisp_Object frm;
1526     Lisp_Object conser;
1527     struct gcpro gcpro1;
1528
1529     XSETFRAME (frm, f);
1530     conser = Fcons (frm, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil));
1531     GCPRO1 (conser);
1532     emacs_handle_focus_change_preliminary (conser);
1533     enqueue_magic_eval_event (emacs_handle_focus_change_final,
1534                               conser);
1535     UNGCPRO;
1536   }
1537 }
1538
1539 /* This is called from the external-widget code */
1540
1541 void emacs_Xt_handle_focus_event (XEvent *event);
1542 void
1543 emacs_Xt_handle_focus_event (XEvent *event)
1544 {
1545   struct device *d = get_device_from_display (event->xany.display);
1546   struct frame *f;
1547
1548   if (DEVICE_X_BEING_DELETED (d))
1549     return;
1550
1551   /*
1552    * It's curious that we're using x_any_window_to_frame() instead
1553    * of x_window_to_frame().  I don't know what the impact of this is.
1554    */
1555   f = x_any_window_to_frame (d, event->xfocus.window);
1556   if (!f)
1557     /* focus events are sometimes generated just before
1558        a frame is destroyed. */
1559     return;
1560   handle_focus_event_1 (f, event->type == FocusIn);
1561 }
1562
1563 /* both MapNotify and VisibilityNotify can cause this
1564    JV is_visible has the same semantics as f->visible*/
1565 static void
1566 change_frame_visibility (struct frame *f, int is_visible)
1567 {
1568   Lisp_Object frame;
1569
1570   XSETFRAME (frame, f);
1571
1572   if (!FRAME_VISIBLE_P (f) && is_visible)
1573     {
1574       FRAME_VISIBLE_P (f) = is_visible;
1575       /* This improves the double flicker when uniconifying a frame
1576          some.  A lot of it is not showing a buffer which has changed
1577          while the frame was iconified.  To fix it further requires
1578          the good 'ol double redisplay structure. */
1579       MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1580       va_run_hook_with_args (Qmap_frame_hook, 1, frame);
1581     }
1582   else if (FRAME_VISIBLE_P (f) && !is_visible)
1583     {
1584       FRAME_VISIBLE_P (f) = 0;
1585       va_run_hook_with_args (Qunmap_frame_hook, 1, frame);
1586     }
1587   else if (FRAME_VISIBLE_P (f) * is_visible < 0)
1588     {
1589       FRAME_VISIBLE_P(f) = - FRAME_VISIBLE_P(f);
1590       if (FRAME_REPAINT_P(f))
1591               MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1592       va_run_hook_with_args (Qmap_frame_hook, 1, frame);
1593     }
1594 }
1595
1596 static void
1597 handle_map_event (struct frame *f, XEvent *event)
1598 {
1599   Lisp_Object frame;
1600
1601   XSETFRAME (frame, f);
1602   if (event->type == MapNotify)
1603     {
1604       XWindowAttributes xwa;
1605
1606       /* Bleagh!!!!!!  Apparently some window managers (e.g. MWM)
1607          send synthetic MapNotify events when a window is first
1608          created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE.
1609          Or something like that.  We initially tried a different
1610          solution below, but that ran into a different window-
1611          manager bug.
1612
1613          It seems that the only reliable way is to treat a
1614          MapNotify event as a "hint" that the window might or
1615          might not be visible, and check explicitly. */
1616
1617       XGetWindowAttributes (event->xany.display, event->xmap.window,
1618                             &xwa);
1619       if (xwa.map_state != IsViewable)
1620         {
1621           /* Calling Fframe_iconified_p is the only way we have to
1622              correctly update FRAME_ICONIFIED_P */
1623           Fframe_iconified_p (frame);
1624           return;
1625         }
1626
1627       FRAME_X_TOTALLY_VISIBLE_P (f) = 1;
1628 #if 0
1629       /* Bleagh again!!!!  We initially tried the following hack
1630          around the MWM problem, but it turns out that TWM
1631          has a race condition when you un-iconify, where it maps
1632          the window and then tells the server that the window
1633          is un-iconified.  Usually, XEmacs wakes up between
1634          those two occurrences, and thus thinks that un-iconified
1635          windows are still iconified.
1636
1637          Ah, the joys of X. */
1638
1639       /* By Emacs definition, a frame that is iconified is not
1640          visible.  Marking a frame as visible will automatically cause
1641          frame-iconified-p to return nil, regardless of whether the
1642          frame is actually iconified.  Therefore, we have to ignore
1643          MapNotify events on iconified frames. (It's not obvious
1644          to me why these are being sent, but it happens at startup
1645          with frames that are initially iconified; perhaps they are
1646          synthetic MapNotify events coming from the window manager.)
1647          Note that `frame-iconified-p' queries the server
1648          to determine whether the frame is currently iconified,
1649          rather than consulting some internal (and likely
1650          inaccurate) state flag.  Therefore, ignoring the MapNotify
1651          is correct. */
1652       if (!FRAME_VISIBLE_P (f) && NILP (Fframe_iconified_p (frame)))
1653 #endif /* 0 */
1654         change_frame_visibility (f, 1);
1655     }
1656   else
1657     {
1658       FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
1659       change_frame_visibility (f, 0);
1660       /* Calling Fframe_iconified_p is the only way we have to
1661          correctly update FRAME_ICONIFIED_P */
1662       Fframe_iconified_p (frame);
1663     }
1664 }
1665
1666 static void
1667 handle_client_message (struct frame *f, XEvent *event)
1668 {
1669   struct device *d = XDEVICE (FRAME_DEVICE (f));
1670   Lisp_Object frame;
1671
1672   XSETFRAME (frame, f);
1673
1674   if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) &&
1675       (Atom) (event->xclient.data.l[0]) == DEVICE_XATOM_WM_DELETE_WINDOW (d))
1676     {
1677       /* WM_DELETE_WINDOW is a misc-user event, but other ClientMessages,
1678          such as WM_TAKE_FOCUS, are eval events.  That's because delete-window
1679          was probably executed with a mouse click, while the others could
1680          have been sent as a result of mouse motion or some other implicit
1681          action.  (Call this a "heuristic"...)  The reason for caring about
1682          this is so that clicking on the close-box will make emacs prompt
1683          using a dialog box instead of the minibuffer if there are unsaved
1684          buffers.
1685          */
1686       enqueue_misc_user_event (frame, Qeval,
1687                                list3 (Qdelete_frame, frame, Qt));
1688     }
1689   else if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) &&
1690            (Atom) event->xclient.data.l[0] == DEVICE_XATOM_WM_TAKE_FOCUS (d))
1691     {
1692       handle_focus_event_1 (f, 1);
1693 #if 0
1694       /* If there is a dialog box up, focus on it.
1695
1696          #### Actually, we're raising it too, which is wrong.  We should
1697          #### just focus on it, but lwlib doesn't currently give us an
1698          #### easy way to do that.  This should be fixed.
1699          */
1700       unsigned long take_focus_timestamp = event->xclient.data.l[1];
1701       Widget widget = lw_raise_all_pop_up_widgets ();
1702       if (widget)
1703         {
1704           /* kludge: raise_all returns bottommost widget, but we really
1705              want the topmost.  So just raise it for now. */
1706           XMapRaised (XtDisplay (widget), XtWindow (widget));
1707           /* Grab the focus with the timestamp of the TAKE_FOCUS. */
1708           XSetInputFocus (XtDisplay (widget), XtWindow (widget),
1709                           RevertToParent, take_focus_timestamp);
1710         }
1711 #endif
1712     }
1713 }
1714
1715 static void
1716 emacs_Xt_force_event_pending (struct frame* f)
1717 {
1718   XEvent event;
1719
1720   Display* dpy = DEVICE_X_DISPLAY (XDEVICE (FRAME_DEVICE  (f)));
1721   event.xclient.type            = ClientMessage;
1722   event.xclient.display         = dpy;
1723   event.xclient.message_type    = XInternAtom (dpy, "BumpQueue", False);
1724   event.xclient.format          = 32;
1725   event.xclient.window          = 0;
1726
1727   /* Send the drop message */
1728   XSendEvent(dpy, XtWindow (FRAME_X_SHELL_WIDGET (f)),
1729              True, NoEventMask, &event);
1730   /* Force event pending to check the X queue. */
1731   quit_check_signal_tick_count++;
1732 }
1733
1734 static void
1735 emacs_Xt_handle_magic_event (Lisp_Event *emacs_event)
1736 {
1737   /* This function can GC */
1738   XEvent *event = &emacs_event->event.magic.underlying_x_event;
1739   struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event));
1740
1741   if (!FRAME_LIVE_P (f) || DEVICE_X_BEING_DELETED (XDEVICE (FRAME_DEVICE (f))))
1742     return;
1743
1744   switch (event->type)
1745     {
1746     case SelectionRequest:
1747       x_handle_selection_request (&event->xselectionrequest);
1748       break;
1749
1750     case SelectionClear:
1751       x_handle_selection_clear (&event->xselectionclear);
1752       break;
1753
1754     case SelectionNotify:
1755       x_handle_selection_notify (&event->xselection);
1756       break;
1757
1758     case PropertyNotify:
1759       x_handle_property_notify (&event->xproperty);
1760       break;
1761
1762     case Expose:
1763       if (!check_for_ignored_expose (f, event->xexpose.x, event->xexpose.y,
1764                                      event->xexpose.width, event->xexpose.height)
1765           &&
1766           !find_matching_subwindow (f, event->xexpose.x, event->xexpose.y,
1767           event->xexpose.width, event->xexpose.height))
1768         x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
1769                                event->xexpose.width, event->xexpose.height);
1770       break;
1771
1772     case GraphicsExpose: /* This occurs when an XCopyArea's source area was
1773                             obscured or not available. */
1774       x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
1775                              event->xexpose.width, event->xexpose.height);
1776       break;
1777
1778     case MapNotify:
1779     case UnmapNotify:
1780       handle_map_event (f, event);
1781       break;
1782
1783     case EnterNotify:
1784       if (event->xcrossing.detail != NotifyInferior)
1785         {
1786           Lisp_Object frame;
1787
1788           XSETFRAME (frame, f);
1789           /* FRAME_X_MOUSE_P (f) = 1; */
1790           va_run_hook_with_args (Qmouse_enter_frame_hook, 1, frame);
1791         }
1792       break;
1793
1794     case LeaveNotify:
1795       if (event->xcrossing.detail != NotifyInferior)
1796         {
1797           Lisp_Object frame;
1798
1799           XSETFRAME (frame, f);
1800           /* FRAME_X_MOUSE_P (f) = 0; */
1801           va_run_hook_with_args (Qmouse_leave_frame_hook, 1, frame);
1802         }
1803       break;
1804
1805     case FocusIn:
1806     case FocusOut:
1807
1808 #ifdef EXTERNAL_WIDGET
1809       /* External widget lossage: Ben said:
1810          YUCK.  The only way to make focus changes work properly is to
1811          completely ignore all FocusIn/FocusOut events and depend only
1812          on notifications from the ExternalClient widget. */
1813       if (FRAME_X_EXTERNAL_WINDOW_P (f))
1814         break;
1815 #endif
1816       handle_focus_event_1 (f, event->type == FocusIn);
1817       break;
1818
1819     case ClientMessage:
1820       handle_client_message (f, event);
1821       break;
1822
1823     case VisibilityNotify: /* window visibility has changed */
1824       if (event->xvisibility.window == XtWindow (FRAME_X_SHELL_WIDGET (f)))
1825         {
1826           FRAME_X_TOTALLY_VISIBLE_P (f) =
1827             (event->xvisibility.state == VisibilityUnobscured);
1828           /* Note that the fvwm pager only sends VisibilityNotify when
1829              changing pages. Is this all we need to do ? JV */
1830           /* Nope.  We must at least trigger a redisplay here.
1831              Since this case seems similar to MapNotify, I've
1832              factored out some code to change_frame_visibility().
1833              This triggers the necessary redisplay and runs
1834              (un)map-frame-hook.  - dkindred@cs.cmu.edu */
1835           /* Changed it again to support the tristate visibility flag */
1836           change_frame_visibility (f, (event->xvisibility.state
1837                                        != VisibilityFullyObscured) ? 1 : -1);
1838         }
1839       break;
1840
1841     case ConfigureNotify:
1842 #ifdef HAVE_XIM
1843       XIM_SetGeometry (f);
1844 #endif
1845       break;
1846
1847     case CreateNotify:
1848       break;
1849
1850     default:
1851       break;
1852     }
1853 }
1854
1855 \f
1856 /************************************************************************/
1857 /*                              timeout events                          */
1858 /************************************************************************/
1859
1860 static int timeout_id_tick;
1861
1862 /* Xt interval id's might not fit into an int (they're pointers, as it
1863    happens), so we need to provide a conversion list. */
1864
1865 static struct Xt_timeout
1866 {
1867   int id;
1868   XtIntervalId interval_id;
1869   struct Xt_timeout *next;
1870 } *pending_timeouts, *completed_timeouts;
1871
1872 static struct Xt_timeout_blocktype
1873 {
1874   Blocktype_declare (struct Xt_timeout);
1875 } *the_Xt_timeout_blocktype;
1876
1877 /* called by XtAppNextEvent() */
1878 static void
1879 Xt_timeout_callback (XtPointer closure, XtIntervalId *id)
1880 {
1881   struct Xt_timeout *timeout = (struct Xt_timeout *) closure;
1882   struct Xt_timeout *t2 = pending_timeouts;
1883   /* Remove this one from the list of pending timeouts */
1884   if (t2 == timeout)
1885     pending_timeouts = pending_timeouts->next;
1886   else
1887     {
1888       while (t2->next && t2->next != timeout) t2 = t2->next;
1889       assert (t2->next);
1890       t2->next = t2->next->next;
1891     }
1892   /* Add this one to the list of completed timeouts */
1893   timeout->next = completed_timeouts;
1894   completed_timeouts = timeout;
1895 }
1896
1897 static int
1898 emacs_Xt_add_timeout (EMACS_TIME thyme)
1899 {
1900   struct Xt_timeout *timeout = Blocktype_alloc (the_Xt_timeout_blocktype);
1901   EMACS_TIME current_time;
1902   int milliseconds;
1903
1904   timeout->id = timeout_id_tick++;
1905   timeout->next = pending_timeouts;
1906   pending_timeouts = timeout;
1907   EMACS_GET_TIME (current_time);
1908   EMACS_SUB_TIME (thyme, thyme, current_time);
1909   milliseconds = EMACS_SECS (thyme) * 1000 +
1910     EMACS_USECS (thyme) / 1000;
1911   if (milliseconds < 1)
1912     milliseconds = 1;
1913   timeout->interval_id = XtAppAddTimeOut (Xt_app_con, milliseconds,
1914                                           Xt_timeout_callback,
1915                                           (XtPointer) timeout);
1916   return timeout->id;
1917 }
1918
1919 static void
1920 emacs_Xt_remove_timeout (int id)
1921 {
1922   struct Xt_timeout *timeout, *t2;
1923
1924   timeout = NULL;
1925
1926   /* Find the timeout on the list of pending ones, if it's still there. */
1927   if (pending_timeouts)
1928     {
1929       if (id == pending_timeouts->id)
1930         {
1931           timeout = pending_timeouts;
1932           pending_timeouts = pending_timeouts->next;
1933         }
1934       else
1935         {
1936           t2 = pending_timeouts;
1937           while (t2->next && t2->next->id != id) t2 = t2->next;
1938           if ( t2->next)   /*found it */
1939             {
1940               timeout = t2->next;
1941               t2->next = t2->next->next;
1942             }
1943         }
1944       /* if it was pending, we have removed it from the list */
1945       if (timeout)
1946         XtRemoveTimeOut (timeout->interval_id);
1947     }
1948
1949   /* It could be that the Xt call back was already called but we didn't convert
1950      into an Emacs event yet */
1951   if (!timeout && completed_timeouts)
1952     {
1953       /* Code duplication! */
1954       if (id == completed_timeouts->id)
1955         {
1956           timeout = completed_timeouts;
1957           completed_timeouts = completed_timeouts->next;
1958         }
1959       else
1960         {
1961           t2 = completed_timeouts;
1962           while (t2->next && t2->next->id != id) t2 = t2->next;
1963           if ( t2->next)   /*found it */
1964             {
1965               timeout = t2->next;
1966               t2->next = t2->next->next;
1967             }
1968         }
1969     }
1970
1971   /* If we found the thing on the lists of timeouts,
1972      and removed it, deallocate
1973   */
1974   if (timeout)
1975     Blocktype_free (the_Xt_timeout_blocktype, timeout);
1976 }
1977
1978 static void
1979 Xt_timeout_to_emacs_event (Lisp_Event *emacs_event)
1980 {
1981   struct Xt_timeout *timeout = completed_timeouts;
1982   assert (timeout);
1983   completed_timeouts = completed_timeouts->next;
1984   emacs_event->event_type = timeout_event;
1985   /* timeout events have nil as channel */
1986   emacs_event->timestamp  = 0; /* #### wrong!! */
1987   emacs_event->event.timeout.interval_id = timeout->id;
1988   emacs_event->event.timeout.function = Qnil;
1989   emacs_event->event.timeout.object = Qnil;
1990   Blocktype_free (the_Xt_timeout_blocktype, timeout);
1991 }
1992
1993 \f
1994 /************************************************************************/
1995 /*                      process and tty events                          */
1996 /************************************************************************/
1997
1998 struct what_is_ready_closure
1999 {
2000   int fd;
2001   Lisp_Object what;
2002   XtInputId id;
2003 };
2004
2005 static Lisp_Object *filedesc_with_input;
2006 static struct what_is_ready_closure **filedesc_to_what_closure;
2007
2008 static void
2009 init_what_input_once (void)
2010 {
2011   int i;
2012
2013   filedesc_with_input = xnew_array (Lisp_Object, MAXDESC);
2014   filedesc_to_what_closure =
2015     xnew_array (struct what_is_ready_closure *, MAXDESC);
2016
2017   for (i = 0; i < MAXDESC; i++)
2018     {
2019       filedesc_to_what_closure[i] = 0;
2020       filedesc_with_input[i] = Qnil;
2021     }
2022
2023   process_events_occurred = 0;
2024   tty_events_occurred = 0;
2025 }
2026
2027 static void
2028 mark_what_as_being_ready (struct what_is_ready_closure *closure)
2029 {
2030   if (NILP (filedesc_with_input[closure->fd]))
2031     {
2032       SELECT_TYPE temp_mask;
2033       FD_ZERO (&temp_mask);
2034       FD_SET (closure->fd, &temp_mask);
2035       /* Check to make sure there's *really* input available.
2036          Sometimes things seem to get confused and this gets called
2037          for the tty fd when there's really only input available
2038          on some process's fd.  (It will subsequently get called
2039          for that process's fd, so returning without setting any
2040          flags will take care of it.)  To see the problem, uncomment
2041          the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS
2042          down to 25, do sh -c 'xemacs -nw -q -f shell 2>/tmp/log'
2043          and press return repeatedly.  (Seen under AIX & Linux.)
2044          -dkindred@cs.cmu.edu */
2045       if (!poll_fds_for_input (temp_mask))
2046         {
2047 #if 0
2048           stderr_out ("mark_what_as_being_ready: no input available (fd=%d)\n",
2049                       closure->fd);
2050 #endif
2051           return;
2052         }
2053       filedesc_with_input[closure->fd] = closure->what;
2054       if (PROCESSP (closure->what))
2055       /* Don't increment this if the current process is already marked
2056        *  as having input. */
2057         process_events_occurred++;
2058       else
2059         tty_events_occurred++;
2060     }
2061 }
2062
2063 static void
2064 Xt_what_callback (void *closure, int *source, XtInputId *id)
2065 {
2066   /* If closure is 0, then we got a fake event from a signal handler.
2067      The only purpose of this is to make XtAppProcessEvent() stop
2068      blocking. */
2069   if (closure)
2070     mark_what_as_being_ready ((struct what_is_ready_closure *) closure);
2071   else
2072     {
2073       fake_event_occurred++;
2074       drain_signal_event_pipe ();
2075     }
2076 }
2077
2078 static void
2079 select_filedesc (int fd, Lisp_Object what)
2080 {
2081   struct what_is_ready_closure *closure;
2082
2083   /* If somebody is trying to select something that's already selected
2084      for, then something went wrong.  The generic routines ought to
2085      detect this and error before here. */
2086   assert (!filedesc_to_what_closure[fd]);
2087
2088   closure = xnew (struct what_is_ready_closure);
2089   closure->fd = fd;
2090   closure->what = what;
2091   closure->id =
2092     XtAppAddInput (Xt_app_con, fd,
2093                    (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
2094                    Xt_what_callback, closure);
2095   filedesc_to_what_closure[fd] = closure;
2096 }
2097
2098 static void
2099 unselect_filedesc (int fd)
2100 {
2101   struct what_is_ready_closure *closure = filedesc_to_what_closure[fd];
2102
2103   assert (closure);
2104   if (!NILP (filedesc_with_input[fd]))
2105     {
2106       /* We are unselecting this process before we have drained the rest of
2107          the input from it, probably from status_notify() in the command loop.
2108          This can happen like so:
2109
2110           - We are waiting in XtAppNextEvent()
2111           - Process generates output
2112           - Process is marked as being ready
2113           - Process dies, SIGCHLD gets generated before we return (!?)
2114             It could happen I guess.
2115           - sigchld_handler() marks process as dead
2116           - Somehow we end up getting a new KeyPress event on the queue
2117             at the same time (I'm really so sure how that happens but I'm
2118             not sure it can't either so let's assume it can...).
2119           - Key events have priority so we return that instead of the proc.
2120           - Before dispatching the lisp key event we call status_notify()
2121           - Which deselects the process that SIGCHLD marked as dead.
2122
2123          Thus we never remove it from _with_input and turn it into a lisp
2124          event, so we need to do it here.  But this does not mean that we're
2125          throwing away the last block of output - status_notify() has already
2126          taken care of running the proc filter or whatever.
2127        */
2128       filedesc_with_input[fd] = Qnil;
2129       if (PROCESSP (closure->what))
2130         {
2131           assert (process_events_occurred > 0);
2132           process_events_occurred--;
2133         }
2134       else
2135         {
2136           assert (tty_events_occurred > 0);
2137           tty_events_occurred--;
2138         }
2139     }
2140   XtRemoveInput (closure->id);
2141   xfree (closure);
2142   filedesc_to_what_closure[fd] = 0;
2143 }
2144
2145 static void
2146 emacs_Xt_select_process (Lisp_Process *p)
2147 {
2148   Lisp_Object process;
2149   int infd = event_stream_unixoid_select_process (p);
2150
2151   XSETPROCESS (process, p);
2152   select_filedesc (infd, process);
2153 }
2154
2155 static void
2156 emacs_Xt_unselect_process (Lisp_Process *p)
2157 {
2158   int infd = event_stream_unixoid_unselect_process (p);
2159
2160   unselect_filedesc (infd);
2161 }
2162
2163 static USID
2164 emacs_Xt_create_stream_pair (void* inhandle, void* outhandle,
2165                 Lisp_Object* instream, Lisp_Object* outstream, int flags)
2166 {
2167   USID u = event_stream_unixoid_create_stream_pair
2168                 (inhandle, outhandle, instream, outstream, flags);
2169   if (u != USID_ERROR)
2170     u = USID_DONTHASH;
2171   return u;
2172 }
2173
2174 static USID
2175 emacs_Xt_delete_stream_pair (Lisp_Object instream, Lisp_Object outstream)
2176 {
2177   event_stream_unixoid_delete_stream_pair (instream, outstream);
2178   return USID_DONTHASH;
2179 }
2180
2181 /* This is called from GC when a process object is about to be freed.
2182    If we've still got pointers to it in this file, we're gonna lose hard.
2183  */
2184 void
2185 debug_process_finalization (Lisp_Process *p)
2186 {
2187 #if 0 /* #### */
2188   int i;
2189   Lisp_Object instr, outstr;
2190
2191   get_process_streams (p, &instr, &outstr);
2192   /* if it still has fds, then it hasn't been killed yet. */
2193   assert (NILP(instr));
2194   assert (NILP(outstr));
2195   /* Better not still be in the "with input" table; we know it's got no fds. */
2196   for (i = 0; i < MAXDESC; i++)
2197     {
2198       Lisp_Object process = filedesc_fds_with_input [i];
2199       assert (!PROCESSP (process) || XPROCESS (process) != p);
2200     }
2201 #endif
2202 }
2203
2204 static void
2205 Xt_process_to_emacs_event (Lisp_Event *emacs_event)
2206 {
2207   int i;
2208
2209   assert (process_events_occurred > 0);
2210
2211   for (i = 0; i < MAXDESC; i++)
2212     {
2213       Lisp_Object process = filedesc_with_input[i];
2214       if (PROCESSP (process))
2215         {
2216           filedesc_with_input[i] = Qnil;
2217           process_events_occurred--;
2218           /* process events have nil as channel */
2219           emacs_event->event_type = process_event;
2220           emacs_event->timestamp  = 0; /* #### */
2221           emacs_event->event.process.process = process;
2222           return;
2223         }
2224     }
2225   abort ();
2226 }
2227
2228 static void
2229 emacs_Xt_select_console (struct console *con)
2230 {
2231   Lisp_Object console;
2232   int infd;
2233
2234   if (CONSOLE_X_P (con))
2235     return; /* X consoles are automatically selected for when we
2236                initialize them in Xt */
2237   infd = event_stream_unixoid_select_console (con);
2238   XSETCONSOLE (console, con);
2239   select_filedesc (infd, console);
2240 }
2241
2242 static void
2243 emacs_Xt_unselect_console (struct console *con)
2244 {
2245   Lisp_Object console;
2246   int infd;
2247
2248   if (CONSOLE_X_P (con))
2249     return; /* X consoles are automatically selected for when we
2250                initialize them in Xt */
2251   infd = event_stream_unixoid_unselect_console (con);
2252   XSETCONSOLE (console, con);
2253   unselect_filedesc (infd);
2254 }
2255
2256 /* read an event from a tty, if one is available.  Returns non-zero
2257    if an event was available.  Note that when this function is
2258    called, there should always be a tty marked as ready for input.
2259    However, the input condition might actually be EOF, so there
2260    may not really be any input available. (In this case,
2261    read_event_from_tty_or_stream_desc() will arrange for the TTY device
2262    to be deleted.) */
2263
2264 static int
2265 Xt_tty_to_emacs_event (Lisp_Event *emacs_event)
2266 {
2267   int i;
2268
2269   assert (tty_events_occurred > 0);
2270   for (i = 0; i < MAXDESC; i++)
2271     {
2272       Lisp_Object console = filedesc_with_input[i];
2273       if (CONSOLEP (console))
2274         {
2275           assert (tty_events_occurred > 0);
2276           tty_events_occurred--;
2277           filedesc_with_input[i] = Qnil;
2278           if (read_event_from_tty_or_stream_desc
2279               (emacs_event, XCONSOLE (console), i))
2280             return 1;
2281         }
2282     }
2283
2284   return 0;
2285 }
2286
2287 \f
2288 /************************************************************************/
2289 /*              debugging functions to decipher an event                */
2290 /************************************************************************/
2291
2292 #ifdef DEBUG_XEMACS
2293 #include "xintrinsicp.h"        /* only describe_event() needs this */
2294 #include <X11/Xproto.h>         /* only describe_event() needs this */
2295
2296 static void
2297 describe_event_window (Window window, Display *display)
2298 {
2299   struct frame *f;
2300   Widget w;
2301   stderr_out ("   window: 0x%lx", (unsigned long) window);
2302   w = XtWindowToWidget (display, window);
2303   if (w)
2304     stderr_out (" %s", w->core.widget_class->core_class.class_name);
2305   f = x_any_window_to_frame (get_device_from_display (display), window);
2306   if (f)
2307     {
2308       char *buf = alloca_array (char, XSTRING_LENGTH (f->name) + 4);
2309       sprintf (buf, " \"%s\"", XSTRING_DATA (f->name));
2310       write_string_to_stdio_stream (stderr, 0, (Bufbyte *) buf, 0,
2311                                     strlen (buf), Qterminal, 1);
2312     }
2313   stderr_out ("\n");
2314 }
2315
2316 static const char *
2317 XEvent_mode_to_string (int mode)
2318 {
2319   switch (mode)
2320   {
2321   case NotifyNormal:       return "Normal";
2322   case NotifyGrab:         return "Grab";
2323   case NotifyUngrab:       return "Ungrab";
2324   case NotifyWhileGrabbed: return "WhileGrabbed";
2325   default:                 return "???";
2326   }
2327 }
2328
2329 static const char *
2330 XEvent_detail_to_string (int detail)
2331 {
2332   switch (detail)
2333   {
2334   case NotifyAncestor:          return "Ancestor";
2335   case NotifyInferior:          return "Inferior";
2336   case NotifyNonlinear:         return "Nonlinear";
2337   case NotifyNonlinearVirtual:  return "NonlinearVirtual";
2338   case NotifyPointer:           return "Pointer";
2339   case NotifyPointerRoot:       return "PointerRoot";
2340   case NotifyDetailNone:        return "DetailNone";
2341   default:                      return "???";
2342   }
2343 }
2344
2345 static const char *
2346 XEvent_visibility_to_string (int state)
2347 {
2348   switch (state)
2349   {
2350   case VisibilityFullyObscured:     return "FullyObscured";
2351   case VisibilityPartiallyObscured: return "PartiallyObscured";
2352   case VisibilityUnobscured:        return "Unobscured";
2353   default:                          return "???";
2354   }
2355 }
2356
2357 static void
2358 describe_event (XEvent *event)
2359 {
2360   char buf[100];
2361   struct device *d = get_device_from_display (event->xany.display);
2362
2363   sprintf (buf, "%s%s", x_event_name (event->type),
2364            event->xany.send_event ? " (send)" : "");
2365   stderr_out ("%-30s", buf);
2366   switch (event->type)
2367     {
2368     case FocusIn:
2369     case FocusOut:
2370       {
2371         XFocusChangeEvent *ev = &event->xfocus;
2372         describe_event_window (ev->window, ev->display);
2373         stderr_out ("     mode: %s\n",   XEvent_mode_to_string  (ev->mode));
2374         stderr_out ("     detail: %s\n", XEvent_detail_to_string(ev->detail));
2375         break;
2376       }
2377
2378     case KeyPress:
2379       {
2380         XKeyEvent *ev = &event->xkey;
2381         unsigned int state = ev->state;
2382
2383         describe_event_window (ev->window, ev->display);
2384         stderr_out ("   subwindow: %ld\n", ev->subwindow);
2385         stderr_out ("   state: ");
2386         /* Complete list of modifier key masks */
2387         if (state & ShiftMask)   stderr_out ("Shift ");
2388         if (state & LockMask)    stderr_out ("Lock ");
2389         if (state & ControlMask) stderr_out ("Control ");
2390         if (state & Mod1Mask)    stderr_out ("Mod1 ");
2391         if (state & Mod2Mask)    stderr_out ("Mod2 ");
2392         if (state & Mod3Mask)    stderr_out ("Mod3 ");
2393         if (state & Mod4Mask)    stderr_out ("Mod4 ");
2394         if (state & Mod5Mask)    stderr_out ("Mod5 ");
2395
2396         if (! state)
2397           stderr_out ("vanilla\n");
2398         else
2399           stderr_out ("\n");
2400         if (x_key_is_modifier_p (ev->keycode, d))
2401           stderr_out ("   Modifier key");
2402         stderr_out ("   keycode: 0x%x\n", ev->keycode);
2403       }
2404     break;
2405
2406     case Expose:
2407       if (x_debug_events > 1)
2408         {
2409           XExposeEvent *ev = &event->xexpose;
2410           describe_event_window (ev->window, ev->display);
2411           stderr_out ("   region: x=%d y=%d width=%d height=%d\n",
2412                       ev->x, ev->y, ev->width, ev->height);
2413           stderr_out ("    count: %d\n", ev->count);
2414         }
2415       else
2416         stderr_out ("\n");
2417       break;
2418
2419     case GraphicsExpose:
2420       if (x_debug_events > 1)
2421         {
2422           XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
2423           describe_event_window (ev->drawable, ev->display);
2424           stderr_out ("    major: %s\n",
2425                       (ev ->major_code == X_CopyArea  ? "CopyArea" :
2426                        (ev->major_code == X_CopyPlane ? "CopyPlane" : "?")));
2427           stderr_out ("   region: x=%d y=%d width=%d height=%d\n",
2428                       ev->x, ev->y, ev->width, ev->height);
2429           stderr_out ("    count: %d\n", ev->count);
2430         }
2431       else
2432         stderr_out ("\n");
2433       break;
2434
2435     case EnterNotify:
2436     case LeaveNotify:
2437       if (x_debug_events > 1)
2438         {
2439           XCrossingEvent *ev = &event->xcrossing;
2440           describe_event_window (ev->window, ev->display);
2441 #if 0
2442           stderr_out(" subwindow: 0x%x\n", ev->subwindow);
2443           stderr_out("      pos: %d %d\n", ev->x, ev->y);
2444           stderr_out(" root pos: %d %d\n", ev->x_root, ev->y_root);
2445 #endif
2446           stderr_out("    mode: %s\n",   XEvent_mode_to_string(ev->mode));
2447           stderr_out("    detail: %s\n", XEvent_detail_to_string(ev->detail));
2448           stderr_out("    focus: %d\n", ev->focus);
2449 #if 0
2450           stderr_out("    state: 0x%x\n", ev->state);
2451 #endif
2452         }
2453       else
2454         stderr_out("\n");
2455       break;
2456
2457     case ConfigureNotify:
2458       if (x_debug_events > 1)
2459         {
2460           XConfigureEvent *ev = &event->xconfigure;
2461           describe_event_window (ev->window, ev->display);
2462           stderr_out("    above: 0x%lx\n", ev->above);
2463           stderr_out("     size: %d %d %d %d\n", ev->x, ev->y,
2464                      ev->width, ev->height);
2465           stderr_out("  redirect: %d\n", ev->override_redirect);
2466         }
2467       else
2468         stderr_out("\n");
2469       break;
2470
2471     case VisibilityNotify:
2472       if (x_debug_events > 1)
2473         {
2474           XVisibilityEvent *ev = &event->xvisibility;
2475           describe_event_window (ev->window, ev->display);
2476           stderr_out("    state: %s\n", XEvent_visibility_to_string(ev->state));
2477         }
2478       else
2479         stderr_out ("\n");
2480       break;
2481
2482     case ClientMessage:
2483       {
2484         XClientMessageEvent *ev = &event->xclient;
2485         char *name = XGetAtomName (ev->display, ev->message_type);
2486         stderr_out ("%s", name);
2487         if (!strcmp (name, "WM_PROTOCOLS")) {
2488           char *protname = XGetAtomName (ev->display, ev->data.l[0]);
2489           stderr_out ("(%s)", protname);
2490           XFree (protname);
2491         }
2492         XFree (name);
2493         stderr_out ("\n");
2494         break;
2495       }
2496
2497     default:
2498       stderr_out ("\n");
2499       break;
2500     }
2501
2502   fflush (stdout);
2503 }
2504
2505 #endif /* include describe_event definition */
2506
2507 \f
2508 /************************************************************************/
2509 /*                      get the next event from Xt                      */
2510 /************************************************************************/
2511
2512 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
2513
2514 void
2515 enqueue_Xt_dispatch_event (Lisp_Object event)
2516 {
2517   enqueue_event (event, &dispatch_event_queue, &dispatch_event_queue_tail);
2518 }
2519
2520 static Lisp_Object
2521 dequeue_Xt_dispatch_event (void)
2522 {
2523   return dequeue_event (&dispatch_event_queue, &dispatch_event_queue_tail);
2524 }
2525
2526 /* This business exists because menu events "happen" when
2527    menubar_selection_callback() is called from somewhere deep
2528    within XtAppProcessEvent in emacs_Xt_next_event().  The
2529    callback needs to terminate the modal loop in that function
2530    or else it will continue waiting until another event is
2531    received.
2532
2533    Same business applies to scrollbar events. */
2534
2535 void
2536 signal_special_Xt_user_event (Lisp_Object channel, Lisp_Object function,
2537                               Lisp_Object object)
2538 {
2539   Lisp_Object event = Fmake_event (Qnil, Qnil);
2540
2541   XEVENT (event)->event_type = misc_user_event;
2542   XEVENT (event)->channel = channel;
2543   XEVENT (event)->event.eval.function = function;
2544   XEVENT (event)->event.eval.object = object;
2545
2546   enqueue_Xt_dispatch_event (event);
2547 }
2548
2549 static void
2550 emacs_Xt_next_event (Lisp_Event *emacs_event)
2551 {
2552  we_didnt_get_an_event:
2553
2554   while (NILP (dispatch_event_queue) &&
2555          !completed_timeouts         &&
2556          !fake_event_occurred        &&
2557          !process_events_occurred    &&
2558          !tty_events_occurred)
2559     {
2560
2561       /* Stupid logic in XtAppProcessEvent() dictates that, if process
2562          events and X events are both available, the process event gets
2563          taken first.  This will cause an infinite loop if we're being
2564          called from Fdiscard_input().
2565        */
2566       if (XtAppPending (Xt_app_con) & XtIMXEvent)
2567         XtAppProcessEvent (Xt_app_con, XtIMXEvent);
2568       else
2569         {
2570           Lisp_Object devcons, concons;
2571
2572           /* We're about to block.  Xt has a bug in it (big surprise,
2573              there) in that it blocks using select() and doesn't
2574              flush the Xlib output buffers (XNextEvent() does this
2575              automatically before blocking).  So it's necessary
2576              for us to do this ourselves.  If we don't do it, then
2577              display output may not be seen until the next time
2578              an X event is received. (This happens esp. with
2579              subprocess output that gets sent to a visible buffer.)
2580
2581              #### The above comment may not have any validity. */
2582
2583           DEVICE_LOOP_NO_BREAK (devcons, concons)
2584             {
2585               struct device *d;
2586               d = XDEVICE (XCAR (devcons));
2587
2588               if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d))
2589                 /* emacs may be exiting */
2590                 XFlush (DEVICE_X_DISPLAY (d));
2591             }
2592           XtAppProcessEvent (Xt_app_con, XtIMAll);
2593         }
2594     }
2595
2596   if (!NILP (dispatch_event_queue))
2597     {
2598       Lisp_Object event, event2;
2599       XSETEVENT (event2, emacs_event);
2600       event = dequeue_Xt_dispatch_event ();
2601       Fcopy_event (event, event2);
2602       Fdeallocate_event (event);
2603     }
2604   else if (tty_events_occurred)
2605     {
2606       if (!Xt_tty_to_emacs_event (emacs_event))
2607         goto we_didnt_get_an_event;
2608     }
2609   else if (completed_timeouts)
2610     Xt_timeout_to_emacs_event (emacs_event);
2611   else if (fake_event_occurred)
2612     {
2613       /* A dummy event, so that a cycle of the command loop will occur. */
2614       fake_event_occurred = 0;
2615       /* eval events have nil as channel */
2616       emacs_event->event_type = eval_event;
2617       emacs_event->event.eval.function = Qidentity;
2618       emacs_event->event.eval.object = Qnil;
2619     }
2620   else /* if (process_events_occurred) */
2621     Xt_process_to_emacs_event (emacs_event);
2622
2623   /* No need to call XFilterEvent; Xt does it for us */
2624 }
2625
2626 void
2627 emacs_Xt_event_handler (Widget wid /* unused */,
2628                         XtPointer closure /* unused */,
2629                         XEvent *event,
2630                         Boolean *continue_to_dispatch /* unused */)
2631 {
2632   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
2633
2634 #ifdef DEBUG_XEMACS
2635   if (x_debug_events > 0)
2636     {
2637       describe_event (event);
2638     }
2639 #endif /* DEBUG_XEMACS */
2640   if (x_event_to_emacs_event (event, XEVENT (emacs_event)))
2641     enqueue_Xt_dispatch_event (emacs_event);
2642   else
2643     Fdeallocate_event (emacs_event);
2644 }
2645
2646 \f
2647 /************************************************************************/
2648 /*                      input pending / C-g checking                    */
2649 /************************************************************************/
2650
2651 static Bool
2652 quit_char_predicate (Display *display, XEvent *event, XPointer data)
2653 {
2654   struct device *d = get_device_from_display (display);
2655   struct x_device *xd = DEVICE_X_DATA (d);
2656   char c, quit_char;
2657   Bool *critical = (Bool *) data;
2658   Lisp_Object keysym;
2659
2660   if (critical)
2661     *critical = False;
2662   if ((event->type != KeyPress) ||
2663       (! x_any_window_to_frame (d, event->xany.window)) ||
2664       (event->xkey.state
2665        & (xd->MetaMask | xd->HyperMask | xd->SuperMask | xd->AltMask)))
2666     return 0;
2667
2668   /* This duplicates some code that exists elsewhere, but it's relatively
2669      fast and doesn't cons. */
2670   keysym = x_to_emacs_keysym (&event->xkey, 1);
2671   if (NILP (keysym)) return 0;
2672   if (CHAR_OR_CHAR_INTP (keysym))
2673     c = XCHAR_OR_CHAR_INT (keysym);
2674   /* Highly doubtful that these are the quit character, but... */
2675   else if (EQ (keysym, QKbackspace))    c = '\b';
2676   else if (EQ (keysym, QKtab))          c = '\t';
2677   else if (EQ (keysym, QKlinefeed))     c = '\n';
2678   else if (EQ (keysym, QKreturn))       c = '\r';
2679   else if (EQ (keysym, QKescape))       c = 27;
2680   else if (EQ (keysym, QKspace))        c = ' ';
2681   else if (EQ (keysym, QKdelete))       c = 127;
2682   else return 0;
2683
2684   if (event->xkey.state & xd->MetaMask)     c |= 0x80;
2685   if ((event->xkey.state & ControlMask) && !(c >= 'A' && c <= 'Z'))
2686     c &= 0x1F;                  /* unshifted control characters */
2687   quit_char = CONSOLE_QUIT_CHAR (XCONSOLE (DEVICE_CONSOLE (d)));
2688   if (c == quit_char)
2689     return True;
2690   /* If we've got Control-Shift-G instead of Control-G, that means
2691      we have a critical_quit.  Caps_Lock is its own modifier, so it
2692      won't cause ^G to act differently than before. */
2693   if (event->xkey.state & ControlMask)  c &= 0x1F;
2694   if (c == quit_char)
2695     {
2696       if (critical) *critical = True;
2697       return True;
2698     }
2699   return False;
2700 }
2701
2702 /* This scans the X input queue for a KeyPress event that matches the
2703    quit character, and sets Vquit_flag.  This is called from the
2704    QUIT macro to determine whether we should quit.
2705
2706    In a SIGIO world, this won't be called unless a SIGIO has happened
2707    since the last time we checked.
2708
2709    In a non-SIGIO world, this is called from emacs_Xt_event_pending_p
2710    (which is called from input_pending_p).
2711  */
2712 static void
2713 x_check_for_quit_char (Display *display)
2714 {
2715   XEvent event;
2716   int queued;
2717   Bool critical_quit = False;
2718   XEventsQueued (display, QueuedAfterReading);
2719   queued = XCheckIfEvent (display, &event,
2720                           quit_char_predicate,
2721                           (char *) &critical_quit);
2722   if (queued)
2723     {
2724       Vquit_flag = (critical_quit ? Qcritical : Qt);
2725       /* don't put the event back onto the queue.  Those functions that
2726          wanted to read a ^G directly have arranged to do this. */
2727     }
2728 }
2729
2730 static void
2731 check_for_tty_quit_char (struct device *d)
2732 {
2733   SELECT_TYPE temp_mask;
2734   int infd = DEVICE_INFD (d);
2735   struct console *con = XCONSOLE (DEVICE_CONSOLE (d));
2736   Emchar quit_char = CONSOLE_QUIT_CHAR (con);
2737
2738   FD_ZERO (&temp_mask);
2739   FD_SET (infd, &temp_mask);
2740
2741   while (1)
2742     {
2743       Lisp_Object event;
2744       Emchar the_char;
2745
2746       if (!poll_fds_for_input (temp_mask))
2747         return;
2748
2749       event = Fmake_event (Qnil, Qnil);
2750       if (!read_event_from_tty_or_stream_desc (XEVENT (event), con, infd))
2751         /* EOF, or something ... */
2752         return;
2753       /* #### bogus.  quit-char should be allowed to be any sort
2754          of event. */
2755       the_char = event_to_character (XEVENT (event), 1, 0, 0);
2756       if (the_char >= 0 && the_char == quit_char)
2757         {
2758           Vquit_flag = Qt;
2759           /* do not queue the C-g.  See above. */
2760           return;
2761         }
2762
2763       /* queue the read event to be read for real later. */
2764       enqueue_Xt_dispatch_event (event);
2765     }
2766 }
2767
2768 static void
2769 emacs_Xt_quit_p (void)
2770 {
2771   Lisp_Object devcons, concons;
2772   CONSOLE_LOOP (concons)
2773     {
2774       struct console *con = XCONSOLE (XCAR (concons));
2775       if (!con->input_enabled)
2776         continue;
2777
2778       CONSOLE_DEVICE_LOOP (devcons, con)
2779         {
2780           struct device *d;
2781           d = XDEVICE (XCAR (devcons));
2782
2783           if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d))
2784             /* emacs may be exiting */
2785             x_check_for_quit_char (DEVICE_X_DISPLAY (d));
2786           else if (DEVICE_TTY_P (d))
2787             check_for_tty_quit_char (d);
2788         }
2789     }
2790 }
2791
2792 static void
2793 drain_X_queue (void)
2794 {
2795   while (XtAppPending (Xt_app_con) & XtIMXEvent)
2796     XtAppProcessEvent (Xt_app_con, XtIMXEvent);
2797 }
2798
2799 static int
2800 emacs_Xt_event_pending_p (int user_p)
2801 {
2802   Lisp_Object event;
2803   int tick_count_val;
2804
2805   /* If `user_p' is false, then this function returns whether there are any
2806      X, timeout, or fd events pending (that is, whether emacs_Xt_next_event()
2807      would return immediately without blocking).
2808
2809      if `user_p' is true, then this function returns whether there are any
2810      *user generated* events available (that is, whether there are keyboard
2811      or mouse-click events ready to be read).  This also implies that
2812      emacs_Xt_next_event() would not block.
2813
2814      In a non-SIGIO world, this also checks whether the user has typed ^G,
2815      since this is a convenient place to do so.  We don't need to do this
2816      in a SIGIO world, since input causes an interrupt.
2817    */
2818
2819 #if 0
2820   /* I don't think there's any point to this and it will nullify
2821      the speed gains achieved by the sigio_happened checking below.
2822      Its only advantage is that it may possibly make C-g response
2823      a bit faster.  The C-g will be noticed within 0.25 second, anyway,
2824      even without this. */
2825 #ifndef SIGIO
2826   /* First check for C-g if necessary */
2827   emacs_Xt_quit_p ();
2828 #endif
2829 #endif
2830
2831   /* This function used to simply check whether there were any X
2832      events (or if user_p was 1, it iterated over all the pending
2833      X events using XCheckIfEvent(), looking for keystrokes and
2834      button events).  That worked in the old cheesoid event loop,
2835      which didn't go through XtAppDispatchEvent(), but it doesn't
2836      work any more -- X events may not result in anything.  For
2837      example, a button press in a blank part of the menubar appears
2838      as an X event but will not result in any Emacs events (a
2839      button press that activates the menubar results in an Emacs
2840      event through the stop_next_event mechanism).
2841
2842      The only accurate way of determining whether these X events
2843      translate into Emacs events is to go ahead and dispatch them
2844      until there's something on the dispatch queue. */
2845
2846   /* See if there are any user events already on the queue. */
2847   EVENT_CHAIN_LOOP (event, dispatch_event_queue)
2848     if (!user_p || command_event_p (event))
2849       return 1;
2850
2851   /* See if there's any TTY input available.
2852    */
2853   if (poll_fds_for_input (tty_only_mask))
2854     return 1;
2855
2856   if (!user_p)
2857     {
2858       /* If not user_p and there are any timer or file-desc events
2859          pending, we know there will be an event so we're through. */
2860       XtInputMask pending_value;
2861
2862       /* Note that formerly we just checked the value of XtAppPending()
2863          to determine if there was file-desc input.  This doesn't
2864          work any more with the signal_event_pipe; XtAppPending()
2865          will says "yes" in this case but there isn't really any
2866          input.  Another way of fixing this problem is for the
2867          signal_event_pipe to generate actual input in the form
2868          of an identity eval event or something. (#### maybe this
2869          actually happens?) */
2870
2871       if (poll_fds_for_input (process_only_mask))
2872         return 1;
2873
2874       pending_value = XtAppPending (Xt_app_con);
2875
2876       if (pending_value & XtIMTimer)
2877         return 1;
2878     }
2879
2880   /* XtAppPending() can be super-slow, esp. over a network connection.
2881      Quantify results have indicated that in some cases the
2882      call to detect_input_pending() completely dominates the
2883      running time of redisplay().  Fortunately, in a SIGIO world
2884      we can more quickly determine whether there are any X events:
2885      if an event has happened since the last time we checked, then
2886      a SIGIO will have happened.  On a machine with broken SIGIO,
2887      we'll still be in an OK state -- the sigio_happened flag
2888      will get set at least once a second, so we'll be no more than
2889      one second behind reality. (In general it's OK if we
2890      erroneously report no input pending when input is actually
2891      pending() -- preemption is just a bit less efficient, that's
2892      all.  It's bad bad bad if you err the other way -- you've
2893      promised that `next-event' won't block but it actually will,
2894      and some action might get delayed until the next time you
2895      hit a key.)
2896      */
2897
2898   /* quit_check_signal_tick_count is volatile so try to avoid race conditions
2899      by using a temporary variable */
2900   tick_count_val = quit_check_signal_tick_count;
2901   if (last_quit_check_signal_tick_count != tick_count_val)
2902     {
2903       last_quit_check_signal_tick_count = tick_count_val;
2904
2905       /* We need to drain the entire queue now -- if we only
2906          drain part of it, we may later on end up with events
2907          actually pending but detect_input_pending() returning
2908          false because there wasn't another SIGIO. */
2909       drain_X_queue ();
2910
2911       EVENT_CHAIN_LOOP (event, dispatch_event_queue)
2912         if (!user_p || command_event_p (event))
2913           return 1;
2914     }
2915
2916   return 0;
2917 }
2918
2919 \f
2920 /************************************************************************/
2921 /*            replacement for standard string-to-pixel converter        */
2922 /************************************************************************/
2923
2924 /* This was constructed by ripping off the standard string-to-pixel
2925    converter from Converters.c in the Xt source code and modifying
2926    appropriately. */
2927
2928 #if 0
2929
2930 /* This is exported by the Xt library (at least by mine).  If this
2931    isn't the case somewhere, rename this appropriately and remove
2932    the '#if 0'.  Note, however, that I got "unknown structure"
2933    errors when I tried this. */
2934 XtConvertArgRec Const colorConvertArgs[] = {
2935   { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
2936     sizeof (Screen *) },
2937   { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
2938     sizeof (Colormap) }
2939 };
2940
2941 #endif
2942
2943 #define done(type, value)               \
2944   if (toVal->addr != NULL) {             \
2945     if (toVal->size < sizeof(type)) {    \
2946       toVal->size = sizeof(type);        \
2947       return False;                      \
2948     }                                    \
2949     *(type*)(toVal->addr) = (value);     \
2950   } else {                               \
2951     static type static_val;              \
2952     static_val = (value);                \
2953     toVal->addr = (XPointer)&static_val; \
2954   }                                      \
2955   toVal->size = sizeof(type);            \
2956   return True /* Caller supplies `;' */
2957
2958 /* JH: We use this because I think there's a possibility this
2959    is called before the device is properly set up, in which case
2960    I don't want to abort. */
2961 extern struct device *get_device_from_display_1 (Display *dpy);
2962
2963 static
2964 Boolean EmacsXtCvtStringToPixel (
2965  Display     *dpy,
2966  XrmValuePtr  args,
2967  Cardinal    *num_args,
2968  XrmValuePtr  fromVal,
2969  XrmValuePtr  toVal,
2970  XtPointer   *closure_ret)
2971 {
2972   String       str = (String)fromVal->addr;
2973   XColor       screenColor;
2974   XColor       exactColor;
2975   Screen       *screen;
2976   Colormap     colormap;
2977   Visual       *visual;
2978   struct device *d;
2979   Status       status;
2980   String       params[1];
2981   Cardinal     num_params  = 1;
2982   XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
2983
2984   if (*num_args != 2) {
2985     XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToPixel",
2986                     "XtToolkitError",
2987                     "String to pixel conversion needs screen and colormap arguments",
2988                     (String *)NULL, (Cardinal *)NULL);
2989     return False;
2990   }
2991
2992   screen   = *((Screen **)  args[0].addr);
2993   colormap = *((Colormap *) args[1].addr);
2994
2995   /* The original uses the private function CompareISOLatin1().
2996      Use XmuCompareISOLatin1() if you want, but I don't think it
2997      makes any difference here. */
2998   if (strcmp(str, XtDefaultBackground) == 0) {
2999     *closure_ret = False;
3000     /* This refers to the display's "*reverseVideo" resource.
3001        These display resources aren't documented anywhere that
3002        I can find, so I'm going to ignore this. */
3003     /* if (pd->rv) done(Pixel, BlackPixelOfScreen(screen)) else */
3004     done(Pixel, WhitePixelOfScreen(screen));
3005   }
3006   if (strcmp(str, XtDefaultForeground) == 0) {
3007     *closure_ret = False;
3008     /* if (pd->rv) done(Pixel, WhitePixelOfScreen(screen)) else */
3009     done(Pixel, BlackPixelOfScreen(screen));
3010   }
3011
3012   /* Originally called XAllocNamedColor() here. */
3013   if ((d = get_device_from_display_1(dpy))) {
3014     visual = DEVICE_X_VISUAL(d);
3015     if (colormap != DEVICE_X_COLORMAP(d)) {
3016       XtAppWarningMsg(the_app_con, "wierdColormap", "cvtStringToPixel",
3017                       "XtToolkitWarning",
3018                       "The colormap passed to cvtStringToPixel doesn't match the one registerd to the device.\n",
3019                       NULL, 0);
3020       status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor);
3021     } else {
3022       status = XParseColor (dpy, colormap, (char*)str, &screenColor);
3023       if (status) {
3024         status = allocate_nearest_color (dpy, colormap, visual, &screenColor);
3025       }
3026     }
3027   } else {
3028     /* We haven't set up this device totally yet, so just punt */
3029     status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor);
3030   }
3031   if (status == 0) {
3032     params[0] = str;
3033     /* Server returns a specific error code but Xlib discards it.  Ugh */
3034     if (XLookupColor(DisplayOfScreen(screen), colormap, (char*) str,
3035                      &exactColor, &screenColor)) {
3036       XtAppWarningMsg(the_app_con, "noColormap", "cvtStringToPixel",
3037                       "XtToolkitError",
3038                       "Cannot allocate colormap entry for \"%s\"",
3039                       params, &num_params);
3040
3041     } else {
3042       XtAppWarningMsg(the_app_con, "badValue", "cvtStringToPixel",
3043                       "XtToolkitError",
3044                       "Color name \"%s\" is not defined", params, &num_params);
3045     }
3046
3047     *closure_ret = False;
3048     return False;
3049   } else {
3050     *closure_ret = (char*)True;
3051     done(Pixel, screenColor.pixel);
3052   }
3053 }
3054
3055 /* ARGSUSED */
3056 static void EmacsFreePixel (
3057   XtAppContext app,
3058   XrmValuePtr  toVal,
3059   XtPointer    closure,
3060   XrmValuePtr  args,
3061   Cardinal    *num_args)
3062 {
3063   if (*num_args != 2) {
3064     XtAppWarningMsg(app, "wrongParameters","freePixel","XtToolkitError",
3065                     "Freeing a pixel requires screen and colormap arguments",
3066                     (String *)NULL, (Cardinal *)NULL);
3067     return;
3068   }
3069
3070   if (closure) {
3071     Screen   *screen  = *((Screen **)  args[0].addr);
3072     Colormap colormap = *((Colormap *) args[1].addr);
3073     XFreeColors(DisplayOfScreen(screen), colormap,
3074                 (unsigned long*)toVal->addr, 1, (unsigned long)0);
3075   }
3076 }
3077
3078 \f
3079 /************************************************************************/
3080 /*            handle focus changes for native widgets                  */
3081 /************************************************************************/
3082 static void
3083 emacs_Xt_event_widget_focus_in (Widget   w,
3084                                 XEvent   *event,
3085                                 String   *params,
3086                                 Cardinal *num_params)
3087 {
3088   struct frame* f =
3089     x_any_widget_or_parent_to_frame (get_device_from_display (event->xany.display), w);
3090
3091   XtSetKeyboardFocus (FRAME_X_SHELL_WIDGET (f), w);
3092 }
3093
3094 static void
3095 emacs_Xt_event_widget_focus_out (Widget   w,
3096                                  XEvent   *event,
3097                                  String   *params,
3098                                  Cardinal *num_params)
3099 {
3100 }
3101
3102 static XtActionsRec widgetActionsList[] =
3103 {
3104   {"widget-focus-in",   emacs_Xt_event_widget_focus_in  },
3105   {"widget-focus-out",  emacs_Xt_event_widget_focus_out },
3106 };
3107
3108 static void
3109 emacs_Xt_event_add_widget_actions (XtAppContext ctx)
3110 {
3111   XtAppAddActions (ctx, widgetActionsList, 2);
3112 }
3113
3114 \f
3115 /************************************************************************/
3116 /*                            initialization                            */
3117 /************************************************************************/
3118
3119 void
3120 syms_of_event_Xt (void)
3121 {
3122   defsymbol (&Qkey_mapping, "key-mapping");
3123   defsymbol (&Qsans_modifiers, "sans-modifiers");
3124   defsymbol (&Qself_insert_command, "self-insert-command");
3125 }
3126
3127 void
3128 reinit_vars_of_event_Xt (void)
3129 {
3130   Xt_event_stream = xnew (struct event_stream);
3131   Xt_event_stream->event_pending_p       = emacs_Xt_event_pending_p;
3132   Xt_event_stream->force_event_pending   = emacs_Xt_force_event_pending;
3133   Xt_event_stream->next_event_cb         = emacs_Xt_next_event;
3134   Xt_event_stream->handle_magic_event_cb = emacs_Xt_handle_magic_event;
3135   Xt_event_stream->add_timeout_cb        = emacs_Xt_add_timeout;
3136   Xt_event_stream->remove_timeout_cb     = emacs_Xt_remove_timeout;
3137   Xt_event_stream->select_console_cb     = emacs_Xt_select_console;
3138   Xt_event_stream->unselect_console_cb   = emacs_Xt_unselect_console;
3139   Xt_event_stream->select_process_cb     = emacs_Xt_select_process;
3140   Xt_event_stream->unselect_process_cb   = emacs_Xt_unselect_process;
3141   Xt_event_stream->quit_p_cb             = emacs_Xt_quit_p;
3142   Xt_event_stream->create_stream_pair_cb = emacs_Xt_create_stream_pair;
3143   Xt_event_stream->delete_stream_pair_cb = emacs_Xt_delete_stream_pair;
3144
3145   the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
3146
3147   last_quit_check_signal_tick_count = 0;
3148
3149   /* this function only makes safe calls */
3150   init_what_input_once ();
3151 }
3152
3153 void
3154 vars_of_event_Xt (void)
3155 {
3156   reinit_vars_of_event_Xt ();
3157
3158   dispatch_event_queue = Qnil;
3159   staticpro (&dispatch_event_queue);
3160   dispatch_event_queue_tail = Qnil;
3161   pdump_wire (&dispatch_event_queue_tail);
3162
3163   DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /*
3164 *Non-nil makes modifier keys sticky.
3165 This means that you can release the modifier key before pressing down
3166 the key that you wish to be modified.  Although this is non-standard
3167 behavior, it is recommended because it reduces the strain on your hand,
3168 thus reducing the incidence of the dreaded Emacs-pinky syndrome.
3169 */ );
3170   modifier_keys_are_sticky = 0;
3171
3172   DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /*
3173 *Non-nil means to allow synthetic events.  Nil means they are ignored.
3174 Beware: allowing emacs to process SendEvents opens a big security hole.
3175 */ );
3176   x_allow_sendevents = 0;
3177
3178 #ifdef DEBUG_XEMACS
3179   DEFVAR_INT ("x-debug-events", &x_debug_events /*
3180 If non-zero, display debug information about X events that XEmacs sees.
3181 Information is displayed on stderr.  Currently defined values are:
3182
3183 1 == non-verbose output
3184 2 == verbose output
3185 */ );
3186   x_debug_events = 0;
3187 #endif
3188 }
3189
3190 /* This mess is a hack that patches the shell widget to treat visual inheritance
3191    the same as colormap and depth inheritance */
3192
3193 static XtInitProc orig_shell_init_proc;
3194
3195 static void ShellVisualPatch(Widget wanted, Widget new,
3196                              ArgList args, Cardinal *num_args)
3197 {
3198   Widget p;
3199   ShellWidget w = (ShellWidget) new;
3200
3201   /* first, call the original setup */
3202   (*orig_shell_init_proc)(wanted, new, args, num_args);
3203
3204   /* if the visual isn't explicitly set, grab it from the nearest shell ancestor */
3205   if (w->shell.visual == CopyFromParent) {
3206     p = XtParent(w);
3207     while (p && !XtIsShell(p)) p = XtParent(p);
3208     if (p) w->shell.visual = ((ShellWidget)p)->shell.visual;
3209   }
3210 }
3211
3212 void
3213 init_event_Xt_late (void) /* called when already initialized */
3214 {
3215   timeout_id_tick = 1;
3216   pending_timeouts = 0;
3217   completed_timeouts = 0;
3218
3219   event_stream = Xt_event_stream;
3220
3221 #if defined(HAVE_XIM) || defined(USE_XFONTSET)
3222   Initialize_Locale();
3223 #endif /* HAVE_XIM || USE_XFONTSET */
3224
3225   XtToolkitInitialize ();
3226   Xt_app_con = XtCreateApplicationContext ();
3227   XtAppSetFallbackResources (Xt_app_con, (String *) x_fallback_resources);
3228
3229   /* In xselect.c */
3230   x_selection_timeout = (XtAppGetSelectionTimeout (Xt_app_con) / 1000);
3231   XSetErrorHandler (x_error_handler);
3232   XSetIOErrorHandler (x_IO_error_handler);
3233
3234 #ifndef WINDOWSNT
3235   XtAppAddInput (Xt_app_con, signal_event_pipe[0],
3236                  (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
3237                  Xt_what_callback, 0);
3238 #endif
3239
3240   XtAppSetTypeConverter (Xt_app_con, XtRString, XtRPixel,
3241                          EmacsXtCvtStringToPixel,
3242                          (XtConvertArgList) colorConvertArgs,
3243                          2, XtCacheByDisplay, EmacsFreePixel);
3244
3245 #ifdef XIM_XLIB
3246   XtAppSetTypeConverter (Xt_app_con, XtRString, XtRXimStyles,
3247                          EmacsXtCvtStringToXIMStyles,
3248                          NULL, 0,
3249                          XtCacheByDisplay, EmacsFreeXIMStyles);
3250 #endif /* XIM_XLIB */
3251   /* Add extra actions to native widgets to handle focus and friends. */
3252   emacs_Xt_event_add_widget_actions (Xt_app_con);
3253
3254   /* insert the visual inheritance patch/hack described above */
3255   orig_shell_init_proc = shellClassRec.core_class.initialize;
3256   shellClassRec.core_class.initialize = ShellVisualPatch;
3257
3258 }