(read_char_minibuf_menu_prompt): Add new parameter
[bpt/emacs.git] / src / xterm.c
index d73e57b..aec7d3b 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
+   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -22,17 +22,13 @@ Boston, MA 02111-1307, USA.  */
 /* New display code by Gerd Moellmann <gerd@gnu.org>.  */
 /* Xt features made by Fred Pierresteguy.  */
 
+#include <config.h>
+
 /* On 4.3 these lose if they come after xterm.h.  */
-/* On HP-UX 8.0 signal.h loses if it comes after config.h.  */
 /* Putting these at the beginning seems to be standard for other .c files.  */
 #include <signal.h>
 
-#include <config.h>
-
 #include <stdio.h>
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#endif
 
 #ifdef HAVE_X_WINDOWS
 
@@ -48,13 +44,11 @@ Boston, MA 02111-1307, USA.  */
 #include "xterm.h"
 #include <X11/cursorfont.h>
 
-#ifndef USG
 /* Load sys/types.h if not already loaded.
    In some systems loading it twice is suicidal.  */
 #ifndef makedev
 #include <sys/types.h>
 #endif /* makedev */
-#endif /* USG */
 
 #ifdef BSD_SYSTEM
 #include <sys/ioctl.h>
@@ -76,8 +70,8 @@ Boston, MA 02111-1307, USA.  */
 #include "charset.h"
 #include "ccl.h"
 #include "frame.h"
-#include "fontset.h"
 #include "dispextern.h"
+#include "fontset.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "termchar.h"
@@ -92,12 +86,12 @@ Boston, MA 02111-1307, USA.  */
 #include "keyboard.h"
 #include "intervals.h"
 #include "process.h"
+#include "atimer.h"
 
 #ifdef USE_X_TOOLKIT
 #include <X11/Shell.h>
 #endif
 
-#include <sys/types.h>
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
@@ -107,8 +101,9 @@ Boston, MA 02111-1307, USA.  */
 
 #ifdef USE_X_TOOLKIT
 
-extern void free_frame_menubar ();
-extern FRAME_PTR x_menubar_window_to_frame ();
+extern void free_frame_menubar P_ ((struct frame *));
+extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
+                                                   int));
 
 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
 #define HACK_EDITRES
@@ -122,13 +117,21 @@ extern void _XEditResCheckMessages ();
 #include <Xm/Xm.h>             /* for LESSTIF_VERSION */
 #include <Xm/ScrollBar.h>
 #include <Xm/ScrollBarP.h>
-#elif defined HAVE_XAW3D
+#else /* !USE_MOTIF i.e. use Xaw */
+
+#ifdef HAVE_XAW3D
 #include <X11/Xaw3d/Simple.h>
-#include <X11/Xaw3d/ThreeD.h>
 #include <X11/Xaw3d/Scrollbar.h>
 #define ARROW_SCROLLBAR
 #include <X11/Xaw3d/ScrollbarP.h>
-#endif /* HAVE_XAW3D */
+#else /* !HAVE_XAW3D */
+#include <X11/Xaw/Simple.h>
+#include <X11/Xaw/Scrollbar.h>
+#endif /* !HAVE_XAW3D */
+#ifndef XtNpickTop
+#define XtNpickTop "pickTop"
+#endif /* !XtNpickTop */
+#endif /* !USE_MOTIF */
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
 #endif /* USE_X_TOOLKIT */
@@ -145,11 +148,6 @@ extern void _XEditResCheckMessages ();
 #endif
 #endif
 
-#ifdef HAVE_SETLOCALE
-/* So we can do setlocale.  */
-#include <locale.h>
-#endif
-
 #ifdef SOLARIS2
 /* memmove will be defined as a macro in Xfuncs.h unless
    <string.h> is included beforehand.  The declaration for memmove in
@@ -197,43 +195,42 @@ static unsigned char zv_bits[] = {
 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[] = {
-   0x30, 0x30, 0x30, 0x30, 0xb4, 0xfc, 0x78, 0x30};
+   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[] = {
-   0x0c, 0x1e, 0x3f, 0x2d, 0x0c, 0x0c, 0x0c, 0x0c};
+   0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
 
-/* 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};
-
-/* Overlay arrow bitmap; a filled `<>'.  */
+/* Overlay arrow bitmap.  */
 
-#if 1
+#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};
-
-#elif 0
-#define ov_width 8
-#define ov_height 8
-static unsigned char ov_bits[] = {
-   0x18, 0x04, 0x08, 0x1c, 0x3e, 0x3a, 0x32, 0x1c};
 #else
+/* A triangular arrow.  */
 #define ov_width 8
 #define ov_height 8
 static unsigned char ov_bits[] = {
-   0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18};
+   0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
+
 #endif
 
 extern Lisp_Object Qhelp_echo;
@@ -247,6 +244,9 @@ int x_toolkit_scroll_bars_p;
    (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.  */
 
@@ -300,6 +300,9 @@ static String Xt_default_resources[] = {0};
 
 struct cursor_pos output_cursor;
 
+/* Non-zero means user is interacting with a toolkit scroll bar.  */
+
+static int toolkit_scroll_bar_interaction;
 
 /* Mouse movement.
 
@@ -382,8 +385,8 @@ extern int extra_keyboard_modifiers;
 
 static Lisp_Object Qvendor_specific_keysyms;
 
-extern XrmDatabase x_load_resources ();
-extern Lisp_Object x_icon_type ();
+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
@@ -399,7 +402,7 @@ enum draw_glyphs_face
   DRAW_IMAGE_SUNKEN
 };
 
-static void x_update_window_end P_ ((struct window *, 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 *,
@@ -410,10 +413,9 @@ 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 *));
 static void note_mode_line_highlight P_ ((struct window *, int, int));
-static void x_check_font P_ ((struct frame *, XFontStruct *));
 static void note_mouse_highlight P_ ((struct frame *, int, int));
-static void note_toolbar_highlight P_ ((struct frame *f, int, int));
-static void x_handle_toolbar_click P_ ((struct frame *, XButtonEvent *));
+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 *));
@@ -450,7 +452,7 @@ static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
-static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *));
+static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
                                       XRectangle *));
 static void expose_frame P_ ((struct frame *, int, int, int, int));
@@ -473,7 +475,13 @@ static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
 static void note_overwritten_text_cursor P_ ((struct window *, 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 *));
+
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
@@ -600,6 +608,13 @@ x_update_window_begin (w)
       if (FRAME_GARBAGED_P (f))
        display_info->mouse_face_window = Qnil;
 
+#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
+        their mouse_face_p flag set, which means that they are always
+        unequal to rows in a desired matrix which never have that
+        flag set.  So, rows containing mouse-face glyphs are never
+        scrolled, and we don't have to switch the mouse highlight off
+        here to prevent it from being scrolled.  */
+      
       /* Can we tell that this update does not affect the window
         where the mouse highlight is?  If so, no need to turn off.
         Likewise, don't do anything if the frame is garbaged;
@@ -617,6 +632,7 @@ x_update_window_begin (w)
          if (i < w->desired_matrix->nrows)
            clear_mouse_face (display_info);
        }
+#endif /* 0 */
     }
 
   UNBLOCK_INPUT;
@@ -642,7 +658,7 @@ x_draw_vertical_border (w)
       int x0, x1, y0, y1;
 
       window_box_edges (w, -1, &x0, &y0, &x1, &y1);
-      x1 += FRAME_X_FLAGS_AREA_WIDTH (f);
+      x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
       y1 -= 1;
       
       XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 
@@ -651,24 +667,45 @@ x_draw_vertical_border (w)
 }
    
    
-/* End update of window W (which is equal to updated_window).  Draw
-   vertical borders between horizontally adjacent windows, and display
-   W's cursor if CURSOR_ON_P is non-zero.  W may be a menu bar
-   pseudo-window in case we don't have X toolkit support.  Such
-   windows don't have a cursor, so don't display it here.  */
+/* End update of window W (which is equal to updated_window).
+
+   Draw vertical borders between horizontally adjacent windows, and
+   display W's cursor if CURSOR_ON_P is non-zero.
+
+   MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
+   glyphs in mouse-face were overwritten.  In that case we have to
+   make sure that the mouse-highlight is properly redrawn.
+
+   W may be a menu bar pseudo-window in case we don't have X toolkit
+   support.  Such windows don't have a cursor, so don't display it
+   here.  */
 
 static void
-x_update_window_end (w, cursor_on_p)
+x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
      struct window *w;
-     int cursor_on_p;
+     int cursor_on_p, mouse_face_overwritten_p;
 {
   if (!w->pseudo_window_p)
     {
+      struct x_display_info *dpyinfo
+       = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+      
       BLOCK_INPUT;
+
+      /* If a row with mouse-face was overwritten, arrange for
+        XTframe_up_to_date to redisplay the mouse highlight.  */
+      if (mouse_face_overwritten_p)
+       {
+         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;
+       }
+      
       if (cursor_on_p)
        x_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;
     }
@@ -704,6 +741,7 @@ XTframe_up_to_date (f)
   if (FRAME_X_P (f))
     {
       struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
       if (dpyinfo->mouse_face_deferred_gc
          || f == dpyinfo->mouse_face_mouse_frame)
        {
@@ -746,7 +784,8 @@ x_after_update_window_line (desired_row)
          struct frame *f = XFRAME (w->frame);
          int width = FRAME_INTERNAL_BORDER_WIDTH (f);
          int height = desired_row->visible_height;
-         int x = window_box_right (w, -1) + FRAME_X_FLAGS_AREA_WIDTH (f);
+         int x = (window_box_right (w, -1)
+                  + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
          int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
 
          XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
@@ -790,7 +829,7 @@ x_draw_bitmap (w, row, which)
       bits = left_bits;
       x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
           - wd
-          - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2);
+          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
       
     case OVERLAY_ARROW_BITMAP:
@@ -799,7 +838,7 @@ x_draw_bitmap (w, row, which)
       bits = ov_bits;
       x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
           - wd
-          - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2);
+          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
       
     case RIGHT_TRUNCATION_BITMAP:
@@ -807,7 +846,7 @@ x_draw_bitmap (w, row, which)
       h = right_height;
       bits = right_bits;
       x = window_box_right (w, -1);
-      x += (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2;
+      x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
       break;
 
     case CONTINUED_LINE_BITMAP:
@@ -815,7 +854,7 @@ x_draw_bitmap (w, row, which)
       h = right_height;
       bits = continued_bits;
       x = window_box_right (w, -1);
-      x += (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2;
+      x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
       break;
       
     case CONTINUATION_LINE_BITMAP:
@@ -824,7 +863,7 @@ x_draw_bitmap (w, row, which)
       bits = continuation_bits;
       x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
           - wd
-          - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2);
+          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
 
     case ZV_LINE_BITMAP:
@@ -833,7 +872,7 @@ x_draw_bitmap (w, row, which)
       bits = zv_bits;
       x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
           - wd
-          - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2);
+          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
 
     default:
@@ -868,7 +907,7 @@ x_draw_row_bitmaps (w, row)
   struct frame *f = XFRAME (w->frame);
   enum bitmap_type bitmap;
   struct face *face;
-  int top_line_height = -1;
+  int header_line_height = -1;
 
   xassert (interrupt_input_blocked);
 
@@ -895,7 +934,7 @@ x_draw_row_bitmaps (w, row)
   /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
      the flags area.  */
   if (bitmap == NO_BITMAP
-      || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_FLAGS_AREA_WIDTH (f)
+      || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
       || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
     {
       /* If W has a vertical border to its left, don't draw over it.  */
@@ -904,8 +943,8 @@ x_draw_row_bitmaps (w, row)
                    ? 1 : 0);
       int left = window_box_left (w, -1);
 
-      if (top_line_height < 0)
-       top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+      if (header_line_height < 0)
+       header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
       
       /* In case the same realized face is used for bitmap areas and
         for something displayed in the text (e.g. face `region' on
@@ -919,11 +958,11 @@ x_draw_row_bitmaps (w, row)
       XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                      face->gc,
                      (left
-                      - FRAME_X_FLAGS_AREA_WIDTH (f)
+                      - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
                       + border),
-                     WINDOW_TO_FRAME_PIXEL_Y (w, max (top_line_height,
+                     WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
                                                       row->y)),
-                     FRAME_X_FLAGS_AREA_WIDTH (f) - border,
+                     FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
                      row->visible_height);
       if (!face->stipple)
        XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
@@ -944,13 +983,13 @@ x_draw_row_bitmaps (w, row)
   /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
      the flags area.  */
   if (bitmap == NO_BITMAP
-      || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_FLAGS_AREA_WIDTH (f)
+      || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
       || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
     {
       int right = window_box_right (w, -1);
 
-      if (top_line_height < 0)
-       top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+      if (header_line_height < 0)
+       header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
 
       /* In case the same realized face is used for bitmap areas and
         for something displayed in the text (e.g. face `region' on
@@ -963,9 +1002,9 @@ x_draw_row_bitmaps (w, row)
       XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                      face->gc,
                      right,
-                     WINDOW_TO_FRAME_PIXEL_Y (w, max (top_line_height,
+                     WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
                                                       row->y)),
-                     FRAME_X_FLAGS_AREA_WIDTH (f),
+                     FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
                      row->visible_height);
       if (!face->stipple)
        XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
@@ -1076,7 +1115,7 @@ XTcursor_to (vpos, hpos, y, x)
     {
       BLOCK_INPUT;
       x_display_cursor (w, 1, hpos, vpos, x, y);
-      XFlush (FRAME_X_DISPLAY (selected_frame));
+      XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
       UNBLOCK_INPUT;
     }
 }
@@ -1091,18 +1130,19 @@ XTcursor_to (vpos, hpos, y, x)
 
 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
                                                       struct glyph *,
-                                                      XChar2b *));
+                                                      XChar2b *,
+                                                      int *));
 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
                                                      int, XChar2b *, 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_special_glyphs P_ ((struct it *, enum display_element_type));
 static void x_produce_image_glyph P_ ((struct it *it));
-     
+
 
 /* Return a pointer to per-char metric information in FONT of a
    character pointed by B which is a pointer to an XChar2b.  */
@@ -1117,9 +1157,8 @@ static void x_produce_image_glyph P_ ((struct it *it));
    : &((font)->max_bounds))
 
 
-/* Get metrics of character CHAR2B in FONT.  Value is always non-null.
-   If CHAR2B is not contained in FONT, the font's default character
-   metric is returned.  */
+/* 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)
@@ -1183,28 +1222,9 @@ x_per_char_metric (font, char2b)
        pcm = &font->max_bounds;
     }
 
-
-  if (pcm == NULL || pcm->width == 0)
-    {
-      /* Character not contained in the font.  FONT->default_char
-        gives the character that will be printed.  FONT->default_char
-        is a 16-bit character code with byte1 in the most significant
-        byte and byte2 in the least significant byte.  */
-      XChar2b default_char;
-      default_char.byte1 = (font->default_char >> BITS_PER_CHAR) & 0xff;
-      default_char.byte2 = font->default_char & 0xff;
-
-      /* Avoid an endless recursion if FONT->default_char itself
-        hasn't per char metrics.  handa@etl.go.jp reports that some
-        fonts have this problem.  */
-      if (default_char.byte1 != char2b->byte1
-         || default_char.byte2 != char2b->byte2)
-       pcm = x_per_char_metric (font, &default_char);
-      else
-       pcm = &font->max_bounds;
-    }
-  
-  return pcm;
+  return ((pcm == NULL
+          || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
+         ? NULL : pcm);
 }
 
 
@@ -1245,7 +1265,7 @@ x_encode_char (c, char2b, font_info)
       /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
       if (font->max_byte1 == 0)        /* 1-byte font */
-       char2b->byte2 = ccl->reg[1];
+       char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
       else
        char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
     }
@@ -1285,12 +1305,8 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
         sure to use a face suitable for unibyte.  */
       char2b->byte1 = 0;
       char2b->byte2 = c;
-      
-      if (!FACE_SUITABLE_FOR_CHARSET_P (face, -1))
-       {
-         face_id = FACE_FOR_CHARSET (f, face_id, -1);
-         face = FACE_FROM_ID (f, face_id);
-       }
+      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)
     {
@@ -1310,32 +1326,13 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
       else
        char2b->byte1 = 0, char2b->byte2 = c1;
 
-      /* Get the face for displaying C.  If `face' is not suitable for
-        charset, get the one that fits.  (This can happen for the
-        translations of composite characters where the glyph
-        specifies a face for ASCII, but translations have a different
-        charset.)  */
-      if (!FACE_SUITABLE_FOR_CHARSET_P (face, charset))
-       {
-         face_id = FACE_FOR_CHARSET (f, face_id, charset);
-         face = FACE_FROM_ID (f, face_id);
-       }
-  
       /* Maybe encode the character in *CHAR2B.  */
-      if (charset != CHARSET_ASCII)
+      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);
-             if (charset == charset_latin_iso8859_1)
-               {
-                 xassert (((XFontStruct *) font_info->font)->max_char_or_byte2
-                          >= 0x80);
-                 char2b->byte2 |= 0x80;
-               }
-           }
+           x_encode_char (c, char2b, font_info);
        }
     }
 
@@ -1348,33 +1345,37 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
 
 
 /* Get face and two-byte form of character glyph GLYPH on frame F.
-   The encoding of GLYPH->u.ch.code is returned in *CHAR2B.  Value is
+   The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
    a pointer to a realized face that is ready for display.  */
 
 static INLINE struct face *
-x_get_glyph_face_and_encoding (f, glyph, char2b)
+x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
      struct frame *f;
      struct glyph *glyph;
      XChar2b *char2b;
+     int *two_byte_p;
 {
   struct face *face;
 
   xassert (glyph->type == CHAR_GLYPH);
-  face = FACE_FROM_ID (f, glyph->u.ch.face_id);
+  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.code;
+      char2b->byte2 = glyph->u.ch;
     }
