]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
(expose_overlaps): New function.
[gnu-emacs] / src / xterm.c
index db255f0765989bcdfa985d8497a22f9f42a95c36..3fbdd725c43dce44d353cd5d2d3c1e7e0f1e213d 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
@@ -98,7 +98,7 @@ Boston, MA 02111-1307, USA.  */
 #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
 
@@ -253,6 +253,13 @@ static Lisp_Object previous_help_echo;
 
 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.  */
@@ -379,9 +386,15 @@ extern int errno;
 
 /* 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 Qlatin_1, Qutf_8;
 
 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 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 *));
@@ -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 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 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 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));
@@ -476,7 +503,8 @@ static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
                               GC, int));
 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
-static void notice_overwritten_cursor P_ ((struct window *, int, int));
+static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area,
+                                          int, int, int, int));
 static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
@@ -489,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 *));
+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.  */
 
@@ -836,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;
-  unsigned char *bits;
+  unsigned char *bits = NULL;
   Pixmap pixmap;
   GC gc = f->output_data.x->normal_gc;
   struct face *face;
@@ -1123,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,
-                                                     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 *));
@@ -1264,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
-   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 *
-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;
-     int multibyte_p;
+     int multibyte_p, display_p;
 {
   struct face *face = FACE_FROM_ID (f, face_id);
 
@@ -1314,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.  */
-  xassert (face != NULL);
-  PREPARE_FACE_FOR_DISPLAY (f, face);
+  if (display_p)
+    {
+      xassert (face != NULL);
+      PREPARE_FACE_FOR_DISPLAY (f, face);
+    }
   
   return face;
 }
