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