-  else if (glyph->u.ch.code < 128
-          && glyph->u.ch.face_id < BASIC_FACE_ID_SENTINEL)
+  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.code;
+      char2b->byte2 = glyph->u.ch;
     }
   else
     {
@@ -1382,7 +1383,7 @@ x_get_glyph_face_and_encoding (f, glyph, char2b)
       
       /* 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.code, charset, c1, c2);
+      SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
       if (c2 > 0)
        char2b->byte1 = c1, char2b->byte2 = c2;
       else
@@ -1395,9 +1396,10 @@ x_get_glyph_face_and_encoding (f, glyph, char2b)
            = FONT_INFO_FROM_ID (f, face->font_info_id);
          if (font_info)
            {
-             x_encode_char (glyph->u.ch.code, char2b, font_info);
-             if (charset == charset_latin_iso8859_1)
-               char2b->byte2 |= 0x80;
+             x_encode_char (glyph->u.ch, char2b, font_info);
+             if (two_byte_p)
+               *two_byte_p
+                 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
            }
        }
     }
@@ -1425,23 +1427,53 @@ x_append_glyph (it)
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
-      /* Play it safe.  If sub-structures of the glyph are not all the
-        same size, it otherwise be that some bits stay set.  This
-        would prevent a comparison with GLYPH_EQUAL_P.  */
-      glyph->u.val = 0;
-      
-      glyph->type = CHAR_GLYPH;
-      glyph->pixel_width = it->pixel_width;
-      glyph->u.ch.code = it->char_to_display;
-      glyph->u.ch.face_id = it->face_id;
       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];
+    }
+}
+
+/* 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);
+  
+  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];
     }
 }
@@ -1489,7 +1521,7 @@ x_produce_image_glyph (it)
   PREPARE_FACE_FOR_DISPLAY (it->f, face);
   prepare_image_for_display (it->f, img);
 
-  it->ascent = it->phys_ascent = IMAGE_ASCENT (img);
+  it->ascent = it->phys_ascent = image_ascent (img, face);
   it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
   it->pixel_width = img->width + 2 * img->margin;
 
@@ -1516,16 +1548,19 @@ x_produce_image_glyph (it)
       glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
       if (glyph < it->glyph_row->glyphs[area + 1])
        {
-         glyph->type = IMAGE_GLYPH;
-         glyph->u.img.id = img->id;
-         glyph->u.img.face_id = it->face_id;
-         glyph->pixel_width = it->pixel_width;
          glyph->charpos = CHARPOS (it->position);
          glyph->object = it->object;
-         glyph->left_box_line_p = it->start_of_box_run_p;
-         glyph->right_box_line_p = it->end_of_box_run_p;
+         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];
        }
     }
@@ -1552,17 +1587,20 @@ x_append_stretch_glyph (it, object, width, height, ascent)
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
-      glyph->type = STRETCH_GLYPH;
-      glyph->u.stretch.ascent = height * ascent;
-      glyph->u.stretch.height = height;
-      glyph->u.stretch.face_id = it->face_id;
-      glyph->pixel_width = width;
       glyph->charpos = CHARPOS (it->position);
       glyph->object = object;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      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];
     }
 }
@@ -1610,7 +1648,10 @@ x_produce_stretch_glyph (it)
      struct it *it;
 {
   /* (space :width WIDTH :height HEIGHT.  */
-  extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
+#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;
@@ -1711,6 +1752,38 @@ x_produce_stretch_glyph (it)
   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))) / 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
@@ -1720,38 +1793,62 @@ 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;
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
       XCharStruct *pcm;
-      struct it ci;
       int font_not_found_p;
-      int c;
+      struct font_info *font_info;
+      int boff;                        /* baseline offset */
 
-      /* Maybe translate single-byte characters to multibyte.  */
+      /* Maybe translate single-byte characters to multibyte, or the
+        other way.  */
       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))))
+      if (!ASCII_BYTE_P (it->c))
        {
-         it->char_to_display = unibyte_char_to_multibyte (it->c);
-         it->charset = CHAR_CHARSET (it->char_to_display);
+         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->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->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
+             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+             face = FACE_FROM_ID (it->f, it->face_id);
+           }
        }
       
-      /* Get face and font to use.  Encode IT->char_to_display.  */
-      face = x_get_char_face_and_encoding (it->f, it->char_to_display,
-                                          it->face_id, &char2b,
-                                          it->multibyte_p);
+      /* 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);
       font = face->font;
 
       /* 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);
+       {
+         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 (it->char_to_display >= ' '
          && (!it->multibyte_p || it->char_to_display < 128))
@@ -1762,11 +1859,22 @@ x_produce_glyphs (it)
          it->nglyphs = 1;
 
          pcm = x_per_char_metric (font, &char2b);
-         it->ascent = font->ascent;
-         it->descent = font->descent;
-         it->phys_ascent = pcm->ascent;
-         it->phys_descent = pcm->descent;
-         it->pixel_width = pcm->width;
+         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;
+           }
+         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.  */
@@ -1814,8 +1922,7 @@ x_produce_glyphs (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->lbearing < 0
-                 || pcm->rbearing > pcm->width)
+             if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
                it->glyph_row->contains_overlapping_glyphs_p = 1;
            }
        }
@@ -1824,8 +1931,8 @@ x_produce_glyphs (it)
          /* 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;
-         it->descent = it->phys_descent = font->descent;
+         it->ascent = it->phys_ascent = font->ascent + boff;
+         it->descent = it->phys_descent = font->descent - boff;
       
          if (face->box != FACE_NO_BOX)
            {
@@ -1837,15 +1944,13 @@ x_produce_glyphs (it)
       else if (it->char_to_display == '\t')
        {
          int tab_width = it->tab_width * CANON_X_UNIT (it->f);
-         int x = (it->current_x
-                  - it->prompt_width
-                  + it->continuation_lines_width);
+         int x = it->current_x + it->continuation_lines_width;
          int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
       
          it->pixel_width = next_tab_x - x;
          it->nglyphs = 1;
-         it->ascent = it->phys_ascent = font->ascent;
-         it->descent = it->phys_descent = font->descent;
+         it->ascent = it->phys_ascent = font->ascent + boff;
+         it->descent = it->phys_descent = font->descent - boff;
          
          if (it->glyph_row)
            {
@@ -1858,56 +1963,37 @@ x_produce_glyphs (it)
        {
          /* 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.  There has to be better support for
-            variable sizes in cmpchar_info to do anything better than
-            that.
+            width of the font.  */
 
-            Note: composite characters are represented as one glyph in
-            the glyph matrix.  There are no padding glyphs.  */
-         if (it->charset == CHARSET_COMPOSITION)
+         /* 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)
            {
-             struct cmpchar_info *cmpcharp;
-             int idx;
+             int charset = CHAR_CHARSET (it->char_to_display);
 
-             idx = COMPOSITE_CHAR_ID (it->char_to_display);
-             cmpcharp = cmpchar_table[idx];
-             it->pixel_width = font->max_bounds.width * cmpcharp->width;
-         
-             /* There are no padding glyphs, so there is only one glyph
-                to produce for the composite char.  Important is that
-                pixel_width, ascent and descent are the values of what is
-                drawn by draw_glyphs.  */
-             it->nglyphs = 1;
-
-             /* These settings may not be correct.  We must have more
-                information in cmpcharp to do the correct setting.  */
-             it->ascent = font->ascent;
-             it->descent = font->descent;
-             it->phys_ascent = font->max_bounds.ascent;
-             it->phys_descent = font->max_bounds.descent;
+             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
            {
-             /* 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);
              it->pixel_width = pcm->width;
-             if (font_not_found_p)
-               it->pixel_width *= CHARSET_WIDTH (it->charset);
-             it->nglyphs = 1;
-             it->ascent = font->ascent;
-             it->descent = font->descent;
-             it->phys_ascent = pcm->ascent;
-             it->phys_descent = pcm->descent;
+             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;
@@ -1931,16 +2017,284 @@ x_produce_glyphs (it)
            x_append_glyph (it);
        }
     }
+  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);
+       }
+      
+      /* 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);
+      font = face->font;
+
+      /* 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;
+       }
+
+      /* 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)
+       {
+         /* 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.  */
+         pcm = x_per_char_metric (font, &char2b);
+         if (pcm)
+           {
+             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);
+             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;
+               }
+
+             pcm = x_per_char_metric (font, &char2b);
+             if (pcm)
+               {
+                 width = pcm->width;
+                 ascent = pcm->ascent;
+                 descent = pcm->descent;
+               }
+             else
+               {
+                 width = FONT_WIDTH (font);
+                 ascent = font->ascent;
+                 descent = font->descent;
+               }
+
+             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;
+       }
+
+      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;
+         it->ascent += thick;
+         it->descent += 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 (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);
 
-  /* Accumulate dimensions.  */
-  xassert (it->ascent >= 0 && it->descent > 0);
+  /* 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;
   
+  it->descent += it->extra_line_spacing;
+  
   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);
@@ -2032,9 +2386,6 @@ struct glyph_string
   XChar2b *char2b;
   int nchars;
 
-  /* Character set of this glyph string.  */
-  int charset;
-
   /* A face-override for drawing cursors, mouse face and similar.  */
   enum draw_glyphs_face hl;
 
@@ -2047,14 +2398,13 @@ struct glyph_string
   /* Font info for this string.  */
   struct font_info *font_info;
 
-  /* Non-null means this string describes (part of) a composite
-     character.  All characters from char2b are drawn at the same
-     x-origin in that case.  */
-  struct cmpchar_info *cmpcharp;
+  /* 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 cmpcharp.  If this is zero, this glyph string
-     describes the first character of a composite character.  */
+     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
@@ -2096,7 +2446,7 @@ struct glyph_string
 };
 
 
-#if GLYPH_DEBUG
+#if 0
 
 static void
 x_dump_glyph_string (s)
@@ -2150,7 +2500,7 @@ 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_glyph_string_underline 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 *));
@@ -2161,9 +2511,9 @@ 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 *, float, int));
+                                     unsigned long *, double, int));
 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
-                                     float, int, unsigned long));
+                                     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 *));
@@ -2178,6 +2528,13 @@ 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 GLYPH_DEBUG
+static void x_check_font P_ ((struct frame *, XFontStruct *));
+#endif
 
 
 /* Append the list of glyph strings with head H and tail T to the list
@@ -2244,7 +2601,7 @@ x_set_cursor_gc (s)
   if (s->font == FRAME_FONT (s->f)
       && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
       && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
-      && !s->cmpcharp)
+      && !s->cmp)
     s->gc = s->f->output_data.x->cursor_gc;
   else
     {
@@ -2295,10 +2652,15 @@ x_set_mouse_face_gc (s)
      struct glyph_string *s;
 {     
   int face_id;
+  struct face *face;
 
   /* What face has to be used for the mouse face?  */
   face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
-  face_id = FACE_FOR_CHARSET (s->f, face_id, s->charset);
+  face = FACE_FROM_ID (s->f, 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);
 
@@ -2342,7 +2704,6 @@ x_set_mode_line_face_gc (s)
      struct glyph_string *s;
 {     
   s->gc = s->face->gc;
-  xassert (s->gc != 0);
 }
 
 
