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