@@ -1607,7 +1643,7 @@ x_append_stretch_glyph (it, object, width, height, ascent)
    4. `:height HEIGHT' specifies that the height of the stretch produced
    should be HEIGHT, measured in canonical character units.
 
-   5. `:relative-height FACTOR' specifies that the height of the the
+   5. `:relative-height FACTOR' specifies that the height of the
    stretch should be FACTOR times the height of the characters having
    the glyph property.
 
@@ -1826,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,
-                                   it->multibyte_p);
+                                   it->multibyte_p, 0);
       font = face->font;
 
       /* When no suitable font found, use the default font.  */
@@ -2058,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, &char2b, it->multibyte_p);
+                                   it->face_id, &char2b, it->multibyte_p, 0);
       font = face->font;
 
       /* When no suitable font found, use the default font.  */
@@ -2146,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,
-                                           it->multibyte_p);
+                                           it->multibyte_p, 0);
              font = face->font;
              if (font == NULL)
                {
@@ -3836,6 +3872,7 @@ x_setup_relief_colors (s)
   if (s->face->use_box_color_for_shadows_p)
     color = s->face->box_color;
   else if (s->first_glyph->type == IMAGE_GLYPH
+          && s->img->pixmap
           && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
     color = IMAGE_BACKGROUND (s->img, s->f, 0);
   else
@@ -4091,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)
-           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
@@ -4207,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)
-           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
@@ -4945,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,               \
-                                     this_face_id, char2b + n, 1);       \
+                                     this_face_id, char2b + n, 1, 1);    \
       }                                                                          \
                                                                          \
     /* Make glyph_strings for each glyph sequence that is drawable by    \
@@ -5207,7 +5252,8 @@ x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
          x1 -= left_area_width;
        }
 
-      notice_overwritten_cursor (w, x0, x1);
+      notice_overwritten_cursor (w, area, x0, x1,
+                                row->y, MATRIX_ROW_BOTTOM_Y (row));
     }
 
   /* Value is the x-position up to which drawn, relative to AREA of W.
@@ -5297,6 +5343,14 @@ x_write_glyphs (start, len)
                     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.  */
@@ -5429,7 +5483,10 @@ x_clear_end_of_line (to_x)
   
   /* Notice if the cursor will be cleared by this operation.  */
   if (!updated_row->full_width_p)
-    notice_overwritten_cursor (w, output_cursor.x, -1);
+    notice_overwritten_cursor (w, updated_area,
+                              output_cursor.x, -1,
+                              updated_row->y,
+                              MATRIX_ROW_BOTTOM_Y (updated_row));
 
   from_x = output_cursor.x;
      
@@ -6015,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
@@ -6056,6 +6146,7 @@ expose_window (w, fr)
       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));
@@ -6074,7 +6165,8 @@ expose_window (w, fr)
       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)
@@ -6087,6 +6179,13 @@ expose_window (w, fr)
              || (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;
            }
@@ -6107,6 +6206,10 @@ expose_window (w, fr)
 
       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);
       
@@ -6246,6 +6349,121 @@ x_new_focus_frame (dpyinfo, frame)
   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
@@ -6414,12 +6632,28 @@ x_x_to_emacs_modifiers (dpyinfo, 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)
-         | ((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
@@ -6427,12 +6661,29 @@ x_emacs_to_x_modifiers (dpyinfo, 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.  */
@@ -6558,9 +6809,9 @@ construct_mouse_click (result, event, 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.  */
-  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),
@@ -6616,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
@@ -6737,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
-note_mode_line_highlight (w, x, mode_line_p)
+note_mode_line_or_margin_highlight (w, x, y, portion)
      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 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);
 }
 
@@ -6838,7 +7058,7 @@ note_mouse_highlight (f, x, y)
     return;
 #endif
 
-  if (disable_mouse_highlight
+  if (NILP (Vmouse_highlight)
       || !f->glyphs_initialized_p)
     return;
 
@@ -6878,10 +7098,10 @@ note_mouse_highlight (f, x, y)
       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;
     }
   
@@ -7097,7 +7317,7 @@ note_mouse_highlight (f, x, y)
              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,
@@ -7195,7 +7415,7 @@ note_mouse_highlight (f, x, y)
            /* 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);
@@ -7462,7 +7682,7 @@ note_tool_bar_highlight (f, x, y)
       
  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;
@@ -7648,9 +7868,9 @@ fast_find_position (w, pos, hpos, vpos, x, y, stop)
 #endif /* not 0 */
 
 
-/* Find the position of the 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.
+/* 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.
 
    RIGHT_P non-zero means return the position of the right edge of the
    glyph, RIGHT_P zero means return the left edge position.
@@ -7744,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
+      /* 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)
@@ -7780,7 +8002,8 @@ show_mouse_face (dpyinfo, draw)
              x_draw_glyphs (w, start_x, row, TEXT_AREA, 
                             start_hpos, end_hpos, draw, 0);
 
-             row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
+             row->mouse_face_p
+               = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
            }
        }
 
@@ -8275,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
-   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,
@@ -8405,7 +8628,7 @@ x_scroll_bar_to_input_event (event, ievent)
   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));
@@ -8428,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.
-   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)
@@ -8482,31 +8705,10 @@ xm_scroll_callback (widget, client_data, call_data)
        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;
       
@@ -8809,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;
 
-  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
     {
@@ -8817,45 +9039,34 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, 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);
-    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 */
+
+  if (whole == 0)
+    top = 0, shown = 1;
+  else
+    {
+      top = (float) position / whole;
+      shown = (float) portion / whole;
+    }
+
   {
     float old_top, old_shown;
     Dimension height;
@@ -8924,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,
-   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 *
@@ -9266,7 +9477,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
        }
 
       /* 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.  */
       {
@@ -9475,7 +9686,7 @@ x_scroll_bar_expose (bar, event)
 }
 
 /* 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.  */
@@ -9491,7 +9702,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
   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 
@@ -9813,11 +10024,13 @@ x_stop_queuing_selection_requests (display)
 \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;
+#endif
 
 /* This holds the state XLookupString needs to implement dead keys
    and other tricks known as "compose processing".  _X Window System_
@@ -9856,7 +10069,7 @@ static struct x_display_info *next_noop_dpyinfo;
          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++;                                                   \
@@ -9880,7 +10093,7 @@ static struct x_display_info *next_noop_dpyinfo;
 
    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;
@@ -9912,18 +10125,6 @@ XTread_socket (sd, bufp, numchars, expected)
 
   ++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)
@@ -9962,6 +10163,12 @@ XTread_socket (sd, bufp, numchars, expected)
          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);
@@ -10044,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.  */
-                       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);
-
                            /* This is just so we only give real data once
                               for a single Emacs process.  */
                            if (f == SELECTED_FRAME ())
@@ -10073,7 +10286,7 @@ XTread_socket (sd, bufp, numchars, expected)
                            if (numchars == 0)
                              abort ();
 
-                           bufp->kind = delete_window_event;
+                           bufp->kind = DELETE_WINDOW_EVENT;
                            XSETFRAME (bufp->frame_or_window, f);
                            bufp->arg = Qnil;
                            bufp++;
@@ -10163,7 +10376,7 @@ XTread_socket (sd, bufp, numchars, expected)
                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;
@@ -10192,7 +10405,7 @@ XTread_socket (sd, bufp, numchars, expected)
                  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;
@@ -10236,6 +10449,8 @@ XTread_socket (sd, bufp, numchars, expected)
              f = x_window_to_frame (dpyinfo, event.xexpose.window);
              if (f)
                {
+                  x_check_fullscreen (f);
+
                  if (f->async_visible == 0)
                    {
                      f->async_visible = 1;
@@ -10330,7 +10545,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      f->async_iconified = 1;
 
-                     bufp->kind = iconify_event;
+                     bufp->kind = ICONIFY_EVENT;
                      XSETFRAME (bufp->frame_or_window, f);
                      bufp->arg = Qnil;
                      bufp++;
@@ -10362,7 +10577,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                  if (f->iconified)
                    {
-                     bufp->kind = deiconify_event;
+                     bufp->kind = DEICONIFY_EVENT;
                      XSETFRAME (bufp->frame_or_window, f);
                      bufp->arg = Qnil;
                      bufp++;
@@ -10379,8 +10594,19 @@ XTread_socket (sd, bufp, numchars, expected)
              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);
 
+             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)
                {
@@ -10414,6 +10640,7 @@ XTread_socket (sd, bufp, numchars, expected)
                  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),
@@ -10443,6 +10670,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      Status status_return;
 
+                     coding_system = Vlocale_coding_system;
                      nbytes = XmbLookupString (FRAME_XIC (f),
                                                &event.xkey, copy_bufptr,
                                                copy_bufsiz, &keysym,
@@ -10456,6 +10684,27 @@ XTread_socket (sd, bufp, numchars, expected)
                                                    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;
@@ -10551,12 +10800,20 @@ XTread_socket (sd, bufp, numchars, expected)
                                || ((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;
-                         bufp->kind = non_ascii_keystroke;
+                         bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
                          bufp->code = keysym;
                          XSETFRAME (bufp->frame_or_window, f);
                          bufp->arg = Qnil;
@@ -10574,6 +10831,17 @@ XTread_socket (sd, bufp, numchars, expected)
                          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
@@ -10582,31 +10850,25 @@ XTread_socket (sd, bufp, numchars, expected)
                              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.  */
@@ -10619,8 +10881,8 @@ XTread_socket (sd, bufp, numchars, expected)
                                                            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;
@@ -10662,15 +10924,16 @@ XTread_socket (sd, bufp, numchars, expected)
              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:
              {
+                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
@@ -10697,34 +10960,29 @@ XTread_socket (sd, bufp, numchars, expected)
              }
 
            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:
+              {
+                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)
                {
@@ -10752,32 +11010,19 @@ XTread_socket (sd, bufp, numchars, expected)
                      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:
-             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;
 
@@ -10793,8 +11038,43 @@ XTread_socket (sd, bufp, numchars, expected)
                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)
-                 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
@@ -10838,8 +11118,17 @@ XTread_socket (sd, bufp, numchars, expected)
              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);
+                  if (dont_resize)
+                    goto OTHER;
                  
                  /* In the toolkit version, change_frame_size
                     is called by the code that handles resizing
@@ -10867,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_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);
@@ -10900,7 +11193,7 @@ XTread_socket (sd, bufp, numchars, expected)
                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
@@ -10966,7 +11259,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    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++;
@@ -11098,23 +11391,49 @@ XTread_socket (sd, bufp, numchars, expected)
                             Text Cursor
  ***********************************************************************/
 
-/* Notice if the text cursor of window W has been overwritten by a
-   drawing operation that outputs N glyphs starting at START_X and
-   ending at END_X in the line given by output_cursor.vpos.
-   Coordinates are area-relative.  END_X < 0 means all the rest
-   of the line after START_X has been written.  */
+/* Notice when the text cursor of window W has been completely
+   overwritten by a drawing operation that outputs glyphs in AREA
+   starting at X0 and ending at X1 in the line starting at Y0 and
+   ending at Y1.  X coordinates are area-relative.  X1 < 0 means all
+   the rest of the line after X0 has been written.  Y coordinates
+   are window-relative.  */
 
 static void
-notice_overwritten_cursor (w, start_x, end_x)
+notice_overwritten_cursor (w, area, x0, x1, y0, y1)
      struct window *w;
-     int start_x, end_x;
+     enum glyph_row_area area;
+     int x0, y0, x1, y1;
 {
-  if (updated_area == TEXT_AREA
-      && w->phys_cursor_on_p
-      && output_cursor.vpos == w->phys_cursor.vpos
-      && start_x <= w->phys_cursor.x
-      && (end_x < 0 || end_x > 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;
+       }
+    }
 }
 
 
@@ -11194,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);
+  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.  */
@@ -11220,10 +11540,11 @@ x_draw_hollow_cursor (w, row)
    --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;
+     enum text_cursor_kinds kind;
 {
   struct frame *f = XFRAME (w->frame);
   struct glyph *cursor_glyph;
@@ -11276,11 +11597,22 @@ x_draw_bar_cursor (w, row, 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);
-      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);
     }
 }
@@ -11314,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;
+      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;
 
+      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.  */
-      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))
@@ -11369,6 +11705,12 @@ x_erase_phys_cursor (w)
   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
@@ -11468,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;
+  int cursor_off_state = 0;
   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
@@ -11507,47 +11849,62 @@ 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.  */
-  cursor_non_selected 
-    = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
-                                 w->buffer));
   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);
-      else if (cursor_non_selected)
-       new_cursor_type = HOLLOW_BOX_CURSOR;
-      else
+      else if (NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
+                                         w->buffer)))
        new_cursor_type = NO_CURSOR;
+      else
+       cursor_off_state = 1;
     }
-  else
+
+  /* Nonselected window or nonselected frame.  */
+  else if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
+          || w != XWINDOW (f->selected_window))
     {
-      if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
-         || w != XWINDOW (f->selected_window))
-       {
-         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;
-       }
-      else if (w->cursor_off_p)
+      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;
       else
-       {
-         struct buffer *b = XBUFFER (w->buffer);
+       cursor_off_state = 1;
+    }
 
-         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);
-       }
+  /* If new_cursor_type isn't decided yet, decide it now.  */
+  if (new_cursor_type == -2)
+    {
+      struct buffer *b = XBUFFER (w->buffer);
+
+      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.  */
@@ -11555,12 +11912,17 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, 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);
 
-  /* 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;
@@ -11585,10 +11947,15 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
          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:
+         w->phys_cursor_width = 0;
          break;
 
        default:
@@ -11780,7 +12147,7 @@ x_error_catcher (display, error)
      XErrorEvent *error;
 {
   XGetErrorText (display, error->error_code,
-                XSTRING (x_error_message_string)->data,
+                SDATA (x_error_message_string),
                 X_ERROR_MESSAGE_SIZE);
 }
 
@@ -11804,7 +12171,7 @@ int
 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);
@@ -11812,7 +12179,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);
-  XSTRING (x_error_message_string)->data[0] = 0;
+  SSET (x_error_message_string, 0, 0);
 
   return count;
 }
@@ -11839,8 +12206,8 @@ x_check_errors (dpy, format)
   /* 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
@@ -11853,7 +12220,7 @@ x_had_errors_p (dpy)
   /* 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.  */
@@ -11862,7 +12229,7 @@ void
 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.
@@ -12162,7 +12529,7 @@ x_new_fontset (f, fontsetname)
        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.  */
@@ -12174,7 +12541,7 @@ x_new_fontset (f, fontsetname)
 #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);
@@ -12633,6 +13000,114 @@ x_set_offset (f, xoff, yoff, change_gravity)
   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
@@ -13219,6 +13694,8 @@ x_free_frame_resources (f)
      struct frame *f;
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  Lisp_Object bar;
+  struct scroll_bar *b;
 
   BLOCK_INPUT;
 
@@ -13228,23 +13705,40 @@ x_free_frame_resources (f)
     {
       if (f->output_data.x->icon_desc)
        XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
-      
+
+#ifdef USE_X_TOOLKIT
+      /* Explicitly destroy the scroll bars of the frame.  Without
+        this, we get "BadDrawable" errors from the toolkit later on,
+        presumably from expose events generated for the disappearing
+        toolkit scroll bars.  */
+      for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
+       {
+         b = XSCROLL_BAR (bar);
+         x_scroll_bar_remove (b);
+       }
+#endif
+
 #ifdef HAVE_X_I18N
       if (FRAME_XIC (f))
        free_frame_xic (f);
 #endif
-      
-      if (FRAME_X_WINDOW (f))
-       XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-      
+
 #ifdef USE_X_TOOLKIT
       if (f->output_data.x->widget)
        {
          XtDestroyWidget (f->output_data.x->widget);
          f->output_data.x->widget = NULL;
        }
+      /* Tooltips don't have widgets, only a simple X window, even if
+        we are using a toolkit.  */
+      else if (FRAME_X_WINDOW (f))
+       XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+
       free_frame_menubar (f);
-#endif /* USE_X_TOOLKIT */
+#else  /* !USE_X_TOOLKIT */
+      if (FRAME_X_WINDOW (f))
+       XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+#endif /* !USE_X_TOOLKIT */
 
       unload_color (f, f->output_data.x->foreground_pixel);
       unload_color (f, f->output_data.x->background_pixel);
@@ -13252,7 +13746,7 @@ x_free_frame_resources (f)
       unload_color (f, f->output_data.x->cursor_foreground_pixel);
       unload_color (f, f->output_data.x->border_pixel);
       unload_color (f, f->output_data.x->mouse_pixel);
-      
+
       if (f->output_data.x->scroll_bar_background_pixel != -1)
        unload_color (f, f->output_data.x->scroll_bar_background_pixel);
       if (f->output_data.x->scroll_bar_foreground_pixel != -1)
@@ -13647,7 +14141,7 @@ x_list_fonts (f, pattern, size, maxnames)
          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
@@ -13690,7 +14184,7 @@ x_list_fonts (f, pattern, size, maxnames)
        {
          /* 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))
            {
@@ -13791,7 +14285,7 @@ x_list_fonts (f, pattern, size, maxnames)
              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
@@ -13971,9 +14465,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,
-                          XSTRING (XCAR (tail))->data)
+                          SDATA (XCAR (tail)))
                  || !strcmp (dpyinfo->font_table[i].full_name,
-                             XSTRING (XCAR (tail))->data)))
+                             SDATA (XCAR (tail)))))
            return (dpyinfo->font_table + i);
     }
 
@@ -13991,7 +14485,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))
-      fontname = (char *) XSTRING (XCAR (font_names))->data;
+      fontname = (char *) SDATA (XCAR (font_names));
 
     BLOCK_INPUT;
     count = x_catch_errors (FRAME_X_DISPLAY (f));
@@ -14144,10 +14638,10 @@ x_load_font (f, fontname, size)
 
     /* Set global flag fonts_changed_p to non-zero if the font loaded
        has a character with a smaller width than any other character
-       before, or if the font loaded has a smalle>r height than any
+       before, or if the font loaded has a smaller height than any
        other font loaded before.  If this happens, it will make a
        glyph matrix reallocation necessary.  */
-    fonts_changed_p = x_compute_min_glyph_bounds (f);
+    fonts_changed_p |= x_compute_min_glyph_bounds (f);
     UNBLOCK_INPUT;
     return fontp;
   }
@@ -14240,10 +14734,10 @@ static int x_initialized;
    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;
-  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;
 
@@ -14324,10 +14818,12 @@ x_term_init (display_name, xrm_option, resource_name)
        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);
+    start_polling ();
 
 #ifdef HAVE_X11XTR6
     /* I think this is to compensate for XtSetLanguageProc.  */
@@ -14339,7 +14835,7 @@ x_term_init (display_name, xrm_option, resource_name)
 #ifdef HAVE_X11R5
   XSetLocaleModifiers ("");
 #endif
-  dpy = XOpenDisplay (XSTRING (display_name)->data);
+  dpy = XOpenDisplay (SDATA (display_name));
 #endif /* not USE_X_TOOLKIT */
 
   /* Detect failure.  */
@@ -14361,8 +14857,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))
-      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;
@@ -14408,11 +14904,11 @@ x_term_init (display_name, xrm_option, resource_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",
-          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);
@@ -14458,6 +14954,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_hidden = 0;
   dpyinfo->x_focus_frame = 0;
   dpyinfo->x_focus_event_frame = 0;
   dpyinfo->x_highlight_frame = 0;
@@ -14474,8 +14971,8 @@ x_term_init (display_name, xrm_option, resource_name)
                                          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);
        }
     }
@@ -14635,8 +15132,8 @@ x_term_init (display_name, xrm_option, resource_name)
                                    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);
   }
   
@@ -14809,9 +15306,13 @@ x_initialize ()
   /* 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);
+
+#ifdef HAVE_X_SM
+  x_session_initialize ();
+#endif
 }
 
 
@@ -14830,6 +15331,11 @@ syms_of_xterm ()
   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;
 
@@ -14843,6 +15349,10 @@ syms_of_xterm ()
   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
@@ -14852,7 +15362,7 @@ wide as that tab on the display.  */);
   DEFVAR_BOOL ("x-use-underline-position-properties",
               &x_use_underline_position_properties,
      doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
-Nil means ignore them.  If you encounter fonts with bogus
+nil means ignore them.  If you encounter fonts with bogus
 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
 to 4.1, set this to nil.  */);
   x_use_underline_position_properties = 1;
@@ -14875,6 +15385,45 @@ Otherwise, value is a symbol describing the X toolkit.  */);
 
   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 */