@@ -2354,6 +2715,8 @@ static INLINE void
 x_set_glyph_string_gc (s)
      struct glyph_string *s;
 {
+  PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+  
   if (s->hl == DRAW_NORMAL_TEXT)
     {
       s->gc = s->face->gc;
@@ -2435,13 +2798,13 @@ x_get_glyph_string_clip_rect (s, r)
      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_TOP_LINE_HEIGHT (s->w);
+    r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
   else
     r->y = max (0, s->row->y);
 
-  /* If drawing a toolbar window, draw it over the internal border
+  /* If drawing a tool-bar window, draw it over the internal border
      at the top of the window.  */
-  if (s->w == XWINDOW (s->f->toolbar_window))
+  if (s->w == XWINDOW (s->f->tool_bar_window))
     r->y -= s->f->output_data.x->internal_border_width;
 
   /* If S draws overlapping rows, it's sufficient to use the top and
@@ -2449,7 +2812,7 @@ x_get_glyph_string_clip_rect (s, r)
      intentionally draws over other lines.  */
   if (s->for_overlaps_p)
     {
-      r->y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (s->w);
+      r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
       r->height = window_text_bottom_y (s->w) - r->y;
     }
       
@@ -2471,13 +2834,13 @@ x_set_glyph_string_clipping (s)
 
 
 /* Compute left and right overhang of glyph string S.  If S is a glyph
-   string for a composite character, assume overhangs don't exist.  */
+   string for a composition, assume overhangs don't exist.  */
 
 static INLINE void
 x_compute_glyph_string_overhangs (s)
      struct glyph_string *s;
 {
-  if (s->cmpcharp == NULL
+  if (s->cmp == NULL
       && s->first_glyph->type == CHAR_GLYPH)
     {
       XCharStruct cs;
@@ -2524,8 +2887,8 @@ x_compute_overhangs_and_x (s, x, backward_p)
 
 
 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
-   frame F.  Overhangs of glyphs other than type CHAR_GLYPH or of
-   character glyphs for composite characters are assumed to be zero.  */
+   frame F.  Overhangs of glyphs other than type CHAR_GLYPH are
+   assumed to be zero.  */
 
 static void
 x_get_glyph_overhangs (glyph, f, left, right)
@@ -2533,26 +2896,22 @@ x_get_glyph_overhangs (glyph, f, left, right)
      struct frame *f;
      int *left, *right;
 {
-  int c;
-  
   *left = *right = 0;
   
-  if (glyph->type == CHAR_GLYPH
-      && (c = glyph->u.ch.code,
-         CHAR_CHARSET (c) != CHARSET_COMPOSITION))
+  if (glyph->type == CHAR_GLYPH)
     {
       XFontStruct *font;
       struct face *face;
       struct font_info *font_info;
       XChar2b char2b;
-      
-      face = x_get_glyph_face_and_encoding (f, glyph, &char2b);
+      XCharStruct *pcm;
+
+      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)
+      if (font
+         && (pcm = x_per_char_metric (font, &char2b)))
        {
-         XCharStruct *pcm = x_per_char_metric (font, &char2b);
-         
          if (pcm->rbearing > pcm->width)
            *right = pcm->rbearing - pcm->width;
          if (pcm->lbearing < 0)
@@ -2631,7 +2990,7 @@ x_right_overwritten (s)
     {
       int x = 0, i;
       struct glyph *glyphs = s->row->glyphs[s->area];
-      int first = (s->first_glyph - glyphs) + (s->cmpcharp ? 1 : s->nchars);
+      int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
       int end = s->row->used[s->area];
       
       for (i = first; i < end && s->right_overhang > x; ++i)
@@ -2655,7 +3014,7 @@ x_right_overwriting (s)
   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->cmpcharp ? 1 : s->nchars);
+  int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
 
   k = -1;
   x = 0;
@@ -2690,7 +3049,8 @@ x_clear_glyph_string_rect (s, x, y, w, h)
 /* 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.  */
+   when a string preceding S draws into the background of S, or S
+   contains the first component of a composition.  */
 
 static void
 x_draw_glyph_string_background (s, force_p)
@@ -2701,16 +3061,7 @@ x_draw_glyph_string_background (s, force_p)
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
-      if (s->cmpcharp
-         && s->gidx > 0
-         && !s->font_not_found_p
-         && !s->extends_to_end_of_line_p)
-       {
-         /* Don't draw background for glyphs of a composite
-            characters, except for the first one.  */
-         s->background_filled_p = 1;
-       }
-      else if (s->stippled_p)
+      if (s->stippled_p)
        {
          /* Fill background with a stipple pattern.  */
          XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
@@ -2724,7 +3075,6 @@ x_draw_glyph_string_background (s, force_p)
       else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
-              || s->cmpcharp
               || force_p)
        {
          x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
@@ -2752,209 +3102,175 @@ x_draw_glyph_string_foreground (s)
   else
     x = s->x;
 
-  if (s->cmpcharp == NULL)
+  /* Draw characters of S as rectangles if S's font could not be
+     loaded.  */
+  if (s->font_not_found_p)
     {
-      /* Not a composite character.  Draw characters of S as
-        rectangles if S's font could not be loaded.  */
-      if (s->font_not_found_p)
+      for (i = 0; i < s->nchars; ++i)
        {
-         for (i = 0; i < s->nchars; ++i)
-           {
-             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;
-           }
+         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;
+
+      /* 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;
+
+      /* 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);
        }
       else
        {
-         char *char1b = (char *) s->char2b;
-
-         /* 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;
-
-         /* 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, 
-                              s->char2b, s->nchars);
-             else
-               XDrawString (s->display, s->window, s->gc, x, s->ybase, 
-                            char1b, s->nchars);
-           }
+         if (s->two_byte_p)
+           XDrawImageString16 (s->display, s->window, s->gc, x,
+                               s->ybase - boff, s->char2b, s->nchars);
          else
-           {
-             if (s->two_byte_p)
-               XDrawImageString16 (s->display, s->window, s->gc,
-                                   x, s->ybase, s->char2b, s->nchars);
-             else
-               XDrawImageString (s->display, s->window, s->gc,
-                                 x, s->ybase, char1b, s->nchars);
-           }
+           XDrawImageString (s->display, s->window, s->gc, x,
+                             s->ybase - boff, char1b, s->nchars);
        }
     }
+}
+
+/* Draw the foreground of composite glyph string S.  */
+
+static void
+x_draw_composite_glyph_string_foreground (s)
+     struct glyph_string *s;
+{
+  int i, x;
+
+  /* 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 + s->face->box_line_width;
   else
-    {
-      /* S is a glyph string for a composite character. S->gidx is the
-        index of the first character drawn in the vector
-        S->cmpcharp->glyph.  S->gidx == 0 means we are drawing the
-        very first component character of a composite char.  */
+    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.  */
 
-      /* Draw a single rectangle for the composite character if S's
-        font could not be loaded.  */
-      if (s->font_not_found_p && s->gidx == 0)
+  /* 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
-       {
-         XCharStruct *pcm;
-         int relative_compose, default_ascent, i;
-         int highest = 0, lowest = 0;
+    }
+  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);
+    }
+}
 
-         /* The value of font_info my be null if we couldn't find it
-            in x_get_char_face_and_encoding.  */
-         if (s->cmpcharp->cmp_rule == NULL && s->font_info)
-           {
-             relative_compose = s->font_info->relative_compose;
-             default_ascent = s->font_info->default_ascent;
-           }
-         else
-           relative_compose = default_ascent = 0;
 
-         if ((s->cmpcharp->cmp_rule || relative_compose)
-             && s->gidx == 0)
-           {
-             /* This is the first character.  Initialize variables.
-                Highest is the highest position of glyphs ever
-                written, lowest the lowest position.  */
-             int x_offset = 0;
-             int first_ch = s->first_glyph->u.ch.code;
-
-             if (default_ascent
-                 && CHAR_TABLE_P (Vuse_default_ascent)
-                 && !NILP (Faref (Vuse_default_ascent, first_ch)))
-               {
-                 highest = default_ascent;
-                 lowest = 0;
-               }
-             else
-               {
-                 pcm = PER_CHAR_METRIC (s->font, s->char2b);
-                 highest = pcm->ascent + 1;
-                 lowest = - pcm->descent;
-               }
+#ifdef USE_X_TOOLKIT
+
+static struct frame *x_frame_of_widget P_ ((Widget));
+
+
+/* Return the frame on which widget WIDGET is used.. Abort if frame
+   cannot be determined.  */
 
-             if (s->cmpcharp->cmp_rule)
-               x_offset = (s->cmpcharp->col_offset[0]
-                           * FONT_WIDTH (s->f->output_data.x->font));
+static struct frame *
+x_frame_of_widget (widget)
+     Widget widget;
+{
+  struct x_display_info *dpyinfo;
+  Lisp_Object tail;
+  struct frame *f;
+  
+  dpyinfo = x_display_info_for_display (XtDisplay (widget));
+  
+  /* 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);
+
+  /* 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;
 
-             /* Draw the first character at the normal position.  */
-             XDrawString16 (s->display, s->window, s->gc,
-                            x + x_offset,
-                            s->ybase, s->char2b, 1);
-             i = 1;
-             ++s->gidx;
-           }
-         else
-           i = 0;
+  abort ();
+}
 
-         for (; i < s->nchars; i++, ++s->gidx)
-           {
-             int x_offset = 0, y_offset = 0;
 
-             if (relative_compose)
-               {
-                 pcm = PER_CHAR_METRIC (s->font, s->char2b + i);
-                 if (NILP (Vignore_relative_composition)
-                     || NILP (Faref (Vignore_relative_composition,
-                                     make_number (s->cmpcharp->glyph[s->gidx]))))
-                   {
-                     if (- pcm->descent >= relative_compose)
-                       {
-                         /* Draw above the current glyphs.  */
-                         y_offset = highest + pcm->descent;
-                         highest += pcm->ascent + pcm->descent;
-                       }
-                     else if (pcm->ascent <= 0)
-                       {
-                         /* Draw beneath the current glyphs.  */
-                         y_offset = lowest - pcm->ascent;
-                         lowest -= pcm->ascent + pcm->descent;
-                       }
-                   }
-                 else
-                   {
-                     /* Draw the glyph at normal position.  If
-                        it sticks out of HIGHEST or LOWEST,
-                        update them appropriately.  */
-                     if (pcm->ascent > highest)
-                       highest = pcm->ascent;
-                     else if (- pcm->descent < lowest)
-                       lowest = - pcm->descent;
-                   }
-               }
-             else if (s->cmpcharp->cmp_rule)
-               {
-                 int gref = (s->cmpcharp->cmp_rule[s->gidx] - 0xA0) / 9;
-                 int nref = (s->cmpcharp->cmp_rule[s->gidx] - 0xA0) % 9;
-                 int bottom, top;
-
-                 /* Re-encode GREF and NREF so that they specify
-                    only Y-axis information:
-                    0:top, 1:base, 2:bottom, 3:center  */
-                 gref = gref / 3 + (gref == 4) * 2;
-                 nref = nref / 3 + (nref == 4) * 2;
-
-                 pcm = PER_CHAR_METRIC (s->font, s->char2b + i);
-                 bottom = ((gref == 0 ? highest : gref == 1 ? 0
-                            : gref == 2 ? lowest
-                            : (highest + lowest) / 2)
-                           - (nref == 0 ? pcm->ascent + pcm->descent
-                              : nref == 1 ? pcm->descent : nref == 2 ? 0
-                              : (pcm->ascent + pcm->descent) / 2));
-                 top = bottom + (pcm->ascent + pcm->descent);
-                 if (top > highest)
-                   highest = top;
-                 if (bottom < lowest)
-                   lowest = bottom;
-                 y_offset = bottom + pcm->descent;
-                 x_offset = (s->cmpcharp->col_offset[s->gidx]
-                             * FONT_WIDTH (FRAME_FONT (s->f)));
-               }
+/* 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.  */
 
-             XDrawString16 (s->display, s->window, s->gc,
-                            x + x_offset, s->ybase - y_offset,
-                            s->char2b + i, 1);
-           }
-       }
-    }
+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);
 }
 
 
+#endif /* USE_X_TOOLKIT */
+
+
 /* Allocate the color COLOR->pixel on SCREEN of 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.  */
 
 int
-x_alloc_nearest_color (display, screen, cmap, color)
-     Display *display;
-     Screen *screen;
+x_alloc_nearest_color (f, cmap, color)
+     struct frame *f;
      Colormap cmap;
      XColor *color;
 {
-  int rc = XAllocColor (display, cmap, color);
+  Display *display = FRAME_X_DISPLAY (f);
+  Screen *screen = FRAME_X_SCREEN (f);
+  int rc;
+
+  gamma_correct (f, color);
+  rc = XAllocColor (display, cmap, color);
   if (rc == 0)
     {
       /* If we got to this point, the colormap is full, so we're going
@@ -2990,10 +3306,62 @@ x_alloc_nearest_color (display, screen, cmap, color)
       rc = XAllocColor (display, cmap, color);
     }
 
+#ifdef DEBUG_X_COLORS
+  if (rc)
+    register_color (color->pixel);
+#endif /* DEBUG_X_COLORS */
+  
   return rc;
 }
 
 
+/* 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;
+  XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (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;
+}
+
+
 /* 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
@@ -3007,7 +3375,7 @@ x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
      Display *display;
      Colormap cmap;
      unsigned long *pixel;
-     float factor;
+     double factor;
      int delta;
 {
   XColor color, new;
@@ -3024,28 +3392,19 @@ x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
   new.blue = min (0xffff, factor * color.blue);
 
   /* Try to allocate the color.  */
-  success_p = x_alloc_nearest_color (display, FRAME_X_SCREEN (f), cmap, &new);
+  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.  */
-         int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
-         
-         /* If display has an immutable color map, freeing colors is
-            not necessary and some servers don't allow it.  So don't
-            do it.  */
-         if (class != StaticColor
-             && class != StaticGray
-             && class != TrueColor)
-           XFreeColors (display, cmap, &new.pixel, 1, 0);
+         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 (display, FRAME_X_SCREEN (f),
-                                            cmap, &new);
+         success_p = x_alloc_nearest_color (f, cmap, &new);
        }
       else
        success_p = 1;
@@ -3067,7 +3426,7 @@ static void
 x_setup_relief_color (f, relief, factor, delta, default_pixel)
      struct frame *f;
      struct relief *relief;
-     float factor;
+     double factor;
      int delta;
      unsigned long default_pixel;
 {
@@ -3076,7 +3435,7 @@ x_setup_relief_color (f, relief, factor, delta, default_pixel)
   unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
   unsigned long pixel;
   unsigned long background = di->relief_background;
-  Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+  Colormap cmap = FRAME_X_COLORMAP (f);
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Display *dpy = FRAME_X_DISPLAY (f);
 
@@ -3089,13 +3448,7 @@ x_setup_relief_color (f, relief, factor, delta, default_pixel)
   if (relief->gc
       && relief->allocated_p)
     {
-      /* If display has an immutable color map, freeing colors is not
-        necessary and some servers don't allow it.  So don't do it.  */
-      int class = dpyinfo->visual->class;
-      if (class != StaticColor
-         && class != StaticGray
-         && class != TrueColor)
-       XFreeColors (dpy, cmap, &relief->pixel, 1, 0);
+      x_free_colors (f, &relief->pixel, 1);
       relief->allocated_p = 0;
     }
 
@@ -3269,13 +3622,13 @@ x_draw_glyph_string_box (s)
   if (s->row->full_width_p
       && !s->w->pseudo_window_p)
     {
-      last_x += FRAME_X_FLAGS_AREA_WIDTH (s->f);
+      last_x += FRAME_X_RIGHT_FLAGS_AREA_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->cmpcharp || s->img
+  last_glyph = (s->cmp || s->img
                ? s->first_glyph
                : s->first_glyph + s->nchars - 1);
 
@@ -3318,7 +3671,7 @@ x_draw_image_foreground (s)
      struct glyph_string *s;
 {
   int x;
-  int y = s->ybase - IMAGE_ASCENT (s->img);
+  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.  */
@@ -3397,7 +3750,7 @@ x_draw_image_relief (s)
   int x0, y0, x1, y1, thick, raised_p;
   XRectangle r;
   int x;
-  int y = s->ybase - IMAGE_ASCENT (s->img);
+  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.  */
@@ -3418,7 +3771,7 @@ x_draw_image_relief (s)
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
     {
-      thick = toolbar_button_relief > 0 ? toolbar_button_relief : 3;
+      thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
       raised_p = s->hl == DRAW_IMAGE_RAISED;
     }
   else
@@ -3446,7 +3799,7 @@ x_draw_image_foreground_1 (s, pixmap)
      Pixmap pixmap;
 {
   int x;
-  int y = s->ybase - s->y - IMAGE_ASCENT (s->img);
+  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.  */
@@ -3734,6 +4087,14 @@ x_draw_glyph_string (s)
       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 ();
     }
@@ -3813,94 +4174,45 @@ x_draw_glyph_string (s)
 }
 
 
-/* A work-list entry used during the construction of glyph_string
-   structures for a composite character.  */
-
-struct work
-{
-  /* Pointer to composite char info defining has the composite
-     character is drawn.  */
-  struct cmpchar_info *cmpcharp;
-
-  /* Start index in compcharp->glyph[].  */
-  int gidx;
-
-  /* Next in stack.  */
-  struct work *next;
-};
-
+static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
+                                             struct face **, int));
 
-static void x_fill_composite_glyph_string P_ ((struct glyph_string *,
-                                              int, struct work **,
-                                              struct work **, 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.
 
-/* Load glyph string S with information from the top of *STACK for a
-   composite character.  FACE_ID is the id of the face in which S is
-   drawn.  *NEW is a pointer to a struct work not on the stack, that
-   can be used if this function needs to push a new structure on the
-   stack.  If it uses it, *NEW is set to null.  OVERLAPS_P non-zero
-   means S should draw the foreground only, and use its lines physical
-   height for clipping.  */
+   Value is the index of a component not in S.  */
 
-static void
-x_fill_composite_glyph_string (s, face_id, stack, new, overlaps_p)
+static int
+x_fill_composite_glyph_string (s, faces, overlaps_p)
      struct glyph_string *s;
-     int face_id;
-     struct work **stack, **new;
+     struct face **faces;
      int overlaps_p;
 {
-  int i, c;
-  struct work *work;
+  int i;
 
-  xassert (s && *new && *stack);
+  xassert (s);
 
-  s->for_overlaps_p = 1;
+  s->for_overlaps_p = overlaps_p;
   
-  /* Pop the work stack.  */
-  work = *stack;
-  *stack = work->next;
-  
-  /* For all glyphs of cmpcharp->glyph, starting at the offset
-     work->offset, until we reach the end of the definition or
-     encounter another composite char, get the font and face to use,
-     and add it to S.  */
-  for (i = work->gidx; i < work->cmpcharp->glyph_len; ++i)
-    {
-      c = FAST_GLYPH_CHAR (work->cmpcharp->glyph[i]);
-      if (CHAR_CHARSET (c) == CHARSET_COMPOSITION)
-       break;
-      s->face = x_get_char_face_and_encoding (s->f, c, face_id,
-                                             s->char2b + s->nchars, 1);
-      s->font = s->face->font;
-      s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
-      ++s->nchars;
-    }
+  s->face = faces[s->gidx];
+  s->font = s->face->font;
+  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
 
-  /* If we find another composite char in the glyph definition of
-     work->cmpcharp, put back the rest of the glyphs on the work
-     stack, and make a new entry for the composite char.  */
-  if (i < work->cmpcharp->glyph_len)
-    {
-      /* Push back an unprocessed rest of this glyph spec.  */
-      if (i < work->cmpcharp->glyph_len - 1)
-       {
-         work->gidx = i + 1;
-         work->next = *stack;
-         *stack = work;
-         work = *new;
-         *new = NULL;
-       }
+  /* 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;
 
-      /* Make an entry for the composite char on the work stack.  */
-      work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)];
-      work->gidx = 0;
-      work->next = *stack;
-      *stack = work;
-    }
+  /* All glyph strings for the same composition has the same width,
+     i.e. the width set for the first component of the composition.  */
 
-  /* The width of this glyph string equals the width of the first
-     glyph.  All characters are drawn at the same x-position.  */
   s->width = s->first_glyph->pixel_width;
 
   /* If the specified font could not be loaded, use the frame's
@@ -3920,14 +4232,17 @@ x_fill_composite_glyph_string (s, face_id, stack, new, overlaps_p)
 
   /* This glyph string must always be drawn with 16-bit functions.  */
   s->two_byte_p = 1;
+
+  return s->gidx + s->nchars;
 }
 
 
-/* Load glyph string S with a sequence of non-composite characters.
+/* 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 lines physical height for clipping.
+   use its physical height for clipping.
 
    Value is the index of the first glyph not in S.  */
 
@@ -3939,8 +4254,8 @@ x_fill_glyph_string (s, face_id, start, end, overlaps_p)
 {
   struct glyph *glyph, *last;
   int voffset;
+  int glyph_not_available_p;
   
-  xassert (s->charset != CHARSET_COMPOSITION);
   xassert (s->f == XFRAME (s->w->frame));
   xassert (s->nchars == 0);
   xassert (start >= 0 && end > start);
@@ -3950,17 +4265,21 @@ x_fill_glyph_string (s, face_id, start, end, overlaps_p)
   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 charset, nowadays.  */
-        && glyph->u.ch.face_id == face_id)
+        /* 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);
-      if (s->char2b[s->nchars].byte2 != 0)
-       s->two_byte_p = 1;
-      
+                                              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;
@@ -3974,7 +4293,7 @@ x_fill_glyph_string (s, face_id, start, end, overlaps_p)
      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)
+  if (s->font == NULL || glyph_not_available_p)
     {
       s->font_not_found_p = 1;
       s->font = FRAME_FONT (s->f);
@@ -3995,9 +4314,9 @@ 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);
+  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->u.img.face_id);
+  s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
   s->font = s->face->font;
   s->width = s->first_glyph->pixel_width;
   
@@ -4006,19 +4325,48 @@ x_fill_image_glyph_string (s)
 }
 
 
-/* Fill glyph string S from stretch glyph S->first_glyph.  */
+/* Fill glyph string S from a sequence of stretch glyphs.
 
-static void
-x_fill_stretch_glyph_string (s)
+   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);
-  s->face = FACE_FROM_ID (s->f, s->first_glyph->u.stretch.face_id);
+  
+  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->width = s->first_glyph->pixel_width;
+  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 += s->first_glyph->voffset;
+  s->ybase += voffset;
+
+  xassert (s->face && s->face->gc);
+  return glyph - s->row->glyphs[s->area];
 }
 
 
@@ -4053,8 +4401,8 @@ x_init_glyph_string (s, char2b, w, row, area, start, hl)
   s->height = row->height;
   s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
 
-  /* Display the internal border below the toolbar window.  */
-  if (s->w == XWINDOW (s->f->toolbar_window))
+  /* 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;
@@ -4100,15 +4448,15 @@ x_set_glyph_string_background_width (s, start, last_x)
    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_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL,    \
-                                HL, X, LAST_X)                             \
+/* 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);            \
-        x_fill_stretch_glyph_string (s);                                   \
+        START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END);    \
         x_append_glyph_string (&HEAD, &TAIL, s);                           \
-        ++START;                                                           \
          s->x = (X);                                                       \
        }                                                                   \
      while (0)
@@ -4122,8 +4470,7 @@ x_set_glyph_string_background_width (s, start, last_x)
    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)                         \
+#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
      do                                                                        \
        {                                                               \
         s = (struct glyph_string *) alloca (sizeof *s);                \
@@ -4145,78 +4492,82 @@ x_set_glyph_string_background_width (s, start, last_x)
    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)                    \
+#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
      do                                                                           \
        {                                                                  \
-        int c, charset, face_id;                                          \
+        int c, face_id;                                                   \
         XChar2b *char2b;                                                  \
                                                                           \
-        c = (ROW)->glyphs[AREA][START].u.ch.code;                         \
-        charset = CHAR_CHARSET (c);                                       \
-        face_id = (ROW)->glyphs[AREA][START].u.ch.face_id;                \
-                                                                          \
-        if (charset == CHARSET_COMPOSITION)                               \
-          {                                                               \
-            struct work *stack, *work, *new = NULL;                       \
-            int n = 0;                                                    \
-             struct glyph_string *first_s = NULL;                         \
-                                                                          \
-            /* Push an initial entry for character c on the stack.  */    \
-            stack = NULL;                                                 \
-            work = (struct work *) alloca (sizeof *work);                 \
-            work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)];        \
-            work->gidx = 0;                                               \
-            work->next = stack;                                           \
-            stack = work;                                                 \
-                                                                          \
-            /* While the stack is not empty, append glyph_strings         \
-               to head/tail for glyphs to draw.  */                       \
-            while (stack)                                                 \
-              {                                                           \
-                s = (struct glyph_string *) alloca (sizeof *s);           \
-                char2b = (XChar2b *) alloca (stack->cmpcharp->glyph_len   \
-                                             * sizeof (XChar2b));         \
-                x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
-                x_append_glyph_string (&(HEAD), &(TAIL), s);              \
-                s->cmpcharp = stack->cmpcharp;                            \
-                s->gidx = stack->gidx;                                    \
-                s->charset = charset;                                     \
-                s->x = (X);                                               \
-                                                                          \
-                 if (n == 0)                                              \
-                  {                                                       \
-                    /* Don't draw the background except for the           \
-                       first glyph string.  */                            \
-                     s->background_filled_p = n > 0;                      \
-                    first_s = s;                                          \
-                  }                                                       \
-                ++n;                                                      \
-                                                                          \
-                if (new == NULL)                                          \
-                  new = (struct work *) alloca (sizeof *new);             \
-                x_fill_composite_glyph_string (s, face_id, &stack,        \
-                                               &new, OVERLAPS_P);         \
-              }                                                           \
+        c = (ROW)->glyphs[AREA][START].u.ch;                              \
+        face_id = (ROW)->glyphs[AREA][START].face_id;                     \
                                                                           \
-            ++START;                                                      \
-             s = first_s;                                                 \
-          }                                                               \
-        else                                                              \
-          {                                                               \
-            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->charset = charset;                                         \
-            s->x = (X);                                                   \
-            START = x_fill_glyph_string (s, face_id, START, END,          \
+        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);       \
+      }                                                                          \
+                                                                         \
+    /* 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
@@ -4227,8 +4578,7 @@ x_set_glyph_string_background_width (s, start, last_x)
    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)                         \
+#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
      do                                                                           \
        {                                                                  \
         HEAD = TAIL = NULL;                                               \
@@ -4243,6 +4593,12 @@ x_set_glyph_string_background_width (s, start, 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);   \
@@ -4319,7 +4675,7 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
       /* X is relative to the left edge of W, without scroll bars
         or flag areas.  */
       struct frame *f = XFRAME (w->frame);
-      int width = FRAME_FLAGS_AREA_WIDTH (f);
+      /* int width = FRAME_FLAGS_AREA_WIDTH (f);  */
       int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
 
       x += window_left_x;
@@ -4328,7 +4684,7 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
 
       if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
        {
-         width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (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
@@ -4676,7 +5032,7 @@ x_clear_end_of_line (to_x)
       to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
     }
   
-  min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+  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);
   
@@ -4693,7 +5049,7 @@ x_clear_end_of_line (to_x)
 
 
 /* Clear entire frame.  If updating_frame is non-null, clear that
-   frame.  Otherwise clear selected_frame.  */
+   frame.  Otherwise clear the selected frame.  */
 
 static void
 x_clear_frame ()
@@ -4703,7 +5059,7 @@ x_clear_frame ()
   if (updating_frame)
     f = updating_frame;
   else
-    f = selected_frame;
+    f = SELECTED_FRAME ();
 
   /* Clearing the frame will erase any cursor, so mark them all as no
      longer visible.  */
@@ -4824,7 +5180,7 @@ XTflash (f)
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
                          (FRAME_INTERNAL_BORDER_WIDTH (f)
-                          + FRAME_TOOLBAR_LINES (f) * CANON_Y_UNIT (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,
@@ -4873,7 +5229,7 @@ XTflash (f)
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
                          (FRAME_INTERNAL_BORDER_WIDTH (f)
-                          + FRAME_TOOLBAR_LINES (f) * CANON_Y_UNIT (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,
@@ -4900,24 +5256,24 @@ XTflash (f)
 
 /* Make audible bell.  */
 
-#define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
-
 void
 XTring_bell ()
 {
-  if (FRAME_X_DISPLAY (selected_frame) == 0)
-    return;
-
+  struct frame *f = SELECTED_FRAME ();
+  
+  if (FRAME_X_DISPLAY (f))
+    {
 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
-  if (visible_bell)
-    XTflash (selected_frame);
-  else
+      if (visible_bell)
+       XTflash (f);
+      else
 #endif
-    {
-      BLOCK_INPUT;
-      XRINGBELL;
-      XFlush (FRAME_X_DISPLAY (selected_frame));
-      UNBLOCK_INPUT;
+       {
+         BLOCK_INPUT;
+         XBell (FRAME_X_DISPLAY (f), 0);
+         XFlush (FRAME_X_DISPLAY (f));
+         UNBLOCK_INPUT;
+       }
     }
 }
 
@@ -4965,8 +5321,8 @@ x_scroll_run (w, run)
      without mode lines.  Include in this box the flags areas to the
      left and right of W.  */
   window_box (w, -1, &x, &y, &width, &height);
-  width += 2 * FRAME_X_FLAGS_AREA_WIDTH (f);
-  x -= FRAME_X_FLAGS_AREA_WIDTH (f);
+  width += FRAME_X_FLAGS_AREA_WIDTH (f);
+  x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
 
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
@@ -5061,9 +5417,9 @@ expose_frame (f, x, y, w, h)
   TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
   expose_window_tree (XWINDOW (f->root_window), &r);
 
-  if (WINDOWP (f->toolbar_window))
+  if (WINDOWP (f->tool_bar_window))
     {
-      struct window *w = XWINDOW (f->toolbar_window);
+      struct window *w = XWINDOW (f->tool_bar_window);
       XRectangle window_rect;
       XRectangle intersection_rect;
       int window_x, window_y, window_width, window_height;
@@ -5127,12 +5483,12 @@ expose_window_tree (w, r)
                      &window_height);
          window_rect.x
            = (window_x
-              - FRAME_X_FLAGS_AREA_WIDTH (f)
-              - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
+              - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
+              - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
          window_rect.y = window_y;
          window_rect.width
            = (window_width
-              + 2 * FRAME_X_FLAGS_AREA_WIDTH (f)
+              + FRAME_X_FLAGS_AREA_WIDTH (f)
               + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
          window_rect.height
            = window_height + CURRENT_MODE_LINE_HEIGHT (w);
@@ -5275,6 +5631,13 @@ expose_window (w, r)
   int yb = window_text_bottom_y (w);
   int cursor_cleared_p;
 
+  /* 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;
+
   TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
          r->x, r->y, r->width, r->height));
 
@@ -5784,37 +6147,10 @@ construct_mouse_click (result, event, f)
   XSETINT (result->x, event->x);
   XSETINT (result->y, event->y);
   XSETFRAME (result->frame_or_window, f);
+  result->arg = Qnil;
   return Qnil;
 }
 
-#if 0 /* This function isn't called. --gerd  */
-
-/* Prepare a menu-event in *RESULT for placement in the input queue.  */
-
-static Lisp_Object
-construct_menu_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;
-  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));
-
-  XSETINT (result->x, event->x);
-  XSETINT (result->y, -1);
-  XSETFRAME (result->frame_or_window, f);
-}
-
-#endif /* 0 */
-
 \f
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
@@ -5880,7 +6216,7 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
      int *hpos, *vpos, *area;
 {
   struct glyph *glyph, *end;
-  struct glyph_row *row;
+  struct glyph_row *row = NULL;
   int x0, i, left_area_width;
 
   /* Find row containing Y.  Give up if some row is not enabled.  */
@@ -5994,7 +6330,7 @@ note_mode_line_highlight (w, x, mode_line_p)
   if (mode_line_p)
     row = MATRIX_MODE_LINE_ROW (w->current_matrix);
   else
-    row = MATRIX_TOP_LINE_ROW (w->current_matrix);
+    row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
   
   if (row->enabled_p)
     {
@@ -6006,7 +6342,7 @@ note_mode_line_highlight (w, x, mode_line_p)
       glyph = row->glyphs[TEXT_AREA];
       end = glyph + row->used[TEXT_AREA];
       x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
-             + FRAME_X_FLAGS_AREA_WIDTH (f));
+             + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
       while (glyph < end
             && x >= x0 + glyph->pixel_width)
        {
@@ -6025,14 +6361,26 @@ note_mode_line_highlight (w, x, mode_line_p)
             setting the global variable help_echo to the help string.  */
          help = Fget_text_property (make_number (glyph->charpos),
                                     Qhelp_echo, glyph->object);
-         if (STRINGP (help))
-           help_echo = help;
+         if (!NILP (help))
+           {
+             help_echo = help;
+             XSETWINDOW (help_echo_window, w);
+             help_echo_object = glyph->object;
+             help_echo_pos = glyph->charpos;
+           }
 
          /* Change the mouse pointer according to what is under X/Y.  */
          map = Fget_text_property (make_number (glyph->charpos),
                                    Qlocal_map, glyph->object);
          if (!NILP (Fkeymapp (map)))
            cursor = f->output_data.x->nontext_cursor;
+         else
+           {
+             map = Fget_text_property (make_number (glyph->charpos),
+                                       Qkeymap, glyph->object);
+             if (!NILP (Fkeymapp (map)))
+               cursor = f->output_data.x->nontext_cursor;
+           }
        }
     }
 
@@ -6061,7 +6409,8 @@ note_mouse_highlight (f, x, y)
     return;
 #endif
 
-  if (disable_mouse_highlight)
+  if (disable_mouse_highlight
+      || !f->glyphs_initialized_p)
     return;
 
   dpyinfo->mouse_face_mouse_x = x;
@@ -6092,11 +6441,11 @@ note_mouse_highlight (f, x, y)
   w = XWINDOW (window);
   frame_to_window_pixel_xy (w, &x, &y);
 
-  /* Handle toolbar window differently since it doesn't display a
+  /* Handle tool-bar window differently since it doesn't display a
      buffer.  */
-  if (EQ (window, f->toolbar_window))
+  if (EQ (window, f->tool_bar_window))
     {
-      note_toolbar_highlight (f, x, y);
+      note_tool_bar_highlight (f, x, y);
       return;
     }
 
@@ -6173,7 +6522,8 @@ note_mouse_highlight (f, x, y)
            overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
            noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
          }
-         
+
+       /* Sort overlays into increasing priority order.  */
        noverlays = sort_overlays (overlay_vec, noverlays, w);
 
        /* Check mouse-face highlighting.  */
@@ -6191,7 +6541,7 @@ note_mouse_highlight (f, x, y)
 
            /* Find the highest priority overlay that has a mouse-face prop.  */
            overlay = Qnil;
-           for (i = 0; i < noverlays; i++)
+           for (i = noverlays - 1; i >= 0; --i)
              {
                mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
                if (!NILP (mouse_face))
@@ -6277,26 +6627,43 @@ note_mouse_highlight (f, x, y)
 
        /* Look for a `help-echo' property.  */
        {
-         Lisp_Object help;
+         Lisp_Object help, overlay;
 
          /* Check overlays first.  */
          help = Qnil;
-         for (i = 0; i < noverlays && !STRINGP (help); ++i)
-           help = Foverlay_get (overlay_vec[i], Qhelp_echo); 
-           
-         /* Try text properties.  */
-         if (!STRINGP (help)
-             && ((STRINGP (glyph->object)
+         for (i = noverlays - 1; i >= 0 && NILP (help); --i)
+           {
+             overlay = overlay_vec[i];
+             help = Foverlay_get (overlay, Qhelp_echo);
+           }
+
+         if (!NILP (help))
+           {
+             help_echo = help;
+             help_echo_window = window;
+             help_echo_object = overlay;
+             help_echo_pos = pos;
+           }
+         else
+           {
+             /* Try text properties.  */
+             if ((STRINGP (glyph->object)
                   && glyph->charpos >= 0
                   && glyph->charpos < XSTRING (glyph->object)->size)
                  || (BUFFERP (glyph->object)
                      && glyph->charpos >= BEGV
-                     && glyph->charpos < ZV)))
-           help = Fget_text_property (make_number (glyph->charpos),
-                                      Qhelp_echo, glyph->object);
+                     && glyph->charpos < ZV))
+               help = Fget_text_property (make_number (glyph->charpos),
+                                          Qhelp_echo, glyph->object);
            
-         if (STRINGP (help))
-           help_echo = help;
+             if (!NILP (help))
+               {
+                 help_echo = help;
+                 help_echo_window = window;
+                 help_echo_object = glyph->object;
+                 help_echo_pos = glyph->charpos;
+               }
+           }
        }
          
        BEGV = obegv;
@@ -6319,37 +6686,37 @@ redo_mouse_highlight ()
 
 \f
 /***********************************************************************
-                              Toolbars
+                              Tool-bars
  ***********************************************************************/
 
-static int x_toolbar_item P_ ((struct frame *, int, int,
-                              struct glyph **, int *, int *, int *));
+static int x_tool_bar_item P_ ((struct frame *, int, int,
+                               struct glyph **, int *, int *, int *));
 
-/* Toolbar item index of the item on which a mouse button was pressed
+/* Tool-bar item index of the item on which a mouse button was pressed
    or -1.  */
 
-static int last_toolbar_item;
+static int last_tool_bar_item;
 
 
-/* Get information about the toolbar item at position X/Y on frame F.
-   Return in *GLYPH a pointer to the glyph of the toolbar item in
-   the current matrix of the toolbar window of F, or NULL if not
-   on a toolbar item.  Return in *PROP_IDX the index of the toolbar
-   item in F->current_toolbar_items.  Value is
+/* 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->current_tool_bar_items.  Value is
 
-   -1  if X/Y is not on a toolbar item
+   -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.  */
 
 static int
-x_toolbar_item (f, x, y, glyph, hpos, vpos, prop_idx)
+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->toolbar_window);
+  struct window *w = XWINDOW (f->tool_bar_window);
   int area;
 
   /* Find the glyph under X/Y.  */
@@ -6357,13 +6724,13 @@ x_toolbar_item (f, x, y, glyph, hpos, vpos, prop_idx)
   if (*glyph == NULL)
     return -1;
 
-  /* Get the start of this toolbar item's properties in
-     f->current_toolbar_items.  */
-  if (!toolbar_item_info (f, *glyph, prop_idx))
+  /* Get the start of this tool-bar item's properties in
+     f->current_tool_bar_items.  */
+  if (!tool_bar_item_info (f, *glyph, prop_idx))
     return -1;
 
   /* Is mouse on the highlighted item?  */
-  if (EQ (f->toolbar_window, dpyinfo->mouse_face_window)
+  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
@@ -6377,31 +6744,31 @@ x_toolbar_item (f, x, y, glyph, hpos, vpos, prop_idx)
 }
 
 
-/* Handle mouse button event on the toolbar of frame F, at
+/* Handle mouse button event on the tool-bar of frame F, at
    frame-relative coordinates X/Y.  EVENT_TYPE is either ButtionPress
    or ButtonRelase.  */
 
 static void
-x_handle_toolbar_click (f, button_event)
+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->toolbar_window);
+  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 toolbar item, return.  */
+  /* If not on the highlighted tool-bar item, return.  */
   frame_to_window_pixel_xy (w, &x, &y);
-  if (x_toolbar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
+  if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
     return;
 
   /* If item is disabled, do nothing.  */
-  enabled_p = (XVECTOR (f->current_toolbar_items)
-              ->contents[prop_idx + TOOLBAR_ITEM_ENABLED_P]);
+  enabled_p = (XVECTOR (f->current_tool_bar_items)
+              ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
   if (NILP (enabled_p))
     return;
   
@@ -6410,7 +6777,7 @@ x_handle_toolbar_click (f, button_event)
       /* Show item in pressed state.  */
       show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
       dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
-      last_toolbar_item = prop_idx;
+      last_tool_bar_item = prop_idx;
     }
   else
     {
@@ -6421,44 +6788,46 @@ x_handle_toolbar_click (f, button_event)
       show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
       dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
 
-      key = (XVECTOR (f->current_toolbar_items)
-            ->contents[prop_idx + TOOLBAR_ITEM_KEY]);
+      key = (XVECTOR (f->current_tool_bar_items)
+            ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
 
       XSETFRAME (frame, f);
-      event.kind = TOOLBAR_EVENT;
-      event.frame_or_window = Fcons (frame, Fcons (Qtoolbar, Qnil));
+      event.kind = TOOL_BAR_EVENT;
+      event.frame_or_window = frame;
+      event.arg = frame;
       kbd_buffer_store_event (&event);
 
-      event.kind = TOOLBAR_EVENT;
-      event.frame_or_window = Fcons (frame, key);
+      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_toolbar_item = -1;
+      last_tool_bar_item = -1;
     }
 }
 
 
-/* Possibly highlight a toolbar item on frame F when mouse moves to
-   toolbar window-relative coordinates X/Y.  Called from
+/* 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.  */
 
 static void
-note_toolbar_highlight (f, x, y)
+note_tool_bar_highlight (f, x, y)
      struct frame *f;
      int x, y;
 {
-  Lisp_Object window = f->toolbar_window;
+  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, j, area;
+  int i;
   Lisp_Object enabled_p;
   int prop_idx;
   enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
-  int on_highlight_p, mouse_down_p, rc;
+  int mouse_down_p, rc;
 
   /* Function note_mouse_highlight is called with negative x(y
      values when mouse moves outside of the frame.  */
@@ -6468,33 +6837,33 @@ note_toolbar_highlight (f, x, y)
       return;
     }
 
-  rc = x_toolbar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
+  rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
   if (rc < 0)
     {
-      /* Not on toolbar item.  */
+      /* Not on tool-bar item.  */
       clear_mouse_face (dpyinfo);
       return;
     }
   else if (rc == 0)
-    /* On same toolbar item as before.  */
+    /* On same tool-bar item as before.  */
     goto set_help_echo;
 
   clear_mouse_face (dpyinfo);
   
-  /* Mouse is down, but on different toolbar item?  */
+  /* 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_toolbar_item != prop_idx)
+      && last_tool_bar_item != prop_idx)
     return;
 
   dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
   
-  /* If toolbar item is not enabled, don't highlight it.  */
-  enabled_p = (XVECTOR (f->current_toolbar_items)
-              ->contents[prop_idx + TOOLBAR_ITEM_ENABLED_P]);
+  /* If tool-bar item is not enabled, don't highlight it.  */
+  enabled_p = (XVECTOR (f->current_tool_bar_items)
+              ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
   if (!NILP (enabled_p))
     {
       /* Compute the x-position of the glyph.  In front and past the
@@ -6515,7 +6884,7 @@ note_toolbar_highlight (f, x, y)
       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 = TOOLBAR_FACE_ID;
+      dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
       
       /* Display it as active.  */
       show_mouse_face (dpyinfo, draw);
@@ -6524,13 +6893,15 @@ note_toolbar_highlight (f, x, y)
       
  set_help_echo:
   
-  /* Set help_echo to a help string.to display for this toolbar item.
+  /* Set help_echo to a help string.to display for this tool-bar item.
      XTread_socket does the rest.  */
-  help_echo = (XVECTOR (f->current_toolbar_items)
-              ->contents[prop_idx + TOOLBAR_ITEM_HELP]);
-  if (!STRINGP (help_echo))
-    help_echo = (XVECTOR (f->current_toolbar_items)
-                ->contents[prop_idx + TOOLBAR_ITEM_CAPTION]);
+  help_echo_object = help_echo_window = Qnil;
+  help_echo_pos = -1;
+  help_echo = (XVECTOR (f->current_tool_bar_items)
+              ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
+  if (NILP (help_echo))
+    help_echo = (XVECTOR (f->current_tool_bar_items)
+                ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
 }
 
 
@@ -6579,6 +6950,9 @@ fast_find_position (w, pos, hpos, vpos, x, y)
          best_row = row;
          best_row_vpos = row_vpos;
        }
+
+      if (row->y + row->height >= yb)
+       break;
       
       ++row;
       ++row_vpos;
@@ -6697,8 +7071,11 @@ show_mouse_face (dpyinfo, draw)
        }
 
       if (end_hpos > start_hpos)
-       x_draw_glyphs (w, start_x, row, updated_area, 
-                      start_hpos, end_hpos, draw, NULL, NULL, 0);
+       {
+         row->mouse_face_p = draw == DRAW_MOUSE_FACE;
+         x_draw_glyphs (w, start_x, row, TEXT_AREA, 
+                        start_hpos, end_hpos, draw, NULL, NULL, 0);
+       }
     }
 
   /* If we turned the cursor off, turn it back on.  */
@@ -6741,6 +7118,24 @@ clear_mouse_face (dpyinfo)
   dpyinfo->mouse_face_window = Qnil;
 }
 
+
+/* 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.  */
+
+static void
+x_clear_mouse_face (w)
+     struct window *w;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+  Lisp_Object window;
+
+  XSETWINDOW (window, w);
+  if (EQ (window, dpyinfo->mouse_face_window))
+    clear_mouse_face (dpyinfo);
+}
+
+
 /* Just discard the mouse face information for frame F, if any.
    This is used when the size of F is changed.  */
 
@@ -6926,7 +7321,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
          }
 
        if (f1 == 0 && insist > 0)
-         f1 = selected_frame;
+         f1 = SELECTED_FRAME ();
 
        if (f1)
          {
@@ -6979,21 +7374,27 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 }
 
 
-DEFUN ("xt-process-timeouts", Fxt_process_timeouts, Sxt_process_timeouts,
-       0, 0, 0,
-  "Arrange for Xt timeout callbacks to be called.")
-  ()
-{
 #ifdef USE_X_TOOLKIT
-  BLOCK_INPUT;
-  while (XtAppPending (Xt_app_con) & XtIMTimer)
-    XtAppProcessEvent (Xt_app_con, XtIMTimer);
-  UNBLOCK_INPUT;
-#endif /* USE_X_TOOLKIT */
-  
-  return Qnil;
+
+/* 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_flag)
+    {
+      BLOCK_INPUT;
+      while (XtAppPending (Xt_app_con) & XtIMTimer)
+       XtAppProcessEvent (Xt_app_con, XtIMTimer);
+      UNBLOCK_INPUT;
+    }
 }
 
+#endif /* USE_X_TOOLKIT */
 
 \f
 /* Scroll bar support.  */
@@ -7001,6 +7402,7 @@ DEFUN ("xt-process-timeouts", Fxt_process_timeouts, Sxt_process_timeouts,
 /* Given an X window ID, find the struct scroll_bar which manages it.
    This can be called in GC, so we have to make sure to strip off mark
    bits.  */
+
 static struct scroll_bar *
 x_window_to_scroll_bar (window_id)
      Window window_id;
@@ -7009,11 +7411,11 @@ x_window_to_scroll_bar (window_id)
 
   for (tail = Vframe_list;
        XGCTYPE (tail) == Lisp_Cons;
-       tail = XCONS (tail)->cdr)
+       tail = XCDR (tail))
     {
       Lisp_Object frame, bar, condemned;
 
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       /* All elements of Vframe_list should be frames.  */
       if (! GC_FRAMEP (frame))
        abort ();
@@ -7064,9 +7466,20 @@ static Lisp_Object window_being_scrolled;
 
 static int last_scroll_bar_part;
 
+/* Whether this is an Xaw with arrow-scrollbars.  This should imply
+   that movements of 1/20 of the screen size are mapped to up/down.  */
+
+static Boolean xaw3d_arrow_scroll;
+
+/* Whether the drag scrolling maintains the mouse at the top of the
+   thumb.  If not, resizing the thumb needs to be done more carefully
+   to avoid jerkyness.  */
+
+static Boolean xaw3d_pick_top;
+
 
 /* Action hook installed via XtAppAddActionHook when toolkit scroll
-   bars are used..  The hoos is responsible for detecting when
+   bars are used..  The hook is responsible for detecting when
    the user ends an interaction with the scroll bar, and generates
    a `end-scroll' scroll_bar_click' event if so.  */
 
@@ -7086,15 +7499,11 @@ xt_action_hook (widget, client_data, action_name, event, params,
 #ifdef USE_MOTIF
   scroll_bar_p = XmIsScrollBar (widget);
   end_action = "Release";
-#elif defined HAVE_XAW3D
+#else /* !USE_MOTIF i.e. use Xaw */
   scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
   end_action = "EndScroll";
-#else
-#error unknown scroll bar toolkit
-#endif /* HAVE_XAW3D */
+#endif /* USE_MOTIF */
 
-  /* Although LessTif uses XtTimeouts like Xaw3d, the timer hack to
-     let Xt timeouts be processed doesn't work.  */
   if (scroll_bar_p
       && strcmp (action_name, end_action) == 0
       && WINDOWP (window_being_scrolled))
@@ -7107,6 +7516,9 @@ xt_action_hook (widget, client_data, action_name, event, params,
       XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
       window_being_scrolled = Qnil;
       last_scroll_bar_part = -1;
+
+      /* Xt timeouts no longer needed.  */
+      toolkit_scroll_bar_interaction = 0;
     }
 }
 
@@ -7131,12 +7543,15 @@ x_send_scroll_bar_event (window, part, portion, whole)
   ev->display = FRAME_X_DISPLAY (f);
   ev->window = FRAME_X_WINDOW (f);
   ev->format = 32;
-  ev->data.l[0] = (long) window;
+  ev->data.l[0] = (long) XFASTINT (window);
   ev->data.l[1] = (long) part;
   ev->data.l[2] = (long) 0;
   ev->data.l[3] = (long) portion;
   ev->data.l[4] = (long) whole;
 
+  /* Make Xt timeouts work while the scroll bar is active.  */
+  toolkit_scroll_bar_interaction = 1;
+
   /* Setting the event mask to zero means that the message will
      be sent to the client that created the window, and if that
      window no longer exists, no event will be sent.  */
@@ -7155,11 +7570,15 @@ x_scroll_bar_to_input_event (event, ievent)
      struct input_event *ievent;
 {
   XClientMessageEvent *ev = (XClientMessageEvent *) event;
-  Lisp_Object window = (Lisp_Object) ev->data.l[0];
-  struct frame *f = XFRAME (XWINDOW (window)->frame);
+  Lisp_Object window;
+  struct frame *f;
+
+  XSETFASTINT (window, ev->data.l[0]);
+  f = XFRAME (XWINDOW (window)->frame);
   
   ievent->kind = scroll_bar_click;
   ievent->frame_or_window = window;
+  ievent->arg = Qnil;
   ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
   ievent->part = ev->data.l[1];
   ievent->code = ev->data.l[2];
@@ -7276,40 +7695,39 @@ xm_scroll_callback (widget, client_data, call_data)
 }
 
 
-#else /* not USE_MOTIF, i.e. XAW3D.  */
+#else /* !USE_MOTIF, i.e. Xaw.  */
 
 
-/* Xaw3d scroll bar callback.  Invoked when the thumb is dragged.
+/* Xaw scroll bar callback.  Invoked when the thumb is dragged.
    WIDGET is the scroll bar widget.  CLIENT_DATA is a pointer to the
    scroll bar struct.  CALL_DATA is a pointer to a float saying where
    the thumb is.  */
 
 static void
-xaw3d_jump_callback (widget, client_data, call_data)
+xaw_jump_callback (widget, client_data, call_data)
      Widget widget;
      XtPointer client_data, call_data;
 {
   struct scroll_bar *bar = (struct scroll_bar *) client_data;
   float top = *(float *) call_data;
   float shown;
-  int whole, portion;
-  int dragging_down_p, part;
-  double epsilon = 0.01;
+  int whole, portion, height;
+  int part;
 
   /* Get the size of the thumb, a value between 0 and 1.  */
   BLOCK_INPUT;
-  XtVaGetValues (widget, XtNshown, &shown, NULL);
+  XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
   UNBLOCK_INPUT;
 
   whole = 10000000;
   portion = shown < 1 ? top * whole : 0;
-  dragging_down_p = (INTEGERP (bar->dragging)
-                    && XINT (bar->dragging) < portion);
 
-  if (shown < 1
-      && (abs (top + shown - 1) < epsilon
-         || (dragging_down_p
-             && last_scroll_bar_part == scroll_bar_down_arrow)))
+  if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
+    /* Some derivatives of Xaw refuse to shrink the thumb when you reach
+       the bottom, so we force the scrolling whenever we see that we're
+       too close to the bottom (in x_set_toolkit_scroll_bar_thumb
+       we try to ensure that we always stay two pixels away from the
+       bottom).  */
     part = scroll_bar_down_arrow;
   else
     part = scroll_bar_handle;
@@ -7321,8 +7739,8 @@ xaw3d_jump_callback (widget, client_data, call_data)
 }
 
 
-/* Xaw3d scroll bar callback.  Invoked for incremental scrolling.,
-   i.e. line or page up or down.  WIDGET is the Xaw3d scroll bar
+/* Xaw scroll bar callback.  Invoked for incremental scrolling.,
+   i.e. line or page up or down.  WIDGET is the Xaw scroll bar
    widget.  CLIENT_DATA is a pointer to the scroll_bar structure for
    the scroll bar.  CALL_DATA is an integer specifying the action that
    has taken place.  It's magnitude is in the range 0..height of the
@@ -7330,7 +7748,7 @@ xaw3d_jump_callback (widget, client_data, call_data)
    Values < height of scroll bar mean line-wise movement.  */
 
 static void
-xaw3d_scroll_callback (widget, client_data, call_data)
+xaw_scroll_callback (widget, client_data, call_data)
      Widget widget;
      XtPointer client_data, call_data;
 {
@@ -7344,25 +7762,20 @@ xaw3d_scroll_callback (widget, client_data, call_data)
   XtVaGetValues (widget, XtNheight, &height, NULL);
   UNBLOCK_INPUT;
 
-  if (position < 0)
-    {
-      if (abs (position) < height)
-       part = scroll_bar_up_arrow;
-      else
-       part = scroll_bar_above_handle;
-    }
+  if (abs (position) >= height)
+    part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
+
+  /* If Xaw3d was compiled with ARROW_SCROLLBAR,
+     it maps line-movement to call_data = max(5, height/20).  */
+  else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
+    part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
   else
-    {
-      if (abs (position) < height)
-       part = scroll_bar_down_arrow;
-      else
-       part = scroll_bar_below_handle;
-    }
+    part = scroll_bar_move_ratio;
 
   window_being_scrolled = bar->window;
   bar->dragging = Qnil;
   last_scroll_bar_part = part;
-  x_send_scroll_bar_event (bar->window, part, 0, 0);
+  x_send_scroll_bar_event (bar->window, part, position, height);
 }
 
 
@@ -7445,7 +7858,7 @@ x_create_toolkit_scroll_bar (f, bar)
   XDefineCursor (XtDisplay (widget), XtWindow (widget),
                 f->output_data.x->nontext_cursor);
   
-#elif defined HAVE_XAW3D
+#else /* !USE_MOTIF i.e. use Xaw */
   
   /* Set resources.  Create the widget.  The background of the
      Xaw3d scroll bar widget is a little bit light for my taste.
@@ -7453,8 +7866,9 @@ x_create_toolkit_scroll_bar (f, bar)
      to their taste with `emacs*verticalScrollBar.background: xxx'.  */
   XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
   XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
-  XtSetArg (av[ac], XtNcursorName, "left_ptr"); ++ac;
-  XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac;
+  /* For smoother scrolling with Xaw3d   -sm */
+  /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
+  /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
   
   pixel = f->output_data.x->scroll_bar_foreground_pixel;
   if (pixel != -1)
@@ -7472,16 +7886,29 @@ x_create_toolkit_scroll_bar (f, bar)
   
   widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
                           f->output_data.x->edit_widget, av, ac);
+
+  {
+    char *initial = "";
+    char *val = initial;
+    XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
+                  XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
+    if (val == initial)
+      {        /* ARROW_SCROLL */
+       xaw3d_arrow_scroll = True;
+       /* Isn't that just a personal preference ?   -sm */
+       XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
+      }
+  }
   
   /* Define callbacks.  */
-  XtAddCallback (widget, XtNjumpProc, xaw3d_jump_callback, (XtPointer) bar);
-  XtAddCallback (widget, XtNscrollProc, xaw3d_scroll_callback,
+  XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
+  XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
                 (XtPointer) bar);
   
   /* Realize the widget.  Only after that is the X window created.  */
   XtRealizeWidget (widget);
   
-#endif /* HAVE_XAW3D */
+#endif /* !USE_MOTIF */
 
   /* Install an action hook that let's us detect when the user
      finishes interacting with a scroll bar.  */
@@ -7506,7 +7933,6 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
      int portion, position, whole;
 {
   float top, shown;
-  Arg av[2];
   Widget widget = SCROLL_BAR_X_WIDGET (bar);
 
   if (whole == 0)
@@ -7526,7 +7952,7 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
     unsigned char flags;
     XmScrollBarWidget sb;
 
-    /* Slider size.  Must be in the range [1 .. MAX - MIN] where NAX
+    /* 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;
@@ -7554,7 +7980,7 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
       XmScrollBarSetValues (widget, value, size, 0, 0, False);
     else if (last_scroll_bar_part == scroll_bar_down_arrow)
       /* This has the negative side effect that the slider value is
-        not would it would be if we scrolled here using line-wise or
+        not what it would be if we scrolled here using line-wise or
         page-wise movement.  */
       XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
     else
@@ -7574,43 +8000,61 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
     sb->scrollBar.arrow2_selected = arrow2_selected;
     sb->scrollBar.flags = flags;
   }
-#elif defined HAVE_XAW3D
+#else /* !USE_MOTIF i.e. use Xaw */
   {
-    /* Restrict to [0 1].  */
-    top = max (0, min (1, top));
-    shown = max (0, min (1, shown));
+    float old_top, old_shown;
+    Dimension height;
+    XtVaGetValues (widget,
+                  XtNtopOfThumb, &old_top,
+                  XtNshown, &old_shown,
+                  XtNheight, &height,
+                  NULL);
+
+    /* Massage the top+shown values.  */
+    if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
+      top = max (0, min (1, top));
+    else
+      top = old_top;
+    /* Keep two pixels available for moving the thumb down.  */
+    shown = max (0, min (1 - top - (2.0 / height), shown));
 
     /* If the call to XawScrollbarSetThumb below doesn't seem to work,
        check that your system's configuration file contains a define
        for `NARROWPROTO'.  See s/freebsd.h for an example.  */
-    if (NILP (bar->dragging))
+    if (top != old_top || shown != old_shown)
       {
-       float old_top, old_shown;
-       XtVaGetValues (widget, XtNtopOfThumb, &old_top, XtNshown, &old_shown,
-                      NULL);
-       if (top != old_top || shown != old_shown)
+       if (NILP (bar->dragging))
          XawScrollbarSetThumb (widget, top, shown);
-      }
-    else
-      {
-       ScrollbarWidget sb = (ScrollbarWidget) widget;
-       int scroll_mode = sb->scrollbar.scroll_mode;
-
-       sb->scrollbar.scroll_mode = 0;
-       
-       if (last_scroll_bar_part == scroll_bar_down_arrow)
-         XawScrollbarSetThumb (widget, top, 1 - top);
        else
          {
-           float old_top;
-           XtVaGetValues (widget, XtNtopOfThumb, &old_top, NULL);
-           XawScrollbarSetThumb (widget, old_top, min (shown, 1 - old_top));
+#ifdef HAVE_XAW3D
+           ScrollbarWidget sb = (ScrollbarWidget) widget;
+           int scroll_mode = 0;
+           
+           /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR.  */
+           if (xaw3d_arrow_scroll)
+             {
+               /* Xaw3d stupidly ignores resize requests while dragging
+                  so we have to make it believe it's not in dragging mode.  */
+               scroll_mode = sb->scrollbar.scroll_mode;
+               if (scroll_mode == 2)
+                 sb->scrollbar.scroll_mode = 0;
+             }
+#endif
+           /* Try to make the scrolling a tad smoother.  */
+           if (!xaw3d_pick_top)
+             shown = min (shown, old_shown);
+           
+           XawScrollbarSetThumb (widget, top, shown);
+           
+#ifdef HAVE_XAW3D
+           if (xaw3d_arrow_scroll && scroll_mode == 2)
+             sb->scrollbar.scroll_mode = scroll_mode;
+#endif
          }
-       
-       sb->scrollbar.scroll_mode = scroll_mode;
       }
   }
-#endif /* HAVE_XAW3D */
+#endif /* !USE_MOTIF */
 
   UNBLOCK_INPUT;
 }
@@ -7634,11 +8078,6 @@ x_scroll_bar_create (w, top, left, width, height)
      int top, left, width, height;
 {
   struct frame *f = XFRAME (w->frame);
-#ifdef USE_X_TOOLKIT
-  Arg av[10];
-#endif
-  int ac = 0;
-  Window window;
   struct scroll_bar *bar
     = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
 
@@ -7650,6 +8089,7 @@ x_scroll_bar_create (w, top, left, width, height)
   {
     XSetWindowAttributes a;
     unsigned long mask;
+    Window window;
 
     a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
     if (a.background_pixel == -1)
@@ -7704,10 +8144,6 @@ x_scroll_bar_create (w, top, left, width, height)
 
   /* Map the window/widget.  */
 #if USE_TOOLKIT_SCROLL_BARS
-  XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-             left, top,
-             FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f),
-             window_box_height (w), False);
   XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
   XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
                     left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
@@ -7736,13 +8172,14 @@ x_scroll_bar_create (w, top, left, width, height)
    the bar's top is as far down as it goes; otherwise, there's no way
    to move to the very end of the buffer.  */
 
+#ifndef USE_TOOLKIT_SCROLL_BARS
+
 static void
 x_scroll_bar_set_handle (bar, start, end, rebuild)
      struct scroll_bar *bar;
      int start, end;
      int rebuild;
 {
-#ifndef USE_TOOLKIT_SCROLL_BARS
   int dragging = ! NILP (bar->dragging);
   Window w = SCROLL_BAR_X_WINDOW (bar);
   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
@@ -7834,9 +8271,9 @@ x_scroll_bar_set_handle (bar, start, end, rebuild)
   }
 
   UNBLOCK_INPUT;
-#endif /* not USE_TOOLKIT_SCROLL_BARS */
 }
 
+#endif /* !USE_TOOLKIT_SCROLL_BARS */
 
 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
    nil.  */
@@ -7845,14 +8282,15 @@ static void
 x_scroll_bar_remove (bar)
      struct scroll_bar *bar;
 {
-  FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-
   BLOCK_INPUT;
 
 #if USE_TOOLKIT_SCROLL_BARS
   XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
 #else /* not USE_TOOLKIT_SCROLL_BARS */
-  XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
+  {
+    FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+    XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
+  }
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
   
   /* Disassociate this scroll bar from its window.  */
@@ -7874,41 +8312,52 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 {
   struct frame *f = XFRAME (w->frame);
   struct scroll_bar *bar;
-  int pixel_top, pixel_left, pixel_width, pixel_height;
+  int top, height, left, sb_left, width, sb_width;
   int window_x, window_y, window_width, window_height;
-  int scroll_bar_area_width;
 
+  /* Get window dimensions.  */
   window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
-  
-  /* Where should this scroll bar be, pixel-wise?  */
-  pixel_top = window_y;
-  pixel_height = window_height;
-
-  /* The width of the scroll bar itself.  */
-  pixel_width = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
-                ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
-                : (FRAME_SCROLL_BAR_COLS (f)
-                   * FONT_WIDTH (FRAME_FONT (f))));
-
-  /* The width on the screen reserved for the scroll bar plus maybe
-     some empty room at both sides of the scroll bar.  */
-  scroll_bar_area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+  top = window_y;
+  width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+  height = window_height;
 
+  /* Compute the left edge of the scroll bar area.  */
   if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
-    pixel_left = (window_x
-                 + window_width
-                 + FRAME_FLAGS_AREA_WIDTH (f)
-                 + scroll_bar_area_width
-                 - pixel_width + 1);
+    left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
   else
-    pixel_left = (window_x
-                 - FRAME_FLAGS_AREA_WIDTH (f)
-                 - scroll_bar_area_width);
+    left = XFASTINT (w->left);
+  left *= CANON_X_UNIT (f);
+  left += FRAME_INTERNAL_BORDER_WIDTH (f);
+
+  /* Compute the width of the scroll bar which might be less than
+     the width of the area reserved for the scroll bar.  */
+  if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
+    sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
+  else
+    sb_width = width;
 
+  /* Compute the left edge of the scroll bar.  */
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+    sb_left = left + width - sb_width - (width - sb_width) / 2; 
+  else
+    sb_left = left + (width - sb_width) / 2;
+#else
+  if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+    sb_left = left + width - sb_width; 
+  else
+    sb_left = left;
+#endif
+  
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
-    bar = x_scroll_bar_create (w, pixel_top, pixel_left, pixel_width,
-                              pixel_height);
+    {
+      BLOCK_INPUT;
+      XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                 left, top, width, height, False);
+      UNBLOCK_INPUT;
+      bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
+    }
   else
     {
       /* It may just need to be moved and resized.  */
@@ -7918,13 +8367,13 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
       BLOCK_INPUT;
 
-      if (pixel_left != XINT (bar->left))
+      if (sb_left != XINT (bar->left))
        mask |= CWX;
-      if (pixel_top != XINT (bar->top))
+      if (top != XINT (bar->top))
        mask |= CWY;
-      if (pixel_width != XINT (bar->width))
+      if (sb_width != XINT (bar->width))
        mask |= CWWidth;
-      if (pixel_height != XINT (bar->height))  
+      if (height != XINT (bar->height))        
        mask |= CWHeight;
       
 #ifdef USE_TOOLKIT_SCROLL_BARS
@@ -7932,44 +8381,42 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
       /* Since toolkit scroll bars are smaller than the space reserved
         for them on the frame, we have to clear "under" them.  */
       XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 pixel_left, pixel_top,
-                 FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f),
-                 pixel_height, False);
+                 left, top, width, height, False);
 
       /* Move/size the scroll bar widget.  */
       if (mask)
        XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
-                          pixel_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                          pixel_top,
-                          pixel_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                          pixel_height, 0);
+                          sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                          top,
+                          sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+                          height, 0);
 
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   
-      /* Clear areas not covered by the scroll bar.  This makes sure a
-        previous mode line display is cleared after C-x 2 C-x 1, for
-        example.  Non-toolkit scroll bars are as wide as the area
-        reserved for scroll bars - trim at both sides.  */
-      XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 pixel_left, pixel_top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                 pixel_height, False);
-      XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 (pixel_left
-                  + pixel_width
-                  - VERTICAL_SCROLL_BAR_WIDTH_TRIM),
-                 pixel_top,
-                 VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                 pixel_height, False);
+      if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
+       {
+         /* Clear areas not covered by the scroll bar.  This makes sure a
+            previous mode line display is cleared after C-x 2 C-x 1, for
+            example.  Non-toolkit scroll bars are as wide as the area
+            reserved for scroll bars - trim at both sides.  */
+         XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                     left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                     height, False);
+         XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                     left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                     top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                     height, False);
+       }
       
       /* Move/size the scroll bar window.  */
       if (mask)
        {
          XWindowChanges wc;
          
-         wc.x = pixel_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
-         wc.y = pixel_top;
-         wc.width = pixel_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
-         wc.height = pixel_height;
+         wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+         wc.y = top;
+         wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
+         wc.height = height;
          XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
                            mask, &wc);
        }
