(XTread_socket): Change calls to gen_help_event.
[bpt/emacs.git] / src / xterm.c
index f1725b3..ccd9f8b 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>
@@ -74,10 +68,11 @@ Boston, MA 02111-1307, USA.  */
 /* #include <sys/param.h>  */
 
 #include "charset.h"
+#include "coding.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 +87,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 +102,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 +118,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 +149,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
@@ -246,6 +245,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.  */
 
@@ -299,6 +301,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.
 
@@ -381,8 +386,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
@@ -398,7 +403,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 *,
@@ -409,7 +414,6 @@ 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_tool_bar_highlight P_ ((struct frame *f, int, int));
 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
@@ -449,7 +453,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));
@@ -472,7 +476,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.  */
 
@@ -599,6 +609,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;
@@ -616,6 +633,7 @@ x_update_window_begin (w)
          if (i < w->desired_matrix->nrows)
            clear_mouse_face (display_info);
        }
+#endif /* 0 */
     }
 
   UNBLOCK_INPUT;
@@ -650,24 +668,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;
     }
@@ -703,6 +742,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)
        {
@@ -1091,17 +1131,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_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.  */
@@ -1116,9 +1158,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)
@@ -1182,28 +1223,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);
 }
 
 
@@ -1244,7 +1266,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];
     }
@@ -1284,12 +1306,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)
     {
@@ -1309,32 +1327,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);
        }
     }
 
@@ -1347,33 +1346,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
     {
@@ -1381,7 +1384,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
@@ -1394,9 +1397,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;
            }
        }
     }
@@ -1424,23 +1428,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];
     }
 }
@@ -1488,7 +1522,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;
 
@@ -1515,16 +1549,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];
        }
     }
@@ -1551,17 +1588,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];
     }
 }
@@ -1609,7 +1649,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;
@@ -1710,6 +1753,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
@@ -1719,36 +1794,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;
       int font_not_found_p;
+      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))
@@ -1759,11 +1860,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.  */
@@ -1811,8 +1923,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;
            }
        }
@@ -1821,8 +1932,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)
            {
@@ -1834,15 +1945,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)
            {
@@ -1855,56 +1964,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;
@@ -1928,16 +2018,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);
@@ -2029,9 +2387,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;
 
@@ -2044,14 +2399,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
@@ -2147,6 +2501,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_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 *));
@@ -2157,9 +2512,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 *));
@@ -2174,6 +2529,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
@@ -2240,7 +2602,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
     {
@@ -2291,10 +2653,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);
 
@@ -2338,7 +2705,6 @@ x_set_mode_line_face_gc (s)
      struct glyph_string *s;
 {     
   s->gc = s->face->gc;
-  xassert (s->gc != 0);
 }
 
 
@@ -2350,6 +2716,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;
@@ -2467,13 +2835,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;
@@ -2520,8 +2888,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)
@@ -2529,26 +2897,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)
@@ -2627,7 +2991,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)
@@ -2651,7 +3015,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;
@@ -2686,7 +3050,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)
@@ -2697,16 +3062,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);
@@ -2720,7 +3076,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,
@@ -2748,213 +3103,116 @@ 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;
-           }
-       }
-      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);
-           }
-         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);
-           }
+         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
     {
-      /* 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.  */
+      char *char1b = (char *) s->char2b;
+      int boff = s->font_info->baseline_offset;
 
-      /* 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)
-       XDrawRectangle (s->display, s->window, s->gc, x, s->y,
-                       s->width - 1, s->height - 1);
+      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
        {
-         XCharStruct *pcm;
-         int relative_compose, default_ascent, i;
-         int highest = 0, lowest = 0;
-
-         /* 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;
-           }
+         if (s->two_byte_p)
+           XDrawImageString16 (s->display, s->window, s->gc, x,
+                               s->ybase - boff, s->char2b, s->nchars);
          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;
-               }
+           XDrawImageString (s->display, s->window, s->gc, x,
+                             s->ybase - boff, char1b, s->nchars);
+       }
+    }
+}
 
-             if (s->cmpcharp->cmp_rule)
-               x_offset = (s->cmpcharp->col_offset[0]
-                           * FONT_WIDTH (s->f->output_data.x->font));
+/* Draw the foreground of composite glyph string S.  */
 
-             /* 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;
+static void
+x_draw_composite_glyph_string_foreground (s)
+     struct glyph_string *s;
+{
+  int i, x;
 
-         for (; i < s->nchars; i++, ++s->gidx)
-           {
-             int x_offset = 0, y_offset = 0;
+  /* 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
+    x = s->x;
 
-             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)));
-               }
+  /* 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.  */
 
-             XDrawString16 (s->display, s->window, s->gc,
-                            x + x_offset, s->ybase - y_offset,
-                            s->char2b + i, 1);
-           }
-       }
+  /* Draw a rectangle for the composition if the font for the very
+     first character of the composition could not be loaded.  */
+  if (s->font_not_found_p)
+    {
+      if (s->gidx == 0)
+       XDrawRectangle (s->display, s->window, s->gc, x, s->y,
+                       s->width - 1, s->height - 1);
+    }
+  else
+    {
+      for (i = 0; i < s->nchars; i++, ++s->gidx)
+       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);
     }
 }
 
 
 #ifdef USE_X_TOOLKIT
 
