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