]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
(Fcall_process_region): Doc fix.
[gnu-emacs] / src / xterm.c
index 080439004685faead37c47a0f0b15eed97a8a8b4..0992e1fac9d6aeb514b2af9e54d6ae8a8974bbf4 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, 2002
+   Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000, 01, 02, 2003
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -158,120 +158,20 @@ extern void _XEditResCheckMessages ();
 
 #define abs(x) ((x) < 0 ? -(x) : (x))
 
-#define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))
-
 \f
-/* Fringe bitmaps.  */
-
-enum fringe_bitmap_type
-{
-  NO_FRINGE_BITMAP,
-  LEFT_TRUNCATION_BITMAP,
-  RIGHT_TRUNCATION_BITMAP,
-  OVERLAY_ARROW_BITMAP,
-  CONTINUED_LINE_BITMAP,
-  CONTINUATION_LINE_BITMAP,
-  ZV_LINE_BITMAP
-};
-
-/* Bitmap drawn to indicate lines not displaying text if
-   `indicate-empty-lines' is non-nil.  */
-
-#define zv_width 8
-#define zv_height 72
-#define zv_period 3
-static unsigned char zv_bits[] = {
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
-
-/* An arrow like this: `<-'.  */
-
-#define left_width 8
-#define left_height 8
-static unsigned char left_bits[] = {
-   0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
-
-/* Right truncation arrow bitmap `->'.  */
-
-#define right_width 8
-#define right_height 8
-static unsigned char right_bits[] = {
-   0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
-
-/* Marker for continued lines.  */
-
-#define continued_width 8
-#define continued_height 8
-static unsigned char continued_bits[] = {
-   0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
-
-/* Marker for continuation lines.  */
-
-#define continuation_width 8
-#define continuation_height 8
-static unsigned char continuation_bits[] = {
-   0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
-
-/* Overlay arrow bitmap.  */
-
-#if 0
-/* A bomb.  */
-#define ov_width 8
-#define ov_height 8
-static unsigned char ov_bits[] = {
-   0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
-#else
-/* A triangular arrow.  */
-#define ov_width 8
-#define ov_height 8
-static unsigned char ov_bits[] = {
-   0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
-
-#endif
 
-extern Lisp_Object Qhelp_echo;
-
-\f
 /* Non-nil means Emacs uses toolkit scroll bars.  */
 
 Lisp_Object Vx_toolkit_scroll_bars;
 
-/* If a string, XTread_socket generates an event to display that string.
-   (The display is done in read_char.)  */
-
-static Lisp_Object help_echo;
-static Lisp_Object help_echo_window;
-static Lisp_Object help_echo_object;
-static int help_echo_pos;
-
-/* Temporary variable for XTread_socket.  */
-
-static Lisp_Object previous_help_echo;
-
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
    start.  */
 
 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.  */
-
-int x_stretch_cursor_p;
-
 /* Non-zero means make use of UNDERLINE_POSITION font properties.  */
 
 int x_use_underline_position_properties;
@@ -305,12 +205,6 @@ XtAppContext Xt_app_con;
 static String Xt_default_resources[] = {0};
 #endif /* USE_X_TOOLKIT */
 
-/* Nominal cursor position -- where to draw output.
-   HPOS and VPOS are window relative glyph matrix coordinates.
-   X and Y are window relative pixel coordinates.  */
-
-struct cursor_pos output_cursor;
-
 /* Non-zero means user is interacting with a toolkit scroll bar.  */
 
 static int toolkit_scroll_bar_interaction;
@@ -337,7 +231,6 @@ static int toolkit_scroll_bar_interaction;
 
 /* Where the mouse was last time we reported a mouse event.  */
 
-FRAME_PTR last_mouse_frame;
 static XRectangle last_mouse_glyph;
 static Lisp_Object last_mouse_press_frame;
 
@@ -404,46 +297,15 @@ 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 *));
 
 
-/* Enumeration for overriding/changing the face to use for drawing
-   glyphs in x_draw_glyphs.  */
-
-enum draw_glyphs_face
-{
-  DRAW_NORMAL_TEXT,
-  DRAW_INVERSE_VIDEO,
-  DRAW_CURSOR,
-  DRAW_MOUSE_FACE,
-  DRAW_IMAGE_RAISED,
-  DRAW_IMAGE_SUNKEN
-};
-
-static int cursor_in_mouse_face_p P_ ((struct window *));
-static int clear_mouse_face P_ ((struct x_display_info *));
 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
 static const XColor *x_color_cells P_ ((Display *, int *));
 static void x_update_window_end P_ ((struct window *, int, int));
-static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
 void x_delete_display P_ ((struct x_display_info *));
 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
                                                unsigned));
-static int fast_find_position P_ ((struct window *, int, int *, int *,
-                                  int *, int *, Lisp_Object));
-static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
-                                    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_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 show_mouse_face P_ ((struct x_display_info *,
-                                enum draw_glyphs_face));
 static int x_io_error_quitter P_ ((Display *));
 int x_catch_errors P_ ((Display *));
 void x_uncatch_errors P_ ((Display *, int));
@@ -458,18 +320,11 @@ void x_wm_set_icon_pixmap P_ ((struct frame *, int));
 void x_initialize P_ ((void));
 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
 static int x_compute_min_glyph_bounds P_ ((struct frame *));
-static void x_draw_phys_cursor_glyph P_ ((struct window *,
-                                         struct glyph_row *,
-                                         enum draw_glyphs_face));
 static void x_update_end P_ ((struct frame *));
 static void XTframe_up_to_date P_ ((struct frame *));
 static void XTset_terminal_modes P_ ((void));
 static void XTreset_terminal_modes P_ ((void));
-static void XTcursor_to P_ ((int, int, int, int));
-static void x_write_glyphs P_ ((struct glyph *, int));
-static void x_clear_end_of_line P_ ((int));
 static void x_clear_frame P_ ((void));
-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 *));
@@ -488,37 +343,13 @@ 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,
                                   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));
-static int expose_line P_ ((struct window *, struct glyph_row *,
-                            XRectangle *));
-static void x_update_cursor_in_window_tree P_ ((struct window *, int));
-static void x_update_window_cursor P_ ((struct window *, int));
-static void x_erase_phys_cursor P_ ((struct window *));
-void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
-static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
-                                     enum fringe_bitmap_type, int left_p));
 
 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 *, 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 *));
-static void x_draw_vertical_border P_ ((struct window *));
 static void x_after_update_window_line P_ ((struct glyph_row *));
-static INLINE void take_vertical_position_into_account P_ ((struct it *));
-static void x_produce_stretch_glyph P_ ((struct it *));
 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            enum scroll_bar_part *,
@@ -689,34 +520,19 @@ x_update_window_begin (w)
 }
 
 
-/* Draw a vertical window border to the right of window W if W doesn't
-   have vertical scroll bars.  */
+/* Draw a vertical window border from (x,y0) to (x,y1)  */
 
 static void
-x_draw_vertical_border (w)
+x_draw_vertical_window_border (w, x, y0, y1)
      struct window *w;
+     int x, y0, y1;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-
-  /* Redraw borders between horizontally adjacent windows.  Don't
-     do it for frames with vertical scroll bars because either the
-     right scroll bar of a window, or the left scroll bar of its
-     neighbor will suffice as a border.  */
-  if (!WINDOW_RIGHTMOST_P (w)
-      && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-    {
-      int x0, x1, y0, y1;
-
-      window_box_edges (w, -1, &x0, &y0, &x1, &y1);
-      x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
-      y1 -= 1;
-
-      XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                f->output_data.x->normal_gc, x1, y0, x1, y1);
-    }
+  
+  XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+            f->output_data.x->normal_gc, x, y0, x, y1);
 }
 
-
 /* End update of window W (which is equal to updated_window).
 
    Draw vertical borders between horizontally adjacent windows, and
@@ -742,9 +558,9 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
       BLOCK_INPUT;
 
       if (cursor_on_p)
-       x_display_and_set_cursor (w, 1, output_cursor.hpos,
-                                 output_cursor.vpos,
-                                 output_cursor.x, output_cursor.y);
+       display_and_set_cursor (w, 1, output_cursor.hpos,
+                               output_cursor.vpos,
+                               output_cursor.x, output_cursor.y);
 
       x_draw_vertical_border (w);
       UNBLOCK_INPUT;
@@ -773,9 +589,11 @@ x_update_end (f)
   /* Mouse highlight may be displayed again.  */
   FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
 
+#ifndef XFlush
   BLOCK_INPUT;
   XFlush (FRAME_X_DISPLAY (f));
   UNBLOCK_INPUT;
+#endif
 }
 
 
@@ -826,7 +644,7 @@ x_after_update_window_line (desired_row)
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
     {
       BLOCK_INPUT;
-      x_draw_row_fringe_bitmaps (w, desired_row);
+      draw_row_fringe_bitmaps (w, desired_row);
       UNBLOCK_INPUT;
     }
 
@@ -861,134 +679,23 @@ x_after_update_window_line (desired_row)
     }
 }
 
-
-/* Draw the bitmap WHICH in one of the left or right fringes of
-   window W.  ROW is the glyph row for which to display the bitmap; it
-   determines the vertical position at which the bitmap has to be
-   drawn.  */
-
 static void
-x_draw_fringe_bitmap (w, row, which, left_p)
+x_draw_fringe_bitmap (w, row, p)
      struct window *w;
      struct glyph_row *row;
-     enum fringe_bitmap_type which;
-     int left_p;
+     struct draw_fringe_bitmap_params *p;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Display *display = FRAME_X_DISPLAY (f);
   Window window = FRAME_X_WINDOW (f);
-  int x, y, wd, h, dy;
-  int b1, b2;
-  unsigned char *bits = NULL;
-  Pixmap pixmap;
   GC gc = f->output_data.x->normal_gc;
-  struct face *face;
-  int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+  struct face *face = p->face;
 
   /* Must clip because of partially visible lines.  */
   x_clip_to_row (w, row, gc, 1);
 
-  /* Convert row to frame coordinates.  */
-  y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
-
-  switch (which)
-    {
-    case NO_FRINGE_BITMAP:
-      wd = 0;
-      h = 0;
-      break;
-
-    case LEFT_TRUNCATION_BITMAP:
-      wd = left_width;
-      h = left_height;
-      bits = left_bits;
-      break;
-
-    case OVERLAY_ARROW_BITMAP:
-      wd = ov_width;
-      h = ov_height;
-      bits = ov_bits;
-      break;
-
-    case RIGHT_TRUNCATION_BITMAP:
-      wd = right_width;
-      h = right_height;
-      bits = right_bits;
-      break;
-
-    case CONTINUED_LINE_BITMAP:
-      wd = continued_width;
-      h = continued_height;
-      bits = continued_bits;
-      break;
-
-    case CONTINUATION_LINE_BITMAP:
-      wd = continuation_width;
-      h = continuation_height;
-      bits = continuation_bits;
-      break;
-
-    case ZV_LINE_BITMAP:
-      wd = zv_width;
-      h = zv_height - (y % zv_period);
-      bits = zv_bits + (y % zv_period);
-      break;
-
-    default:
-      abort ();
-    }
-
-  /* Clip bitmap if too high.  */
-  if (h > row->height)
-    h = row->height;
-
-  /* Set dy to the offset in the row to start drawing the bitmap.  */
-  dy = (row->height - h) / 2;
-
-  face = FACE_FROM_ID (f, FRINGE_FACE_ID);
-  PREPARE_FACE_FOR_DISPLAY (f, face);
-
-  /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
-     the fringe.  */
-  b1 = b2 = -1;
-  if (left_p)
-    {
-      if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
-       wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
-      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-          - wd
-          - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
-      if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
-       {
-         /* If W has a vertical border to its left, don't draw over it.  */
-         int border = ((XFASTINT (w->left) > 0
-                        && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-                       ? 1 : 0);
-         b1 = (window_box_left (w, -1)
-               - FRAME_X_LEFT_FRINGE_WIDTH (f)
-               + border);
-         b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
-       }
-    }
-  else
-    {
-      if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
-       wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
-      x = (window_box_right (w, -1)
-          + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
-      /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
-        the fringe.  */
-      if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
-       {
-         b1 = window_box_right (w, -1);
-         b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
-       }
-    }
-
-  if (b1 >= 0)
+  if (p->bx >= 0)
     {
-      int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-
       /* In case the same realized face is used for fringes and
         for something displayed in the text (e.g. face `region' on
         mono-displays, the fill style may have been changed to
@@ -999,81 +706,31 @@ x_draw_fringe_bitmap (w, row, which, left_p)
        XSetForeground (display, face->gc, face->background);
 
       XFillRectangle (display, window, face->gc,
-                     b1,
-                     WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                      row->y)),
-                     b2,
-                     row->visible_height);
+                     p->bx, p->by, p->nx, p->ny);
+
       if (!face->stipple)
        XSetForeground (display, face->gc, face->foreground);
     }
 
-  if (which != NO_FRINGE_BITMAP)
+  if (p->which != NO_FRINGE_BITMAP)
     {
+      unsigned char *bits = fringe_bitmaps[p->which].bits + p->dh;
+      Pixmap pixmap;
+      int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+
       /* Draw the bitmap.  I believe these small pixmaps can be cached
         by the server.  */
-      pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
+      pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
                                            face->foreground,
                                            face->background, depth);
-      XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
+      XCopyArea (display, pixmap, window, gc, 0, 0,
+                p->wd, p->h, p->x, p->y);
       XFreePixmap (display, pixmap);
     }
 
   XSetClipMask (display, gc, None);
 }
 
-
-/* Draw fringe bitmaps for glyph row ROW on window W.  Call this
-   function with input blocked.  */
-
-static void
-x_draw_row_fringe_bitmaps (w, row)
-     struct window *w;
-     struct glyph_row *row;
-{
-  struct frame *f = XFRAME (w->frame);
-  enum fringe_bitmap_type bitmap;
-
-  xassert (interrupt_input_blocked);
-
-  /* If row is completely invisible, because of vscrolling, we
-     don't have to draw anything.  */
-  if (row->visible_height <= 0)
-    return;
-
-  if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
-    {
-      /* Decide which bitmap to draw in the left fringe.  */
-      if (row->overlay_arrow_p)
-       bitmap = OVERLAY_ARROW_BITMAP;
-      else if (row->truncated_on_left_p)
-       bitmap = LEFT_TRUNCATION_BITMAP;
-      else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
-       bitmap = CONTINUATION_LINE_BITMAP;
-      else if (row->indicate_empty_line_p)
-       bitmap = ZV_LINE_BITMAP;
-      else
-       bitmap = NO_FRINGE_BITMAP;
-
-      x_draw_fringe_bitmap (w, row, bitmap, 1);
-    }
-
-  if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
-    {
-      /* Decide which bitmap to draw in the right fringe.  */
-      if (row->truncated_on_right_p)
-       bitmap = RIGHT_TRUNCATION_BITMAP;
-      else if (row->continued_p)
-       bitmap = CONTINUED_LINE_BITMAP;
-      else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
-       bitmap = ZV_LINE_BITMAP;
-      else
-       bitmap = NO_FRINGE_BITMAP;
-
-      x_draw_fringe_bitmap (w, row, bitmap, 0);
-    }
-}
-
 \f
 
 /* This is called when starting Emacs and when restarting after
@@ -1095,65 +752,6 @@ XTreset_terminal_modes ()
 }
 
 
-\f
-/***********************************************************************
-                           Output Cursor
- ***********************************************************************/
-
-/* Set the global variable output_cursor to CURSOR.  All cursor
-   positions are relative to updated_window.  */
-
-static void
-set_output_cursor (cursor)
-    struct cursor_pos *cursor;
-{
-  output_cursor.hpos = cursor->hpos;
-  output_cursor.vpos = cursor->vpos;
-  output_cursor.x = cursor->x;
-  output_cursor.y = cursor->y;
-}
-
-
-/* Set a nominal cursor position.
-
-   HPOS and VPOS are column/row positions in a window glyph matrix.  X
-   and Y are window text area relative pixel positions.
-
-   If this is done during an update, updated_window will contain the
-   window that is being updated and the position is the future output
-   cursor position for that window.  If updated_window is null, use
-   selected_window and display the cursor at the given position.  */
-
-static void
-XTcursor_to (vpos, hpos, y, x)
-     int vpos, hpos, y, x;
-{
-  struct window *w;
-
-  /* If updated_window is not set, work on selected_window.  */
-  if (updated_window)
-    w = updated_window;
-  else
-    w = XWINDOW (selected_window);
-
-  /* Set the output cursor.  */
-  output_cursor.hpos = hpos;
-  output_cursor.vpos = vpos;
-  output_cursor.x = x;
-  output_cursor.y = y;
-
-  /* If not called as part of an update, really display the cursor.
-     This will also set the cursor position of W.  */
-  if (updated_window == NULL)
-    {
-      BLOCK_INPUT;
-      x_display_cursor (w, 1, hpos, vpos, x, y);
-      XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
-      UNBLOCK_INPUT;
-    }
-}
-
-
 \f
 /***********************************************************************
                           Display Iterator
@@ -1161,30 +759,17 @@ XTcursor_to (vpos, hpos, y, x)
 
 /* Function prototypes of this page.  */
 
-static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
-                                                      struct glyph *,
-                                                      XChar2b *,
-                                                      int *));
-static struct face *x_get_char_face_and_encoding P_ ((struct frame *, 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 void x_append_composite_glyph P_ ((struct it *));
-static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
-                                       int, int, double));
-static void x_produce_glyphs P_ ((struct it *));
-static void x_produce_image_glyph P_ ((struct it *it));
+static int x_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
 
 
 /* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B
    is not contained in the font.  */
 
-static INLINE XCharStruct *
-x_per_char_metric (font, char2b)
+static XCharStruct *
+x_per_char_metric (font, char2b, font_type)
      XFontStruct *font;
      XChar2b *char2b;
+     int font_type;  /* unused on X */
 {
   /* The result metric information.  */
   XCharStruct *pcm = NULL;
@@ -1252,11 +837,12 @@ x_per_char_metric (font, char2b)
 /* Encode CHAR2B using encoding information from FONT_INFO.  CHAR2B is
    the two-byte form of C.  Encoding is returned in *CHAR2B.  */
 
-static INLINE void
-x_encode_char (c, char2b, font_info)
+static int
+x_encode_char (c, char2b, font_info, two_byte_p)
      int c;
      XChar2b *char2b;
      struct font_info *font_info;
+     int *two_byte_p;
 {
   int charset = CHAR_CHARSET (c);
   XFontStruct *font = font_info->font;
@@ -1304,6829 +890,2673 @@ x_encode_char (c, char2b, font_info)
       if (enc == 1 || enc == 3)
        char2b->byte2 |= 0x80;
     }
-}
 
+  if (two_byte_p)
+    *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
 
-/* 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.  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.  */
+  return FONT_TYPE_UNKNOWN;
+}
 
-static INLINE struct face *
-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, display_p;
-{
-  struct face *face = FACE_FROM_ID (f, face_id);
 
-  if (!multibyte_p)
-    {
-      /* Unibyte case.  We don't have to encode, but we have to make
-        sure to use a face suitable for unibyte.  */
-      char2b->byte1 = 0;
-      char2b->byte2 = c;
-      face_id = FACE_FOR_CHAR (f, face, c);
-      face = FACE_FROM_ID (f, face_id);
-    }
-  else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
-    {
-      /* Case of ASCII in a face known to fit ASCII.  */
-      char2b->byte1 = 0;
-      char2b->byte2 = c;
-    }
-  else
-    {
-      int c1, c2, charset;
+\f
+/***********************************************************************
+                           Glyph display
+ ***********************************************************************/
 
-      /* Split characters into bytes.  If c2 is -1 afterwards, C is
-        really a one-byte character so that byte1 is zero.  */
-      SPLIT_CHAR (c, charset, c1, c2);
-      if (c2 > 0)
-       char2b->byte1 = c1, char2b->byte2 = c2;
-      else
-       char2b->byte1 = 0, char2b->byte2 = c1;
 
-      /* Maybe encode the character in *CHAR2B.  */
-      if (face->font != NULL)
-       {
-         struct font_info *font_info
-           = FONT_INFO_FROM_ID (f, face->font_info_id);
-         if (font_info)
-           x_encode_char (c, char2b, font_info);
-       }
-    }
 
-  /* Make sure X resources of the face are allocated.  */
-  if (display_p)
-    {
-      xassert (face != NULL);
-      PREPARE_FACE_FOR_DISPLAY (f, face);
-    }
+static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
+static void x_set_glyph_string_gc P_ ((struct glyph_string *));
+static void x_draw_glyph_string_background P_ ((struct glyph_string *,
+                                               int));
+static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
+static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
+static void x_draw_glyph_string_box P_ ((struct glyph_string *));
+static void x_draw_glyph_string  P_ ((struct glyph_string *));
+static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
+static void x_set_cursor_gc P_ ((struct glyph_string *));
+static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
+static void x_set_mouse_face_gc P_ ((struct glyph_string *));
+static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
+                                     unsigned long *, double, int));
+static void x_setup_relief_color P_ ((struct frame *, struct relief *,
+                                     double, int, unsigned long));
+static void x_setup_relief_colors P_ ((struct glyph_string *));
+static void x_draw_image_glyph_string P_ ((struct glyph_string *));
+static void x_draw_image_relief P_ ((struct glyph_string *));
+static void x_draw_image_foreground P_ ((struct glyph_string *));
+static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
+static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
+                                          int, int, int));
+static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
+                                   int, int, int, int, XRectangle *));
+static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
+                                int, int, int, XRectangle *));
 
-  return face;
-}
+#if GLYPH_DEBUG
+static void x_check_font P_ ((struct frame *, XFontStruct *));
+#endif
 
 
-/* Get face and two-byte form of character glyph GLYPH on frame F.
-   The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
-   a pointer to a realized face that is ready for display.  */
+/* Set S->gc to a suitable GC for drawing glyph string S in cursor
+   face.  */
 
-static INLINE struct face *
-x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
-     struct frame *f;
-     struct glyph *glyph;
-     XChar2b *char2b;
-     int *two_byte_p;
+static void
+x_set_cursor_gc (s)
+     struct glyph_string *s;
 {
-  struct face *face;
-
-  xassert (glyph->type == CHAR_GLYPH);
-  face = FACE_FROM_ID (f, glyph->face_id);
-
-  if (two_byte_p)
-    *two_byte_p = 0;
-
-  if (!glyph->multibyte_p)
-    {
-      /* Unibyte case.  We don't have to encode, but we have to make
-        sure to use a face suitable for unibyte.  */
-      char2b->byte1 = 0;
-      char2b->byte2 = glyph->u.ch;
-    }
-  else if (glyph->u.ch < 128
-          && glyph->face_id < BASIC_FACE_ID_SENTINEL)
-    {
-      /* Case of ASCII in a face known to fit ASCII.  */
-      char2b->byte1 = 0;
-      char2b->byte2 = glyph->u.ch;
-    }
+  if (s->font == FRAME_FONT (s->f)
+      && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
+      && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
+      && !s->cmp)
+    s->gc = s->f->output_data.x->cursor_gc;
   else
     {
-      int c1, c2, charset;
+      /* Cursor on non-default face: must merge.  */
+      XGCValues xgcv;
+      unsigned long mask;
 
-      /* Split characters into bytes.  If c2 is -1 afterwards, C is
-        really a one-byte character so that byte1 is zero.  */
-      SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
-      if (c2 > 0)
-       char2b->byte1 = c1, char2b->byte2 = c2;
-      else
-       char2b->byte1 = 0, char2b->byte2 = c1;
+      xgcv.background = s->f->output_data.x->cursor_pixel;
+      xgcv.foreground = s->face->background;
+
+      /* If the glyph would be invisible, try a different foreground.  */
+      if (xgcv.foreground == xgcv.background)
+       xgcv.foreground = s->face->foreground;
+      if (xgcv.foreground == xgcv.background)
+       xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
+      if (xgcv.foreground == xgcv.background)
+       xgcv.foreground = s->face->foreground;
 
-      /* Maybe encode the character in *CHAR2B.  */
-      if (charset != CHARSET_ASCII)
+      /* Make sure the cursor is distinct from text in this face.  */
+      if (xgcv.background == s->face->background
+         && xgcv.foreground == s->face->foreground)
        {
-         struct font_info *font_info
-           = FONT_INFO_FROM_ID (f, face->font_info_id);
-         if (font_info)
-           {
-             x_encode_char (glyph->u.ch, char2b, font_info);
-             if (two_byte_p)
-               *two_byte_p
-                 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
-           }
+         xgcv.background = s->face->foreground;
+         xgcv.foreground = s->face->background;
        }
-    }
-
-  /* Make sure X resources of the face are allocated.  */
-  xassert (face != NULL);
-  PREPARE_FACE_FOR_DISPLAY (f, face);
-  return face;
-}
-
 
-/* Store one glyph for IT->char_to_display in IT->glyph_row.
-   Called from x_produce_glyphs when IT->glyph_row is non-null.  */
-
-static INLINE void
-x_append_glyph (it)
-     struct it *it;
-{
-  struct glyph *glyph;
-  enum glyph_row_area area = it->area;
+      IF_DEBUG (x_check_font (s->f, s->font));
+      xgcv.font = s->font->fid;
+      xgcv.graphics_exposures = False;
+      mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
 
-  xassert (it->glyph_row);
-  xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
+      if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
+       XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
+                  mask, &xgcv);
+      else
+       FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
+         = XCreateGC (s->display, s->window, mask, &xgcv);
 
-  glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
-  if (glyph < it->glyph_row->glyphs[area + 1])
-    {
-      glyph->charpos = CHARPOS (it->position);
-      glyph->object = it->object;
-      glyph->pixel_width = it->pixel_width;
-      glyph->voffset = it->voffset;
-      glyph->type = CHAR_GLYPH;
-      glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
-      glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
-                                     || it->phys_descent > it->descent);
-      glyph->padding_p = 0;
-      glyph->glyph_not_available_p = it->glyph_not_available_p;
-      glyph->face_id = it->face_id;
-      glyph->u.ch = it->char_to_display;
-      ++it->glyph_row->used[area];
+      s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
     }
 }
 
-/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
-   Called from x_produce_glyphs when IT->glyph_row is non-null.  */
-
-static INLINE void
-x_append_composite_glyph (it)
-     struct it *it;
-{
-  struct glyph *glyph;
-  enum glyph_row_area area = it->area;
 
-  xassert (it->glyph_row);
+/* Set up S->gc of glyph string S for drawing text in mouse face.  */
 
-  glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
-  if (glyph < it->glyph_row->glyphs[area + 1])
-    {
-      glyph->charpos = CHARPOS (it->position);
-      glyph->object = it->object;
-      glyph->pixel_width = it->pixel_width;
-      glyph->voffset = it->voffset;
-      glyph->type = COMPOSITE_GLYPH;
-      glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
-      glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
-                                     || it->phys_descent > it->descent);
-      glyph->padding_p = 0;
-      glyph->glyph_not_available_p = 0;
-      glyph->face_id = it->face_id;
-      glyph->u.cmp_id = it->cmp_id;
-      ++it->glyph_row->used[area];
-    }
-}
+static void
+x_set_mouse_face_gc (s)
+     struct glyph_string *s;
+{
+  int face_id;
+  struct face *face;
 
+  /* What face has to be used last for the mouse face?  */
+  face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
+  face = FACE_FROM_ID (s->f, face_id);
+  if (face == NULL)
+    face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
 
-/* Change IT->ascent and IT->height according to the setting of
-   IT->voffset.  */
+  if (s->first_glyph->type == CHAR_GLYPH)
+    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+  else
+    face_id = FACE_FOR_CHAR (s->f, face, 0);
+  s->face = FACE_FROM_ID (s->f, face_id);
+  PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
-static INLINE void
-take_vertical_position_into_account (it)
-     struct it *it;
-{
-  if (it->voffset)
+  /* If font in this face is same as S->font, use it.  */
+  if (s->font == s->face->font)
+    s->gc = s->face->gc;
+  else
     {
-      if (it->voffset < 0)
-       /* Increase the ascent so that we can display the text higher
-          in the line.  */
-       it->ascent += abs (it->voffset);
+      /* Otherwise construct scratch_cursor_gc with values from FACE
+        but font FONT.  */
+      XGCValues xgcv;
+      unsigned long mask;
+
+      xgcv.background = s->face->background;
+      xgcv.foreground = s->face->foreground;
+      IF_DEBUG (x_check_font (s->f, s->font));
+      xgcv.font = s->font->fid;
+      xgcv.graphics_exposures = False;
+      mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
+
+      if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
+       XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
+                  mask, &xgcv);
       else
-       /* Increase the descent so that we can display the text lower
-          in the line.  */
-       it->descent += it->voffset;
+       FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
+         = XCreateGC (s->display, s->window, mask, &xgcv);
+
+      s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
     }
+
+  xassert (s->gc != 0);
 }
 
 
-/* Produce glyphs/get display metrics for the image IT is loaded with.
-   See the description of struct display_iterator in dispextern.h for
-   an overview of struct display_iterator.  */
+/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
+   Faces to use in the mode line have already been computed when the
+   matrix was built, so there isn't much to do, here.  */
 
-static void
-x_produce_image_glyph (it)
-     struct it *it;
+static INLINE void
+x_set_mode_line_face_gc (s)
+     struct glyph_string *s;
 {
-  struct image *img;
-  struct face *face;
-
-  xassert (it->what == IT_IMAGE);
-
-  face = FACE_FROM_ID (it->f, it->face_id);
-  img = IMAGE_FROM_ID (it->f, it->image_id);
-  xassert (img);
+  s->gc = s->face->gc;
+}
 
-  /* Make sure X resources of the face and image are loaded.  */
-  PREPARE_FACE_FOR_DISPLAY (it->f, face);
-  prepare_image_for_display (it->f, img);
 
-  it->ascent = it->phys_ascent = image_ascent (img, face);
-  it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
-  it->pixel_width = img->width + 2 * img->hmargin;
+/* Set S->gc of glyph string S for drawing that glyph string.  Set
+   S->stippled_p to a non-zero value if the face of S has a stipple
+   pattern.  */
 
-  it->nglyphs = 1;
+static INLINE void
+x_set_glyph_string_gc (s)
+     struct glyph_string *s;
+{
+  PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
-  if (face->box != FACE_NO_BOX)
+  if (s->hl == DRAW_NORMAL_TEXT)
     {
-      if (face->box_line_width > 0)
-       {
-         it->ascent += face->box_line_width;
-         it->descent += face->box_line_width;
-       }
-
-      if (it->start_of_box_run_p)
-       it->pixel_width += abs (face->box_line_width);
-      if (it->end_of_box_run_p)
-       it->pixel_width += abs (face->box_line_width);
+      s->gc = s->face->gc;
+      s->stippled_p = s->face->stipple != 0;
     }
-
-  take_vertical_position_into_account (it);
-
-  if (it->glyph_row)
+  else if (s->hl == DRAW_INVERSE_VIDEO)
     {
-      struct glyph *glyph;
-      enum glyph_row_area area = it->area;
-
-      glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
-      if (glyph < it->glyph_row->glyphs[area + 1])
-       {
-         glyph->charpos = CHARPOS (it->position);
-         glyph->object = it->object;
-         glyph->pixel_width = it->pixel_width;
-         glyph->voffset = it->voffset;
-         glyph->type = IMAGE_GLYPH;
-         glyph->multibyte_p = it->multibyte_p;
-         glyph->left_box_line_p = it->start_of_box_run_p;
-         glyph->right_box_line_p = it->end_of_box_run_p;
-         glyph->overlaps_vertically_p = 0;
-          glyph->padding_p = 0;
-         glyph->glyph_not_available_p = 0;
-         glyph->face_id = it->face_id;
-         glyph->u.img_id = img->id;
-         ++it->glyph_row->used[area];
-       }
+      x_set_mode_line_face_gc (s);
+      s->stippled_p = s->face->stipple != 0;
+    }
+  else if (s->hl == DRAW_CURSOR)
+    {
+      x_set_cursor_gc (s);
+      s->stippled_p = 0;
+    }
+  else if (s->hl == DRAW_MOUSE_FACE)
+    {
+      x_set_mouse_face_gc (s);
+      s->stippled_p = s->face->stipple != 0;
+    }
+  else if (s->hl == DRAW_IMAGE_RAISED
+          || s->hl == DRAW_IMAGE_SUNKEN)
+    {
+      s->gc = s->face->gc;
+      s->stippled_p = s->face->stipple != 0;
     }
+  else
+    {
+      s->gc = s->face->gc;
+      s->stippled_p = s->face->stipple != 0;
+    }
+
+  /* GC must have been set.  */
+  xassert (s->gc != 0);
 }
 
 
-/* Append a stretch glyph to IT->glyph_row.  OBJECT is the source
-   of the glyph, WIDTH and HEIGHT are the width and height of the
-   stretch.  ASCENT is the percentage/100 of HEIGHT to use for the
-   ascent of the glyph (0 <= ASCENT <= 1).  */
+/* Set clipping for output of glyph string S.  S may be part of a mode
+   line or menu if we don't have X toolkit support.  */
 
-static void
-x_append_stretch_glyph (it, object, width, height, ascent)
-     struct it *it;
-     Lisp_Object object;
-     int width, height;
-     double ascent;
+static INLINE void
+x_set_glyph_string_clipping (s)
+     struct glyph_string *s;
 {
-  struct glyph *glyph;
-  enum glyph_row_area area = it->area;
+  XRectangle r;
+  get_glyph_string_clip_rect (s, &r);
+  XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
+}
 
-  xassert (ascent >= 0 && ascent <= 1);
 
-  glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
-  if (glyph < it->glyph_row->glyphs[area + 1])
+/* RIF:
+   Compute left and right overhang of glyph string S.  If S is a glyph
+   string for a composition, assume overhangs don't exist.  */
+
+static void
+x_compute_glyph_string_overhangs (s)
+     struct glyph_string *s;
+{
+  if (s->cmp == NULL
+      && s->first_glyph->type == CHAR_GLYPH)
     {
-      glyph->charpos = CHARPOS (it->position);
-      glyph->object = object;
-      glyph->pixel_width = width;
-      glyph->voffset = it->voffset;
-      glyph->type = STRETCH_GLYPH;
-      glyph->multibyte_p = it->multibyte_p;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
-      glyph->overlaps_vertically_p = 0;
-      glyph->padding_p = 0;
-      glyph->glyph_not_available_p = 0;
-      glyph->face_id = it->face_id;
-      glyph->u.stretch.ascent = height * ascent;
-      glyph->u.stretch.height = height;
-      ++it->glyph_row->used[area];
+      XCharStruct cs;
+      int direction, font_ascent, font_descent;
+      XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
+                     &font_ascent, &font_descent, &cs);
+      s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
+      s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
     }
 }
 
 
-/* Produce a stretch glyph for iterator IT.  IT->object is the value
-   of the glyph property displayed.  The value must be a list
-   `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
-   being recognized:
-
-   1. `:width WIDTH' specifies that the space should be WIDTH *
-   canonical char width wide.  WIDTH may be an integer or floating
-   point number.
-
-   2. `:relative-width FACTOR' specifies that the width of the stretch
-   should be computed from the width of the first character having the
-   `glyph' property, and should be FACTOR times that width.
-
-   3. `:align-to HPOS' specifies that the space should be wide enough
-   to reach HPOS, a value in canonical character units.
-
-   Exactly one of the above pairs must be present.
-
-   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
-   stretch should be FACTOR times the height of the characters having
-   the glyph property.
-
-   Either none or exactly one of 4 or 5 must be present.
+/* Fill rectangle X, Y, W, H with background color of glyph string S.  */
 
-   6. `:ascent ASCENT'  specifies that ASCENT percent of the height
-   of the stretch should be used for the ascent of the stretch.
-   ASCENT must be in the range 0 <= ASCENT <= 100.  */
+static INLINE void
+x_clear_glyph_string_rect (s, x, y, w, h)
+     struct glyph_string *s;
+     int x, y, w, h;
+{
+  XGCValues xgcv;
+  XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
+  XSetForeground (s->display, s->gc, xgcv.background);
+  XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
+  XSetForeground (s->display, s->gc, xgcv.foreground);
+}
 
-#define NUMVAL(X)                              \
-     ((INTEGERP (X) || FLOATP (X))             \
-      ? XFLOATINT (X)                          \
-      : - 1)
 
+/* Draw the background of glyph_string S.  If S->background_filled_p
+   is non-zero don't draw it.  FORCE_P non-zero means draw the
+   background even if it wouldn't be drawn normally.  This is used
+   when a string preceding S draws into the background of S, or S
+   contains the first component of a composition.  */
 
 static void
-x_produce_stretch_glyph (it)
-     struct it *it;
+x_draw_glyph_string_background (s, force_p)
+     struct glyph_string *s;
+     int force_p;
 {
-  /* (space :width WIDTH :height HEIGHT.  */
-#if GLYPH_DEBUG
-  extern Lisp_Object Qspace;
-#endif
-  extern Lisp_Object QCwidth, QCheight, QCascent;
-  extern Lisp_Object QCrelative_width, QCrelative_height;
-  extern Lisp_Object QCalign_to;
-  Lisp_Object prop, plist;
-  double width = 0, height = 0, ascent = 0;
-  struct face *face = FACE_FROM_ID (it->f, it->face_id);
-  XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
-
-  PREPARE_FACE_FOR_DISPLAY (it->f, face);
-
-  /* List should start with `space'.  */
-  xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
-  plist = XCDR (it->object);
-
-  /* Compute the width of the stretch.  */
-  if (prop = Fplist_get (plist, QCwidth),
-      NUMVAL (prop) > 0)
-    /* Absolute width `:width WIDTH' specified and valid.  */
-    width = NUMVAL (prop) * CANON_X_UNIT (it->f);
-  else if (prop = Fplist_get (plist, QCrelative_width),
-          NUMVAL (prop) > 0)
-    {
-      /* Relative width `:relative-width FACTOR' specified and valid.
-        Compute the width of the characters having the `glyph'
-        property.  */
-      struct it it2;
-      unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
-
-      it2 = *it;
-      if (it->multibyte_p)
+  /* Nothing to do if background has already been drawn or if it
+     shouldn't be drawn in the first place.  */
+  if (!s->background_filled_p)
+    {
+      int box_line_width = max (s->face->box_line_width, 0);
+
+      if (s->stippled_p)
        {
-         int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
-                       - IT_BYTEPOS (*it));
-         it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
+         /* Fill background with a stipple pattern.  */
+         XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+         XFillRectangle (s->display, s->window, s->gc, s->x,
+                         s->y + box_line_width,
+                         s->background_width,
+                         s->height - 2 * box_line_width);
+         XSetFillStyle (s->display, s->gc, FillSolid);
+         s->background_filled_p = 1;
+       }
+      else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
+              || s->font_not_found_p
+              || s->extends_to_end_of_line_p
+              || force_p)
+       {
+         x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
+                                    s->background_width,
+                                    s->height - 2 * box_line_width);
+         s->background_filled_p = 1;
        }
-      else
-       it2.c = *p, it2.len = 1;
-
-      it2.glyph_row = NULL;
-      it2.what = IT_CHARACTER;
-      x_produce_glyphs (&it2);
-      width = NUMVAL (prop) * it2.pixel_width;
     }
-  else if (prop = Fplist_get (plist, QCalign_to),
-          NUMVAL (prop) > 0)
-    width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
-  else
-    /* Nothing specified -> width defaults to canonical char width.  */
-    width = CANON_X_UNIT (it->f);
-
-  /* Compute height.  */
-  if (prop = Fplist_get (plist, QCheight),
-      NUMVAL (prop) > 0)
-    height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
-  else if (prop = Fplist_get (plist, QCrelative_height),
-          NUMVAL (prop) > 0)
-    height = FONT_HEIGHT (font) * NUMVAL (prop);
-  else
-    height = FONT_HEIGHT (font);
-
-  /* Compute percentage of height used for ascent.  If
-     `:ascent ASCENT' is present and valid, use that.  Otherwise,
-     derive the ascent from the font in use.  */
-  if (prop = Fplist_get (plist, QCascent),
-      NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
-    ascent = NUMVAL (prop) / 100.0;
-  else
-    ascent = (double) font->ascent / FONT_HEIGHT (font);
+}
 
-  if (width <= 0)
-    width = 1;
-  if (height <= 0)
-    height = 1;
 
-  if (it->glyph_row)
-    {
-      Lisp_Object object = it->stack[it->sp - 1].string;
-      if (!STRINGP (object))
-       object = it->w->buffer;
-      x_append_stretch_glyph (it, object, width, height, ascent);
-    }
+/* Draw the foreground of glyph string S.  */
+
+static void
+x_draw_glyph_string_foreground (s)
+     struct glyph_string *s;
+{
+  int i, x;
 
-  it->pixel_width = width;
-  it->ascent = it->phys_ascent = height * ascent;
-  it->descent = it->phys_descent = height - it->ascent;
-  it->nglyphs = 1;
+  /* If first glyph of S has a left box line, start drawing the text
+     of S to the right of that box line.  */
+  if (s->face->box != FACE_NO_BOX
+      && s->first_glyph->left_box_line_p)
+    x = s->x + abs (s->face->box_line_width);
+  else
+    x = s->x;
 
-  if (face->box != FACE_NO_BOX)
+  /* Draw characters of S as rectangles if S's font could not be
+     loaded.  */
+  if (s->font_not_found_p)
     {
-      if (face->box_line_width > 0)
+      for (i = 0; i < s->nchars; ++i)
        {
-         it->ascent += face->box_line_width;
-         it->descent += face->box_line_width;
+         struct glyph *g = s->first_glyph + i;
+         XDrawRectangle (s->display, s->window,
+                         s->gc, x, s->y, g->pixel_width - 1,
+                         s->height - 1);
+         x += g->pixel_width;
        }
+    }
+  else
+    {
+      char *char1b = (char *) s->char2b;
+      int boff = s->font_info->baseline_offset;
 
-      if (it->start_of_box_run_p)
-       it->pixel_width += abs (face->box_line_width);
-      if (it->end_of_box_run_p)
-       it->pixel_width += abs (face->box_line_width);
-    }
-
-  take_vertical_position_into_account (it);
-}
-
-/* Return proper value to be used as baseline offset of font that has
-   ASCENT and DESCENT to draw characters by the font at the vertical
-   center of the line of frame F.
-
-   Here, out task is to find the value of BOFF in the following figure;
-
-       -------------------------+-----------+-
-        -+-+---------+-+        |           |
-         | |         | |        |           |
-         | |         | |        F_ASCENT    F_HEIGHT
-         | |         | ASCENT   |           |
-     HEIGHT |         | |        |           |
-         | |         |-|-+------+-----------|------- baseline
-         | |         | | BOFF   |           |
-         | |---------|-+-+      |           |
-         | |         | DESCENT  |           |
-        -+-+---------+-+        F_DESCENT   |
-       -------------------------+-----------+-
-
-       -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
-       BOFF = DESCENT +  (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
-       DESCENT = FONT->descent
-       HEIGHT = FONT_HEIGHT (FONT)
-       F_DESCENT = (F->output_data.x->font->descent
-                    - F->output_data.x->baseline_offset)
-       F_HEIGHT = FRAME_LINE_HEIGHT (F)
-*/
-
-#define VCENTER_BASELINE_OFFSET(FONT, F)                       \
-  ((FONT)->descent                                             \
-   + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))           \
-      + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2  \
-   - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
-
-/* Produce glyphs/get display metrics for the display element IT is
-   loaded with.  See the description of struct display_iterator in
-   dispextern.h for an overview of struct display_iterator.  */
-
-static void
-x_produce_glyphs (it)
-     struct it *it;
-{
-  it->glyph_not_available_p = 0;
-
-  if (it->what == IT_CHARACTER)
-    {
-      XChar2b char2b;
-      XFontStruct *font;
-      struct face *face = FACE_FROM_ID (it->f, it->face_id);
-      XCharStruct *pcm;
-      int font_not_found_p;
-      struct font_info *font_info;
-      int boff;                        /* baseline offset */
-      /* We may change it->multibyte_p upon unibyte<->multibyte
-        conversion.  So, save the current value now and restore it
-        later.
-
-        Note: It seems that we don't have to record multibyte_p in
-        struct glyph because the character code itself tells if or
-        not the character is multibyte.  Thus, in the future, we must
-        consider eliminating the field `multibyte_p' in the struct
-        glyph.  */
-      int saved_multibyte_p = it->multibyte_p;
-
-      /* Maybe translate single-byte characters to multibyte, or the
-        other way.  */
-      it->char_to_display = it->c;
-      if (!ASCII_BYTE_P (it->c))
-       {
-         if (unibyte_display_via_language_environment
-             && SINGLE_BYTE_CHAR_P (it->c)
-             && (it->c >= 0240
-                 || !NILP (Vnonascii_translation_table)))
-           {
-             it->char_to_display = unibyte_char_to_multibyte (it->c);
-             it->multibyte_p = 1;
-             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
-             face = FACE_FROM_ID (it->f, it->face_id);
-           }
-         else if (!SINGLE_BYTE_CHAR_P (it->c)
-                  && !it->multibyte_p)
-           {
-             it->multibyte_p = 1;
-             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
-             face = FACE_FROM_ID (it->f, it->face_id);
-           }
-       }
+      if (s->font_info->vertical_centering)
+       boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
 
-      /* 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, 0);
-      font = face->font;
+      /* If we can use 8-bit functions, condense S->char2b.  */
+      if (!s->two_byte_p)
+       for (i = 0; i < s->nchars; ++i)
+         char1b[i] = s->char2b[i].byte2;
 
-      /* When no suitable font found, use the default font.  */
-      font_not_found_p = font == NULL;
-      if (font_not_found_p)
+      /* Draw text with XDrawString if background has already been
+        filled.  Otherwise, use XDrawImageString.  (Note that
+        XDrawImageString is usually faster than XDrawString.)  Always
+        use XDrawImageString when drawing the cursor so that there is
+        no chance that characters under a box cursor are invisible.  */
+      if (s->for_overlaps_p
+         || (s->background_filled_p && s->hl != DRAW_CURSOR))
        {
-         font = FRAME_FONT (it->f);
-         boff = it->f->output_data.x->baseline_offset;
-         font_info = NULL;
+         /* Draw characters with 16-bit or 8-bit functions.  */
+         if (s->two_byte_p)
+           XDrawString16 (s->display, s->window, s->gc, x,
+                          s->ybase - boff, s->char2b, s->nchars);
+         else
+           XDrawString (s->display, s->window, s->gc, x,
+                        s->ybase - boff, char1b, s->nchars);
        }
       else
        {
-         font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
-         boff = font_info->baseline_offset;
-         if (font_info->vertical_centering)
-           boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+         if (s->two_byte_p)
+           XDrawImageString16 (s->display, s->window, s->gc, x,
+                               s->ybase - boff, s->char2b, s->nchars);
+         else
+           XDrawImageString (s->display, s->window, s->gc, x,
+                             s->ybase - boff, char1b, s->nchars);
        }
 
-      if (it->char_to_display >= ' '
-         && (!it->multibyte_p || it->char_to_display < 128))
+      if (s->face->overstrike)
        {
-         /* Either unibyte or ASCII.  */
-         int stretched_p;
-
-         it->nglyphs = 1;
-
-         pcm = x_per_char_metric (font, &char2b);
-         it->ascent = font->ascent + boff;
-         it->descent = font->descent - boff;
-
-         if (pcm)
-           {
-             it->phys_ascent = pcm->ascent + boff;
-             it->phys_descent = pcm->descent - boff;
-             it->pixel_width = pcm->width;
-           }
+         /* For overstriking (to simulate bold-face), draw the
+            characters again shifted to the right by one pixel.  */
+         if (s->two_byte_p)
+           XDrawString16 (s->display, s->window, s->gc, x + 1,
+                          s->ybase - boff, s->char2b, s->nchars);
          else
-           {
-             it->glyph_not_available_p = 1;
-             it->phys_ascent = font->ascent + boff;
-             it->phys_descent = font->descent - boff;
-             it->pixel_width = FONT_WIDTH (font);
-           }
-
-         /* If this is a space inside a region of text with
-            `space-width' property, change its width.  */
-         stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
-         if (stretched_p)
-           it->pixel_width *= XFLOATINT (it->space_width);
-
-         /* If face has a box, add the box thickness to the character
-            height.  If character has a box line to the left and/or
-            right, add the box line width to the character's width.  */
-         if (face->box != FACE_NO_BOX)
-           {
-             int thick = face->box_line_width;
-
-             if (thick > 0)
-               {
-                 it->ascent += thick;
-                 it->descent += thick;
-               }
-             else
-               thick = -thick;
-
-             if (it->start_of_box_run_p)
-               it->pixel_width += thick;
-             if (it->end_of_box_run_p)
-               it->pixel_width += thick;
-           }
-
-         /* If face has an overline, add the height of the overline
-            (1 pixel) and a 1 pixel margin to the character height.  */
-         if (face->overline_p)
-           it->ascent += 2;
-
-         take_vertical_position_into_account (it);
-
-         /* If we have to actually produce glyphs, do it.  */
-         if (it->glyph_row)
-           {
-             if (stretched_p)
-               {
-                 /* Translate a space with a `space-width' property
-                    into a stretch glyph.  */
-                 double ascent = (double) font->ascent / FONT_HEIGHT (font);
-                 x_append_stretch_glyph (it, it->object, it->pixel_width,
-                                         it->ascent + it->descent, ascent);
-               }
-             else
-               x_append_glyph (it);
-
-             /* If characters with lbearing or rbearing are displayed
-                in this line, record that fact in a flag of the
-                glyph row.  This is used to optimize X output code.  */
-             if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
-               it->glyph_row->contains_overlapping_glyphs_p = 1;
-           }
-       }
-      else if (it->char_to_display == '\n')
-       {
-         /* A newline has no width but we need the height of the line.  */
-         it->pixel_width = 0;
-         it->nglyphs = 0;
-         it->ascent = it->phys_ascent = font->ascent + boff;
-         it->descent = it->phys_descent = font->descent - boff;
-
-         if (face->box != FACE_NO_BOX
-             && face->box_line_width > 0)
-           {
-             it->ascent += face->box_line_width;
-             it->descent += face->box_line_width;
-           }
-       }
-      else if (it->char_to_display == '\t')
-       {
-         int tab_width = it->tab_width * CANON_X_UNIT (it->f);
-         int x = it->current_x + it->continuation_lines_width;
-         int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
-
-         /* If the distance from the current position to the next tab
-            stop is less than a canonical character width, use the
-            tab stop after that.  */
-         if (next_tab_x - x < CANON_X_UNIT (it->f))
-           next_tab_x += tab_width;
-
-         it->pixel_width = next_tab_x - x;
-         it->nglyphs = 1;
-         it->ascent = it->phys_ascent = font->ascent + boff;
-         it->descent = it->phys_descent = font->descent - boff;
-
-         if (it->glyph_row)
-           {
-             double ascent = (double) it->ascent / (it->ascent + it->descent);
-             x_append_stretch_glyph (it, it->object, it->pixel_width,
-                                     it->ascent + it->descent, ascent);
-           }
+           XDrawString (s->display, s->window, s->gc, x + 1,
+                        s->ybase - boff, char1b, s->nchars);
        }
-      else
-       {
-         /* A multi-byte character.  Assume that the display width of the
-            character is the width of the character multiplied by the
-            width of the font.  */
-
-         /* If we found a font, this font should give us the right
-            metrics.  If we didn't find a font, use the frame's
-            default font and calculate the width of the character
-            from the charset width; this is what old redisplay code
-            did.  */
-         pcm = x_per_char_metric (font, &char2b);
-         if (font_not_found_p || !pcm)
-           {
-             int charset = CHAR_CHARSET (it->char_to_display);
-
-             it->glyph_not_available_p = 1;
-             it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
-                                * CHARSET_WIDTH (charset));
-             it->phys_ascent = font->ascent + boff;
-             it->phys_descent = font->descent - boff;
-           }
-         else
-           {
-             it->pixel_width = pcm->width;
-             it->phys_ascent = pcm->ascent + boff;
-             it->phys_descent = pcm->descent - boff;
-             if (it->glyph_row
-                 && (pcm->lbearing < 0
-                     || pcm->rbearing > pcm->width))
-               it->glyph_row->contains_overlapping_glyphs_p = 1;
-           }
-         it->nglyphs = 1;
-         it->ascent = font->ascent + boff;
-         it->descent = font->descent - boff;
-         if (face->box != FACE_NO_BOX)
-           {
-             int thick = face->box_line_width;
-
-             if (thick > 0)
-               {
-                 it->ascent += thick;
-                 it->descent += thick;
-               }
-             else
-               thick = - thick;
-
-             if (it->start_of_box_run_p)
-               it->pixel_width += thick;
-             if (it->end_of_box_run_p)
-               it->pixel_width += thick;
-           }
-
-         /* If face has an overline, add the height of the overline
-            (1 pixel) and a 1 pixel margin to the character height.  */
-         if (face->overline_p)
-           it->ascent += 2;
+    }
+}
 
-         take_vertical_position_into_account (it);
+/* Draw the foreground of composite glyph string S.  */
 
-         if (it->glyph_row)
-           x_append_glyph (it);
-       }
-      it->multibyte_p = saved_multibyte_p;
-    }
-  else if (it->what == IT_COMPOSITION)
-    {
-      /* Note: A composition is represented as one glyph in the
-        glyph matrix.  There are no padding glyphs.  */
-      XChar2b char2b;
-      XFontStruct *font;
-      struct face *face = FACE_FROM_ID (it->f, it->face_id);
-      XCharStruct *pcm;
-      int font_not_found_p;
-      struct font_info *font_info;
-      int boff;                        /* baseline offset */
-      struct composition *cmp = composition_table[it->cmp_id];
-
-      /* Maybe translate single-byte characters to multibyte.  */
-      it->char_to_display = it->c;
-      if (unibyte_display_via_language_environment
-         && SINGLE_BYTE_CHAR_P (it->c)
-         && (it->c >= 0240
-             || (it->c >= 0200
-                 && !NILP (Vnonascii_translation_table))))
-       {
-         it->char_to_display = unibyte_char_to_multibyte (it->c);
-       }
+static void
+x_draw_composite_glyph_string_foreground (s)
+     struct glyph_string *s;
+{
+  int i, x;
 
-      /* Get face and font to use.  Encode 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, 0);
-      font = face->font;
+  /* If first glyph of S has a left box line, start drawing the text
+     of S to the right of that box line.  */
+  if (s->face->box != FACE_NO_BOX
+      && s->first_glyph->left_box_line_p)
+    x = s->x + abs (s->face->box_line_width);
+  else
+    x = s->x;
 
-      /* When no suitable font found, use the default font.  */
-      font_not_found_p = font == NULL;
-      if (font_not_found_p)
-       {
-         font = FRAME_FONT (it->f);
-         boff = it->f->output_data.x->baseline_offset;
-         font_info = NULL;
-       }
-      else
-       {
-         font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
-         boff = font_info->baseline_offset;
-         if (font_info->vertical_centering)
-           boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
-       }
+  /* S is a glyph string for a composition.  S->gidx is the index of
+     the first character drawn for glyphs of this composition.
+     S->gidx == 0 means we are drawing the very first character of
+     this composition.  */
 
-      /* There are no padding glyphs, so there is only one glyph to
-        produce for the composition.  Important is that pixel_width,
-        ascent and descent are the values of what is drawn by
-        draw_glyphs (i.e. the values of the overall glyphs composed).  */
-      it->nglyphs = 1;
-
-      /* If we have not yet calculated pixel size data of glyphs of
-        the composition for the current face font, calculate them
-        now.  Theoretically, we have to check all fonts for the
-        glyphs, but that requires much time and memory space.  So,
-        here we check only the font of the first glyph.  This leads
-        to incorrect display very rarely, and C-l (recenter) can
-        correct the display anyway.  */
-      if (cmp->font != (void *) font)
+  /* Draw a rectangle for the composition if the font for the very
+     first character of the composition could not be loaded.  */
+  if (s->font_not_found_p)
+    {
+      if (s->gidx == 0)
+       XDrawRectangle (s->display, s->window, s->gc, x, s->y,
+                       s->width - 1, s->height - 1);
+    }
+  else
+    {
+      for (i = 0; i < s->nchars; i++, ++s->gidx)
        {
-         /* Ascent and descent of the font of the first character of
-            this composition (adjusted by baseline offset).  Ascent
-            and descent of overall glyphs should not be less than
-            them respectively.  */
-         int font_ascent = font->ascent + boff;
-         int font_descent = font->descent - boff;
-         /* Bounding box of the overall glyphs.  */
-         int leftmost, rightmost, lowest, highest;
-         int i, width, ascent, descent;
-
-         cmp->font = (void *) font;
-
-         /* Initialize the bounding box.  */
-         if (font_info
-             && (pcm = x_per_char_metric (font, &char2b)))
-           {
-             width = pcm->width;
-             ascent = pcm->ascent;
-             descent = pcm->descent;
-           }
-         else
-           {
-             width = FONT_WIDTH (font);
-             ascent = font->ascent;
-             descent = font->descent;
-           }
-
-         rightmost = width;
-         lowest = - descent + boff;
-         highest = ascent + boff;
-         leftmost = 0;
-
-         if (font_info
-             && font_info->default_ascent
-             && CHAR_TABLE_P (Vuse_default_ascent)
-             && !NILP (Faref (Vuse_default_ascent,
-                              make_number (it->char_to_display))))
-           highest = font_info->default_ascent + boff;
-
-         /* Draw the first glyph at the normal position.  It may be
-            shifted to right later if some other glyphs are drawn at
-            the left.  */
-         cmp->offsets[0] = 0;
-         cmp->offsets[1] = boff;
-
-         /* Set cmp->offsets for the remaining glyphs.  */
-         for (i = 1; i < cmp->glyph_len; i++)
-           {
-             int left, right, btm, top;
-             int ch = COMPOSITION_GLYPH (cmp, i);
-             int face_id = FACE_FOR_CHAR (it->f, face, ch);
-
-             face = FACE_FROM_ID (it->f, face_id);
-             x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
-                                           it->multibyte_p, 0);
-             font = face->font;
-             if (font == NULL)
-               {
-                 font = FRAME_FONT (it->f);
-                 boff = it->f->output_data.x->baseline_offset;
-                 font_info = NULL;
-               }
-             else
-               {
-                 font_info
-                   = FONT_INFO_FROM_ID (it->f, face->font_info_id);
-                 boff = font_info->baseline_offset;
-                 if (font_info->vertical_centering)
-                   boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
-               }
-
-             if (font_info
-                 && (pcm = x_per_char_metric (font, &char2b)))
-               {
-                 width = pcm->width;
-                 ascent = pcm->ascent;
-                 descent = pcm->descent;
-               }
-             else
-               {
-                 width = FONT_WIDTH (font);
-                 ascent = 1;
-                 descent = 0;
-               }
-
-             if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
-               {
-                 /* Relative composition with or without
-                    alternate chars.  */
-                 left = (leftmost + rightmost - width) / 2;
-                 btm = - descent + boff;
-                 if (font_info && font_info->relative_compose
-                     && (! CHAR_TABLE_P (Vignore_relative_composition)
-                         || NILP (Faref (Vignore_relative_composition,
-                                         make_number (ch)))))
-                   {
-
-                     if (- descent >= font_info->relative_compose)
-                       /* One extra pixel between two glyphs.  */
-                       btm = highest + 1;
-                     else if (ascent <= 0)
-                       /* One extra pixel between two glyphs.  */
-                       btm = lowest - 1 - ascent - descent;
-                   }
-               }
-             else
-               {
-                 /* A composition rule is specified by an integer
-                    value that encodes global and new reference
-                    points (GREF and NREF).  GREF and NREF are
-                    specified by numbers as below:
-
-                       0---1---2 -- ascent
-                       |       |
-                       |       |
-                       |       |
-                       9--10--11 -- center
-                       |       |
-                    ---3---4---5--- baseline
-                       |       |
-                       6---7---8 -- descent
-                 */
-                 int rule = COMPOSITION_RULE (cmp, i);
-                 int gref, nref, grefx, grefy, nrefx, nrefy;
-
-                 COMPOSITION_DECODE_RULE (rule, gref, nref);
-                 grefx = gref % 3, nrefx = nref % 3;
-                 grefy = gref / 3, nrefy = nref / 3;
-
-                 left = (leftmost
-                         + grefx * (rightmost - leftmost) / 2
-                         - nrefx * width / 2);
-                 btm = ((grefy == 0 ? highest
-                         : grefy == 1 ? 0
-                         : grefy == 2 ? lowest
-                         : (highest + lowest) / 2)
-                        - (nrefy == 0 ? ascent + descent
-                           : nrefy == 1 ? descent - boff
-                           : nrefy == 2 ? 0
-                           : (ascent + descent) / 2));
-               }
-
-             cmp->offsets[i * 2] = left;
-             cmp->offsets[i * 2 + 1] = btm + descent;
-
-             /* Update the bounding box of the overall glyphs. */
-             right = left + width;
-             top = btm + descent + ascent;
-             if (left < leftmost)
-               leftmost = left;
-             if (right > rightmost)
-               rightmost = right;
-             if (top > highest)
-               highest = top;
-             if (btm < lowest)
-               lowest = btm;
-           }
-
-         /* If there are glyphs whose x-offsets are negative,
-            shift all glyphs to the right and make all x-offsets
-            non-negative.  */
-         if (leftmost < 0)
-           {
-             for (i = 0; i < cmp->glyph_len; i++)
-               cmp->offsets[i * 2] -= leftmost;
-             rightmost -= leftmost;
-           }
-
-         cmp->pixel_width = rightmost;
-         cmp->ascent = highest;
-         cmp->descent = - lowest;
-         if (cmp->ascent < font_ascent)
-           cmp->ascent = font_ascent;
-         if (cmp->descent < font_descent)
-           cmp->descent = font_descent;
+         XDrawString16 (s->display, s->window, s->gc,
+                        x + s->cmp->offsets[s->gidx * 2],
+                        s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
+                        s->char2b + i, 1);
+         if (s->face->overstrike)
+           XDrawString16 (s->display, s->window, s->gc,
+                          x + s->cmp->offsets[s->gidx * 2] + 1,
+                          s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
+                          s->char2b + i, 1);
        }
+    }
+}
 
-      it->pixel_width = cmp->pixel_width;
-      it->ascent = it->phys_ascent = cmp->ascent;
-      it->descent = it->phys_descent = cmp->descent;
 
-      if (face->box != FACE_NO_BOX)
-       {
-         int thick = face->box_line_width;
+#ifdef USE_X_TOOLKIT
 
-         if (thick > 0)
-           {
-             it->ascent += thick;
-             it->descent += thick;
-           }
-         else
-           thick = - thick;
+static struct frame *x_frame_of_widget P_ ((Widget));
+static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
+                                       XrmValue *, XrmValue *, XtPointer *));
+static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
+                               XrmValue *, Cardinal *));
 
-         if (it->start_of_box_run_p)
-           it->pixel_width += thick;
-         if (it->end_of_box_run_p)
-           it->pixel_width += thick;
-       }
 
-      /* If face has an overline, add the height of the overline
-        (1 pixel) and a 1 pixel margin to the character height.  */
-      if (face->overline_p)
-       it->ascent += 2;
+/* Return the frame on which widget WIDGET is used.. Abort if frame
+   cannot be determined.  */
 
-      take_vertical_position_into_account (it);
+static struct frame *
+x_frame_of_widget (widget)
+     Widget widget;
+{
+  struct x_display_info *dpyinfo;
+  Lisp_Object tail;
+  struct frame *f;
 
-      if (it->glyph_row)
-       x_append_composite_glyph (it);
-    }
-  else if (it->what == IT_IMAGE)
-    x_produce_image_glyph (it);
-  else if (it->what == IT_STRETCH)
-    x_produce_stretch_glyph (it);
+  dpyinfo = x_display_info_for_display (XtDisplay (widget));
 
-  /* Accumulate dimensions.  Note: can't assume that it->descent > 0
-     because this isn't true for images with `:ascent 100'.  */
-  xassert (it->ascent >= 0 && it->descent >= 0);
-  if (it->area == TEXT_AREA)
-    it->current_x += it->pixel_width;
+  /* Find the top-level shell of the widget.  Note that this function
+     can be called when the widget is not yet realized, so XtWindow
+     (widget) == 0.  That's the reason we can't simply use
+     x_any_window_to_frame.  */
+  while (!XtIsTopLevelShell (widget))
+    widget = XtParent (widget);
 
-  it->descent += it->extra_line_spacing;
+  /* Look for a frame with that top-level widget.  Allocate the color
+     on that frame to get the right gamma correction value.  */
+  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
+    if (GC_FRAMEP (XCAR (tail))
+       && (f = XFRAME (XCAR (tail)),
+           (f->output_data.nothing != 1
+            && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
+       && f->output_data.x->widget == widget)
+      return f;
 
-  it->max_ascent = max (it->max_ascent, it->ascent);
-  it->max_descent = max (it->max_descent, it->descent);
-  it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
-  it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
+  abort ();
 }
 
 
-/* Estimate the pixel height of the mode or top line on frame F.
-   FACE_ID specifies what line's height to estimate.  */
+/* Allocate the color COLOR->pixel on the screen and display of
+   widget WIDGET in colormap CMAP.  If an exact match cannot be
+   allocated, try the nearest color available.  Value is non-zero
+   if successful.  This is called from lwlib.  */
 
 int
-x_estimate_mode_line_height (f, face_id)
-     struct frame *f;
-     enum face_id face_id;
+x_alloc_nearest_color_for_widget (widget, cmap, color)
+     Widget widget;
+     Colormap cmap;
+     XColor *color;
 {
-  int height = FONT_HEIGHT (FRAME_FONT (f));
-
-  /* This function is called so early when Emacs starts that the face
-     cache and mode line face are not yet initialized.  */
-  if (FRAME_FACE_CACHE (f))
-      {
-       struct face *face = FACE_FROM_ID (f, face_id);
-       if (face)
-         {
-           if (face->font)
-             height = FONT_HEIGHT (face->font);
-           if (face->box_line_width > 0)
-             height += 2 * face->box_line_width;
-         }
-      }
-
-  return height;
+  struct frame *f = x_frame_of_widget (widget);
+  return x_alloc_nearest_color (f, cmap, color);
 }
 
-\f
-/***********************************************************************
-                           Glyph display
- ***********************************************************************/
-
-/* A sequence of glyphs to be drawn in the same face.
 
-   This data structure is not really completely X specific, so it
-   could possibly, at least partially, be useful for other systems.  It
-   is currently not part of the external redisplay interface because
-   it's not clear what other systems will need.  */
+/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
+   or DELTA.  Try a color with RGB values multiplied by FACTOR first.
+   If this produces the same color as PIXEL, try a color where all RGB
+   values have DELTA added.  Return the allocated color in *PIXEL.
+   DISPLAY is the X display, CMAP is the colormap to operate on.
+   Value is non-zero if successful.  */
 
-struct glyph_string
+int
+x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
+     Widget widget;
+     Display *display;
+     Colormap cmap;
+     unsigned long *pixel;
+     double factor;
+     int delta;
 {
-  /* X-origin of the string.  */
-  int x;
-
-  /* Y-origin and y-position of the base line of this string.  */
-  int y, ybase;
+  struct frame *f = x_frame_of_widget (widget);
+  return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
+}
 
-  /* The width of the string, not including a face extension.  */
-  int width;
 
-  /* The width of the string, including a face extension.  */
-  int background_width;
+/* Structure specifying which arguments should be passed by Xt to
+   cvt_string_to_pixel.  We want the widget's screen and colormap.  */
 
-  /* The height of this string.  This is the height of the line this
-     string is drawn in, and can be different from the height of the
-     font the string is drawn in.  */
-  int height;
+static XtConvertArgRec cvt_string_to_pixel_args[] =
+  {
+    {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
+     sizeof (Screen *)},
+    {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
+     sizeof (Colormap)}
+  };
 
-  /* Number of pixels this string overwrites in front of its x-origin.
-     This number is zero if the string has an lbearing >= 0; it is
-     -lbearing, if the string has an lbearing < 0.  */
-  int left_overhang;
 
-  /* Number of pixels this string overwrites past its right-most
-     nominal x-position, i.e. x + width.  Zero if the string's
-     rbearing is <= its nominal width, rbearing - width otherwise.  */
-  int right_overhang;
+/* The address of this variable is returned by
+   cvt_string_to_pixel.  */
 
-  /* The frame on which the glyph string is drawn.  */
-  struct frame *f;
+static Pixel cvt_string_to_pixel_value;
 
-  /* The window on which the glyph string is drawn.  */
-  struct window *w;
 
-  /* X display and window for convenience.  */
-  Display *display;
-  Window window;
+/* Convert a color name to a pixel color.
 
-  /* The glyph row for which this string was built.  It determines the
-     y-origin and height of the string.  */
-  struct glyph_row *row;
+   DPY is the display we are working on.
 
-  /* The area within row.  */
-  enum glyph_row_area area;
+   ARGS is an array of *NARGS XrmValue structures holding additional
+   information about the widget for which the conversion takes place.
+   The contents of this array are determined by the specification
+   in cvt_string_to_pixel_args.
 
-  /* Characters to be drawn, and number of characters.  */
-  XChar2b *char2b;
-  int nchars;
+   FROM is a pointer to an XrmValue which points to the color name to
+   convert.  TO is an XrmValue in which to return the pixel color.
 
-  /* A face-override for drawing cursors, mouse face and similar.  */
-  enum draw_glyphs_face hl;
+   CLOSURE_RET is a pointer to user-data, in which we record if
+   we allocated the color or not.
 
-  /* Face in which this string is to be drawn.  */
-  struct face *face;
+   Value is True if successful, False otherwise.  */
 
-  /* Font in which this string is to be drawn.  */
-  XFontStruct *font;
+static Boolean
+cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
+     Display *dpy;
+     XrmValue *args;
+     Cardinal *nargs;
+     XrmValue *from, *to;
+     XtPointer *closure_ret;
+{
+  Screen *screen;
+  Colormap cmap;
+  Pixel pixel;
+  String color_name;
+  XColor color;
 
-  /* Font info for this string.  */
-  struct font_info *font_info;
-
-  /* Non-null means this string describes (part of) a composition.
-     All characters from char2b are drawn composed.  */
-  struct composition *cmp;
-
-  /* Index of this glyph string's first character in the glyph
-     definition of CMP.  If this is zero, this glyph string describes
-     the first character of a composition.  */
-  int gidx;
-
-  /* 1 means this glyph strings face has to be drawn to the right end
-     of the window's drawing area.  */
-  unsigned extends_to_end_of_line_p : 1;
+  if (*nargs != 2)
+    {
+      XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
+                      "wrongParameters", "cvt_string_to_pixel",
+                      "XtToolkitError",
+                      "Screen and colormap args required", NULL, NULL);
+      return False;
+    }
 
-  /* 1 means the background of this string has been drawn.  */
-  unsigned background_filled_p : 1;
+  screen = *(Screen **) args[0].addr;
+  cmap = *(Colormap *) args[1].addr;
+  color_name = (String) from->addr;
 
-  /* 1 means glyph string must be drawn with 16-bit functions.  */
-  unsigned two_byte_p : 1;
+  if (strcmp (color_name, XtDefaultBackground) == 0)
+    {
+      *closure_ret = (XtPointer) False;
+      pixel = WhitePixelOfScreen (screen);
+    }
+  else if (strcmp (color_name, XtDefaultForeground) == 0)
+    {
+      *closure_ret = (XtPointer) False;
+      pixel = BlackPixelOfScreen (screen);
+    }
+  else if (XParseColor (dpy, cmap, color_name, &color)
+          && x_alloc_nearest_color_1 (dpy, cmap, &color))
+    {
+      pixel = color.pixel;
+      *closure_ret = (XtPointer) True;
+    }
+  else
+    {
+      String params[1];
+      Cardinal nparams = 1;
 
-  /* 1 means that the original font determined for drawing this glyph
-     string could not be loaded.  The member `font' has been set to
-     the frame's default font in this case.  */
-  unsigned font_not_found_p : 1;
+      params[0] = color_name;
+      XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
+                      "badValue", "cvt_string_to_pixel",
+                      "XtToolkitError", "Invalid color `%s'",
+                      params, &nparams);
+      return False;
+    }
 
-  /* 1 means that the face in which this glyph string is drawn has a
-     stipple pattern.  */
-  unsigned stippled_p : 1;
+  if (to->addr != NULL)
+    {
+      if (to->size < sizeof (Pixel))
+       {
+         to->size = sizeof (Pixel);
+         return False;
+       }
 
-  /* 1 means only the foreground of this glyph string must be drawn,
-     and we should use the physical height of the line this glyph
-     string appears in as clip rect.  */
-  unsigned for_overlaps_p : 1;
+      *(Pixel *) to->addr = pixel;
+    }
+  else
+    {
+      cvt_string_to_pixel_value = pixel;
+      to->addr = (XtPointer) &cvt_string_to_pixel_value;
+    }
 
-  /* The GC to use for drawing this glyph string.  */
-  GC gc;
+  to->size = sizeof (Pixel);
+  return True;
+}
 
-  /* A pointer to the first glyph in the string.  This glyph
-     corresponds to char2b[0].  Needed to draw rectangles if
-     font_not_found_p is 1.  */
-  struct glyph *first_glyph;
 
-  /* Image, if any.  */
-  struct image *img;
+/* Free a pixel color which was previously allocated via
+   cvt_string_to_pixel.  This is registered as the destructor
+   for this type of resource via XtSetTypeConverter.
 
-  struct glyph_string *next, *prev;
-};
+   APP is the application context in which we work.
 
+   TO is a pointer to an XrmValue holding the color to free.
+   CLOSURE is the value we stored in CLOSURE_RET for this color
+   in cvt_string_to_pixel.
 
-#if GLYPH_DEBUG
+   ARGS and NARGS are like for cvt_string_to_pixel.  */
 
 static void
-x_dump_glyph_string (s)
-     struct glyph_string *s;
+cvt_pixel_dtor (app, to, closure, args, nargs)
+    XtAppContext app;
+    XrmValuePtr to;
+    XtPointer closure;
+    XrmValuePtr args;
+    Cardinal *nargs;
 {
-  fprintf (stderr, "glyph string\n");
-  fprintf (stderr, "  x, y, w, h = %d, %d, %d, %d\n",
-          s->x, s->y, s->width, s->height);
-  fprintf (stderr, "  ybase = %d\n", s->ybase);
-  fprintf (stderr, "  hl = %d\n", s->hl);
-  fprintf (stderr, "  left overhang = %d, right = %d\n",
-          s->left_overhang, s->right_overhang);
-  fprintf (stderr, "  nchars = %d\n", s->nchars);
-  fprintf (stderr, "  extends to end of line = %d\n",
-          s->extends_to_end_of_line_p);
-  fprintf (stderr, "  font height = %d\n", FONT_HEIGHT (s->font));
-  fprintf (stderr, "  bg width = %d\n", s->background_width);
-}
-
-#endif /* GLYPH_DEBUG */
-
-
-
-static void x_append_glyph_string_lists P_ ((struct glyph_string **,
-                                            struct glyph_string **,
-                                            struct glyph_string *,
-                                            struct glyph_string *));
-static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
-                                             struct glyph_string **,
-                                             struct glyph_string *,
-                                             struct glyph_string *));
-static void x_append_glyph_string P_ ((struct glyph_string **,
-                                      struct glyph_string **,
-                                      struct glyph_string *));
-static int x_left_overwritten P_ ((struct glyph_string *));
-static int x_left_overwriting P_ ((struct glyph_string *));
-static int x_right_overwritten P_ ((struct glyph_string *));
-static int x_right_overwriting P_ ((struct glyph_string *));
-static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
-                                   int));
-static void x_init_glyph_string P_ ((struct glyph_string *,
-                                       XChar2b *, struct window *,
-                                       struct glyph_row *,
-                                       enum glyph_row_area, int,
-                                       enum draw_glyphs_face));
-static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
-                             enum glyph_row_area, int, int,
-                             enum draw_glyphs_face, int));
-static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
-static void x_set_glyph_string_gc P_ ((struct glyph_string *));
-static void x_draw_glyph_string_background P_ ((struct glyph_string *,
-                                               int));
-static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
-static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
-static void x_draw_glyph_string_box P_ ((struct glyph_string *));
-static void x_draw_glyph_string  P_ ((struct glyph_string *));
-static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
-static void x_set_cursor_gc P_ ((struct glyph_string *));
-static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
-static void x_set_mouse_face_gc P_ ((struct glyph_string *));
-static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
-                                      int *, int *));
-static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
-static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
-                                     unsigned long *, double, int));
-static void x_setup_relief_color P_ ((struct frame *, struct relief *,
-                                     double, int, unsigned long));
-static void x_setup_relief_colors P_ ((struct glyph_string *));
-static void x_draw_image_glyph_string P_ ((struct glyph_string *));
-static void x_draw_image_relief P_ ((struct glyph_string *));
-static void x_draw_image_foreground P_ ((struct glyph_string *));
-static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
-static void x_fill_image_glyph_string P_ ((struct glyph_string *));
-static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
-                                          int, int, int));
-static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
-                                   int, int, int, int, XRectangle *));
-static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
-                                int, int, int, XRectangle *));
-static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
-                                       enum glyph_row_area));
-static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
-                                           struct glyph_row *,
-                                           enum glyph_row_area, int, int));
+  if (*nargs != 2)
+    {
+      XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
+                      "XtToolkitError",
+                      "Screen and colormap arguments required",
+                      NULL, NULL);
+    }
+  else if (closure != NULL)
+    {
+      /* We did allocate the pixel, so free it.  */
+      Screen *screen = *(Screen **) args[0].addr;
+      Colormap cmap = *(Colormap *) args[1].addr;
+      x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
+                        (Pixel *) to->addr, 1);
+    }
+}
 
-#if GLYPH_DEBUG
-static void x_check_font P_ ((struct frame *, XFontStruct *));
-#endif
 
+#endif /* USE_X_TOOLKIT */
 
-/* Append the list of glyph strings with head H and tail T to the list
-   with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the result.  */
 
-static INLINE void
-x_append_glyph_string_lists (head, tail, h, t)
-     struct glyph_string **head, **tail;
-     struct glyph_string *h, *t;
+/* Value is an array of XColor structures for the contents of the
+   color map of display DPY.  Set *NCELLS to the size of the array.
+   Note that this probably shouldn't be called for large color maps,
+   say a 24-bit TrueColor map.  */
+
+static const XColor *
+x_color_cells (dpy, ncells)
+     Display *dpy;
+     int *ncells;
 {
-  if (h)
+  struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
+
+  if (dpyinfo->color_cells == NULL)
     {
-      if (*head)
-       (*tail)->next = h;
-      else
-       *head = h;
-      h->prev = *tail;
-      *tail = t;
+      Screen *screen = dpyinfo->screen;
+      int i;
+
+      dpyinfo->ncolor_cells
+       = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
+      dpyinfo->color_cells
+       = (XColor *) xmalloc (dpyinfo->ncolor_cells
+                             * sizeof *dpyinfo->color_cells);
+
+      for (i = 0; i < dpyinfo->ncolor_cells; ++i)
+       dpyinfo->color_cells[i].pixel = i;
+
+      XQueryColors (dpy, dpyinfo->cmap,
+                   dpyinfo->color_cells, dpyinfo->ncolor_cells);
     }
+
+  *ncells = dpyinfo->ncolor_cells;
+  return dpyinfo->color_cells;
 }
 
 
-/* Prepend the list of glyph strings with head H and tail T to the
-   list with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the
-   result.  */
+/* On frame F, translate pixel colors to RGB values for the NCOLORS
+   colors in COLORS.  Use cached information, if available.  */
 
-static INLINE void
-x_prepend_glyph_string_lists (head, tail, h, t)
-     struct glyph_string **head, **tail;
-     struct glyph_string *h, *t;
+void
+x_query_colors (f, colors, ncolors)
+     struct frame *f;
+     XColor *colors;
+     int ncolors;
 {
-  if (h)
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+  if (dpyinfo->color_cells)
     {
-      if (*head)
-       (*head)->prev = t;
-      else
-       *tail = t;
-      t->next = *head;
-      *head = h;
+      int i;
+      for (i = 0; i < ncolors; ++i)
+       {
+         unsigned long pixel = colors[i].pixel;
+         xassert (pixel < dpyinfo->ncolor_cells);
+         xassert (dpyinfo->color_cells[pixel].pixel == pixel);
+         colors[i] = dpyinfo->color_cells[pixel];
+       }
     }
+  else
+    XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
 }
 
 
-/* Append glyph string S to the list with head *HEAD and tail *TAIL.
-   Set *HEAD and *TAIL to the resulting list.  */
+/* On frame F, translate pixel color to RGB values for the color in
+   COLOR.  Use cached information, if available.  */
 
-static INLINE void
-x_append_glyph_string (head, tail, s)
-     struct glyph_string **head, **tail;
-     struct glyph_string *s;
+void
+x_query_color (f, color)
+     struct frame *f;
+     XColor *color;
 {
-  s->next = s->prev = NULL;
-  x_append_glyph_string_lists (head, tail, s, s);
+  x_query_colors (f, color, 1);
 }
 
 
-/* Set S->gc to a suitable GC for drawing glyph string S in cursor
-   face.  */
+/* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP.  If an
+   exact match can't be allocated, try the nearest color available.
+   Value is non-zero if successful.  Set *COLOR to the color
+   allocated.  */
 
-static void
-x_set_cursor_gc (s)
-     struct glyph_string *s;
+static int
+x_alloc_nearest_color_1 (dpy, cmap, color)
+     Display *dpy;
+     Colormap cmap;
+     XColor *color;
 {
-  if (s->font == FRAME_FONT (s->f)
-      && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
-      && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
-      && !s->cmp)
-    s->gc = s->f->output_data.x->cursor_gc;
-  else
-    {
-      /* Cursor on non-default face: must merge.  */
-      XGCValues xgcv;
-      unsigned long mask;
-
-      xgcv.background = s->f->output_data.x->cursor_pixel;
-      xgcv.foreground = s->face->background;
+  int rc;
 
-      /* If the glyph would be invisible, try a different foreground.  */
-      if (xgcv.foreground == xgcv.background)
-       xgcv.foreground = s->face->foreground;
-      if (xgcv.foreground == xgcv.background)
-       xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
-      if (xgcv.foreground == xgcv.background)
-       xgcv.foreground = s->face->foreground;
+  rc = XAllocColor (dpy, cmap, color);
+  if (rc == 0)
+    {
+      /* If we got to this point, the colormap is full, so we're going
+        to try to get the next closest color.  The algorithm used is
+        a least-squares matching, which is what X uses for closest
+        color matching with StaticColor visuals.  */
+      int nearest, i;
+      unsigned long nearest_delta = ~0;
+      int ncells;
+      const XColor *cells = x_color_cells (dpy, &ncells);
 
-      /* Make sure the cursor is distinct from text in this face.  */
-      if (xgcv.background == s->face->background
-         && xgcv.foreground == s->face->foreground)
+      for (nearest = i = 0; i < ncells; ++i)
        {
-         xgcv.background = s->face->foreground;
-         xgcv.foreground = s->face->background;
-       }
+         long dred   = (color->red   >> 8) - (cells[i].red   >> 8);
+         long dgreen = (color->green >> 8) - (cells[i].green >> 8);
+         long dblue  = (color->blue  >> 8) - (cells[i].blue  >> 8);
+         unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
 
-      IF_DEBUG (x_check_font (s->f, s->font));
-      xgcv.font = s->font->fid;
-      xgcv.graphics_exposures = False;
-      mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
+         if (delta < nearest_delta)
+           {
+             nearest = i;
+             nearest_delta = delta;
+           }
+       }
 
-      if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
-       XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
-                  mask, &xgcv);
-      else
-       FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
-         = XCreateGC (s->display, s->window, mask, &xgcv);
-
-      s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
+      color->red   = cells[nearest].red;
+      color->green = cells[nearest].green;
+      color->blue  = cells[nearest].blue;
+      rc = XAllocColor (dpy, cmap, color);
     }
-}
-
-
-/* Set up S->gc of glyph string S for drawing text in mouse face.  */
-
-static void
-x_set_mouse_face_gc (s)
-     struct glyph_string *s;
-{
-  int face_id;
-  struct face *face;
-
-  /* What face has to be used last for the mouse face?  */
-  face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
-  face = FACE_FROM_ID (s->f, face_id);
-  if (face == NULL)
-    face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
-
-  if (s->first_glyph->type == CHAR_GLYPH)
-    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
-  else
-    face_id = FACE_FOR_CHAR (s->f, face, 0);
-  s->face = FACE_FROM_ID (s->f, face_id);
-  PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
-
-  /* If font in this face is same as S->font, use it.  */
-  if (s->font == s->face->font)
-    s->gc = s->face->gc;
   else
     {
-      /* Otherwise construct scratch_cursor_gc with values from FACE
-        but font FONT.  */
-      XGCValues xgcv;
-      unsigned long mask;
-
-      xgcv.background = s->face->background;
-      xgcv.foreground = s->face->foreground;
-      IF_DEBUG (x_check_font (s->f, s->font));
-      xgcv.font = s->font->fid;
-      xgcv.graphics_exposures = False;
-      mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
-
-      if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
-       XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
-                  mask, &xgcv);
-      else
-       FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
-         = XCreateGC (s->display, s->window, mask, &xgcv);
+      /* If allocation succeeded, and the allocated pixel color is not
+         equal to a cached pixel color recorded earlier, there was a
+         change in the colormap, so clear the color cache.  */
+      struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
+      XColor *cached_color;
 
-      s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
+      if (dpyinfo->color_cells
+         && (cached_color = &dpyinfo->color_cells[color->pixel],
+             (cached_color->red != color->red
+              || cached_color->blue != color->blue
+              || cached_color->green != color->green)))
+       {
+         xfree (dpyinfo->color_cells);
+         dpyinfo->color_cells = NULL;
+         dpyinfo->ncolor_cells = 0;
+       }
     }
 
-  xassert (s->gc != 0);
+#ifdef DEBUG_X_COLORS
+  if (rc)
+    register_color (color->pixel);
+#endif /* DEBUG_X_COLORS */
+
+  return rc;
 }
 
 
-/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
-   Faces to use in the mode line have already been computed when the
-   matrix was built, so there isn't much to do, here.  */
+/* Allocate the color COLOR->pixel on frame F, colormap CMAP.  If an
+   exact match can't be allocated, try the nearest color available.
+   Value is non-zero if successful.  Set *COLOR to the color
+   allocated.  */
 
-static INLINE void
-x_set_mode_line_face_gc (s)
-     struct glyph_string *s;
+int
+x_alloc_nearest_color (f, cmap, color)
+     struct frame *f;
+     Colormap cmap;
+     XColor *color;
 {
-  s->gc = s->face->gc;
+  gamma_correct (f, color);
+  return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
 }
 
 
-/* Set S->gc of glyph string S for drawing that glyph string.  Set
-   S->stippled_p to a non-zero value if the face of S has a stipple
-   pattern.  */
+/* Allocate color PIXEL on frame F.  PIXEL must already be allocated.
+   It's necessary to do this instead of just using PIXEL directly to
+   get color reference counts right.  */
 
-static INLINE void
-x_set_glyph_string_gc (s)
-     struct glyph_string *s;
+unsigned long
+x_copy_color (f, pixel)
+     struct frame *f;
+     unsigned long pixel;
 {
-  PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
-
-  if (s->hl == DRAW_NORMAL_TEXT)
-    {
-      s->gc = s->face->gc;
-      s->stippled_p = s->face->stipple != 0;
-    }
-  else if (s->hl == DRAW_INVERSE_VIDEO)
-    {
-      x_set_mode_line_face_gc (s);
-      s->stippled_p = s->face->stipple != 0;
-    }
-  else if (s->hl == DRAW_CURSOR)
-    {
-      x_set_cursor_gc (s);
-      s->stippled_p = 0;
-    }
-  else if (s->hl == DRAW_MOUSE_FACE)
-    {
-      x_set_mouse_face_gc (s);
-      s->stippled_p = s->face->stipple != 0;
-    }
-  else if (s->hl == DRAW_IMAGE_RAISED
-          || s->hl == DRAW_IMAGE_SUNKEN)
-    {
-      s->gc = s->face->gc;
-      s->stippled_p = s->face->stipple != 0;
-    }
-  else
-    {
-      s->gc = s->face->gc;
-      s->stippled_p = s->face->stipple != 0;
-    }
+  XColor color;
 
-  /* GC must have been set.  */
-  xassert (s->gc != 0);
+  color.pixel = pixel;
+  BLOCK_INPUT;
+  x_query_color (f, &color);
+  XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
+  UNBLOCK_INPUT;
+#ifdef DEBUG_X_COLORS
+  register_color (pixel);
+#endif
+  return color.pixel;
 }
 
 
-/* Return in *R the clipping rectangle for glyph string S.  */
+/* Allocate color PIXEL on display DPY.  PIXEL must already be allocated.
+   It's necessary to do this instead of just using PIXEL directly to
+   get color reference counts right.  */
 
-static void
-x_get_glyph_string_clip_rect (s, r)
-     struct glyph_string *s;
-     XRectangle *r;
+unsigned long
+x_copy_dpy_color (dpy, cmap, pixel)
+     Display *dpy;
+     Colormap cmap;
+     unsigned long pixel;
 {
-  if (s->row->full_width_p)
-    {
-      /* Draw full-width.  X coordinates are relative to S->w->left.  */
-      int canon_x = CANON_X_UNIT (s->f);
-
-      r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
-      r->width = XFASTINT (s->w->width) * canon_x;
-
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
-       {
-         int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
-         if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
-           r->x -= width;
-       }
+  XColor color;
 
-      r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
+  color.pixel = pixel;
+  BLOCK_INPUT;
+  XQueryColor (dpy, cmap, &color);
+  XAllocColor (dpy, cmap, &color);
+  UNBLOCK_INPUT;
+#ifdef DEBUG_X_COLORS
+  register_color (pixel);
+#endif
+  return color.pixel;
+}
 
-      /* Unless displaying a mode or menu bar line, which are always
-        fully visible, clip to the visible part of the row.  */
-      if (s->w->pseudo_window_p)
-       r->height = s->row->visible_height;
-      else
-       r->height = s->height;
-    }
-  else
-    {
-      /* This is a text line that may be partially visible.  */
-      r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
-      r->width = window_box_width (s->w, s->area);
-      r->height = s->row->visible_height;
-    }
 
-  /* If S draws overlapping rows, it's sufficient to use the top and
-     bottom of the window for clipping because this glyph string
-     intentionally draws over other lines.  */
-  if (s->for_overlaps_p)
-    {
-      r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
-      r->height = window_text_bottom_y (s->w) - r->y;
-    }
-  else
-    {
-      /* Don't use S->y for clipping because it doesn't take partially
-        visible lines into account.  For example, it can be negative for
-        partially visible lines at the top of a window.  */
-      if (!s->row->full_width_p
-         && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
-       r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
-      else
-       r->y = max (0, s->row->y);
+/* Brightness beyond which a color won't have its highlight brightness
+   boosted.
 
-      /* If drawing a tool-bar window, draw it over the internal border
-        at the top of the window.  */
-      if (s->w == XWINDOW (s->f->tool_bar_window))
-       r->y -= s->f->output_data.x->internal_border_width;
-    }
+   Nominally, highlight colors for `3d' faces are calculated by
+   brightening an object's color by a constant scale factor, but this
+   doesn't yield good results for dark colors, so for colors who's
+   brightness is less than this value (on a scale of 0-65535) have an
+   use an additional additive factor.
 
-  r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
-}
+   The value here is set so that the default menu-bar/mode-line color
+   (grey75) will not have its highlights changed at all.  */
+#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
 
 
-/* Set clipping for output of glyph string S.  S may be part of a mode
-   line or menu if we don't have X toolkit support.  */
+/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
+   or DELTA.  Try a color with RGB values multiplied by FACTOR first.
+   If this produces the same color as PIXEL, try a color where all RGB
+   values have DELTA added.  Return the allocated color in *PIXEL.
+   DISPLAY is the X display, CMAP is the colormap to operate on.
+   Value is non-zero if successful.  */
 
-static INLINE void
-x_set_glyph_string_clipping (s)
-     struct glyph_string *s;
+static int
+x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
+     struct frame *f;
+     Display *display;
+     Colormap cmap;
+     unsigned long *pixel;
+     double factor;
+     int delta;
 {
-  XRectangle r;
-  x_get_glyph_string_clip_rect (s, &r);
-  XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
-}
-
-
-/* Compute left and right overhang of glyph string S.  If S is a glyph
-   string for a composition, assume overhangs don't exist.  */
+  XColor color, new;
+  long bright;
+  int success_p;
 
-static INLINE void
-x_compute_glyph_string_overhangs (s)
-     struct glyph_string *s;
-{
-  if (s->cmp == NULL
-      && s->first_glyph->type == CHAR_GLYPH)
-    {
-      XCharStruct cs;
-      int direction, font_ascent, font_descent;
-      XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
-                     &font_ascent, &font_descent, &cs);
-      s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
-      s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
-    }
-}
+  /* Get RGB color values.  */
+  color.pixel = *pixel;
+  x_query_color (f, &color);
 
+  /* Change RGB values by specified FACTOR.  Avoid overflow!  */
+  xassert (factor >= 0);
+  new.red = min (0xffff, factor * color.red);
+  new.green = min (0xffff, factor * color.green);
+  new.blue = min (0xffff, factor * color.blue);
 
-/* Compute overhangs and x-positions for glyph string S and its
-   predecessors, or successors.  X is the starting x-position for S.
-   BACKWARD_P non-zero means process predecessors.  */
+  /* Calculate brightness of COLOR.  */
+  bright = (2 * color.red + 3 * color.green + color.blue) / 6;
 
-static void
-x_compute_overhangs_and_x (s, x, backward_p)
-     struct glyph_string *s;
-     int x;
-     int backward_p;
-{
-  if (backward_p)
+  /* We only boost colors that are darker than
+     HIGHLIGHT_COLOR_DARK_BOOST_LIMIT.  */
+  if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
+    /* Make an additive adjustment to NEW, because it's dark enough so
+       that scaling by FACTOR alone isn't enough.  */
     {
-      while (s)
+      /* How far below the limit this color is (0 - 1, 1 being darker).  */
+      double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
+      /* The additive adjustment.  */
+      int min_delta = delta * dimness * factor / 2;
+
+      if (factor < 1)
+       {
+         new.red =   max (0, new.red -   min_delta);
+         new.green = max (0, new.green - min_delta);
+         new.blue =  max (0, new.blue -  min_delta);
+       }
+      else
        {
-         x_compute_glyph_string_overhangs (s);
-         x -= s->width;
-         s->x = x;
-         s = s->prev;
+         new.red =   min (0xffff, min_delta + new.red);
+         new.green = min (0xffff, min_delta + new.green);
+         new.blue =  min (0xffff, min_delta + new.blue);
        }
     }
-  else
+
+  /* Try to allocate the color.  */
+  success_p = x_alloc_nearest_color (f, cmap, &new);
+  if (success_p)
     {
-      while (s)
+      if (new.pixel == *pixel)
        {
-         x_compute_glyph_string_overhangs (s);
-         s->x = x;
-         x += s->width;
-         s = s->next;
+         /* If we end up with the same color as before, try adding
+            delta to the RGB values.  */
+         x_free_colors (f, &new.pixel, 1);
+
+         new.red = min (0xffff, delta + color.red);
+         new.green = min (0xffff, delta + color.green);
+         new.blue = min (0xffff, delta + color.blue);
+         success_p = x_alloc_nearest_color (f, cmap, &new);
        }
+      else
+       success_p = 1;
+      *pixel = new.pixel;
     }
+
+  return success_p;
 }
 
 
-/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
-   frame F.  Overhangs of glyphs other than type CHAR_GLYPH are
-   assumed to be zero.  */
+/* Set up the foreground color for drawing relief lines of glyph
+   string S.  RELIEF is a pointer to a struct relief containing the GC
+   with which lines will be drawn.  Use a color that is FACTOR or
+   DELTA lighter or darker than the relief's background which is found
+   in S->f->output_data.x->relief_background.  If such a color cannot
+   be allocated, use DEFAULT_PIXEL, instead.  */
 
 static void
-x_get_glyph_overhangs (glyph, f, left, right)
-     struct glyph *glyph;
+x_setup_relief_color (f, relief, factor, delta, default_pixel)
      struct frame *f;
-     int *left, *right;
+     struct relief *relief;
+     double factor;
+     int delta;
+     unsigned long default_pixel;
 {
-  *left = *right = 0;
+  XGCValues xgcv;
+  struct x_output *di = f->output_data.x;
+  unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
+  unsigned long pixel;
+  unsigned long background = di->relief_background;
+  Colormap cmap = FRAME_X_COLORMAP (f);
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  Display *dpy = FRAME_X_DISPLAY (f);
 
-  if (glyph->type == CHAR_GLYPH)
-    {
-      XFontStruct *font;
-      struct face *face;
-      struct font_info *font_info;
-      XChar2b char2b;
-      XCharStruct *pcm;
+  xgcv.graphics_exposures = False;
+  xgcv.line_width = 1;
 
-      face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
-      font = face->font;
-      font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
-      if (font
-         && (pcm = x_per_char_metric (font, &char2b)))
-       {
-         if (pcm->rbearing > pcm->width)
-           *right = pcm->rbearing - pcm->width;
-         if (pcm->lbearing < 0)
-           *left = -pcm->lbearing;
-       }
+  /* Free previously allocated color.  The color cell will be reused
+     when it has been freed as many times as it was allocated, so this
+     doesn't affect faces using the same colors.  */
+  if (relief->gc
+      && relief->allocated_p)
+    {
+      x_free_colors (f, &relief->pixel, 1);
+      relief->allocated_p = 0;
     }
-}
-
-
-/* Return the index of the first glyph preceding glyph string S that
-   is overwritten by S because of S's left overhang.  Value is -1
-   if no glyphs are overwritten.  */
-
-static int
-x_left_overwritten (s)
-     struct glyph_string *s;
-{
-  int k;
 
-  if (s->left_overhang)
+  /* Allocate new color.  */
+  xgcv.foreground = default_pixel;
+  pixel = background;
+  if (dpyinfo->n_planes != 1
+      && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
     {
-      int x = 0, i;
-      struct glyph *glyphs = s->row->glyphs[s->area];
-      int first = s->first_glyph - glyphs;
-
-      for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
-       x -= glyphs[i].pixel_width;
+      relief->allocated_p = 1;
+      xgcv.foreground = relief->pixel = pixel;
+    }
 
-      k = i + 1;
+  if (relief->gc == 0)
+    {
+      xgcv.stipple = dpyinfo->gray;
+      mask |= GCStipple;
+      relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
     }
   else
-    k = -1;
-
-  return k;
+    XChangeGC (dpy, relief->gc, mask, &xgcv);
 }
 
 
-/* Return the index of the first glyph preceding glyph string S that
-   is overwriting S because of its right overhang.  Value is -1 if no
-   glyph in front of S overwrites S.  */
+/* Set up colors for the relief lines around glyph string S.  */
 
-static int
-x_left_overwriting (s)
+static void
+x_setup_relief_colors (s)
      struct glyph_string *s;
 {
-  int i, k, x;
-  struct glyph *glyphs = s->row->glyphs[s->area];
-  int first = s->first_glyph - glyphs;
+  struct x_output *di = s->f->output_data.x;
+  unsigned long color;
 
-  k = -1;
-  x = 0;
-  for (i = first - 1; i >= 0; --i)
+  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
     {
-      int left, right;
-      x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
-      if (x + right > 0)
-       k = i;
-      x -= glyphs[i].pixel_width;
+      XGCValues xgcv;
+
+      /* Get the background color of the face.  */
+      XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
+      color = xgcv.background;
     }
 
-  return k;
+  if (di->white_relief.gc == 0
+      || color != di->relief_background)
+    {
+      di->relief_background = color;
+      x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
+                           WHITE_PIX_DEFAULT (s->f));
+      x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
+                           BLACK_PIX_DEFAULT (s->f));
+    }
 }
 
 
-/* Return the index of the last glyph following glyph string S that is
-   not overwritten by S because of S's right overhang.  Value is -1 if
-   no such glyph is found.  */
+/* Draw a relief on frame F inside the rectangle given by LEFT_X,
+   TOP_Y, RIGHT_X, and BOTTOM_Y.  WIDTH is the thickness of the relief
+   to draw, it must be >= 0.  RAISED_P non-zero means draw a raised
+   relief.  LEFT_P non-zero means draw a relief on the left side of
+   the rectangle.  RIGHT_P non-zero means draw a relief on the right
+   side of the rectangle.  CLIP_RECT is the clipping rectangle to use
+   when drawing.  */
 
-static int
-x_right_overwritten (s)
-     struct glyph_string *s;
+static void
+x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
+                   raised_p, left_p, right_p, clip_rect)
+     struct frame *f;
+     int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
+     XRectangle *clip_rect;
 {
-  int k = -1;
+  Display *dpy = FRAME_X_DISPLAY (f);
+  Window window = FRAME_X_WINDOW (f);
+  int i;
+  GC gc;
 
-  if (s->right_overhang)
-    {
-      int x = 0, i;
-      struct glyph *glyphs = s->row->glyphs[s->area];
-      int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
-      int end = s->row->used[s->area];
+  if (raised_p)
+    gc = f->output_data.x->white_relief.gc;
+  else
+    gc = f->output_data.x->black_relief.gc;
+  XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
+
+  /* Top.  */
+  for (i = 0; i < width; ++i)
+    XDrawLine (dpy, window, gc,
+              left_x + i * left_p, top_y + i,
+              right_x + 1 - i * right_p, top_y + i);
 
-      for (i = first; i < end && s->right_overhang > x; ++i)
-       x += glyphs[i].pixel_width;
+  /* Left.  */
+  if (left_p)
+    for (i = 0; i < width; ++i)
+      XDrawLine (dpy, window, gc,
+                left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
 
-      k = i;
-    }
+  XSetClipMask (dpy, gc, None);
+  if (raised_p)
+    gc = f->output_data.x->black_relief.gc;
+  else
+    gc = f->output_data.x->white_relief.gc;
+  XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
+
+  /* Bottom.  */
+  for (i = 0; i < width; ++i)
+    XDrawLine (dpy, window, gc,
+              left_x + i * left_p, bottom_y - i,
+              right_x + 1 - i * right_p, bottom_y - i);
+
+  /* Right.  */
+  if (right_p)
+    for (i = 0; i < width; ++i)
+      XDrawLine (dpy, window, gc,
+                right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
 
-  return k;
+  XSetClipMask (dpy, gc, None);
 }
 
 
-/* Return the index of the last glyph following glyph string S that
-   overwrites S because of its left overhang.  Value is negative
-   if no such glyph is found.  */
+/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
+   RIGHT_X, and BOTTOM_Y.  WIDTH is the thickness of the lines to
+   draw, it must be >= 0.  LEFT_P non-zero means draw a line on the
+   left side of the rectangle.  RIGHT_P non-zero means draw a line
+   on the right side of the rectangle.  CLIP_RECT is the clipping
+   rectangle to use when drawing.  */
 
-static int
-x_right_overwriting (s)
+static void
+x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
+                left_p, right_p, clip_rect)
      struct glyph_string *s;
+     int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
+     XRectangle *clip_rect;
 {
-  int i, k, x;
-  int end = s->row->used[s->area];
-  struct glyph *glyphs = s->row->glyphs[s->area];
-  int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+  XGCValues xgcv;
 
-  k = -1;
-  x = 0;
-  for (i = first; i < end; ++i)
-    {
-      int left, right;
-      x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
-      if (x - left < 0)
-       k = i;
-      x += glyphs[i].pixel_width;
-    }
+  XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+  XSetForeground (s->display, s->gc, s->face->box_color);
+  XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
 
-  return k;
-}
+  /* Top.  */
+  XFillRectangle (s->display, s->window, s->gc,
+                 left_x, top_y, right_x - left_x + 1, width);
 
+  /* Left.  */
+  if (left_p)
+    XFillRectangle (s->display, s->window, s->gc,
+                   left_x, top_y, width, bottom_y - top_y + 1);
 
-/* Fill rectangle X, Y, W, H with background color of glyph string S.  */
+  /* Bottom.  */
+  XFillRectangle (s->display, s->window, s->gc,
+                 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
+
+  /* Right.  */
+  if (right_p)
+    XFillRectangle (s->display, s->window, s->gc,
+                   right_x - width + 1, top_y, width, bottom_y - top_y + 1);
 
-static INLINE void
-x_clear_glyph_string_rect (s, x, y, w, h)
-     struct glyph_string *s;
-     int x, y, w, h;
-{
-  XGCValues xgcv;
-  XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
-  XSetForeground (s->display, s->gc, xgcv.background);
-  XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
   XSetForeground (s->display, s->gc, xgcv.foreground);
+  XSetClipMask (s->display, s->gc, None);
 }
 
 
-/* Draw the background of glyph_string S.  If S->background_filled_p
-   is non-zero don't draw it.  FORCE_P non-zero means draw the
-   background even if it wouldn't be drawn normally.  This is used
-   when a string preceding S draws into the background of S, or S
-   contains the first component of a composition.  */
+/* Draw a box around glyph string S.  */
 
 static void
-x_draw_glyph_string_background (s, force_p)
+x_draw_glyph_string_box (s)
      struct glyph_string *s;
-     int force_p;
 {
-  /* Nothing to do if background has already been drawn or if it
-     shouldn't be drawn in the first place.  */
-  if (!s->background_filled_p)
+  int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
+  int left_p, right_p;
+  struct glyph *last_glyph;
+  XRectangle clip_rect;
+
+  last_x = window_box_right (s->w, s->area);
+  if (s->row->full_width_p
+      && !s->w->pseudo_window_p)
     {
-      int box_line_width = max (s->face->box_line_width, 0);
+      last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
+      if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
+       last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
+    }
 
-      if (s->stippled_p)
-       {
-         /* Fill background with a stipple pattern.  */
-         XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
-         XFillRectangle (s->display, s->window, s->gc, s->x,
-                         s->y + box_line_width,
-                         s->background_width,
-                         s->height - 2 * box_line_width);
-         XSetFillStyle (s->display, s->gc, FillSolid);
-         s->background_filled_p = 1;
-       }
-      else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
-              || s->font_not_found_p
-              || s->extends_to_end_of_line_p
-              || force_p)
-       {
-         x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
-                                    s->background_width,
-                                    s->height - 2 * box_line_width);
-         s->background_filled_p = 1;
-       }
+  /* The glyph that may have a right box line.  */
+  last_glyph = (s->cmp || s->img
+               ? s->first_glyph
+               : s->first_glyph + s->nchars - 1);
+
+  width = abs (s->face->box_line_width);
+  raised_p = s->face->box == FACE_RAISED_BOX;
+  left_x = s->x;
+  right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
+            ? last_x - 1
+            : min (last_x, s->x + s->background_width) - 1);
+  top_y = s->y;
+  bottom_y = top_y + s->height - 1;
+
+  left_p = (s->first_glyph->left_box_line_p
+           || (s->hl == DRAW_MOUSE_FACE
+               && (s->prev == NULL
+                   || s->prev->hl != s->hl)));
+  right_p = (last_glyph->right_box_line_p
+            || (s->hl == DRAW_MOUSE_FACE
+                && (s->next == NULL
+                    || s->next->hl != s->hl)));
+
+  get_glyph_string_clip_rect (s, &clip_rect);
+
+  if (s->face->box == FACE_SIMPLE_BOX)
+    x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
+                    left_p, right_p, &clip_rect);
+  else
+    {
+      x_setup_relief_colors (s);
+      x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
+                         width, raised_p, left_p, right_p, &clip_rect);
     }
 }
 
 
-/* Draw the foreground of glyph string S.  */
+/* Draw foreground of image glyph string S.  */
 
 static void
-x_draw_glyph_string_foreground (s)
+x_draw_image_foreground (s)
      struct glyph_string *s;
 {
-  int i, x;
+  int x;
+  int y = s->ybase - image_ascent (s->img, s->face);
 
-  /* If first glyph of S has a left box line, start drawing the text
-     of S to the right of that box line.  */
+  /* If first glyph of S has a left box line, start drawing it to the
+     right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
     x = s->x + abs (s->face->box_line_width);
   else
     x = s->x;
 
-  /* Draw characters of S as rectangles if S's font could not be
-     loaded.  */
-  if (s->font_not_found_p)
+  /* If there is a margin around the image, adjust x- and y-position
+     by that margin.  */
+  x += s->img->hmargin;
+  y += s->img->vmargin;
+
+  if (s->img->pixmap)
     {
-      for (i = 0; i < s->nchars; ++i)
+      if (s->img->mask)
        {
-         struct glyph *g = s->first_glyph + i;
-         XDrawRectangle (s->display, s->window,
-                         s->gc, x, s->y, g->pixel_width - 1,
-                         s->height - 1);
-         x += g->pixel_width;
-       }
-    }
-  else
-    {
-      char *char1b = (char *) s->char2b;
-      int boff = s->font_info->baseline_offset;
-
-      if (s->font_info->vertical_centering)
-       boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
+         /* We can't set both a clip mask and use XSetClipRectangles
+            because the latter also sets a clip mask.  We also can't
+            trust on the shape extension to be available
+            (XShapeCombineRegion).  So, compute the rectangle to draw
+            manually.  */
+         unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
+                               | GCFunction);
+         XGCValues xgcv;
+         XRectangle clip_rect, image_rect, r;
 
-      /* If we can use 8-bit functions, condense S->char2b.  */
-      if (!s->two_byte_p)
-       for (i = 0; i < s->nchars; ++i)
-         char1b[i] = s->char2b[i].byte2;
+         xgcv.clip_mask = s->img->mask;
+         xgcv.clip_x_origin = x;
+         xgcv.clip_y_origin = y;
+         xgcv.function = GXcopy;
+         XChangeGC (s->display, s->gc, mask, &xgcv);
 
-      /* Draw text with XDrawString if background has already been
-        filled.  Otherwise, use XDrawImageString.  (Note that
-        XDrawImageString is usually faster than XDrawString.)  Always
-        use XDrawImageString when drawing the cursor so that there is
-        no chance that characters under a box cursor are invisible.  */
-      if (s->for_overlaps_p
-         || (s->background_filled_p && s->hl != DRAW_CURSOR))
-       {
-         /* Draw characters with 16-bit or 8-bit functions.  */
-         if (s->two_byte_p)
-           XDrawString16 (s->display, s->window, s->gc, x,
-                          s->ybase - boff, s->char2b, s->nchars);
-         else
-           XDrawString (s->display, s->window, s->gc, x,
-                        s->ybase - boff, char1b, s->nchars);
+         get_glyph_string_clip_rect (s, &clip_rect);
+         image_rect.x = x;
+         image_rect.y = y;
+         image_rect.width = s->img->width;
+         image_rect.height = s->img->height;
+         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
+           XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
+                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
        }
       else
        {
-         if (s->two_byte_p)
-           XDrawImageString16 (s->display, s->window, s->gc, x,
-                               s->ybase - boff, s->char2b, s->nchars);
-         else
-           XDrawImageString (s->display, s->window, s->gc, x,
-                             s->ybase - boff, char1b, s->nchars);
-       }
+         XRectangle clip_rect, image_rect, r;
 
-      if (s->face->overstrike)
-       {
-         /* For overstriking (to simulate bold-face), draw the
-            characters again shifted to the right by one pixel.  */
-         if (s->two_byte_p)
-           XDrawString16 (s->display, s->window, s->gc, x + 1,
-                          s->ybase - boff, s->char2b, s->nchars);
-         else
-           XDrawString (s->display, s->window, s->gc, x + 1,
-                        s->ybase - boff, char1b, s->nchars);
+         get_glyph_string_clip_rect (s, &clip_rect);
+         image_rect.x = x;
+         image_rect.y = y;
+         image_rect.width = s->img->width;
+         image_rect.height = s->img->height;
+         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
+           XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
+                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+
+         /* When the image has a mask, we can expect that at
+            least part of a mouse highlight or a block cursor will
+            be visible.  If the image doesn't have a mask, make
+            a block cursor visible by drawing a rectangle around
+            the image.  I believe it's looking better if we do
+            nothing here for mouse-face.  */
+         if (s->hl == DRAW_CURSOR)
+           {
+             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
+    /* Draw a rectangle if image could not be loaded.  */
+    XDrawRectangle (s->display, s->window, s->gc, x, y,
+                   s->img->width - 1, s->img->height - 1);
 }
 
-/* Draw the foreground of composite glyph string S.  */
+
+/* Draw a relief around the image glyph string S.  */
 
 static void
-x_draw_composite_glyph_string_foreground (s)
+x_draw_image_relief (s)
      struct glyph_string *s;
 {
-  int i, x;
+  int x0, y0, x1, y1, thick, raised_p;
+  XRectangle r;
+  int x;
+  int y = s->ybase - image_ascent (s->img, s->face);
 
-  /* If first glyph of S has a left box line, start drawing the text
-     of S to the right of that box line.  */
+  /* If first glyph of S has a left box line, start drawing it to the
+     right of that line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
     x = s->x + abs (s->face->box_line_width);
   else
     x = s->x;
 
-  /* S is a glyph string for a composition.  S->gidx is the index of
-     the first character drawn for glyphs of this composition.
-     S->gidx == 0 means we are drawing the very first character of
-     this composition.  */
+  /* If there is a margin around the image, adjust x- and y-position
+     by that margin.  */
+  x += s->img->hmargin;
+  y += s->img->vmargin;
 
-  /* Draw a rectangle for the composition if the font for the very
-     first character of the composition could not be loaded.  */
-  if (s->font_not_found_p)
+  if (s->hl == DRAW_IMAGE_SUNKEN
+      || s->hl == DRAW_IMAGE_RAISED)
     {
-      if (s->gidx == 0)
-       XDrawRectangle (s->display, s->window, s->gc, x, s->y,
-                       s->width - 1, s->height - 1);
+      thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
+      raised_p = s->hl == DRAW_IMAGE_RAISED;
     }
   else
     {
-      for (i = 0; i < s->nchars; i++, ++s->gidx)
-       {
-         XDrawString16 (s->display, s->window, s->gc,
-                        x + s->cmp->offsets[s->gidx * 2],
-                        s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                        s->char2b + i, 1);
-         if (s->face->overstrike)
-           XDrawString16 (s->display, s->window, s->gc,
-                          x + s->cmp->offsets[s->gidx * 2] + 1,
-                          s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                          s->char2b + i, 1);
-       }
+      thick = abs (s->img->relief);
+      raised_p = s->img->relief > 0;
     }
-}
-
 
-#ifdef USE_X_TOOLKIT
+  x0 = x - thick;
+  y0 = y - thick;
+  x1 = x + s->img->width + thick - 1;
+  y1 = y + s->img->height + thick - 1;
 
-static struct frame *x_frame_of_widget P_ ((Widget));
-static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
-                                       XrmValue *, XrmValue *, XtPointer *));
-static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
-                               XrmValue *, Cardinal *));
+  x_setup_relief_colors (s);
+  get_glyph_string_clip_rect (s, &r);
+  x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
+}
 
 
-/* Return the frame on which widget WIDGET is used.. Abort if frame
-   cannot be determined.  */
+/* Draw the foreground of image glyph string S to PIXMAP.  */
 
-static struct frame *
-x_frame_of_widget (widget)
-     Widget widget;
+static void
+x_draw_image_foreground_1 (s, pixmap)
+     struct glyph_string *s;
+     Pixmap pixmap;
 {
-  struct x_display_info *dpyinfo;
-  Lisp_Object tail;
-  struct frame *f;
-
-  dpyinfo = x_display_info_for_display (XtDisplay (widget));
+  int x;
+  int y = s->ybase - s->y - image_ascent (s->img, s->face);
 
-  /* Find the top-level shell of the widget.  Note that this function
-     can be called when the widget is not yet realized, so XtWindow
-     (widget) == 0.  That's the reason we can't simply use
-     x_any_window_to_frame.  */
-  while (!XtIsTopLevelShell (widget))
-    widget = XtParent (widget);
+  /* If first glyph of S has a left box line, start drawing it to the
+     right of that line.  */
+  if (s->face->box != FACE_NO_BOX
+      && s->first_glyph->left_box_line_p)
+    x = abs (s->face->box_line_width);
+  else
+    x = 0;
 
-  /* Look for a frame with that top-level widget.  Allocate the color
-     on that frame to get the right gamma correction value.  */
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
-    if (GC_FRAMEP (XCAR (tail))
-       && (f = XFRAME (XCAR (tail)),
-           (f->output_data.nothing != 1
-            && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
-       && f->output_data.x->widget == widget)
-      return f;
-
-  abort ();
-}
-
-
-/* Allocate the color COLOR->pixel on the screen and display of
-   widget WIDGET in colormap CMAP.  If an exact match cannot be
-   allocated, try the nearest color available.  Value is non-zero
-   if successful.  This is called from lwlib.  */
-
-int
-x_alloc_nearest_color_for_widget (widget, cmap, color)
-     Widget widget;
-     Colormap cmap;
-     XColor *color;
-{
-  struct frame *f = x_frame_of_widget (widget);
-  return x_alloc_nearest_color (f, cmap, color);
-}
-
-
-/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
-   or DELTA.  Try a color with RGB values multiplied by FACTOR first.
-   If this produces the same color as PIXEL, try a color where all RGB
-   values have DELTA added.  Return the allocated color in *PIXEL.
-   DISPLAY is the X display, CMAP is the colormap to operate on.
-   Value is non-zero if successful.  */
-
-int
-x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
-     Widget widget;
-     Display *display;
-     Colormap cmap;
-     unsigned long *pixel;
-     double factor;
-     int delta;
-{
-  struct frame *f = x_frame_of_widget (widget);
-  return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
-}
-
-
-/* Structure specifying which arguments should be passed by Xt to
-   cvt_string_to_pixel.  We want the widget's screen and colormap.  */
-
-static XtConvertArgRec cvt_string_to_pixel_args[] =
-  {
-    {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
-     sizeof (Screen *)},
-    {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
-     sizeof (Colormap)}
-  };
-
-
-/* The address of this variable is returned by
-   cvt_string_to_pixel.  */
-
-static Pixel cvt_string_to_pixel_value;
-
-
-/* Convert a color name to a pixel color.
-
-   DPY is the display we are working on.
-
-   ARGS is an array of *NARGS XrmValue structures holding additional
-   information about the widget for which the conversion takes place.
-   The contents of this array are determined by the specification
-   in cvt_string_to_pixel_args.
-
-   FROM is a pointer to an XrmValue which points to the color name to
-   convert.  TO is an XrmValue in which to return the pixel color.
-
-   CLOSURE_RET is a pointer to user-data, in which we record if
-   we allocated the color or not.
-
-   Value is True if successful, False otherwise.  */
-
-static Boolean
-cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
-     Display *dpy;
-     XrmValue *args;
-     Cardinal *nargs;
-     XrmValue *from, *to;
-     XtPointer *closure_ret;
-{
-  Screen *screen;
-  Colormap cmap;
-  Pixel pixel;
-  String color_name;
-  XColor color;
-
-  if (*nargs != 2)
-    {
-      XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
-                      "wrongParameters", "cvt_string_to_pixel",
-                      "XtToolkitError",
-                      "Screen and colormap args required", NULL, NULL);
-      return False;
-    }
-
-  screen = *(Screen **) args[0].addr;
-  cmap = *(Colormap *) args[1].addr;
-  color_name = (String) from->addr;
-
-  if (strcmp (color_name, XtDefaultBackground) == 0)
-    {
-      *closure_ret = (XtPointer) False;
-      pixel = WhitePixelOfScreen (screen);
-    }
-  else if (strcmp (color_name, XtDefaultForeground) == 0)
-    {
-      *closure_ret = (XtPointer) False;
-      pixel = BlackPixelOfScreen (screen);
-    }
-  else if (XParseColor (dpy, cmap, color_name, &color)
-          && x_alloc_nearest_color_1 (dpy, cmap, &color))
-    {
-      pixel = color.pixel;
-      *closure_ret = (XtPointer) True;
-    }
-  else
-    {
-      String params[1];
-      Cardinal nparams = 1;
-
-      params[0] = color_name;
-      XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
-                      "badValue", "cvt_string_to_pixel",
-                      "XtToolkitError", "Invalid color `%s'",
-                      params, &nparams);
-      return False;
-    }
-
-  if (to->addr != NULL)
-    {
-      if (to->size < sizeof (Pixel))
-       {
-         to->size = sizeof (Pixel);
-         return False;
-       }
-
-      *(Pixel *) to->addr = pixel;
-    }
-  else
-    {
-      cvt_string_to_pixel_value = pixel;
-      to->addr = (XtPointer) &cvt_string_to_pixel_value;
-    }
-
-  to->size = sizeof (Pixel);
-  return True;
-}
-
-
-/* Free a pixel color which was previously allocated via
-   cvt_string_to_pixel.  This is registered as the destructor
-   for this type of resource via XtSetTypeConverter.
-
-   APP is the application context in which we work.
-
-   TO is a pointer to an XrmValue holding the color to free.
-   CLOSURE is the value we stored in CLOSURE_RET for this color
-   in cvt_string_to_pixel.
-
-   ARGS and NARGS are like for cvt_string_to_pixel.  */
-
-static void
-cvt_pixel_dtor (app, to, closure, args, nargs)
-    XtAppContext app;
-    XrmValuePtr to;
-    XtPointer closure;
-    XrmValuePtr args;
-    Cardinal *nargs;
-{
-  if (*nargs != 2)
-    {
-      XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
-                      "XtToolkitError",
-                      "Screen and colormap arguments required",
-                      NULL, NULL);
-    }
-  else if (closure != NULL)
-    {
-      /* We did allocate the pixel, so free it.  */
-      Screen *screen = *(Screen **) args[0].addr;
-      Colormap cmap = *(Colormap *) args[1].addr;
-      x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
-                        (Pixel *) to->addr, 1);
-    }
-}
-
-
-#endif /* USE_X_TOOLKIT */
-
-
-/* Value is an array of XColor structures for the contents of the
-   color map of display DPY.  Set *NCELLS to the size of the array.
-   Note that this probably shouldn't be called for large color maps,
-   say a 24-bit TrueColor map.  */
-
-static const XColor *
-x_color_cells (dpy, ncells)
-     Display *dpy;
-     int *ncells;
-{
-  struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
-
-  if (dpyinfo->color_cells == NULL)
-    {
-      Screen *screen = dpyinfo->screen;
-      int i;
-
-      dpyinfo->ncolor_cells
-       = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
-      dpyinfo->color_cells
-       = (XColor *) xmalloc (dpyinfo->ncolor_cells
-                             * sizeof *dpyinfo->color_cells);
-
-      for (i = 0; i < dpyinfo->ncolor_cells; ++i)
-       dpyinfo->color_cells[i].pixel = i;
-
-      XQueryColors (dpy, dpyinfo->cmap,
-                   dpyinfo->color_cells, dpyinfo->ncolor_cells);
-    }
-
-  *ncells = dpyinfo->ncolor_cells;
-  return dpyinfo->color_cells;
-}
-
-
-/* On frame F, translate pixel colors to RGB values for the NCOLORS
-   colors in COLORS.  Use cached information, if available.  */
-
-void
-x_query_colors (f, colors, ncolors)
-     struct frame *f;
-     XColor *colors;
-     int ncolors;
-{
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-
-  if (dpyinfo->color_cells)
-    {
-      int i;
-      for (i = 0; i < ncolors; ++i)
-       {
-         unsigned long pixel = colors[i].pixel;
-         xassert (pixel < dpyinfo->ncolor_cells);
-         xassert (dpyinfo->color_cells[pixel].pixel == pixel);
-         colors[i] = dpyinfo->color_cells[pixel];
-       }
-    }
-  else
-    XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
-}
-
-
-/* On frame F, translate pixel color to RGB values for the color in
-   COLOR.  Use cached information, if available.  */
-
-void
-x_query_color (f, color)
-     struct frame *f;
-     XColor *color;
-{
-  x_query_colors (f, color, 1);
-}
-
-
-/* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP.  If an
-   exact match can't be allocated, try the nearest color available.
-   Value is non-zero if successful.  Set *COLOR to the color
-   allocated.  */
-
-static int
-x_alloc_nearest_color_1 (dpy, cmap, color)
-     Display *dpy;
-     Colormap cmap;
-     XColor *color;
-{
-  int rc;
-
-  rc = XAllocColor (dpy, cmap, color);
-  if (rc == 0)
-    {
-      /* If we got to this point, the colormap is full, so we're going
-        to try to get the next closest color.  The algorithm used is
-        a least-squares matching, which is what X uses for closest
-        color matching with StaticColor visuals.  */
-      int nearest, i;
-      unsigned long nearest_delta = ~0;
-      int ncells;
-      const XColor *cells = x_color_cells (dpy, &ncells);
-
-      for (nearest = i = 0; i < ncells; ++i)
-       {
-         long dred   = (color->red   >> 8) - (cells[i].red   >> 8);
-         long dgreen = (color->green >> 8) - (cells[i].green >> 8);
-         long dblue  = (color->blue  >> 8) - (cells[i].blue  >> 8);
-         unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
-
-         if (delta < nearest_delta)
-           {
-             nearest = i;
-             nearest_delta = delta;
-           }
-       }
-
-      color->red   = cells[nearest].red;
-      color->green = cells[nearest].green;
-      color->blue  = cells[nearest].blue;
-      rc = XAllocColor (dpy, cmap, color);
-    }
-  else
-    {
-      /* If allocation succeeded, and the allocated pixel color is not
-         equal to a cached pixel color recorded earlier, there was a
-         change in the colormap, so clear the color cache.  */
-      struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
-      XColor *cached_color;
-
-      if (dpyinfo->color_cells
-         && (cached_color = &dpyinfo->color_cells[color->pixel],
-             (cached_color->red != color->red
-              || cached_color->blue != color->blue
-              || cached_color->green != color->green)))
-       {
-         xfree (dpyinfo->color_cells);
-         dpyinfo->color_cells = NULL;
-         dpyinfo->ncolor_cells = 0;
-       }
-    }
-
-#ifdef DEBUG_X_COLORS
-  if (rc)
-    register_color (color->pixel);
-#endif /* DEBUG_X_COLORS */
-
-  return rc;
-}
-
-
-/* Allocate the color COLOR->pixel on frame F, colormap CMAP.  If an
-   exact match can't be allocated, try the nearest color available.
-   Value is non-zero if successful.  Set *COLOR to the color
-   allocated.  */
-
-int
-x_alloc_nearest_color (f, cmap, color)
-     struct frame *f;
-     Colormap cmap;
-     XColor *color;
-{
-  gamma_correct (f, color);
-  return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
-}
-
-
-/* Allocate color PIXEL on frame F.  PIXEL must already be allocated.
-   It's necessary to do this instead of just using PIXEL directly to
-   get color reference counts right.  */
-
-unsigned long
-x_copy_color (f, pixel)
-     struct frame *f;
-     unsigned long pixel;
-{
-  XColor color;
-
-  color.pixel = pixel;
-  BLOCK_INPUT;
-  x_query_color (f, &color);
-  XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
-  UNBLOCK_INPUT;
-#ifdef DEBUG_X_COLORS
-  register_color (pixel);
-#endif
-  return color.pixel;
-}
-
-
-/* Allocate color PIXEL on display DPY.  PIXEL must already be allocated.
-   It's necessary to do this instead of just using PIXEL directly to
-   get color reference counts right.  */
-
-unsigned long
-x_copy_dpy_color (dpy, cmap, pixel)
-     Display *dpy;
-     Colormap cmap;
-     unsigned long pixel;
-{
-  XColor color;
-
-  color.pixel = pixel;
-  BLOCK_INPUT;
-  XQueryColor (dpy, cmap, &color);
-  XAllocColor (dpy, cmap, &color);
-  UNBLOCK_INPUT;
-#ifdef DEBUG_X_COLORS
-  register_color (pixel);
-#endif
-  return color.pixel;
-}
-
-
-/* Brightness beyond which a color won't have its highlight brightness
-   boosted.
-
-   Nominally, highlight colors for `3d' faces are calculated by
-   brightening an object's color by a constant scale factor, but this
-   doesn't yield good results for dark colors, so for colors who's
-   brightness is less than this value (on a scale of 0-65535) have an
-   use an additional additive factor.
-
-   The value here is set so that the default menu-bar/mode-line color
-   (grey75) will not have its highlights changed at all.  */
-#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
-
-
-/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
-   or DELTA.  Try a color with RGB values multiplied by FACTOR first.
-   If this produces the same color as PIXEL, try a color where all RGB
-   values have DELTA added.  Return the allocated color in *PIXEL.
-   DISPLAY is the X display, CMAP is the colormap to operate on.
-   Value is non-zero if successful.  */
-
-static int
-x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
-     struct frame *f;
-     Display *display;
-     Colormap cmap;
-     unsigned long *pixel;
-     double factor;
-     int delta;
-{
-  XColor color, new;
-  long bright;
-  int success_p;
-
-  /* Get RGB color values.  */
-  color.pixel = *pixel;
-  x_query_color (f, &color);
-
-  /* Change RGB values by specified FACTOR.  Avoid overflow!  */
-  xassert (factor >= 0);
-  new.red = min (0xffff, factor * color.red);
-  new.green = min (0xffff, factor * color.green);
-  new.blue = min (0xffff, factor * color.blue);
-
-  /* Calculate brightness of COLOR.  */
-  bright = (2 * color.red + 3 * color.green + color.blue) / 6;
-
-  /* We only boost colors that are darker than
-     HIGHLIGHT_COLOR_DARK_BOOST_LIMIT.  */
-  if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
-    /* Make an additive adjustment to NEW, because it's dark enough so
-       that scaling by FACTOR alone isn't enough.  */
-    {
-      /* How far below the limit this color is (0 - 1, 1 being darker).  */
-      double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
-      /* The additive adjustment.  */
-      int min_delta = delta * dimness * factor / 2;
-
-      if (factor < 1)
-       {
-         new.red =   max (0, new.red -   min_delta);
-         new.green = max (0, new.green - min_delta);
-         new.blue =  max (0, new.blue -  min_delta);
-       }
-      else
-       {
-         new.red =   min (0xffff, min_delta + new.red);
-         new.green = min (0xffff, min_delta + new.green);
-         new.blue =  min (0xffff, min_delta + new.blue);
-       }
-    }
-
-  /* Try to allocate the color.  */
-  success_p = x_alloc_nearest_color (f, cmap, &new);
-  if (success_p)
-    {
-      if (new.pixel == *pixel)
-       {
-         /* If we end up with the same color as before, try adding
-            delta to the RGB values.  */
-         x_free_colors (f, &new.pixel, 1);
-
-         new.red = min (0xffff, delta + color.red);
-         new.green = min (0xffff, delta + color.green);
-         new.blue = min (0xffff, delta + color.blue);
-         success_p = x_alloc_nearest_color (f, cmap, &new);
-       }
-      else
-       success_p = 1;
-      *pixel = new.pixel;
-    }
-
-  return success_p;
-}
-
-
-/* Set up the foreground color for drawing relief lines of glyph
-   string S.  RELIEF is a pointer to a struct relief containing the GC
-   with which lines will be drawn.  Use a color that is FACTOR or
-   DELTA lighter or darker than the relief's background which is found
-   in S->f->output_data.x->relief_background.  If such a color cannot
-   be allocated, use DEFAULT_PIXEL, instead.  */
-
-static void
-x_setup_relief_color (f, relief, factor, delta, default_pixel)
-     struct frame *f;
-     struct relief *relief;
-     double factor;
-     int delta;
-     unsigned long default_pixel;
-{
-  XGCValues xgcv;
-  struct x_output *di = f->output_data.x;
-  unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
-  unsigned long pixel;
-  unsigned long background = di->relief_background;
-  Colormap cmap = FRAME_X_COLORMAP (f);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  Display *dpy = FRAME_X_DISPLAY (f);
-
-  xgcv.graphics_exposures = False;
-  xgcv.line_width = 1;
-
-  /* Free previously allocated color.  The color cell will be reused
-     when it has been freed as many times as it was allocated, so this
-     doesn't affect faces using the same colors.  */
-  if (relief->gc
-      && relief->allocated_p)
-    {
-      x_free_colors (f, &relief->pixel, 1);
-      relief->allocated_p = 0;
-    }
-
-  /* Allocate new color.  */
-  xgcv.foreground = default_pixel;
-  pixel = background;
-  if (dpyinfo->n_planes != 1
-      && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
-    {
-      relief->allocated_p = 1;
-      xgcv.foreground = relief->pixel = pixel;
-    }
-
-  if (relief->gc == 0)
-    {
-      xgcv.stipple = dpyinfo->gray;
-      mask |= GCStipple;
-      relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
-    }
-  else
-    XChangeGC (dpy, relief->gc, mask, &xgcv);
-}
-
-
-/* Set up colors for the relief lines around glyph string S.  */
-
-static void
-x_setup_relief_colors (s)
-     struct glyph_string *s;
-{
-  struct x_output *di = s->f->output_data.x;
-  unsigned long color;
-
-  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
-    {
-      XGCValues xgcv;
-
-      /* Get the background color of the face.  */
-      XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
-      color = xgcv.background;
-    }
-
-  if (di->white_relief.gc == 0
-      || color != di->relief_background)
-    {
-      di->relief_background = color;
-      x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
-                           WHITE_PIX_DEFAULT (s->f));
-      x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
-                           BLACK_PIX_DEFAULT (s->f));
-    }
-}
-
-
-/* Draw a relief on frame F inside the rectangle given by LEFT_X,
-   TOP_Y, RIGHT_X, and BOTTOM_Y.  WIDTH is the thickness of the relief
-   to draw, it must be >= 0.  RAISED_P non-zero means draw a raised
-   relief.  LEFT_P non-zero means draw a relief on the left side of
-   the rectangle.  RIGHT_P non-zero means draw a relief on the right
-   side of the rectangle.  CLIP_RECT is the clipping rectangle to use
-   when drawing.  */
-
-static void
-x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
-                   raised_p, left_p, right_p, clip_rect)
-     struct frame *f;
-     int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
-     XRectangle *clip_rect;
-{
-  Display *dpy = FRAME_X_DISPLAY (f);
-  Window window = FRAME_X_WINDOW (f);
-  int i;
-  GC gc;
-
-  if (raised_p)
-    gc = f->output_data.x->white_relief.gc;
-  else
-    gc = f->output_data.x->black_relief.gc;
-  XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
-
-  /* Top.  */
-  for (i = 0; i < width; ++i)
-    XDrawLine (dpy, window, gc,
-              left_x + i * left_p, top_y + i,
-              right_x + 1 - i * right_p, top_y + i);
-
-  /* Left.  */
-  if (left_p)
-    for (i = 0; i < width; ++i)
-      XDrawLine (dpy, window, gc,
-                left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
-
-  XSetClipMask (dpy, gc, None);
-  if (raised_p)
-    gc = f->output_data.x->black_relief.gc;
-  else
-    gc = f->output_data.x->white_relief.gc;
-  XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
-
-  /* Bottom.  */
-  for (i = 0; i < width; ++i)
-    XDrawLine (dpy, window, gc,
-              left_x + i * left_p, bottom_y - i,
-              right_x + 1 - i * right_p, bottom_y - i);
-
-  /* Right.  */
-  if (right_p)
-    for (i = 0; i < width; ++i)
-      XDrawLine (dpy, window, gc,
-                right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
-
-  XSetClipMask (dpy, gc, None);
-}
-
-
-/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
-   RIGHT_X, and BOTTOM_Y.  WIDTH is the thickness of the lines to
-   draw, it must be >= 0.  LEFT_P non-zero means draw a line on the
-   left side of the rectangle.  RIGHT_P non-zero means draw a line
-   on the right side of the rectangle.  CLIP_RECT is the clipping
-   rectangle to use when drawing.  */
-
-static void
-x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
-                left_p, right_p, clip_rect)
-     struct glyph_string *s;
-     int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
-     XRectangle *clip_rect;
-{
-  XGCValues xgcv;
-
-  XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
-  XSetForeground (s->display, s->gc, s->face->box_color);
-  XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
-
-  /* Top.  */
-  XFillRectangle (s->display, s->window, s->gc,
-                 left_x, top_y, right_x - left_x + 1, width);
-
-  /* Left.  */
-  if (left_p)
-    XFillRectangle (s->display, s->window, s->gc,
-                   left_x, top_y, width, bottom_y - top_y + 1);
-
-  /* Bottom.  */
-  XFillRectangle (s->display, s->window, s->gc,
-                 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
-
-  /* Right.  */
-  if (right_p)
-    XFillRectangle (s->display, s->window, s->gc,
-                   right_x - width + 1, top_y, width, bottom_y - top_y + 1);
-
-  XSetForeground (s->display, s->gc, xgcv.foreground);
-  XSetClipMask (s->display, s->gc, None);
-}
-
-
-/* Draw a box around glyph string S.  */
-
-static void
-x_draw_glyph_string_box (s)
-     struct glyph_string *s;
-{
-  int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
-  int left_p, right_p;
-  struct glyph *last_glyph;
-  XRectangle clip_rect;
-
-  last_x = window_box_right (s->w, s->area);
-  if (s->row->full_width_p
-      && !s->w->pseudo_window_p)
-    {
-      last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
-       last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
-    }
-
-  /* The glyph that may have a right box line.  */
-  last_glyph = (s->cmp || s->img
-               ? s->first_glyph
-               : s->first_glyph + s->nchars - 1);
-
-  width = abs (s->face->box_line_width);
-  raised_p = s->face->box == FACE_RAISED_BOX;
-  left_x = s->x;
-  right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
-            ? last_x - 1
-            : min (last_x, s->x + s->background_width) - 1);
-  top_y = s->y;
-  bottom_y = top_y + s->height - 1;
-
-  left_p = (s->first_glyph->left_box_line_p
-           || (s->hl == DRAW_MOUSE_FACE
-               && (s->prev == NULL
-                   || s->prev->hl != s->hl)));
-  right_p = (last_glyph->right_box_line_p
-            || (s->hl == DRAW_MOUSE_FACE
-                && (s->next == NULL
-                    || s->next->hl != s->hl)));
-
-  x_get_glyph_string_clip_rect (s, &clip_rect);
-
-  if (s->face->box == FACE_SIMPLE_BOX)
-    x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
-                    left_p, right_p, &clip_rect);
-  else
-    {
-      x_setup_relief_colors (s);
-      x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
-                         width, raised_p, left_p, right_p, &clip_rect);
-    }
-}
-
-
-/* Draw foreground of image glyph string S.  */
-
-static void
-x_draw_image_foreground (s)
-     struct glyph_string *s;
-{
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
-
-  /* If first glyph of S has a left box line, start drawing it to the
-     right of that line.  */
-  if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
-
-  /* If there is a margin around the image, adjust x- and y-position
-     by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
-
-  if (s->img->pixmap)
-    {
-      if (s->img->mask)
-       {
-         /* We can't set both a clip mask and use XSetClipRectangles
-            because the latter also sets a clip mask.  We also can't
-            trust on the shape extension to be available
-            (XShapeCombineRegion).  So, compute the rectangle to draw
-            manually.  */
-         unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
-                               | GCFunction);
-         XGCValues xgcv;
-         XRectangle clip_rect, image_rect, r;
-
-         xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
-         xgcv.function = GXcopy;
-         XChangeGC (s->display, s->gc, mask, &xgcv);
-
-         x_get_glyph_string_clip_rect (s, &clip_rect);
-         image_rect.x = x;
-         image_rect.y = y;
-         image_rect.width = s->img->width;
-         image_rect.height = s->img->height;
-         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
-           XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
-       }
-      else
-       {
-         XRectangle clip_rect, image_rect, r;
-
-         x_get_glyph_string_clip_rect (s, &clip_rect);
-         image_rect.x = x;
-         image_rect.y = y;
-         image_rect.width = s->img->width;
-         image_rect.height = s->img->height;
-         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
-           XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
-
-         /* When the image has a mask, we can expect that at
-            least part of a mouse highlight or a block cursor will
-            be visible.  If the image doesn't have a mask, make
-            a block cursor visible by drawing a rectangle around
-            the image.  I believe it's looking better if we do
-            nothing here for mouse-face.  */
-         if (s->hl == DRAW_CURSOR)
-           {
-             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
-    /* Draw a rectangle if image could not be loaded.  */
-    XDrawRectangle (s->display, s->window, s->gc, x, y,
-                   s->img->width - 1, s->img->height - 1);
-}
-
-
-/* Draw a relief around the image glyph string S.  */
-
-static void
-x_draw_image_relief (s)
-     struct glyph_string *s;
-{
-  int x0, y0, x1, y1, thick, raised_p;
-  XRectangle r;
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
-
-  /* If first glyph of S has a left box line, start drawing it to the
-     right of that line.  */
-  if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
-
-  /* If there is a margin around the image, adjust x- and y-position
-     by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
-
-  if (s->hl == DRAW_IMAGE_SUNKEN
-      || s->hl == DRAW_IMAGE_RAISED)
-    {
-      thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
-      raised_p = s->hl == DRAW_IMAGE_RAISED;
-    }
-  else
-    {
-      thick = abs (s->img->relief);
-      raised_p = s->img->relief > 0;
-    }
-
-  x0 = x - thick;
-  y0 = y - thick;
-  x1 = x + s->img->width + thick - 1;
-  y1 = y + s->img->height + thick - 1;
-
-  x_setup_relief_colors (s);
-  x_get_glyph_string_clip_rect (s, &r);
-  x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
-}
-
-
-/* Draw the foreground of image glyph string S to PIXMAP.  */
-
-static void
-x_draw_image_foreground_1 (s, pixmap)
-     struct glyph_string *s;
-     Pixmap pixmap;
-{
-  int x;
-  int y = s->ybase - s->y - image_ascent (s->img, s->face);
-
-  /* If first glyph of S has a left box line, start drawing it to the
-     right of that line.  */
-  if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = abs (s->face->box_line_width);
-  else
-    x = 0;
-
-  /* If there is a margin around the image, adjust x- and y-position
-     by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
-
-  if (s->img->pixmap)
-    {
-      if (s->img->mask)
-       {
-         /* We can't set both a clip mask and use XSetClipRectangles
-            because the latter also sets a clip mask.  We also can't
-            trust on the shape extension to be available
-            (XShapeCombineRegion).  So, compute the rectangle to draw
-            manually.  */
-         unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
-                               | GCFunction);
-         XGCValues xgcv;
-
-         xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
-         xgcv.function = GXcopy;
-         XChangeGC (s->display, s->gc, mask, &xgcv);
-
-         XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
-         XSetClipMask (s->display, s->gc, None);
-       }
-      else
-       {
-         XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
-
-         /* When the image has a mask, we can expect that at
-            least part of a mouse highlight or a block cursor will
-            be visible.  If the image doesn't have a mask, make
-            a block cursor visible by drawing a rectangle around
-            the image.  I believe it's looking better if we do
-            nothing here for mouse-face.  */
-         if (s->hl == DRAW_CURSOR)
-           {
-             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
-    /* Draw a rectangle if image could not be loaded.  */
-    XDrawRectangle (s->display, pixmap, s->gc, x, y,
-                   s->img->width - 1, s->img->height - 1);
-}
-
-
-/* Draw part of the background of glyph string S.  X, Y, W, and H
-   give the rectangle to draw.  */
-
-static void
-x_draw_glyph_string_bg_rect (s, x, y, w, h)
-     struct glyph_string *s;
-     int x, y, w, h;
-{
-  if (s->stippled_p)
-    {
-      /* Fill background with a stipple pattern.  */
-      XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
-      XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
-      XSetFillStyle (s->display, s->gc, FillSolid);
-    }
-  else
-    x_clear_glyph_string_rect (s, x, y, w, h);
-}
-
-
-/* Draw image glyph string S.
-
-            s->y
-   s->x      +-------------------------
-            |   s->face->box
-            |
-            |     +-------------------------
-            |     |  s->img->margin
-            |     |
-            |     |       +-------------------
-            |     |       |  the image
-
- */
-
-static void
-x_draw_image_glyph_string (s)
-     struct glyph_string *s;
-{
-  int x, y;
-  int box_line_hwidth = abs (s->face->box_line_width);
-  int box_line_vwidth = max (s->face->box_line_width, 0);
-  int height;
-  Pixmap pixmap = None;
-
-  height = s->height - 2 * box_line_vwidth;
-
-
-  /* Fill background with face under the image.  Do it only if row is
-     taller than image or if image has a clip mask to reduce
-     flickering.  */
-  s->stippled_p = s->face->stipple != 0;
-  if (height > s->img->height
-      || s->img->hmargin
-      || s->img->vmargin
-      || s->img->mask
-      || s->img->pixmap == 0
-      || s->width != s->background_width)
-    {
-      if (box_line_hwidth && s->first_glyph->left_box_line_p)
-       x = s->x + box_line_hwidth;
-      else
-       x = s->x;
-
-      y = s->y + box_line_vwidth;
-
-      if (s->img->mask)
-       {
-         /* Create a pixmap as large as the glyph string.  Fill it
-            with the background color.  Copy the image to it, using
-            its mask.  Copy the temporary pixmap to the display.  */
-         Screen *screen = FRAME_X_SCREEN (s->f);
-         int depth = DefaultDepthOfScreen (screen);
-
-         /* Create a pixmap as large as the glyph string.  */
-         pixmap = XCreatePixmap (s->display, s->window,
-                                 s->background_width,
-                                 s->height, depth);
-
-         /* Don't clip in the following because we're working on the
-            pixmap.  */
-         XSetClipMask (s->display, s->gc, None);
-
-         /* Fill the pixmap with the background color/stipple.  */
-         if (s->stippled_p)
-           {
-             /* Fill background with a stipple pattern.  */
-             XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
-             XFillRectangle (s->display, pixmap, s->gc,
-                             0, 0, s->background_width, s->height);
-             XSetFillStyle (s->display, s->gc, FillSolid);
-           }
-         else
-           {
-             XGCValues xgcv;
-             XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
-                           &xgcv);
-             XSetForeground (s->display, s->gc, xgcv.background);
-             XFillRectangle (s->display, pixmap, s->gc,
-                             0, 0, s->background_width, s->height);
-             XSetForeground (s->display, s->gc, xgcv.foreground);
-           }
-       }
-      else
-       x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
-
-      s->background_filled_p = 1;
-    }
-
-  /* Draw the foreground.  */
-  if (pixmap != None)
-    {
-      x_draw_image_foreground_1 (s, pixmap);
-      x_set_glyph_string_clipping (s);
-      XCopyArea (s->display, pixmap, s->window, s->gc,
-                0, 0, s->background_width, s->height, s->x, s->y);
-      XFreePixmap (s->display, pixmap);
-    }
-  else
-    x_draw_image_foreground (s);
-
-  /* If we must draw a relief around the image, do it.  */
-  if (s->img->relief
-      || s->hl == DRAW_IMAGE_RAISED
-      || s->hl == DRAW_IMAGE_SUNKEN)
-    x_draw_image_relief (s);
-}
-
-
-/* Draw stretch glyph string S.  */
-
-static void
-x_draw_stretch_glyph_string (s)
-     struct glyph_string *s;
-{
-  xassert (s->first_glyph->type == STRETCH_GLYPH);
-  s->stippled_p = s->face->stipple != 0;
-
-  if (s->hl == DRAW_CURSOR
-      && !x_stretch_cursor_p)
-    {
-      /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
-        as wide as the stretch glyph.  */
-      int width = min (CANON_X_UNIT (s->f), s->background_width);
-
-      /* Draw cursor.  */
-      x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
-
-      /* Clear rest using the GC of the original non-cursor face.  */
-      if (width < s->background_width)
-       {
-         int x = s->x + width, y = s->y;
-         int w = s->background_width - width, h = s->height;
-         XRectangle r;
-         GC gc;
-
-         if (s->row->mouse_face_p
-             && cursor_in_mouse_face_p (s->w))
-           {
-             x_set_mouse_face_gc (s);
-             gc = s->gc;
-           }
-         else
-           gc = s->face->gc;
-
-         x_get_glyph_string_clip_rect (s, &r);
-         XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
-
-         if (s->face->stipple)
-           {
-             /* Fill background with a stipple pattern.  */
-             XSetFillStyle (s->display, gc, FillOpaqueStippled);
-             XFillRectangle (s->display, s->window, gc, x, y, w, h);
-             XSetFillStyle (s->display, gc, FillSolid);
-           }
-         else
-           {
-             XGCValues xgcv;
-             XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
-             XSetForeground (s->display, gc, xgcv.background);
-             XFillRectangle (s->display, s->window, gc, x, y, w, h);
-             XSetForeground (s->display, gc, xgcv.foreground);
-           }
-       }
-    }
-  else if (!s->background_filled_p)
-    x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
-                                s->height);
-
-  s->background_filled_p = 1;
-}
-
-
-/* Draw glyph string S.  */
-
-static void
-x_draw_glyph_string (s)
-     struct glyph_string *s;
-{
-  int relief_drawn_p = 0;
-
-  /* If S draws into the background of its successor, draw the
-     background of the successor first so that S can draw into it.
-     This makes S->next use XDrawString instead of XDrawImageString.  */
-  if (s->next && s->right_overhang && !s->for_overlaps_p)
-    {
-      xassert (s->next->img == NULL);
-      x_set_glyph_string_gc (s->next);
-      x_set_glyph_string_clipping (s->next);
-      x_draw_glyph_string_background (s->next, 1);
-    }
-
-  /* Set up S->gc, set clipping and draw S.  */
-  x_set_glyph_string_gc (s);
-
-  /* Draw relief (if any) in advance for char/composition so that the
-     glyph string can be drawn over it.  */
-  if (!s->for_overlaps_p
-      && s->face->box != FACE_NO_BOX
-      && (s->first_glyph->type == CHAR_GLYPH
-         || s->first_glyph->type == COMPOSITE_GLYPH))
-
-    {
-      x_set_glyph_string_clipping (s);
-      x_draw_glyph_string_background (s, 1);
-      x_draw_glyph_string_box (s);
-      x_set_glyph_string_clipping (s);
-      relief_drawn_p = 1;
-    }
-  else
-    x_set_glyph_string_clipping (s);
-
-  switch (s->first_glyph->type)
-    {
-    case IMAGE_GLYPH:
-      x_draw_image_glyph_string (s);
-      break;
-
-    case STRETCH_GLYPH:
-      x_draw_stretch_glyph_string (s);
-      break;
-
-    case CHAR_GLYPH:
-      if (s->for_overlaps_p)
-       s->background_filled_p = 1;
-      else
-       x_draw_glyph_string_background (s, 0);
-      x_draw_glyph_string_foreground (s);
-      break;
-
-    case COMPOSITE_GLYPH:
-      if (s->for_overlaps_p || s->gidx > 0)
-       s->background_filled_p = 1;
-      else
-       x_draw_glyph_string_background (s, 1);
-      x_draw_composite_glyph_string_foreground (s);
-      break;
-
-    default:
-      abort ();
-    }
-
-  if (!s->for_overlaps_p)
-    {
-      /* Draw underline.  */
-      if (s->face->underline_p)
-       {
-         unsigned long tem, h;
-         int y;
-
-         /* Get the underline thickness.  Default is 1 pixel.  */
-         if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
-           h = 1;
-
-         /* Get the underline position.  This is the recommended
-            vertical offset in pixels from the baseline to the top of
-            the underline.  This is a signed value according to the
-            specs, and its default is
-
-            ROUND ((maximum descent) / 2), with
-            ROUND(x) = floor (x + 0.5)  */
-
-         if (x_use_underline_position_properties
-             && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
-           y = s->ybase + (long) tem;
-         else if (s->face->font)
-           y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
-         else
-           y = s->y + s->height - h;
-
-         if (s->face->underline_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc,
-                           s->x, y, s->width, h);
-         else
-           {
-             XGCValues xgcv;
-             XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
-             XSetForeground (s->display, s->gc, s->face->underline_color);
-             XFillRectangle (s->display, s->window, s->gc,
-                             s->x, y, s->width, h);
-             XSetForeground (s->display, s->gc, xgcv.foreground);
-           }
-       }
-
-      /* Draw overline.  */
-      if (s->face->overline_p)
-       {
-         unsigned long dy = 0, h = 1;
-
-         if (s->face->overline_color_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->width, h);
-         else
-           {
-             XGCValues xgcv;
-             XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
-             XSetForeground (s->display, s->gc, s->face->overline_color);
-             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->width, h);
-             XSetForeground (s->display, s->gc, xgcv.foreground);
-           }
-       }
-
-      /* Draw strike-through.  */
-      if (s->face->strike_through_p)
-       {
-         unsigned long h = 1;
-         unsigned long dy = (s->height - h) / 2;
-
-         if (s->face->strike_through_color_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->width, h);
-         else
-           {
-             XGCValues xgcv;
-             XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
-             XSetForeground (s->display, s->gc, s->face->strike_through_color);
-             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->width, h);
-             XSetForeground (s->display, s->gc, xgcv.foreground);
-           }
-       }
-
-      /* Draw relief if not yet drawn.  */
-      if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
-       x_draw_glyph_string_box (s);
-    }
-
-  /* Reset clipping.  */
-  XSetClipMask (s->display, s->gc, None);
-}
-
-
-static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
-                                             struct face **, int));
-
-
-/* Fill glyph string S with composition components specified by S->cmp.
-
-   FACES is an array of faces for all components of this composition.
-   S->gidx is the index of the first component for S.
-   OVERLAPS_P non-zero means S should draw the foreground only, and
-   use its physical height for clipping.
-
-   Value is the index of a component not in S.  */
-
-static int
-x_fill_composite_glyph_string (s, faces, overlaps_p)
-     struct glyph_string *s;
-     struct face **faces;
-     int overlaps_p;
-{
-  int i;
-
-  xassert (s);
-
-  s->for_overlaps_p = overlaps_p;
-
-  s->face = faces[s->gidx];
-  s->font = s->face->font;
-  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
-
-  /* For all glyphs of this composition, starting at the offset
-     S->gidx, until we reach the end of the definition or encounter a
-     glyph that requires the different face, add it to S.  */
-  ++s->nchars;
-  for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
-    ++s->nchars;
-
-  /* All glyph strings for the same composition has the same width,
-     i.e. the width set for the first component of the composition.  */
-
-  s->width = s->first_glyph->pixel_width;
-
-  /* If the specified font could not be loaded, use the frame's
-     default font, but record the fact that we couldn't load it in
-     the glyph string so that we can draw rectangles for the
-     characters of the glyph string.  */
-  if (s->font == NULL)
-    {
-      s->font_not_found_p = 1;
-      s->font = FRAME_FONT (s->f);
-    }
-
-  /* Adjust base line for subscript/superscript text.  */
-  s->ybase += s->first_glyph->voffset;
-
-  xassert (s->face && s->face->gc);
-
-  /* This glyph string must always be drawn with 16-bit functions.  */
-  s->two_byte_p = 1;
-
-  return s->gidx + s->nchars;
-}
-
-
-/* Fill glyph string S from a sequence of character glyphs.
-
-   FACE_ID is the face id of the string.  START is the index of the
-   first glyph to consider, END is the index of the last + 1.
-   OVERLAPS_P non-zero means S should draw the foreground only, and
-   use its physical height for clipping.
-
-   Value is the index of the first glyph not in S.  */
-
-static int
-x_fill_glyph_string (s, face_id, start, end, overlaps_p)
-     struct glyph_string *s;
-     int face_id;
-     int start, end, overlaps_p;
-{
-  struct glyph *glyph, *last;
-  int voffset;
-  int glyph_not_available_p;
-
-  xassert (s->f == XFRAME (s->w->frame));
-  xassert (s->nchars == 0);
-  xassert (start >= 0 && end > start);
-
-  s->for_overlaps_p = overlaps_p,
-  glyph = s->row->glyphs[s->area] + start;
-  last = s->row->glyphs[s->area] + end;
-  voffset = glyph->voffset;
-
-  glyph_not_available_p = glyph->glyph_not_available_p;
-
-  while (glyph < last
-        && glyph->type == CHAR_GLYPH
-        && glyph->voffset == voffset
-        /* Same face id implies same font, nowadays.  */
-        && glyph->face_id == face_id
-        && glyph->glyph_not_available_p == glyph_not_available_p)
-    {
-      int two_byte_p;
-
-      s->face = x_get_glyph_face_and_encoding (s->f, glyph,
-                                              s->char2b + s->nchars,
-                                              &two_byte_p);
-      s->two_byte_p = two_byte_p;
-      ++s->nchars;
-      xassert (s->nchars <= end - start);
-      s->width += glyph->pixel_width;
-      ++glyph;
-    }
-
-  s->font = s->face->font;
-  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
-
-  /* If the specified font could not be loaded, use the frame's font,
-     but record the fact that we couldn't load it in
-     S->font_not_found_p so that we can draw rectangles for the
-     characters of the glyph string.  */
-  if (s->font == NULL || glyph_not_available_p)
-    {
-      s->font_not_found_p = 1;
-      s->font = FRAME_FONT (s->f);
-    }
-
-  /* Adjust base line for subscript/superscript text.  */
-  s->ybase += voffset;
-
-  xassert (s->face && s->face->gc);
-  return glyph - s->row->glyphs[s->area];
-}
-
-
-/* Fill glyph string S from image glyph S->first_glyph.  */
-
-static void
-x_fill_image_glyph_string (s)
-     struct glyph_string *s;
-{
-  xassert (s->first_glyph->type == IMAGE_GLYPH);
-  s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
-  xassert (s->img);
-  s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
-  s->font = s->face->font;
-  s->width = s->first_glyph->pixel_width;
-
-  /* Adjust base line for subscript/superscript text.  */
-  s->ybase += s->first_glyph->voffset;
-}
-
-
-/* Fill glyph string S from a sequence of stretch glyphs.
-
-   ROW is the glyph row in which the glyphs are found, AREA is the
-   area within the row.  START is the index of the first glyph to
-   consider, END is the index of the last + 1.
-
-   Value is the index of the first glyph not in S.  */
-
-static int
-x_fill_stretch_glyph_string (s, row, area, start, end)
-     struct glyph_string *s;
-     struct glyph_row *row;
-     enum glyph_row_area area;
-     int start, end;
-{
-  struct glyph *glyph, *last;
-  int voffset, face_id;
-
-  xassert (s->first_glyph->type == STRETCH_GLYPH);
-
-  glyph = s->row->glyphs[s->area] + start;
-  last = s->row->glyphs[s->area] + end;
-  face_id = glyph->face_id;
-  s->face = FACE_FROM_ID (s->f, face_id);
-  s->font = s->face->font;
-  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
-  s->width = glyph->pixel_width;
-  voffset = glyph->voffset;
-
-  for (++glyph;
-       (glyph < last
-       && glyph->type == STRETCH_GLYPH
-       && glyph->voffset == voffset
-       && glyph->face_id == face_id);
-       ++glyph)
-    s->width += glyph->pixel_width;
-
-  /* Adjust base line for subscript/superscript text.  */
-  s->ybase += voffset;
-
-  /* The case that face->gc == 0 is handled when drawing the glyph
-     string by calling PREPARE_FACE_FOR_DISPLAY.  */
-  xassert (s->face);
-  return glyph - s->row->glyphs[s->area];
-}
-
-
-/* Initialize glyph string S.  CHAR2B is a suitably allocated vector
-   of XChar2b structures for S; it can't be allocated in
-   x_init_glyph_string because it must be allocated via `alloca'.  W
-   is the window on which S is drawn.  ROW and AREA are the glyph row
-   and area within the row from which S is constructed.  START is the
-   index of the first glyph structure covered by S.  HL is a
-   face-override for drawing S.  */
-
-static void
-x_init_glyph_string (s, char2b, w, row, area, start, hl)
-     struct glyph_string *s;
-     XChar2b *char2b;
-     struct window *w;
-     struct glyph_row *row;
-     enum glyph_row_area area;
-     int start;
-     enum draw_glyphs_face hl;
-{
-  bzero (s, sizeof *s);
-  s->w = w;
-  s->f = XFRAME (w->frame);
-  s->display = FRAME_X_DISPLAY (s->f);
-  s->window = FRAME_X_WINDOW (s->f);
-  s->char2b = char2b;
-  s->hl = hl;
-  s->row = row;
-  s->area = area;
-  s->first_glyph = row->glyphs[area] + start;
-  s->height = row->height;
-  s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
-
-  /* Display the internal border below the tool-bar window.  */
-  if (s->w == XWINDOW (s->f->tool_bar_window))
-    s->y -= s->f->output_data.x->internal_border_width;
-
-  s->ybase = s->y + row->ascent;
-}
-
-
-/* Set background width of glyph string S.  START is the index of the
-   first glyph following S.  LAST_X is the right-most x-position + 1
-   in the drawing area.  */
-
-static INLINE void
-x_set_glyph_string_background_width (s, start, last_x)
-     struct glyph_string *s;
-     int start;
-     int last_x;
-{
-  /* If the face of this glyph string has to be drawn to the end of
-     the drawing area, set S->extends_to_end_of_line_p.  */
-  struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
-
-  if (start == s->row->used[s->area]
-      && s->area == TEXT_AREA
-      && ((s->hl == DRAW_NORMAL_TEXT
-          && (s->row->fill_line_p
-              || s->face->background != default_face->background
-              || s->face->stipple != default_face->stipple
-              || s->row->mouse_face_p))
-         || s->hl == DRAW_MOUSE_FACE
-         || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
-             && s->row->fill_line_p)))
-      s->extends_to_end_of_line_p = 1;
-
-  /* If S extends its face to the end of the line, set its
-     background_width to the distance to the right edge of the drawing
-     area.  */
-  if (s->extends_to_end_of_line_p)
-    s->background_width = last_x - s->x + 1;
-  else
-    s->background_width = s->width;
-}
-
-
-/* Add a glyph string for a stretch glyph to the list of strings
-   between HEAD and TAIL.  START is the index of the stretch glyph in
-   row area AREA of glyph row ROW.  END is the index of the last glyph
-   in that glyph row area.  X is the current output position assigned
-   to the new glyph string constructed.  HL overrides that face of the
-   glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn.  LAST_X
-   is the right-most x-position of the drawing area.  */
-
-/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
-   and below -- keep them on one line.  */
-#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
-     do                                                                            \
-       {                                                                   \
-        s = (struct glyph_string *) alloca (sizeof *s);                    \
-        x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL);            \
-        START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END);    \
-        x_append_glyph_string (&HEAD, &TAIL, s);                           \
-         s->x = (X);                                                       \
-       }                                                                   \
-     while (0)
-
-
-/* Add a glyph string for an image glyph to the list of strings
-   between HEAD and TAIL.  START is the index of the image glyph in
-   row area AREA of glyph row ROW.  END is the index of the last glyph
-   in that glyph row area.  X is the current output position assigned
-   to the new glyph string constructed.  HL overrides that face of the
-   glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn.  LAST_X
-   is the right-most x-position of the drawing area.  */
-
-#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
-     do                                                                        \
-       {                                                               \
-        s = (struct glyph_string *) alloca (sizeof *s);                \
-        x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL);        \
-        x_fill_image_glyph_string (s);                                 \
-        x_append_glyph_string (&HEAD, &TAIL, s);                       \
-        ++START;                                                       \
-         s->x = (X);                                                   \
-       }                                                               \
-     while (0)
-
-
-/* Add a glyph string for a sequence of character glyphs to the list
-   of strings between HEAD and TAIL.  START is the index of the first
-   glyph in row area AREA of glyph row ROW that is part of the new
-   glyph string.  END is the index of the last glyph in that glyph row
-   area.  X is the current output position assigned to the new glyph
-   string constructed.  HL overrides that face of the glyph; e.g. it
-   is DRAW_CURSOR if a cursor has to be drawn.  LAST_X is the
-   right-most x-position of the drawing area.  */
-
-#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
-     do                                                                           \
-       {                                                                  \
-        int c, face_id;                                                   \
-        XChar2b *char2b;                                                  \
-                                                                          \
-        c = (ROW)->glyphs[AREA][START].u.ch;                              \
-        face_id = (ROW)->glyphs[AREA][START].face_id;                     \
-                                                                          \
-        s = (struct glyph_string *) alloca (sizeof *s);                   \
-        char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b);     \
-        x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL);         \
-        x_append_glyph_string (&HEAD, &TAIL, s);                          \
-        s->x = (X);                                                       \
-        START = x_fill_glyph_string (s, face_id, START, END,              \
-                                          OVERLAPS_P);                    \
-       }                                                                  \
-     while (0)
-
-
-/* Add a glyph string for a composite sequence to the list of strings
-   between HEAD and TAIL.  START is the index of the first glyph in
-   row area AREA of glyph row ROW that is part of the new glyph
-   string.  END is the index of the last glyph in that glyph row area.
-   X is the current output position assigned to the new glyph string
-   constructed.  HL overrides that face of the glyph; e.g. it is
-   DRAW_CURSOR if a cursor has to be drawn.  LAST_X is the right-most
-   x-position of the drawing area.  */
-
-#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P)    \
-  do {                                                                   \
-    int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id;                    \
-    int face_id = (ROW)->glyphs[AREA][START].face_id;                    \
-    struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id);          \
-    struct composition *cmp = composition_table[cmp_id];                 \
-    int glyph_len = cmp->glyph_len;                                      \
-    XChar2b *char2b;                                                     \
-    struct face **faces;                                                 \
-    struct glyph_string *first_s = NULL;                                 \
-    int n;                                                               \
-                                                                         \
-    base_face = base_face->ascii_face;                                   \
-    char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len);                  \
-    faces = (struct face **) alloca ((sizeof *faces) * glyph_len);       \
-    /* At first, fill in `char2b' and `faces'.  */                       \
-    for (n = 0; n < glyph_len; n++)                                      \
-      {                                                                          \
-       int c = COMPOSITION_GLYPH (cmp, n);                               \
-       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, 1);    \
-      }                                                                          \
-                                                                         \
-    /* Make glyph_strings for each glyph sequence that is drawable by    \
-       the same face, and append them to HEAD/TAIL.  */                          \
-    for (n = 0; n < cmp->glyph_len;)                                     \
-      {                                                                          \
-       s = (struct glyph_string *) alloca (sizeof *s);                   \
-       x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL);     \
-       x_append_glyph_string (&(HEAD), &(TAIL), s);                      \
-       s->cmp = cmp;                                                     \
-       s->gidx = n;                                                      \
-       s->x = (X);                                                       \
-                                                                         \
-       if (n == 0)                                                       \
-         first_s = s;                                                    \
-                                                                         \
-       n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P);         \
-      }                                                                          \
-                                                                         \
-    ++START;                                                             \
-    s = first_s;                                                         \
-  } while (0)
-
-
-/* Build a list of glyph strings between HEAD and TAIL for the glyphs
-   of AREA of glyph row ROW on window W between indices START and END.
-   HL overrides the face for drawing glyph strings, e.g. it is
-   DRAW_CURSOR to draw a cursor.  X and LAST_X are start and end
-   x-positions of the drawing area.
-
-   This is an ugly monster macro construct because we must use alloca
-   to allocate glyph strings (because x_draw_glyphs can be called
-   asynchronously).  */
-
-#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
-     do                                                                           \
-       {                                                                  \
-        HEAD = TAIL = NULL;                                               \
-        while (START < END)                                               \
-          {                                                               \
-             struct glyph *first_glyph = (ROW)->glyphs[AREA] + START;     \
-             switch (first_glyph->type)                                           \
-              {                                                           \
-              case CHAR_GLYPH:                                            \
-                 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
-                                          TAIL, HL, X, LAST_X,            \
-                                           OVERLAPS_P);                           \
-                break;                                                    \
-                                                                          \
-              case COMPOSITE_GLYPH:                                       \
-                 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END,   \
-                                                HEAD, TAIL, HL, X, LAST_X,\
-                                                OVERLAPS_P);              \
-                break;                                                    \
-                                                                          \
-              case STRETCH_GLYPH:                                         \
-                BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END,     \
-                                            HEAD, TAIL, HL, X, LAST_X);   \
-                break;                                                    \
-                                                                          \
-              case IMAGE_GLYPH:                                           \
-                BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
-                                          TAIL, HL, X, LAST_X);           \
-                break;                                                    \
-                                                                          \
-              default:                                                    \
-                abort ();                                                 \
-              }                                                           \
-                                                                          \
-             x_set_glyph_string_background_width (s, START, LAST_X);      \
-            (X) += s->width;                                              \
-            }                                                             \
-       }                                                                  \
-     while (0)
-
-
-/* Draw glyphs between START and END in AREA of ROW on window W,
-   starting at x-position X.  X is relative to AREA in W.  HL is a
-   face-override with the following meaning:
-
-   DRAW_NORMAL_TEXT    draw normally
-   DRAW_CURSOR         draw in cursor face
-   DRAW_MOUSE_FACE     draw in mouse face.
-   DRAW_INVERSE_VIDEO  draw in mode line face
-   DRAW_IMAGE_SUNKEN   draw an image with a sunken relief around it
-   DRAW_IMAGE_RAISED   draw an image with a raised relief around it
-
-   If OVERLAPS_P is non-zero, draw only the foreground of characters
-   and clip to the physical height of ROW.
-
-   Value is the x-position reached, relative to AREA of W.  */
-
-static int
-x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
-     struct window *w;
-     int x;
-     struct glyph_row *row;
-     enum glyph_row_area area;
-     int start, end;
-     enum draw_glyphs_face hl;
-     int overlaps_p;
-{
-  struct glyph_string *head, *tail;
-  struct glyph_string *s;
-  int last_x, area_width;
-  int x_reached;
-  int i, j;
-
-  /* Let's rather be paranoid than getting a SEGV.  */
-  end = min (end, row->used[area]);
-  start = max (0, start);
-  start = min (end, start);
-
-  /* Translate X to frame coordinates.  Set last_x to the right
-     end of the drawing area.  */
-  if (row->full_width_p)
-    {
-      /* X is relative to the left edge of W, without scroll bars
-        or fringes.  */
-      struct frame *f = XFRAME (w->frame);
-      int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
-
-      x += window_left_x;
-      area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
-      last_x = window_left_x + area_width;
-
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-       {
-         int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
-         if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
-           last_x += width;
-         else
-           x -= width;
-       }
-
-      x += FRAME_INTERNAL_BORDER_WIDTH (f);
-      last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
-    }
-  else
-    {
-      x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
-      area_width = window_box_width (w, area);
-      last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
-    }
-
-  /* Build a doubly-linked list of glyph_string structures between
-     head and tail from what we have to draw.  Note that the macro
-     BUILD_GLYPH_STRINGS will modify its start parameter.  That's
-     the reason we use a separate variable `i'.  */
-  i = start;
-  BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
-                      overlaps_p);
-  if (tail)
-    x_reached = tail->x + tail->background_width;
-  else
-    x_reached = x;
-
-  /* If there are any glyphs with lbearing < 0 or rbearing > width in
-     the row, redraw some glyphs in front or following the glyph
-     strings built above.  */
-  if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
-    {
-      int dummy_x = 0;
-      struct glyph_string *h, *t;
-
-      /* Compute overhangs for all glyph strings.  */
-      for (s = head; s; s = s->next)
-       x_compute_glyph_string_overhangs (s);
-
-      /* Prepend glyph strings for glyphs in front of the first glyph
-        string that are overwritten because of the first glyph
-        string's left overhang.  The background of all strings
-        prepended must be drawn because the first glyph string
-        draws over it.  */
-      i = x_left_overwritten (head);
-      if (i >= 0)
-       {
-         j = i;
-         BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
-                              DRAW_NORMAL_TEXT, dummy_x, last_x,
-                              overlaps_p);
-         start = i;
-         x_compute_overhangs_and_x (t, head->x, 1);
-         x_prepend_glyph_string_lists (&head, &tail, h, t);
-       }
-
-      /* Prepend glyph strings for glyphs in front of the first glyph
-        string that overwrite that glyph string because of their
-        right overhang.  For these strings, only the foreground must
-        be drawn, because it draws over the glyph string at `head'.
-        The background must not be drawn because this would overwrite
-        right overhangs of preceding glyphs for which no glyph
-        strings exist.  */
-      i = x_left_overwriting (head);
-      if (i >= 0)
-       {
-         BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
-                              DRAW_NORMAL_TEXT, dummy_x, last_x,
-                              overlaps_p);
-         for (s = h; s; s = s->next)
-           s->background_filled_p = 1;
-         x_compute_overhangs_and_x (t, head->x, 1);
-         x_prepend_glyph_string_lists (&head, &tail, h, t);
-       }
-
-      /* Append glyphs strings for glyphs following the last glyph
-        string tail that are overwritten by tail.  The background of
-        these strings has to be drawn because tail's foreground draws
-        over it.  */
-      i = x_right_overwritten (tail);
-      if (i >= 0)
-       {
-         BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
-                              DRAW_NORMAL_TEXT, x, last_x,
-                              overlaps_p);
-         x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
-         x_append_glyph_string_lists (&head, &tail, h, t);
-       }
-
-      /* Append glyph strings for glyphs following the last glyph
-        string tail that overwrite tail.  The foreground of such
-        glyphs has to be drawn because it writes into the background
-        of tail.  The background must not be drawn because it could
-        paint over the foreground of following glyphs.  */
-      i = x_right_overwriting (tail);
-      if (i >= 0)
-       {
-         BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
-                              DRAW_NORMAL_TEXT, x, last_x,
-                              overlaps_p);
-         for (s = h; s; s = s->next)
-           s->background_filled_p = 1;
-         x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
-         x_append_glyph_string_lists (&head, &tail, h, t);
-       }
-    }
-
-  /* Draw all strings.  */
-  for (s = head; s; s = s->next)
-    x_draw_glyph_string (s);
-
-  if (area == TEXT_AREA
-      && !row->full_width_p
-      /* When drawing overlapping rows, only the glyph strings'
-        foreground is drawn, which doesn't erase a cursor
-        completely. */
-      && !overlaps_p)
-    {
-      int x0 = head ? head->x : x;
-      int x1 = tail ? tail->x + tail->background_width : x;
-
-      x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
-      x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
-
-      if (XFASTINT (w->left_margin_width) != 0)
-       {
-         int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
-         x0 -= left_area_width;
-         x1 -= left_area_width;
-       }
-
-      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.
-     This doesn't include parts drawn because of overhangs.  */
-  x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
-  if (!row->full_width_p)
-    {
-      if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
-       x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
-      if (area > TEXT_AREA)
-       x_reached -= window_box_width (w, TEXT_AREA);
-    }
-
-  return x_reached;
-}
-
-
-/* Fix the display of area AREA of overlapping row ROW in window W.  */
-
-static void
-x_fix_overlapping_area (w, row, area)
-     struct window *w;
-     struct glyph_row *row;
-     enum glyph_row_area area;
-{
-  int i, x;
-
-  BLOCK_INPUT;
-
-  if (area == LEFT_MARGIN_AREA)
-    x = 0;
-  else if (area == TEXT_AREA)
-    x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
-  else
-    x = (window_box_width (w, LEFT_MARGIN_AREA)
-        + window_box_width (w, TEXT_AREA));
-
-  for (i = 0; i < row->used[area];)
-    {
-      if (row->glyphs[area][i].overlaps_vertically_p)
-       {
-         int start = i, start_x = x;
-
-         do
-           {
-             x += row->glyphs[area][i].pixel_width;
-             ++i;
-           }
-         while (i < row->used[area]
-                && row->glyphs[area][i].overlaps_vertically_p);
-
-         x_draw_glyphs (w, start_x, row, area, start, i,
-                        DRAW_NORMAL_TEXT, 1);
-       }
-      else
-       {
-         x += row->glyphs[area][i].pixel_width;
-         ++i;
-       }
-    }
-
-  UNBLOCK_INPUT;
-}
-
-
-/* Output LEN glyphs starting at START at the nominal cursor position.
-   Advance the nominal cursor over the text.  The global variable
-   updated_window contains the window being updated, updated_row is
-   the glyph row being updated, and updated_area is the area of that
-   row being updated.  */
-
-static void
-x_write_glyphs (start, len)
-     struct glyph *start;
-     int len;
-{
-  int x, hpos;
-
-  xassert (updated_window && updated_row);
-  BLOCK_INPUT;
-
-  /* Write glyphs.  */
-
-  hpos = start - updated_row->glyphs[updated_area];
-  x = x_draw_glyphs (updated_window, output_cursor.x,
-                    updated_row, updated_area,
-                    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.  */
-  output_cursor.hpos += len;
-  output_cursor.x = x;
-}
-
-
-/* Insert LEN glyphs from START at the nominal cursor position.   */
-
-static void
-x_insert_glyphs (start, len)
-     struct glyph *start;
-     register int len;
-{
-  struct frame *f;
-  struct window *w;
-  int line_height, shift_by_width, shifted_region_width;
-  struct glyph_row *row;
-  struct glyph *glyph;
-  int frame_x, frame_y, hpos;
-
-  xassert (updated_window && updated_row);
-  BLOCK_INPUT;
-  w = updated_window;
-  f = XFRAME (WINDOW_FRAME (w));
-
-  /* Get the height of the line we are in.  */
-  row = updated_row;
-  line_height = row->height;
-
-  /* Get the width of the glyphs to insert.  */
-  shift_by_width = 0;
-  for (glyph = start; glyph < start + len; ++glyph)
-    shift_by_width += glyph->pixel_width;
-
-  /* Get the width of the region to shift right.  */
-  shifted_region_width = (window_box_width (w, updated_area)
-                         - output_cursor.x
-                         - shift_by_width);
-
-  /* Shift right.  */
-  frame_x = window_box_left (w, updated_area) + output_cursor.x;
-  frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
-  XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
-            f->output_data.x->normal_gc,
-            frame_x, frame_y,
-            shifted_region_width, line_height,
-            frame_x + shift_by_width, frame_y);
-
-  /* Write the glyphs.  */
-  hpos = start - row->glyphs[updated_area];
-  x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
-                DRAW_NORMAL_TEXT, 0);
-
-  /* Advance the output cursor.  */
-  output_cursor.hpos += len;
-  output_cursor.x += shift_by_width;
-  UNBLOCK_INPUT;
-}
-
-
-/* Delete N glyphs at the nominal cursor position.  Not implemented
-   for X frames.  */
-
-static void
-x_delete_glyphs (n)
-     register int n;
-{
-  abort ();
-}
-
-
-/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
-   If they are <= 0, this is probably an error.  */
-
-void
-x_clear_area (dpy, window, x, y, width, height, exposures)
-     Display *dpy;
-     Window window;
-     int x, y;
-     int width, height;
-     int exposures;
-{
-  xassert (width > 0 && height > 0);
-  XClearArea (dpy, window, x, y, width, height, exposures);
-}
-
-
-/* Erase the current text line from the nominal cursor position
-   (inclusive) to pixel column TO_X (exclusive).  The idea is that
-   everything from TO_X onward is already erased.
-
-   TO_X is a pixel position relative to updated_area of
-   updated_window.  TO_X == -1 means clear to the end of this area.  */
-
-static void
-x_clear_end_of_line (to_x)
-     int to_x;
-{
-  struct frame *f;
-  struct window *w = updated_window;
-  int max_x, min_y, max_y;
-  int from_x, from_y, to_y;
-
-  xassert (updated_window && updated_row);
-  f = XFRAME (w->frame);
-
-  if (updated_row->full_width_p)
-    {
-      max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
-         && !w->pseudo_window_p)
-       max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
-    }
-  else
-    max_x = window_box_width (w, updated_area);
-  max_y = window_text_bottom_y (w);
-
-  /* TO_X == 0 means don't do anything.  TO_X < 0 means clear to end
-     of window.  For TO_X > 0, truncate to end of drawing area.  */
-  if (to_x == 0)
-    return;
-  else if (to_x < 0)
-    to_x = max_x;
-  else
-    to_x = min (to_x, max_x);
-
-  to_y = min (max_y, output_cursor.y + updated_row->height);
-
-  /* Notice if the cursor will be cleared by this operation.  */
-  if (!updated_row->full_width_p)
-    notice_overwritten_cursor (w, updated_area,
-                              output_cursor.x, -1,
-                              updated_row->y,
-                              MATRIX_ROW_BOTTOM_Y (updated_row));
-
-  from_x = output_cursor.x;
-
-  /* Translate to frame coordinates.  */
-  if (updated_row->full_width_p)
-    {
-      from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
-      to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
-    }
-  else
-    {
-      from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
-      to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
-    }
-
-  min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-  from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
-  to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
-
-  /* Prevent inadvertently clearing to end of the X window.  */
-  if (to_x > from_x && to_y > from_y)
-    {
-      BLOCK_INPUT;
-      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   from_x, from_y, to_x - from_x, to_y - from_y,
-                   False);
-      UNBLOCK_INPUT;
-    }
-}
-
-
-/* Clear entire frame.  If updating_frame is non-null, clear that
-   frame.  Otherwise clear the selected frame.  */
-
-static void
-x_clear_frame ()
-{
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
-  /* Clearing the frame will erase any cursor, so mark them all as no
-     longer visible.  */
-  mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
-  output_cursor.hpos = output_cursor.vpos = 0;
-  output_cursor.x = -1;
-
-  /* We don't set the output cursor here because there will always
-     follow an explicit cursor_to.  */
-  BLOCK_INPUT;
-  XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-
-  /* We have to clear the scroll bars, too.  If we have changed
-     colors or something like that, then they should be notified.  */
-  x_scroll_bar_clear (f);
-
-  XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
-}
-
-
-\f
-/* Invert the middle quarter of the frame for .15 sec.  */
-
-/* We use the select system call to do the waiting, so we have to make
-   sure it's available.  If it isn't, we just won't do visual bells.  */
-
-#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
-
-
-/* Subtract the `struct timeval' values X and Y, storing the result in
-   *RESULT.  Return 1 if the difference is negative, otherwise 0.  */
-
-static int
-timeval_subtract (result, x, y)
-     struct timeval *result, x, y;
-{
-  /* Perform the carry for the later subtraction by updating y.  This
-     is safer because on some systems the tv_sec member is unsigned.  */
-  if (x.tv_usec < y.tv_usec)
-    {
-      int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
-      y.tv_usec -= 1000000 * nsec;
-      y.tv_sec += nsec;
-    }
-
-  if (x.tv_usec - y.tv_usec > 1000000)
-    {
-      int nsec = (y.tv_usec - x.tv_usec) / 1000000;
-      y.tv_usec += 1000000 * nsec;
-      y.tv_sec -= nsec;
-    }
-
-  /* Compute the time remaining to wait.  tv_usec is certainly
-     positive.  */
-  result->tv_sec = x.tv_sec - y.tv_sec;
-  result->tv_usec = x.tv_usec - y.tv_usec;
-
-  /* Return indication of whether the result should be considered
-     negative.  */
-  return x.tv_sec < y.tv_sec;
-}
-
-void
-XTflash (f)
-     struct frame *f;
-{
-  BLOCK_INPUT;
-
-  {
-    GC gc;
-
-    /* Create a GC that will use the GXxor function to flip foreground
-       pixels into background pixels.  */
-    {
-      XGCValues values;
-
-      values.function = GXxor;
-      values.foreground = (f->output_data.x->foreground_pixel
-                          ^ f->output_data.x->background_pixel);
-
-      gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                     GCFunction | GCForeground, &values);
-    }
-
-    {
-      /* Get the height not including a menu bar widget.  */
-      int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
-      /* Height of each line to flash.  */
-      int flash_height = FRAME_LINE_HEIGHT (f);
-      /* These will be the left and right margins of the rectangles.  */
-      int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
-      int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
-
-      int width;
-
-      /* Don't flash the area between a scroll bar and the frame
-        edge it is next to.  */
-      switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
-       {
-       case vertical_scroll_bar_left:
-         flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
-         break;
-
-       case vertical_scroll_bar_right:
-         flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
-         break;
-
-       default:
-         break;
-       }
-
-      width = flash_right - flash_left;
-
-      /* If window is tall, flash top and bottom line.  */
-      if (height > 3 * FRAME_LINE_HEIGHT (f))
-       {
-         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                         flash_left,
-                         (FRAME_INTERNAL_BORDER_WIDTH (f)
-                          + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
-                         width, flash_height);
-         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                         flash_left,
-                         (height - flash_height
-                          - FRAME_INTERNAL_BORDER_WIDTH (f)),
-                         width, flash_height);
-       }
-      else
-       /* If it is short, flash it all.  */
-       XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                       flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
-                       width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
-
-      x_flush (f);
-
-      {
-       struct timeval wakeup;
-
-       EMACS_GET_TIME (wakeup);
-
-       /* Compute time to wait until, propagating carry from usecs.  */
-       wakeup.tv_usec += 150000;
-       wakeup.tv_sec += (wakeup.tv_usec / 1000000);
-       wakeup.tv_usec %= 1000000;
-
-       /* Keep waiting until past the time wakeup or any input gets
-          available.  */
-       while (! detect_input_pending ())
-         {
-           struct timeval current;
-           struct timeval timeout;
-
-           EMACS_GET_TIME (current);
-
-           /* Break if result would be negative.  */
-           if (timeval_subtract (&current, wakeup, current))
-             break;
-
-           /* How long `select' should wait.  */
-           timeout.tv_sec = 0;
-           timeout.tv_usec = 10000;
-
-           /* Try to wait that long--but we might wake up sooner.  */
-           select (0, NULL, NULL, NULL, &timeout);
-         }
-      }
-
-      /* If window is tall, flash top and bottom line.  */
-      if (height > 3 * FRAME_LINE_HEIGHT (f))
-       {
-         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                         flash_left,
-                         (FRAME_INTERNAL_BORDER_WIDTH (f)
-                          + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
-                         width, flash_height);
-         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                         flash_left,
-                         (height - flash_height
-                          - FRAME_INTERNAL_BORDER_WIDTH (f)),
-                         width, flash_height);
-       }
-      else
-       /* If it is short, flash it all.  */
-       XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
-                       flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
-                       width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
-
-      XFreeGC (FRAME_X_DISPLAY (f), gc);
-      x_flush (f);
-    }
-  }
-
-  UNBLOCK_INPUT;
-}
-
-#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
-
-
-/* Make audible bell.  */
-
-void
-XTring_bell ()
-{
-  struct frame *f = SELECTED_FRAME ();
-
-  if (FRAME_X_DISPLAY (f))
-    {
-#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
-      if (visible_bell)
-       XTflash (f);
-      else
-#endif
-       {
-         BLOCK_INPUT;
-         XBell (FRAME_X_DISPLAY (f), 0);
-         XFlush (FRAME_X_DISPLAY (f));
-         UNBLOCK_INPUT;
-       }
-    }
-}
-
-\f
-/* Specify how many text lines, from the top of the window,
-   should be affected by insert-lines and delete-lines operations.
-   This, and those operations, are used only within an update
-   that is bounded by calls to x_update_begin and x_update_end.  */
-
-static void
-XTset_terminal_window (n)
-     register int n;
-{
-  /* This function intentionally left blank.  */
-}
-
-
-\f
-/***********************************************************************
-                             Line Dance
- ***********************************************************************/
-
-/* Perform an insert-lines or delete-lines operation, inserting N
-   lines or deleting -N lines at vertical position VPOS.  */
-
-static void
-x_ins_del_lines (vpos, n)
-     int vpos, n;
-{
-  abort ();
-}
-
-
-/* Scroll part of the display as described by RUN.  */
-
-static void
-x_scroll_run (w, run)
-     struct window *w;
-     struct run *run;
-{
-  struct frame *f = XFRAME (w->frame);
-  int x, y, width, height, from_y, to_y, bottom_y;
-
-  /* Get frame-relative bounding box of the text display area of W,
-     without mode lines.  Include in this box the left and right
-     fringe of W.  */
-  window_box (w, -1, &x, &y, &width, &height);
-  width += FRAME_X_FRINGE_WIDTH (f);
-  x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
-
-  from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
-  to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
-  bottom_y = y + height;
-
-  if (to_y < from_y)
-    {
-      /* Scrolling up.  Make sure we don't copy part of the mode
-        line at the bottom.  */
-      if (from_y + run->height > bottom_y)
-       height = bottom_y - from_y;
-      else
-       height = run->height;
-    }
-  else
-    {
-      /* Scolling down.  Make sure we don't copy over the mode line.
-        at the bottom.  */
-      if (to_y + run->height > bottom_y)
-       height = bottom_y - to_y;
-      else
-       height = run->height;
-    }
-
-  BLOCK_INPUT;
-
-  /* Cursor off.  Will be switched on again in x_update_window_end.  */
-  updated_window = w;
-  x_clear_cursor (w);
-
-  XCopyArea (FRAME_X_DISPLAY (f),
-            FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
-            f->output_data.x->normal_gc,
-            x, from_y,
-            width, height,
-            x, to_y);
-
-  UNBLOCK_INPUT;
-}
-
-
-\f
-/***********************************************************************
-                          Exposure Events
- ***********************************************************************/
-
-/* Redisplay an exposed area of frame F.  X and Y are the upper-left
-   corner of the exposed rectangle.  W and H are width and height of
-   the exposed area.  All are pixel values.  W or H zero means redraw
-   the entire frame.  */
-
-static void
-expose_frame (f, x, y, w, h)
-     struct frame *f;
-     int x, y, w, h;
-{
-  XRectangle r;
-  int mouse_face_overwritten_p = 0;
-
-  TRACE ((stderr, "expose_frame "));
-
-  /* No need to redraw if frame will be redrawn soon.  */
-  if (FRAME_GARBAGED_P (f))
-    {
-      TRACE ((stderr, " garbaged\n"));
-      return;
-    }
-
-  /* If basic faces haven't been realized yet, there is no point in
-     trying to redraw anything.  This can happen when we get an expose
-     event while Emacs is starting, e.g. by moving another window.  */
-  if (FRAME_FACE_CACHE (f) == NULL
-      || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
-    {
-      TRACE ((stderr, " no faces\n"));
-      return;
-    }
-
-  if (w == 0 || h == 0)
-    {
-      r.x = r.y = 0;
-      r.width = CANON_X_UNIT (f) * f->width;
-      r.height = CANON_Y_UNIT (f) * f->height;
-    }
-  else
-    {
-      r.x = x;
-      r.y = y;
-      r.width = w;
-      r.height = h;
-    }
-
-  TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
-  mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
-
-  if (WINDOWP (f->tool_bar_window))
-    mouse_face_overwritten_p
-      |= expose_window (XWINDOW (f->tool_bar_window), &r);
-
-#ifndef USE_X_TOOLKIT
-  if (WINDOWP (f->menu_bar_window))
-    mouse_face_overwritten_p
-      |= expose_window (XWINDOW (f->menu_bar_window), &r);
-#endif /* not USE_X_TOOLKIT */
-
-  /* Some window managers support a focus-follows-mouse style with
-     delayed raising of frames.  Imagine a partially obscured frame,
-     and moving the mouse into partially obscured mouse-face on that
-     frame.  The visible part of the mouse-face will be highlighted,
-     then the WM raises the obscured frame.  With at least one WM, KDE
-     2.1, Emacs is not getting any event for the raising of the frame
-     (even tried with SubstructureRedirectMask), only Expose events.
-     These expose events will draw text normally, i.e. not
-     highlighted.  Which means we must redo the highlight here.
-     Subsume it under ``we love X''.  --gerd 2001-08-15  */
-  if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
-    {
-      struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-      if (f == dpyinfo->mouse_face_mouse_frame)
-       {
-         int x = dpyinfo->mouse_face_mouse_x;
-         int y = dpyinfo->mouse_face_mouse_y;
-         clear_mouse_face (dpyinfo);
-         note_mouse_highlight (f, x, y);
-       }
-    }
-}
-
-
-/* Redraw (parts) of all windows in the window tree rooted at W that
-   intersect R.  R contains frame pixel coordinates.  Value is
-   non-zero if the exposure overwrites mouse-face.  */
-
-static int
-expose_window_tree (w, r)
-     struct window *w;
-     XRectangle *r;
-{
-  struct frame *f = XFRAME (w->frame);
-  int mouse_face_overwritten_p = 0;
-
-  while (w && !FRAME_GARBAGED_P (f))
-    {
-      if (!NILP (w->hchild))
-       mouse_face_overwritten_p
-         |= expose_window_tree (XWINDOW (w->hchild), r);
-      else if (!NILP (w->vchild))
-       mouse_face_overwritten_p
-         |= expose_window_tree (XWINDOW (w->vchild), r);
-      else
-       mouse_face_overwritten_p |= expose_window (w, r);
-
-      w = NILP (w->next) ? NULL : XWINDOW (w->next);
-    }
-
-  return mouse_face_overwritten_p;
-}
-
-
-/* Redraw the part of glyph row area AREA of glyph row ROW on window W
-   which intersects rectangle R.  R is in window-relative coordinates.  */
-
-static void
-expose_area (w, row, r, area)
-     struct window *w;
-     struct glyph_row *row;
-     XRectangle *r;
-     enum glyph_row_area area;
-{
-  struct glyph *first = row->glyphs[area];
-  struct glyph *end = row->glyphs[area] + row->used[area];
-  struct glyph *last;
-  int first_x, start_x, x;
-
-  if (area == TEXT_AREA && row->fill_line_p)
-    /* If row extends face to end of line write the whole line.  */
-    x_draw_glyphs (w, 0, row, area, 0, row->used[area],
-                  DRAW_NORMAL_TEXT, 0);
-  else
-    {
-      /* Set START_X to the window-relative start position for drawing glyphs of
-        AREA.  The first glyph of the text area can be partially visible.
-        The first glyphs of other areas cannot.  */
-      if (area == LEFT_MARGIN_AREA)
-       start_x = 0;
-      else if (area == TEXT_AREA)
-       start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
-      else
-       start_x = (window_box_width (w, LEFT_MARGIN_AREA)
-                  + window_box_width (w, TEXT_AREA));
-      x = start_x;
-
-      /* Find the first glyph that must be redrawn.  */
-      while (first < end
-            && x + first->pixel_width < r->x)
-       {
-         x += first->pixel_width;
-         ++first;
-       }
-
-      /* Find the last one.  */
-      last = first;
-      first_x = x;
-      while (last < end
-            && x < r->x + r->width)
-       {
-         x += last->pixel_width;
-         ++last;
-       }
-
-      /* Repaint.  */
-      if (last > first)
-       x_draw_glyphs (w, first_x - start_x, row, area,
-                      first - row->glyphs[area],
-                      last - row->glyphs[area],
-                      DRAW_NORMAL_TEXT, 0);
-    }
-}
-
-
-/* Redraw the parts of the glyph row ROW on window W intersecting
-   rectangle R.  R is in window-relative coordinates.  Value is
-   non-zero if mouse-face was overwritten.  */
-
-static int
-expose_line (w, row, r)
-     struct window *w;
-     struct glyph_row *row;
-     XRectangle *r;
-{
-  xassert (row->enabled_p);
-
-  if (row->mode_line_p || w->pseudo_window_p)
-    x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
-                  DRAW_NORMAL_TEXT, 0);
-  else
-    {
-      if (row->used[LEFT_MARGIN_AREA])
-       expose_area (w, row, r, LEFT_MARGIN_AREA);
-      if (row->used[TEXT_AREA])
-       expose_area (w, row, r, TEXT_AREA);
-      if (row->used[RIGHT_MARGIN_AREA])
-       expose_area (w, row, r, RIGHT_MARGIN_AREA);
-      x_draw_row_fringe_bitmaps (w, row);
-    }
-
-  return row->mouse_face_p;
-}
-
-
-/* Return non-zero if W's cursor intersects rectangle R.  */
-
-static int
-x_phys_cursor_in_rect_p (w, r)
-     struct window *w;
-     XRectangle *r;
-{
-  XRectangle cr, result;
-  struct glyph *cursor_glyph;
-
-  cursor_glyph = get_phys_cursor_glyph (w);
-  if (cursor_glyph)
-    {
-      cr.x = w->phys_cursor.x;
-      cr.y = w->phys_cursor.y;
-      cr.width = cursor_glyph->pixel_width;
-      cr.height = w->phys_cursor_height;
-      return x_intersect_rectangles (&cr, r, &result);
-    }
-  else
-    return 0;
-}
-
-
-/* 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
-   mouse-face.  */
-
-static int
-expose_window (w, fr)
-     struct window *w;
-     XRectangle *fr;
-{
-  struct frame *f = XFRAME (w->frame);
-  XRectangle wr, r;
-  int mouse_face_overwritten_p = 0;
-
-  /* If window is not yet fully initialized, do nothing.  This can
-     happen when toolkit scroll bars are used and a window is split.
-     Reconfiguring the scroll bar will generate an expose for a newly
-     created window.  */
-  if (w->current_matrix == NULL)
-    return 0;
-
-  /* When we're currently updating the window, display and current
-     matrix usually don't agree.  Arrange for a thorough display
-     later.  */
-  if (w == updated_window)
-    {
-      SET_FRAME_GARBAGED (f);
-      return 0;
-    }
-
-  /* Frame-relative pixel rectangle of W.  */
-  wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
-  wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
-  wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
-  wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+  /* If there is a margin around the image, adjust x- and y-position
+     by that margin.  */
+  x += s->img->hmargin;
+  y += s->img->vmargin;
 
-  if (x_intersect_rectangles (fr, &wr, &r))
+  if (s->img->pixmap)
     {
-      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));
+      if (s->img->mask)
+       {
+         /* We can't set both a clip mask and use XSetClipRectangles
+            because the latter also sets a clip mask.  We also can't
+            trust on the shape extension to be available
+            (XShapeCombineRegion).  So, compute the rectangle to draw
+            manually.  */
+         unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
+                               | GCFunction);
+         XGCValues xgcv;
 
-      /* Convert to window coordinates.  */
-      r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
-      r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
+         xgcv.clip_mask = s->img->mask;
+         xgcv.clip_x_origin = x;
+         xgcv.clip_y_origin = y;
+         xgcv.function = GXcopy;
+         XChangeGC (s->display, s->gc, mask, &xgcv);
 
-      /* Turn off the cursor.  */
-      if (!w->pseudo_window_p
-         && x_phys_cursor_in_rect_p (w, &r))
-       {
-         x_clear_cursor (w);
-         cursor_cleared_p = 1;
+         XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
+                    0, 0, s->img->width, s->img->height, x, y);
+         XSetClipMask (s->display, s->gc, None);
        }
       else
-       cursor_cleared_p = 0;
-
-      /* Update lines intersecting rectangle R.  */
-      first_overlapping_row = last_overlapping_row = NULL;
-      for (row = w->current_matrix->rows;
-          row->enabled_p;
-          ++row)
        {
-         int y0 = row->y;
-         int y1 = MATRIX_ROW_BOTTOM_Y (row);
+         XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
+                    0, 0, s->img->width, s->img->height, x, y);
 
-         if ((y0 >= r.y && y0 < r.y + r.height)
-             || (y1 > r.y && y1 < r.y + r.height)
-             || (r.y >= y0 && r.y < y1)
-             || (r.y + r.height > y0 && r.y + r.height < y1))
+         /* When the image has a mask, we can expect that at
+            least part of a mouse highlight or a block cursor will
+            be visible.  If the image doesn't have a mask, make
+            a block cursor visible by drawing a rectangle around
+            the image.  I believe it's looking better if we do
+            nothing here for mouse-face.  */
+         if (s->hl == DRAW_CURSOR)
            {
-             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;
+             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);
            }
-
-         if (y1 >= yb)
-           break;
-       }
-
-      /* Display the mode line if there is one.  */
-      if (WINDOW_WANTS_MODELINE_P (w)
-         && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
-             row->enabled_p)
-         && row->y < r.y + r.height)
-       {
-         if (expose_line (w, row, &r))
-           mouse_face_overwritten_p = 1;
-       }
-
-      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);
-
-         /* Turn the cursor on again.  */
-         if (cursor_cleared_p)
-           x_update_window_cursor (w, 1);
        }
     }
-
-  return mouse_face_overwritten_p;
+  else
+    /* Draw a rectangle if image could not be loaded.  */
+    XDrawRectangle (s->display, pixmap, s->gc, x, y,
+                   s->img->width - 1, s->img->height - 1);
 }
 
 
-/* Determine the intersection of two rectangles R1 and R2.  Return
-   the intersection in *RESULT.  Value is non-zero if RESULT is not
-   empty.  */
+/* Draw part of the background of glyph string S.  X, Y, W, and H
+   give the rectangle to draw.  */
 
-static int
-x_intersect_rectangles (r1, r2, result)
-     XRectangle *r1, *r2, *result;
+static void
+x_draw_glyph_string_bg_rect (s, x, y, w, h)
+     struct glyph_string *s;
+     int x, y, w, h;
 {
-  XRectangle *left, *right;
-  XRectangle *upper, *lower;
-  int intersection_p = 0;
-
-  /* Rearrange so that R1 is the left-most rectangle.  */
-  if (r1->x < r2->x)
-    left = r1, right = r2;
-  else
-    left = r2, right = r1;
-
-  /* X0 of the intersection is right.x0, if this is inside R1,
-     otherwise there is no intersection.  */
-  if (right->x <= left->x + left->width)
+  if (s->stippled_p)
     {
-      result->x = right->x;
-
-      /* The right end of the intersection is the minimum of the
-        the right ends of left and right.  */
-      result->width = (min (left->x + left->width, right->x + right->width)
-                      - result->x);
-
-      /* Same game for Y.  */
-      if (r1->y < r2->y)
-       upper = r1, lower = r2;
-      else
-       upper = r2, lower = r1;
-
-      /* The upper end of the intersection is lower.y0, if this is inside
-        of upper.  Otherwise, there is no intersection.  */
-      if (lower->y <= upper->y + upper->height)
-       {
-         result->y = lower->y;
-
-         /* The lower end of the intersection is the minimum of the lower
-            ends of upper and lower.  */
-         result->height = (min (lower->y + lower->height,
-                                upper->y + upper->height)
-                           - result->y);
-         intersection_p = 1;
-       }
+      /* Fill background with a stipple pattern.  */
+      XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+      XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
+      XSetFillStyle (s->display, s->gc, FillSolid);
     }
-
-  return intersection_p;
+  else
+    x_clear_glyph_string_rect (s, x, y, w, h);
 }
 
 
+/* Draw image glyph string S.
 
+            s->y
+   s->x      +-------------------------
+            |   s->face->box
+            |
+            |     +-------------------------
+            |     |  s->img->margin
+            |     |
+            |     |       +-------------------
+            |     |       |  the image
 
-\f
-static void
-frame_highlight (f)
-     struct frame *f;
-{
-  /* We used to only do this if Vx_no_window_manager was non-nil, but
-     the ICCCM (section 4.1.6) says that the window's border pixmap
-     and border pixel are window attributes which are "private to the
-     client", so we can always change it to whatever we want.  */
-  BLOCK_INPUT;
-  XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   f->output_data.x->border_pixel);
-  UNBLOCK_INPUT;
-  x_update_cursor (f, 1);
-}
+ */
 
 static void
-frame_unhighlight (f)
-     struct frame *f;
+x_draw_image_glyph_string (s)
+     struct glyph_string *s;
 {
-  /* We used to only do this if Vx_no_window_manager was non-nil, but
-     the ICCCM (section 4.1.6) says that the window's border pixmap
-     and border pixel are window attributes which are "private to the
-     client", so we can always change it to whatever we want.  */
-  BLOCK_INPUT;
-  XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                         f->output_data.x->border_tile);
-  UNBLOCK_INPUT;
-  x_update_cursor (f, 1);
-}
+  int x, y;
+  int box_line_hwidth = abs (s->face->box_line_width);
+  int box_line_vwidth = max (s->face->box_line_width, 0);
+  int height;
+  Pixmap pixmap = None;
 
-/* The focus has changed.  Update the frames as necessary to reflect
-   the new situation.  Note that we can't change the selected frame
-   here, because the Lisp code we are interrupting might become confused.
-   Each event gets marked with the frame in which it occurred, so the
-   Lisp code can tell when the switch took place by examining the events.  */
+  height = s->height - 2 * box_line_vwidth;
 
-static void
-x_new_focus_frame (dpyinfo, frame)
-     struct x_display_info *dpyinfo;
-     struct frame *frame;
-{
-  struct frame *old_focus = dpyinfo->x_focus_frame;
 
-  if (frame != dpyinfo->x_focus_frame)
+  /* Fill background with face under the image.  Do it only if row is
+     taller than image or if image has a clip mask to reduce
+     flickering.  */
+  s->stippled_p = s->face->stipple != 0;
+  if (height > s->img->height
+      || s->img->hmargin
+      || s->img->vmargin
+      || s->img->mask
+      || s->img->pixmap == 0
+      || s->width != s->background_width)
     {
-      /* Set this before calling other routines, so that they see
-        the correct value of x_focus_frame.  */
-      dpyinfo->x_focus_frame = frame;
-
-      if (old_focus && old_focus->auto_lower)
-       x_lower_frame (old_focus);
-
-#if 0
-      selected_frame = frame;
-      XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
-                selected_frame);
-      Fselect_window (selected_frame->selected_window);
-      choose_minibuf_frame ();
-#endif /* ! 0 */
-
-      if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
-       pending_autoraise_frame = dpyinfo->x_focus_frame;
+      if (box_line_hwidth && s->first_glyph->left_box_line_p)
+       x = s->x + box_line_hwidth;
       else
-       pending_autoraise_frame = 0;
-    }
-
-  x_frame_rehighlight (dpyinfo);
-}
+       x = s->x;
 
-/* Handle FocusIn and FocusOut state changes for FRAME.
-   If FRAME has focus and there exists more than one frame, puts
-   a FOCUS_IN_EVENT into BUFP.
-   Returns number of events inserted into BUFP. */
+      y = s->y + box_line_vwidth;
 
-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 (s->img->mask)
+       {
+         /* Create a pixmap as large as the glyph string.  Fill it
+            with the background color.  Copy the image to it, using
+            its mask.  Copy the temporary pixmap to the display.  */
+         Screen *screen = FRAME_X_SCREEN (s->f);
+         int depth = DefaultDepthOfScreen (screen);
 
-  if (type == FocusIn)
-    {
-      if (dpyinfo->x_focus_event_frame != frame)
-        {
-          x_new_focus_frame (dpyinfo, frame);
-          dpyinfo->x_focus_event_frame = frame;
+         /* Create a pixmap as large as the glyph string.  */
+         pixmap = XCreatePixmap (s->display, s->window,
+                                 s->background_width,
+                                 s->height, depth);
 
-          /* 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;
-            }
-        }
+         /* Don't clip in the following because we're working on the
+            pixmap.  */
+         XSetClipMask (s->display, s->gc, None);
 
-      frame->output_data.x->focus_state |= state;
+         /* Fill the pixmap with the background color/stipple.  */
+         if (s->stippled_p)
+           {
+             /* Fill background with a stipple pattern.  */
+             XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+             XFillRectangle (s->display, pixmap, s->gc,
+                             0, 0, s->background_width, s->height);
+             XSetFillStyle (s->display, s->gc, FillSolid);
+           }
+         else
+           {
+             XGCValues xgcv;
+             XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
+                           &xgcv);
+             XSetForeground (s->display, s->gc, xgcv.background);
+             XFillRectangle (s->display, pixmap, s->gc,
+                             0, 0, s->background_width, s->height);
+             XSetForeground (s->display, s->gc, xgcv.foreground);
+           }
+       }
+      else
+       x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
 
-#ifdef HAVE_X_I18N
-      if (FRAME_XIC (frame))
-        XSetICFocus (FRAME_XIC (frame));
-#endif
+      s->background_filled_p = 1;
     }
-  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
+  /* Draw the foreground.  */
+  if (pixmap != None)
+    {
+      x_draw_image_foreground_1 (s, pixmap);
+      x_set_glyph_string_clipping (s);
+      XCopyArea (s->display, pixmap, s->window, s->gc,
+                0, 0, s->background_width, s->height, s->x, s->y);
+      XFreePixmap (s->display, pixmap);
     }
+  else
+    x_draw_image_foreground (s);
 
-  return nr_events;
+  /* If we must draw a relief around the image, do it.  */
+  if (s->img->relief
+      || s->hl == DRAW_IMAGE_RAISED
+      || s->hl == DRAW_IMAGE_SUNKEN)
+    x_draw_image_relief (s);
 }
 
-/* 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. */
+/* Draw stretch glyph string S.  */
 
-static int
-x_detect_focus_change (dpyinfo, event, bufp, numchars)
-     struct x_display_info *dpyinfo;
-     XEvent *event;
-     struct input_event *bufp;
-     int numchars;
+static void
+x_draw_stretch_glyph_string (s)
+     struct glyph_string *s;
 {
-  struct frame *frame;
-  int nr_events = 0;
-
-  frame = x_top_window_to_frame (dpyinfo, event->xany.window);
-  if (! frame) return nr_events;
+  xassert (s->first_glyph->type == STRETCH_GLYPH);
+  s->stippled_p = s->face->stipple != 0;
 
-  switch (event->type)
+  if (s->hl == DRAW_CURSOR
+      && !x_stretch_cursor_p)
     {
-    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;
+      /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
+        as wide as the stretch glyph.  */
+      int width = min (CANON_X_UNIT (s->f), s->background_width);
 
-    case FocusIn:
-    case FocusOut:
-      nr_events = x_focus_changed (event->type,
-                                   (event->xfocus.detail == NotifyPointer
-                                    ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
-                                   dpyinfo,
-                                   frame,
-                                   bufp,
-                                   numchars);
-      break;
-    }
+      /* Draw cursor.  */
+      x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
 
-  return nr_events;
-}
+      /* Clear rest using the GC of the original non-cursor face.  */
+      if (width < s->background_width)
+       {
+         int x = s->x + width, y = s->y;
+         int w = s->background_width - width, h = s->height;
+         XRectangle r;
+         GC gc;
 
+         if (s->row->mouse_face_p
+             && cursor_in_mouse_face_p (s->w))
+           {
+             x_set_mouse_face_gc (s);
+             gc = s->gc;
+           }
+         else
+           gc = s->face->gc;
 
-/* Handle an event saying the mouse has moved out of an Emacs frame.  */
+         get_glyph_string_clip_rect (s, &r);
+         XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
 
-void
-x_mouse_leave (dpyinfo)
-     struct x_display_info *dpyinfo;
-{
-  x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
-}
+         if (s->face->stipple)
+           {
+             /* Fill background with a stipple pattern.  */
+             XSetFillStyle (s->display, gc, FillOpaqueStippled);
+             XFillRectangle (s->display, s->window, gc, x, y, w, h);
+             XSetFillStyle (s->display, gc, FillSolid);
+           }
+         else
+           {
+             XGCValues xgcv;
+             XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
+             XSetForeground (s->display, gc, xgcv.background);
+             XFillRectangle (s->display, s->window, gc, x, y, w, h);
+             XSetForeground (s->display, gc, xgcv.foreground);
+           }
+       }
+    }
+  else if (!s->background_filled_p)
+    x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
+                                s->height);
 
-/* The focus has changed, or we have redirected a frame's focus to
-   another frame (this happens when a frame uses a surrogate
-   mini-buffer frame).  Shift the highlight as appropriate.
+  s->background_filled_p = 1;
+}
 
-   The FRAME argument doesn't necessarily have anything to do with which
-   frame is being highlighted or un-highlighted; we only use it to find
-   the appropriate X display info.  */
 
-static void
-XTframe_rehighlight (frame)
-     struct frame *frame;
-{
-  x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
-}
+/* Draw glyph string S.  */
 
 static void
-x_frame_rehighlight (dpyinfo)
-     struct x_display_info *dpyinfo;
+x_draw_glyph_string (s)
+     struct glyph_string *s;
 {
-  struct frame *old_highlight = dpyinfo->x_highlight_frame;
+  int relief_drawn_p = 0;
 
-  if (dpyinfo->x_focus_frame)
+  /* If S draws into the background of its successor, draw the
+     background of the successor first so that S can draw into it.
+     This makes S->next use XDrawString instead of XDrawImageString.  */
+  if (s->next && s->right_overhang && !s->for_overlaps_p)
     {
-      dpyinfo->x_highlight_frame
-       = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
-          ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
-          : dpyinfo->x_focus_frame);
-      if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
-       {
-         FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
-         dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
-       }
+      xassert (s->next->img == NULL);
+      x_set_glyph_string_gc (s->next);
+      x_set_glyph_string_clipping (s->next);
+      x_draw_glyph_string_background (s->next, 1);
     }
-  else
-    dpyinfo->x_highlight_frame = 0;
 
-  if (dpyinfo->x_highlight_frame != old_highlight)
-    {
-      if (old_highlight)
-       frame_unhighlight (old_highlight);
-      if (dpyinfo->x_highlight_frame)
-       frame_highlight (dpyinfo->x_highlight_frame);
-    }
-}
+  /* Set up S->gc, set clipping and draw S.  */
+  x_set_glyph_string_gc (s);
 
+  /* Draw relief (if any) in advance for char/composition so that the
+     glyph string can be drawn over it.  */
+  if (!s->for_overlaps_p
+      && s->face->box != FACE_NO_BOX
+      && (s->first_glyph->type == CHAR_GLYPH
+         || s->first_glyph->type == COMPOSITE_GLYPH))
 
-\f
-/* Keyboard processing - modifier keys, vendor-specific keysyms, etc.  */
+    {
+      x_set_glyph_string_clipping (s);
+      x_draw_glyph_string_background (s, 1);
+      x_draw_glyph_string_box (s);
+      x_set_glyph_string_clipping (s);
+      relief_drawn_p = 1;
+    }
+  else
+    x_set_glyph_string_clipping (s);
 
-/* Initialize mode_switch_bit and modifier_meaning.  */
-static void
-x_find_modifier_meanings (dpyinfo)
-     struct x_display_info *dpyinfo;
-{
-  int min_code, max_code;
-  KeySym *syms;
-  int syms_per_code;
-  XModifierKeymap *mods;
+  switch (s->first_glyph->type)
+    {
+    case IMAGE_GLYPH:
+      x_draw_image_glyph_string (s);
+      break;
 
-  dpyinfo->meta_mod_mask = 0;
-  dpyinfo->shift_lock_mask = 0;
-  dpyinfo->alt_mod_mask = 0;
-  dpyinfo->super_mod_mask = 0;
-  dpyinfo->hyper_mod_mask = 0;
+    case STRETCH_GLYPH:
+      x_draw_stretch_glyph_string (s);
+      break;
 
-#ifdef HAVE_X11R4
-  XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
-#else
-  min_code = dpyinfo->display->min_keycode;
-  max_code = dpyinfo->display->max_keycode;
-#endif
+    case CHAR_GLYPH:
+      if (s->for_overlaps_p)
+       s->background_filled_p = 1;
+      else
+       x_draw_glyph_string_background (s, 0);
+      x_draw_glyph_string_foreground (s);
+      break;
 
-  syms = XGetKeyboardMapping (dpyinfo->display,
-                             min_code, max_code - min_code + 1,
-                             &syms_per_code);
-  mods = XGetModifierMapping (dpyinfo->display);
+    case COMPOSITE_GLYPH:
+      if (s->for_overlaps_p || s->gidx > 0)
+       s->background_filled_p = 1;
+      else
+       x_draw_glyph_string_background (s, 1);
+      x_draw_composite_glyph_string_foreground (s);
+      break;
 
-  /* Scan the modifier table to see which modifier bits the Meta and
-     Alt keysyms are on.  */
-  {
-    int row, col;      /* The row and column in the modifier table.  */
+    default:
+      abort ();
+    }
 
-    for (row = 3; row < 8; row++)
-      for (col = 0; col < mods->max_keypermod; col++)
+  if (!s->for_overlaps_p)
+    {
+      /* Draw underline.  */
+      if (s->face->underline_p)
        {
-         KeyCode code
-           = mods->modifiermap[(row * mods->max_keypermod) + col];
+         unsigned long tem, h;
+         int y;
 
-         /* Zeroes are used for filler.  Skip them.  */
-         if (code == 0)
-           continue;
+         /* Get the underline thickness.  Default is 1 pixel.  */
+         if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
+           h = 1;
 
-         /* Are any of this keycode's keysyms a meta key?  */
-         {
-           int code_col;
+         /* Get the underline position.  This is the recommended
+            vertical offset in pixels from the baseline to the top of
+            the underline.  This is a signed value according to the
+            specs, and its default is
 
-           for (code_col = 0; code_col < syms_per_code; code_col++)
-             {
-               int sym = syms[((code - min_code) * syms_per_code) + code_col];
+            ROUND ((maximum descent) / 2), with
+            ROUND(x) = floor (x + 0.5)  */
 
-               switch (sym)
-                 {
-                 case XK_Meta_L:
-                 case XK_Meta_R:
-                   dpyinfo->meta_mod_mask |= (1 << row);
-                   break;
+         if (x_use_underline_position_properties
+             && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
+           y = s->ybase + (long) tem;
+         else if (s->face->font)
+           y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
+         else
+           y = s->y + s->height - h;
 
-                 case XK_Alt_L:
-                 case XK_Alt_R:
-                   dpyinfo->alt_mod_mask |= (1 << row);
-                   break;
+         if (s->face->underline_defaulted_p)
+           XFillRectangle (s->display, s->window, s->gc,
+                           s->x, y, s->width, h);
+         else
+           {
+             XGCValues xgcv;
+             XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+             XSetForeground (s->display, s->gc, s->face->underline_color);
+             XFillRectangle (s->display, s->window, s->gc,
+                             s->x, y, s->width, h);
+             XSetForeground (s->display, s->gc, xgcv.foreground);
+           }
+       }
 
-                 case XK_Hyper_L:
-                 case XK_Hyper_R:
-                   dpyinfo->hyper_mod_mask |= (1 << row);
-                   break;
+      /* Draw overline.  */
+      if (s->face->overline_p)
+       {
+         unsigned long dy = 0, h = 1;
 
-                 case XK_Super_L:
-                 case XK_Super_R:
-                   dpyinfo->super_mod_mask |= (1 << row);
-                   break;
+         if (s->face->overline_color_defaulted_p)
+           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+                           s->width, h);
+         else
+           {
+             XGCValues xgcv;
+             XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+             XSetForeground (s->display, s->gc, s->face->overline_color);
+             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+                             s->width, h);
+             XSetForeground (s->display, s->gc, xgcv.foreground);
+           }
+       }
 
-                 case XK_Shift_Lock:
-                   /* Ignore this if it's not on the lock modifier.  */
-                   if ((1 << row) == LockMask)
-                     dpyinfo->shift_lock_mask = LockMask;
-                   break;
-                 }
-             }
-         }
+      /* Draw strike-through.  */
+      if (s->face->strike_through_p)
+       {
+         unsigned long h = 1;
+         unsigned long dy = (s->height - h) / 2;
+
+         if (s->face->strike_through_color_defaulted_p)
+           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+                           s->width, h);
+         else
+           {
+             XGCValues xgcv;
+             XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+             XSetForeground (s->display, s->gc, s->face->strike_through_color);
+             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+                             s->width, h);
+             XSetForeground (s->display, s->gc, xgcv.foreground);
+           }
        }
-  }
 
-  /* If we couldn't find any meta keys, accept any alt keys as meta keys.  */
-  if (! dpyinfo->meta_mod_mask)
-    {
-      dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
-      dpyinfo->alt_mod_mask = 0;
+      /* Draw relief if not yet drawn.  */
+      if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
+       x_draw_glyph_string_box (s);
     }
 
-  /* If some keys are both alt and meta,
-     make them just meta, not alt.  */
-  if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
-    {
-      dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
-    }
+  /* Reset clipping.  */
+  XSetClipMask (s->display, s->gc, None);
+}
 
-  XFree ((char *) syms);
-  XFreeModifiermap (mods);
+/* Shift display to make room for inserted glyphs.   */
+
+void
+x_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
+     struct frame *f;
+     int x, y, width, height, shift_by;
+{
+  XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
+            f->output_data.x->normal_gc,
+            x, y, width, height,
+            x + shift_by, y);
 }
 
-/* Convert between the modifier bits X uses and the modifier bits
-   Emacs uses.  */
+/* Delete N glyphs at the nominal cursor position.  Not implemented
+   for X frames.  */
 
-static unsigned int
-x_x_to_emacs_modifiers (dpyinfo, state)
-     struct x_display_info *dpyinfo;
-     unsigned int state;
+static void
+x_delete_glyphs (n)
+     register int n;
 {
-  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;
+  abort ();
+}
 
-  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);
 
+/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
+   If they are <= 0, this is probably an error.  */
 
-  return (  ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_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));
+void
+x_clear_area (dpy, window, x, y, width, height, exposures)
+     Display *dpy;
+     Window window;
+     int x, y;
+     int width, height;
+     int exposures;
+{
+  xassert (width > 0 && height > 0);
+  XClearArea (dpy, window, x, y, width, height, exposures);
 }
 
-static unsigned int
-x_emacs_to_x_modifiers (dpyinfo, state)
-     struct x_display_info *dpyinfo;
-     unsigned int state;
+
+/* Clear entire frame.  If updating_frame is non-null, clear that
+   frame.  Otherwise clear the selected frame.  */
+
+static void
+x_clear_frame ()
 {
-  EMACS_UINT mod_meta = meta_modifier;
-  EMACS_UINT mod_alt  = alt_modifier;
-  EMACS_UINT mod_hyper = hyper_modifier;
-  EMACS_UINT mod_super = super_modifier;
+  struct frame *f;
 
-  Lisp_Object tem;
+  if (updating_frame)
+    f = updating_frame;
+  else
+    f = SELECTED_FRAME ();
 
-  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);
+  /* Clearing the frame will erase any cursor, so mark them all as no
+     longer visible.  */
+  mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
+  output_cursor.hpos = output_cursor.vpos = 0;
+  output_cursor.x = -1;
 
+  /* We don't set the output cursor here because there will always
+     follow an explicit cursor_to.  */
+  BLOCK_INPUT;
+  XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 
-  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));
-}
+  /* We have to clear the scroll bars, too.  If we have changed
+     colors or something like that, then they should be notified.  */
+  x_scroll_bar_clear (f);
 
-/* Convert a keysym to its name.  */
+  XFlush (FRAME_X_DISPLAY (f));
 
-char *
-x_get_keysym_name (keysym)
-     KeySym keysym;
-{
-  char *value;
+#ifdef USE_GTK
+  xg_frame_cleared (f);
+#endif
 
-  BLOCK_INPUT;
-  value = XKeysymToString (keysym);
   UNBLOCK_INPUT;
-
-  return value;
 }
 
 
 \f
-/* Mouse clicks and mouse movement.  Rah.  */
+/* Invert the middle quarter of the frame for .15 sec.  */
 
-/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
-   co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle that the
-   glyph at X, Y occupies, if BOUNDS != 0.  If NOCLIP is non-zero, do
-   not force the value into range.  */
+/* We use the select system call to do the waiting, so we have to make
+   sure it's available.  If it isn't, we just won't do visual bells.  */
+
+#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
 
-void
-pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
-     FRAME_PTR f;
-     register int pix_x, pix_y;
-     register int *x, *y;
-     XRectangle *bounds;
-     int noclip;
-{
-  /* Arrange for the division in PIXEL_TO_CHAR_COL etc.  to round down
-     even for negative values.  */
-  if (pix_x < 0)
-    pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
-  if (pix_y < 0)
-    pix_y -= (f)->output_data.x->line_height - 1;
 
-  pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
-  pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
+/* Subtract the `struct timeval' values X and Y, storing the result in
+   *RESULT.  Return 1 if the difference is negative, otherwise 0.  */
 
-  if (bounds)
+static int
+timeval_subtract (result, x, y)
+     struct timeval *result, x, y;
+{
+  /* Perform the carry for the later subtraction by updating y.  This
+     is safer because on some systems the tv_sec member is unsigned.  */
+  if (x.tv_usec < y.tv_usec)
     {
-      bounds->width  = FONT_WIDTH  (f->output_data.x->font);
-      bounds->height = f->output_data.x->line_height;
-      bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
-      bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
+      int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
+      y.tv_usec -= 1000000 * nsec;
+      y.tv_sec += nsec;
     }
 
-  if (!noclip)
+  if (x.tv_usec - y.tv_usec > 1000000)
     {
-      if (pix_x < 0)
-       pix_x = 0;
-      else if (pix_x > FRAME_WINDOW_WIDTH (f))
-       pix_x = FRAME_WINDOW_WIDTH (f);
-
-      if (pix_y < 0)
-       pix_y = 0;
-      else if (pix_y > f->height)
-       pix_y = f->height;
+      int nsec = (y.tv_usec - x.tv_usec) / 1000000;
+      y.tv_usec += 1000000 * nsec;
+      y.tv_sec -= nsec;
     }
 
-  *x = pix_x;
-  *y = pix_y;
-}
-
+  /* Compute the time remaining to wait.  tv_usec is certainly
+     positive.  */
+  result->tv_sec = x.tv_sec - y.tv_sec;
+  result->tv_usec = x.tv_usec - y.tv_usec;
 
-/* Given HPOS/VPOS in the current matrix of W, return corresponding
-   frame-relative pixel positions in *FRAME_X and *FRAME_Y.  If we
-   can't tell the positions because W's display is not up to date,
-   return 0.  */
+  /* Return indication of whether the result should be considered
+     negative.  */
+  return x.tv_sec < y.tv_sec;
+}
 
-int
-glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
-     struct window *w;
-     int hpos, vpos;
-     int *frame_x, *frame_y;
+void
+XTflash (f)
+     struct frame *f;
 {
-  int success_p;
+  BLOCK_INPUT;
 
-  xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
-  xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
+  {
+    GC gc;
 
-  if (display_completed)
+    /* Create a GC that will use the GXxor function to flip foreground
+       pixels into background pixels.  */
     {
-      struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
-      struct glyph *glyph = row->glyphs[TEXT_AREA];
-      struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
+      XGCValues values;
 
-      *frame_y = row->y;
-      *frame_x = row->x;
-      while (glyph < end)
-       {
-         *frame_x += glyph->pixel_width;
-         ++glyph;
-       }
+      values.function = GXxor;
+      values.foreground = (f->output_data.x->foreground_pixel
+                          ^ f->output_data.x->background_pixel);
 
-      success_p = 1;
-    }
-  else
-    {
-      *frame_y = *frame_x = 0;
-      success_p = 0;
+      gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                     GCFunction | GCForeground, &values);
     }
 
-  *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
-  *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
-  return success_p;
-}
-
-
-/* Prepare a mouse-event in *RESULT for placement in the input queue.
+    {
+      /* Get the height not including a menu bar widget.  */
+      int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
+      /* Height of each line to flash.  */
+      int flash_height = FRAME_LINE_HEIGHT (f);
+      /* These will be the left and right margins of the rectangles.  */
+      int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
+      int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
 
-   If the event is a button press, then note that we have grabbed
-   the mouse.  */
+      int width;
 
-static Lisp_Object
-construct_mouse_click (result, event, f)
-     struct input_event *result;
-     XButtonEvent *event;
-     struct frame *f;
-{
-  /* Make the event type NO_EVENT; we'll change that when we decide
-     otherwise.  */
-  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),
-                                              event->state)
-                      | (event->type == ButtonRelease
-                         ? up_modifier
-                         : down_modifier));
+      /* Don't flash the area between a scroll bar and the frame
+        edge it is next to.  */
+      switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
+       {
+       case vertical_scroll_bar_left:
+         flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+         break;
 
-  XSETINT (result->x, event->x);
-  XSETINT (result->y, event->y);
-  XSETFRAME (result->frame_or_window, f);
-  result->arg = Qnil;
-  return Qnil;
-}
+       case vertical_scroll_bar_right:
+         flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+         break;
 
-\f
-/* Function to report a mouse movement to the mainstream Emacs code.
-   The input handler calls this.
+       default:
+         break;
+       }
 
-   We have received a mouse movement event, which is given in *event.
-   If the mouse is over a different glyph than it was last time, tell
-   the mainstream emacs code by setting mouse_moved.  If not, ask for
-   another motion event, so we can check again the next time it moves.  */
+      width = flash_right - flash_left;
 
-static XMotionEvent last_mouse_motion_event;
-static Lisp_Object last_mouse_motion_frame;
+      /* If window is tall, flash top and bottom line.  */
+      if (height > 3 * FRAME_LINE_HEIGHT (f))
+       {
+         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                         flash_left,
+                         (FRAME_INTERNAL_BORDER_WIDTH (f)
+                          + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
+                         width, flash_height);
+         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                         flash_left,
+                         (height - flash_height
+                          - FRAME_INTERNAL_BORDER_WIDTH (f)),
+                         width, flash_height);
+       }
+      else
+       /* If it is short, flash it all.  */
+       XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                       flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+                       width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
 
-static void
-note_mouse_movement (frame, event)
-     FRAME_PTR frame;
-     XMotionEvent *event;
-{
-  last_mouse_movement_time = event->time;
-  last_mouse_motion_event = *event;
-  XSETFRAME (last_mouse_motion_frame, frame);
+      x_flush (f);
 
-  if (event->window != FRAME_X_WINDOW (frame))
-    {
-      frame->mouse_moved = 1;
-      last_mouse_scroll_bar = Qnil;
-      note_mouse_highlight (frame, -1, -1);
-    }
+      {
+       struct timeval wakeup;
 
-  /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  else if (event->x < last_mouse_glyph.x
-          || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
-          || event->y < last_mouse_glyph.y
-          || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
-    {
-      frame->mouse_moved = 1;
-      last_mouse_scroll_bar = Qnil;
-      note_mouse_highlight (frame, event->x, event->y);
-    }
-}
+       EMACS_GET_TIME (wakeup);
 
-\f
-/************************************************************************
-                             Mouse Face
- ************************************************************************/
+       /* Compute time to wait until, propagating carry from usecs.  */
+       wakeup.tv_usec += 150000;
+       wakeup.tv_sec += (wakeup.tv_usec / 1000000);
+       wakeup.tv_usec %= 1000000;
 
-/* Find the glyph under window-relative coordinates X/Y in window W.
-   Consider only glyphs from buffer text, i.e. no glyphs from overlay
-   strings.  Return in *HPOS and *VPOS the row and column number of
-   the glyph found.  Return in *AREA the glyph area containing X.
-   Value is a pointer to the glyph found or null if X/Y is not on
-   text, or we can't tell because W's current matrix is not up to
-   date.  */
+       /* Keep waiting until past the time wakeup or any input gets
+          available.  */
+       while (! detect_input_pending ())
+         {
+           struct timeval current;
+           struct timeval timeout;
 
-static struct glyph *
-x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
-     struct window *w;
-     int x, y;
-     int *hpos, *vpos, *area;
-     int buffer_only_p;
-{
-  struct glyph *glyph, *end;
-  struct glyph_row *row = NULL;
-  int x0, i, left_area_width;
+           EMACS_GET_TIME (current);
 
-  /* Find row containing Y.  Give up if some row is not enabled.  */
-  for (i = 0; i < w->current_matrix->nrows; ++i)
-    {
-      row = MATRIX_ROW (w->current_matrix, i);
-      if (!row->enabled_p)
-       return NULL;
-      if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
-       break;
-    }
+           /* Break if result would be negative.  */
+           if (timeval_subtract (&current, wakeup, current))
+             break;
 
-  *vpos = i;
-  *hpos = 0;
+           /* How long `select' should wait.  */
+           timeout.tv_sec = 0;
+           timeout.tv_usec = 10000;
 
-  /* Give up if Y is not in the window.  */
-  if (i == w->current_matrix->nrows)
-    return NULL;
+           /* Try to wait that long--but we might wake up sooner.  */
+           select (0, NULL, NULL, NULL, &timeout);
+         }
+      }
 
-  /* Get the glyph area containing X.  */
-  if (w->pseudo_window_p)
-    {
-      *area = TEXT_AREA;
-      x0 = 0;
-    }
-  else
-    {
-      left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
-      if (x < left_area_width)
-       {
-         *area = LEFT_MARGIN_AREA;
-         x0 = 0;
-       }
-      else if (x < left_area_width + window_box_width (w, TEXT_AREA))
+      /* If window is tall, flash top and bottom line.  */
+      if (height > 3 * FRAME_LINE_HEIGHT (f))
        {
-         *area = TEXT_AREA;
-         x0 = row->x + left_area_width;
+         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                         flash_left,
+                         (FRAME_INTERNAL_BORDER_WIDTH (f)
+                          + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
+                         width, flash_height);
+         XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                         flash_left,
+                         (height - flash_height
+                          - FRAME_INTERNAL_BORDER_WIDTH (f)),
+                         width, flash_height);
        }
       else
-       {
-         *area = RIGHT_MARGIN_AREA;
-         x0 = left_area_width + window_box_width (w, TEXT_AREA);
-       }
-    }
-
-  /* Find glyph containing X.  */
-  glyph = row->glyphs[*area];
-  end = glyph + row->used[*area];
-  while (glyph < end)
-    {
-      if (x < x0 + glyph->pixel_width)
-       {
-         if (w->pseudo_window_p)
-           break;
-         else if (!buffer_only_p || BUFFERP (glyph->object))
-           break;
-       }
+       /* If it is short, flash it all.  */
+       XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+                       flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
+                       width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
 
-      x0 += glyph->pixel_width;
-      ++glyph;
+      XFreeGC (FRAME_X_DISPLAY (f), gc);
+      x_flush (f);
     }
+  }
 
-  if (glyph == end)
-    return NULL;
-
-  *hpos = glyph - row->glyphs[*area];
-  return glyph;
+  UNBLOCK_INPUT;
 }
 
-
-/* Convert frame-relative x/y to coordinates relative to window W.
-   Takes pseudo-windows into account.  */
-
-static void
-frame_to_window_pixel_xy (w, x, y)
-     struct window *w;
-     int *x, *y;
-{
-  if (w->pseudo_window_p)
-    {
-      /* A pseudo-window is always full-width, and starts at the
-        left edge of the frame, plus a frame border.  */
-      struct frame *f = XFRAME (w->frame);
-      *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
-      *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
-    }
-  else
-    {
-      *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
-      *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
-    }
-}
+#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
 
 
-/* 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.  */
+/* Make audible bell.  */
 
-static void
-note_mode_line_or_margin_highlight (w, x, y, portion)
-     struct window *w;
-     int x, y, portion;
+void
+XTring_bell ()
 {
-  struct frame *f = XFRAME (w->frame);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
-  int charpos;
-  Lisp_Object string, help, map, pos;
-
-  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);
+  struct frame *f = SELECTED_FRAME ();
 
-  if (STRINGP (string))
+  if (FRAME_X_DISPLAY (f))
     {
-      pos = make_number (charpos);
-
-      /* 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))
+#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
+      if (visible_bell)
+       XTflash (f);
+      else
+#endif
        {
-         help_echo = help;
-         XSETWINDOW (help_echo_window, w);
-         help_echo_object = string;
-         help_echo_pos = charpos;
+         BLOCK_INPUT;
+         XBell (FRAME_X_DISPLAY (f), 0);
+         XFlush (FRAME_X_DISPLAY (f));
+         UNBLOCK_INPUT;
        }
-
-     /* 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);
 }
 
-
-/* Take proper action when the mouse has moved to position X, Y on
-   frame F as regards highlighting characters that have mouse-face
-   properties.  Also de-highlighting chars where the mouse was before.
-   X and Y can be negative or out of range.  */
+\f
+/* Specify how many text lines, from the top of the window,
+   should be affected by insert-lines and delete-lines operations.
+   This, and those operations, are used only within an update
+   that is bounded by calls to x_update_begin and x_update_end.  */
 
 static void
-note_mouse_highlight (f, x, y)
-     struct frame *f;
-     int x, y;
+XTset_terminal_window (n)
+     register int n;
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int portion;
-  Lisp_Object window;
-  struct window *w;
-  Cursor cursor = None;
-  struct buffer *b;
-
-  /* When a menu is active, don't highlight because this looks odd.  */
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
-  if (popup_activated ())
-    return;
-#endif
+  /* This function intentionally left blank.  */
+}
 
-  if (NILP (Vmouse_highlight)
-      || !f->glyphs_initialized_p)
-    return;
 
-  dpyinfo->mouse_face_mouse_x = x;
-  dpyinfo->mouse_face_mouse_y = y;
-  dpyinfo->mouse_face_mouse_frame = f;
+\f
+/***********************************************************************
+                             Line Dance
+ ***********************************************************************/
 
-  if (dpyinfo->mouse_face_defer)
-    return;
+/* Perform an insert-lines or delete-lines operation, inserting N
+   lines or deleting -N lines at vertical position VPOS.  */
 
-  if (gc_in_progress)
-    {
-      dpyinfo->mouse_face_deferred_gc = 1;
-      return;
-    }
+static void
+x_ins_del_lines (vpos, n)
+     int vpos, n;
+{
+  abort ();
+}
 
-  /* Which window is that in?  */
-  window = window_from_coordinates (f, x, y, &portion, 1);
 
-  /* If we were displaying active text in another window, clear that.  */
-  if (! EQ (window, dpyinfo->mouse_face_window))
-    clear_mouse_face (dpyinfo);
+/* Scroll part of the display as described by RUN.  */
 
-  /* Not on a window -> return.  */
-  if (!WINDOWP (window))
-    return;
+static void
+x_scroll_run (w, run)
+     struct window *w;
+     struct run *run;
+{
+  struct frame *f = XFRAME (w->frame);
+  int x, y, width, height, from_y, to_y, bottom_y;
 
-  /* Convert to window-relative pixel coordinates.  */
-  w = XWINDOW (window);
-  frame_to_window_pixel_xy (w, &x, &y);
+  /* Get frame-relative bounding box of the text display area of W,
+     without mode lines.  Include in this box the left and right
+     fringe of W.  */
+  window_box (w, -1, &x, &y, &width, &height);
+  width += FRAME_X_FRINGE_WIDTH (f);
+  x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
 
-  /* Handle tool-bar window differently since it doesn't display a
-     buffer.  */
-  if (EQ (window, f->tool_bar_window))
-    {
-      note_tool_bar_highlight (f, x, y);
-      return;
-    }
+  from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
+  to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
+  bottom_y = y + height;
 
-  /* Mouse is on the mode, header line or margin?  */
-  if (portion == 1 || portion == 3 || portion == 6 || portion == 7)
+  if (to_y < from_y)
     {
-      note_mode_line_or_margin_highlight (w, x, y, portion);
-      return;
+      /* Scrolling up.  Make sure we don't copy part of the mode
+        line at the bottom.  */
+      if (from_y + run->height > bottom_y)
+       height = bottom_y - from_y;
+      else
+       height = run->height;
     }
-
-  if (portion == 2)
-    cursor = f->output_data.x->horizontal_drag_cursor;
   else
-    cursor = f->output_data.x->text_cursor;
-
-  /* Are we in a window whose display is up to date?
-     And verify the buffer's text has not changed.  */
-  b = XBUFFER (w->buffer);
-  if (/* Within text portion of the window.  */
-      portion == 0
-      && EQ (w->window_end_valid, w->buffer)
-      && XFASTINT (w->last_modified) == BUF_MODIFF (b)
-      && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
-    {
-      int hpos, vpos, pos, i, area;
-      struct glyph *glyph;
-      Lisp_Object object;
-      Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
-      Lisp_Object *overlay_vec = NULL;
-      int len, noverlays;
-      struct buffer *obuf;
-      int obegv, ozv, same_region;
-
-      /* Find the glyph under X/Y.  */
-      glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
-
-      /* Clear mouse face if X/Y not over text.  */
-      if (glyph == NULL
-         || area != TEXT_AREA
-         || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
-       {
-         if (clear_mouse_face (dpyinfo))
-           cursor = None;
-         goto set_cursor;
-       }
-
-      pos = glyph->charpos;
-      object = glyph->object;
-      if (!STRINGP (object) && !BUFFERP (object))
-       goto set_cursor;
-
-      /* If we get an out-of-range value, return now; avoid an error.  */
-      if (BUFFERP (object) && pos > BUF_Z (b))
-       goto set_cursor;
-
-      /* Make the window's buffer temporarily current for
-        overlays_at and compute_char_face.  */
-      obuf = current_buffer;
-      current_buffer = b;
-      obegv = BEGV;
-      ozv = ZV;
-      BEGV = BEG;
-      ZV = Z;
-
-      /* Is this char mouse-active or does it have help-echo?  */
-      position = make_number (pos);
-
-      if (BUFFERP (object))
-       {
-         /* Put all the overlays we want in a vector in overlay_vec.
-            Store the length in len.  If there are more than 10, make
-            enough space for all, and try again.  */
-         len = 10;
-         overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-         noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
-         if (noverlays > len)
-           {
-             len = noverlays;
-             overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-             noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
-           }
-
-         /* Sort overlays into increasing priority order.  */
-         noverlays = sort_overlays (overlay_vec, noverlays, w);
-       }
+    {
+      /* Scolling down.  Make sure we don't copy over the mode line.
+        at the bottom.  */
+      if (to_y + run->height > bottom_y)
+       height = bottom_y - to_y;
       else
-       noverlays = 0;
-
-      same_region = (EQ (window, dpyinfo->mouse_face_window)
-                    && vpos >= dpyinfo->mouse_face_beg_row
-                    && vpos <= dpyinfo->mouse_face_end_row
-                    && (vpos > dpyinfo->mouse_face_beg_row
-                        || hpos >= dpyinfo->mouse_face_beg_col)
-                    && (vpos < dpyinfo->mouse_face_end_row
-                        || hpos < dpyinfo->mouse_face_end_col
-                        || dpyinfo->mouse_face_past_end));
-
-      if (same_region)
-       cursor = None;
-
-      /* Check mouse-face highlighting.  */
-      if (! same_region
-         /* If there exists an overlay with mouse-face overlapping
-            the one we are currently highlighting, we have to
-            check if we enter the overlapping overlay, and then
-            highlight only that.  */
-         || (OVERLAYP (dpyinfo->mouse_face_overlay)
-             && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
-       {
-         /* Find the highest priority overlay that has a mouse-face
-            property.  */
-         overlay = Qnil;
-         for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
-           {
-             mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
-             if (!NILP (mouse_face))
-               overlay = overlay_vec[i];
-           }
-
-         /* If we're actually highlighting the same overlay as
-            before, there's no need to do that again.  */
-         if (!NILP (overlay)
-             && EQ (overlay, dpyinfo->mouse_face_overlay))
-           goto check_help_echo;
-
-         dpyinfo->mouse_face_overlay = overlay;
-
-         /* Clear the display of the old active region, if any.  */
-         if (clear_mouse_face (dpyinfo))
-           cursor = None;
-
-         /* If no overlay applies, get a text property.  */
-         if (NILP (overlay))
-           mouse_face = Fget_text_property (position, Qmouse_face, object);
-
-         /* Handle the overlay case.  */
-         if (!NILP (overlay))
-           {
-             /* Find the range of text around this char that
-                should be active.  */
-             Lisp_Object before, after;
-             int ignore;
-
-             before = Foverlay_start (overlay);
-             after = Foverlay_end (overlay);
-             /* Record this as the current active region.  */
-             fast_find_position (w, XFASTINT (before),
-                                 &dpyinfo->mouse_face_beg_col,
-                                 &dpyinfo->mouse_face_beg_row,
-                                 &dpyinfo->mouse_face_beg_x,
-                                 &dpyinfo->mouse_face_beg_y, Qnil);
-
-             dpyinfo->mouse_face_past_end
-               = !fast_find_position (w, XFASTINT (after),
-                                      &dpyinfo->mouse_face_end_col,
-                                      &dpyinfo->mouse_face_end_row,
-                                      &dpyinfo->mouse_face_end_x,
-                                      &dpyinfo->mouse_face_end_y, Qnil);
-             dpyinfo->mouse_face_window = window;
-             dpyinfo->mouse_face_face_id
-               = face_at_buffer_position (w, pos, 0, 0,
-                                          &ignore, pos + 1,
-                                          !dpyinfo->mouse_face_hidden);
-
-             /* Display it as active.  */
-             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-             cursor = None;
-           }
-         /* Handle the text property case.  */
-         else if (!NILP (mouse_face) && BUFFERP (object))
-           {
-             /* Find the range of text around this char that
-                should be active.  */
-             Lisp_Object before, after, beginning, end;
-             int ignore;
-
-             beginning = Fmarker_position (w->start);
-             end = make_number (BUF_Z (XBUFFER (object))
-                                - XFASTINT (w->window_end_pos));
-             before
-               = Fprevious_single_property_change (make_number (pos + 1),
-                                                   Qmouse_face,
-                                                   object, beginning);
-             after
-               = Fnext_single_property_change (position, Qmouse_face,
-                                               object, end);
-
-             /* Record this as the current active region.  */
-             fast_find_position (w, XFASTINT (before),
-                                 &dpyinfo->mouse_face_beg_col,
-                                 &dpyinfo->mouse_face_beg_row,
-                                 &dpyinfo->mouse_face_beg_x,
-                                 &dpyinfo->mouse_face_beg_y, Qnil);
-             dpyinfo->mouse_face_past_end
-               = !fast_find_position (w, XFASTINT (after),
-                                      &dpyinfo->mouse_face_end_col,
-                                      &dpyinfo->mouse_face_end_row,
-                                      &dpyinfo->mouse_face_end_x,
-                                      &dpyinfo->mouse_face_end_y, Qnil);
-             dpyinfo->mouse_face_window = window;
-
-             if (BUFFERP (object))
-               dpyinfo->mouse_face_face_id
-                 = face_at_buffer_position (w, pos, 0, 0,
-                                            &ignore, pos + 1,
-                                            !dpyinfo->mouse_face_hidden);
-
-             /* Display it as active.  */
-             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-             cursor = None;
-           }
-         else if (!NILP (mouse_face) && STRINGP (object))
-           {
-             Lisp_Object b, e;
-             int ignore;
-
-             b = Fprevious_single_property_change (make_number (pos + 1),
-                                                   Qmouse_face,
-                                                   object, Qnil);
-             e = Fnext_single_property_change (position, Qmouse_face,
-                                               object, Qnil);
-             if (NILP (b))
-               b = make_number (0);
-             if (NILP (e))
-               e = make_number (SCHARS (object) - 1);
-             fast_find_string_pos (w, XINT (b), object,
-                                   &dpyinfo->mouse_face_beg_col,
-                                   &dpyinfo->mouse_face_beg_row,
-                                   &dpyinfo->mouse_face_beg_x,
-                                   &dpyinfo->mouse_face_beg_y, 0);
-             fast_find_string_pos (w, XINT (e), object,
-                                   &dpyinfo->mouse_face_end_col,
-                                   &dpyinfo->mouse_face_end_row,
-                                   &dpyinfo->mouse_face_end_x,
-                                   &dpyinfo->mouse_face_end_y, 1);
-             dpyinfo->mouse_face_past_end = 0;
-             dpyinfo->mouse_face_window = window;
-             dpyinfo->mouse_face_face_id
-               = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
-                                          glyph->face_id, 1);
-             show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-             cursor = None;
-           }
-         else if (STRINGP (object) && NILP (mouse_face))
-           {
-             /* A string which doesn't have mouse-face, but
-                the text ``under'' it might have.  */
-             struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
-             int start = MATRIX_ROW_START_CHARPOS (r);
-
-             pos = string_buffer_position (w, object, start);
-             if (pos > 0)
-               mouse_face = get_char_property_and_overlay (make_number (pos),
-                                                           Qmouse_face,
-                                                           w->buffer,
-                                                           &overlay);
-             if (!NILP (mouse_face) && !NILP (overlay))
-               {
-                 Lisp_Object before = Foverlay_start (overlay);
-                 Lisp_Object after = Foverlay_end (overlay);
-                 int ignore;
-
-                 /* Note that we might not be able to find position
-                    BEFORE in the glyph matrix if the overlay is
-                    entirely covered by a `display' property.  In
-                    this case, we overshoot.  So let's stop in
-                    the glyph matrix before glyphs for OBJECT.  */
-                 fast_find_position (w, XFASTINT (before),
-                                     &dpyinfo->mouse_face_beg_col,
-                                     &dpyinfo->mouse_face_beg_row,
-                                     &dpyinfo->mouse_face_beg_x,
-                                     &dpyinfo->mouse_face_beg_y,
-                                     object);
-
-                 dpyinfo->mouse_face_past_end
-                   = !fast_find_position (w, XFASTINT (after),
-                                          &dpyinfo->mouse_face_end_col,
-                                          &dpyinfo->mouse_face_end_row,
-                                          &dpyinfo->mouse_face_end_x,
-                                          &dpyinfo->mouse_face_end_y,
-                                          Qnil);
-                 dpyinfo->mouse_face_window = window;
-                 dpyinfo->mouse_face_face_id
-                   = face_at_buffer_position (w, pos, 0, 0,
-                                              &ignore, pos + 1,
-                                              !dpyinfo->mouse_face_hidden);
-
-                 /* Display it as active.  */
-                 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
-                 cursor = None;
-               }
-           }
-       }
-
-    check_help_echo:
-
-      /* Look for a `help-echo' property.  */
-      {
-       Lisp_Object help, overlay;
+       height = run->height;
+    }
 
-       /* Check overlays first.  */
-       help = overlay = Qnil;
-       for (i = noverlays - 1; i >= 0 && NILP (help); --i)
-         {
-           overlay = overlay_vec[i];
-           help = Foverlay_get (overlay, Qhelp_echo);
-         }
+  BLOCK_INPUT;
 
-       if (!NILP (help))
-         {
-           help_echo = help;
-           help_echo_window = window;
-           help_echo_object = overlay;
-           help_echo_pos = pos;
-         }
-       else
-         {
-           Lisp_Object object = glyph->object;
-           int charpos = glyph->charpos;
+  /* Cursor off.  Will be switched on again in x_update_window_end.  */
+  updated_window = w;
+  x_clear_cursor (w);
 
-           /* Try text properties.  */
-           if (STRINGP (object)
-               && charpos >= 0
-               && charpos < SCHARS (object))
-             {
-               help = Fget_text_property (make_number (charpos),
-                                          Qhelp_echo, object);
-               if (NILP (help))
-                 {
-                   /* If the string itself doesn't specify a help-echo,
-                      see if the buffer text ``under'' it does.  */
-                   struct glyph_row *r
-                     = MATRIX_ROW (w->current_matrix, vpos);
-                   int start = MATRIX_ROW_START_CHARPOS (r);
-                   int pos = string_buffer_position (w, object, start);
-                   if (pos > 0)
-                     {
-                       help = Fget_char_property (make_number (pos),
-                                                  Qhelp_echo, w->buffer);
-                       if (!NILP (help))
-                         {
-                           charpos = pos;
-                           object = w->buffer;
-                         }
-                     }
-                 }
-             }
-           else if (BUFFERP (object)
-                    && charpos >= BEGV
-                    && charpos < ZV)
-             help = Fget_text_property (make_number (charpos), Qhelp_echo,
-                                        object);
+  XCopyArea (FRAME_X_DISPLAY (f),
+            FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
+            f->output_data.x->normal_gc,
+            x, from_y,
+            width, height,
+            x, to_y);
 
-           if (!NILP (help))
-             {
-               help_echo = help;
-               help_echo_window = window;
-               help_echo_object = object;
-               help_echo_pos = charpos;
-             }
-         }
-      }
+  UNBLOCK_INPUT;
+}
 
-      BEGV = obegv;
-      ZV = ozv;
-      current_buffer = obuf;
-    }
 
- set_cursor:
+\f
+/***********************************************************************
+                          Exposure Events
+ ***********************************************************************/
 
-  if (cursor != None)
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
+\f
+static void
+frame_highlight (f)
+     struct frame *f;
+{
+  /* We used to only do this if Vx_no_window_manager was non-nil, but
+     the ICCCM (section 4.1.6) says that the window's border pixmap
+     and border pixel are window attributes which are "private to the
+     client", so we can always change it to whatever we want.  */
+  BLOCK_INPUT;
+  XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                   f->output_data.x->border_pixel);
+  UNBLOCK_INPUT;
+  x_update_cursor (f, 1);
 }
 
 static void
-redo_mouse_highlight ()
+frame_unhighlight (f)
+     struct frame *f;
 {
-  if (!NILP (last_mouse_motion_frame)
-      && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
-    note_mouse_highlight (XFRAME (last_mouse_motion_frame),
-                         last_mouse_motion_event.x,
-                         last_mouse_motion_event.y);
+  /* We used to only do this if Vx_no_window_manager was non-nil, but
+     the ICCCM (section 4.1.6) says that the window's border pixmap
+     and border pixel are window attributes which are "private to the
+     client", so we can always change it to whatever we want.  */
+  BLOCK_INPUT;
+  XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                         f->output_data.x->border_tile);
+  UNBLOCK_INPUT;
+  x_update_cursor (f, 1);
 }
 
+/* The focus has changed.  Update the frames as necessary to reflect
+   the new situation.  Note that we can't change the selected frame
+   here, because the Lisp code we are interrupting might become confused.
+   Each event gets marked with the frame in which it occurred, so the
+   Lisp code can tell when the switch took place by examining the events.  */
 
-\f
-/***********************************************************************
-                              Tool-bars
- ***********************************************************************/
+static void
+x_new_focus_frame (dpyinfo, frame)
+     struct x_display_info *dpyinfo;
+     struct frame *frame;
+{
+  struct frame *old_focus = dpyinfo->x_focus_frame;
 
-static int x_tool_bar_item P_ ((struct frame *, int, int,
-                               struct glyph **, int *, int *, int *));
+  if (frame != dpyinfo->x_focus_frame)
+    {
+      /* Set this before calling other routines, so that they see
+        the correct value of x_focus_frame.  */
+      dpyinfo->x_focus_frame = frame;
 
-/* Tool-bar item index of the item on which a mouse button was pressed
-   or -1.  */
+      if (old_focus && old_focus->auto_lower)
+       x_lower_frame (old_focus);
 
-static int last_tool_bar_item;
+#if 0
+      selected_frame = frame;
+      XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
+                selected_frame);
+      Fselect_window (selected_frame->selected_window, Qnil);
+      choose_minibuf_frame ();
+#endif /* ! 0 */
 
+      if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
+       pending_autoraise_frame = dpyinfo->x_focus_frame;
+      else
+       pending_autoraise_frame = 0;
+    }
 
-/* Get information about the tool-bar item at position X/Y on frame F.
-   Return in *GLYPH a pointer to the glyph of the tool-bar item in
-   the current matrix of the tool-bar window of F, or NULL if not
-   on a tool-bar item.  Return in *PROP_IDX the index of the tool-bar
-   item in F->tool_bar_items.  Value is
+  x_frame_rehighlight (dpyinfo);
+}
 
-   -1  if X/Y is not on a tool-bar item
-   0   if X/Y is on the same item that was highlighted before.
-   1   otherwise.  */
+/* Handle FocusIn and FocusOut state changes for FRAME.
+   If FRAME has focus and there exists more than one frame, puts
+   a FOCUS_IN_EVENT into BUFP.
+   Returns number of events inserted into BUFP. */
 
 static int
-x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
-     struct frame *f;
-     int x, y;
-     struct glyph **glyph;
-     int *hpos, *vpos, *prop_idx;
-{
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  struct window *w = XWINDOW (f->tool_bar_window);
-  int area;
-
-  /* Find the glyph under X/Y.  */
-  *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
-  if (*glyph == NULL)
-    return -1;
-
-  /* Get the start of this tool-bar item's properties in
-     f->tool_bar_items.  */
-  if (!tool_bar_item_info (f, *glyph, prop_idx))
-    return -1;
-
-  /* Is mouse on the highlighted item?  */
-  if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
-      && *vpos >= dpyinfo->mouse_face_beg_row
-      && *vpos <= dpyinfo->mouse_face_end_row
-      && (*vpos > dpyinfo->mouse_face_beg_row
-         || *hpos >= dpyinfo->mouse_face_beg_col)
-      && (*vpos < dpyinfo->mouse_face_end_row
-         || *hpos < dpyinfo->mouse_face_end_col
-         || dpyinfo->mouse_face_past_end))
-    return 0;
-
-  return 1;
-}
-
+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;
 
-/* Handle mouse button event on the tool-bar of frame F, at
-   frame-relative coordinates X/Y.  EVENT_TYPE is either ButtonPress
-   or ButtonRelase.  */
+  if (type == FocusIn)
+    {
+      if (dpyinfo->x_focus_event_frame != frame)
+        {
+          x_new_focus_frame (dpyinfo, frame);
+          dpyinfo->x_focus_event_frame = frame;
 
-static void
-x_handle_tool_bar_click (f, button_event)
-     struct frame *f;
-     XButtonEvent *button_event;
-{
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  struct window *w = XWINDOW (f->tool_bar_window);
-  int hpos, vpos, prop_idx;
-  struct glyph *glyph;
-  Lisp_Object enabled_p;
-  int x = button_event->x;
-  int y = button_event->y;
-
-  /* If not on the highlighted tool-bar item, return.  */
-  frame_to_window_pixel_xy (w, &x, &y);
-  if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
-    return;
+          /* 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;
+            }
+        }
 
-  /* If item is disabled, do nothing.  */
-  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
-  if (NILP (enabled_p))
-    return;
+      frame->output_data.x->focus_state |= state;
 
-  if (button_event->type == ButtonPress)
-    {
-      /* Show item in pressed state.  */
-      show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
-      dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
-      last_tool_bar_item = prop_idx;
+#ifdef HAVE_X_I18N
+      if (FRAME_XIC (frame))
+        XSetICFocus (FRAME_XIC (frame));
+#endif
     }
-  else
+  else if (type == FocusOut)
     {
-      Lisp_Object key, frame;
-      struct input_event event;
-
-      /* Show item in released state.  */
-      show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
-      dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
-
-      key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
+      frame->output_data.x->focus_state &= ~state;
 
-      XSETFRAME (frame, f);
-      event.kind = TOOL_BAR_EVENT;
-      event.frame_or_window = frame;
-      event.arg = frame;
-      kbd_buffer_store_event (&event);
+      if (dpyinfo->x_focus_event_frame == frame)
+        {
+          dpyinfo->x_focus_event_frame = 0;
+          x_new_focus_frame (dpyinfo, 0);
+        }
 
-      event.kind = TOOL_BAR_EVENT;
-      event.frame_or_window = frame;
-      event.arg = key;
-      event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                               button_event->state);
-      kbd_buffer_store_event (&event);
-      last_tool_bar_item = -1;
+#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.
 
-/* Possibly highlight a tool-bar item on frame F when mouse moves to
-   tool-bar window-relative coordinates X/Y.  Called from
-   note_mouse_highlight.  */
+   Returns number of events inserted into BUFP. */
 
-static void
-note_tool_bar_highlight (f, x, y)
-     struct frame *f;
-     int x, y;
+static int
+x_detect_focus_change (dpyinfo, event, bufp, numchars)
+     struct x_display_info *dpyinfo;
+     XEvent *event;
+     struct input_event *bufp;
+     int numchars;
 {
-  Lisp_Object window = f->tool_bar_window;
-  struct window *w = XWINDOW (window);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int hpos, vpos;
-  struct glyph *glyph;
-  struct glyph_row *row;
-  int i;
-  Lisp_Object enabled_p;
-  int prop_idx;
-  enum draw_glyphs_face draw;
-  int mouse_down_p, rc;
+  struct frame *frame;
+  int nr_events = 0;
 
-  /* Function note_mouse_highlight is called with negative x(y
-     values when mouse moves outside of the frame.  */
-  if (x <= 0 || y <= 0)
-    {
-      clear_mouse_face (dpyinfo);
-      return;
-    }
+  frame = x_any_window_to_frame (dpyinfo, event->xany.window);
+  if (! frame) return nr_events;
 
-  rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
-  if (rc < 0)
+  switch (event->type)
     {
-      /* Not on tool-bar item.  */
-      clear_mouse_face (dpyinfo);
-      return;
-    }
-  else if (rc == 0)
-    goto set_help_echo;
-
-  clear_mouse_face (dpyinfo);
+    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;
 
-  /* Mouse is down, but on different tool-bar item?  */
-  mouse_down_p = (dpyinfo->grabbed
-                 && f == last_mouse_frame
-                 && FRAME_LIVE_P (f));
-  if (mouse_down_p
-      && last_tool_bar_item != prop_idx)
-    return;
+    case FocusIn:
+    case FocusOut:
+      nr_events = x_focus_changed (event->type,
+                                   (event->xfocus.detail == NotifyPointer
+                                    ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
+                                   dpyinfo,
+                                   frame,
+                                   bufp,
+                                   numchars);
+      break;
+    }
 
-  dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
-  draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
+  return nr_events;
+}
 
-  /* If tool-bar item is not enabled, don't highlight it.  */
-  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
-  if (!NILP (enabled_p))
-    {
-      /* Compute the x-position of the glyph.  In front and past the
-        image is a space.  We include this is the highlighted area.  */
-      row = MATRIX_ROW (w->current_matrix, vpos);
-      for (i = x = 0; i < hpos; ++i)
-       x += row->glyphs[TEXT_AREA][i].pixel_width;
 
-      /* Record this as the current active region.  */
-      dpyinfo->mouse_face_beg_col = hpos;
-      dpyinfo->mouse_face_beg_row = vpos;
-      dpyinfo->mouse_face_beg_x = x;
-      dpyinfo->mouse_face_beg_y = row->y;
-      dpyinfo->mouse_face_past_end = 0;
+/* Handle an event saying the mouse has moved out of an Emacs frame.  */
 
-      dpyinfo->mouse_face_end_col = hpos + 1;
-      dpyinfo->mouse_face_end_row = vpos;
-      dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
-      dpyinfo->mouse_face_end_y = row->y;
-      dpyinfo->mouse_face_window = window;
-      dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
+void
+x_mouse_leave (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+  x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
+}
 
-      /* Display it as active.  */
-      show_mouse_face (dpyinfo, draw);
-      dpyinfo->mouse_face_image_state = draw;
-    }
+/* The focus has changed, or we have redirected a frame's focus to
+   another frame (this happens when a frame uses a surrogate
+   mini-buffer frame).  Shift the highlight as appropriate.
 
- set_help_echo:
+   The FRAME argument doesn't necessarily have anything to do with which
+   frame is being highlighted or un-highlighted; we only use it to find
+   the appropriate X display info.  */
 
-  /* 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;
-  help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
-  if (NILP (help_echo))
-    help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
+static void
+XTframe_rehighlight (frame)
+     struct frame *frame;
+{
+  x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
 }
 
-
-\f
-/* Find the glyph matrix position of buffer position CHARPOS in window
-   *W.  HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
-   current glyphs must be up to date.  If CHARPOS is above window
-   start return (0, 0, 0, 0).  If CHARPOS is after end of W, return end
-   of last line in W.  In the row containing CHARPOS, stop before glyphs
-   having STOP as object.  */
-
-#if 0 /* This is a version of fast_find_position that's more correct
-        in the presence of hscrolling, for example.  I didn't install
-        it right away because the problem fixed is minor, it failed
-        in 20.x as well, and I think it's too risky to install
-        so near the release of 21.1.  2001-09-25 gerd.  */
-
-static int
-fast_find_position (w, charpos, hpos, vpos, x, y, stop)
-     struct window *w;
-     int charpos;
-     int *hpos, *vpos, *x, *y;
-     Lisp_Object stop;
+static void
+x_frame_rehighlight (dpyinfo)
+     struct x_display_info *dpyinfo;
 {
-  struct glyph_row *row, *first;
-  struct glyph *glyph, *end;
-  int i, past_end = 0;
+  struct frame *old_highlight = dpyinfo->x_highlight_frame;
 
-  first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  row = row_containing_pos (w, charpos, first, NULL, 0);
-  if (row == NULL)
+  if (dpyinfo->x_focus_frame)
     {
-      if (charpos < MATRIX_ROW_START_CHARPOS (first))
-       {
-         *x = *y = *hpos = *vpos = 0;
-         return 0;
-       }
-      else
+      dpyinfo->x_highlight_frame
+       = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
+          ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
+          : dpyinfo->x_focus_frame);
+      if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
        {
-         row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
-         past_end = 1;
+         FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
+         dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
        }
     }
+  else
+    dpyinfo->x_highlight_frame = 0;
 
-  *x = row->x;
-  *y = row->y;
-  *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
-
-  glyph = row->glyphs[TEXT_AREA];
-  end = glyph + row->used[TEXT_AREA];
-
-  /* Skip over glyphs not having an object at the start of the row.
-     These are special glyphs like truncation marks on terminal
-     frames.  */
-  if (row->displays_text_p)
-    while (glyph < end
-          && INTEGERP (glyph->object)
-          && !EQ (stop, glyph->object)
-          && glyph->charpos < 0)
-      {
-       *x += glyph->pixel_width;
-       ++glyph;
-      }
-
-  while (glyph < end
-        && !INTEGERP (glyph->object)
-        && !EQ (stop, glyph->object)
-        && (!BUFFERP (glyph->object)
-            || glyph->charpos < charpos))
+  if (dpyinfo->x_highlight_frame != old_highlight)
     {
-      *x += glyph->pixel_width;
-      ++glyph;
+      if (old_highlight)
+       frame_unhighlight (old_highlight);
+      if (dpyinfo->x_highlight_frame)
+       frame_highlight (dpyinfo->x_highlight_frame);
     }
-
-  *hpos = glyph - row->glyphs[TEXT_AREA];
-  return past_end;
 }
 
-#else /* not 0 */
 
-static int
-fast_find_position (w, pos, hpos, vpos, x, y, stop)
-     struct window *w;
-     int pos;
-     int *hpos, *vpos, *x, *y;
-     Lisp_Object stop;
-{
-  int i;
-  int lastcol;
-  int maybe_next_line_p = 0;
-  int line_start_position;
-  int yb = window_text_bottom_y (w);
-  struct glyph_row *row, *best_row;
-  int row_vpos, best_row_vpos;
-  int current_x;
-
-  row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+\f
+/* Keyboard processing - modifier keys, vendor-specific keysyms, etc.  */
 
-  while (row->y < yb)
-    {
-      if (row->used[TEXT_AREA])
-       line_start_position = row->glyphs[TEXT_AREA]->charpos;
-      else
-       line_start_position = 0;
+/* Initialize mode_switch_bit and modifier_meaning.  */
+static void
+x_find_modifier_meanings (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+  int min_code, max_code;
+  KeySym *syms;
+  int syms_per_code;
+  XModifierKeymap *mods;
 
-      if (line_start_position > pos)
-       break;
-      /* If the position sought is the end of the buffer,
-        don't include the blank lines at the bottom of the window.  */
-      else if (line_start_position == pos
-              && pos == BUF_ZV (XBUFFER (w->buffer)))
-       {
-         maybe_next_line_p = 1;
-         break;
-       }
-      else if (line_start_position > 0)
-       {
-         best_row = row;
-         best_row_vpos = row_vpos;
-       }
+  dpyinfo->meta_mod_mask = 0;
+  dpyinfo->shift_lock_mask = 0;
+  dpyinfo->alt_mod_mask = 0;
+  dpyinfo->super_mod_mask = 0;
+  dpyinfo->hyper_mod_mask = 0;
 
-      if (row->y + row->height >= yb)
-       break;
+#ifdef HAVE_X11R4
+  XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
+#else
+  min_code = dpyinfo->display->min_keycode;
+  max_code = dpyinfo->display->max_keycode;
+#endif
 
-      ++row;
-      ++row_vpos;
-    }
+  syms = XGetKeyboardMapping (dpyinfo->display,
+                             min_code, max_code - min_code + 1,
+                             &syms_per_code);
+  mods = XGetModifierMapping (dpyinfo->display);
 
-  /* Find the right column within BEST_ROW.  */
-  lastcol = 0;
-  current_x = best_row->x;
-  for (i = 0; i < best_row->used[TEXT_AREA]; i++)
-    {
-      struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
-      int charpos = glyph->charpos;
+  /* Scan the modifier table to see which modifier bits the Meta and
+     Alt keysyms are on.  */
+  {
+    int row, col;      /* The row and column in the modifier table.  */
 
-      if (BUFFERP (glyph->object))
+    for (row = 3; row < 8; row++)
+      for (col = 0; col < mods->max_keypermod; col++)
        {
-         if (charpos == pos)
-           {
-             *hpos = i;
-             *vpos = best_row_vpos;
-             *x = current_x;
-             *y = best_row->y;
-             return 1;
-           }
-         else if (charpos > pos)
-           break;
-       }
-      else if (EQ (glyph->object, stop))
-       break;
-
-      if (charpos > 0)
-       lastcol = i;
-      current_x += glyph->pixel_width;
-    }
-
-  /* If we're looking for the end of the buffer,
-     and we didn't find it in the line we scanned,
-     use the start of the following line.  */
-  if (maybe_next_line_p)
-    {
-      ++best_row;
-      ++best_row_vpos;
-      lastcol = 0;
-      current_x = best_row->x;
-    }
-
-  *vpos = best_row_vpos;
-  *hpos = lastcol + 1;
-  *x = current_x;
-  *y = best_row->y;
-  return 0;
-}
+         KeyCode code
+           = mods->modifiermap[(row * mods->max_keypermod) + col];
 
-#endif /* not 0 */
+         /* Zeroes are used for filler.  Skip them.  */
+         if (code == 0)
+           continue;
 
+         /* Are any of this keycode's keysyms a meta key?  */
+         {
+           int code_col;
 
-/* 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.
+           for (code_col = 0; code_col < syms_per_code; code_col++)
+             {
+               int sym = syms[((code - min_code) * syms_per_code) + code_col];
 
-   RIGHT_P non-zero means return the position of the right edge of the
-   glyph, RIGHT_P zero means return the left edge position.
+               switch (sym)
+                 {
+                 case XK_Meta_L:
+                 case XK_Meta_R:
+                   dpyinfo->meta_mod_mask |= (1 << row);
+                   break;
 
-   If no glyph for POS exists in the matrix, return the position of
-   the glyph with the next smaller position that is in the matrix, if
-   RIGHT_P is zero.  If RIGHT_P is non-zero, and no glyph for POS
-   exists in the matrix, return the position of the glyph with the
-   next larger position in OBJECT.
+                 case XK_Alt_L:
+                 case XK_Alt_R:
+                   dpyinfo->alt_mod_mask |= (1 << row);
+                   break;
 
-   Value is non-zero if a glyph was found.  */
+                 case XK_Hyper_L:
+                 case XK_Hyper_R:
+                   dpyinfo->hyper_mod_mask |= (1 << row);
+                   break;
 
-static int
-fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
-     struct window *w;
-     int pos;
-     Lisp_Object object;
-     int *hpos, *vpos, *x, *y;
-     int right_p;
-{
-  int yb = window_text_bottom_y (w);
-  struct glyph_row *r;
-  struct glyph *best_glyph = NULL;
-  struct glyph_row *best_row = NULL;
-  int best_x = 0;
-
-  for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-       r->enabled_p && r->y < yb;
-       ++r)
-    {
-      struct glyph *g = r->glyphs[TEXT_AREA];
-      struct glyph *e = g + r->used[TEXT_AREA];
-      int gx;
-
-      for (gx = r->x; g < e; gx += g->pixel_width, ++g)
-       if (EQ (g->object, object))
-         {
-           if (g->charpos == pos)
-             {
-               best_glyph = g;
-               best_x = gx;
-               best_row = r;
-               goto found;
-             }
-           else if (best_glyph == NULL
-                    || ((abs (g->charpos - pos)
-                        < abs (best_glyph->charpos - pos))
-                        && (right_p
-                            ? g->charpos < pos
-                            : g->charpos > pos)))
-             {
-               best_glyph = g;
-               best_x = gx;
-               best_row = r;
+                 case XK_Super_L:
+                 case XK_Super_R:
+                   dpyinfo->super_mod_mask |= (1 << row);
+                   break;
+
+                 case XK_Shift_Lock:
+                   /* Ignore this if it's not on the lock modifier.  */
+                   if ((1 << row) == LockMask)
+                     dpyinfo->shift_lock_mask = LockMask;
+                   break;
+                 }
              }
          }
-    }
-
- found:
+       }
+  }
 
-  if (best_glyph)
+  /* If we couldn't find any meta keys, accept any alt keys as meta keys.  */
+  if (! dpyinfo->meta_mod_mask)
     {
-      *x = best_x;
-      *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
-
-      if (right_p)
-       {
-         *x += best_glyph->pixel_width;
-         ++*hpos;
-       }
+      dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
+      dpyinfo->alt_mod_mask = 0;
+    }
 
-      *y = best_row->y;
-      *vpos = best_row - w->current_matrix->rows;
+  /* If some keys are both alt and meta,
+     make them just meta, not alt.  */
+  if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
+    {
+      dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
     }
 
-  return best_glyph != NULL;
+  XFree ((char *) syms);
+  XFreeModifiermap (mods);
 }
 
+/* Convert between the modifier bits X uses and the modifier bits
+   Emacs uses.  */
 
-/* Display the active region described by mouse_face_*
-   in its mouse-face if HL > 0, in its normal face if HL = 0.  */
-
-static void
-show_mouse_face (dpyinfo, draw)
+static unsigned int
+x_x_to_emacs_modifiers (dpyinfo, state)
      struct x_display_info *dpyinfo;
-     enum draw_glyphs_face draw;
+     unsigned int state;
 {
-  struct window *w = XWINDOW (dpyinfo->mouse_face_window);
-  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  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;
 
-  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)
-    {
-      int phys_cursor_on_p = w->phys_cursor_on_p;
-      struct glyph_row *row, *first, *last;
+  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);
 
-      first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
-      last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
 
-      for (row = first; row <= last && row->enabled_p; ++row)
-       {
-         int start_hpos, end_hpos, start_x;
+  return (  ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_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));
+}
 
-         /* For all but the first row, the highlight starts at column 0.  */
-         if (row == first)
-           {
-             start_hpos = dpyinfo->mouse_face_beg_col;
-             start_x = dpyinfo->mouse_face_beg_x;
-           }
-         else
-           {
-             start_hpos = 0;
-             start_x = 0;
-           }
+static unsigned int
+x_emacs_to_x_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;
 
-         if (row == last)
-           end_hpos = dpyinfo->mouse_face_end_col;
-         else
-           end_hpos = row->used[TEXT_AREA];
+  Lisp_Object tem;
 
-         if (end_hpos > start_hpos)
-           {
-             x_draw_glyphs (w, start_x, row, TEXT_AREA,
-                            start_hpos, end_hpos, draw, 0);
+  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);
 
-             row->mouse_face_p
-               = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
-           }
-       }
 
-      /* When we've written over the cursor, arrange for it to
-        be displayed again.  */
-      if (phys_cursor_on_p && !w->phys_cursor_on_p)
-       x_display_cursor (w, 1,
-                         w->phys_cursor.hpos, w->phys_cursor.vpos,
-                         w->phys_cursor.x, w->phys_cursor.y);
-    }
-
-  /* Change the mouse cursor.  */
-  if (draw == DRAW_NORMAL_TEXT)
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->text_cursor);
-  else if (draw == DRAW_MOUSE_FACE)
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->cross_cursor);
-  else
-    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  f->output_data.x->nontext_cursor);
+  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));
 }
 
-/* Clear out the mouse-highlighted active region.
-   Redraw it un-highlighted first.  Value is non-zero if mouse
-   face was actually drawn unhighlighted.  */
+/* Convert a keysym to its name.  */
 
-static int
-clear_mouse_face (dpyinfo)
-     struct x_display_info *dpyinfo;
+char *
+x_get_keysym_name (keysym)
+     KeySym keysym;
 {
-  int cleared = 0;
+  char *value;
 
-  if (!NILP (dpyinfo->mouse_face_window))
-    {
-      show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
-      cleared = 1;
-    }
+  BLOCK_INPUT;
+  value = XKeysymToString (keysym);
+  UNBLOCK_INPUT;
 
-  dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
-  dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
-  dpyinfo->mouse_face_window = Qnil;
-  dpyinfo->mouse_face_overlay = Qnil;
-  return cleared;
+  return value;
 }
 
 
-/* Clear any mouse-face on window W.  This function is part of the
-   redisplay interface, and is called from try_window_id and similar
-   functions to ensure the mouse-highlight is off.  */
+\f
+/* Mouse clicks and mouse movement.  Rah.  */
 
-static void
-x_clear_mouse_face (w)
-     struct window *w;
+/* Prepare a mouse-event in *RESULT for placement in the input queue.
+
+   If the event is a button press, then note that we have grabbed
+   the mouse.  */
+
+static Lisp_Object
+construct_mouse_click (result, event, f)
+     struct input_event *result;
+     XButtonEvent *event;
+     struct frame *f;
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
-  Lisp_Object window;
+  /* Make the event type NO_EVENT; we'll change that when we decide
+     otherwise.  */
+  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),
+                                              event->state)
+                      | (event->type == ButtonRelease
+                         ? up_modifier
+                         : down_modifier));
 
-  BLOCK_INPUT;
-  XSETWINDOW (window, w);
-  if (EQ (window, dpyinfo->mouse_face_window))
-    clear_mouse_face (dpyinfo);
-  UNBLOCK_INPUT;
+  XSETINT (result->x, event->x);
+  XSETINT (result->y, event->y);
+  XSETFRAME (result->frame_or_window, f);
+  result->arg = Qnil;
+  return Qnil;
 }
 
+\f
+/* Function to report a mouse movement to the mainstream Emacs code.
+   The input handler calls this.
+
+   We have received a mouse movement event, which is given in *event.
+   If the mouse is over a different glyph than it was last time, tell
+   the mainstream emacs code by setting mouse_moved.  If not, ask for
+   another motion event, so we can check again the next time it moves.  */
 
-/* Just discard the mouse face information for frame F, if any.
-   This is used when the size of F is changed.  */
+static XMotionEvent last_mouse_motion_event;
+static Lisp_Object last_mouse_motion_frame;
 
-void
-cancel_mouse_face (f)
-     FRAME_PTR f;
+static void
+note_mouse_movement (frame, event)
+     FRAME_PTR frame;
+     XMotionEvent *event;
 {
-  Lisp_Object window;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  last_mouse_movement_time = event->time;
+  last_mouse_motion_event = *event;
+  XSETFRAME (last_mouse_motion_frame, frame);
 
-  window = dpyinfo->mouse_face_window;
-  if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
+  if (event->window != FRAME_X_WINDOW (frame))
     {
-      dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
-      dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
-      dpyinfo->mouse_face_window = Qnil;
+      frame->mouse_moved = 1;
+      last_mouse_scroll_bar = Qnil;
+      note_mouse_highlight (frame, -1, -1);
+    }
+
+  /* Has the mouse moved off the glyph it was on at the last sighting?  */
+  else if (event->x < last_mouse_glyph.x
+          || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
+          || event->y < last_mouse_glyph.y
+          || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
+    {
+      frame->mouse_moved = 1;
+      last_mouse_scroll_bar = Qnil;
+      note_mouse_highlight (frame, event->x, event->y);
     }
 }
 
 \f
+/************************************************************************
+                             Mouse Face
+ ************************************************************************/
+
+static void
+redo_mouse_highlight ()
+{
+  if (!NILP (last_mouse_motion_frame)
+      && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
+    note_mouse_highlight (XFRAME (last_mouse_motion_frame),
+                         last_mouse_motion_event.x,
+                         last_mouse_motion_event.y);
+}
+
+
 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
 
 
@@ -8142,9 +3572,9 @@ glyph_rect (f, x, y, rect)
      XRectangle *rect;
 {
   Lisp_Object window;
-  int part, found = 0;
+  int found = 0;
 
-  window = window_from_coordinates (f, x, y, &part, 0);
+  window = window_from_coordinates (f, x, y, 0, 0);
   if (!NILP (window))
     {
       struct window *w = XWINDOW (window);
@@ -8401,29 +3831,11 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 }
 
 
-#ifdef USE_X_TOOLKIT
-
-/* Atimer callback function for TIMER.  Called every 0.1s to process
-   Xt timeouts, if needed.  We must avoid calling XtAppPending as
-   much as possible because that function does an implicit XFlush
-   that slows us down.  */
-
-static void
-x_process_timeouts (timer)
-     struct atimer *timer;
-{
-  if (toolkit_scroll_bar_interaction || popup_activated ())
-    {
-      BLOCK_INPUT;
-      while (XtAppPending (Xt_app_con) & XtIMTimer)
-       XtAppProcessEvent (Xt_app_con, XtIMTimer);
-      UNBLOCK_INPUT;
-    }
-}
-
-#endif /* USE_X_TOOLKIT */
-
 \f
+/***********************************************************************
+                              Scroll bars
+ ***********************************************************************/
+
 /* Scroll bar support.  */
 
 /* Given an X window ID, find the struct scroll_bar which manages it.
@@ -8436,6 +3848,10 @@ x_window_to_scroll_bar (window_id)
 {
   Lisp_Object tail;
 
+#ifdef USE_GTK
+  window_id = (Window) xg_get_scroll_id_for_window (window_id);
+#endif /* USE_GTK */
+
   for (tail = Vframe_list;
        XGCTYPE (tail) == Lisp_Cons;
        tail = XCDR (tail))
@@ -8532,6 +3948,7 @@ static Boolean xaw3d_arrow_scroll;
 
 static Boolean xaw3d_pick_top;
 
+extern void set_vertical_scroll_bar P_ ((struct window *));
 
 /* Action hook installed via XtAppAddActionHook when toolkit scroll
    bars are used..  The hook is responsible for detecting when
@@ -8568,7 +3985,13 @@ xt_action_hook (widget, client_data, action_name, event, params,
       x_send_scroll_bar_event (window_being_scrolled,
                               scroll_bar_end_scroll, 0, 0);
       w = XWINDOW (window_being_scrolled);
-      XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
+      
+      if (!NILP (XSCROLL_BAR (w->vertical_scroll_bar)->dragging))
+       {
+         XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
+         /* The thumb size is incorrect while dragging: fix it.  */
+         set_vertical_scroll_bar (w);
+       }
       window_being_scrolled = Qnil;
       last_scroll_bar_part = -1;
 
@@ -8687,9 +4110,7 @@ x_scroll_bar_to_input_event (event, ievent)
 
 /* Minimum and maximum values used for Motif scroll bars.  */
 
-#define XM_SB_MIN 1
 #define XM_SB_MAX 10000000
-#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
 
 
 /* Scroll bar callback for Motif scroll bars.  WIDGET is the scroll
@@ -8740,16 +4161,14 @@ xm_scroll_callback (widget, client_data, call_data)
     case XmCR_DRAG:
       {
        int slider_size;
-       int dragging_down_p = (INTEGERP (bar->dragging)
-                              && XINT (bar->dragging) <= cs->value);
 
        /* Get the slider size.  */
        BLOCK_INPUT;
        XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
        UNBLOCK_INPUT;
 
-       whole = XM_SB_RANGE - slider_size;
-       portion = min (cs->value - XM_SB_MIN, whole);
+       whole = XM_SB_MAX - slider_size;
+       portion = min (cs->value, whole);
        part = scroll_bar_handle;
        bar->dragging = make_number (cs->value);
       }
@@ -8770,12 +4189,12 @@ xm_scroll_callback (widget, client_data, call_data)
 
 #else /* !USE_MOTIF, i.e. Xaw or GTK */
 #ifdef USE_GTK
-/* Scroll bar callback for Gtk scroll bars.  WIDGET is the scroll
-   bar adjustment widget.  DATA is a pointer to the scroll_bar structure. */
+/* Scroll bar callback for GTK scroll bars.  WIDGET is the scroll
+   bar widget.  DATA is a pointer to the scroll_bar structure. */
 
 static void
 xg_scroll_callback (widget, data)
-     GtkWidget *widget;
+     GtkRange *widget;
      gpointer data;
 {
   struct scroll_bar *bar = (struct scroll_bar *) data;
@@ -8783,12 +4202,12 @@ xg_scroll_callback (widget, data)
   gdouble position;
   gdouble *p;
   int diff;
-  
+
   int part = -1, whole = 0, portion = 0;
-  GtkAdjustment *adj = GTK_ADJUSTMENT (widget);
-  
+  GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (widget));
+
   if (xg_ignore_gtk_scrollbar) return;
-  
+
   position = gtk_adjustment_get_value (adj);
 
   p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
@@ -8803,7 +4222,7 @@ xg_scroll_callback (widget, data)
   *p = position;
 
   diff = (int) (position - previous);
-  
+
   if (diff == (int) adj->step_increment)
     {
       part = scroll_bar_down_arrow;
@@ -8828,13 +4247,12 @@ xg_scroll_callback (widget, data)
     {
       part = scroll_bar_handle;
       whole = adj->upper - adj->page_size;
-      portion = min (position, whole);
-      bar->dragging = make_number (portion);
+      portion = min ((int)position, whole);
+      bar->dragging = make_number ((int)portion);
     }
-  
+
   if (part >= 0)
     {
-      xg_ignore_next_thumb = 1;
       window_being_scrolled = bar->window;
       last_scroll_bar_part = part;
       x_send_scroll_bar_event (bar->window, part, portion, whole);
@@ -8965,7 +4383,7 @@ x_create_toolkit_scroll_bar (f, bar)
 #ifdef USE_MOTIF
   /* Set resources.  Create the widget.  */
   XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
-  XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
+  XtSetArg (av[ac], XmNminimum, 0); ++ac;
   XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
   XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
   XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
@@ -9190,14 +4608,13 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
       /* 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 = shown * XM_SB_MAX;
+      size = min (size, XM_SB_MAX);
       size = max (size, 1);
 
       /* Position.  Must be in the range [MIN .. MAX - SLIDER_SIZE].  */
-      value = top * XM_SB_RANGE;
+      value = top * XM_SB_MAX;
       value = min (value, XM_SB_MAX - size);
-      value = max (value, XM_SB_MIN);
 
       XmScrollBarSetValues (widget, value, size, 0, 0, False);
     }
@@ -9363,7 +4780,9 @@ x_scroll_bar_create (w, top, left, width, height)
                              top,
                              left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                              width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                             max (height, 1));
+                             max (height, 1),
+                             left,
+                             width);
     xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
 #else /* not USE_GTK */
     Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
@@ -9613,7 +5032,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
                                  top,
                                  sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                                  sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                                 max (height, 1));
+                                 max (height, 1),
+                                 left,
+                                 width);
 #else /* not USE_GTK */
 
       /* Since toolkit scroll bars are smaller than the space reserved
@@ -9819,6 +5240,7 @@ XTjudge_scroll_bars (f)
 }
 
 
+#ifndef USE_TOOLKIT_SCROLL_BARS
 /* Handle an Expose or GraphicsExpose event on a scroll bar.  This
    is a no-op when using toolkit scroll bars.
 
@@ -9830,8 +5252,6 @@ x_scroll_bar_expose (bar, event)
      struct scroll_bar *bar;
      XEvent *event;
 {
-#ifndef USE_TOOLKIT_SCROLL_BARS
-
   Window w = SCROLL_BAR_X_WINDOW (bar);
   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   GC gc = f->output_data.x->normal_gc;
@@ -9851,8 +5271,8 @@ x_scroll_bar_expose (bar, event)
 
   UNBLOCK_INPUT;
 
-#endif /* not USE_TOOLKIT_SCROLL_BARS */
 }
+#endif /* not USE_TOOLKIT_SCROLL_BARS */
 
 /* 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.
@@ -9860,7 +5280,6 @@ x_scroll_bar_expose (bar, event)
    This may be called from a signal handler, so we have to ignore GC
    mark bits.  */
 
-#ifndef USE_TOOLKIT_SCROLL_BARS
 
 static void
 x_scroll_bar_handle_click (bar, event, emacs_event)
@@ -9914,6 +5333,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
       XSETINT (bar->dragging, y - XINT (bar->start));
 #endif
 
+#ifndef USE_TOOLKIT_SCROLL_BARS
     /* If the user has released the handle, set it to its final position.  */
     if (event->type == ButtonRelease
        && ! NILP (bar->dragging))
@@ -9924,6 +5344,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
        x_scroll_bar_set_handle (bar, new_start, new_end, 0);
        bar->dragging = Qnil;
       }
+#endif
 
     /* Same deal here as the other #if 0.  */
 #if 0
@@ -9941,6 +5362,8 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
   }
 }
 
+#ifndef USE_TOOLKIT_SCROLL_BARS
+
 /* Handle some mouse motion while someone is dragging the scroll bar.
 
    This may be called from a signal handler, so we have to ignore GC
@@ -10214,6 +5637,32 @@ enum
   X_EVENT_DROP
 };
 
+/* Filter events for the current X input method.
+   DPYINFO is the display this event is for.
+   EVENT is the X event to filter.
+
+   Returns non-zero if the event was filtered, caller shall not process
+   this event further.
+   Returns zero if event is wasn't filtered.  */
+
+#ifdef HAVE_X_I18N
+static int
+x_filter_event (dpyinfo, event)
+     struct x_display_info *dpyinfo;
+     XEvent *event;
+{
+  /* XFilterEvent returns non-zero if the input method has
+   consumed the event.  We pass the frame's X window to
+   XFilterEvent because that's the one for which the IC
+   was created.  */
+
+  struct frame *f1 = x_any_window_to_frame (dpyinfo,
+                                            event->xclient.window);
+
+  return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
+}
+#endif
+
 #ifdef USE_GTK
 static struct x_display_info *current_dpyinfo;
 static struct input_event **current_bufp;
@@ -10233,13 +5682,23 @@ event_handler_gdk (gxev, ev, data)
   XEvent *xev = (XEvent*)gxev;
 
   if (current_numcharsp)
-    current_count += handle_one_xevent (current_dpyinfo,
-                                        xev,
-                                        current_bufp,
-                                        current_numcharsp,
-                                        &current_finish);
+    {
+#ifdef HAVE_X_I18N
+      /* Filter events for the current X input method.
+         GTK calls XFilterEvent but not for key press and release,
+         so we do it here.  */
+      if (xev->type == KeyPress || xev->type == KeyRelease)
+        if (x_filter_event (current_dpyinfo, xev))
+          return GDK_FILTER_REMOVE;
+#endif
+      current_count += handle_one_xevent (current_dpyinfo,
+                                          xev,
+                                          current_bufp,
+                                          current_numcharsp,
+                                          &current_finish);
+    }
   else
-    x_dispatch_event (xev, GDK_DISPLAY ());
+    current_finish = x_dispatch_event (xev, GDK_DISPLAY ());
 
   if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
     return GDK_FILTER_REMOVE;
@@ -10250,7 +5709,7 @@ event_handler_gdk (gxev, ev, data)
 
 
 /* Handles the XEvent EVENT on display DPYINFO.
-   
+
    *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
    *FINISH is zero if caller should continue reading events.
    *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
@@ -10258,7 +5717,7 @@ event_handler_gdk (gxev, ev, data)
    Events representing keys are stored in buffer *BUFP_R,
    which can hold up to *NUMCHARSP characters.
    We return the number of characters stored into the buffer. */
-   
+
 static int
 handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
      struct x_display_info *dpyinfo;
@@ -10276,7 +5735,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
   XEvent event = *eventp;
 
   *finish = X_EVENT_NORMAL;
-  
+
   switch (event.type)
     {
     case ClientMessage:
@@ -10533,8 +5992,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           x_real_positions (f, &x, &y);
           f->output_data.x->left_pos = x;
           f->output_data.x->top_pos = y;
-          goto OTHER;
         }
+      goto OTHER;
       break;
 
     case Expose:
@@ -11148,7 +6607,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
               int n;
 
               XSETFRAME (frame, f);
-              help_echo = Qnil;
+              help_echo_string = Qnil;
               n = gen_help_event (bufp, numchars,
                                   Qnil, frame, Qnil, Qnil, 0);
               bufp += n, count += n, numchars -= n;
@@ -11172,8 +6631,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
     case MotionNotify:
       {
-        previous_help_echo = help_echo;
-        help_echo = help_echo_object = help_echo_window = Qnil;
+        previous_help_echo_string = help_echo_string;
+        help_echo_string = help_echo_object = help_echo_window = Qnil;
         help_echo_pos = -1;
 
         if (dpyinfo->grabbed && last_mouse_frame
@@ -11195,11 +6654,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
             if (mouse_autoselect_window)
               {
                 Lisp_Object window;
-                int area;
 
                 window = window_from_coordinates (f,
                                                   event.xmotion.x, event.xmotion.y,
-                                                  &area, 0);
+                                                  0, 0);
 
                 /* Window will be selected only when it is not selected now and
                    last mouse movement event was not in it.  Minibuffer window
@@ -11234,10 +6692,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
             clear_mouse_face (dpyinfo);
           }
 
-        /* If the contents of the global variable help_echo
+        /* If the contents of the global variable help_echo_string
            has changed, generate a HELP_EVENT.  */
-        if (!NILP (help_echo)
-            || !NILP (previous_help_echo))
+        if (!NILP (help_echo_string)
+            || !NILP (previous_help_echo_string))
           {
             Lisp_Object frame;
             int n;
@@ -11248,7 +6706,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
               frame = Qnil;
 
             any_help_event_p = 1;
-            n = gen_help_event (bufp, numchars, help_echo, frame,
+            n = gen_help_event (bufp, numchars, help_echo_string, frame,
                                 help_echo_window, help_echo_object,
                                 help_echo_pos);
             bufp += n, count += n, numchars -= n;
@@ -11359,17 +6817,19 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
               {
                 Lisp_Object window;
-                int p, x, y;
+                int x = event.xbutton.x;
+                int y = event.xbutton.y;
 
-                x = event.xbutton.x;
-                y = event.xbutton.y;
-
-                /* Set x and y.  */
-                window = window_from_coordinates (f, x, y, &p, 1);
+                window = window_from_coordinates (f, x, y, 0, 1);
                 if (EQ (window, f->tool_bar_window))
                   {
-                    x_handle_tool_bar_click (f, &event.xbutton);
-                    tool_bar_p = 1;
+                   if (event.xbutton.type == ButtonPress)
+                     handle_tool_bar_click (f, x, y, 1, 0);
+                   else
+                     handle_tool_bar_click (f, x, y, 0,
+                                            x_x_to_emacs_modifiers (dpyinfo,
+                                                                    event.xbutton.state));
+                   tool_bar_p = 1;
                   }
               }
 
@@ -11385,10 +6845,18 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           }
         else
           {
-#ifndef USE_TOOLKIT_SCROLL_BARS
             struct scroll_bar *bar
               = x_window_to_scroll_bar (event.xbutton.window);
 
+#ifdef USE_TOOLKIT_SCROLL_BARS
+            /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
+               scroll bars.  */
+            if (bar && event.xbutton.state & ControlMask)
+              {
+                x_scroll_bar_handle_click (bar, &event, &emacs_event);
+                *finish = X_EVENT_DROP;
+              }
+#else /* not USE_TOOLKIT_SCROLL_BARS */
             if (bar)
               x_scroll_bar_handle_click (bar, &event, &emacs_event);
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
@@ -11498,14 +6966,15 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
     OTHER:
 #ifdef USE_X_TOOLKIT
     BLOCK_INPUT;
-    XtDispatchEvent (&event);
+    if (*finish != X_EVENT_DROP)
+      XtDispatchEvent (&event);
     UNBLOCK_INPUT;
 #endif /* USE_X_TOOLKIT */
     break;
     }
 
   goto ret;
-  
+
  out:
   *finish = X_EVENT_GOTO_OUT;
 
@@ -11513,15 +6982,17 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
   *bufp_r = bufp;
   *numcharsp = numchars;
   *eventp = event;
-  
+
   return count;
 }
 
 
 /* Handles the XEvent EVENT on display DISPLAY.
    This is used for event loops outside the normal event handling,
-   i.e. looping while a popup menu or a dialog is posted.  */
-void
+   i.e. looping while a popup menu or a dialog is posted.
+
+   Returns the value handle_one_xevent sets in the finish argument.  */
+int
 x_dispatch_event (event, display)
      XEvent *event;
      Display *display;
@@ -11530,12 +7001,12 @@ x_dispatch_event (event, display)
   struct input_event bufp[10];
   struct input_event *bufpp = bufp;
   int numchars = 10;
-  int finish;
-      
+  int finish = X_EVENT_NORMAL;
+
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
     if (dpyinfo->display == display)
       break;
-          
+
   if (dpyinfo)
     {
       int i, events;
@@ -11547,6 +7018,8 @@ x_dispatch_event (event, display)
       for (i = 0; i < events; ++i)
         kbd_buffer_store_event (&bufp[i]);
     }
+
+  return finish;
 }
 
 
@@ -11569,7 +7042,6 @@ XTread_socket (sd, bufp, numchars, expected)
      int expected;
 {
   int count = 0;
-  int nbytes = 0;
   XEvent event;
   int event_found = 0;
   struct x_display_info *dpyinfo;
@@ -11641,7 +7113,7 @@ XTread_socket (sd, bufp, numchars, expected)
          We use a bunch of globals to communicate with our filter function,
          that is kind of ugly, but it works. */
       current_dpyinfo = dpyinfo;
-      
+
       while (gtk_events_pending ())
         {
           static int nr = 0;
@@ -11663,21 +7135,13 @@ XTread_socket (sd, bufp, numchars, expected)
       while (XPending (dpyinfo->display))
        {
           int finish;
-          
+
          XNextEvent (dpyinfo->display, &event);
 
 #ifdef HAVE_X_I18N
-         {
-           /* Filter events for the current X input method.
-              XFilterEvent returns non-zero if the input method has
-              consumed the event.  We pass the frame's X window to
-              XFilterEvent because that's the one for which the IC
-              was created.  */
-           struct frame *f1 = x_any_window_to_frame (dpyinfo,
-                                                     event.xclient.window);
-           if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
-             break;
-         }
+          /* Filter events for the current X input method.  */
+          if (x_filter_event (dpyinfo, &event))
+            break;
 #endif
          event_found = 1;
 
@@ -11738,52 +7202,6 @@ XTread_socket (sd, bufp, numchars, expected)
                             Text Cursor
  ***********************************************************************/
 
-/* 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, area, x0, x1, y0, y1)
-     struct window *w;
-     enum glyph_row_area area;
-     int x0, y0, x1, y1;
-{
-  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;
-       }
-    }
-}
-
-
 /* Set clipping for output in glyph row ROW.  W is the window in which
    we operate.  GC is the graphics context to set clipping in.
    WHOLE_LINE_P non-zero means include the areas used for truncation
@@ -11910,7 +7328,7 @@ x_draw_bar_cursor (w, row, width, kind)
     {
       struct glyph_row *row;
       row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
-      x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
+      draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
     }
   else
     {
@@ -11965,281 +7383,62 @@ x_draw_bar_cursor (w, row, width, kind)
 }
 
 
-/* Clear the cursor of window W to background color, and mark the
-   cursor as not shown.  This is used when the text where the cursor
-   is is about to be rewritten.  */
+/* RIF: Define cursor CURSOR on frame F.  */
 
 static void
-x_clear_cursor (w)
-     struct window *w;
+x_define_frame_cursor (f, cursor)
+     struct frame *f;
+     Cursor cursor;
 {
-  if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
-    x_update_window_cursor (w, 0);
+  XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
 }
 
 
-/* Draw the cursor glyph of window W in glyph row ROW.  See the
-   comment of x_draw_glyphs for the meaning of HL.  */
+/* RIF: Clear area on frame F.  */
 
 static void
-x_draw_phys_cursor_glyph (w, row, hl)
-     struct window *w;
-     struct glyph_row *row;
-     enum draw_glyphs_face hl;
+x_clear_frame_area (f, x, y, width, height)
+     struct frame *f;
+     int x, y, width, height;
 {
-  /* If cursor hpos is out of bounds, don't draw garbage.  This can
-     happen in mini-buffer windows when switching between echo area
-     glyphs and mini-buffer.  */
-  if (w->phys_cursor.hpos < row->used[TEXT_AREA])
-    {
-      int on_p = w->phys_cursor_on_p;
-      int x1;
-
-      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.  */
-      else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
-       {
-         if (row > w->current_matrix->rows
-             && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
-           x_fix_overlapping_area (w, row - 1, TEXT_AREA);
-
-         if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
-             && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
-           x_fix_overlapping_area (w, row + 1, TEXT_AREA);
-       }
-    }
+  x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+               x, y, width, height, False);
 }
 
 
-/* Erase the image of a cursor of window W from the screen.  */
+/* RIF: Draw cursor on window W.  */
 
 static void
-x_erase_phys_cursor (w)
-     struct window *w;
-{
-  struct frame *f = XFRAME (w->frame);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int hpos = w->phys_cursor.hpos;
-  int vpos = w->phys_cursor.vpos;
-  int mouse_face_here_p = 0;
-  struct glyph_matrix *active_glyphs = w->current_matrix;
-  struct glyph_row *cursor_row;
-  struct glyph *cursor_glyph;
-  enum draw_glyphs_face hl;
-
-  /* No cursor displayed or row invalidated => nothing to do on the
-     screen.  */
-  if (w->phys_cursor_type == NO_CURSOR)
-    goto mark_cursor_off;
-
-  /* VPOS >= active_glyphs->nrows means that window has been resized.
-     Don't bother to erase the cursor.  */
-  if (vpos >= active_glyphs->nrows)
-    goto mark_cursor_off;
-
-  /* If row containing cursor is marked invalid, there is nothing we
-     can do.  */
-  cursor_row = MATRIX_ROW (active_glyphs, vpos);
-  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
-     able to erase the cursor in this case because we don't have a
-     cursor glyph at hand.  */
-  if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
-    goto mark_cursor_off;
-
-  /* If the cursor is in the mouse face area, redisplay that when
-     we clear the cursor.  */
-  if (! NILP (dpyinfo->mouse_face_window)
-      && w == XWINDOW (dpyinfo->mouse_face_window)
-      && (vpos > dpyinfo->mouse_face_beg_row
-         || (vpos == dpyinfo->mouse_face_beg_row
-             && hpos >= dpyinfo->mouse_face_beg_col))
-      && (vpos < dpyinfo->mouse_face_end_row
-         || (vpos == dpyinfo->mouse_face_end_row
-             && hpos < dpyinfo->mouse_face_end_col))
-      /* Don't redraw the cursor's spot in mouse face if it is at the
-        end of a line (on a newline).  The cursor appears there, but
-        mouse highlighting does not.  */
-      && cursor_row->used[TEXT_AREA] > hpos)
-    mouse_face_here_p = 1;
-
-  /* Maybe clear the display under the cursor.  */
-  if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
-    {
-      int x;
-      int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-
-      cursor_glyph = get_phys_cursor_glyph (w);
-      if (cursor_glyph == NULL)
-       goto mark_cursor_off;
-
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-
-      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   x,
-                   WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                    cursor_row->y)),
-                   cursor_glyph->pixel_width,
-                   cursor_row->visible_height,
-                   False);
-    }
-
-  /* Erase the cursor by redrawing the character underneath it.  */
-  if (mouse_face_here_p)
-    hl = DRAW_MOUSE_FACE;
-  else
-    hl = DRAW_NORMAL_TEXT;
-  x_draw_phys_cursor_glyph (w, cursor_row, hl);
-
- mark_cursor_off:
-  w->phys_cursor_on_p = 0;
-  w->phys_cursor_type = NO_CURSOR;
-}
-
-
-/* Non-zero if physical cursor of window W is within mouse face.  */
-
-static int
-cursor_in_mouse_face_p (w)
-     struct window *w;
-{
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
-  int in_mouse_face = 0;
-
-  if (WINDOWP (dpyinfo->mouse_face_window)
-      && XWINDOW (dpyinfo->mouse_face_window) == w)
-    {
-      int hpos = w->phys_cursor.hpos;
-      int vpos = w->phys_cursor.vpos;
-
-      if (vpos >= dpyinfo->mouse_face_beg_row
-         && vpos <= dpyinfo->mouse_face_end_row
-         && (vpos > dpyinfo->mouse_face_beg_row
-             || hpos >= dpyinfo->mouse_face_beg_col)
-         && (vpos < dpyinfo->mouse_face_end_row
-             || hpos < dpyinfo->mouse_face_end_col
-             || dpyinfo->mouse_face_past_end))
-       in_mouse_face = 1;
-    }
-
-  return in_mouse_face;
-}
-
-
-/* Display or clear cursor of window W.  If ON is zero, clear the
-   cursor.  If it is non-zero, display the cursor.  If ON is nonzero,
-   where to put the cursor is specified by HPOS, VPOS, X and Y.  */
-
-void
-x_display_and_set_cursor (w, on, hpos, vpos, x, y)
+x_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
      struct window *w;
-     int on, hpos, vpos, x, y;
+     struct glyph_row *glyph_row;
+     int x, y;
+     int cursor_type, cursor_width;
+     int on_p, active_p;
 {
-  struct frame *f = XFRAME (w->frame);
-  int new_cursor_type;
-  int new_cursor_width;
-  int active_cursor;
-  struct glyph_matrix *current_glyphs;
-  struct glyph_row *glyph_row;
-  struct glyph *glyph;
-
-  /* This is pointless on invisible frames, and dangerous on garbaged
-     windows and frames; in the latter case, the frame or window may
-     be in the midst of changing its size, and x and y may be off the
-     window.  */
-  if (! FRAME_VISIBLE_P (f)
-      || FRAME_GARBAGED_P (f)
-      || vpos >= w->current_matrix->nrows
-      || hpos >= w->current_matrix->matrix_w)
-    return;
-
-  /* If cursor is off and we want it off, return quickly.  */
-  if (!on && !w->phys_cursor_on_p)
-    return;
-
-  current_glyphs = w->current_matrix;
-  glyph_row = MATRIX_ROW (current_glyphs, vpos);
-  glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
 
-  /* If cursor row is not enabled, we don't really know where to
-     display the cursor.  */
-  if (!glyph_row->enabled_p)
+  if (on_p)
     {
-      w->phys_cursor_on_p = 0;
-      return;
-    }
-
-  xassert (interrupt_input_blocked);
-
-  /* Set new_cursor_type to the cursor we want to be displayed.  */
-  new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
-
-  /* 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 (w->phys_cursor_on_p
-      && (!on
-         || w->phys_cursor.x != x
-         || w->phys_cursor.y != y
-         || new_cursor_type != w->phys_cursor_type
-         || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
-             && new_cursor_width != w->phys_cursor_width)))
-    x_erase_phys_cursor (w);
-
-  /* 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;
-
-      /* Set phys_cursor_.* before x_draw_.* is called because some
-        of them may need the information.  */
-      w->phys_cursor.x = x;
-      w->phys_cursor.y = glyph_row->y;
-      w->phys_cursor.hpos = hpos;
-      w->phys_cursor.vpos = vpos;
-      w->phys_cursor_type = new_cursor_type;
+      w->phys_cursor_type = cursor_type;
       w->phys_cursor_on_p = 1;
 
-      switch (new_cursor_type)
+      switch (cursor_type)
        {
        case HOLLOW_BOX_CURSOR:
          x_draw_hollow_cursor (w, glyph_row);
          break;
 
        case FILLED_BOX_CURSOR:
-         x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+         draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
          break;
 
        case BAR_CURSOR:
-         x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
+         x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
          break;
 
        case HBAR_CURSOR:
-         x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
+         x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
          break;
 
        case NO_CURSOR:
@@ -12263,79 +7462,6 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
 #endif
 }
 
-
-/* Display the cursor on window W, or clear it.  X and Y are window
-   relative pixel coordinates.  HPOS and VPOS are glyph matrix
-   positions.  If W is not the selected window, display a hollow
-   cursor.  ON non-zero means display the cursor at X, Y which
-   correspond to HPOS, VPOS, otherwise it is cleared.  */
-
-void
-x_display_cursor (w, on, hpos, vpos, x, y)
-     struct window *w;
-     int on, hpos, vpos, x, y;
-{
-  BLOCK_INPUT;
-  x_display_and_set_cursor (w, on, hpos, vpos, x, y);
-  UNBLOCK_INPUT;
-}
-
-
-/* Display the cursor on window W, or clear it, according to ON_P.
-   Don't change the cursor's position.  */
-
-void
-x_update_cursor (f, on_p)
-     struct frame *f;
-     int on_p;
-{
-  x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
-}
-
-
-/* Call x_update_window_cursor with parameter ON_P on all leaf windows
-   in the window tree rooted at W.  */
-
-static void
-x_update_cursor_in_window_tree (w, on_p)
-     struct window *w;
-     int on_p;
-{
-  while (w)
-    {
-      if (!NILP (w->hchild))
-       x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
-      else if (!NILP (w->vchild))
-       x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
-      else
-       x_update_window_cursor (w, on_p);
-
-      w = NILP (w->next) ? 0 : XWINDOW (w->next);
-    }
-}
-
-
-/* Switch the display of W's cursor on or off, according to the value
-   of ON.  */
-
-static void
-x_update_window_cursor (w, on)
-     struct window *w;
-     int on;
-{
-  /* Don't update cursor in windows whose frame is in the process
-     of being deleted.  */
-  if (w->current_matrix)
-    {
-      BLOCK_INPUT;
-      x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
-                               w->phys_cursor.x, w->phys_cursor.y);
-      UNBLOCK_INPUT;
-    }
-}
-
-
-
 \f
 /* Icons.  */
 
@@ -12400,15 +7526,10 @@ x_text_icon (f, icon_name)
     text.encoding = XA_STRING;
     text.format = 8;
     text.nitems = strlen (icon_name);
-#ifdef USE_X_TOOLKIT
-    XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
-                   &text);
-#else /* not USE_X_TOOLKIT */
-    XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
-#endif /* not USE_X_TOOLKIT */
+    XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
   }
 #else /* not HAVE_X11R4 */
-  XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
+  XSetIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), icon_name);
 #endif /* not HAVE_X11R4 */
 
   if (f->output_data.x->icon_bitmap > 0)
@@ -12765,7 +7886,7 @@ x_new_font (f, fontname)
   f->output_data.x->baseline_offset = fontp->baseline_offset;
   f->output_data.x->fontset = -1;
 
-  x_compute_fringe_widths (f, 1);
+  compute_fringe_widths (f, 1);
 
   /* Compute the scroll bar width in character columns.  */
   if (f->scroll_bar_pixel_width > 0)
@@ -12844,90 +7965,6 @@ x_new_fontset (f, fontsetname)
   return build_string (fontsetname);
 }
 
-/* Compute actual fringe widths */
-
-void
-x_compute_fringe_widths (f, redraw)
-     struct frame *f;
-     int redraw;
-{
-  int o_left = f->output_data.x->left_fringe_width;
-  int o_right = f->output_data.x->right_fringe_width;
-  int o_cols = f->output_data.x->fringe_cols;
-
-  Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
-  Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
-  int left_fringe_width, right_fringe_width;
-
-  if (!NILP (left_fringe))
-    left_fringe = Fcdr (left_fringe);
-  if (!NILP (right_fringe))
-    right_fringe = Fcdr (right_fringe);
-
-  left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
-                      XINT (left_fringe));
-  right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
-                       XINT (right_fringe));
-
-  if (left_fringe_width || right_fringe_width)
-    {
-      int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
-      int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
-      int conf_wid = left_wid + right_wid;
-      int font_wid = FONT_WIDTH (f->output_data.x->font);
-      int cols = (left_wid + right_wid + font_wid-1) / font_wid;
-      int real_wid = cols * font_wid;
-      if (left_wid && right_wid)
-       {
-         if (left_fringe_width < 0)
-           {
-             /* Left fringe width is fixed, adjust right fringe if necessary */
-             f->output_data.x->left_fringe_width = left_wid;
-             f->output_data.x->right_fringe_width = real_wid - left_wid;
-           }
-         else if (right_fringe_width < 0)
-           {
-             /* Right fringe width is fixed, adjust left fringe if necessary */
-             f->output_data.x->left_fringe_width = real_wid - right_wid;
-             f->output_data.x->right_fringe_width = right_wid;
-           }
-         else
-           {
-             /* Adjust both fringes with an equal amount.
-                Note that we are doing integer arithmetic here, so don't
-                lose a pixel if the total width is an odd number.  */
-             int fill = real_wid - conf_wid;
-             f->output_data.x->left_fringe_width = left_wid + fill/2;
-             f->output_data.x->right_fringe_width = right_wid + fill - fill/2;
-           }
-       }
-      else if (left_fringe_width)
-       {
-         f->output_data.x->left_fringe_width = real_wid;
-         f->output_data.x->right_fringe_width = 0;
-       }
-      else
-       {
-         f->output_data.x->left_fringe_width = 0;
-         f->output_data.x->right_fringe_width = real_wid;
-       }
-      f->output_data.x->fringe_cols = cols;
-      f->output_data.x->fringes_extra = real_wid;
-    }
-  else
-    {
-      f->output_data.x->left_fringe_width = 0;
-      f->output_data.x->right_fringe_width = 0;
-      f->output_data.x->fringe_cols = 0;
-      f->output_data.x->fringes_extra = 0;
-    }
-
-  if (redraw && FRAME_VISIBLE_P (f))
-    if (o_left != f->output_data.x->left_fringe_width ||
-       o_right != f->output_data.x->right_fringe_width ||
-       o_cols != f->output_data.x->fringe_cols)
-      redraw_frame (f);
-}
 \f
 /***********************************************************************
                           X Input Methods
@@ -13025,7 +8062,7 @@ struct xim_inst_t
 };
 
 /* XIM instantiate callback function, which is called whenever an XIM
-   server is available.  DISPLAY is teh display of the XIM.
+   server is available.  DISPLAY is the display of the XIM.
    CLIENT_DATA contains a pointer to an xim_inst_t structure created
    when the callback was registered.  */
 
@@ -13319,7 +8356,6 @@ x_check_fullscreen (f)
 
           /* Wait for the change of frame size to occur */
           f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
-
         }
     }
 }
@@ -13354,53 +8390,6 @@ x_check_fullscreen_move (f)
 }
 
 
-/* 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
    top-left-corner window gravity for this size change and subsequent
@@ -13422,7 +8411,7 @@ x_set_window_size_1 (f, change_gravity, cols, rows)
        ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
 
-  x_compute_fringe_widths (f, 0);
+  compute_fringe_widths (f, 0);
 
   pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
   pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
@@ -13592,11 +8581,7 @@ x_raise_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-#ifdef USE_X_TOOLKIT
-      XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
-#else /* not USE_X_TOOLKIT */
-      XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-#endif /* not USE_X_TOOLKIT */
+      XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
       XFlush (FRAME_X_DISPLAY (f));
       UNBLOCK_INPUT;
     }
@@ -13611,11 +8596,7 @@ x_lower_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-#ifdef USE_X_TOOLKIT
-      XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
-#else /* not USE_X_TOOLKIT */
-      XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-#endif /* not USE_X_TOOLKIT */
+      XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
       XFlush (FRAME_X_DISPLAY (f));
       UNBLOCK_INPUT;
     }
@@ -13677,6 +8658,7 @@ x_make_frame_visible (f)
 #else /* not USE_X_TOOLKIT */
 #ifdef USE_GTK
       gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
+      gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
 #else
       XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 #endif /* not USE_GTK */
@@ -13805,12 +8787,8 @@ x_make_frame_invisible (f)
 {
   Window window;
 
-#ifdef USE_X_TOOLKIT
   /* Use the frame's outermost window, not the one we normally draw on.  */
-  window = XtWindow (f->output_data.x->widget);
-#else /* not USE_X_TOOLKIT */
-  window = FRAME_X_WINDOW (f);
-#endif /* not USE_X_TOOLKIT */
+  window = FRAME_OUTER_WINDOW (f);
 
   /* Don't keep the highlight on an invisible frame.  */
   if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
@@ -13832,12 +8810,10 @@ x_make_frame_invisible (f)
 
 #ifdef USE_GTK
   if (FRAME_GTK_OUTER_WIDGET (f))
-    {
-      gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
-      goto out;
-    }
+    gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
+  else
 #endif
-
+  {
 #ifdef HAVE_X11R4
 
   if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
@@ -13871,8 +8847,8 @@ x_make_frame_invisible (f)
   /* Unmap the window ourselves.  Cheeky!  */
   XUnmapWindow (FRAME_X_DISPLAY (f), window);
 #endif /* ! defined (HAVE_X11R4) */
+  }
 
- out:
   /* We can't distinguish this from iconification
      just by the event that we get from the server.
      So we can't win using the usual strategy of letting
@@ -14073,7 +9049,7 @@ x_free_frame_resources (f)
           FRAME_GTK_OUTER_WIDGET (f) = 0;
         }
 #endif /* USE_GTK */
-          
+
       if (FRAME_X_WINDOW (f))
        XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 #endif /* !USE_X_TOOLKIT */
@@ -14176,7 +9152,7 @@ x_wm_set_size_hint (f, flags, user_position)
   int ac = 0;
   Dimension widget_width, widget_height;
 #endif
-  
+
   Window window = FRAME_OUTER_WINDOW (f);
 
   /* Setting PMaxSize caused various problems.  */
@@ -14381,11 +9357,7 @@ x_wm_set_icon_position (f, icon_x, icon_y)
      struct frame *f;
      int icon_x, icon_y;
 {
-#ifdef USE_X_TOOLKIT
-  Window window = XtWindow (f->output_data.x->widget);
-#else
-  Window window = FRAME_X_WINDOW (f);
-#endif
+  Window window = FRAME_OUTER_WINDOW (f);
 
   f->output_data.x->wm_hints.flags |= IconPositionHint;
   f->output_data.x->wm_hints.icon_x = icon_x;
@@ -14524,8 +9496,28 @@ 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, SDATA (pattern), max (maxnames, 10),
-                             &num_fonts);
+          if (maxnames < 0)
+            {
+              int limit;
+
+              for (limit = 500;;)
+                {
+                  names = XListFonts (dpy, SDATA (pattern), limit, &num_fonts);
+                  if (num_fonts == limit)
+                    {
+                      BLOCK_INPUT;
+                      XFreeFontNames (names);
+                      UNBLOCK_INPUT;
+                      limit *= 2;
+                    }
+                  else
+                    break;
+                }
+            }
+          else
+            names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10),
+                                &num_fonts);
+
          if (x_had_errors_p (dpy))
            {
              /* This error is perhaps due to insufficient memory on X
@@ -15166,7 +10158,11 @@ x_term_init (display_name, xrm_option, resource_name)
 
     argv[argc++] = "--name";
     argv[argc++] = resource_name;
-    
+
+#ifdef HAVE_X11R5
+    XSetLocaleModifiers ("");
+#endif
+
     gtk_init (&argc, &argv2);
 
     /* gtk_init does set_locale.  We must fix locale after calling it.  */
@@ -15174,7 +10170,7 @@ x_term_init (display_name, xrm_option, resource_name)
     xg_initialize ();
 
     dpy = GDK_DISPLAY ();
-    
+
     /* NULL window -> events for all windows go to our function */
     gdk_window_add_filter (NULL, event_handler_gdk, NULL);
 
@@ -15184,16 +10180,16 @@ x_term_init (display_name, xrm_option, resource_name)
       char *file = "~/.emacs.d/gtkrc";
       Lisp_Object s, abs_file;
 
-      GCPRO2 (str, abs_file);
+      GCPRO2 (s, abs_file);
       s = make_string (file, strlen (file));
       abs_file = Fexpand_file_name(s, Qnil);
 
       if (! NILP (abs_file) && Ffile_readable_p (abs_file))
         gtk_rc_parse (SDATA (abs_file));
-      
+
       UNGCPRO;
     }
-    
+
     XSetErrorHandler (x_error_handler);
     XSetIOErrorHandler (x_io_error_quitter);
   }
@@ -15610,11 +10606,36 @@ x_delete_display (dpyinfo)
   xfree (dpyinfo);
 }
 
+#ifdef USE_X_TOOLKIT
+
+/* Atimer callback function for TIMER.  Called every 0.1s to process
+   Xt timeouts, if needed.  We must avoid calling XtAppPending as
+   much as possible because that function does an implicit XFlush
+   that slows us down.  */
+
+static void
+x_process_timeouts (timer)
+     struct atimer *timer;
+{
+  if (toolkit_scroll_bar_interaction || popup_activated ())
+    {
+      BLOCK_INPUT;
+      while (XtAppPending (Xt_app_con) & XtIMTimer)
+       XtAppProcessEvent (Xt_app_con, XtIMTimer);
+      UNBLOCK_INPUT;
+    }
+}
+
+#endif /* USE_X_TOOLKIT */
+
 \f
 /* Set up use of X before we make the first connection.  */
 
+extern frame_parm_handler x_frame_parm_handlers[];
+
 static struct redisplay_interface x_redisplay_interface =
 {
+  x_frame_parm_handlers,
   x_produce_glyphs,
   x_write_glyphs,
   x_insert_glyphs,
@@ -15623,11 +10644,26 @@ static struct redisplay_interface x_redisplay_interface =
   x_after_update_window_line,
   x_update_window_begin,
   x_update_window_end,
-  XTcursor_to,
+  x_cursor_to,
+  x_flush,
+#ifndef XFlush
   x_flush,
-  x_clear_mouse_face,
+#else
+  0,  /* flush_display_optional */
+#endif
+  x_clear_window_mouse_face,
   x_get_glyph_overhangs,
-  x_fix_overlapping_area
+  x_fix_overlapping_area,
+  x_draw_fringe_bitmap,
+  x_per_char_metric,
+  x_encode_char,
+  x_compute_glyph_string_overhangs,
+  x_draw_glyph_string,
+  x_define_frame_cursor,
+  x_clear_frame_area,
+  x_draw_window_cursor,
+  x_draw_vertical_window_border,
+  x_shift_glyphs_for_insert
 };
 
 void
@@ -15653,7 +10689,6 @@ x_initialize ()
   condemn_scroll_bars_hook = XTcondemn_scroll_bars;
   redeem_scroll_bar_hook = XTredeem_scroll_bar;
   judge_scroll_bars_hook = XTjudge_scroll_bars;
-  estimate_mode_line_height_hook = x_estimate_mode_line_height;
 
   scroll_region_ok = 1;                /* we'll scroll partial frames */
   char_ins_del_ok = 1;
@@ -15745,26 +10780,6 @@ syms_of_xterm ()
   staticpro (&last_mouse_press_frame);
   last_mouse_press_frame = Qnil;
 
-  help_echo = Qnil;
-  staticpro (&help_echo);
-  help_echo_object = Qnil;
-  staticpro (&help_echo_object);
-  help_echo_window = Qnil;
-  staticpro (&help_echo_window);
-  previous_help_echo = Qnil;
-  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
-wide as that tab on the display.  */);
-  x_stretch_cursor_p = 0;
-
   DEFVAR_BOOL ("x-use-underline-position-properties",
               &x_use_underline_position_properties,
      doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.