-/* 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.  */
+static struct frame *x_frame_of_widget P_ ((Widget));
 
-int
-x_alloc_nearest_color_for_widget (widget, cmap, color)
+
+/* Return the frame on which widget WIDGET is used.. Abort if frame
+   cannot be determined.  */
+
+static struct frame *
+x_frame_of_widget (widget)
      Widget widget;
-     Colormap cmap;
-     XColor *color;
 {
-  struct frame *f;
   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
@@ -2972,11 +3230,28 @@ x_alloc_nearest_color_for_widget (widget, cmap, color)
            (f->output_data.nothing != 1
             && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
        && f->output_data.x->widget == widget)
-      return x_alloc_nearest_color (f, cmap, color);
+      return f;
 
   abort ();
 }
 
+
+/* Allocate the color COLOR->pixel on the screen and display of
+   widget WIDGET in colormap CMAP.  If an exact match cannot be
+   allocated, try the nearest color available.  Value is non-zero
+   if successful.  This is called from lwlib.  */
+
+int
+x_alloc_nearest_color_for_widget (widget, cmap, color)
+     Widget widget;
+     Colormap cmap;
+     XColor *color;
+{
+  struct frame *f = x_frame_of_widget (widget);
+  return x_alloc_nearest_color (f, cmap, color);
+}
+
+
 #endif /* USE_X_TOOLKIT */
 
 
@@ -3032,10 +3307,62 @@ x_alloc_nearest_color (f, 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
@@ -3049,7 +3376,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;
@@ -3073,15 +3400,7 @@ x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
        {
          /* 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);
@@ -3108,7 +3427,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;
 {
@@ -3117,7 +3436,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);
 
@@ -3130,13 +3449,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;
     }
 
@@ -3316,7 +3629,7 @@ x_draw_glyph_string_box (s)
     }
   
   /* 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);
 
@@ -3359,7 +3672,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.  */
@@ -3408,8 +3721,18 @@ x_draw_image_foreground (s)
        }
       else
        {
-         XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
+         unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
+         XGCValues xgcv;
+         XRectangle clip_rect, image_rect, r;
+
+         x_get_glyph_string_clip_rect (s, &clip_rect);
+         image_rect.x = x;
+         image_rect.y = y;
+         image_rect.width = s->img->width;
+         image_rect.height = s->img->height;
+         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
+           XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
+                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
          
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -3438,7 +3761,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.  */
@@ -3487,7 +3810,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.  */
@@ -3775,6 +4098,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 ();
     }
@@ -3854,94 +4185,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
@@ -3961,14 +4243,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.  */
 
@@ -3980,8 +4265,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);
@@ -3991,17 +4276,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;
@@ -4015,7 +4304,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);
@@ -4036,9 +4325,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;
   
@@ -4047,19 +4336,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];
 }
 
 
@@ -4148,9 +4466,8 @@ x_set_glyph_string_background_width (s, start, last_x)
        {                                                                   \
         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)
@@ -4189,74 +4506,79 @@ x_set_glyph_string_background_width (s, start, last_x)
 #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
@@ -4282,6 +4604,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);   \
@@ -5830,37 +6158,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.
@@ -5926,7 +6227,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.  */
@@ -6071,14 +6372,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;
+           }
        }
     }
 
@@ -6107,7 +6420,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;
@@ -6212,14 +6526,15 @@ note_mouse_highlight (f, x, y)
           enough space for all, and try again.  */
        len = 10;
        overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-       noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
+       noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
        if (noverlays > len)
          {
            len = noverlays;
            overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-           noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
+           noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
          }
-         
+
+       /* Sort overlays into increasing priority order.  */
        noverlays = sort_overlays (overlay_vec, noverlays, w);
 
        /* Check mouse-face highlighting.  */
