]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
2002-08-10 Andrew Choi <akochoi@shaw.ca>
[gnu-emacs] / src / xterm.c
index 503b67bcdf38ee5b836414300d6c26889a295aaa..338fd65613f38071a39e78bd6a3bfe7827067d18 100644 (file)
@@ -1,5 +1,5 @@
 /* X Communication module for terminals which understand the X protocol.
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
+   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -98,7 +98,7 @@ Boston, MA 02111-1307, USA.  */
 #endif
 
 #ifdef USE_LUCID
 #endif
 
 #ifdef USE_LUCID
-extern int xlwmenu_window_p (Widget w, Window window);
+extern int xlwmenu_window_p P_ ((Widget w, Window window));
 extern void xlwmenu_redisplay P_ ((Widget));
 #endif
 
 extern void xlwmenu_redisplay P_ ((Widget));
 #endif
 
@@ -253,6 +253,13 @@ static Lisp_Object previous_help_echo;
 
 static int any_help_event_p;
 
 
 static int any_help_event_p;
 
+/* Non-zero means autoselect window with the mouse cursor.  */
+
+int mouse_autoselect_window;
+
+/* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
+static Lisp_Object last_window;
+
 /* Non-zero means draw block and hollow cursor as wide as the glyph
    under it.  For example, if a block cursor is over a tab, it will be
    drawn as wide as that tab on the display.  */
 /* Non-zero means draw block and hollow cursor as wide as the glyph
    under it.  For example, if a block cursor is over a tab, it will be
    drawn as wide as that tab on the display.  */
@@ -379,9 +386,15 @@ extern int errno;
 
 /* A mask of extra modifier bits to put into every keyboard char.  */
 
 
 /* A mask of extra modifier bits to put into every keyboard char.  */
 
-extern int extra_keyboard_modifiers;
+extern EMACS_INT extra_keyboard_modifiers;
+
+/* The keysyms to use for the various modifiers.  */
+
+Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
+static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
 
 static Lisp_Object Qvendor_specific_keysyms;
 
 static Lisp_Object Qvendor_specific_keysyms;
+static Lisp_Object Qlatin_1, Qutf_8;
 
 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
 extern Lisp_Object x_icon_type P_ ((struct frame *));
 
 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
 extern Lisp_Object x_icon_type P_ ((struct frame *));
@@ -417,7 +430,8 @@ static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
 static void set_output_cursor P_ ((struct cursor_pos *));
 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
                                           int *, int *, int *, int));
 static void set_output_cursor P_ ((struct cursor_pos *));
 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
                                           int *, int *, int *, int));
-static void note_mode_line_highlight P_ ((struct window *, int, int));
+static void note_mode_line_or_margin_highlight P_ ((struct window *, int,
+                                                   int, int));
 static void note_mouse_highlight P_ ((struct frame *, int, int));
 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
 static void note_mouse_highlight P_ ((struct frame *, int, int));
 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
@@ -452,14 +466,27 @@ static void x_clear_cursor P_ ((struct window *));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
+static int  x_focus_changed P_ ((int,
+                                 int,
+                                 struct x_display_info *,
+                                 struct frame *,
+                                 struct input_event *,
+                                 int));
+static int  x_detect_focus_change P_ ((struct x_display_info *,
+                                       XEvent *,
+                                       struct input_event *,
+                                       int));
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
-static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
+static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
+                                  enum text_cursor_kinds));
 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
                                       XRectangle *));
 static void expose_frame P_ ((struct frame *, int, int, int, int));
 static int expose_window_tree P_ ((struct window *, XRectangle *));
 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
                                       XRectangle *));
 static void expose_frame P_ ((struct frame *, int, int, int, int));
 static int expose_window_tree P_ ((struct window *, XRectangle *));
+static void expose_overlaps P_ ((struct window *, struct glyph_row *,
+                                struct glyph_row *));
 static int expose_window P_ ((struct window *, XRectangle *));
 static void expose_area P_ ((struct window *, struct glyph_row *,
                             XRectangle *, enum glyph_row_area));
 static int expose_window P_ ((struct window *, XRectangle *));
 static void expose_area P_ ((struct window *, struct glyph_row *,
                             XRectangle *, enum glyph_row_area));
@@ -490,6 +517,8 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            enum scroll_bar_part *,
                                            Lisp_Object *, Lisp_Object *,
                                            unsigned long *));
                                            enum scroll_bar_part *,
                                            Lisp_Object *, Lisp_Object *,
                                            unsigned long *));
+static void x_check_fullscreen P_ ((struct frame *));
+static void x_check_fullscreen_move P_ ((struct frame *));
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
@@ -837,7 +866,7 @@ x_draw_fringe_bitmap (w, row, which, left_p)
   Window window = FRAME_X_WINDOW (f);
   int x, y, wd, h, dy;
   int b1, b2;
   Window window = FRAME_X_WINDOW (f);
   int x, y, wd, h, dy;
   int b1, b2;
-  unsigned char *bits;
+  unsigned char *bits = NULL;
   Pixmap pixmap;
   GC gc = f->output_data.x->normal_gc;
   struct face *face;
   Pixmap pixmap;
   GC gc = f->output_data.x->normal_gc;
   struct face *face;
@@ -1124,7 +1153,8 @@ static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
                                                       XChar2b *,
                                                       int *));
 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
                                                       XChar2b *,
                                                       int *));
 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
-                                                     int, XChar2b *, int));
+                                                     int, XChar2b *, int,
+                                                     int));
 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
 static void x_append_glyph P_ ((struct it *));
 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
 static void x_append_glyph P_ ((struct it *));
@@ -1265,15 +1295,17 @@ x_encode_char (c, char2b, font_info)
 
 /* Get face and two-byte form of character C in face FACE_ID on frame
    F.  The encoding of C is returned in *CHAR2B.  MULTIBYTE_P non-zero
 
 /* Get face and two-byte form of character C in face FACE_ID on frame
    F.  The encoding of C is returned in *CHAR2B.  MULTIBYTE_P non-zero
-   means we want to display multibyte text.  Value is a pointer to a
-   realized face that is ready for display.  */
+   means we want to display multibyte text.  DISPLAY_P non-zero means
+   make sure that X resources for the face returned are allocated.
+   Value is a pointer to a realized face that is ready for display if
+   DISPLAY_P is non-zero.  */
 
 static INLINE struct face *
 
 static INLINE struct face *
-x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
+x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
      struct frame *f;
      int c, face_id;
      XChar2b *char2b;
      struct frame *f;
      int c, face_id;
      XChar2b *char2b;
-     int multibyte_p;
+     int multibyte_p, display_p;
 {
   struct face *face = FACE_FROM_ID (f, face_id);
 
 {
   struct face *face = FACE_FROM_ID (f, face_id);
 
@@ -1315,8 +1347,11 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
     }
 
   /* Make sure X resources of the face are allocated.  */
     }
 
   /* Make sure X resources of the face are allocated.  */
-  xassert (face != NULL);
-  PREPARE_FACE_FOR_DISPLAY (f, face);
+  if (display_p)
+    {
+      xassert (face != NULL);
+      PREPARE_FACE_FOR_DISPLAY (f, face);
+    }
   
   return face;
 }
   
   return face;
 }
@@ -1827,7 +1862,7 @@ x_produce_glyphs (it)
       /* Get font to use.  Encode IT->char_to_display.  */
       x_get_char_face_and_encoding (it->f, it->char_to_display,
                                    it->face_id, &char2b,
       /* Get font to use.  Encode IT->char_to_display.  */
       x_get_char_face_and_encoding (it->f, it->char_to_display,
                                    it->face_id, &char2b,
-                                   it->multibyte_p);
+                                   it->multibyte_p, 0);
       font = face->font;
 
       /* When no suitable font found, use the default font.  */
       font = face->font;
 
       /* When no suitable font found, use the default font.  */
@@ -2059,7 +2094,7 @@ x_produce_glyphs (it)
       it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
       face = FACE_FROM_ID (it->f, it->face_id);
       x_get_char_face_and_encoding (it->f, it->char_to_display,
       it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
       face = FACE_FROM_ID (it->f, it->face_id);
       x_get_char_face_and_encoding (it->f, it->char_to_display,
-                                   it->face_id, &char2b, it->multibyte_p);
+                                   it->face_id, &char2b, it->multibyte_p, 0);
       font = face->font;
 
       /* When no suitable font found, use the default font.  */
       font = face->font;
 
       /* When no suitable font found, use the default font.  */
@@ -2147,7 +2182,7 @@ x_produce_glyphs (it)
              
              face = FACE_FROM_ID (it->f, face_id);
              x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
              
              face = FACE_FROM_ID (it->f, face_id);
              x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
-                                           it->multibyte_p);
+                                           it->multibyte_p, 0);
              font = face->font;
              if (font == NULL)
                {
              font = face->font;
              if (font == NULL)
                {
@@ -4093,8 +4128,12 @@ x_draw_image_foreground (s)
             the image.  I believe it's looking better if we do
             nothing here for mouse-face.  */
          if (s->hl == DRAW_CURSOR)
             the image.  I believe it's looking better if we do
             nothing here for mouse-face.  */
          if (s->hl == DRAW_CURSOR)
-           XDrawRectangle (s->display, s->window, s->gc, x, y,
-                           s->img->width - 1, s->img->height - 1);
+           {
+             int r = s->img->relief;
+             if (r < 0) r = -r;
+             XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
+                             s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+           }
        }
     }
   else
        }
     }
   else
@@ -4209,8 +4248,12 @@ x_draw_image_foreground_1 (s, pixmap)
             the image.  I believe it's looking better if we do
             nothing here for mouse-face.  */
          if (s->hl == DRAW_CURSOR)
             the image.  I believe it's looking better if we do
             nothing here for mouse-face.  */
          if (s->hl == DRAW_CURSOR)
-           XDrawRectangle (s->display, pixmap, s->gc, x, y,
-                           s->img->width - 1, s->img->height - 1);
+           {
+             int r = s->img->relief;
+             if (r < 0) r = -r;
+             XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
+                             s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+           }
        }
     }
   else
        }
     }
   else
@@ -4947,7 +4990,7 @@ x_set_glyph_string_background_width (s, start, last_x)
        int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
        faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id);        \
        x_get_char_face_and_encoding (XFRAME (w->frame), c,               \
        int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
        faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id);        \
        x_get_char_face_and_encoding (XFRAME (w->frame), c,               \
-                                     this_face_id, char2b + n, 1);       \
+                                     this_face_id, char2b + n, 1, 1);    \
       }                                                                          \
                                                                          \
     /* Make glyph_strings for each glyph sequence that is drawable by    \
       }                                                                          \
                                                                          \
     /* Make glyph_strings for each glyph sequence that is drawable by    \
@@ -5300,6 +5343,14 @@ x_write_glyphs (start, len)
                     hpos, hpos + len,
                     DRAW_NORMAL_TEXT, 0);
 
                     hpos, hpos + len,
                     DRAW_NORMAL_TEXT, 0);
 
+  /* Invalidate old phys cursor if the glyph at its hpos is redrawn.  */
+  if (updated_area == TEXT_AREA
+      && updated_window->phys_cursor_on_p
+      && updated_window->phys_cursor.vpos == output_cursor.vpos
+      && updated_window->phys_cursor.hpos >= hpos
+      && updated_window->phys_cursor.hpos < hpos + len)
+    updated_window->phys_cursor_on_p = 0;
+
   UNBLOCK_INPUT;
   
   /* Advance the output cursor.  */
   UNBLOCK_INPUT;
   
   /* Advance the output cursor.  */
@@ -6021,6 +6072,39 @@ x_phys_cursor_in_rect_p (w, r)
 }
 
 
 }
 
 