@@ -7977,10 +8424,10 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
 
       /* Remember new settings.  */
-      XSETINT (bar->left, pixel_left);
-      XSETINT (bar->top, pixel_top);
-      XSETINT (bar->width, pixel_width);
-      XSETINT (bar->height, pixel_height);
+      XSETINT (bar->left, sb_left);
+      XSETINT (bar->top, top);
+      XSETINT (bar->width, sb_width);
+      XSETINT (bar->height, height);
       
       UNBLOCK_INPUT;
     }
@@ -7992,7 +8439,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
      dragged.  */
   if (NILP (bar->dragging))
     {
-      int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, pixel_height);
+      int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
 
       if (whole == 0)
        x_scroll_bar_set_handle (bar, 0, top_range, 0);
@@ -8157,6 +8604,8 @@ 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)
      struct scroll_bar *bar;
@@ -8176,6 +8625,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
          ? up_modifier
          : down_modifier));
   emacs_event->frame_or_window = bar->window;
+  emacs_event->arg = Qnil;
   emacs_event->timestamp = event->xbutton.time;
   {
 #if 0
@@ -8267,6 +8717,8 @@ x_scroll_bar_note_movement (bar, event)
     }
 }
 
+#endif /* !USE_TOOLKIT_SCROLL_BARS */
+
 /* Return information to the user about the current position of the mouse
    on the scroll bar.  */
 
