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