+/* Redraw those parts of glyphs rows during expose event handling that
+   overlap other rows.  Redrawing of an exposed line writes over parts
+   of lines overlapping that exposed line; this function fixes that.
+
+   W is the window being exposed.  FIRST_OVERLAPPING_ROW is the first
+   row in W's current matrix that is exposed and overlaps other rows.
+   LAST_OVERLAPPING_ROW is the last such row.  */
+
+static void
+expose_overlaps (w, first_overlapping_row, last_overlapping_row)
+     struct window *w;
+     struct glyph_row *first_overlapping_row;
+     struct glyph_row *last_overlapping_row;
+{
+  struct glyph_row *row;
+  
+  for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
+    if (row->overlapping_p)
+      {
+       xassert (row->enabled_p && !row->mode_line_p);
+         
+       if (row->used[LEFT_MARGIN_AREA])
+         x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
+  
+       if (row->used[TEXT_AREA])
+         x_fix_overlapping_area (w, row, TEXT_AREA);
+  
+       if (row->used[RIGHT_MARGIN_AREA])
+         x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
+      }
+}
+
+
 /* Redraw the part of window W intersection rectangle FR.  Pixel
    coordinates in FR are frame-relative.  Call this function with
    input blocked.  Value is non-zero if the exposure overwrites
 /* Redraw the part of window W intersection rectangle FR.  Pixel
    coordinates in FR are frame-relative.  Call this function with
    input blocked.  Value is non-zero if the exposure overwrites
@@ -6062,6 +6146,7 @@ expose_window (w, fr)
       int yb = window_text_bottom_y (w);
       struct glyph_row *row;
       int cursor_cleared_p;
       int yb = window_text_bottom_y (w);
       struct glyph_row *row;
       int cursor_cleared_p;
+      struct glyph_row *first_overlapping_row, *last_overlapping_row;
   
       TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
              r.x, r.y, r.width, r.height));
   
       TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
              r.x, r.y, r.width, r.height));
@@ -6080,7 +6165,8 @@ expose_window (w, fr)
       else
        cursor_cleared_p = 0;
 
       else
        cursor_cleared_p = 0;
 
-      /* Find the first row intersecting the rectangle R.  */
+      /* Update lines intersecting rectangle R.  */
+      first_overlapping_row = last_overlapping_row = NULL;
       for (row = w->current_matrix->rows;
           row->enabled_p;
           ++row)
       for (row = w->current_matrix->rows;
           row->enabled_p;
           ++row)
@@ -6093,6 +6179,13 @@ expose_window (w, fr)
              || (r.y >= y0 && r.y < y1)
              || (r.y + r.height > y0 && r.y + r.height < y1))
            {
              || (r.y >= y0 && r.y < y1)
              || (r.y + r.height > y0 && r.y + r.height < y1))
            {
+             if (row->overlapping_p)
+               {
+                 if (first_overlapping_row == NULL)
+                   first_overlapping_row = row;
+                 last_overlapping_row = row;
+               }
+             
              if (expose_line (w, row, &r))
                mouse_face_overwritten_p = 1;
            }
              if (expose_line (w, row, &r))
                mouse_face_overwritten_p = 1;
            }
@@ -6113,6 +6206,10 @@ expose_window (w, fr)
 
       if (!w->pseudo_window_p)
        {
 
       if (!w->pseudo_window_p)
        {
+         /* Fix the display of overlapping rows.  */
+         if (first_overlapping_row)
+           expose_overlaps (w, first_overlapping_row, last_overlapping_row);
+         
          /* Draw border between windows.  */
          x_draw_vertical_border (w);
       
          /* Draw border between windows.  */
          x_draw_vertical_border (w);
       
@@ -6252,6 +6349,121 @@ x_new_focus_frame (dpyinfo, frame)
   x_frame_rehighlight (dpyinfo);
 }
 
   x_frame_rehighlight (dpyinfo);
 }
 
+/* Handle FocusIn and FocusOut state changes for FRAME.
+   If FRAME has focus and there exists more than one frame, puts
+   an FOCUS_IN_EVENT into BUFP.
+   Returns number of events inserted into BUFP. */
+
+static int
+x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
+     int type;
+     int state;
+     struct x_display_info *dpyinfo;
+     struct frame *frame;
+     struct input_event *bufp;
+     int numchars;
+{
+  int nr_events = 0;
+
+  if (type == FocusIn)
+    {
+      if (dpyinfo->x_focus_event_frame != frame)
+        {
+          x_new_focus_frame (dpyinfo, frame);
+          dpyinfo->x_focus_event_frame = frame;
+      
+          /* Don't stop displaying the initial startup message
+             for a switch-frame event we don't need.  */
+          if (numchars > 0
+              && GC_NILP (Vterminal_frame)
+              && GC_CONSP (Vframe_list)
+              && !GC_NILP (XCDR (Vframe_list)))
+            {
+              bufp->kind = FOCUS_IN_EVENT;
+              XSETFRAME (bufp->frame_or_window, frame);
+              bufp->arg = Qnil;
+              ++bufp;
+              numchars--;
+              ++nr_events;
+            }
+        }
+
+      frame->output_data.x->focus_state |= state;
+
+#ifdef HAVE_X_I18N
+      if (FRAME_XIC (frame))
+        XSetICFocus (FRAME_XIC (frame));
+#endif
+    }
+  else if (type == FocusOut)
+    {
+      frame->output_data.x->focus_state &= ~state;
+      
+      if (dpyinfo->x_focus_event_frame == frame)
+        {
+          dpyinfo->x_focus_event_frame = 0;
+          x_new_focus_frame (dpyinfo, 0);
+        }
+
+#ifdef HAVE_X_I18N
+      if (FRAME_XIC (frame))
+        XUnsetICFocus (FRAME_XIC (frame));
+#endif
+    }
+
+  return nr_events;
+}
+
+/* The focus may have changed.  Figure out if it is a real focus change,
+   by checking both FocusIn/Out and Enter/LeaveNotify events.
+
+   Returns number of events inserted into BUFP. */
+
+static int
+x_detect_focus_change (dpyinfo, event, bufp, numchars)
+     struct x_display_info *dpyinfo;
+     XEvent *event;
+     struct input_event *bufp;
+     int numchars;
+{
+  struct frame *frame;
+  int nr_events = 0;
+  
+  frame = x_top_window_to_frame (dpyinfo, event->xany.window);
+  if (! frame) return nr_events;
+  
+  switch (event->type)
+    {
+    case EnterNotify:
+    case LeaveNotify:
+      if (event->xcrossing.detail != NotifyInferior
+          && event->xcrossing.focus
+          && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT))
+        nr_events = x_focus_changed ((event->type == EnterNotify
+                                      ? FocusIn : FocusOut),
+                                     FOCUS_IMPLICIT,
+                                     dpyinfo,
+                                     frame,
+                                     bufp,
+                                     numchars);
+      break;
+
+    case FocusIn:
+    case FocusOut:
+      nr_events = x_focus_changed (event->type,
+                                   (event->xfocus.detail == NotifyPointer
+                                    ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
+                                   dpyinfo,
+                                   frame,
+                                   bufp,
+                                   numchars);
+      break;
+    }
+
+  return nr_events;
+}
+
+
 /* Handle an event saying the mouse has moved out of an Emacs frame.  */
 
 void
 /* Handle an event saying the mouse has moved out of an Emacs frame.  */
 
 void
