diff src/event-Xt.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents de805c49cfc1
children 41dbb7a9d5f2
line wrap: on
line diff
--- a/src/event-Xt.c	Mon Aug 13 11:19:22 2007 +0200
+++ b/src/event-Xt.c	Mon Aug 13 11:20:41 2007 +0200
@@ -65,9 +65,19 @@
 #include "offix.h"
 #endif
 
+#ifdef WINDOWSNT
+/* Hmm, under unix we want X modifiers, under NT we want X modifiers if
+   we are running X and Windows modifiers otherwise.
+   gak. This is a kludge until we support multiple native GUIs!
+*/
+#undef MOD_ALT
+#undef MOD_CONTROL
+#undef MOD_SHIFT
+#endif
+
 #include "events-mod.h"
 
-static void handle_focus_event_1 (struct frame *f, int in_p);
+static void enqueue_Xt_dispatch_event (Lisp_Object event);
 
 static struct event_stream *Xt_event_stream;
 
@@ -86,6 +96,8 @@
 /* Do we accept events sent by other clients? */
 int x_allow_sendevents;
 
+int modifier_keys_are_sticky;
+
 #ifdef DEBUG_XEMACS
 int x_debug_events;
 #endif
@@ -96,7 +108,7 @@
 /* Mask of bits indicating the descriptors that we wait for input on */
 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
 