@@ -6237,7 +6552,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))
@@ -6323,26 +6638,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;
@@ -6472,11 +6804,13 @@ x_handle_tool_bar_click (f, button_event)
 
       XSETFRAME (frame, f);
       event.kind = TOOL_BAR_EVENT;
-      event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
+      event.frame_or_window = frame;
+      event.arg = frame;
       kbd_buffer_store_event (&event);
 
       event.kind = TOOL_BAR_EVENT;
-      event.frame_or_window = Fcons (frame, key);
+      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);
@@ -6572,9 +6906,11 @@ note_tool_bar_highlight (f, x, y)
   
   /* Set help_echo to a help string.to display for this tool-bar item.
      XTread_socket does the rest.  */
+  help_echo_object = help_echo_window = Qnil;
+  help_echo_pos = -1;
   help_echo = (XVECTOR (f->current_tool_bar_items)
               ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
-  if (!STRINGP (help_echo))
+  if (NILP (help_echo))
     help_echo = (XVECTOR (f->current_tool_bar_items)
                 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
 }
@@ -6625,6 +6961,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;
@@ -6743,8 +7082,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.  */
@@ -6787,6 +7129,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.  */
 
@@ -7025,21 +7385,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.  */
@@ -7047,6 +7413,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;
@@ -7110,9 +7477,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.  */
 
@@ -7132,15 +7510,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))
@@ -7153,6 +7527,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;
     }
 }
 
@@ -7177,12 +7554,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.  */
@@ -7201,11 +7581,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];
@@ -7322,40 +7706,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;
@@ -7367,8 +7750,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
@@ -7376,7 +7759,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;
 {
@@ -7390,25 +7773,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);
 }
 
 
@@ -7491,7 +7869,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.
@@ -7499,8 +7877,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)
@@ -7518,16 +7897,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.  */
@@ -7571,7 +7963,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;
@@ -7599,7 +7991,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
@@ -7619,43 +8011,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;
 }
@@ -8226,6 +8636,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
@@ -8581,6 +8992,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--;                                               \
@@ -8615,9 +9027,7 @@ 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
+  struct coding_system coding;
 
   if (interrupt_input_blocked)
     {
@@ -8634,6 +9044,20 @@ XTread_socket (sd, bufp, numchars, expected)
   if (numchars <= 0)
     abort ();                  /* Don't think this happens.  */
 
+  ++handling_signal;
+  
+  /* The input should be decoded if it is from XIM.  Currently the
+     locale of XIM is the same as that of the system.  So, we can use
+     Vlocale_coding_system which is initialized properly at Emacs
+     startup time.  */
+  setup_coding_system (Vlocale_coding_system, &coding);
+  coding.src_multibyte = 0;
+  coding.dst_multibyte = 1;
+  /* The input is converted to events, thus we can't handle
+     composition.  Anyway, there's no XIM that gives us composition
+     information.  */
+  coding.composing = COMPOSITION_DISABLED;
+
   /* Find the display we are supposed to read input for.
      It's the one communicating on descriptor SD.  */
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
@@ -8676,28 +9100,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
@@ -8723,6 +9135,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.  */
@@ -8743,6 +9168,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)
@@ -8783,6 +9209,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                            bufp->kind = delete_window_event;
                            XSETFRAME (bufp->frame_or_window, f);
+                           bufp->arg = Qnil;
                            bufp++;
 
                            count += 1;
@@ -8875,6 +9302,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;
@@ -8905,6 +9333,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;
@@ -9018,6 +9447,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                      bufp->kind = iconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
@@ -9049,6 +9479,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      bufp->kind = deiconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
@@ -9083,9 +9514,20 @@ XTread_socket (sd, bufp, numchars, expected)
              if (f != 0)
                {
                  KeySym keysym, orig_keysym;
-                 /* al%imercury@uunet.uu.net says that making this 81 instead of
-                    80 fixed a bug whereby meta chars made his Emacs hang.  */
-                 unsigned char copy_buffer[81];
+                 /* al%imercury@uunet.uu.net says that making this 81
+                    instead of 80 fixed a bug whereby meta chars made
+                    his Emacs hang.
+
+                    It seems that some version of XmbLookupString has
+                    a bug of not returning XBufferOverflow in
+                    status_return even if the input is too long to
+                    fit in 81 bytes.  So, we must prepare sufficient
+                    bytes for copy_buffer.  513 bytes (256 chars for
+                    two-byte character set) seems to be a faily good
+                    approximation.  -- 2000.8.10 handa@etl.go.jp  */
+                 unsigned char copy_buffer[513];
+                 unsigned char *copy_bufptr = copy_buffer;
+                 int copy_bufsiz = sizeof (copy_buffer);
                  int modifiers;
 
                  event.xkey.state
@@ -9114,28 +9556,41 @@ 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;
+                     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 ();
                    }
                  else