@@ -8529,6 +8981,7 @@ static struct x_display_info *next_noop_dpyinfo;
            {                                                           \
              bufp->kind = menu_bar_activate_event;                     \
              XSETFRAME (bufp->frame_or_window, f);                     \
+             bufp->arg = Qnil;                                         \
              bufp++;                                                   \
              count++;                                                  \
              numchars--;                                               \
@@ -8563,9 +9016,6 @@ XTread_socket (sd, bufp, numchars, expected)
   struct frame *f;
   int event_found = 0;
   struct x_display_info *dpyinfo;
-#ifdef HAVE_X_I18N
-  Status status_return;
-#endif
 
   if (interrupt_input_blocked)
     {
@@ -8582,6 +9032,8 @@ XTread_socket (sd, bufp, numchars, expected)
   if (numchars <= 0)
     abort ();                  /* Don't think this happens.  */
 
+  ++handling_signal;
+  
   /* Find the display we are supposed to read input for.
      It's the one communicating on descriptor SD.  */
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
@@ -8624,28 +9076,16 @@ XTread_socket (sd, bufp, numchars, expected)
        {
          XNextEvent (dpyinfo->display, &event);
 
-         if (display_busy_cursor_p)
-           {
-             /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor
-                display until the next X event is read and we come
-                here again.  Setting it to 1 inhibits busy-cursor
-                display for direct commands.  */
-             if (event.type == MotionNotify
-                 || event.type == EnterNotify
-                 || (dpyinfo->grabbed
-                     && event.type != ButtonRelease))
-               inhibit_busy_cursor = 2;
-             else
-               inhibit_busy_cursor = 1;
-           }
-
 #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);
-           /* The necessity of the following line took me
-              a full work-day to decipher from the docs!!  */
-           if (f1 != 0 && FRAME_XIC (f1) && XFilterEvent (&event, None))
+           if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
              break;
          }
 #endif
@@ -8671,6 +9111,19 @@ XTread_socket (sd, bufp, numchars, expected)
                        if (f && FRAME_XIC (f))
                          XSetICFocus (FRAME_XIC (f));
 #endif
+#if 0 /* Emacs sets WM hints whose `input' field is `true'.  This
+        instructs the WM to set the input focus automatically for
+        Emacs with a call to XSetInputFocus.  Setting WM_TAKE_FOCUS
+        tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
+        it has set the focus.  So, XSetInputFocus below is not
+        needed.
+
+        The call to XSetInputFocus below has also caused trouble.  In
+        cases where the XSetInputFocus done by the WM and the one
+        below are temporally close (on a fast machine), the call
+        below can generate additional FocusIn events which confuse
+        Emacs.  */
+                       
                        /* Since we set WM_TAKE_FOCUS, we must call
                           XSetInputFocus explicitly.  But not if f is null,
                           since that might be an event for a deleted frame.  */
@@ -8681,7 +9134,9 @@ XTread_socket (sd, bufp, numchars, expected)
                               iconified by a window manager such as GWM.  */
                            int count = x_catch_errors (d);
                            XSetInputFocus (d, event.xclient.window,
-                                           RevertToPointerRoot,
+                                           /* The ICCCM says this is
+                                              the only valid choice.  */
+                                           RevertToParent,
                                            event.xclient.data.l[1]);
                            /* This is needed to detect the error
                               if there is an error.  */
@@ -8689,6 +9144,7 @@ XTread_socket (sd, bufp, numchars, expected)
                            x_uncatch_errors (d, count);
                          }  
                        /* Not certain about handling scroll bars here */
+#endif /* 0 */
                      }
                    else if (event.xclient.data.l[0]
                             == dpyinfo->Xatom_wm_save_yourself)