-static const String x_fallback_resources[] =
+static CONST String x_fallback_resources[] =
 {
   /* This file is automatically generated from the app-defaults file
      in ../etc/Emacs.ad.  These resources are consulted only if no
@@ -108,7 +120,7 @@
 
 static Lisp_Object x_keysym_to_emacs_keysym (KeySym keysym, int simple_p);
 void emacs_Xt_mapping_action (Widget w, XEvent *event);
-void debug_process_finalization (Lisp_Process *p);
+void debug_process_finalization (struct Lisp_Process *p);
 void emacs_Xt_event_handler (Widget wid, XtPointer closure, XEvent *event,
 			     Boolean *continue_to_dispatch);
 
@@ -162,204 +174,6 @@
    use a pop-up-window instead.)
  */
 
-/* For every key on the keyboard that has a known character correspondence,
-   we define the ascii-character property of the keysym, and make the
-   default binding for the key be self-insert-command.
-
-   The following magic is basically intimate knowledge of X11/keysymdef.h.
-   The keysym mappings defined by X11 are based on the iso8859 standards,
-   except for Cyrillic and Greek.
-
-   In a non-Mule world, a user can still have a multi-lingual editor, by doing
-   (set-face-font "...-iso8859-2" (current-buffer))
-   for all their Latin-2 buffers, etc.  */
-
-static Lisp_Object
-x_keysym_to_character (KeySym keysym)
-{
-#ifdef MULE
-  Lisp_Object charset = Qzero;
-#define USE_CHARSET(var,cs) \
-  ((var) = CHARSET_BY_LEADING_BYTE (LEADING_BYTE_##cs))
-#else
-#define USE_CHARSET(var,lb)
-#endif /* MULE */
-  int code = 0;
-
-  if ((keysym & 0xff) < 0xa0)
-    return Qnil;
-
-  switch (keysym >> 8)
-    {
-    case 0: /* ASCII + Latin1 */
-      USE_CHARSET (charset, LATIN_ISO8859_1);
-      code = keysym & 0x7f;
-      break;
-    case 1: /* Latin2 */
-      USE_CHARSET (charset, LATIN_ISO8859_2);
-      code = keysym & 0x7f;
-      break;
-    case 2: /* Latin3 */
-      USE_CHARSET (charset, LATIN_ISO8859_3);
-      code = keysym & 0x7f;
-      break;
-    case 3: /* Latin4 */
-      USE_CHARSET (charset, LATIN_ISO8859_4);
-      code = keysym & 0x7f;
-      break;
-    case 4: /* Katakana */
-      USE_CHARSET (charset, KATAKANA_JISX0201);
-      if ((keysym & 0xff) > 0xa0)
-	code = keysym & 0x7f;
-      break;
-    case 5: /* Arabic */
-      USE_CHARSET (charset, ARABIC_ISO8859_6);
-      code = keysym & 0x7f;
-      break;
-    case 6: /* Cyrillic */
-      {
-	static unsigned char const cyrillic[] = /* 0x20 - 0x7f */
-	{0x00, 0x72, 0x73, 0x71, 0x74, 0x75, 0x76, 0x77,
-	 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x00, 0x7e, 0x7f,
-	 0x70, 0x22, 0x23, 0x21, 0x24, 0x25, 0x26, 0x27,
-	 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x00, 0x2e, 0x2f,
-	 0x6e, 0x50, 0x51, 0x66, 0x54, 0x55, 0x64, 0x53,
-	 0x65, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
-	 0x5f, 0x6f, 0x60, 0x61, 0x62, 0x63, 0x56, 0x52,
-	 0x6c, 0x6b, 0x57, 0x68, 0x6d, 0x69, 0x67, 0x6a,
-	 0x4e, 0x30, 0x31, 0x46, 0x34, 0x35, 0x44, 0x33,
-	 0x45, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
-	 0x3f, 0x4f, 0x40, 0x41, 0x42, 0x43, 0x36, 0x32,
-	 0x4c, 0x4b, 0x37, 0x48, 0x4d, 0x49, 0x47, 0x4a};
-	USE_CHARSET (charset, CYRILLIC_ISO8859_5);
-	code = cyrillic[(keysym & 0x7f) - 0x20];
-	break;
-      }
-    case 7: /* Greek */
-      {
-	static unsigned char const greek[] = /* 0x20 - 0x7f */
-	{0x00, 0x36, 0x38, 0x39, 0x3a, 0x5a, 0x00, 0x3c,
-	 0x3e, 0x5b, 0x00, 0x3f, 0x00, 0x00, 0x35, 0x2f,
-	 0x00, 0x5c, 0x5d, 0x5e, 0x5f, 0x7a, 0x40, 0x7c,
-	 0x7d, 0x7b, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-	 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
-	 0x50, 0x51, 0x53, 0x00, 0x54, 0x55, 0x56, 0x57,
-	 0x58, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-	 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
-	 0x70, 0x71, 0x73, 0x72, 0x74, 0x75, 0x76, 0x77,
-	 0x78, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-	USE_CHARSET (charset, GREEK_ISO8859_7);
-	code = greek[(keysym & 0x7f) - 0x20];
-	break;
-      }
-    case 8: /* Technical */
-      break;
-    case 9: /* Special */
-      break;
-    case 10: /* Publishing */
-      break;
-    case 11: /* APL */
-      break;
-    case 12: /* Hebrew */
-      USE_CHARSET (charset, HEBREW_ISO8859_8);
-      code = keysym & 0x7f;
-      break;
-    case 13: /* Thai */
-      /* #### This needs to deal with character composition. */
-      USE_CHARSET (charset, THAI_TIS620);
-      code = keysym & 0x7f;
-      break;
-    case 14: /* Korean Hangul */
-      break;
-    case 19: /* Latin 9 - ISO8859-15 - unsupported charset. */
-      break;
-    case 32: /* Currency */
-      break;
-    default:
-      break;
-    }
-
-  if (code == 0)
-    return Qnil;
-
-#ifdef MULE
-  return make_char (MAKE_CHAR (charset, code, 0));
-#else
-  return make_char (code + 0x80);
-#endif
-}
-
-/* #### The way that keysym correspondence to characters should work:
-   - a Lisp_Event should contain a keysym AND a character slot.
-   - keybindings are tried with the keysym.  If no binding can be found,
-   and there is a corresponding character, call self-insert-command.
-
-   #### Nuke x-iso8859-1.el.
-   #### Nuke the Qascii_character property.
-   #### Nuke Vcharacter_set_property.
-*/
-static void
-maybe_define_x_key_as_self_inserting_character (KeySym keysym, Lisp_Object symbol)
-{
-  Lisp_Object character = x_keysym_to_character (keysym);
-
-  if (CHARP (character))
-    {
-      extern Lisp_Object Vcurrent_global_map;
-      extern Lisp_Object Qascii_character;
-      Fput (symbol, Qascii_character, character);
-      if (NILP (Flookup_key (Vcurrent_global_map, symbol, Qnil)))
-	Fdefine_key (Vcurrent_global_map, symbol, Qself_insert_command);
-    }
-}
-
-static void
-x_has_keysym (KeySym keysym, Lisp_Object hash_table, int with_modifiers)
-{
-  KeySym upper_lower[2];
-  int j;
-
-  if (keysym < 0x80) /* Optimize for ASCII keysyms */
-    return;
-
-  /* If you execute:
-     xmodmap -e 'keysym NN = scaron'
-     and then press (Shift scaron), X11 will return the different
-     keysym `Scaron', but  `xmodmap -pke'  might not even mention `Scaron'.
-     So we "register" both `scaron' and `Scaron'. */
-#ifdef HAVE_XCONVERTCASE
-  XConvertCase (keysym, &upper_lower[0], &upper_lower[1]);
-#else
-  upper_lower[0] = upper_lower[1] = keysym;
-#endif
-
-  for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++)
-    {
-      char *name;
-      keysym = upper_lower[j];
-
-      name = XKeysymToString (keysym);
-      if (name)
-	{
-	  /* X guarantees NAME to be in the Host Portable Character Encoding */
-	  Lisp_Object sym = x_keysym_to_emacs_keysym (keysym, 0);
-	  Lisp_Object new_value = with_modifiers ? Qt : Qsans_modifiers;
-	  Lisp_Object old_value = Fgethash (sym, hash_table, Qnil);
-
-	  if (! EQ (old_value, new_value)
-	      && ! (EQ (old_value, Qsans_modifiers) &&
-		    EQ (new_value, Qt)))
-	    {
-	      maybe_define_x_key_as_self_inserting_character (keysym, sym);
-	      Fputhash (build_ext_string (name, Qbinary), new_value, hash_table);
-	      Fputhash (sym, new_value, hash_table);
-	    }
-	}
-    }
-}
-
 static void
 x_reset_key_mapping (struct device *d)
 {
@@ -397,18 +211,34 @@
       if (keysym[0] == NoSymbol)
 	continue;
 
-      x_has_keysym (keysym[0], hash_table, 0);
+      {
+	char *name = XKeysymToString (keysym[0]);
+	Lisp_Object sym = x_keysym_to_emacs_keysym (keysym[0], 0);
+	if (name)
+	  {
+	    Fputhash (build_string (name), Qsans_modifiers, hash_table);
+	    Fputhash (sym, Qsans_modifiers, hash_table);
+	  }
+      }
 
       for (j = 1; j < keysyms_per_code; j++)
 	{
 	  if (keysym[j] != keysym[0] &&
 	      keysym[j] != NoSymbol)
-	    x_has_keysym (keysym[j], hash_table, 1);
+	    {
+	      char *name = XKeysymToString (keysym[j]);
+	      Lisp_Object sym = x_keysym_to_emacs_keysym (keysym[j], 0);
+	      if (name && NILP (Fgethash (sym, hash_table, Qnil)))
+		{
+		  Fputhash (build_string (name), Qt, hash_table);
+		  Fputhash (sym, Qt, hash_table);
+		}
+	    }
 	}
     }
 }
 
-static const char *
+static CONST char *
 index_to_name (int indice)
 {
   switch (indice)
@@ -563,7 +393,7 @@
      be totally wrong. */
   if (mode_bit)
     {
-      const char *warn = 0;
+      CONST char *warn = 0;
       if      (mode_bit == meta_bit)  warn = "Meta",  meta_bit  = 0;
       else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
       else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
@@ -977,8 +807,7 @@
   len = XmImMbLookupString (XtWindowToWidget (event->display, event->window),
 			    event, bufptr, bufsiz, &keysym, &status);
 #else /* XIM_XLIB */
-  if (xic)
-    len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status);
+  len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status);
 #endif /* HAVE_XIM */
 
 #ifdef DEBUG_XEMACS
@@ -1029,9 +858,10 @@
 	Lstream *istr;
 	struct gcpro gcpro1, gcpro2;
 
-	fb_instream = make_fixed_buffer_input_stream (bufptr, len);
-
-        /* #### Use Fget_coding_system (Vcomposed_input_coding_system) */
+	fb_instream =
+          make_fixed_buffer_input_stream ((unsigned char *) bufptr, len);
+
+        /* ### Use Fget_coding_system (Vcomposed_input_coding_system) */
 	instream =
 	  make_decoding_input_stream (XLSTREAM (fb_instream),
 				      Fget_coding_system (Qundecided));
@@ -1042,7 +872,7 @@
         while ((ch = Lstream_get_emchar (istr)) != EOF)
           {
             Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
-	    Lisp_Event *ev          = XEVENT (emacs_event);
+	    struct Lisp_Event *ev = XEVENT (emacs_event);
             ev->channel	            = DEVICE_CONSOLE (d);
             ev->event_type	    = key_press_event;
             ev->timestamp	    = event->time;
@@ -1089,7 +919,7 @@
 }
 
 static int
-x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
+x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
 {
   Display *display    = x_event->xany.display;
   struct device *d    = get_device_from_display (display);
@@ -1111,7 +941,7 @@
     case ButtonPress:
     case ButtonRelease:
       {
-	int modifiers = 0;
+	unsigned int modifiers = 0;
 	int shift_p, lock_p;
 	Bool key_event_p = (x_event->type == KeyPress);
 	unsigned int *state =
@@ -1138,11 +968,11 @@
 
 	x_handle_sticky_modifiers (x_event, d);
 
-	if (*state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
-	if (*state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
-	if (*state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
-	if (*state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
-	if (*state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
+	if (*state & ControlMask)    modifiers |= MOD_CONTROL;
+	if (*state & xd->MetaMask)   modifiers |= MOD_META;
+	if (*state & xd->SuperMask)  modifiers |= MOD_SUPER;
+	if (*state & xd->HyperMask)  modifiers |= MOD_HYPER;
+	if (*state & xd->AltMask)    modifiers |= MOD_ALT;
 
 	/* Ignore the Caps_Lock key if:
 	   - any other modifiers are down, so that Caps_Lock doesn't
@@ -1155,7 +985,7 @@
 	lock_p  = *state & LockMask;
 
 	if (shift_p || lock_p)
-	  modifiers |= XEMACS_MOD_SHIFT;
+	  modifiers |= MOD_SHIFT;
 
 	if (key_event_p)
 	  {
@@ -1187,7 +1017,7 @@
 		! (CHAR_OR_CHAR_INTP (keysym)
 		   && keysym_obeys_caps_lock_p
 		   ((KeySym) XCHAR_OR_CHAR_INT (keysym), d)))
-	      modifiers &= (~XEMACS_MOD_SHIFT);
+	      modifiers &= (~MOD_SHIFT);
 
 	    /* If this key contains two distinct keysyms, that is,
 	       "shift" generates a different keysym than the
@@ -1199,13 +1029,13 @@
 	       in the modifiers slot.  Neither the characters "a",
 	       "A", "2", nor "@" normally have the shift bit set.
 	       However, "F1" normally does. */
-	    if (modifiers & XEMACS_MOD_SHIFT)
+	    if (modifiers & MOD_SHIFT)
 	      {
 		int Mode_switch_p = *state & xd->ModeMask;
 		KeySym bot = XLookupKeysym (ev, Mode_switch_p ? 2 : 0);
 		KeySym top = XLookupKeysym (ev, Mode_switch_p ? 3 : 1);
 		if (top && bot && top != bot)
-		  modifiers &= ~XEMACS_MOD_SHIFT;
+		  modifiers &= ~MOD_SHIFT;
 	      }
 	    emacs_event->event_type	     = key_press_event;
 	    emacs_event->timestamp	     = ev->time;
@@ -1216,7 +1046,6 @@
 	  {
 	    XButtonEvent *ev = &x_event->xbutton;
 	    struct frame *frame = x_window_to_frame (d, ev->window);
-
 	    if (! frame)
 	      return 0;	/* not for us */
 	    XSETFRAME (emacs_event->channel, frame);
@@ -1229,11 +1058,7 @@
 	    emacs_event->event.button.button	= ev->button;
 	    emacs_event->event.button.x		= ev->x;
 	    emacs_event->event.button.y		= ev->y;
-	    /* because we don't seem to get a FocusIn event for button clicks
-	       when a widget-glyph is selected we will assume that we want the
-	       focus if a button gets pressed. */
-	    if (x_event->type == ButtonPress)
-	      handle_focus_event_1 (frame, 1);
+
 	  }
       }
     break;
@@ -1242,7 +1067,7 @@
       {
         XMotionEvent *ev = &x_event->xmotion;
         struct frame *frame = x_window_to_frame (d, ev->window);
-        int modifiers = 0;
+        unsigned int modifiers = 0;
         XMotionEvent event2;
 
         if (! frame)
@@ -1271,12 +1096,12 @@
         emacs_event->timestamp      = ev->time;
         emacs_event->event.motion.x = ev->x;
         emacs_event->event.motion.y = ev->y;
-        if (ev->state & ShiftMask)	modifiers |= XEMACS_MOD_SHIFT;
-        if (ev->state & ControlMask)	modifiers |= XEMACS_MOD_CONTROL;
-        if (ev->state & xd->MetaMask)	modifiers |= XEMACS_MOD_META;
-        if (ev->state & xd->SuperMask)	modifiers |= XEMACS_MOD_SUPER;
-        if (ev->state & xd->HyperMask)	modifiers |= XEMACS_MOD_HYPER;
-        if (ev->state & xd->AltMask)	modifiers |= XEMACS_MOD_ALT;
+        if (ev->state & ShiftMask)	modifiers |= MOD_SHIFT;
+        if (ev->state & ControlMask)	modifiers |= MOD_CONTROL;
+        if (ev->state & xd->MetaMask)	modifiers |= MOD_META;
+        if (ev->state & xd->SuperMask)	modifiers |= MOD_SUPER;
+        if (ev->state & xd->HyperMask)	modifiers |= MOD_HYPER;
+        if (ev->state & xd->AltMask)	modifiers |= MOD_ALT;
         /* Currently ignores Shift_Lock but probably shouldn't
            (but it definitely should ignore Caps_Lock). */
         emacs_event->event.motion.modifiers = modifiers;
@@ -1292,9 +1117,7 @@
 #ifdef HAVE_OFFIX_DND
 	if (DndIsDropMessage(x_event))
 	  {
-	    unsigned int state;
-	    int modifiers = 0;
-	    unsigned int button=0;
+	    unsigned int state, modifiers = 0, button=0;
 	    struct frame *frame = x_any_window_to_frame (d, ev->window);
 	    Extbyte *data;
 	    unsigned long size, dtype;
@@ -1313,12 +1136,12 @@
 
 	    state=DndDragButtons(x_event);
 
-	    if (state & ShiftMask)	modifiers |= XEMACS_MOD_SHIFT;
-	    if (state & ControlMask)	modifiers |= XEMACS_MOD_CONTROL;
-	    if (state & xd->MetaMask)	modifiers |= XEMACS_MOD_META;
-	    if (state & xd->SuperMask)	modifiers |= XEMACS_MOD_SUPER;
-	    if (state & xd->HyperMask)	modifiers |= XEMACS_MOD_HYPER;
-	    if (state & xd->AltMask)	modifiers |= XEMACS_MOD_ALT;
+	    if (state & ShiftMask)	modifiers |= MOD_SHIFT;
+	    if (state & ControlMask)	modifiers |= MOD_CONTROL;
+	    if (state & xd->MetaMask)	modifiers |= MOD_META;
+	    if (state & xd->SuperMask)	modifiers |= MOD_SUPER;
+	    if (state & xd->HyperMask)	modifiers |= MOD_HYPER;
+	    if (state & xd->AltMask)	modifiers |= MOD_ALT;
 
 	    if (state & Button5Mask)    button = Button5;
 	    if (state & Button4Mask)    button = Button4;
@@ -1361,7 +1184,7 @@
 					    make_string ((Bufbyte *)"8bit", 4),
 					    make_ext_string ((Extbyte *)data,
 							     strlen((char *)data),
-							     Qctext) ) );
+							     FORMAT_CTEXT) ) );
 		break;
 	      case DndMIME:
 		/* we have to parse this in some way to extract
@@ -1374,7 +1197,7 @@
 		l_type = Qdragdrop_MIME;
 		l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
 						     strlen((char *)data),
-						     Qbinary) );
+						     FORMAT_BINARY) );
 		break;
 	      case DndFile:
 	      case DndDir:
@@ -1395,7 +1218,7 @@
 		   and escaping again will break them (cause % is unsave) */
 		l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
 						     strlen ((char *)data),
-						     Qfile_name) );
+						     FORMAT_FILENAME) );
 		l_type = Qdragdrop_URL;
 		break;
 	      default: /* Unknown, RawData and any other type */
@@ -1403,7 +1226,7 @@
 					    make_string ((Bufbyte *)"8bit", 4),
 					    make_ext_string ((Extbyte *)data,
 							     size,
-							     Qbinary) ) );
+							     FORMAT_BINARY) ) );
 		l_type = Qdragdrop_MIME;
 		break;
 	      }