@@ -6420,12 +6632,28 @@ x_x_to_emacs_modifiers (dpyinfo, state)
      struct x_display_info *dpyinfo;
      unsigned int state;
 {
      struct x_display_info *dpyinfo;
      unsigned int state;
 {
+  EMACS_UINT mod_meta = meta_modifier;
+  EMACS_UINT mod_alt  = alt_modifier;
+  EMACS_UINT mod_hyper = hyper_modifier;
+  EMACS_UINT mod_super = super_modifier;
+  Lisp_Object tem;
+  
+  tem = Fget (Vx_alt_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
+  tem = Fget (Vx_meta_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
+  tem = Fget (Vx_hyper_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
+  tem = Fget (Vx_super_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
+  
+
   return (  ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
   return (  ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
-         | ((state & ControlMask)             ? ctrl_modifier  : 0)
-         | ((state & dpyinfo->meta_mod_mask)  ? meta_modifier  : 0)
-         | ((state & dpyinfo->alt_mod_mask)   ? alt_modifier  : 0)
-         | ((state & dpyinfo->super_mod_mask) ? super_modifier  : 0)
-         | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier  : 0));
+            | ((state & ControlMask)                   ? ctrl_modifier : 0)
+            | ((state & dpyinfo->meta_mod_mask)                ? mod_meta      : 0)
+            | ((state & dpyinfo->alt_mod_mask)         ? mod_alt       : 0)
+            | ((state & dpyinfo->super_mod_mask)       ? mod_super     : 0)
+            | ((state & dpyinfo->hyper_mod_mask)       ? mod_hyper     : 0));
 }
 
 static unsigned int
 }
 
 static unsigned int
@@ -6433,12 +6661,29 @@ x_emacs_to_x_modifiers (dpyinfo, state)
      struct x_display_info *dpyinfo;
      unsigned int state;
 {
      struct x_display_info *dpyinfo;
      unsigned int state;
 {
-  return (  ((state & alt_modifier)    ? dpyinfo->alt_mod_mask   : 0)
-         | ((state & super_modifier)   ? dpyinfo->super_mod_mask : 0)
-         | ((state & hyper_modifier)   ? dpyinfo->hyper_mod_mask : 0)
-         | ((state & shift_modifier)   ? ShiftMask        : 0)
-         | ((state & ctrl_modifier)    ? ControlMask      : 0)
-         | ((state & meta_modifier)    ? dpyinfo->meta_mod_mask  : 0));
+  EMACS_UINT mod_meta = meta_modifier;
+  EMACS_UINT mod_alt  = alt_modifier;
+  EMACS_UINT mod_hyper = hyper_modifier;
+  EMACS_UINT mod_super = super_modifier;
+  
+  Lisp_Object tem;
+  
+  tem = Fget (Vx_alt_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
+  tem = Fget (Vx_meta_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
+  tem = Fget (Vx_hyper_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
+  tem = Fget (Vx_super_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
+  
+  
+  return (  ((state & mod_alt)         ? dpyinfo->alt_mod_mask   : 0)
+            | ((state & mod_super)     ? dpyinfo->super_mod_mask : 0)
+            | ((state & mod_hyper)     ? dpyinfo->hyper_mod_mask : 0)
+            | ((state & shift_modifier)        ? ShiftMask        : 0)
+            | ((state & ctrl_modifier) ? ControlMask      : 0)
+            | ((state & mod_meta)      ? dpyinfo->meta_mod_mask  : 0));
 }
 
 /* Convert a keysym to its name.  */
 }
 
 /* Convert a keysym to its name.  */
@@ -6564,9 +6809,9 @@ construct_mouse_click (result, event, f)
      XButtonEvent *event;
      struct frame *f;
 {
      XButtonEvent *event;
      struct frame *f;
 {
-  /* Make the event type no_event; we'll change that when we decide
+  /* Make the event type NO_EVENT; we'll change that when we decide
      otherwise.  */
      otherwise.  */
-  result->kind = mouse_click;
+  result->kind = MOUSE_CLICK_EVENT;
   result->code = event->button - Button1;
   result->timestamp = event->time;
   result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
   result->code = event->button - Button1;
   result->timestamp = event->time;
   result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
@@ -6622,11 +6867,6 @@ note_mouse_movement (frame, event)
     }
 }
 
     }
 }
 
-/* This is used for debugging, to turn off note_mouse_highlight.  */
-
- int disable_mouse_highlight;
-
-
 \f
 /************************************************************************
                              Mouse Face
 \f
 /************************************************************************
                              Mouse Face
@@ -6743,80 +6983,54 @@ frame_to_window_pixel_xy (w, x, y)
 }
 
 
 }
 
 
-/* Take proper action when mouse has moved to the mode or header line of
-   window W, x-position X.  MODE_LINE_P non-zero means mouse is on the
-   mode line.  X is relative to the start of the text display area of
-   W, so the width of fringes and scroll bars must be subtracted
-   to get a position relative to the start of the mode line.  */
-
+/* Take proper action when mouse has moved to the mode or header line
+   or marginal area of window W, x-position X and y-position Y.  Area
+   is 1, 3, 6 or 7 for the mode line, header line, left and right
+   marginal area respectively.  X is relative to the start of the text
+   display area of W, so the width of bitmap areas and scroll bars
+   must be subtracted to get a position relative to the start of the
+   mode line.  */
 static void
 static void
-note_mode_line_highlight (w, x, mode_line_p)
+note_mode_line_or_margin_highlight (w, x, y, portion)
      struct window *w;
      struct window *w;
-     int x, mode_line_p;
+     int x, y, portion;
 {
   struct frame *f = XFRAME (w->frame);
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
 {
   struct frame *f = XFRAME (w->frame);
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
-  struct glyph_row *row;
+  int charpos;
+  Lisp_Object string, help, map, pos;
 
 
-  if (mode_line_p)
-    row = MATRIX_MODE_LINE_ROW (w->current_matrix);
-  else
-    row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
+  if (portion == 1 || portion == 3)
+    string = mode_line_string (w, x, y, portion == 1, &charpos);
+   else
+     string = marginal_area_string (w, x, y, portion, &charpos);
 
 
-  if (row->enabled_p)
+  if (STRINGP (string))
     {
     {
-      struct glyph *glyph, *end;
-      Lisp_Object help, map;
-      int x0;
-      
-      /* Find the glyph under X.  */
-      glyph = row->glyphs[TEXT_AREA];
-      end = glyph + row->used[TEXT_AREA];
-      x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
-             + FRAME_X_LEFT_FRINGE_WIDTH (f));
+      pos = make_number (charpos);
       
       
-      while (glyph < end
-            && x >= x0 + glyph->pixel_width)
+      /* If we're on a string with `help-echo' text property, arrange
+        for the help to be displayed.  This is done by setting the
+        global variable help_echo to the help string.  */
+      help = Fget_text_property (pos, Qhelp_echo, string);
+      if (!NILP (help))
        {
        {
-         x0 += glyph->pixel_width;
-         ++glyph;
+         help_echo = help;
+         XSETWINDOW (help_echo_window, w);
+         help_echo_object = string;
+         help_echo_pos = charpos;
        }
 
        }
 
-      if (glyph < end
-         && STRINGP (glyph->object)
-         && XSTRING (glyph->object)->intervals
-         && glyph->charpos >= 0
-         && glyph->charpos < XSTRING (glyph->object)->size)
-       {
-         /* If we're on a string with `help-echo' text property,
-            arrange for the help to be displayed.  This is done by
-            setting the global variable help_echo to the help string.  */
-         help = Fget_text_property (make_number (glyph->charpos),
-                                    Qhelp_echo, glyph->object);
-         if (!NILP (help))
-           {
-             help_echo = help;
-             XSETWINDOW (help_echo_window, w);
-             help_echo_object = glyph->object;
-             help_echo_pos = glyph->charpos;
-           }
-
-         /* Change the mouse pointer according to what is under X/Y.  */
-         map = Fget_text_property (make_number (glyph->charpos),
-                                   Qlocal_map, glyph->object);
-         if (KEYMAPP (map))
-           cursor = f->output_data.x->nontext_cursor;
-         else
-           {
-             map = Fget_text_property (make_number (glyph->charpos),
-                                       Qkeymap, glyph->object);
-             if (KEYMAPP (map))
-               cursor = f->output_data.x->nontext_cursor;
-           }
-       }
+     /* Change the mouse pointer according to what is under X/Y.  */
+      map = Fget_text_property (pos, Qlocal_map, string);
+      if (!KEYMAPP (map))
+       map = Fget_text_property (pos, Qkeymap, string);
+      if (KEYMAPP (map))
+       cursor = f->output_data.x->nontext_cursor;
     }
     }
-
+  
   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
 }
 
   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
 }
 
@@ -6844,7 +7058,7 @@ note_mouse_highlight (f, x, y)
     return;
 #endif
 
     return;
 #endif
 
-  if (disable_mouse_highlight
+  if (NILP (Vmouse_highlight)
       || !f->glyphs_initialized_p)
     return;
 
       || !f->glyphs_initialized_p)
     return;
 
@@ -6884,10 +7098,10 @@ note_mouse_highlight (f, x, y)
       return;
     }
 
       return;
     }
 
-  /* Mouse is on the mode or header line?  */
-  if (portion == 1 || portion == 3)
+  /* Mouse is on the mode, header line or margin?  */
+  if (portion == 1 || portion == 3 || portion == 6 || portion == 7)
     {
     {
-      note_mode_line_highlight (w, x, portion == 1);
+      note_mode_line_or_margin_highlight (w, x, y, portion);
       return;
     }
   
       return;
     }
   
@@ -7103,7 +7317,7 @@ note_mouse_highlight (f, x, y)
              if (NILP (b))
                b = make_number (0);
              if (NILP (e))
              if (NILP (b))
                b = make_number (0);
              if (NILP (e))
-               e = make_number (XSTRING (object)->size - 1);
+               e = make_number (SCHARS (object) - 1);
              fast_find_string_pos (w, XINT (b), object,
                                    &dpyinfo->mouse_face_beg_col,
                                    &dpyinfo->mouse_face_beg_row,
              fast_find_string_pos (w, XINT (b), object,
                                    &dpyinfo->mouse_face_beg_col,
                                    &dpyinfo->mouse_face_beg_row,
@@ -7201,7 +7415,7 @@ note_mouse_highlight (f, x, y)
            /* Try text properties.  */
            if (STRINGP (object)
                && charpos >= 0
            /* Try text properties.  */
            if (STRINGP (object)
                && charpos >= 0
-               && charpos < XSTRING (object)->size)
+               && charpos < SCHARS (object))
              {
                help = Fget_text_property (make_number (charpos),
                                           Qhelp_echo, object);
              {
                help = Fget_text_property (make_number (charpos),
                                           Qhelp_echo, object);
@@ -7468,7 +7682,7 @@ note_tool_bar_highlight (f, x, y)
       
  set_help_echo:
   
       
  set_help_echo:
   
-  /* Set help_echo to a help string.to display for this tool-bar item.
+  /* Set help_echo to a help string to display for this tool-bar item.
      XTread_socket does the rest.  */
   help_echo_object = help_echo_window = Qnil;
   help_echo_pos = -1;
      XTread_socket does the rest.  */
   help_echo_object = help_echo_window = Qnil;
   help_echo_pos = -1;
@@ -7655,8 +7869,8 @@ fast_find_position (w, pos, hpos, vpos, x, y, stop)
 
 
 /* Find the position of the glyph for position POS in OBJECT in
 
 
 /* Find the position of the glyph for position POS in OBJECT in
-   window W's current matrix, and return in *X/*Y the pixel
-   coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
+   window W's current matrix, and return in *X*Y the pixel
+   coordinates, and return in *HPOS*VPOS the column/row of the glyph.
 
    RIGHT_P non-zero means return the position of the right edge of the
    glyph, RIGHT_P zero means return the left edge position.
 
    RIGHT_P non-zero means return the position of the right edge of the
    glyph, RIGHT_P zero means return the left edge position.
@@ -7750,6 +7964,8 @@ show_mouse_face (dpyinfo, draw)
   if (/* If window is in the process of being destroyed, don't bother
         to do anything.  */
       w->current_matrix != NULL
   if (/* If window is in the process of being destroyed, don't bother
         to do anything.  */
       w->current_matrix != NULL
+      /* Don't update mouse highlight if hidden */
+      && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
       /* Recognize when we are called to operate on rows that don't exist
         anymore.  This can happen when a window is split.  */
       && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
       /* Recognize when we are called to operate on rows that don't exist
         anymore.  This can happen when a window is split.  */
       && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
@@ -8282,7 +8498,7 @@ static Boolean xaw3d_pick_top;
 /* Action hook installed via XtAppAddActionHook when toolkit scroll
    bars are used..  The hook is responsible for detecting when
    the user ends an interaction with the scroll bar, and generates
 /* Action hook installed via XtAppAddActionHook when toolkit scroll
    bars are used..  The hook is responsible for detecting when
    the user ends an interaction with the scroll bar, and generates
-   a `end-scroll' scroll_bar_click' event if so.  */
+   a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so.  */
 
 static void
 xt_action_hook (widget, client_data, action_name, event, params,
 
 static void
 xt_action_hook (widget, client_data, action_name, event, params,
@@ -8412,7 +8628,7 @@ x_scroll_bar_to_input_event (event, ievent)
   XSETWINDOW (window, w);
   f = XFRAME (w->frame);
   
   XSETWINDOW (window, w);
   f = XFRAME (w->frame);
   
-  ievent->kind = scroll_bar_click;
+  ievent->kind = SCROLL_BAR_CLICK_EVENT;
   ievent->frame_or_window = window;
   ievent->arg = Qnil;
   ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
   ievent->frame_or_window = window;
   ievent->arg = Qnil;
   ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
@@ -8435,7 +8651,7 @@ x_scroll_bar_to_input_event (event, ievent)
 
 /* Scroll bar callback for Motif scroll bars.  WIDGET is the scroll
    bar widget.  CLIENT_DATA is a pointer to the scroll_bar structure.
 
 /* Scroll bar callback for Motif scroll bars.  WIDGET is the scroll
    bar widget.  CLIENT_DATA is a pointer to the scroll_bar structure.
-   CALL_DATA is a pointer a a XmScrollBarCallbackStruct.  */
+   CALL_DATA is a pointer to a XmScrollBarCallbackStruct.  */
 
 static void
 xm_scroll_callback (widget, client_data, call_data)
 
 static void
 xm_scroll_callback (widget, client_data, call_data)
@@ -8489,31 +8705,10 @@ xm_scroll_callback (widget, client_data, call_data)
        XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
        UNBLOCK_INPUT;
 
        XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
        UNBLOCK_INPUT;
 
-       /* At the max position of the scroll bar, do a line-wise
-          movement.  Without doing anything, we would be called with
-          the same cs->value again and again.  If we want to make
-          sure that we can reach the end of the buffer, we have to do
-          something.
-
-          Implementation note: setting bar->dragging always to
-          cs->value gives a smoother movement at the max position.
-          Setting it to nil when doing line-wise movement gives
-          a better slider behavior. */
-       
-       if (cs->value + slider_size == XM_SB_MAX
-           || (dragging_down_p
-               && last_scroll_bar_part == scroll_bar_down_arrow))
-         {
-           part = scroll_bar_down_arrow;
-           bar->dragging = Qnil;
-         }
-       else
-         {
-           whole = XM_SB_RANGE;
-           portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
-           part = scroll_bar_handle;
-           bar->dragging = make_number (cs->value);
-         }
+       whole = XM_SB_RANGE - slider_size;
+       portion = min (cs->value - XM_SB_MIN, whole);
+       part = scroll_bar_handle;
+       bar->dragging = make_number (cs->value);
       }
       break;
       
       }
       break;
       
@@ -8790,7 +8985,7 @@ x_create_toolkit_scroll_bar (f, bar)
   
 #endif /* !USE_MOTIF */
 
   
 #endif /* !USE_MOTIF */
 
-  /* Install an action hook that let's us detect when the user
+  /* Install an action hook that lets us detect when the user
      finishes interacting with a scroll bar.  */
   if (action_hook_id == 0)
     action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
      finishes interacting with a scroll bar.  */
   if (action_hook_id == 0)
     action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
@@ -8816,7 +9011,27 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
   Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
   float top, shown;
 
   Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
   float top, shown;
 
-  if (whole == 0)
+  BLOCK_INPUT;
+
+#ifdef USE_MOTIF
+
+  /* We use an estimate of 30 chars per line rather than the real
+     `portion' value.  This has the disadvantage that the thumb size
+     is not very representative, but it makes our life a lot easier.
+     Otherwise, we have to constantly adjust the thumb size, which
+     we can't always do quickly enough: while dragging, the size of
+     the thumb might prevent the user from dragging the thumb all the
+     way to the end.  but Motif and some versions of Xaw3d don't allow
+     updating the thumb size while dragging.  Also, even if we can update
+     its size, the update will often happen too late.
+     If you don't believe it, check out revision 1.650 of xterm.c to see
+     what hoops we were going through and the still poor behavior we got.  */
+  portion = XFASTINT (XWINDOW (bar->window)->height) * 30;
+  /* When the thumb is at the bottom, position == whole.
+     So we need to increase `whole' to make space for the thumb.  */
+  whole += portion;
+
+  if (whole <= 0)
     top = 0, shown = 1;
   else
     {
     top = 0, shown = 1;
   else
     {
@@ -8824,45 +9039,34 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
       shown = (float) portion / whole;
     }
 
       shown = (float) portion / whole;
     }
 
-  BLOCK_INPUT;
-
-#ifdef USE_MOTIF
-  {
-    int size, value;
-
-    /* Slider size.  Must be in the range [1 .. MAX - MIN] where MAX
-       is the scroll bar's maximum and MIN is the scroll bar's minimum
-       value.  */
-    size = shown * XM_SB_RANGE;
-    size = min (size, XM_SB_RANGE);
-    size = max (size, 1);
+  if (NILP (bar->dragging))
+    {
+      int size, value;
 
 
-    /* Position.  Must be in the range [MIN .. MAX - SLIDER_SIZE].  */
-    value = top * XM_SB_RANGE;
-    value = min (value, XM_SB_MAX - size);
-    value = max (value, XM_SB_MIN);
+      /* Slider size.  Must be in the range [1 .. MAX - MIN] where MAX
+         is the scroll bar's maximum and MIN is the scroll bar's minimum
+        value.  */
+      size = shown * XM_SB_RANGE;
+      size = min (size, XM_SB_RANGE);
+      size = max (size, 1);
 
 
-    if (NILP (bar->dragging))
+      /* Position.  Must be in the range [MIN .. MAX - SLIDER_SIZE].  */
+      value = top * XM_SB_RANGE;
+      value = min (value, XM_SB_MAX - size);
+      value = max (value, XM_SB_MIN);
+      
       XmScrollBarSetValues (widget, value, size, 0, 0, False);
       XmScrollBarSetValues (widget, value, size, 0, 0, False);
-    else if (last_scroll_bar_part == scroll_bar_down_arrow)
-      /* This has the negative side effect that the slider value is
-        not what it would be if we scrolled here using line-wise or
-        page-wise movement.  */
-      XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
-    else
-      {
-       /* If currently dragging, only update the slider size.
-          This reduces flicker effects.  */
-       int old_value, old_size, increment, page_increment;
-       
-       XmScrollBarGetValues (widget, &old_value, &old_size,
-                             &increment, &page_increment);
-       XmScrollBarSetValues (widget, old_value,
-                             min (size, XM_SB_RANGE - old_value),
-                             0, 0, False);
-      }
-  }
+    }
 #else /* !USE_MOTIF i.e. use Xaw */
 #else /* !USE_MOTIF i.e. use Xaw */
+
+  if (whole == 0)
+    top = 0, shown = 1;
+  else
+    {
+      top = (float) position / whole;
+      shown = (float) portion / whole;
+    }
+
   {
     float old_top, old_shown;
     Dimension height;
   {
     float old_top, old_shown;
     Dimension height;
@@ -8931,7 +9135,7 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
                                                                         
 /* Create a scroll bar and return the scroll bar vector for it.  W is
    the Emacs window on which to create the scroll bar. TOP, LEFT,
                                                                         
 /* Create a scroll bar and return the scroll bar vector for it.  W is
    the Emacs window on which to create the scroll bar. TOP, LEFT,
-   WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
+   WIDTH and HEIGHT are the pixel coordinates and dimensions of the
    scroll bar. */
 
 static struct scroll_bar *
    scroll bar. */
 
 static struct scroll_bar *
@@ -9273,7 +9477,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
        }
 
       /* Clear areas not covered by the scroll bar because it's not as
        }
 
       /* Clear areas not covered by the scroll bar because it's not as
-        wide as the area reserved for it .  This makes sure a
+        wide as the area reserved for it.  This makes sure a
         previous mode line display is cleared after C-x 2 C-x 1, for
         example.  */
       {
         previous mode line display is cleared after C-x 2 C-x 1, for
         example.  */
       {
@@ -9482,7 +9686,7 @@ x_scroll_bar_expose (bar, event)
 }
 
 /* Handle a mouse click on the scroll bar BAR.  If *EMACS_EVENT's kind
 }
 
 /* Handle a mouse click on the scroll bar BAR.  If *EMACS_EVENT's kind
-   is set to something other than no_event, it is enqueued.
+   is set to something other than NO_EVENT, it is enqueued.
 
    This may be called from a signal handler, so we have to ignore GC
    mark bits.  */
 
    This may be called from a signal handler, so we have to ignore GC
    mark bits.  */
@@ -9498,7 +9702,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
   if (! GC_WINDOWP (bar->window))
     abort ();
 
   if (! GC_WINDOWP (bar->window))
     abort ();
 
-  emacs_event->kind = scroll_bar_click;
+  emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
   emacs_event->code = event->xbutton.button - Button1;
   emacs_event->modifiers
     = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO 
   emacs_event->code = event->xbutton.button - Button1;
   emacs_event->modifiers
     = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO 
@@ -9820,11 +10024,13 @@ x_stop_queuing_selection_requests (display)
 \f
 /* The main X event-reading loop - XTread_socket.  */
 
 \f
 /* The main X event-reading loop - XTread_socket.  */
 
+#if 0
 /* Time stamp of enter window event.  This is only used by XTread_socket,
    but we have to put it out here, since static variables within functions
    sometimes don't work.  */
 
 static Time enter_timestamp;
 /* Time stamp of enter window event.  This is only used by XTread_socket,
    but we have to put it out here, since static variables within functions
    sometimes don't work.  */
 
 static Time enter_timestamp;
+#endif
 
 /* This holds the state XLookupString needs to implement dead keys
    and other tricks known as "compose processing".  _X Window System_
 
 /* This holds the state XLookupString needs to implement dead keys
    and other tricks known as "compose processing".  _X Window System_
@@ -9863,7 +10069,7 @@ static struct x_display_info *next_noop_dpyinfo;
          bcopy (&event, f->output_data.x->saved_menu_event, size);     \
          if (numchars >= 1)                                            \
            {                                                           \
          bcopy (&event, f->output_data.x->saved_menu_event, size);     \
          if (numchars >= 1)                                            \
            {                                                           \
-             bufp->kind = menu_bar_activate_event;                     \
+             bufp->kind = MENU_BAR_ACTIVATE_EVENT;                     \
              XSETFRAME (bufp->frame_or_window, f);                     \
              bufp->arg = Qnil;                                         \
              bufp++;                                                   \
              XSETFRAME (bufp->frame_or_window, f);                     \
              bufp->arg = Qnil;                                         \
              bufp++;                                                   \
@@ -9887,7 +10093,7 @@ static struct x_display_info *next_noop_dpyinfo;
 
    EXPECTED is nonzero if the caller knows input is available.  */
 
 
    EXPECTED is nonzero if the caller knows input is available.  */
 
-int
+static int
 XTread_socket (sd, bufp, numchars, expected)
      register int sd;
      /* register */ struct input_event *bufp;
 XTread_socket (sd, bufp, numchars, expected)
      register int sd;
      /* register */ struct input_event *bufp;
@@ -9919,18 +10125,6 @@ XTread_socket (sd, bufp, numchars, expected)
 
   ++handling_signal;
   
 
   ++handling_signal;
   
-  /* The input should be decoded if it is from XIM.  Currently the
-     locale of XIM is the same as that of the system.  So, we can use
-     Vlocale_coding_system which is initialized properly at Emacs
-     startup time.  */
-  setup_coding_system (Vlocale_coding_system, &coding);
-  coding.src_multibyte = 0;
-  coding.dst_multibyte = 1;
-  /* The input is converted to events, thus we can't handle
-     composition.  Anyway, there's no XIM that gives us composition
-     information.  */
-  coding.composing = COMPOSITION_DISABLED;
-
   /* Find the display we are supposed to read input for.
      It's the one communicating on descriptor SD.  */
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
   /* Find the display we are supposed to read input for.
      It's the one communicating on descriptor SD.  */
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
@@ -9969,6 +10163,12 @@ XTread_socket (sd, bufp, numchars, expected)
          x_io_error_quitter (dpyinfo->display);
        }
 
          x_io_error_quitter (dpyinfo->display);
        }
 
+#ifdef HAVE_X_SM
+      BLOCK_INPUT;
+      count += x_session_check_input (bufp, &numchars);
+      UNBLOCK_INPUT;
+#endif
+
       while (XPending (dpyinfo->display))
        {
          XNextEvent (dpyinfo->display, &event);
       while (XPending (dpyinfo->display))
        {
          XNextEvent (dpyinfo->display, &event);
@@ -10051,11 +10251,17 @@ XTread_socket (sd, bufp, numchars, expected)
                           the session manager, who's looking for such a
                           PropertyNotify.  Can restart processing when
                           a keyboard or mouse event arrives.  */
                           the session manager, who's looking for such a
                           PropertyNotify.  Can restart processing when
                           a keyboard or mouse event arrives.  */
-                       if (numchars > 0)
+                        /* If we have a session manager, don't set this.
+                           KDE will then start two Emacsen, one for the
+                           session manager and one for this. */
+                       if (numchars > 0
+#ifdef HAVE_X_SM
+                            && ! x_session_have_connection ()
+#endif
+                            )
                          {
                            f = x_top_window_to_frame (dpyinfo,
                                                       event.xclient.window);
                          {
                            f = x_top_window_to_frame (dpyinfo,
                                                       event.xclient.window);
-
                            /* This is just so we only give real data once
                               for a single Emacs process.  */
                            if (f == SELECTED_FRAME ())
                            /* This is just so we only give real data once
                               for a single Emacs process.  */
                            if (f == SELECTED_FRAME ())
@@ -10080,7 +10286,7 @@ XTread_socket (sd, bufp, numchars, expected)
                            if (numchars == 0)
                              abort ();
 
                            if (numchars == 0)
                              abort ();
 
-                           bufp->kind = delete_window_event;
+                           bufp->kind = DELETE_WINDOW_EVENT;
                            XSETFRAME (bufp->frame_or_window, f);
                            bufp->arg = Qnil;
                            bufp++;
                            XSETFRAME (bufp->frame_or_window, f);
                            bufp->arg = Qnil;
                            bufp++;
@@ -10170,7 +10376,7 @@ XTread_socket (sd, bufp, numchars, expected)
                if (numchars == 0)
                  abort ();
 
                if (numchars == 0)
                  abort ();
 
-               bufp->kind = selection_clear_event;
+               bufp->kind = SELECTION_CLEAR_EVENT;
                SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
                SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
                SELECTION_EVENT_TIME (bufp) = eventp->time;
                SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
                SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
                SELECTION_EVENT_TIME (bufp) = eventp->time;
@@ -10199,7 +10405,7 @@ XTread_socket (sd, bufp, numchars, expected)
                  if (numchars == 0)
                    abort ();
 
                  if (numchars == 0)
                    abort ();
 
-                 bufp->kind = selection_request_event;
+                 bufp->kind = SELECTION_REQUEST_EVENT;
                  SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
                  SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
                  SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
                  SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
                  SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
                  SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
@@ -10243,6 +10449,8 @@ XTread_socket (sd, bufp, numchars, expected)
              f = x_window_to_frame (dpyinfo, event.xexpose.window);
              if (f)
                {
              f = x_window_to_frame (dpyinfo, event.xexpose.window);
              if (f)
                {
+                  x_check_fullscreen (f);
+
                  if (f->async_visible == 0)
                    {
                      f->async_visible = 1;
                  if (f->async_visible == 0)
                    {
                      f->async_visible = 1;
@@ -10337,7 +10545,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      f->async_iconified = 1;
 
                    {
                      f->async_iconified = 1;
 
-                     bufp->kind = iconify_event;
+                     bufp->kind = ICONIFY_EVENT;
                      XSETFRAME (bufp->frame_or_window, f);
                      bufp->arg = Qnil;
                      bufp++;
                      XSETFRAME (bufp->frame_or_window, f);
                      bufp->arg = Qnil;
                      bufp++;
@@ -10369,7 +10577,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                  if (f->iconified)
                    {
 
                  if (f->iconified)
                    {
-                     bufp->kind = deiconify_event;
+                     bufp->kind = DEICONIFY_EVENT;
                      XSETFRAME (bufp->frame_or_window, f);
                      bufp->arg = Qnil;
                      bufp++;
                      XSETFRAME (bufp->frame_or_window, f);
                      bufp->arg = Qnil;
                      bufp++;
@@ -10386,8 +10594,19 @@ XTread_socket (sd, bufp, numchars, expected)
              goto OTHER;
 
            case KeyPress:
              goto OTHER;
 
            case KeyPress:
+
+             /* Dispatch KeyPress events when in menu.  */
+             if (popup_activated_flag)
+               goto OTHER;
+
              f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
              f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
+             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+               {
+                 dpyinfo->mouse_face_hidden = 1;
+                 clear_mouse_face (dpyinfo);
+               }
+
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
              if (f == 0)
                {
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
              if (f == 0)
                {
@@ -10421,6 +10640,7 @@ XTread_socket (sd, bufp, numchars, expected)
                  unsigned char *copy_bufptr = copy_buffer;
                  int copy_bufsiz = sizeof (copy_buffer);
                  int modifiers;
                  unsigned char *copy_bufptr = copy_buffer;
                  int copy_bufsiz = sizeof (copy_buffer);
                  int modifiers;
+                 Lisp_Object coding_system = Qlatin_1;
 
                  event.xkey.state
                    |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
 
                  event.xkey.state
                    |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
@@ -10450,6 +10670,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      Status status_return;
 
                    {
                      Status status_return;
 
+                     coding_system = Vlocale_coding_system;
                      nbytes = XmbLookupString (FRAME_XIC (f),
                                                &event.xkey, copy_bufptr,
                                                copy_bufsiz, &keysym,
                      nbytes = XmbLookupString (FRAME_XIC (f),
                                                &event.xkey, copy_bufptr,
                                                copy_bufsiz, &keysym,
@@ -10463,6 +10684,27 @@ XTread_socket (sd, bufp, numchars, expected)
                                                    copy_bufsiz, &keysym,
                                                    &status_return);
                        }
                                                    copy_bufsiz, &keysym,
                                                    &status_return);
                        }
+/* Xutf8LookupString is a new but already deprecated interface.  -stef  */
+#if 0 && defined X_HAVE_UTF8_STRING
+                     else if (status_return == XLookupKeySym)
+                       {  /* Try again but with utf-8.  */
+                         coding_system = Qutf_8;
+                         nbytes = Xutf8LookupString (FRAME_XIC (f),
+                                                     &event.xkey, copy_bufptr,
+                                                     copy_bufsiz, &keysym,
+                                                     &status_return);
+                         if (status_return == XBufferOverflow)
+                           {
+                             copy_bufsiz = nbytes + 1;
+                             copy_bufptr = (char *) alloca (copy_bufsiz);
+                             nbytes = Xutf8LookupString (FRAME_XIC (f),
+                                                         &event.xkey,
+                                                         copy_bufptr,
+                                                         copy_bufsiz, &keysym,
+                                                         &status_return);
+                           }
+                       }
+#endif
 
                      if (status_return == XLookupNone)
                        break;
 
                      if (status_return == XLookupNone)
                        break;
@@ -10558,12 +10800,20 @@ XTread_socket (sd, bufp, numchars, expected)
                                || ((unsigned)(orig_keysym) == XK_Num_Lock)
 #endif
 #endif /* not HAVE_X11R5 */
                                || ((unsigned)(orig_keysym) == XK_Num_Lock)
 #endif
 #endif /* not HAVE_X11R5 */
+                               /* The symbols from XK_ISO_Lock to
+                                  XK_ISO_Last_Group_Lock doesn't have real
+                                  modifiers but should be treated similarly
+                                  to Mode_switch by Emacs. */
+#if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
+                               || ((unsigned)(orig_keysym) >=  XK_ISO_Lock
+                                   && (unsigned)(orig_keysym) <= XK_ISO_Last_Group_Lock)
+#endif
                                ))
                        {
                          if (temp_index == sizeof temp_buffer / sizeof (short))
                            temp_index = 0;
                          temp_buffer[temp_index++] = keysym;
                                ))
                        {
                          if (temp_index == sizeof temp_buffer / sizeof (short))
                            temp_index = 0;
                          temp_buffer[temp_index++] = keysym;
-                         bufp->kind = non_ascii_keystroke;
+                         bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
                          bufp->code = keysym;
                          XSETFRAME (bufp->frame_or_window, f);
                          bufp->arg = Qnil;
                          bufp->code = keysym;
                          XSETFRAME (bufp->frame_or_window, f);
                          bufp->arg = Qnil;
@@ -10581,6 +10831,17 @@ XTread_socket (sd, bufp, numchars, expected)
                          register int c;
                          int nchars, len;
 
                          register int c;
                          int nchars, len;
 
+                         /* The input should be decoded with `coding_system'
+                            which depends on which X*LookupString function
+                            we used just above and the locale.  */
+                         setup_coding_system (coding_system, &coding);
+                         coding.src_multibyte = 0;
+                         coding.dst_multibyte = 1;
+                         /* The input is converted to events, thus we can't
+                            handle composition.  Anyway, there's no XIM that
+                            gives us composition information.  */
+                         coding.composing = COMPOSITION_DISABLED;
+
                          for (i = 0; i < nbytes; i++)
                            {
                              if (temp_index == (sizeof temp_buffer
                          for (i = 0; i < nbytes; i++)
                            {
                              if (temp_index == (sizeof temp_buffer
@@ -10589,31 +10850,25 @@ XTread_socket (sd, bufp, numchars, expected)
                              temp_buffer[temp_index++] = copy_bufptr[i];
                            }
 
                              temp_buffer[temp_index++] = copy_bufptr[i];
                            }
 
-                         if (/* If the event is not from XIM, */
-                             event.xkey.keycode != 0
-                             /* or the current locale doesn't request
-                                decoding of the intup data, ... */
-                             || coding.type == coding_type_raw_text
-                             || coding.type == coding_type_no_conversion)
-                           {
-                             /* ... we can use the input data as is.  */
-                             nchars = nbytes;
-                           }
-                         else
-                           { 
-                             /* We have to decode the input data.  */
-                             int require;
-                             unsigned char *p;
-
-                             require = decoding_buffer_size (&coding, nbytes);
-                             p = (unsigned char *) alloca (require);
-                             coding.mode |= CODING_MODE_LAST_BLOCK;
-                             decode_coding (&coding, copy_bufptr, p,
-                                            nbytes, require);
-                             nbytes = coding.produced;
-                             nchars = coding.produced_char;
-                             copy_bufptr = p;
-                           }
+                         {
+                           /* Decode the input data.  */
+                           int require;
+                           unsigned char *p;
+
+                           require = decoding_buffer_size (&coding, nbytes);
+                           p = (unsigned char *) alloca (require);
+                           coding.mode |= CODING_MODE_LAST_BLOCK;
+                           /* We explicitely disable composition
+                              handling because key data should
+                              not contain any composition
+                              sequence.  */
+                           coding.composing = COMPOSITION_DISABLED;
+                           decode_coding (&coding, copy_bufptr, p,
+                                          nbytes, require);
+                           nbytes = coding.produced;
+                           nchars = coding.produced_char;
+                           copy_bufptr = p;
+                         }
 
                          /* Convert the input data to a sequence of
                             character events.  */
 
                          /* Convert the input data to a sequence of
                             character events.  */
@@ -10626,8 +10881,8 @@ XTread_socket (sd, bufp, numchars, expected)
                                                            nbytes - i, len);
                              
                              bufp->kind = (SINGLE_BYTE_CHAR_P (c)
                                                            nbytes - i, len);
                              
                              bufp->kind = (SINGLE_BYTE_CHAR_P (c)
-                                           ? ascii_keystroke
-                                           : multibyte_char_keystroke);
+                                           ? ASCII_KEYSTROKE_EVENT
+                                           : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
                              bufp->code = c;
                              XSETFRAME (bufp->frame_or_window, f);
                              bufp->arg = Qnil;
                              bufp->code = c;
                              XSETFRAME (bufp->frame_or_window, f);
                              bufp->arg = Qnil;
@@ -10669,15 +10924,16 @@ XTread_socket (sd, bufp, numchars, expected)
              goto OTHER;
 #endif
 
              goto OTHER;
 #endif
 
-             /* Here's a possible interpretation of the whole
-                FocusIn-EnterNotify FocusOut-LeaveNotify mess.  If
-                you get a FocusIn event, you have to get a FocusOut
-                event before you relinquish the focus.  If you
-                haven't received a FocusIn event, then a mere
-                LeaveNotify is enough to free you.  */
-
            case EnterNotify:
              {
            case EnterNotify:
              {
+                int n;
+
+                n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+                if (n > 0)
+                {
+                  bufp += n, count += n, numchars -= n;
+                }
+              
                f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
 #if 0
                f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
 #if 0
@@ -10704,34 +10960,29 @@ XTread_socket (sd, bufp, numchars, expected)
              }
 
            case FocusIn:
              }
 
            case FocusIn:
-             f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
-             if (event.xfocus.detail != NotifyPointer)
-               dpyinfo->x_focus_event_frame = f;
-             if (f)
-               {
-                 x_new_focus_frame (dpyinfo, f);
+              {
+                int n;
 
 
-                 /* Don't stop displaying the initial startup message
-                    for a switch-frame event we don't need.  */
-                 if (GC_NILP (Vterminal_frame)
-                     && GC_CONSP (Vframe_list)
-                     && !GC_NILP (XCDR (Vframe_list)))
-                   {
-                     bufp->kind = FOCUS_IN_EVENT;
-                     XSETFRAME (bufp->frame_or_window, f);
-                     bufp->arg = Qnil;
-                     ++bufp, ++count, --numchars;
-                   }
-               }
-
-#ifdef HAVE_X_I18N
-             if (f && FRAME_XIC (f))
-               XSetICFocus (FRAME_XIC (f));
-#endif
+                n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+                if (n > 0)
+                  {
+                    bufp += n, count += n, numchars -= n;
+                  }
+              }
 
              goto OTHER;
 
            case LeaveNotify:
 
              goto OTHER;
 
            case LeaveNotify:
+              {
+                int n;
+
+                n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+                if (n > 0)
+                {
+                  bufp += n, count += n, numchars -= n;
+                }
+              }
+
              f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
              if (f)
                {
              f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
              if (f)
                {
@@ -10759,32 +11010,19 @@ XTread_socket (sd, bufp, numchars, expected)
                      bufp += n, count += n, numchars -= n;
                    }
 
                      bufp += n, count += n, numchars -= n;
                    }
 
-#if 0
-                 if (event.xcrossing.focus)
-                   x_mouse_leave (dpyinfo);
-                 else
-                   {
-                     if (f == dpyinfo->x_focus_event_frame)
-                       dpyinfo->x_focus_event_frame = 0;
-                     if (f == dpyinfo->x_focus_frame)
-                       x_new_focus_frame (dpyinfo, 0);
-                   }
-#endif
                }
              goto OTHER;
 
            case FocusOut:
                }
              goto OTHER;
 
            case FocusOut:
-             f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
-             if (event.xfocus.detail != NotifyPointer
-                 && f == dpyinfo->x_focus_event_frame)
-               dpyinfo->x_focus_event_frame = 0;
-             if (f && f == dpyinfo->x_focus_frame)
-               x_new_focus_frame (dpyinfo, 0);
+              {
+                int n;
 
 
-#ifdef HAVE_X_I18N
-             if (f && FRAME_XIC (f))
-               XUnsetICFocus (FRAME_XIC (f));
-#endif
+                n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+                if (n > 0)
+                {
+                  bufp += n, count += n, numchars -= n;
+                }
+              }
 
              goto OTHER;
 
 
              goto OTHER;
 
@@ -10800,8 +11038,43 @@ XTread_socket (sd, bufp, numchars, expected)
                else
                  f = x_window_to_frame (dpyinfo, event.xmotion.window);
 
                else
                  f = x_window_to_frame (dpyinfo, event.xmotion.window);
 
+               if (dpyinfo->mouse_face_hidden)
+                 {
+                   dpyinfo->mouse_face_hidden = 0;
+                   clear_mouse_face (dpyinfo);
+                 }
+
                if (f)
                if (f)
-                 note_mouse_movement (f, &event.xmotion);
+                 {
+
+                   /* Generate SELECT_WINDOW_EVENTs when needed.  */
+                   if (mouse_autoselect_window)
+                     {
+                       Lisp_Object window;
+                       int area;
+
+                       window = window_from_coordinates (f,
+                                                         event.xmotion.x, event.xmotion.y,
+                                                         &area, 0);
+
+                       /* Window will be selected only when it is not selected now and
+                          last mouse movement event was not in it.  Minibuffer window
+                          will be selected iff it is active.  */
+                       if (WINDOWP(window)
+                           && !EQ (window, last_window)
+                           && !EQ (window, selected_window)
+                           && numchars > 0)
+                         {
+                           bufp->kind = SELECT_WINDOW_EVENT;
+                           bufp->frame_or_window = window;
+                           bufp->arg = Qnil;
+                           ++bufp, ++count, --numchars;
+                         }
+
+                       last_window=window;
+                     }
+                   note_mouse_movement (f, &event.xmotion);
+                 }
                else
                  {
 #ifndef USE_TOOLKIT_SCROLL_BARS
                else
                  {
 #ifndef USE_TOOLKIT_SCROLL_BARS
@@ -10845,8 +11118,17 @@ XTread_socket (sd, bufp, numchars, expected)
              if (f)
                {
 #ifndef USE_X_TOOLKIT
              if (f)
                {
 #ifndef USE_X_TOOLKIT
+                  /* If there is a pending resize for fullscreen, don't
+                     do this one, the right one will come later.
+                    The toolkit version doesn't seem to need this, but we
+                    need to reset it below.  */
+                  int dont_resize =
+                    ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
+                     && FRAME_NEW_WIDTH (f) != 0);
                  int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
                  int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
                  int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
                  int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
+                  if (dont_resize)
+                    goto OTHER;
                  
                  /* In the toolkit version, change_frame_size
                     is called by the code that handles resizing
                  
                  /* In the toolkit version, change_frame_size
                     is called by the code that handles resizing
@@ -10874,6 +11156,10 @@ XTread_socket (sd, bufp, numchars, expected)
                  x_real_positions (f, &f->output_data.x->left_pos,
                                    &f->output_data.x->top_pos);
 
                  x_real_positions (f, &f->output_data.x->left_pos,
                                    &f->output_data.x->top_pos);
 
+                  x_check_fullscreen_move(f);
+                  if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
+                    f->output_data.x->want_fullscreen &=
+                      ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
 #ifdef HAVE_X_I18N
                  if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
                    xic_set_statusarea (f);
 #ifdef HAVE_X_I18N
                  if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
                    xic_set_statusarea (f);
@@ -10907,7 +11193,7 @@ XTread_socket (sd, bufp, numchars, expected)
                struct input_event emacs_event;
                int tool_bar_p = 0;
                
                struct input_event emacs_event;
                int tool_bar_p = 0;
                
-               emacs_event.kind = no_event;
+               emacs_event.kind = NO_EVENT;
                bzero (&compose_status, sizeof (compose_status));
 
                if (dpyinfo->grabbed
                bzero (&compose_status, sizeof (compose_status));
 
                if (dpyinfo->grabbed
@@ -10973,7 +11259,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    dpyinfo->grabbed &= ~(1 << event.xbutton.button);
                  }
 
                    dpyinfo->grabbed &= ~(1 << event.xbutton.button);
                  }
 
-               if (numchars >= 1 && emacs_event.kind != no_event)
+               if (numchars >= 1 && emacs_event.kind != NO_EVENT)
                  {
                    bcopy (&emacs_event, bufp, sizeof (struct input_event));
                    bufp++;
                  {
                    bcopy (&emacs_event, bufp, sizeof (struct input_event));
                    bufp++;
@@ -11118,13 +11404,36 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
      enum glyph_row_area area;
      int x0, y0, x1, y1;
 {
      enum glyph_row_area area;
      int x0, y0, x1, y1;
 {
-  if (area == TEXT_AREA
-      && w->phys_cursor_on_p
-      && y0 <= w->phys_cursor.y
-      && y1 >= w->phys_cursor.y + w->phys_cursor_height
-      && x0 <= w->phys_cursor.x
-      && (x1 < 0 || x1 > w->phys_cursor.x))
-    w->phys_cursor_on_p = 0;
+  if (area == TEXT_AREA && w->phys_cursor_on_p)
+    {
+      int cx0 = w->phys_cursor.x;
+      int cx1 = cx0 + w->phys_cursor_width;
+      int cy0 = w->phys_cursor.y;
+      int cy1 = cy0 + w->phys_cursor_height;
+
+      if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))
+       {
+         /* The cursor image will be completely removed from the
+            screen if the output area intersects the cursor area in
+            y-direction.  When we draw in [y0 y1[, and some part of
+            the cursor is at y < y0, that part must have been drawn
+            before.  When scrolling, the cursor is erased before
+            actually scrolling, so we don't come here.  When not
+            scrolling, the rows above the old cursor row must have
+            changed, and in this case these rows must have written
+            over the cursor image.
+
+            Likewise if part of the cursor is below y1, with the
+            exception of the cursor being in the first blank row at
+            the buffer and window end because update_text_area
+            doesn't draw that row.  (Except when it does, but
+            that's handled in update_text_area.)  */
+         
+         if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))
+             && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)
+           w->phys_cursor_on_p = 0;
+       }
+    }
 }
 
 
 }
 
 
@@ -11204,6 +11513,7 @@ x_draw_hollow_cursor (w, row)
   if (cursor_glyph->type == STRETCH_GLYPH
       && !x_stretch_cursor_p)
     wd = min (CANON_X_UNIT (f), wd);
   if (cursor_glyph->type == STRETCH_GLYPH
       && !x_stretch_cursor_p)
     wd = min (CANON_X_UNIT (f), wd);
+  w->phys_cursor_width = wd;
   
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
   
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
@@ -11230,10 +11540,11 @@ x_draw_hollow_cursor (w, row)
    --gerd.  */
 
 static void
    --gerd.  */
 
 static void
-x_draw_bar_cursor (w, row, width)
+x_draw_bar_cursor (w, row, width, kind)
      struct window *w;
      struct glyph_row *row;
      int width;
      struct window *w;
      struct glyph_row *row;
      int width;
+     enum text_cursor_kinds kind;
 {
   struct frame *f = XFRAME (w->frame);
   struct glyph *cursor_glyph;
 {
   struct frame *f = XFRAME (w->frame);
   struct glyph *cursor_glyph;
@@ -11286,11 +11597,22 @@ x_draw_bar_cursor (w, row, width)
        width = f->output_data.x->cursor_width;
       width = min (cursor_glyph->pixel_width, width);
   
        width = f->output_data.x->cursor_width;
       width = min (cursor_glyph->pixel_width, width);
   
+      w->phys_cursor_width = width;
       x_clip_to_row (w, row, gc, 0);
       x_clip_to_row (w, row, gc, 0);
-      XFillRectangle (dpy, window, gc,
-                     WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
-                     WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-                     width, row->height);
+      
+      if (kind == BAR_CURSOR)
+         XFillRectangle (dpy, window, gc,
+                         WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+                         WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+                         width, row->height);
+      else
+         XFillRectangle (dpy, window, gc,
+                         WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+                         WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+                                                  row->height - width),
+                         cursor_glyph->pixel_width,
+                         width);
+
       XSetClipMask (dpy, gc, None);
     }
 }
       XSetClipMask (dpy, gc, None);
     }
 }
@@ -11324,16 +11646,20 @@ x_draw_phys_cursor_glyph (w, row, hl)
   if (w->phys_cursor.hpos < row->used[TEXT_AREA])
     {
       int on_p = w->phys_cursor_on_p;
   if (w->phys_cursor.hpos < row->used[TEXT_AREA])
     {
       int on_p = w->phys_cursor_on_p;
+      int x1;
       
       
-      x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
-                    w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
-                    hl, 0);
+      x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
+                         w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
+                         hl, 0);
       w->phys_cursor_on_p = on_p;
 
       w->phys_cursor_on_p = on_p;
 
+      if (hl == DRAW_CURSOR)
+       w->phys_cursor_width = x1 - w->phys_cursor.x;
+
       /* When we erase the cursor, and ROW is overlapped by other
         rows, make sure that these overlapping parts of other rows
         are redrawn.  */
       /* When we erase the cursor, and ROW is overlapped by other
         rows, make sure that these overlapping parts of other rows
         are redrawn.  */
-      if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
+      else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
        {
          if (row > w->current_matrix->rows
              && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
        {
          if (row > w->current_matrix->rows
              && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
@@ -11379,6 +11705,12 @@ x_erase_phys_cursor (w)
   if (!cursor_row->enabled_p)
     goto mark_cursor_off;
   
   if (!cursor_row->enabled_p)
     goto mark_cursor_off;
   
+  /* If row is completely invisible, don't attempt to delete a cursor which
+     isn't there.  This can happen if cursor is at top of a window, and
+     we switch to a buffer with a header line in that window.  */
+  if (cursor_row->visible_height <= 0)
+    goto mark_cursor_off;
+  
   /* This can happen when the new row is shorter than the old one.
      In this case, either x_draw_glyphs or clear_end_of_line
      should have cleared the cursor.  Note that we wouldn't be
   /* This can happen when the new row is shorter than the old one.
      In this case, either x_draw_glyphs or clear_end_of_line
      should have cleared the cursor.  Note that we wouldn't be
@@ -11478,10 +11810,10 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
   struct frame *f = XFRAME (w->frame);
   int new_cursor_type;
   int new_cursor_width;
   struct frame *f = XFRAME (w->frame);
   int new_cursor_type;
   int new_cursor_width;
+  int cursor_off_state = 0;
   struct glyph_matrix *current_glyphs;
   struct glyph_row *glyph_row;
   struct glyph *glyph;
   struct glyph_matrix *current_glyphs;
   struct glyph_row *glyph_row;
   struct glyph *glyph;
-  int cursor_non_selected;
 
   /* This is pointless on invisible frames, and dangerous on garbaged
      windows and frames; in the latter case, the frame or window may
 
   /* This is pointless on invisible frames, and dangerous on garbaged
      windows and frames; in the latter case, the frame or window may
@@ -11517,47 +11849,65 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
      the cursor type given by the frame parameter.  If explicitly
      marked off, draw no cursor.  In all other cases, we want a hollow
      box cursor.  */
      the cursor type given by the frame parameter.  If explicitly
      marked off, draw no cursor.  In all other cases, we want a hollow
      box cursor.  */
-  cursor_non_selected 
-    = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
-                                 w->buffer));
   new_cursor_width = -1;
   new_cursor_width = -1;
+  new_cursor_type = -2;
+
+  /* Echo area */
   if (cursor_in_echo_area
       && FRAME_HAS_MINIBUF_P (f)
       && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
     {
       if (w == XWINDOW (echo_area_window))
        new_cursor_type = FRAME_DESIRED_CURSOR (f);
   if (cursor_in_echo_area
       && FRAME_HAS_MINIBUF_P (f)
       && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
     {
       if (w == XWINDOW (echo_area_window))
        new_cursor_type = FRAME_DESIRED_CURSOR (f);
-      else if (cursor_non_selected)
-       new_cursor_type = HOLLOW_BOX_CURSOR;
+      else if (NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
+                                         w->buffer)))
+       new_cursor_type = NO_CURSOR;
       else
       else
+       cursor_off_state = 1;
+    }
+
+  /* Nonselected window or nonselected frame.  */
+  else if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
+          || w != XWINDOW (f->selected_window))
+    {
+      if ((MINI_WINDOW_P (w) && minibuf_level == 0)
+         || NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
+                                       w->buffer))
+         || NILP (XBUFFER (w->buffer)->cursor_type))
        new_cursor_type = NO_CURSOR;
        new_cursor_type = NO_CURSOR;
+      else
+       cursor_off_state = 1;
     }
     }
-  else
+
+  /* If new_cursor_type isn't decided yet, decide it now.  */
+  if (new_cursor_type == -2)
     {
     {
-      if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
-         || w != XWINDOW (f->selected_window))
+      struct buffer *b = XBUFFER (w->buffer);
+
+      if (EQ (b->cursor_type, Qt))
        {
        {
-         if ((MINI_WINDOW_P (w) && minibuf_level == 0)
-             || !cursor_non_selected
-             || NILP (XBUFFER (w->buffer)->cursor_type))
-           new_cursor_type = NO_CURSOR;
-         else
-           new_cursor_type = HOLLOW_BOX_CURSOR;
+         new_cursor_type = FRAME_DESIRED_CURSOR (f);
+         new_cursor_width = FRAME_CURSOR_WIDTH (f);
        }
        }
-      else if (w->cursor_off_p)
-       new_cursor_type = NO_CURSOR;
       else
       else
-       {
-         struct buffer *b = XBUFFER (w->buffer);
+       new_cursor_type = x_specified_cursor_type (b->cursor_type, 
+                                                  &new_cursor_width);
+    }
 
 
-         if (EQ (b->cursor_type, Qt))
-           new_cursor_type = FRAME_DESIRED_CURSOR (f);
-         else
-           new_cursor_type = x_specified_cursor_type (b->cursor_type, 
-                                                      &new_cursor_width);
-       }
+  /* Dim out or hollow out the cursor,
+     if it has blinked off or for nonselected windows.  */
+  if (w->cursor_off_p || cursor_off_state)
+    {
+      if (new_cursor_type == FILLED_BOX_CURSOR)
+       new_cursor_type = HOLLOW_BOX_CURSOR;
+      else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
+       new_cursor_width = 1;
+      else
+       new_cursor_type = NO_CURSOR;
     }
 
     }
 
+  /* Now new_cursor_type is correct.  */
+
   /* If cursor is currently being shown and we don't want it to be or
      it is in the wrong place, or the cursor type is not what we want,
      erase it.  */
   /* If cursor is currently being shown and we don't want it to be or
      it is in the wrong place, or the cursor type is not what we want,
      erase it.  */
@@ -11565,12 +11915,17 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       && (!on
          || w->phys_cursor.x != x
          || w->phys_cursor.y != y
       && (!on
          || w->phys_cursor.x != x
          || w->phys_cursor.y != y
-         || new_cursor_type != w->phys_cursor_type))
+         || new_cursor_type != w->phys_cursor_type
+         || (new_cursor_type == BAR_CURSOR
+             && new_cursor_width != w->phys_cursor_width)))
     x_erase_phys_cursor (w);
 
     x_erase_phys_cursor (w);
 
-  /* If the cursor is now invisible and we want it to be visible,
-     display it.  */
-  if (on && !w->phys_cursor_on_p)
+  /* Don't check phys_cursor_on_p here because that flag is only set
+     to zero in some cases where we know that the cursor has been
+     completely erased, to avoid the extra work of erasing the cursor
+     twice.  In other words, phys_cursor_on_p can be 1 and the cursor
+     still not be visible, or it has only been partly erased.  */
+  if (on)
     {
       w->phys_cursor_ascent = glyph_row->ascent;
       w->phys_cursor_height = glyph_row->height;
     {
       w->phys_cursor_ascent = glyph_row->ascent;
       w->phys_cursor_height = glyph_row->height;
@@ -11595,10 +11950,15 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
          break;
 
        case BAR_CURSOR:
          break;
 
        case BAR_CURSOR:
-         x_draw_bar_cursor (w, glyph_row, new_cursor_width);
+         x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
+         break;
+
+       case HBAR_CURSOR:
+         x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
          break;
 
        case NO_CURSOR:
          break;
 
        case NO_CURSOR:
+         w->phys_cursor_width = 0;
          break;
 
        default:
          break;
 
        default:
@@ -11790,7 +12150,7 @@ x_error_catcher (display, error)
      XErrorEvent *error;
 {
   XGetErrorText (display, error->error_code,
      XErrorEvent *error;
 {
   XGetErrorText (display, error->error_code,
-                XSTRING (x_error_message_string)->data,
+                SDATA (x_error_message_string),
                 X_ERROR_MESSAGE_SIZE);
 }
 
                 X_ERROR_MESSAGE_SIZE);
 }
 
@@ -11814,7 +12174,7 @@ int
 x_catch_errors (dpy)
      Display *dpy;
 {
 x_catch_errors (dpy)
      Display *dpy;
 {
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
 
   /* Make sure any errors from previous requests have been dealt with.  */
   XSync (dpy, False);
 
   /* Make sure any errors from previous requests have been dealt with.  */
   XSync (dpy, False);
@@ -11822,7 +12182,7 @@ x_catch_errors (dpy)
   record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
 
   x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
   record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
 
   x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
-  XSTRING (x_error_message_string)->data[0] = 0;
+  SSET (x_error_message_string, 0, 0);
 
   return count;
 }
 
   return count;
 }
@@ -11849,8 +12209,8 @@ x_check_errors (dpy, format)
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
-  if (XSTRING (x_error_message_string)->data[0])
-    error (format, XSTRING (x_error_message_string)->data);
+  if (SREF (x_error_message_string, 0))
+    error (format, SDATA (x_error_message_string));
 }
 
 /* Nonzero if we had any X protocol errors
 }
 
 /* Nonzero if we had any X protocol errors
@@ -11863,7 +12223,7 @@ x_had_errors_p (dpy)
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
-  return XSTRING (x_error_message_string)->data[0] != 0;
+  return SREF (x_error_message_string, 0) != 0;
 }
 
 /* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
 }
 
 /* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
@@ -11872,7 +12232,7 @@ void
 x_clear_errors (dpy)
      Display *dpy;
 {
 x_clear_errors (dpy)
      Display *dpy;
 {
-  XSTRING (x_error_message_string)->data[0] = 0;
+  SSET (x_error_message_string, 0, 0);
 }
 
 /* Stop catching X protocol errors and let them make Emacs die.
 }
 
 /* Stop catching X protocol errors and let them make Emacs die.
@@ -12172,7 +12532,7 @@ x_new_fontset (f, fontsetname)
        to do.  */
     return fontset_name (fontset);
 
        to do.  */
     return fontset_name (fontset);
 
-  result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
+  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
@@ -12184,7 +12544,7 @@ x_new_fontset (f, fontsetname)
 #ifdef HAVE_X_I18N
   if (FRAME_XIC (f)
       && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
 #ifdef HAVE_X_I18N
   if (FRAME_XIC (f)
       && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
-    xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
+    xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
 #endif
   
   return build_string (fontsetname);
 #endif
   
   return build_string (fontsetname);
@@ -12643,6 +13003,114 @@ x_set_offset (f, xoff, yoff, change_gravity)
   UNBLOCK_INPUT;
 }
 
   UNBLOCK_INPUT;
 }
 
+/* Check if we need to resize the frame due to a fullscreen request.
+   If so needed, resize the frame. */
+static void
+x_check_fullscreen (f)
+     struct frame *f;
+{
+  if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
+    {
+      int width, height, ign;
+                      
+      x_real_positions (f, &f->output_data.x->left_pos,
+                        &f->output_data.x->top_pos);
+
+      x_fullscreen_adjust (f, &width, &height, &ign, &ign);
+                  
+      /* We do not need to move the window, it shall be taken care of
+         when setting WM manager hints.
+         If the frame is visible already, the position is checked by
+         x_check_fullscreen_move. */
+      if (f->width != width || f->height != height)
+        {
+          change_frame_size (f, height, width, 0, 1, 0);
+          SET_FRAME_GARBAGED (f);
+          cancel_mouse_face (f);
+
+          /* Wait for the change of frame size to occur */
+          f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
+          
+        }
+    }
+}
+
+/* If frame parameters are set after the frame is mapped, we need to move
+   the window.  This is done in xfns.c.
+   Some window managers moves the window to the right position, some
+   moves the outer window manager window to the specified position.
+   Here we check that we are in the right spot.  If not, make a second
+   move, assuming we are dealing with the second kind of window manager. */
+static void
+x_check_fullscreen_move (f)
+     struct frame *f;
+{
+  if (f->output_data.x->want_fullscreen & FULLSCREEN_MOVE_WAIT)
+  {
+    int expect_top = f->output_data.x->top_pos;
+    int expect_left = f->output_data.x->left_pos;
+
+    if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
+      expect_top = 0;
+    if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
+      expect_left = 0;
+    
+    if (expect_top != f->output_data.x->top_pos
+        || expect_left != f->output_data.x->left_pos)
+      x_set_offset (f, expect_left, expect_top, 1);
+
+    /* Just do this once */
+    f->output_data.x->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
+  }
+}
+
+
+/* Calculate fullscreen size.  Return in *TOP_POS and *LEFT_POS the
+   wanted positions of the WM window (not emacs window).
+   Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
+   window (FRAME_X_WINDOW).
+ */
+void
+x_fullscreen_adjust (f, width, height, top_pos, left_pos)
+     struct frame *f;
+     int *width;
+     int *height;
+     int *top_pos;
+     int *left_pos;
+{
+  int newwidth = f->width, newheight = f->height;
+
+  *top_pos = f->output_data.x->top_pos;
+  *left_pos = f->output_data.x->left_pos;
+  
+  if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
+    {
+      int ph;
+      
+      ph = FRAME_X_DISPLAY_INFO (f)->height;
+      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+      ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
+        - f->output_data.x->y_pixels_diff;
+      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+      *top_pos = 0;
+    }
+
+  if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
+    {
+      int pw;
+      
+      pw = FRAME_X_DISPLAY_INFO (f)->width;
+      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+      pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
+        - f->output_data.x->x_pixels_diff;
+      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+      *left_pos = 0;
+    }
+
+  *width = newwidth;
+  *height = newheight;
+}
+
 
 /* Change the size of frame F's X window to COLS/ROWS in the case F
    doesn't have a widget.  If CHANGE_GRAVITY is 1, we change to
 
 /* Change the size of frame F's X window to COLS/ROWS in the case F
    doesn't have a widget.  If CHANGE_GRAVITY is 1, we change to
@@ -13676,7 +14144,7 @@ x_list_fonts (f, pattern, size, maxnames)
          XFontStruct *font;
          unsigned long value;
 
          XFontStruct *font;
          unsigned long value;
 
-         font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
+         font = XLoadQueryFont (dpy, SDATA (pattern));
          if (x_had_errors_p (dpy))
            {
              /* This error is perhaps due to insufficient memory on X
          if (x_had_errors_p (dpy))
            {
              /* This error is perhaps due to insufficient memory on X
@@ -13719,7 +14187,7 @@ x_list_fonts (f, pattern, size, maxnames)
        {
          /* We try at least 10 fonts because XListFonts will return
             auto-scaled fonts at the head.  */
        {
          /* We try at least 10 fonts because XListFonts will return
             auto-scaled fonts at the head.  */
-         names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
+         names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10),
                              &num_fonts);
          if (x_had_errors_p (dpy))
            {
                              &num_fonts);
          if (x_had_errors_p (dpy))
            {
@@ -13820,7 +14288,7 @@ x_list_fonts (f, pattern, size, maxnames)
              BLOCK_INPUT;
              count = x_catch_errors (dpy);
              thisinfo = XLoadQueryFont (dpy,
              BLOCK_INPUT;
              count = x_catch_errors (dpy);
              thisinfo = XLoadQueryFont (dpy,
-                                        XSTRING (XCAR (tem))->data);
+                                        SDATA (XCAR (tem)));
              if (x_had_errors_p (dpy))
                {
                  /* This error is perhaps due to insufficient memory on X
              if (x_had_errors_p (dpy))
                {
                  /* This error is perhaps due to insufficient memory on X
@@ -14000,9 +14468,9 @@ x_load_font (f, fontname, size)
        for (tail = font_names; CONSP (tail); tail = XCDR (tail))
          if (dpyinfo->font_table[i].name
              && (!strcmp (dpyinfo->font_table[i].name,
        for (tail = font_names; CONSP (tail); tail = XCDR (tail))
          if (dpyinfo->font_table[i].name
              && (!strcmp (dpyinfo->font_table[i].name,
-                          XSTRING (XCAR (tail))->data)
+                          SDATA (XCAR (tail)))
                  || !strcmp (dpyinfo->font_table[i].full_name,
                  || !strcmp (dpyinfo->font_table[i].full_name,
-                             XSTRING (XCAR (tail))->data)))
+                             SDATA (XCAR (tail)))))
            return (dpyinfo->font_table + i);
     }
 
            return (dpyinfo->font_table + i);
     }
 
@@ -14020,7 +14488,7 @@ x_load_font (f, fontname, size)
        a bug of not finding a font even if the font surely exists and
        is loadable by XLoadQueryFont.  */
     if (size > 0 && !NILP (font_names))
        a bug of not finding a font even if the font surely exists and
        is loadable by XLoadQueryFont.  */
     if (size > 0 && !NILP (font_names))
-      fontname = (char *) XSTRING (XCAR (font_names))->data;
+      fontname = (char *) SDATA (XCAR (font_names));
 
     BLOCK_INPUT;
     count = x_catch_errors (FRAME_X_DISPLAY (f));
 
     BLOCK_INPUT;
     count = x_catch_errors (FRAME_X_DISPLAY (f));
@@ -14269,10 +14737,10 @@ static int x_initialized;
    the screen number from the server number.  */
 static int
 same_x_server (name1, name2)
    the screen number from the server number.  */
 static int
 same_x_server (name1, name2)
-     char *name1, *name2;
+     const char *name1, *name2;
 {
   int seen_colon = 0;
 {
   int seen_colon = 0;
-  unsigned char *system_name = XSTRING (Vsystem_name)->data;
+  const unsigned char *system_name = SDATA (Vsystem_name);
   int system_name_length = strlen (system_name);
   int length_until_period = 0;
 
   int system_name_length = strlen (system_name);
   int length_until_period = 0;
 
@@ -14353,10 +14821,12 @@ x_term_init (display_name, xrm_option, resource_name)
        argv[argc++] = "-xrm";
        argv[argc++] = xrm_option;
       }
        argv[argc++] = "-xrm";
        argv[argc++] = xrm_option;
       }
-    dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
+    stop_polling ();
+    dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name),
                         resource_name, EMACS_CLASS,
                         emacs_options, XtNumber (emacs_options),
                         &argc, argv);
                         resource_name, EMACS_CLASS,
                         emacs_options, XtNumber (emacs_options),
                         &argc, argv);
+    start_polling ();
 
 #ifdef HAVE_X11XTR6
     /* I think this is to compensate for XtSetLanguageProc.  */
 
 #ifdef HAVE_X11XTR6
     /* I think this is to compensate for XtSetLanguageProc.  */
@@ -14368,7 +14838,7 @@ x_term_init (display_name, xrm_option, resource_name)
 #ifdef HAVE_X11R5
   XSetLocaleModifiers ("");
 #endif
 #ifdef HAVE_X11R5
   XSetLocaleModifiers ("");
 #endif
-  dpy = XOpenDisplay (XSTRING (display_name)->data);
+  dpy = XOpenDisplay (SDATA (display_name));
 #endif /* not USE_X_TOOLKIT */
 
   /* Detect failure.  */
 #endif /* not USE_X_TOOLKIT */
 
   /* Detect failure.  */
@@ -14390,8 +14860,8 @@ x_term_init (display_name, xrm_option, resource_name)
 
     for (share = x_display_list, tail = x_display_name_list; share;
         share = share->next, tail = XCDR (tail))
 
     for (share = x_display_list, tail = x_display_name_list; share;
         share = share->next, tail = XCDR (tail))
-      if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
-                        XSTRING (display_name)->data))
+      if (same_x_server (SDATA (XCAR (XCAR (tail))),
+                        SDATA (display_name)))
        break;
     if (share)
       dpyinfo->kboard = share->kboard;
        break;
     if (share)
       dpyinfo->kboard = share->kboard;
@@ -14437,11 +14907,11 @@ x_term_init (display_name, xrm_option, resource_name)
 #endif /* ! 0 */
 
   dpyinfo->x_id_name
 #endif /* ! 0 */
 
   dpyinfo->x_id_name
-    = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
-                       + STRING_BYTES (XSTRING (Vsystem_name))
+    = (char *) xmalloc (SBYTES (Vinvocation_name)
+                       + SBYTES (Vsystem_name)
                        + 2);
   sprintf (dpyinfo->x_id_name, "%s@%s",
                        + 2);
   sprintf (dpyinfo->x_id_name, "%s@%s",
-          XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
+          SDATA (Vinvocation_name), SDATA (Vsystem_name));
 
   /* Figure out which modifier bits mean what.  */
   x_find_modifier_meanings (dpyinfo);
 
   /* Figure out which modifier bits mean what.  */
   x_find_modifier_meanings (dpyinfo);
@@ -14487,6 +14957,7 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->mouse_face_overlay = Qnil;
   dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
   dpyinfo->mouse_face_defer = 0;
   dpyinfo->mouse_face_overlay = Qnil;
   dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
   dpyinfo->mouse_face_defer = 0;
+  dpyinfo->mouse_face_hidden = 0;
   dpyinfo->x_focus_frame = 0;
   dpyinfo->x_focus_event_frame = 0;
   dpyinfo->x_highlight_frame = 0;
   dpyinfo->x_focus_frame = 0;
   dpyinfo->x_focus_event_frame = 0;
   dpyinfo->x_highlight_frame = 0;
@@ -14503,8 +14974,8 @@ x_term_init (display_name, xrm_option, resource_name)
                                          build_string ("PrivateColormap"),
                                          Qnil, Qnil);
          if (STRINGP (value)
                                          build_string ("PrivateColormap"),
                                          Qnil, Qnil);
          if (STRINGP (value)
-             && (!strcmp (XSTRING (value)->data, "true")
-                 || !strcmp (XSTRING (value)->data, "on")))
+             && (!strcmp (SDATA (value), "true")
+                 || !strcmp (SDATA (value), "on")))
            dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
        }
     }
            dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
        }
     }
