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