@@ -1452,7 +1275,6 @@
 	  case FocusIn:
 	  case FocusOut:	 FROB(xfocus, window);		  break;
 	  case VisibilityNotify: FROB(xvisibility, window);	  break;
-	  case CreateNotify: FROB(xcreatewindow, window);	  break;
           default:
 	    w = x_event->xany.window;
 	    *x_event_copy = *x_event;
@@ -1482,12 +1304,10 @@
 static void
 handle_focus_event_1 (struct frame *f, int in_p)
 {
-#if XtSpecificationRelease > 5
-  Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
-#endif
 #ifdef HAVE_XIM
   XIM_focus_event (f, in_p);
 #endif /* HAVE_XIM */
+
   /* On focus change, clear all memory of sticky modifiers
      to avoid non-intuitive behavior. */
   clear_sticky_modifiers (XDEVICE (FRAME_DEVICE (f)));
@@ -1499,26 +1319,7 @@
      Actually, we half handle it: we handle it as far as changing the
      box cursor for redisplay, but we don't call any hooks or do any
      select-frame stuff until after the sit-for.
-
-     Unfortunately native widgets break the model because they grab
-     the keyboard focus and nothing sets it back again. I cannot find
-     any reasonable way to do this elsewhere so we assert here that
-     the keyboard focus is on the emacs text widget. Menus and dialogs
-     do this in their selection callback, but we don't want that since
-     a button having focus is legitimate. An edit field having focus
-     is mandatory. Weirdly you get a FocusOut event when you click in
-     a widget-glyph but you don't get a correspondng FocusIn when you
-     click in the frame. Why is this?  */
-  if (in_p
-#if XtSpecificationRelease > 5
-      && FRAME_X_TEXT_WIDGET (f) != focus_widget
-#endif
-      )
-    {
-      lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f),
-			     FRAME_X_TEXT_WIDGET (f));
-    }
-  /* do the generic event-stream stuff. */
+   */
   {
     Lisp_Object frm;
     Lisp_Object conser;
@@ -1603,7 +1404,7 @@
 
       /* Bleagh!!!!!!  Apparently some window managers (e.g. MWM)
 	 send synthetic MapNotify events when a window is first
-	 created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE.
+	 created, EVENT IF IT'S CREATED ICONIFIED OR INVISIBLE.
 	 Or something like that.  We initially tried a different
 	 solution below, but that ran into a different window-
 	 manager bug.
@@ -1711,26 +1512,7 @@
 }
 
 static void
-emacs_Xt_force_event_pending (struct frame* f)
-{
-  XEvent event;
-
-  Display* dpy = DEVICE_X_DISPLAY (XDEVICE (FRAME_DEVICE  (f)));
-  event.xclient.type		= ClientMessage;
-  event.xclient.display		= dpy;
-  event.xclient.message_type	= XInternAtom (dpy, "BumpQueue", False);
-  event.xclient.format		= 32;
-  event.xclient.window		= 0;
-
-  /* Send the drop message */
-  XSendEvent(dpy, XtWindow (FRAME_X_SHELL_WIDGET (f)),
-	     True, NoEventMask, &event);
-  /* Force event pending to check the X queue. */
-  quit_check_signal_tick_count++;
-}
-
-static void
-emacs_Xt_handle_magic_event (Lisp_Event *emacs_event)
+emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event)
 {
   /* This function can GC */
   XEvent *event = &emacs_event->event.magic.underlying_x_event;
@@ -1758,13 +1540,8 @@
       break;
 
     case Expose:
-      if (!check_for_ignored_expose (f, event->xexpose.x, event->xexpose.y,
-				     event->xexpose.width, event->xexpose.height)
-	  &&
-	  !find_matching_subwindow (f, event->xexpose.x, event->xexpose.y,
-	  event->xexpose.width, event->xexpose.height))
-	x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
-			       event->xexpose.width, event->xexpose.height);
+      x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
+			     event->xexpose.width, event->xexpose.height);
       break;
 
     case GraphicsExpose: /* This occurs when an XCopyArea's source area was
@@ -1802,7 +1579,6 @@
 
     case FocusIn:
     case FocusOut:
-
 #ifdef EXTERNAL_WIDGET
       /* External widget lossage: Ben said:
 	 YUCK.  The only way to make focus changes work properly is to
@@ -1842,9 +1618,6 @@
 #endif
       break;
 
-    case CreateNotify:
-      break;
-
     default:
       break;
     }
@@ -1860,14 +1633,14 @@
 /* Xt interval id's might not fit into an int (they're pointers, as it
    happens), so we need to provide a conversion list. */
 