@@ -14664,8 +15135,8 @@ x_term_init (display_name, xrm_option, resource_name)
                                    build_string ("Synchronous"),
                                    Qnil, Qnil);
     if (STRINGP (value)
                                    build_string ("Synchronous"),
                                    Qnil, Qnil);
     if (STRINGP (value)
-       && (!strcmp (XSTRING (value)->data, "true")
-           || !strcmp (XSTRING (value)->data, "on")))
+       && (!strcmp (SDATA (value), "true")
+           || !strcmp (SDATA (value), "on")))
       XSynchronize (dpyinfo->display, True);
   }
   
       XSynchronize (dpyinfo->display, True);
   }
   
@@ -14838,9 +15309,13 @@ x_initialize ()
   /* Disable Window Change signals;  they are handled by X events.  */
 #ifdef SIGWINCH
   signal (SIGWINCH, SIG_DFL);
   /* Disable Window Change signals;  they are handled by X events.  */
 #ifdef SIGWINCH
   signal (SIGWINCH, SIG_DFL);
-#endif /* ! defined (SIGWINCH) */
+#endif /* SIGWINCH */
 
   signal (SIGPIPE, x_connection_signal);
 
   signal (SIGPIPE, x_connection_signal);
+
+#ifdef HAVE_X_SM
+  x_session_initialize ();
+#endif
 }
 
 
 }
 
 