@@ -8705,7 +9161,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                            /* This is just so we only give real data once
                               for a single Emacs process.  */
-                           if (f == selected_frame)
+                           if (f == SELECTED_FRAME ())
                              XSetCommand (FRAME_X_DISPLAY (f),
                                           event.xclient.window,
                                           initial_argv, initial_argc);
@@ -8729,6 +9185,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                            bufp->kind = delete_window_event;
                            XSETFRAME (bufp->frame_or_window, f);
+                           bufp->arg = Qnil;
                            bufp++;
 
                            count += 1;
@@ -8775,7 +9232,6 @@ XTread_socket (sd, bufp, numchars, expected)
                       reply with "Next" if we received "Page", but we
                       currently never do because we are interested in
                       images, only, which should have 1 page.  */
-                   Window gs_window = (Window) event.xclient.data.l[0];
                    Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
                    struct frame *f
                      = x_window_to_frame (dpyinfo, event.xclient.window);
@@ -8822,6 +9278,7 @@ XTread_socket (sd, bufp, numchars, expected)
                SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
                SELECTION_EVENT_TIME (bufp) = eventp->time;
                bufp->frame_or_window = Qnil;
+               bufp->arg = Qnil;
                bufp++;
 
                count += 1;
@@ -8852,6 +9309,7 @@ XTread_socket (sd, bufp, numchars, expected)
                  SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
                  SELECTION_EVENT_TIME (bufp) = eventp->time;
                  bufp->frame_or_window = Qnil;
+                 bufp->arg = Qnil;
                  bufp++;
 
                  count += 1;
@@ -8965,6 +9423,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                      bufp->kind = iconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
@@ -8996,12 +9455,13 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      bufp->kind = deiconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
                    }
                  else if (! NILP (Vframe_list)
-                          && ! NILP (XCONS (Vframe_list)->cdr))
+                          && ! NILP (XCDR (Vframe_list)))
                    /* Force a redisplay sooner or later
                       to update the frame titles
                       in case this is the second frame.  */
@@ -9061,18 +9521,31 @@ XTread_socket (sd, bufp, numchars, expected)
 #ifdef HAVE_X_I18N
                  if (FRAME_XIC (f))
                    {
-                     /* The necessity of the following line took me
-                        a full work-day to decipher from the docs!!  */
-                     if (XFilterEvent (&event, None))
-                       break;
+                     unsigned char *copy_bufptr = copy_buffer;
+                     int copy_bufsiz = sizeof (copy_buffer);
+                     Status status_return;
+
                      nbytes = XmbLookupString (FRAME_XIC (f),
-                                               &event.xkey, copy_buffer,
-                                               80, &keysym,
+                                               &event.xkey, copy_bufptr,
+                                               copy_bufsiz, &keysym,
                                                &status_return);
+                     if (status_return == XBufferOverflow)
+                       {
+                         copy_bufsiz = nbytes + 1;
+                         copy_bufptr = (char *) alloca (copy_bufsiz);
+                         nbytes = XmbLookupString (FRAME_XIC (f),
+                                                   &event.xkey, copy_bufptr,
+                                                   copy_bufsiz, &keysym,
+                                                   &status_return);
+                       }
+
                      if (status_return == XLookupNone)
                        break;
                      else if (status_return == XLookupChars)
-                       keysym = NoSymbol;
+                       {
+                         keysym = NoSymbol;
+                         modifiers = 0;
+                       }
                      else if (status_return != XLookupKeySym
                               && status_return != XLookupBoth)
                        abort ();
@@ -9165,6 +9638,7 @@ XTread_socket (sd, bufp, numchars, expected)
                          bufp->kind = non_ascii_keystroke;
                          bufp->code = keysym;
                          XSETFRAME (bufp->frame_or_window, f);
+                         bufp->arg = Qnil;
                          bufp->modifiers
                            = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
                                                      modifiers);
@@ -9172,10 +9646,6 @@ XTread_socket (sd, bufp, numchars, expected)
                          bufp++;
                          count++;
                          numchars--;
-                         
-                         if (display_busy_cursor_p)
-                           if (keysym != XK_Return || minibuf_level == 0)
-                             inhibit_busy_cursor = 2;
                        }
                      else if (numchars > nbytes)
                        {
@@ -9189,6 +9659,7 @@ XTread_socket (sd, bufp, numchars, expected)
                              bufp->kind = ascii_keystroke;
                              bufp->code = copy_buffer[i];
                              XSETFRAME (bufp->frame_or_window, f);
+                             bufp->arg = Qnil;
                              bufp->modifiers
                                = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
                                                          modifiers);
@@ -9208,7 +9679,24 @@ XTread_socket (sd, bufp, numchars, expected)
                  else
                    abort ();
                }
+#ifdef HAVE_X_I18N
+             /* Don't dispatch this event since XtDispatchEvent calls
+                XFilterEvent, and two calls in a row may freeze the
+                client.  */
+             break;
+#else
+             goto OTHER;
+#endif
+
+           case KeyRelease:
+#ifdef HAVE_X_I18N
+             /* Don't dispatch this event since XtDispatchEvent calls
+                XFilterEvent, and two calls in a row may freeze the
+                client.  */
+             break;
+#else
              goto OTHER;
+#endif
 
              /* Here's a possible interpretation of the whole
                 FocusIn-EnterNotify FocusOut-LeaveNotify mess.  If
@@ -9279,7 +9767,21 @@ XTread_socket (sd, bufp, numchars, expected)
              if (event.xfocus.detail != NotifyPointer)
                dpyinfo->x_focus_event_frame = f;
              if (f)
-               x_new_focus_frame (dpyinfo, f);
+               {
+                 x_new_focus_frame (dpyinfo, f);
+
+                 /* Don't stop displaying the initial startup message
+                    for a switch-frame event we don't need.  */
+                 if (GC_NILP (Vterminal_frame)
+                     && GC_CONSP (Vframe_list)
+                     && !GC_NILP (XCDR (Vframe_list)))
+                   {
+                     bufp->kind = FOCUS_IN_EVENT;
+                     XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
+                     ++bufp, ++count, --numchars;
+                   }
+               }
 
 #ifdef HAVE_X_I18N
              if (f && FRAME_XIC (f))
@@ -9309,10 +9811,12 @@ XTread_socket (sd, bufp, numchars, expected)
                     the mouse leaves the frame.  */
                  if (any_help_event_p)
                    {
+                     Lisp_Object frame;
+                     int n;
+
                      XSETFRAME (frame, f);
-                     bufp->kind = HELP_EVENT;
-                     bufp->frame_or_window = Fcons (frame, Qnil);
-                     ++bufp, ++count, --numchars;
+                     n = gen_help_event (bufp, Qnil, frame, Qnil, Qnil, 0);
+                     bufp += n, count += n, numchars -= n;
                    }
 
 #ifdef LESSTIF_VERSION