-static struct Xt_timeout
+struct Xt_timeout
 {
   int id;
   XtIntervalId interval_id;
   struct Xt_timeout *next;
 } *pending_timeouts, *completed_timeouts;
 
-static struct Xt_timeout_blocktype
+struct Xt_timeout_blocktype
 {
   Blocktype_declare (struct Xt_timeout);
 } *the_Xt_timeout_blocktype;
@@ -1974,7 +1747,7 @@
 }
 
 static void
-Xt_timeout_to_emacs_event (Lisp_Event *emacs_event)
+Xt_timeout_to_emacs_event (struct Lisp_Event *emacs_event)
 {
   struct Xt_timeout *timeout = completed_timeouts;
   assert (timeout);
@@ -2141,7 +1914,7 @@
 }
 
 static void
-emacs_Xt_select_process (Lisp_Process *p)
+emacs_Xt_select_process (struct Lisp_Process *p)
 {
   Lisp_Object process;
   int infd = event_stream_unixoid_select_process (p);
@@ -2151,7 +1924,7 @@
 }
 
 static void
-emacs_Xt_unselect_process (Lisp_Process *p)
+emacs_Xt_unselect_process (struct Lisp_Process *p)
 {
   int infd = event_stream_unixoid_unselect_process (p);
 
@@ -2180,7 +1953,7 @@
    If we've still got pointers to it in this file, we're gonna lose hard.
  */
 void
-debug_process_finalization (Lisp_Process *p)
+debug_process_finalization (struct Lisp_Process *p)
 {
 #if 0 /* #### */
   int i;
@@ -2200,27 +1973,25 @@
 }
 
 static void
-Xt_process_to_emacs_event (Lisp_Event *emacs_event)
+Xt_process_to_emacs_event (struct Lisp_Event *emacs_event)
 {
   int i;
+  Lisp_Object process;
 
   assert (process_events_occurred > 0);
-
   for (i = 0; i < MAXDESC; i++)
     {
-      Lisp_Object process = filedesc_with_input[i];
+      process = filedesc_with_input[i];
       if (PROCESSP (process))
-	{
-	  filedesc_with_input[i] = Qnil;
-	  process_events_occurred--;
-	  /* process events have nil as channel */
-	  emacs_event->event_type = process_event;
-	  emacs_event->timestamp  = 0; /* #### */
-	  emacs_event->event.process.process = process;
-	  return;
-	}
+	break;
     }
-  abort ();
+  assert (i < MAXDESC);
+  filedesc_with_input[i] = Qnil;
+  process_events_occurred--;
+  /* process events have nil as channel */
+  emacs_event->event_type = process_event;
+  emacs_event->timestamp  = 0; /* #### */
+  emacs_event->event.process.process = process;
 }
 
 static void
@@ -2228,6 +1999,9 @@
 {
   Lisp_Object console;
   int infd;
+#ifdef HAVE_GPM
+  int mousefd;
+#endif
 
   if (CONSOLE_X_P (con))
     return; /* X consoles are automatically selected for when we
@@ -2235,6 +2009,22 @@
   infd = event_stream_unixoid_select_console (con);
   XSETCONSOLE (console, con);
   select_filedesc (infd, console);
+#ifdef HAVE_GPM
+  /* On a stream device (ie: noninteractive), bad things can happen. */
+  if (EQ (CONSOLE_TYPE (con), Qtty)) {
+    mousefd = CONSOLE_TTY_MOUSE_FD (con);
+	/* We check filedesc_to_what_closure[fd] here because if you run
+	** XEmacs from a TTY, it will fire up GPM, select the mouse fd, then
+	** if you run gnuattach to connect to another TTY, it will fire up
+	** GPM again, and try to reselect the mouse fd.  GPM uses the same
+	** fd for every connection apparently, and select_filedesc will
+	** fail its assertion if we try to select it twice.
+	*/
+    if ((mousefd >= 0) && !filedesc_to_what_closure[mousefd]) {
+      select_filedesc (mousefd, console);
+    }
+  }
+#endif
 }
 
 static void
@@ -2242,6 +2032,9 @@
 {
   Lisp_Object console;
   int infd;
+#ifdef HAVE_GPM
+  int mousefd;
+#endif
 
   if (CONSOLE_X_P (con))
     return; /* X consoles are automatically selected for when we
@@ -2249,6 +2042,15 @@
   infd = event_stream_unixoid_unselect_console (con);
   XSETCONSOLE (console, con);
   unselect_filedesc (infd);
+#ifdef HAVE_GPM
+  /* On a stream device (ie: noninteractive), bad things can happen. */
+  if (EQ (CONSOLE_TYPE (con), Qtty)) {
+    mousefd = CONSOLE_TTY_MOUSE_FD (con);
+    if (mousefd >= 0) {
+      unselect_filedesc (mousefd);
+    }
+  }
+#endif
 }
 
 /* read an event from a tty, if one is available.  Returns non-zero
@@ -2260,7 +2062,7 @@
    to be deleted.) */
 
 static int
-Xt_tty_to_emacs_event (Lisp_Event *emacs_event)
+Xt_tty_to_emacs_event (struct Lisp_Event *emacs_event)
 {
   int i;
 
@@ -2306,12 +2108,12 @@
       char *buf = alloca_array (char, XSTRING_LENGTH (f->name) + 4);
       sprintf (buf, " \"%s\"", XSTRING_DATA (f->name));
       write_string_to_stdio_stream (stderr, 0, (Bufbyte *) buf, 0,
-				    strlen (buf), Qterminal, 1);
+				    strlen (buf), FORMAT_TERMINAL);
     }
   stderr_out ("\n");
 }
 