-                   nbytes = XLookupString (&event.xkey, copy_buffer,
-                                           80, &keysym, &compose_status);
+                   nbytes = XLookupString (&event.xkey, copy_bufptr,
+                                           copy_bufsiz, &keysym,
+                                           &compose_status);
 #else
-                 nbytes = XLookupString (&event.xkey, copy_buffer,
-                                         80, &keysym, &compose_status);
+                 nbytes = XLookupString (&event.xkey, copy_bufptr,
+                                         copy_bufsiz, &keysym,
+                                         &compose_status);
 #endif
 
                  orig_keysym = keysym;
@@ -9218,6 +9673,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);
@@ -9225,23 +9681,60 @@ 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)
                        {
                          register int i;
+                         register int c;
+                         unsigned char *p, *pend;
+                         int nchars, len;
 
                          for (i = 0; i < nbytes; i++)
                            {
-                             if (temp_index == sizeof temp_buffer / sizeof (short))
+                             if (temp_index == (sizeof temp_buffer
+                                                / sizeof (short)))
                                temp_index = 0;
-                             temp_buffer[temp_index++] = copy_buffer[i];
-                             bufp->kind = ascii_keystroke;
-                             bufp->code = copy_buffer[i];
+                             temp_buffer[temp_index++] = copy_bufptr[i];
+                           }
+
+                         if (/* If the event is not from XIM, */
+                             event.xkey.keycode != 0
+                             /* or the current locale doesn't request
+                                decoding of the intup data, ... */
+                             || coding.type == coding_type_raw_text
+                             || coding.type == coding_type_no_conversion)
+                           {
+                             /* ... we can use the input data as is.  */
+                             nchars = nbytes;
+                           }
+                         else
+                           { 
+                             /* We have to decode the input data.  */
+                             int require;
+                             unsigned char *p;
+
+                             require = decoding_buffer_size (&coding, nbytes);
+                             p = (unsigned char *) alloca (require);
+                             coding.mode |= CODING_MODE_LAST_BLOCK;
+                             decode_coding (&coding, copy_bufptr, p,
+                                            nbytes, require);
+                             nbytes = coding.produced;
+                             nchars = coding.produced_char;
+                             copy_bufptr = p;
+                           }
+
+                         /* Convert the input data to a sequence of
+                            character events.  */
+                         for (i = 0; i < nbytes; i += len)
+                           {
+                             c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
+                                                         nbytes - i, len);
+                             bufp->kind = (SINGLE_BYTE_CHAR_P (c)
+                                           ? ascii_keystroke
+                                           : multibyte_char_keystroke);
+                             bufp->code = c;
                              XSETFRAME (bufp->frame_or_window, f);
+                             bufp->arg = Qnil;
                              bufp->modifiers
                                = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
                                                          modifiers);
@@ -9249,8 +9742,8 @@ XTread_socket (sd, bufp, numchars, expected)
                              bufp++;
                            }
 
-                         count += nbytes;
-                         numchars -= nbytes;
+                         count += nchars;
+                         numchars -= nchars;
 
                          if (keysym == NoSymbol)
                            break;
@@ -9261,7 +9754,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
@@ -9332,7 +9842,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))
@@ -9362,10 +9886,13 @@ 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, numchars,
+                                         Qnil, frame, Qnil, Qnil, 0);
+                     bufp += n, count += n, numchars -= n;
                    }
 
 #ifdef LESSTIF_VERSION
@@ -9412,7 +9939,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))
@@ -9439,10 +9967,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);
@@ -9450,9 +9979,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, numchars, help_echo, frame,
+                                       help_echo_window, help_echo_object,
+                                       help_echo_pos);
+                   bufp += n, count += n, numchars -= n;
                  }
                
                goto OTHER;
@@ -9492,6 +10022,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,
@@ -9580,8 +10115,6 @@ XTread_socket (sd, bufp, numchars, expected)
                    
                    if (!tool_bar_p)
                      last_tool_bar_item = -1;
-                   if (display_busy_cursor_p)
-                     inhibit_busy_cursor = 2;
                  }
                else
                  {
@@ -9709,6 +10242,7 @@ XTread_socket (sd, bufp, numchars, expected)
     }
 
   UNBLOCK_INPUT;