@@ -9359,7 +9863,8 @@ XTread_socket (sd, bufp, numchars, expected)
            case MotionNotify:
              {
                previous_help_echo = help_echo;
-               help_echo = Qnil;
+               help_echo = help_echo_object = help_echo_window = Qnil;
+               help_echo_pos = -1;
                
                if (dpyinfo->grabbed && last_mouse_frame
                    && FRAME_LIVE_P (last_mouse_frame))
@@ -9371,13 +9876,13 @@ XTread_socket (sd, bufp, numchars, expected)
                  note_mouse_movement (f, &event.xmotion);
                else
                  {
-#ifndef USE_X_TOOLKIT
+#ifndef USE_TOOLKIT_SCROLL_BARS
                    struct scroll_bar *bar
                      = x_window_to_scroll_bar (event.xmotion.window);
 
                    if (bar)
                      x_scroll_bar_note_movement (bar, &event);
-#endif /* USE_X_TOOLKIT */
+#endif /* USE_TOOLKIT_SCROLL_BARS */
 
                    /* If we move outside the frame, then we're
                       certainly no longer on any text in the frame.  */
@@ -9386,10 +9891,11 @@ XTread_socket (sd, bufp, numchars, expected)
 
                /* If the contents of the global variable help_echo
                   has changed, generate a HELP_EVENT.  */
-               if (STRINGP (help_echo)
-                   || STRINGP (previous_help_echo))
+               if (!NILP (help_echo)
+                   || !NILP (previous_help_echo))
                  {
                    Lisp_Object frame;
+                   int n;
 
                    if (f)
                      XSETFRAME (frame, f);
@@ -9397,9 +9903,10 @@ XTread_socket (sd, bufp, numchars, expected)
                      frame = Qnil;
 
                    any_help_event_p = 1;
-                   bufp->kind = HELP_EVENT;
-                   bufp->frame_or_window = Fcons (frame, help_echo);
-                   ++bufp, ++count, --numchars;
+                   n = gen_help_event (bufp, help_echo, frame,
+                                       help_echo_window, help_echo_object,
+                                       help_echo_pos);
+                   bufp += n, count += n, numchars -= n;
                  }
                
                goto OTHER;
@@ -9409,10 +9916,10 @@ XTread_socket (sd, bufp, numchars, expected)
              f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
              if (f)
                {
+#ifndef USE_X_TOOLKIT
                  int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
                  int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
-
-#ifndef USE_X_TOOLKIT
+                 
                  /* In the toolkit version, change_frame_size
                     is called by the code that handles resizing
                     of the EmacsFrame widget.  */
@@ -9439,6 +9946,11 @@ XTread_socket (sd, bufp, numchars, expected)
                  x_real_positions (f, &f->output_data.x->left_pos,
                                    &f->output_data.x->top_pos);
 
+#ifdef HAVE_X_I18N
+                 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
+                   xic_set_statusarea (f);
+#endif
+
                  if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
                    {
                      /* Since the WM decorations come below top_pos now,
@@ -9465,7 +9977,7 @@ XTread_socket (sd, bufp, numchars, expected)
                /* If we decide we want to generate an event to be seen
                   by the rest of Emacs, we put it here.  */
                struct input_event emacs_event;
-               int toolbar_p = 0;
+               int tool_bar_p = 0;
                
                emacs_event.kind = no_event;
                bzero (&compose_status, sizeof (compose_status));
@@ -9479,9 +9991,9 @@ XTread_socket (sd, bufp, numchars, expected)
 
                if (f)
                  {
-                   /* Is this in the toolbar?  */
-                   if (WINDOWP (f->toolbar_window)
-                       && XFASTINT (XWINDOW (f->toolbar_window)->height))
+                   /* Is this in the tool-bar?  */
+                   if (WINDOWP (f->tool_bar_window)
+                       && XFASTINT (XWINDOW (f->tool_bar_window)->height))
                      {
                        Lisp_Object window;
                        int p, x, y;
@@ -9491,14 +10003,14 @@ XTread_socket (sd, bufp, numchars, expected)
 
                        /* Set x and y.  */
                        window = window_from_coordinates (f, x, y, &p, 1);
-                       if (EQ (window, f->toolbar_window))
+                       if (EQ (window, f->tool_bar_window))
                          {
-                           x_handle_toolbar_click (f, &event.xbutton);
-                           toolbar_p = 1;
+                           x_handle_tool_bar_click (f, &event.xbutton);
+                           tool_bar_p = 1;
                          }
                      }
 
-                   if (!toolbar_p)
+                   if (!tool_bar_p)
                      if (!dpyinfo->x_focus_frame
                          || f == dpyinfo->x_focus_frame)
                        construct_mouse_click (&emacs_event, &event, f);
@@ -9525,10 +10037,8 @@ XTread_socket (sd, bufp, numchars, expected)
                    if (f != 0)
                      f->mouse_moved = 0;
                    
-                   if (!toolbar_p)
-                     last_toolbar_item = -1;
-                   if (display_busy_cursor_p)
-                     inhibit_busy_cursor = 2;
+                   if (!tool_bar_p)
+                     last_tool_bar_item = -1;
                  }
                else
                  {
@@ -9656,6 +10166,7 @@ XTread_socket (sd, bufp, numchars, expected)
     }
 
   UNBLOCK_INPUT;
+  --handling_signal;
   return count;
 }
 
@@ -9717,8 +10228,8 @@ x_clip_to_row (w, row, gc, whole_line_p)
      the rectangle to the left and increase its width.  */
   if (whole_line_p)
     {
-      clip_rect.x -= FRAME_X_FLAGS_AREA_WIDTH (f);
-      clip_rect.width += 2 * FRAME_X_FLAGS_AREA_WIDTH (f);
+      clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
+      clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
     }
 
   XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
@@ -9787,9 +10298,10 @@ x_draw_hollow_cursor (w, row)
    --gerd.  */
 
 static void
-x_draw_bar_cursor (w, row)
+x_draw_bar_cursor (w, row, width)
      struct window *w;
      struct glyph_row *row;
+     int width;
 {
   /* If cursor hpos is out of bounds, don't draw garbage.  This can
      happen in mini-buffer windows when switching between echo area
@@ -9825,13 +10337,15 @@ x_draw_bar_cursor (w, row)
          FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
        }
 
+      if (width < 0)
+       width = f->output_data.x->cursor_width;
+
       x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
       x_clip_to_row (w, row, gc, 0);
       XFillRectangle (dpy, window, gc,
                      x,
                      WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-                     min (cursor_glyph->pixel_width,
-                          f->output_data.x->cursor_width),
+                     min (cursor_glyph->pixel_width, width),
                      row->height);
       XSetClipMask (dpy, gc, None);
     }
@@ -9928,7 +10442,8 @@ x_erase_phys_cursor (w)
         
   /* If the cursor is in the mouse face area, redisplay that when
      we clear the cursor.  */
-  if (w == XWINDOW (dpyinfo->mouse_face_window)
+  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))
@@ -9945,7 +10460,7 @@ x_erase_phys_cursor (w)
   if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
     {
       int x;
-      int top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
+      int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
 
       cursor_glyph = get_phys_cursor_glyph (w);
       if (cursor_glyph == NULL)
@@ -9955,7 +10470,7 @@ x_erase_phys_cursor (w)
       
       XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                  x,
-                 WINDOW_TO_FRAME_PIXEL_Y (w, max (top_line_height,
+                 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
                                                   cursor_row->y)),
                  cursor_glyph->pixel_width,
                  cursor_row->visible_height,
@@ -9988,6 +10503,7 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
 {
   struct frame *f = XFRAME (w->frame);
   int new_cursor_type;
+  int new_cursor_width;
   struct glyph_matrix *current_glyphs;
   struct glyph_row *glyph_row;
   struct glyph *glyph;
@@ -10026,6 +10542,7 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
      the cursor type given by the frame parameter.  If explicitly
      marked off, draw no cursor.  In all other cases, we want a hollow
      box cursor.  */
+  new_cursor_width = -1;
   if (cursor_in_echo_area
       && FRAME_HAS_MINIBUF_P (f)
       && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
@@ -10040,7 +10557,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       if (w != XWINDOW (selected_window)
          || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
        {
-         if (MINI_WINDOW_P (w))
+         extern int cursor_in_non_selected_windows;
+         
+         if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
            new_cursor_type = NO_CURSOR;
          else
            new_cursor_type = HOLLOW_BOX_CURSOR;
@@ -10048,7 +10567,15 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       else if (w->cursor_off_p)
        new_cursor_type = NO_CURSOR;
       else
-       new_cursor_type = FRAME_DESIRED_CURSOR (f);
+       {
+         struct buffer *b = XBUFFER (w->buffer);
+
+         if (EQ (b->cursor_type, Qt))
+           new_cursor_type = FRAME_DESIRED_CURSOR (f);
+         else
+           new_cursor_type = x_specified_cursor_type (b->cursor_type, 
+                                                      &new_cursor_width);
+       }
     }
 
   /* If cursor is currently being shown and we don't want it to be or
@@ -10088,7 +10615,7 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
          break;
 
        case BAR_CURSOR:
-         x_draw_bar_cursor (w, glyph_row);
+         x_draw_bar_cursor (w, glyph_row, new_cursor_width);
          break;
 
        case NO_CURSOR:
@@ -10097,6 +10624,12 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
        default:
          abort ();
        }
+      
+#ifdef HAVE_X_I18N
+      if (w == XWINDOW (f->selected_window))
+       if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
+         xic_set_preeditarea (w, x, y);
+#endif
     }
 
 #ifndef XFlush
@@ -10164,10 +10697,15 @@ x_update_window_cursor (w, on)
      struct window *w;
      int on;
 {
-  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;
+  /* 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;
+    }
 }
 
 
@@ -10420,11 +10958,14 @@ x_connection_closed (display, error_message)
 
   /* Indicate that this display is dead.  */
 
+#if 0 /* Closing the display caused a bus error on OpenWindows.  */
 #ifdef USE_X_TOOLKIT
   XtCloseDisplay (display);
+#endif
 #endif
 
-  dpyinfo->display = 0;
+  if (dpyinfo)
+    dpyinfo->display = 0;
 
   /* First delete frames whose mini-buffers are on frames
      that are on the dead display.  */
@@ -10537,14 +11078,13 @@ x_new_font (f, fontname)
      register char *fontname;
 {
   struct font_info *fontp
-    = fs_load_font (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII, fontname, -1);
+    = FS_LOAD_FONT (f, 0, fontname, -1);
 
   if (!fontp)
     return Qnil;
 
   f->output_data.x->font = (XFontStruct *) (fontp->font);
-  f->output_data.x->font_baseline
-    = (f->output_data.x->font->ascent + fontp->baseline_offset);
+  f->output_data.x->baseline_offset = fontp->baseline_offset;
   f->output_data.x->fontset = -1;
   
   /* Compute the scroll bar width in character columns.  */
@@ -10590,8 +11130,7 @@ x_new_fontset (f, fontsetname)
      struct frame *f;
      char *fontsetname;
 {
-  int fontset = fs_query_fontset (f, fontsetname);
-  struct fontset_info *fontsetp;
+  int fontset = fs_query_fontset (build_string (fontsetname), 0);
   Lisp_Object result;
 
   if (fontset < 0)
@@ -10600,15 +11139,9 @@ x_new_fontset (f, fontsetname)
   if (f->output_data.x->fontset == fontset)
     /* This fontset is already set in frame F.  There's nothing more
        to do.  */
-    return build_string (fontsetname);
-
-  fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
+    return fontset_name (fontset);
 
-  if (!fontsetp->fontname[CHARSET_ASCII])
-    /* This fontset doesn't contain ASCII font.  */
-    return Qnil;
-
-  result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
+  result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
@@ -10616,11 +11149,220 @@ x_new_fontset (f, fontsetname)
 
   /* Since x_new_font doesn't update any fontset information, do it now.  */
   f->output_data.x->fontset = fontset;
-  FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
-               CHARSET_ASCII, fontsetp->fontname[CHARSET_ASCII], fontset);
 
+#ifdef HAVE_X_I18N
+  if (FRAME_XIC (f)
+      && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
+    xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
+#endif
+  
   return build_string (fontsetname);
 }
+
+\f
+/***********************************************************************
+                          X Input Methods
+ ***********************************************************************/
+
+#ifdef HAVE_X_I18N
+
+#ifdef HAVE_X11R6
+
+/* XIM destroy callback function, which is called whenever the
+   connection to input method XIM dies.  CLIENT_DATA contains a
+   pointer to the x_display_info structure corresponding to XIM.  */
+
+static void
+xim_destroy_callback (xim, client_data, call_data)
+     XIM xim;
+     XPointer client_data;
+     XPointer call_data;
+{
+  struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
+  Lisp_Object frame, tail;
+  
+  BLOCK_INPUT;
+  
+  /* No need to call XDestroyIC.. */
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
+      if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
+       {
+         FRAME_XIC (f) = NULL;
+         if (FRAME_XIC_FONTSET (f))
+           {
+             XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
+             FRAME_XIC_FONTSET (f) = NULL;
+           }
+       }
+    }
+  
+  /* No need to call XCloseIM.  */
+  dpyinfo->xim = NULL;
+  XFree (dpyinfo->xim_styles);
+  UNBLOCK_INPUT;
+}
+
+#endif /* HAVE_X11R6 */
+
+/* Open the connection to the XIM server on display DPYINFO.
+   RESOURCE_NAME is the resource name Emacs uses.  */
+
+static void
+xim_open_dpy (dpyinfo, resource_name)
+     struct x_display_info *dpyinfo;
+     char *resource_name;
+{
+#ifdef USE_XIM
+  XIM xim;
+
+  xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
+  dpyinfo->xim = xim;
+
+  if (xim)
+    {
+#ifdef HAVE_X11R6
+      XIMCallback destroy;
+#endif
+      
+      /* Get supported styles and XIM values.  */
+      XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
+      
+#ifdef HAVE_X11R6
+      destroy.callback = xim_destroy_callback;
+      destroy.client_data = (XPointer)dpyinfo;
+      /* This isn't prptotyped in OSF 5.0.  */
+      XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
+#endif
+    }
+  
+#else /* not USE_XIM */
+  dpyinfo->xim = NULL;
+#endif /* not USE_XIM */
+}
+
+
+#ifdef HAVE_X11R6_XIM
+
+struct xim_inst_t
+{
+  struct x_display_info *dpyinfo;
+  char *resource_name;
+};
+
+/* XIM instantiate callback function, which is called whenever an XIM
+   server is available.  DISPLAY is teh display of the XIM.
+   CLIENT_DATA contains a pointer to an xim_inst_t structure created
+   when the callback was registered.  */
+
+static void
+xim_instantiate_callback (display, client_data, call_data)
+     Display *display;
+     XPointer client_data;
+     XPointer call_data;
+{
+  struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
+  struct x_display_info *dpyinfo = xim_inst->dpyinfo;
+
+  /* We don't support multiple XIM connections. */
+  if (dpyinfo->xim)
+    return;
+  
+  xim_open_dpy (dpyinfo, xim_inst->resource_name);
+
+  /* Create XIC for the existing frames on the same display, as long
+     as they have no XIC.  */
+  if (dpyinfo->xim && dpyinfo->reference_count > 0)
+    {
+      Lisp_Object tail, frame;
+
+      BLOCK_INPUT;
+      FOR_EACH_FRAME (tail, frame)
+       {
+         struct frame *f = XFRAME (frame);
+         
+         if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
+           if (FRAME_XIC (f) == NULL)
+             {
+               create_frame_xic (f);
+               if (FRAME_XIC_STYLE (f) & XIMStatusArea)
+                 xic_set_statusarea (f);
+               if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
+                 {
+                   struct window *w = XWINDOW (f->selected_window);
+                   xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
+                 }
+             }
+       }
+      
+      UNBLOCK_INPUT;
+    }
+}
+
+#endif /* HAVE_X11R6_XIM */
+
+
+/* Open a connection to the XIM server on display DPYINFO.
+   RESOURCE_NAME is the resource name for Emacs.  On X11R5, open the
+   connection only at the first time.  On X11R6, open the connection
+   in the XIM instantiate callback function.  */
+
+static void
+xim_initialize (dpyinfo, resource_name)
+     struct x_display_info *dpyinfo;
+     char *resource_name;
+{
+#ifdef USE_XIM
+#ifdef HAVE_X11R6_XIM
+  struct xim_inst_t *xim_inst;
+  int len;
+  
+  dpyinfo->xim = NULL;
+  xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
+  xim_inst->dpyinfo = dpyinfo;
+  len = strlen (resource_name);
+  xim_inst->resource_name = (char *) xmalloc (len + 1);
+  bcopy (resource_name, xim_inst->resource_name, len + 1);
+  XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
+                                 resource_name, EMACS_CLASS,
+                                 xim_instantiate_callback,
+                                 /* Fixme: This is XPointer in
+                                    XFree86 but (XPointer *) on
+                                    Tru64, at least.  */
+                                 (XPointer) xim_inst);
+#else /* not HAVE_X11R6_XIM */
+  dpyinfo->xim = NULL;
+  xim_open_dpy (dpyinfo, resource_name);
+#endif /* not HAVE_X11R6_XIM */
+  
+#else /* not USE_XIM */
+  dpyinfo->xim = NULL;
+#endif /* not USE_XIM */
+}
+
+
+/* Close the connection to the XIM server on display DPYINFO. */
+
+static void
+xim_close_dpy (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+#ifdef USE_XIM
+#ifdef HAVE_X11R6_XIM
+  XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
+                                   NULL, EMACS_CLASS,
+                                   xim_instantiate_callback, NULL);
+#endif /* not HAVE_X11R6_XIM */
+  XCloseIM (dpyinfo->xim);
+  dpyinfo->xim = NULL;
+  XFree (dpyinfo->xim_styles);
+#endif /* USE_XIM */
+}
+
+#endif /* not HAVE_X11R6_XIM */
+
+
 \f
 /* Calculate the absolute position in frame F
    from its current recorded position values and gravity.  */
@@ -10672,7 +11414,7 @@ x_calc_absolute_position (f)
            {
              Window newroot, newparent = 0xdeadbeef;
              Window *newchildren;
-             int nchildren;
+             unsigned int nchildren;
 
              if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
                                &newparent, &newchildren, &nchildren))
@@ -10816,7 +11558,7 @@ x_set_window_size (f, change_gravity, cols, rows)
        ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
   f->output_data.x->flags_areas_extra
-    = 2 * FRAME_FLAGS_AREA_WIDTH (f);
+    = FRAME_FLAGS_AREA_WIDTH (f);
   pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
   pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
 
@@ -11041,7 +11783,7 @@ x_make_frame_visible (f)
      so that incoming events are handled.  */
   {
     Lisp_Object frame;
-    int count = input_signal_count;
+    int count;
     /* This must be before UNBLOCK_INPUT
        since events that arrive in response to the actions above
        will set it when they are handled.  */
@@ -11093,37 +11835,36 @@ x_make_frame_visible (f)
 
     XSETFRAME (frame, f);
 
-    while (1)
+    /* Wait until the frame is visible.  Process X events until a
+       MapNotify event has been seen, or until we think we won't get a
+       MapNotify at all..  */
+    for (count = input_signal_count + 10;
+        input_signal_count < count && !FRAME_VISIBLE_P (f);)
       {
+       /* Force processing of queued events.  */
        x_sync (f);
-       /* Once we have handled input events,
-          we should have received the MapNotify if one is coming.
-          So if we have not got it yet, stop looping.
-          Some window managers make their own decisions
-          about visibility.  */
-       if (input_signal_count != count)
-         break;
-       /* Machines that do polling rather than SIGIO have been observed
-          to go into a busy-wait here.  So we'll fake an alarm signal
-          to let the handler know that there's something to be read.
-          We used to raise a real alarm, but it seems that the handler
-          isn't always enabled here.  This is probably a bug.  */
+
+       /* Machines that do polling rather than SIGIO have been
+          observed to go into a busy-wait here.  So we'll fake an
+          alarm signal to let the handler know that there's something
+          to be read.  We used to raise a real alarm, but it seems
+          that the handler isn't always enabled here.  This is
+          probably a bug.  */
        if (input_polling_used ())
          {
-           /* It could be confusing if a real alarm arrives while processing
-              the fake one.  Turn it off and let the handler reset it.  */
-           alarm (0);
-           input_poll_signal (0);
+           /* It could be confusing if a real alarm arrives while
+              processing the fake one.  Turn it off and let the
+              handler reset it.  */
+           extern void poll_for_input_1 P_ ((void));
+           int old_poll_suppress_count = poll_suppress_count;
+           poll_suppress_count = 1;
+           poll_for_input_1 ();
+           poll_suppress_count = old_poll_suppress_count;
          }
-       /* Once we have handled input events,
-          we should have received the MapNotify if one is coming.
-          So if we have not got it yet, stop looping.
-          Some window managers make their own decisions
-          about visibility.  */
-       if (input_signal_count != count)
-         break;
+
+       /* See if a MapNotify event has been processed.  */
+       FRAME_SAMPLE_VISIBILITY (f);
       }
-    FRAME_SAMPLE_VISIBILITY (f);
   }
 }
 
@@ -11336,16 +12077,8 @@ x_destroy_window (f)
       if (f->output_data.x->icon_desc != 0)
        XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
 #ifdef HAVE_X_I18N
-      if (FRAME_XIM (f))
-       {
-         XDestroyIC (FRAME_XIC (f));
-#if ! defined (SOLARIS2) || defined (HAVE_X11R6)
-         /* This line causes crashes on Solaris with Openwin,
-            due to an apparent bug in XCloseIM.
-            X11R6 seems not to have the bug.  */
-         XCloseIM (FRAME_XIM (f));
-#endif
-       }
+      if (FRAME_XIC (f))
+       free_frame_xic (f);
 #endif
       XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
 #ifdef USE_X_TOOLKIT
@@ -11354,6 +12087,21 @@ x_destroy_window (f)
       free_frame_menubar (f);
 #endif /* USE_X_TOOLKIT */
 
+      unload_color (f, f->output_data.x->foreground_pixel);
+      unload_color (f, f->output_data.x->background_pixel);
+      unload_color (f, f->output_data.x->cursor_pixel);
+      unload_color (f, f->output_data.x->cursor_foreground_pixel);
+      unload_color (f, f->output_data.x->border_pixel);
+      unload_color (f, f->output_data.x->mouse_pixel);
+      if (f->output_data.x->scroll_bar_background_pixel != -1)
+       unload_color (f, f->output_data.x->scroll_bar_background_pixel);
+      if (f->output_data.x->scroll_bar_foreground_pixel != -1)
+       unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
+      if (f->output_data.x->white_relief.allocated_p)
+       unload_color (f, f->output_data.x->white_relief.pixel);
+      if (f->output_data.x->black_relief.allocated_p)
+       unload_color (f, f->output_data.x->black_relief.pixel);
+      
       free_frame_faces (f);
       XFlush (FRAME_X_DISPLAY (f));
     }
@@ -11668,17 +12416,17 @@ x_list_fonts (f, pattern, size, maxnames)
     /* We can return any single font matching PATTERN.  */
     try_XLoadQueryFont = 1;
 
-  for (; CONSP (patterns); patterns = XCONS (patterns)->cdr)
+  for (; CONSP (patterns); patterns = XCDR (patterns))
     {
       int num_fonts;
-      char **names;
+      char **names = NULL;
 
-      pattern = XCONS (patterns)->car;
+      pattern = XCAR (patterns);
       /* See if we cached the result for this particular query.
          The cache is an alist of the form:
           (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
       */
-      if (f && (tem = XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr,
+      if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
                key = Fcons (pattern, make_number (maxnames)),
                !NILP (list = Fassoc (key, tem))))
        {
@@ -11804,30 +12552,30 @@ x_list_fonts (f, pattern, size, maxnames)
 
       /* Now store the result in the cache.  */
       if (f != NULL)
-       XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr
+       XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
          = Fcons (Fcons (key, list),
-                  XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
+                  XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
 
     label_cached:
       if (NILP (list)) continue; /* Try the remaining alternatives.  */
 
       newlist = second_best = Qnil;
       /* Make a list of the fonts that have the right width.  */
-      for (; CONSP (list); list = XCONS (list)->cdr)
+      for (; CONSP (list); list = XCDR (list))
        {
          int found_size;
 
-         tem = XCONS (list)->car;
+         tem = XCAR (list);
 
-         if (!CONSP (tem) || NILP (XCONS (tem)->car))
+         if (!CONSP (tem) || NILP (XCAR (tem)))
            continue;
          if (!size)
            {
-             newlist = Fcons (XCONS (tem)->car, newlist);
+             newlist = Fcons (XCAR (tem), newlist);
              continue;
            }
 
-         if (!INTEGERP (XCONS (tem)->cdr))
+         if (!INTEGERP (XCDR (tem)))
            {
              /* Since we have not yet known the size of this font, we
                must try slow function call XLoadQueryFont.  */
@@ -11836,7 +12584,7 @@ x_list_fonts (f, pattern, size, maxnames)
              BLOCK_INPUT;
              count = x_catch_errors (dpy);
              thisinfo = XLoadQueryFont (dpy,
-                                        XSTRING (XCONS (tem)->car)->data);
+                                        XSTRING (XCAR (tem))->data);
              if (x_had_errors_p (dpy))
                {
                  /* This error is perhaps due to insufficient memory on X
@@ -11849,7 +12597,7 @@ x_list_fonts (f, pattern, size, maxnames)
 
              if (thisinfo)
                {
-                 XCONS (tem)->cdr
+                 XCDR (tem)
                    = (thisinfo->min_bounds.width == 0
                       ? make_number (0)
                       : make_number (thisinfo->max_bounds.width));
@@ -11859,26 +12607,26 @@ x_list_fonts (f, pattern, size, maxnames)
                /* For unknown reason, the previous call of XListFont had
                  returned a font which can't be opened.  Record the size
                  as 0 not to try to open it again.  */
-               XCONS (tem)->cdr = make_number (0);
+               XCDR (tem) = make_number (0);
            }
 
-         found_size = XINT (XCONS (tem)->cdr);
+         found_size = XINT (XCDR (tem));
          if (found_size == size)
-           newlist = Fcons (XCONS (tem)->car, newlist);
+           newlist = Fcons (XCAR (tem), newlist);
          else if (found_size > 0)
            {
              if (NILP (second_best))
                second_best = tem;
              else if (found_size < size)
                {
-                 if (XINT (XCONS (second_best)->cdr) > size
-                     || XINT (XCONS (second_best)->cdr) < found_size)
+                 if (XINT (XCDR (second_best)) > size
+                     || XINT (XCDR (second_best)) < found_size)
                    second_best = tem;
                }
              else
                {
-                 if (XINT (XCONS (second_best)->cdr) > size
-                     && XINT (XCONS (second_best)->cdr) > found_size)
+                 if (XINT (XCDR (second_best)) > size
+                     && XINT (XCDR (second_best)) > found_size)
                    second_best = tem;
                }
            }
@@ -11887,7 +12635,7 @@ x_list_fonts (f, pattern, size, maxnames)
        break;
       else if (!NILP (second_best))
        {
-         newlist = Fcons (XCONS (second_best)->car, Qnil);
+         newlist = Fcons (XCAR (second_best), Qnil);
          break;
        }
     }
@@ -12011,12 +12759,12 @@ x_load_font (f, fontname, size)
       int i;
 
       for (i = 0; i < dpyinfo->n_fonts; i++)
-       for (tail = font_names; CONSP (tail); tail = XCONS (tail)->cdr)
+       for (tail = font_names; CONSP (tail); tail = XCDR (tail))
          if (dpyinfo->font_table[i].name
              && (!strcmp (dpyinfo->font_table[i].name,
-                          XSTRING (XCONS (tail)->car)->data)
+                          XSTRING (XCAR (tail))->data)
                  || !strcmp (dpyinfo->font_table[i].full_name,
-                             XSTRING (XCONS (tail)->car)->data)))
+                             XSTRING (XCAR (tail))->data)))
            return (dpyinfo->font_table + i);
     }
 