-static const char *
+static CONST char *
 XEvent_mode_to_string (int mode)
 {
   switch (mode)
@@ -2324,7 +2126,7 @@
   }
 }
 
-static const char *
+static CONST char *
 XEvent_detail_to_string (int detail)
 {
   switch (detail)
@@ -2340,7 +2142,7 @@
   }
 }
 
-static const char *
+static CONST char *
 XEvent_visibility_to_string (int state)
 {
   switch (state)
@@ -2509,7 +2311,7 @@
 
 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
 
-void
+static void
 enqueue_Xt_dispatch_event (Lisp_Object event)
 {
   enqueue_event (event, &dispatch_event_queue, &dispatch_event_queue_tail);
@@ -2545,7 +2347,7 @@
 }
 
 static void
-emacs_Xt_next_event (Lisp_Event *emacs_event)
+emacs_Xt_next_event (struct Lisp_Event *emacs_event)
 {
  we_didnt_get_an_event:
 
@@ -2930,10 +2732,10 @@
    the '#if 0'.  Note, however, that I got "unknown structure"
    errors when I tried this. */
 XtConvertArgRec Const colorConvertArgs[] = {
-  { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
-    sizeof (Screen *) },
-  { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
-    sizeof (Colormap) }
+  {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
+   sizeof(Screen *)},
+  {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
+   sizeof(Colormap)}
 };
 
 #endif
@@ -3075,42 +2877,6 @@
 
 
 /************************************************************************/
-/*            handle focus changes for native widgets                  */
-/************************************************************************/
-static void
-emacs_Xt_event_widget_focus_in (Widget   w,
-				XEvent   *event,
-				String   *params,
-				Cardinal *num_params)
-{
-  struct frame* f =
-    x_any_widget_or_parent_to_frame (get_device_from_display (event->xany.display), w);
-
-  XtSetKeyboardFocus (FRAME_X_SHELL_WIDGET (f), w);
-}
-
-static void
-emacs_Xt_event_widget_focus_out (Widget   w,
-				 XEvent   *event,
-				 String   *params,
-				 Cardinal *num_params)
-{
-}
-
-static XtActionsRec widgetActionsList[] =
-{
-  {"widget-focus-in",	emacs_Xt_event_widget_focus_in	},
-  {"widget-focus-out",	emacs_Xt_event_widget_focus_out	},
-};
-
-static void
-emacs_Xt_event_add_widget_actions (XtAppContext ctx)
-{
-  XtAppAddActions (ctx, widgetActionsList, 2);
-}
-
-
-/************************************************************************/
 /*                            initialization                            */
 /************************************************************************/
 
@@ -3119,15 +2885,20 @@
 {
   defsymbol (&Qkey_mapping, "key-mapping");
   defsymbol (&Qsans_modifiers, "sans-modifiers");
-  defsymbol (&Qself_insert_command, "self-insert-command");
 }
 
 void
-reinit_vars_of_event_Xt (void)
+vars_of_event_Xt (void)
 {
+  dispatch_event_queue = Qnil;
+  staticpro (&dispatch_event_queue);
+  dispatch_event_queue_tail = Qnil;
+
+  /* this function only makes safe calls */
+  init_what_input_once ();
+
   Xt_event_stream = xnew (struct event_stream);
   Xt_event_stream->event_pending_p 	 = emacs_Xt_event_pending_p;
-  Xt_event_stream->force_event_pending 	 = emacs_Xt_force_event_pending;
   Xt_event_stream->next_event_cb	 = emacs_Xt_next_event;
   Xt_event_stream->handle_magic_event_cb = emacs_Xt_handle_magic_event;
   Xt_event_stream->add_timeout_cb 	 = emacs_Xt_add_timeout;
@@ -3140,23 +2911,14 @@
   Xt_event_stream->create_stream_pair_cb = emacs_Xt_create_stream_pair;
   Xt_event_stream->delete_stream_pair_cb = emacs_Xt_delete_stream_pair;
 
-  the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
-
-  last_quit_check_signal_tick_count = 0;
-
-  /* this function only makes safe calls */
-  init_what_input_once ();
-}
-
-void
-vars_of_event_Xt (void)
-{
-  reinit_vars_of_event_Xt ();
-
-  dispatch_event_queue = Qnil;
-  staticpro (&dispatch_event_queue);
-  dispatch_event_queue_tail = Qnil;
-  pdump_wire (&dispatch_event_queue_tail);
+  DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /*
+*Non-nil makes modifier keys sticky.
+This means that you can release the modifier key before pressing down
+the key that you wish to be modified.  Although this is non-standard
+behavior, it is recommended because it reduces the strain on your hand,
+thus reducing the incidence of the dreaded Emacs-pinky syndrome.
+*/ );
+  modifier_keys_are_sticky = 0;
 
   DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /*
 *Non-nil means to allow synthetic events.  Nil means they are ignored.
@@ -3174,6 +2936,10 @@
 */ );
   x_debug_events = 0;
 #endif
+
+  the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
+
+  last_quit_check_signal_tick_count = 0;
 }
 
 /* This mess is a hack that patches the shell widget to treat visual inheritance
@@ -3220,7 +2986,7 @@
   XSetErrorHandler (x_error_handler);
   XSetIOErrorHandler (x_IO_error_handler);
 
-#ifndef WIN32_NATIVE
+#ifndef WINDOWSNT
   XtAppAddInput (Xt_app_con, signal_event_pipe[0],
 		 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
 		 Xt_what_callback, 0);
@@ -3237,8 +3003,6 @@
 			 NULL, 0,
 			 XtCacheByDisplay, EmacsFreeXIMStyles);
 #endif /* XIM_XLIB */
-  /* Add extra actions to native widgets to handle focus and friends. */
-  emacs_Xt_event_add_widget_actions (Xt_app_con);
 
   /* insert the visual inheritance patch/hack described above */
   orig_shell_init_proc = shellClassRec.core_class.initialize;