+  --handling_signal;
   return count;
 }
 
@@ -9840,28 +10374,38 @@ 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
-     glyphs and mini-buffer.  */
-  if (w->phys_cursor.hpos < row->used[TEXT_AREA])
-    {
-      struct frame *f = XFRAME (w->frame);
-      struct glyph *cursor_glyph;
-      GC gc;
-      int x;
-      unsigned long mask;
-      XGCValues xgcv;
-      Display *dpy;
-      Window window;
+  struct frame *f = XFRAME (w->frame);
+  struct glyph *cursor_glyph;
+  GC gc;
+  int x;
+  unsigned long mask;
+  XGCValues xgcv;
+  Display *dpy;
+  Window window;
       
-      cursor_glyph = get_phys_cursor_glyph (w);
-      if (cursor_glyph == NULL)
-       return;
+  /* If cursor is out of bounds, don't draw garbage.  This can happen
+     in mini-buffer windows when switching between echo area glyphs
+     and mini-buffer.  */
+  cursor_glyph = get_phys_cursor_glyph (w);
+  if (cursor_glyph == NULL)
+    return;
 
+  /* If on an image, draw like a normal cursor.  That's usually better
+     visible than drawing a bar, esp. if the image is large so that
+     the bar might not be in the window.  */
+  if (cursor_glyph->type == IMAGE_GLYPH)
+    {
+      struct glyph_row *row;
+      row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
+      x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
+    }
+  else
+    {
       xgcv.background = f->output_data.x->cursor_pixel;
       xgcv.foreground = f->output_data.x->cursor_pixel;
       xgcv.graphics_exposures = 0;
@@ -9869,7 +10413,7 @@ x_draw_bar_cursor (w, row)
       dpy = FRAME_X_DISPLAY (f);
       window = FRAME_X_WINDOW (f);
       gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
-      
+  
       if (gc)
        XChangeGC (dpy, gc, mask, &xgcv);
       else
@@ -9877,14 +10421,16 @@ x_draw_bar_cursor (w, row)
          gc = XCreateGC (dpy, window, mask, &xgcv);
          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);
     }
@@ -9981,7 +10527,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))
@@ -10041,6 +10588,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;
@@ -10079,6 +10627,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))
@@ -10093,7 +10642,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;
@@ -10101,7 +10652,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
@@ -10141,7 +10700,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:
@@ -10150,6 +10709,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
@@ -10217,10 +10782,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;
+    }
 }
 
 
@@ -10473,11 +11043,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.  */
@@ -10590,14 +11163,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.  */
@@ -10643,8 +11215,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)
@@ -10653,15 +11224,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.  */
@@ -10669,11 +11234,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.  */
@@ -10725,7 +11499,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))
@@ -11094,7 +11868,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.  */
@@ -11146,37 +11920,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);
   }
 }
 
@@ -11389,16 +12162,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
@@ -11407,6 +12172,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));
     }
@@ -11724,7 +12504,7 @@ x_list_fonts (f, pattern, size, maxnames)
   for (; CONSP (patterns); patterns = XCDR (patterns))
     {
       int num_fonts;
-      char **names;
+      char **names = NULL;
 
       pattern = XCAR (patterns);
       /* See if we cached the result for this particular query.
@@ -12200,9 +12980,8 @@ x_load_font (f, fontname, size)
 
     /* 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
@@ -12378,28 +13157,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;
@@ -12419,11 +13176,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:
@@ -12493,9 +13245,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;
@@ -12552,8 +13306,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);
@@ -12580,6 +13334,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);
@@ -12671,6 +13445,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)
@@ -12719,6 +13497,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;
@@ -12745,8 +13537,7 @@ x_delete_display (dpyinfo)
       tail = x_display_name_list;
       while (CONSP (tail) && CONSP (XCDR (tail)))
        {
-         if (EQ (XCAR (XCDR (tail)),
-                 dpyinfo->name_list_element))
+         if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
            {
              XCDR (tail) = XCDR (XCDR (tail));
              break;
@@ -12755,6 +13546,9 @@ x_delete_display (dpyinfo)
        }
     }
 
+  if (next_noop_dpyinfo == dpyinfo)
+    next_noop_dpyinfo = dpyinfo->next;
+
   if (x_display_list == dpyinfo)
     x_display_list = dpyinfo->next;
   else
@@ -12775,6 +13569,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);
@@ -12794,6 +13593,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
 };
@@ -12844,6 +13644,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
@@ -12878,10 +13694,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\
@@ -12897,7 +13718,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;
 }