@@ -14859,6 +15334,11 @@ syms_of_xterm ()
   staticpro (&Qvendor_specific_keysyms);
   Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
 
   staticpro (&Qvendor_specific_keysyms);
   Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
 
+  staticpro (&Qutf_8);
+  Qutf_8 = intern ("utf-8");
+  staticpro (&Qlatin_1);
+  Qlatin_1 = intern ("latin-1");
+
   staticpro (&last_mouse_press_frame);
   last_mouse_press_frame = Qnil;
 
   staticpro (&last_mouse_press_frame);
   last_mouse_press_frame = Qnil;
 
@@ -14872,6 +15352,10 @@ syms_of_xterm ()
   staticpro (&previous_help_echo);
   help_echo_pos = -1;
 
   staticpro (&previous_help_echo);
   help_echo_pos = -1;
 
+  DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
+    doc: /* *Non-nil means autoselect window with mouse pointer.  */);
+  mouse_autoselect_window = 0;
+
   DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
     doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
 For example, if a block cursor is over a tab, it will be drawn as
   DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
     doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
 For example, if a block cursor is over a tab, it will be drawn as
@@ -14904,6 +15388,45 @@ Otherwise, value is a symbol describing the X toolkit.  */);
 
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
+  
+  Qmodifier_value = intern ("modifier-value");
+  Qalt = intern ("alt");
+  Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
+  Qhyper = intern ("hyper");
+  Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
+  Qmeta = intern ("meta");
+  Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
+  Qsuper = intern ("super");
+  Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
+  
+  DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
+    doc: /* Which keys Emacs uses for the alt modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `alt' means use the Alt_L and Alt_R keysyms.  The default
+is nil, which is the same as `alt'.  */);
+  Vx_alt_keysym = Qnil;
+  
+  DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
+    doc: /* Which keys Emacs uses for the hyper modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `hyper' means use the Hyper_L and Hyper_R keysyms.  The
+default is nil, which is the same as `hyper'.  */);
+  Vx_hyper_keysym = Qnil;
+  
+  DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
+    doc: /* Which keys Emacs uses for the meta modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `meta' means use the Meta_L and Meta_R keysyms.  The
+default is nil, which is the same as `meta'.  */);
+  Vx_meta_keysym = Qnil;
+  
+  DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
+    doc: /* Which keys Emacs uses for the super modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `super' means use the Super_L and Super_R keysyms.  The
+default is nil, which is the same as `super'.  */);
+  Vx_super_keysym = Qnil;
+
 }
 
 #endif /* HAVE_X_WINDOWS */
 }
 
 #endif /* HAVE_X_WINDOWS */