@@ -12034,7 +12782,7 @@ x_load_font (f, fontname, size)
        a bug of not finding a font even if the font surely exists and
        is loadable by XLoadQueryFont.  */
     if (size > 0 && !NILP (font_names))
-      fontname = (char *) XSTRING (XCONS (font_names)->car)->data;
+      fontname = (char *) XSTRING (XCAR (font_names))->data;
 
     BLOCK_INPUT;
     count = x_catch_errors (FRAME_X_DISPLAY (f));
@@ -12130,26 +12878,25 @@ x_load_font (f, fontname, size)
        Lisp_Object lispy_name = build_string (fontname);
        Lisp_Object lispy_full_name = build_string (fontp->full_name);
 
-       XCONS (dpyinfo->name_list_element)->cdr
+       XCDR (dpyinfo->name_list_element)
          = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
                          Fcons (Fcons (lispy_full_name,
                                        make_number (fontp->size)),
                                 Qnil)),
-                  XCONS (dpyinfo->name_list_element)->cdr);
+                  XCDR (dpyinfo->name_list_element));
        if (full_name)
-         XCONS (dpyinfo->name_list_element)->cdr
+         XCDR (dpyinfo->name_list_element)
            = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
                            Fcons (Fcons (lispy_full_name,
                                          make_number (fontp->size)),
                                   Qnil)),
-                    XCONS (dpyinfo->name_list_element)->cdr);
+                    XCDR (dpyinfo->name_list_element));
       }
 
     /* The slot `encoding' specifies how to map a character
        code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
-       the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
-       the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
-       0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
+       the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
+       (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
        2:0xA020..0xFF7F).  For the moment, we don't know which charset
        uses this font.  So, we set information in fontp->encoding[1]
        which is never used by any charset.  If mapping can't be
@@ -12228,12 +12975,12 @@ x_find_ccl_program (fontp)
 {
   Lisp_Object list, elt;
 
-  for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCONS (list)->cdr)
+  for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
     {
-      elt = XCONS (list)->car;
+      elt = XCAR (list);
       if (CONSP (elt)
-         && STRINGP (XCONS (elt)->car)
-         && (fast_c_string_match_ignore_case (XCONS (elt)->car, fontp->name)
+         && STRINGP (XCAR (elt))
+         && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
              >= 0))
        break;
     }
@@ -12242,7 +12989,7 @@ x_find_ccl_program (fontp)
       struct ccl_program *ccl
        = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
 
-      if (setup_ccl_program (ccl, XCONS (elt)->cdr) < 0)
+      if (setup_ccl_program (ccl, XCDR (elt)) < 0)
        xfree (ccl);
       else
        fontp->font_encoder = ccl;
@@ -12325,28 +13072,6 @@ same_x_server (name1, name2)
 }
 #endif
 
-#if defined (HAVE_X_I18N) || (defined (USE_X_TOOLKIT) && defined (HAVE_X11XTR6))
-/* Recover from setlocale (LC_ALL, "").  */
-static void
-fixup_locale ()
-{
-  /* Currently we require strerror to use the "C" locale,
-     since we don't yet support decoding its string result.  */
-#ifdef LC_MESSAGES
-  setlocale (LC_MESSAGES, "C");
-#endif
-
-  /* The Emacs Lisp reader needs LC_NUMERIC to be "C",
-     so that numbers are read and printed properly for Emacs Lisp.  */
-  setlocale (LC_NUMERIC, "C");
-
-  /* Currently we require strftime to use the "C" locale,
-     since we don't yet support encoding its format argument,
-     or decoding its string result.  */
-  setlocale (LC_TIME, "C");
-}
-#endif
-
 struct x_display_info *
 x_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -12366,11 +13091,6 @@ x_term_init (display_name, xrm_option, resource_name)
       x_initialized = 1;
     }
 
-#ifdef HAVE_X_I18N
-  setlocale (LC_ALL, "");
-  fixup_locale ();
-#endif
-
 #ifdef USE_X_TOOLKIT
   /* weiner@footloose.sps.mot.com reports that this causes
      errors with X11R5:
@@ -12427,8 +13147,8 @@ x_term_init (display_name, xrm_option, resource_name)
     Lisp_Object tail;
 
     for (share = x_display_list, tail = x_display_name_list; share;
-        share = share->next, tail = XCONS (tail)->cdr)
-      if (same_x_server (XSTRING (XCONS (XCONS (tail)->car)->car)->data,
+        share = share->next, tail = XCDR (tail))
+      if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
                         XSTRING (display_name)->data))
        break;
     if (share)
@@ -12440,9 +13160,11 @@ x_term_init (display_name, xrm_option, resource_name)
        if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
          {
            char *vendor = ServerVendor (dpy);
+           UNBLOCK_INPUT;
            dpyinfo->kboard->Vsystem_key_alist
              = call1 (Qvendor_specific_keysyms,
                       build_string (vendor ? vendor : ""));
+           BLOCK_INPUT;
          }
 
        dpyinfo->kboard->next_kboard = all_kboards;
@@ -12464,7 +13186,7 @@ x_term_init (display_name, xrm_option, resource_name)
   /* Put it on x_display_name_list as well, to keep them parallel.  */ 
   x_display_name_list = Fcons (Fcons (display_name, Qnil),
                               x_display_name_list);
-  dpyinfo->name_list_element = XCONS (x_display_name_list)->car;
+  dpyinfo->name_list_element = XCAR (x_display_name_list);
 
   dpyinfo->display = dpy;
 
@@ -12499,8 +13221,8 @@ x_term_init (display_name, xrm_option, resource_name)
 
   dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
                                     DefaultScreen (dpyinfo->display));
-  dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
-                                  &dpyinfo->n_planes);
+  select_visual (dpyinfo);
+  dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
   dpyinfo->height = HeightOfScreen (dpyinfo->screen);
   dpyinfo->width = WidthOfScreen (dpyinfo->screen);
   dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
@@ -12527,6 +13249,26 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->x_highlight_frame = 0;
   dpyinfo->image_cache = make_image_cache ();
 
+  /* See if a private colormap is requested.  */
+  if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
+    {
+      if (dpyinfo->visual->class == PseudoColor)
+       {
+         Lisp_Object value;
+         value = display_x_get_resource (dpyinfo,
+                                         build_string ("privateColormap"),
+                                         build_string ("PrivateColormap"),
+                                         Qnil, Qnil);
+         if (STRINGP (value)
+             && (!strcmp (XSTRING (value)->data, "true")
+                 || !strcmp (XSTRING (value)->data, "on")))
+           dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
+       }
+    }
+  else
+    dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
+                                    dpyinfo->visual, AllocNone);
+      
   {
     int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
     double pixels = DisplayHeight (dpyinfo->display, screen_number);
@@ -12618,6 +13360,10 @@ x_term_init (display_name, xrm_option, resource_name)
                                     (unsigned long) 1, (unsigned long) 0, 1);
   }
 
+#ifdef HAVE_X_I18N
+  xim_initialize (dpyinfo, resource_name);
+#endif
+  
 #ifdef subprocesses
   /* This is only needed for distinguishing keyboard and process input.  */
   if (connection != 0)
@@ -12666,6 +13412,20 @@ x_term_init (display_name, xrm_option, resource_name)
 #endif
 #endif
 
+  /* See if we should run in synchronous mode.  This is useful
+     for debugging X code.  */
+  {
+    Lisp_Object value;
+    value = display_x_get_resource (dpyinfo,
+                                   build_string ("synchronous"),
+                                   build_string ("Synchronous"),
+                                   Qnil, Qnil);
+    if (STRINGP (value)
+       && (!strcmp (XSTRING (value)->data, "true")
+           || !strcmp (XSTRING (value)->data, "on")))
+      XSynchronize (dpyinfo->display, True);
+  }
+  
   UNBLOCK_INPUT;
 
   return dpyinfo;
@@ -12683,25 +13443,27 @@ x_delete_display (dpyinfo)
   /* Discard this display from x_display_name_list and x_display_list.
      We can't use Fdelq because that can quit.  */
   if (! NILP (x_display_name_list)
-      && EQ (XCONS (x_display_name_list)->car, dpyinfo->name_list_element))
-    x_display_name_list = XCONS (x_display_name_list)->cdr;
+      && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
+    x_display_name_list = XCDR (x_display_name_list);
   else
     {
       Lisp_Object tail;
 
       tail = x_display_name_list;
-      while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
+      while (CONSP (tail) && CONSP (XCDR (tail)))
        {
-         if (EQ (XCONS (XCONS (tail)->cdr)->car,
-                 dpyinfo->name_list_element))
+         if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
            {
-             XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
+             XCDR (tail) = XCDR (XCDR (tail));
              break;
            }
-         tail = XCONS (tail)->cdr;
+         tail = XCDR (tail);
        }
     }
 
+  if (next_noop_dpyinfo == dpyinfo)
+    next_noop_dpyinfo = dpyinfo->next;
+
   if (x_display_list == dpyinfo)
     x_display_list = dpyinfo->next;
   else
@@ -12722,6 +13484,11 @@ x_delete_display (dpyinfo)
   if (--dpyinfo->kboard->reference_count == 0)
     delete_kboard (dpyinfo->kboard);
 #endif
+#ifdef HAVE_X_I18N
+  if (dpyinfo->xim)
+    xim_close_dpy (dpyinfo);
+#endif
+  
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->x_id_name);
   xfree (dpyinfo);
@@ -12741,6 +13508,7 @@ static struct redisplay_interface x_redisplay_interface =
   x_update_window_end,
   XTcursor_to,
   x_flush,
+  x_clear_mouse_face,
   x_get_glyph_overhangs,
   x_fix_overlapping_area
 };
@@ -12781,7 +13549,7 @@ x_initialize ()
   baud_rate = 19200;
 
   x_noop_count = 0;
-  last_toolbar_item = -1;
+  last_tool_bar_item = -1;
   any_help_event_p = 0;
   
   /* Try to use interrupt input; if we can't, then start polling.  */
@@ -12791,6 +13559,22 @@ x_initialize ()
   XtToolkitInitialize ();
   Xt_app_con = XtCreateApplicationContext ();
   XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
+
+  /* Install an asynchronous timer that processes Xt timeout events
+     every 0.1s.  This is necessary because some widget sets use
+     timeouts internally, for example the LessTif menu bar, or the
+     Xaw3d scroll bar.  When Xt timouts aren't processed, these
+     widgets don't behave normally.  */
+  {
+    EMACS_TIME interval;
+    EMACS_SET_SECS_USECS (interval, 0, 100000);
+    start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
+  }
+#endif
+  
+#if USE_TOOLKIT_SCROLL_BARS
+  xaw3d_arrow_scroll = False;
+  xaw3d_pick_top = True;
 #endif
 
   /* Note that there is no real way portable across R3/R4 to get the
@@ -12825,10 +13609,15 @@ syms_of_xterm ()
   staticpro (&last_mouse_press_frame);
   last_mouse_press_frame = Qnil;
 
-  staticpro (&help_echo);
   help_echo = Qnil;
-  staticpro (&previous_help_echo);
+  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 ("x-stretch-cursor", &x_stretch_cursor_p,
     "*Non-nil means draw block cursor as wide as the glyph under it.\n\
@@ -12844,7 +13633,6 @@ wide as that tab on the display.");
   x_toolkit_scroll_bars_p = 0;
 #endif
 
-  defsubr (&Sxt_process_timeouts);
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 }