(x_new_font): Don't change a tooltip's size.
[bpt/emacs.git] / src / xterm.c
index 2629ec9..f5c0a5d 100644 (file)
@@ -1,5 +1,5 @@
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
+   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -44,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>
@@ -70,6 +68,7 @@ Boston, MA 02111-1307, USA.  */
 /* #include <sys/param.h>  */
 
 #include "charset.h"
+#include "coding.h"
 #include "ccl.h"
 #include "frame.h"
 #include "dispextern.h"
@@ -94,7 +93,6 @@ Boston, MA 02111-1307, USA.  */
 #include <X11/Shell.h>
 #endif
 
-#include <sys/types.h>
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
@@ -104,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
@@ -150,13 +149,6 @@ extern void _XEditResCheckMessages ();
 #endif
 #endif
 
-#ifdef SOLARIS2
-/* memmove will be defined as a macro in Xfuncs.h unless
-   <string.h> is included beforehand.  The declaration for memmove in
-   <string.h> will cause a syntax error when Xfuncs.h later includes it.  */
-#include <string.h>
-#endif
-
 #ifndef min
 #define min(a,b) ((a) < (b) ? (a) : (b))
 #endif
@@ -238,14 +230,17 @@ static unsigned char ov_bits[] = {
 extern Lisp_Object Qhelp_echo;
 
 \f
-/* Non-zero means Emacs uses toolkit scroll bars.  */
+/* Non-nil means Emacs uses toolkit scroll bars.  */
 
-int x_toolkit_scroll_bars_p;
+Lisp_Object Vx_toolkit_scroll_bars;
 
 /* If a string, XTread_socket generates an event to display that string.
    (The display is done in read_char.)  */
    
 static Lisp_Object help_echo;
+static Lisp_Object help_echo_window;
+static Lisp_Object help_echo_object;
+static int help_echo_pos;
 
 /* Temporary variable for XTread_socket.  */
 
@@ -384,8 +379,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
@@ -401,7 +396,9 @@ enum draw_glyphs_face
   DRAW_IMAGE_SUNKEN
 };
 
-static void x_update_window_end P_ ((struct window *, int));
+static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
+static const XColor *x_color_cells P_ ((struct frame *, 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 *,
@@ -412,7 +409,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 *));
@@ -475,7 +471,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.  */
 
@@ -602,6 +604,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;
@@ -619,6 +628,7 @@ x_update_window_begin (w)
          if (i < w->desired_matrix->nrows)
            clear_mouse_face (display_info);
        }
+#endif /* 0 */
     }
 
   UNBLOCK_INPUT;
@@ -653,24 +663,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;
     }
@@ -706,6 +737,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)
        {
@@ -1108,19 +1140,6 @@ 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.  */
-
-#define PER_CHAR_METRIC(font, b)                                          \
-  ((font)->per_char                                                       \
-   ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2                   \
-      + (((font)->min_byte1 || (font)->max_byte1)                         \
-        ? (((b)->byte1 - (font)->min_byte1)                               \
-           * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
-        : 0))                                                             \
-   : &((font)->max_bounds))
-
-
 /* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B
    is not contained in the font.  */
 
@@ -1187,7 +1206,7 @@ x_per_char_metric (font, char2b)
     }
 
   return ((pcm == NULL
-          || pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
+          || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
          ? NULL : pcm);
 }
 
@@ -1391,24 +1410,20 @@ 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 = it->char_to_display;
-      glyph->face_id = it->face_id;
       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 = 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];
     }
 }
@@ -1428,23 +1443,20 @@ x_append_composite_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 = COMPOSITE_GLYPH;
-      glyph->pixel_width = it->pixel_width;
-      glyph->u.cmp_id = it->cmp_id;
-      glyph->face_id = it->face_id;
       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 = 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];
     }
 }
@@ -1493,8 +1505,8 @@ x_produce_image_glyph (it)
   prepare_image_for_display (it->f, img);
 
   it->ascent = it->phys_ascent = image_ascent (img, face);
-  it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
-  it->pixel_width = img->width + 2 * img->margin;
+  it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
+  it->pixel_width = img->width + 2 * img->hmargin;
 
   it->nglyphs = 1;
   
@@ -1519,16 +1531,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->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];
        }
     }
@@ -1555,17 +1570,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->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];
     }
 }
@@ -1613,7 +1631,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;
@@ -1742,10 +1763,11 @@ x_produce_stretch_glyph (it)
        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))
+#define VCENTER_BASELINE_OFFSET(FONT, F)                       \
+  ((FONT)->descent                                             \
+   + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))           \
+      + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2  \
+   - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
 
 /* Produce glyphs/get display metrics for the display element IT is
    loaded with.  See the description of struct display_iterator in
@@ -1766,6 +1788,17 @@ x_produce_glyphs (it)
       int font_not_found_p;
       struct font_info *font_info;
       int boff;                        /* baseline offset */
+      /* We may change it->multibyte_p upon unibyte<->multibyte
+        conversion.  So, save the current value now and restore it
+        later.
+
+        Note: It seems that we don't have to record multibyte_p in
+        struct glyph because the character code itself tells if or
+        not the character is multibyte.  Thus, in the future, we must
+        consider eliminating the field `multibyte_p' in the struct
+        glyph.
+      */
+      int saved_multibyte_p = it->multibyte_p;
 
       /* Maybe translate single-byte characters to multibyte, or the
         other way.  */
@@ -1778,6 +1811,7 @@ x_produce_glyphs (it)
                  || !NILP (Vnonascii_translation_table)))
            {
              it->char_to_display = unibyte_char_to_multibyte (it->c);
+             it->multibyte_p = 1;
              it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
              face = FACE_FROM_ID (it->f, it->face_id);
            }
@@ -1785,6 +1819,7 @@ x_produce_glyphs (it)
                   && !it->multibyte_p)
            {
              it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
+             it->multibyte_p = 0;
              it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
              face = FACE_FROM_ID (it->f, it->face_id);
            }
@@ -1908,6 +1943,12 @@ x_produce_glyphs (it)
          int tab_width = it->tab_width * CANON_X_UNIT (it->f);
          int x = it->current_x + it->continuation_lines_width;
          int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
+
+         /* If the distance from the current position to the next tab
+            stop is less than a canonical character width, use the
+            tab stop after that.  */
+         if (next_tab_x - x < CANON_X_UNIT (it->f))
+           next_tab_x += tab_width;
       
          it->pixel_width = next_tab_x - x;
          it->nglyphs = 1;
@@ -1978,6 +2019,7 @@ x_produce_glyphs (it)
          if (it->glyph_row)
            x_append_glyph (it);
        }
+      it->multibyte_p = saved_multibyte_p;
     }
   else if (it->what == IT_COMPOSITION)
     {
@@ -2049,16 +2091,30 @@ x_produce_glyphs (it)
          int font_descent = font->descent - boff;
          /* Bounding box of the overall glyphs.  */
          int leftmost, rightmost, lowest, highest;
-         int i;
+         int i, width, ascent, descent;
 
          cmp->font = (void *) font;
 
          /* Initialize the bounding box.  */
-         pcm = x_per_char_metric (font, &char2b);
+         if (font_info
+             && (pcm = x_per_char_metric (font, &char2b)))
+           {
+             width = pcm->width;
+             ascent = pcm->ascent;
+             descent = pcm->descent;
+           }
+         else
+           {
+             width = FONT_WIDTH (font);
+             ascent = font->ascent;
+             descent = font->descent;
+           }
+         
+         rightmost = width;
+         lowest = - descent + boff;
+         highest = ascent + boff;
          leftmost = 0;
-         rightmost = pcm->width;
-         lowest = - pcm->descent + boff;
-         highest = pcm->ascent + boff;
+         
          if (font_info
              && font_info->default_ascent
              && CHAR_TABLE_P (Vuse_default_ascent)
@@ -2098,27 +2154,38 @@ x_produce_glyphs (it)
                    boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
                }
 
-             pcm = x_per_char_metric (font, &char2b);
+             if (font_info
+                 && (pcm = x_per_char_metric (font, &char2b)))
+               {
+                 width = pcm->width;
+                 ascent = pcm->ascent;
+                 descent = pcm->descent;
+               }
+             else
+               {
+                 width = FONT_WIDTH (font);
+                 ascent = 1;
+                 descent = 0;
+               }
 
              if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
                {
                  /* Relative composition with or without
                     alternate chars.  */
-                 left = (leftmost + rightmost - pcm->width) / 2;
-                 btm = - pcm->descent + boff;
+                 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 (- pcm->descent
-                         >= font_info->relative_compose)
+                     if (- descent >= font_info->relative_compose)
                        /* One extra pixel between two glyphs.  */
                        btm = highest + 1;
-                     else if (pcm->ascent <= 0)
+                     else if (ascent <= 0)
                        /* One extra pixel between two glyphs.  */
-                       btm = lowest - 1 - pcm->ascent - pcm->descent;
+                       btm = lowest - 1 - ascent - descent;
                    }
                }
              else
@@ -2147,23 +2214,23 @@ x_produce_glyphs (it)
 
                  left = (leftmost
                          + grefx * (rightmost - leftmost) / 2
-                         - nrefx * pcm->width / 2);
+                         - nrefx * width / 2);
                  btm = ((grefy == 0 ? highest
                          : grefy == 1 ? 0
                          : grefy == 2 ? lowest
                          : (highest + lowest) / 2)
-                        - (nrefy == 0 ? pcm->ascent + pcm->descent
-                           : nrefy == 1 ? pcm->descent - boff
+                        - (nrefy == 0 ? ascent + descent
+                           : nrefy == 1 ? descent - boff
                            : nrefy == 2 ? 0
-                           : (pcm->ascent + pcm->descent) / 2));
+                           : (ascent + descent) / 2));
                }
 
              cmp->offsets[i * 2] = left;
-             cmp->offsets[i * 2 + 1] = btm + pcm->descent;
+             cmp->offsets[i * 2 + 1] = btm + descent;
 
              /* Update the bounding box of the overall glyphs. */
-             right = left + pcm->width;
-             top = btm + pcm->descent + pcm->ascent;
+             right = left + width;
+             top = btm + descent + ascent;
              if (left < leftmost)
                leftmost = left;
              if (right > rightmost)
@@ -2224,8 +2291,9 @@ x_produce_glyphs (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;
   
@@ -2246,7 +2314,7 @@ x_estimate_mode_line_height (f, face_id)
      struct frame *f;
      enum face_id face_id;
 {
-  int height = 1;
+  int height = FONT_HEIGHT (FRAME_FONT (f));
 
   /* This function is called so early when Emacs starts that the face
      cache and mode line face are not yet initialized.  */
@@ -2254,7 +2322,11 @@ x_estimate_mode_line_height (f, face_id)
       {
        struct face *face = FACE_FROM_ID (f, face_id);
        if (face)
-         height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
+         {
+           if (face->font)
+             height = FONT_HEIGHT (face->font);
+           height += 2 * face->box_line_width;
+         }
       }
   
   return height;
@@ -2464,6 +2536,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
@@ -2583,10 +2662,16 @@ x_set_mouse_face_gc (s)
   int face_id;
   struct face *face;
 
-  /* What face has to be used for the mouse face?  */
+  /* What face has to be used last for the mouse face?  */
   face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
   face = FACE_FROM_ID (s->f, face_id);
-  face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+  if (face == NULL)
+    face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
+  
+  if (s->first_glyph->type == CHAR_GLYPH)
+    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+  else
+    face_id = FACE_FOR_CHAR (s->f, face, 0);
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
@@ -2630,7 +2715,6 @@ x_set_mode_line_face_gc (s)
      struct glyph_string *s;
 {     
   s->gc = s->face->gc;
-  xassert (s->gc != 0);
 }
 
 
@@ -2642,6 +2726,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;
@@ -2821,8 +2907,6 @@ x_get_glyph_overhangs (glyph, f, left, right)
      struct frame *f;
      int *left, *right;
 {
-  int c;
-  
   *left = *right = 0;
   
   if (glyph->type == CHAR_GLYPH)
@@ -3125,21 +3209,20 @@ x_draw_composite_glyph_string_foreground (s)
 
 #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
@@ -3157,14 +3240,127 @@ 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);
+}
+
+
+/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
+   or DELTA.  Try a color with RGB values multiplied by FACTOR first.
+   If this produces the same color as PIXEL, try a color where all RGB
+   values have DELTA added.  Return the allocated color in *PIXEL.
+   DISPLAY is the X display, CMAP is the colormap to operate on.
+   Value is non-zero if successful.  */
+
+int
+x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
+     Widget widget;
+     Display *display;
+     Colormap cmap;
+     unsigned long *pixel;
+     double factor;
+     int delta;
+{
+  struct frame *f = x_frame_of_widget (widget);
+  return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
+}
+
+
 #endif /* USE_X_TOOLKIT */
 
 
+/* Value is an array of XColor structures for the contents of the
+   color map of frame F.  Set *NCELLS to the size of the array.
+   Note that this probably shouldn't be called for large color maps,
+   say a 24-bit TrueColor map.  */
+
+static const XColor *
+x_color_cells (f, ncells)
+     struct frame *f;
+     int *ncells;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+  if (dpyinfo->color_cells == NULL)
+    {
+      Display *display = FRAME_X_DISPLAY (f);
+      Screen *screen = FRAME_X_SCREEN (f);
+      int i;
+      
+      dpyinfo->ncolor_cells
+       = XDisplayCells (display, XScreenNumberOfScreen (screen));
+      dpyinfo->color_cells
+       = (XColor *) xmalloc (dpyinfo->ncolor_cells
+                             * sizeof *dpyinfo->color_cells);
+      
+      for (i = 0; i < dpyinfo->ncolor_cells; ++i)
+       dpyinfo->color_cells[i].pixel = i;
+      
+      XQueryColors (display, FRAME_X_COLORMAP (f),
+                   dpyinfo->color_cells, dpyinfo->ncolor_cells);
+    }
+
+  *ncells = dpyinfo->ncolor_cells;
+  return dpyinfo->color_cells;
+}
+
+
+/* On frame F, translate pixel colors to RGB values for the NCOLORS
+   colors in COLORS.  Use cached information, if available.  */
+
+void
+x_query_colors (f, colors, ncolors)
+     struct frame *f;
+     XColor *colors;
+     int ncolors;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+  if (dpyinfo->color_cells)
+    {
+      int i;
+      for (i = 0; i < ncolors; ++i)
+       {
+         unsigned long pixel = colors[i].pixel;
+         xassert (pixel < dpyinfo->ncolor_cells);
+         xassert (dpyinfo->color_cells[pixel].pixel == pixel);
+         colors[i] = dpyinfo->color_cells[pixel];
+       }
+    }
+  else
+    XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
+}
+
+
+/* On frame F, translate pixel color to RGB values for the color in
+   COLOR.  Use cached information, if available.  */
+
+void
+x_query_color (f, color)
+     struct frame *f;
+     XColor *color;
+{
+  x_query_colors (f, color, 1);
+}
+     
+
 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
    CMAP.  If an exact match can't be allocated, try the nearest color
    available.  Value is non-zero if successful.  Set *COLOR to the
@@ -3190,12 +3386,8 @@ x_alloc_nearest_color (f, cmap, color)
         color matching with StaticColor visuals.  */
       int nearest, i;
       unsigned long nearest_delta = ~0;
-      int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
-      XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
-
-      for (i = 0; i < ncells; ++i)
-       cells[i].pixel = i;
-      XQueryColors (display, cmap, cells, ncells);
+      int ncells;
+      const XColor *cells = x_color_cells (f, &ncells);
 
       for (nearest = i = 0; i < ncells; ++i)
        {
@@ -3216,6 +3408,25 @@ x_alloc_nearest_color (f, cmap, color)
       color->blue  = cells[nearest].blue;
       rc = XAllocColor (display, cmap, color);
     }
+  else
+    {
+      /* If allocation succeeded, and the allocated pixel color is not
+         equal to a cached pixel color recorded earlier, there was a
+         change in the colormap, so clear the color cache.  */
+      struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+      XColor *cached_color;
+      
+      if (dpyinfo->color_cells
+         && (cached_color = &dpyinfo->color_cells[color->pixel],
+             (cached_color->red != color->red
+              || cached_color->blue != color->blue
+              || cached_color->green != color->green)))
+       {
+         xfree (dpyinfo->color_cells);
+         dpyinfo->color_cells = NULL;
+         dpyinfo->ncolor_cells = 0;
+       }
+    }
 
 #ifdef DEBUG_X_COLORS
   if (rc)
@@ -3239,7 +3450,7 @@ x_copy_color (f, pixel)
 
   color.pixel = pixel;
   BLOCK_INPUT;
-  XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
+  x_query_color (f, &color);
   XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
   UNBLOCK_INPUT;
 #ifdef DEBUG_X_COLORS
@@ -3249,6 +3460,44 @@ x_copy_color (f, pixel)
 }
 
 
+/* Allocate color PIXEL on display DPY.  PIXEL must already be allocated.
+   It's necessary to do this instead of just using PIXEL directly to
+   get color reference counts right.  */
+
+unsigned long
+x_copy_dpy_color (dpy, cmap, pixel)
+     Display *dpy;
+     Colormap cmap;
+     unsigned long pixel;
+{
+  XColor color;
+
+  color.pixel = pixel;
+  BLOCK_INPUT;
+  XQueryColor (dpy, cmap, &color);
+  XAllocColor (dpy, cmap, &color);
+  UNBLOCK_INPUT;
+#ifdef DEBUG_X_COLORS
+  register_color (pixel);
+#endif
+  return color.pixel;
+}
+
+
+/* Brightness beyond which a color won't have its highlight brightness
+   boosted.
+
+   Nominally, highlight colors for `3d' faces are calculated by
+   brightening an object's color by a constant scale factor, but this
+   doesn't yield good results for dark colors, so for colors who's
+   brightness is less than this value (on a scale of 0-65535) have an
+   use an additional additive factor.
+
+   The value here is set so that the default menu-bar/mode-line color
+   (grey75) will not have its highlights changed at all.  */
+#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
+
+
 /* Allocate a color which is lighter or darker than *PIXEL by FACTOR
    or DELTA.  Try a color with RGB values multiplied by FACTOR first.
    If this produces the same color as PIXEL, try a color where all RGB
@@ -3266,11 +3515,12 @@ x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
      int delta;
 {
   XColor color, new;
+  long bright;
   int success_p;
 
   /* Get RGB color values.  */
   color.pixel = *pixel;
-  XQueryColor (display, cmap, &color);
+  x_query_color (f, &color);
 
   /* Change RGB values by specified FACTOR.  Avoid overflow!  */
   xassert (factor >= 0);
@@ -3278,6 +3528,34 @@ x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
   new.green = min (0xffff, factor * color.green);
   new.blue = min (0xffff, factor * color.blue);
 
+  /* Calculate brightness of COLOR.  */
+  bright = (2 * color.red + 3 * color.green + color.blue) / 6;
+
+  /* We only boost colors that are darker than
+     HIGHLIGHT_COLOR_DARK_BOOST_LIMIT.  */
+  if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
+    /* Make an additive adjustment to NEW, because it's dark enough so
+       that scaling by FACTOR alone isn't enough.  */
+    {
+      /* How far below the limit this color is (0 - 1, 1 being darker).  */
+      double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
+      /* The additive adjustment.  */
+      int min_delta = delta * dimness * factor / 2;
+
+      if (factor < 1)
+       {
+         new.red =   max (0, new.red -   min_delta);
+         new.green = max (0, new.green - min_delta);
+         new.blue =  max (0, new.blue -  min_delta);
+       }
+      else
+       {
+         new.red =   min (0xffff, min_delta + new.red);
+         new.green = min (0xffff, min_delta + new.green);
+         new.blue =  min (0xffff, min_delta + new.blue);
+       }
+    }
+
   /* Try to allocate the color.  */
   success_p = x_alloc_nearest_color (f, cmap, &new);
   if (success_p)
@@ -3335,8 +3613,6 @@ 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.  */
       x_free_colors (f, &relief->pixel, 1);
       relief->allocated_p = 0;
     }
@@ -3475,21 +3751,21 @@ x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
   
   /* Top.  */
   XFillRectangle (s->display, s->window, s->gc,
-                 left_x, top_y, right_x - left_x, width);
+                 left_x, top_y, right_x - left_x + 1, width);
 
   /* Left.  */
   if (left_p)
     XFillRectangle (s->display, s->window, s->gc,
-                   left_x, top_y, width, bottom_y - top_y);
+                   left_x, top_y, width, bottom_y - top_y + 1);
 
   /* Bottom.  */
   XFillRectangle (s->display, s->window, s->gc,
-                 left_x, bottom_y - width, right_x - left_x, width);
+                 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
   
   /* Right.  */
   if (right_p)
     XFillRectangle (s->display, s->window, s->gc,
-                   right_x - width, top_y, width, bottom_y - top_y);
+                   right_x - width + 1, top_y, width, bottom_y - top_y + 1);
 
   XSetForeground (s->display, s->gc, xgcv.foreground);
   XSetClipMask (s->display, s->gc, None);
@@ -3572,11 +3848,8 @@ x_draw_image_foreground (s)
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
@@ -3609,8 +3882,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
@@ -3651,11 +3934,8 @@ x_draw_image_relief (s)
   
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
   
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
@@ -3700,11 +3980,8 @@ x_draw_image_foreground_1 (s, pixmap)
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
@@ -3792,7 +4069,6 @@ x_draw_image_glyph_string (s)
 {
   int x, y;
   int box_line_width = s->face->box_line_width;
-  int margin = s->img->margin;
   int height;
   Pixmap pixmap = None;
 
@@ -3803,7 +4079,8 @@ x_draw_image_glyph_string (s)
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
   if (height > s->img->height
-      || margin
+      || s->img->hmargin
+      || s->img->vmargin
       || s->img->mask
       || s->img->pixmap == 0
       || s->width != s->background_width)
@@ -3817,9 +4094,9 @@ x_draw_image_glyph_string (s)
       
       if (s->img->mask)
        {
-         /* Create a pixmap as large as the glyph string Fill it with
-            the background color.  Copy the image to it, using its
-            mask.  Copy the temporary pixmap to the display.  */
+         /* Create a pixmap as large as the glyph string.  Fill it
+            with the background color.  Copy the image to it, using
+            its mask.  Copy the temporary pixmap to the display.  */
          Screen *screen = FRAME_X_SCREEN (s->f);
          int depth = DefaultDepthOfScreen (screen);
 
@@ -3853,10 +4130,6 @@ x_draw_image_glyph_string (s)
            }
        }
       else
-       /* Implementation idea: Is it possible to construct a mask?
-          We could look at the color at the margins of the image, and
-          say that this color is probably the background color of the
-          image.  */
        x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
       
       s->background_filled_p = 1;
@@ -3993,23 +4266,38 @@ x_draw_glyph_string (s)
       /* Draw underline.  */
       if (s->face->underline_p)
        {
-         unsigned long dy, h;
+         unsigned long tem, h;
+         int y;
 
+         /* Get the underline thickness.  Default is 1 pixel.  */
          if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
            h = 1;
-         if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
-           dy = s->height - h;
+
+         /* Get the underline position.  This is the recommended
+            vertical offset in pixels from the baseline to the top of
+            the underline.  This is a signed value according to the
+            specs, and its default is
+
+            ROUND ((maximum descent) / 2), with
+            ROUND(x) = floor (x + 0.5)  */
+         
+         if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
+           y = s->ybase + (long) tem;
+         else if (s->face->font)
+           y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
+         else
+           y = s->height - h;
       
          if (s->face->underline_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->width, h);
+           XFillRectangle (s->display, s->window, s->gc,
+                           s->x, y, s->width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->underline_color);
-             XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->width, h);
+             XFillRectangle (s->display, s->window, s->gc,
+                             s->x, y, s->width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -4067,11 +4355,12 @@ static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
                                              struct face **, int));
 
 
-/* Load glyph string S with a composition components specified by S->cmp.
+/* 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 lines physical height for clipping.
+   use its physical height for clipping.
 
    Value is the index of a component not in S.  */
 
@@ -4125,11 +4414,12 @@ x_fill_composite_glyph_string (s, faces, overlaps_p)
 }
 
 
-/* Load glyph string S with a sequence 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.  */
 
@@ -4212,19 +4502,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->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];
 }
 
 
@@ -4313,9 +4632,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)
@@ -4354,7 +4672,7 @@ 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;                              \
@@ -4520,8 +4838,9 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   int i, j;
 
   /* Let's rather be paranoid than getting a SEGV.  */
-  start = max (0, start);
   end = min (end, row->used[area]);
+  start = max (0, start);
+  start = min (end, start);
   if (real_start)
     *real_start = start;
   if (real_end)
@@ -4575,7 +4894,7 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   /* If there are any glyphs with lbearing < 0 or rbearing > width in
      the row, redraw some glyphs in front or following the glyph
      strings built above.  */
-  if (!overlaps_p && row->contains_overlapping_glyphs_p)
+  if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
     {
       int dummy_x = 0;
       struct glyph_string *h, *t;
@@ -4674,6 +4993,7 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
       if (area > TEXT_AREA)
        x_reached -= window_box_width (w, TEXT_AREA);
     }
+  
   return x_reached;
 }
 
@@ -5371,31 +5691,31 @@ expose_area (w, row, r, area)
      XRectangle *r;
      enum glyph_row_area area;
 {
-  int x;
   struct glyph *first = row->glyphs[area];
   struct glyph *end = row->glyphs[area] + row->used[area];
   struct glyph *last;
-  int first_x;
-
-  /* Set x to the window-relative start position for drawing glyphs of
-     AREA.  The first glyph of the text area can be partially visible.
-     The first glyphs of other areas cannot.  */
-  if (area == LEFT_MARGIN_AREA)
-    x = 0;
-  else if (area == TEXT_AREA)
-    x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
-  else
-    x = (window_box_width (w, LEFT_MARGIN_AREA)
-        + window_box_width (w, TEXT_AREA));
+  int first_x, start_x, x;
 
   if (area == TEXT_AREA && row->fill_line_p)
     /* If row extends face to end of line write the whole line.  */
-    x_draw_glyphs (w, x, row, area,
+    x_draw_glyphs (w, 0, row, area,
                   0, row->used[area],
                   row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
                   NULL, NULL, 0);
   else
     {
+      /* Set START_X to the window-relative start position for drawing glyphs of
+        AREA.  The first glyph of the text area can be partially visible.
+        The first glyphs of other areas cannot.  */
+      if (area == LEFT_MARGIN_AREA)
+       start_x = 0;
+      else if (area == TEXT_AREA)
+       start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
+      else
+       start_x = (window_box_width (w, LEFT_MARGIN_AREA)
+                  + window_box_width (w, TEXT_AREA));
+      x = start_x;
+
       /* Find the first glyph that must be redrawn.  */
       while (first < end
             && x + first->pixel_width < r->x)
@@ -5416,7 +5736,7 @@ expose_area (w, row, r, area)
       
       /* Repaint.  */
       if (last > first)
-       x_draw_glyphs (w, first_x, row, area,
+       x_draw_glyphs (w, first_x - start_x, row, area,
                       first - row->glyphs[area],
                       last - row->glyphs[area],
                       row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
@@ -5494,7 +5814,7 @@ expose_window (w, r)
      happen when toolkit scroll bars are used and a window is split.
      Reconfiguring the scroll bar will generate an expose for a newly
      created window.  */
-  if (w->current_matrix == NULL)
+  if (w->current_matrix == NULL || w == updated_window)
     return;
 
   TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
@@ -6006,37 +6326,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.
@@ -6102,7 +6395,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.  */
@@ -6197,7 +6490,7 @@ frame_to_window_pixel_xy (w, x, y)
 }
 
 
-/* Take proper action when mouse has moved to the mode or top line of
+/* Take proper action when mouse has moved to the mode or header line of
    window W, x-position X.  MODE_LINE_P non-zero means mouse is on the
    mode line.  X is relative to the start of the text display area of
    W, so the width of bitmap areas and scroll bars must be subtracted
@@ -6217,7 +6510,7 @@ note_mode_line_highlight (w, x, mode_line_p)
     row = MATRIX_MODE_LINE_ROW (w->current_matrix);
   else
     row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
-  
+
   if (row->enabled_p)
     {
       struct glyph *glyph, *end;
@@ -6229,6 +6522,7 @@ note_mode_line_highlight (w, x, mode_line_p)
       end = glyph + row->used[TEXT_AREA];
       x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
              + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
+      
       while (glyph < end
             && x >= x0 + glyph->pixel_width)
        {
@@ -6247,14 +6541,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)))
+         if (KEYMAPP (map))
            cursor = f->output_data.x->nontext_cursor;
+         else
+           {
+             map = Fget_text_property (make_number (glyph->charpos),
+                                       Qkeymap, glyph->object);
+             if (KEYMAPP (map))
+               cursor = f->output_data.x->nontext_cursor;
+           }
        }
     }
 
@@ -6329,6 +6635,9 @@ note_mouse_highlight (f, x, y)
       note_mode_line_highlight (w, x, portion == 1);
       return;
     }
+  else if (portion == 2)
+    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                  f->output_data.x->horizontal_drag_cursor);
   else
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                   f->output_data.x->text_cursor);
@@ -6389,14 +6698,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.  */
@@ -6414,7 +6724,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))
@@ -6500,26 +6810,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)
+         help = overlay = Qnil;
+         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;
@@ -6558,7 +6885,7 @@ static int last_tool_bar_item;
    Return in *GLYPH a pointer to the glyph of the tool-bar item in
    the current matrix of the tool-bar window of F, or NULL if not
    on a tool-bar item.  Return in *PROP_IDX the index of the tool-bar
-   item in F->current_tool_bar_items.  Value is
+   item in F->tool_bar_items.  Value is
 
    -1  if X/Y is not on a tool-bar item
    0   if X/Y is on the same item that was highlighted before.
@@ -6581,7 +6908,7 @@ x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
     return -1;
 
   /* Get the start of this tool-bar item's properties in
-     f->current_tool_bar_items.  */
+     f->tool_bar_items.  */
   if (!tool_bar_item_info (f, *glyph, prop_idx))
     return -1;
 
@@ -6623,8 +6950,7 @@ x_handle_tool_bar_click (f, button_event)
     return;
 
   /* If item is disabled, do nothing.  */
-  enabled_p = (XVECTOR (f->current_tool_bar_items)
-              ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
+  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
   if (NILP (enabled_p))
     return;
   
@@ -6644,16 +6970,17 @@ x_handle_tool_bar_click (f, button_event)
       show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
       dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
 
-      key = (XVECTOR (f->current_tool_bar_items)
-            ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
+      key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
 
       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);
@@ -6716,8 +7043,7 @@ note_tool_bar_highlight (f, x, y)
   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
   
   /* If tool-bar item is not enabled, don't highlight it.  */
-  enabled_p = (XVECTOR (f->current_tool_bar_items)
-              ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
+  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
   if (!NILP (enabled_p))
     {
       /* Compute the x-position of the glyph.  In front and past the
@@ -6749,11 +7075,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 = (XVECTOR (f->current_tool_bar_items)
-              ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
-  if (!STRINGP (help_echo))
-    help_echo = (XVECTOR (f->current_tool_bar_items)
-                ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
+  help_echo_object = help_echo_window = Qnil;
+  help_echo_pos = -1;
+  help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
+  if (NILP (help_echo))
+    help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
 }
 
 
@@ -6923,8 +7249,11 @@ show_mouse_face (dpyinfo, draw)
        }
 
       if (end_hpos > start_hpos)
-       x_draw_glyphs (w, start_x, row, TEXT_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.  */
@@ -6956,8 +7285,11 @@ void
 clear_mouse_face (dpyinfo)
      struct x_display_info *dpyinfo;
 {
-  if (tip_frame)
+#if 0 /* This prevents redrawing tool bar items when changing from one
+        to another while a tooltip is open, so don't do it.  */
+  if (!NILP (tip_frame))
     return;
+#endif
   
   if (! NILP (dpyinfo->mouse_face_window))
     show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
@@ -6967,6 +7299,26 @@ 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;
+
+  BLOCK_INPUT;
+  XSETWINDOW (window, w);
+  if (EQ (window, dpyinfo->mouse_face_window))
+    clear_mouse_face (dpyinfo);
+  UNBLOCK_INPUT;
+}
+
+
 /* Just discard the mouse face information for frame F, if any.
    This is used when the size of F is changed.  */
 
@@ -7131,6 +7483,15 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 
            /* Is win one of our frames?  */
            f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
+
+#ifdef USE_X_TOOLKIT
+           /* If we end up with the menu bar window, say it's not
+              on the frame.  */
+           if (f1 != NULL
+               && f1->output_data.x->menubar_widget
+               && win == XtWindow (f1->output_data.x->menubar_widget))
+             f1 = NULL;
+#endif /* USE_X_TOOLKIT */
          }
 
        if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
@@ -7274,7 +7635,7 @@ x_window_to_scroll_bar (window_id)
                         Toolkit scroll bars
  ************************************************************************/
 
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
 
 static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
 static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
@@ -7353,6 +7714,12 @@ xt_action_hook (widget, client_data, action_name, event, params,
     }
 }
 
+/* A vector of windows used for communication between
+   x_send_scroll_bar_event and x_scroll_bar_to_input_event.  */
+
+static struct window **scroll_bar_windows;
+static int scroll_bar_windows_size;
+
 
 /* Send a client message with message type Xatom_Scrollbar for a
    scroll action to the frame of WINDOW.  PART is a value identifying
@@ -7366,15 +7733,41 @@ x_send_scroll_bar_event (window, part, portion, whole)
 {
   XEvent event;
   XClientMessageEvent *ev = (XClientMessageEvent *) &event;
-  struct frame *f = XFRAME (XWINDOW (window)->frame);
+  struct window *w = XWINDOW (window);
+  struct frame *f = XFRAME (w->frame);
+  int i;
 
+  BLOCK_INPUT;
+  
   /* Construct a ClientMessage event to send to the frame.  */
   ev->type = ClientMessage;
   ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
   ev->display = FRAME_X_DISPLAY (f);
   ev->window = FRAME_X_WINDOW (f);
   ev->format = 32;
-  ev->data.l[0] = (long) window;
+
+  /* We can only transfer 32 bits in the XClientMessageEvent, which is
+     not enough to store a pointer or Lisp_Object on a 64 bit system.
+     So, store the window in scroll_bar_windows and pass the index
+     into that array in the event.  */
+  for (i = 0; i < scroll_bar_windows_size; ++i)
+    if (scroll_bar_windows[i] == NULL)
+      break;
+
+  if (i == scroll_bar_windows_size)
+    {
+      int new_size = max (10, 2 * scroll_bar_windows_size);
+      size_t nbytes = new_size * sizeof *scroll_bar_windows;
+      size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
+      
+      scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
+                                                       nbytes);
+      bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
+      scroll_bar_windows_size = new_size;
+    }
+
+  scroll_bar_windows[i] = w;
+  ev->data.l[0] = (long) i;
   ev->data.l[1] = (long) part;
   ev->data.l[2] = (long) 0;
   ev->data.l[3] = (long) portion;
@@ -7386,7 +7779,6 @@ x_send_scroll_bar_event (window, part, portion, whole)
   /* 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.  */
-  BLOCK_INPUT;
   XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
   UNBLOCK_INPUT;
 }
@@ -7401,11 +7793,19 @@ 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;
+  struct window *w;
+  
+  w = scroll_bar_windows[ev->data.l[0]];
+  scroll_bar_windows[ev->data.l[0]] = NULL;
+
+  XSETWINDOW (window, w);
+  f = XFRAME (w->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];
@@ -7759,8 +8159,9 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
      struct scroll_bar *bar;
      int portion, position, whole;
 {
+  struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+  Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
   float top, shown;
-  Widget widget = SCROLL_BAR_X_WIDGET (bar);
 
   if (whole == 0)
     top = 0, shown = 1;
@@ -7856,7 +8257,7 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
          {
 #ifdef HAVE_XAW3D
            ScrollbarWidget sb = (ScrollbarWidget) widget;
-           int scroll_mode;
+           int scroll_mode = 0;
            
            /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR.  */
            if (xaw3d_arrow_scroll)
@@ -7910,7 +8311,7 @@ x_scroll_bar_create (w, top, left, width, height)
 
   BLOCK_INPUT;
 
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
   x_create_toolkit_scroll_bar (f, bar);
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   {
@@ -7970,13 +8371,16 @@ x_scroll_bar_create (w, top, left, width, height)
     XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
 
   /* Map the window/widget.  */
-#if USE_TOOLKIT_SCROLL_BARS
-  XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
-  XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ {
+   Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
+   XtConfigureWidget (scroll_bar,
                     left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                     top,
                     width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                     height, 0);
+   XtMapWidget (scroll_bar);
+ }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
@@ -8109,16 +8513,14 @@ static void
 x_scroll_bar_remove (bar)
      struct scroll_bar *bar;
 {
+  struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   BLOCK_INPUT;
 
-#if USE_TOOLKIT_SCROLL_BARS
-  XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
-#else /* not USE_TOOLKIT_SCROLL_BARS */
-  {
-    FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-    XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
-  }
-#endif /* not USE_TOOLKIT_SCROLL_BARS */
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
+#else
+  XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
+#endif
   
   /* Disassociate this scroll bar from its window.  */
   XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
@@ -8212,7 +8614,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
       /* Move/size the scroll bar widget.  */
       if (mask)
-       XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
+       XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
                           sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                           top,
                           sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
@@ -8259,7 +8661,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
       UNBLOCK_INPUT;
     }
 
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
   x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   /* Set the scroll bar's current state, unless we're currently being
@@ -8313,13 +8715,16 @@ XTcondemn_scroll_bars (frame)
     }
 }
 
+
 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
    Note that WINDOW isn't necessarily condemned at all.  */
+
 static void
 XTredeem_scroll_bar (window)
      struct window *window;
 {
   struct scroll_bar *bar;
+  struct frame *f;
 
   /* We can't redeem this window's scroll bar if it doesn't have one.  */
   if (NILP (window->vertical_scroll_bar))
@@ -8328,36 +8733,33 @@ XTredeem_scroll_bar (window)
   bar = XSCROLL_BAR (window->vertical_scroll_bar);
 
   /* Unlink it from the condemned list.  */
-  {
-    FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
-
-    if (NILP (bar->prev))
-      {
-       /* If the prev pointer is nil, it must be the first in one of
-           the lists.  */
-       if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
-         /* It's not condemned.  Everything's fine.  */
-         return;
-       else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
-                    window->vertical_scroll_bar))
-         FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
-       else
-         /* If its prev pointer is nil, it must be at the front of
-             one or the other!  */
-         abort ();
-      }
-    else
-      XSCROLL_BAR (bar->prev)->next = bar->next;
+  f = XFRAME (WINDOW_FRAME (window));
+  if (NILP (bar->prev))
+    {
+      /* If the prev pointer is nil, it must be the first in one of
+        the lists.  */
+      if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
+       /* It's not condemned.  Everything's fine.  */
+       return;
+      else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+                  window->vertical_scroll_bar))
+       FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
+      else
+       /* If its prev pointer is nil, it must be at the front of
+          one or the other!  */
+       abort ();
+    }
+  else
+    XSCROLL_BAR (bar->prev)->next = bar->next;
 
-    if (! NILP (bar->next))
-      XSCROLL_BAR (bar->next)->prev = bar->prev;
+  if (! NILP (bar->next))
+    XSCROLL_BAR (bar->next)->prev = bar->prev;
 
-    bar->next = FRAME_SCROLL_BARS (f);
-    bar->prev = Qnil;
-    XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
-    if (! NILP (bar->next))
-      XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
-  }
+  bar->next = FRAME_SCROLL_BARS (f);
+  bar->prev = Qnil;
+  XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
+  if (! NILP (bar->next))
+    XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
 }
 
 /* Remove all scroll bars on FRAME that haven't been saved since the
@@ -8452,6 +8854,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
@@ -8807,6 +9210,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--;                                               \
@@ -8841,6 +9245,7 @@ XTread_socket (sd, bufp, numchars, expected)
   struct frame *f;
   int event_found = 0;
   struct x_display_info *dpyinfo;
+  struct coding_system coding;
 
   if (interrupt_input_blocked)
     {
@@ -8857,6 +9262,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)
@@ -9008,6 +9427,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                            bufp->kind = delete_window_event;
                            XSETFRAME (bufp->frame_or_window, f);
+                           bufp->arg = Qnil;
                            bufp++;
 
                            count += 1;
@@ -9100,6 +9520,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;
@@ -9130,6 +9551,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;
@@ -9243,6 +9665,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                      bufp->kind = iconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
@@ -9274,6 +9697,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      bufp->kind = deiconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
@@ -9290,7 +9714,7 @@ XTread_socket (sd, bufp, numchars, expected)
            case KeyPress:
              f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
-#ifdef USE_MOTIF
+#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
              /* I couldn't find a way to prevent LessTif scroll bars
                 from consuming key events.  */
              if (f == 0)
@@ -9303,14 +9727,25 @@ XTread_socket (sd, bufp, numchars, expected)
                      f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
                    }
                }
-#endif /* USE_MOTIF */
+#endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
 
              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
@@ -9339,8 +9774,6 @@ XTread_socket (sd, bufp, numchars, expected)
 #ifdef HAVE_X_I18N
                  if (FRAME_XIC (f))
                    {
-                     unsigned char *copy_bufptr = copy_buffer;
-                     int copy_bufsiz = sizeof (copy_buffer);
                      Status status_return;
 
                      nbytes = XmbLookupString (FRAME_XIC (f),
@@ -9360,17 +9793,22 @@ XTread_socket (sd, bufp, numchars, expected)
                      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;
@@ -9453,6 +9891,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);
@@ -9464,15 +9903,55 @@ XTread_socket (sd, bufp, numchars, expected)
                      else if (numchars > nbytes)
                        {
                          register int i;
+                         register int c;
+                         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);
@@ -9480,8 +9959,8 @@ XTread_socket (sd, bufp, numchars, expected)
                              bufp++;
                            }
 
-                         count += nbytes;
-                         numchars -= nbytes;
+                         count += nchars;
+                         numchars -= nchars;
 
                          if (keysym == NoSymbol)
                            break;
@@ -9580,7 +10059,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))
@@ -9593,7 +10086,6 @@ XTread_socket (sd, bufp, numchars, expected)
              f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
              if (f)
                {
-                 Lisp_Object frame;
                  int from_menu_bar_p = 0;
                  
                  if (f == dpyinfo->mouse_face_mouse_frame)
@@ -9610,10 +10102,14 @@ 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;
+                     help_echo = Qnil;
+                     n = gen_help_event (bufp, numchars,
+                                         Qnil, frame, Qnil, Qnil, 0);
+                     bufp += n, count += n, numchars -= n;
                    }
 
 #ifdef LESSTIF_VERSION
@@ -9660,7 +10156,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))
@@ -9687,10 +10184,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);
@@ -9698,9 +10196,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;
@@ -9960,6 +10459,7 @@ XTread_socket (sd, bufp, numchars, expected)
     }
 
   UNBLOCK_INPUT;
+  --handling_signal;
   return count;
 }
 
@@ -10096,24 +10596,33 @@ x_draw_bar_cursor (w, row, width)
      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;
@@ -10121,7 +10630,7 @@ x_draw_bar_cursor (w, row, width)
       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
@@ -10129,10 +10638,10 @@ x_draw_bar_cursor (w, row, width)
          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,
@@ -10352,7 +10861,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
        {
          extern int cursor_in_non_selected_windows;
          
-         if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
+         if (MINI_WINDOW_P (w)
+             || !cursor_in_non_selected_windows
+             || NILP (XBUFFER (w->buffer)->cursor_type))
            new_cursor_type = NO_CURSOR;
          else
            new_cursor_type = HOLLOW_BOX_CURSOR;
@@ -10736,28 +11247,60 @@ x_connection_signal (signalnum)       /* If we don't have an argument, */
   signal (signalnum, x_connection_signal);
 #endif /* USG */
 }
+
 \f
-/* Handling X errors.  */
+/************************************************************************
+                         Handling X errors
+ ************************************************************************/
 
-/* Handle the loss of connection to display DISPLAY.  */
+/* Handle the loss of connection to display DPY.  ERROR_MESSAGE is
+   the text of an error message that lead to the connection loss.  */
 
 static SIGTYPE
-x_connection_closed (display, error_message)
-     Display *display;
+x_connection_closed (dpy, error_message)
+     Display *dpy;
      char *error_message;
 {
-  struct x_display_info *dpyinfo = x_display_info_for_display (display);
+  struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
+  int count;
+  char *msg;
+  
+  msg = (char *) alloca (strlen (error_message) + 1);
+  strcpy (msg, error_message);
+  handling_signal = 0;
+  
+  /* Prevent being called recursively because of an error condition
+     below.  Otherwise, we might end up with printing ``can't find per
+     display information'' in the recursive call instead of printing
+     the original message here.  */
+  count = x_catch_errors (dpy);
+  
+  /* We have to close the display to inform Xt that it doesn't
+     exist anymore.  If we don't, Xt will continue to wait for
+     events from the display.  As a consequence, a sequence of
 
-  /* Indicate that this display is dead.  */
+     M-x make-frame-on-display RET :1 RET
+     ...kill the new frame, so that we get an IO error...
+     M-x make-frame-on-display RET :1 RET
+
+     will indefinitely wait in Xt for events for display `:1', opened
+     in the first class to make-frame-on-display.
 
-#if 0 /* Closing the display caused a bus error on OpenWindows.  */
+     Closing the display is reported to lead to a bus error on
+     OpenWindows in certain situations.  I suspect that is a bug
+     in OpenWindows.  I don't know how to cicumvent it here.  */
+  
 #ifdef USE_X_TOOLKIT
-  XtCloseDisplay (display);
-#endif
+  /* If DPYINFO is null, this means we didn't open the display
+     in the first place, so don't try to close it.  */
+  if (dpyinfo)
+    XtCloseDisplay (dpy);
 #endif
 
-  dpyinfo->display = 0;
+  /* Indicate that this display is dead.  */
+  if (dpyinfo)
+    dpyinfo->display = 0;
 
   /* First delete frames whose mini-buffers are on frames
      that are on the dead display.  */
@@ -10789,9 +11332,11 @@ x_connection_closed (display, error_message)
   if (dpyinfo)
     x_delete_display (dpyinfo);
 
+  x_uncatch_errors (dpy, count);
+  
   if (x_display_list == 0)
     {
-      fprintf (stderr, "%s\n", error_message);
+      fprintf (stderr, "%s\n", msg);
       shut_down_emacs (0, 0, Qnil);
       exit (70);
     }
@@ -10804,9 +11349,10 @@ x_connection_closed (display, error_message)
   TOTALLY_UNBLOCK_INPUT;
 
   clear_waiting_for_input ();
-  error ("%s", error_message);
+  error ("%s", msg);
 }
 
+
 /* This is the usual handler for X protocol errors.
    It kills all frames on the display that we got the error for.
    If that was the only one, it prints an error message and kills Emacs.  */
@@ -10827,6 +11373,7 @@ x_error_quitter (display, error)
   x_connection_closed (display, buf1);
 }
 
+
 /* This is the first-level handler for X protocol errors.
    It calls x_error_quitter or x_error_catcher.  */
 
@@ -10902,7 +11449,12 @@ x_new_font (f, fontname)
                f->output_data.x->font->fid);
 
       frame_update_line_height (f);
-      x_set_window_size (f, 0, f->width, f->height);
+
+      /* Don't change the size of a tip frame; there's no point in
+        doing it because it's done in Fx_show_tip, and it leads to
+        problems because the tip frame has no widget.  */
+      if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+       x_set_window_size (f, 0, f->width, f->height);
     }
   else
     /* If we are setting a new frame's font for the first time,
@@ -10924,7 +11476,6 @@ x_new_fontset (f, fontsetname)
 {
   int fontset = fs_query_fontset (build_string (fontsetname), 0);
   Lisp_Object result;
-  char *fontname;
 
   if (fontset < 0)
     return Qnil;
@@ -11007,6 +11558,7 @@ 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);
@@ -11024,9 +11576,14 @@ xim_open_dpy (dpyinfo, resource_name)
 #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 */
 }
 
 
@@ -11100,6 +11657,7 @@ 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;
@@ -11113,11 +11671,18 @@ xim_initialize (dpyinfo, resource_name)
   XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
                                  resource_name, EMACS_CLASS,
                                  xim_instantiate_callback,
-                                 (XPointer)xim_inst);
+                                 /* 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 */
 }
 
 
@@ -11127,14 +11692,18 @@ 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);
+  if (dpyinfo->display)
+    XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
+                                     NULL, EMACS_CLASS,
+                                     xim_instantiate_callback, NULL);
 #endif /* not HAVE_X11R6_XIM */
-  XCloseIM (dpyinfo->xim);
+  if (dpyinfo->display)
+    XCloseIM (dpyinfo->xim);
   dpyinfo->xim = NULL;
   XFree (dpyinfo->xim_styles);
+#endif /* USE_XIM */
 }
 
 #endif /* not HAVE_X11R6_XIM */
@@ -11191,7 +11760,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))
@@ -11217,25 +11786,33 @@ x_calc_absolute_position (f)
                                  - PIXEL_WIDTH (f)
                                  + f->output_data.x->left_pos);
 
-  if (flags & YNegative)
-    {
-      int menubar_height = 0;
+  {
+    int height = PIXEL_HEIGHT (f);
 
-#ifdef USE_X_TOOLKIT
-      if (f->output_data.x->menubar_widget)
-       menubar_height
-         = (f->output_data.x->menubar_widget->core.height
-            + f->output_data.x->menubar_widget->core.border_width);
+#if defined USE_X_TOOLKIT && defined USE_MOTIF
+    /* Something is fishy here.  When using Motif, starting Emacs with
+       `-g -0-0', the frame appears too low by a few pixels.
+
+       This seems to be so because initially, while Emacs is starting,
+       the column widget's height and the frame's pixel height are
+       different.  The column widget's height is the right one.  In
+       later invocations, when Emacs is up, the frame's pixel height
+       is right, though.
+
+       It's not obvious where the initial small difference comes from.
+       2000-12-01, gerd.  */
+    
+    XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
 #endif
-      
-      f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
-                                  - 2 * f->output_data.x->border_width
-                                  - win_y
-                                  - PIXEL_HEIGHT (f)
-                                  - menubar_height
-                                  + f->output_data.x->top_pos);
-    }
 
+  if (flags & YNegative)
+    f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
+                                - 2 * f->output_data.x->border_width
+                                - win_y
+                                - height
+                                + f->output_data.x->top_pos);
+  }
+  
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */
@@ -11295,37 +11872,19 @@ x_set_offset (f, xoff, yoff, change_gravity)
   UNBLOCK_INPUT;
 }
 
-/* Call this to change the size of frame F's x-window.
-   If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
-   for this size change and subsequent size changes.
-   Otherwise we leave the window gravity unchanged.  */
 
-void
-x_set_window_size (f, change_gravity, cols, rows)
+/* Change the size of frame F's X window to COLS/ROWS in the case F
+   doesn't have a widget.  If CHANGE_GRAVITY is 1, we change to
+   top-left-corner window gravity for this size change and subsequent
+   size changes.  Otherwise we leave the window gravity unchanged.  */
+
+static void
+x_set_window_size_1 (f, change_gravity, cols, rows)
      struct frame *f;
      int change_gravity;
      int cols, rows;
 {
-#ifndef USE_X_TOOLKIT
   int pixelwidth, pixelheight;
-#endif
-
-  BLOCK_INPUT;
-
-#ifdef USE_X_TOOLKIT
-  {
-    /* The x and y position of the widget is clobbered by the
-       call to XtSetValues within EmacsFrameSetCharSize.
-       This is a real kludge, but I don't understand Xt so I can't
-       figure out a correct fix.  Can anyone else tell me? -- rms.  */
-    int xpos = f->output_data.x->widget->core.x;
-    int ypos = f->output_data.x->widget->core.y;
-    EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
-    f->output_data.x->widget->core.x = xpos;
-    f->output_data.x->widget->core.y = ypos;
-  }
-
-#else /* not USE_X_TOOLKIT */
 
   check_frame_size (f, &rows, &cols);
   f->output_data.x->vertical_scroll_bar_extra
@@ -11370,7 +11929,43 @@ x_set_window_size (f, change_gravity, cols, rows)
   SET_FRAME_GARBAGED (f);
 
   XFlush (FRAME_X_DISPLAY (f));
+}
+
+
+/* Call this to change the size of frame F's x-window.
+   If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
+   for this size change and subsequent size changes.
+   Otherwise we leave the window gravity unchanged.  */
+
+void
+x_set_window_size (f, change_gravity, cols, rows)
+     struct frame *f;
+     int change_gravity;
+     int cols, rows;
+{
+  BLOCK_INPUT;
 
+#ifdef USE_X_TOOLKIT
+  
+  if (f->output_data.x->widget != None)
+    {
+      /* The x and y position of the widget is clobbered by the
+        call to XtSetValues within EmacsFrameSetCharSize.
+        This is a real kludge, but I don't understand Xt so I can't
+        figure out a correct fix.  Can anyone else tell me? -- rms.  */
+      int xpos = f->output_data.x->widget->core.x;
+      int ypos = f->output_data.x->widget->core.y;
+      EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
+      f->output_data.x->widget->core.x = xpos;
+      f->output_data.x->widget->core.y = ypos;
+    }
+  else
+    x_set_window_size_1 (f, change_gravity, cols, rows);
+  
+#else /* not USE_X_TOOLKIT */
+  
+  x_set_window_size_1 (f, change_gravity, cols, rows);
+  
 #endif /* not USE_X_TOOLKIT */
 
   /* If cursor was outside the new size, mark it as off.  */
@@ -11518,6 +12113,9 @@ x_make_frame_visible (f)
 {
   Lisp_Object type;
   int original_top, original_left;
+  int retry_count = 2;
+
+ retry:
 
   BLOCK_INPUT;
 
@@ -11632,6 +12230,7 @@ x_make_frame_visible (f)
            /* 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 ();
@@ -11641,6 +12240,20 @@ x_make_frame_visible (f)
        /* See if a MapNotify event has been processed.  */
        FRAME_SAMPLE_VISIBILITY (f);
       }
+
+    /* 2000-09-28: In
+
+       (let ((f (selected-frame)))
+          (iconify-frame f)
+         (raise-frame f))
+
+       the frame is not raised with various window managers on
+       FreeBSD, Linux and Solaris.  It turns out that, for some
+       unknown reason, the call to XtMapWidget is completely ignored.
+       Mapping the widget a second time works.  */
+    
+    if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
+      goto retry;
   }
 }
 
@@ -11835,11 +12448,12 @@ x_iconify_frame (f)
   UNBLOCK_INPUT;
 #endif /* not USE_X_TOOLKIT */
 }
+
 \f
-/* Destroy the X window of frame F.  */
+/* Free X resources of frame F.  */
 
 void
-x_destroy_window (f)
+x_free_frame_resources (f)
      struct frame *f;
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
@@ -11848,22 +12462,45 @@ x_destroy_window (f)
 
   /* If a display connection is dead, don't try sending more
      commands to the X server.  */
-  if (dpyinfo->display != 0)
+  if (dpyinfo->display)
     {
-      if (f->output_data.x->icon_desc != 0)
+      if (f->output_data.x->icon_desc)
        XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
+      
 #ifdef HAVE_X_I18N
       if (FRAME_XIC (f))
        free_frame_xic (f);
 #endif
-      XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
+      
+      if (FRAME_X_WINDOW (f))
+       XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+      
 #ifdef USE_X_TOOLKIT
       if (f->output_data.x->widget)
        XtDestroyWidget (f->output_data.x->widget);
       free_frame_menubar (f);
 #endif /* USE_X_TOOLKIT */
 
-      free_frame_faces (f);
+      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);
+
+      if (FRAME_FACE_CACHE (f))
+       free_frame_faces (f);
+      
+      x_free_gcs (f);
       XFlush (FRAME_X_DISPLAY (f));
     }
 
@@ -11871,7 +12508,8 @@ x_destroy_window (f)
     xfree (f->output_data.x->saved_menu_event);
 
   xfree (f->output_data.x);
-  f->output_data.x = 0;
+  f->output_data.x = NULL;
+  
   if (f == dpyinfo->x_focus_frame)
     dpyinfo->x_focus_frame = 0;
   if (f == dpyinfo->x_focus_event_frame)
@@ -11879,8 +12517,6 @@ x_destroy_window (f)
   if (f == dpyinfo->x_highlight_frame)
     dpyinfo->x_highlight_frame = 0;
 
-  dpyinfo->reference_count--;
-
   if (f == dpyinfo->mouse_face_mouse_frame)
     {
       dpyinfo->mouse_face_beg_row
@@ -11894,6 +12530,24 @@ x_destroy_window (f)
 
   UNBLOCK_INPUT;
 }
+
+
+/* Destroy the X window of frame F.  */
+
+void
+x_destroy_window (f)
+     struct frame *f;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+  /* If a display connection is dead, don't try sending more
+     commands to the X server.  */
+  if (dpyinfo->display != 0)
+    x_free_frame_resources (f);
+
+  dpyinfo->reference_count--;
+}
+
 \f
 /* Setting window manager hints.  */
 
@@ -12150,24 +12804,38 @@ x_get_font_info (f, font_idx)
 }
 
 
-/* Return a list of names of available fonts matching PATTERN on frame
-   F.  If SIZE is not 0, it is the size (maximum bound width) of fonts
-   to be listed.  Frame F NULL means we have not yet created any
-   frame on X, and consult the first display in x_display_list.
-   MAXNAMES sets a limit on how many fonts to match.  */
+/* Return a list of names of available fonts matching PATTERN on frame F.
+
+   If SIZE is > 0, it is the size (maximum bounds width) of fonts
+   to be listed.
+
+   SIZE < 0 means include scalable fonts.
+
+   Frame F null means we have not yet created any frame on X, and
+   consult the first display in x_display_list.  MAXNAMES sets a limit
+   on how many fonts to match.  */
 
 Lisp_Object
 x_list_fonts (f, pattern, size, maxnames)
-     FRAME_PTR f;
+     struct frame *f;
      Lisp_Object pattern;
      int size;
      int maxnames;
 {
   Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
   Lisp_Object tem, second_best;
-  Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
+  struct x_display_info *dpyinfo
+    = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
+  Display *dpy = dpyinfo->display;
   int try_XLoadQueryFont = 0;
   int count;
+  int allow_scalable_fonts_p = 0;
+
+  if (size < 0)
+    {
+      allow_scalable_fonts_p = 1;
+      size = 0;
+    }
 
   patterns = Fassoc (pattern, Valternate_fontname_alist);
   if (NILP (patterns))
@@ -12180,16 +12848,17 @@ 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.
          The cache is an alist of the form:
-          (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
-      */
-      if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
-               key = Fcons (pattern, make_number (maxnames)),
-               !NILP (list = Fassoc (key, tem))))
+        ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...)  */
+      tem = XCDR (dpyinfo->name_list_element);
+      key = Fcons (Fcons (pattern, make_number (maxnames)),
+                  allow_scalable_fonts_p ? Qt : Qnil);
+      list = Fassoc (key, tem);
+      if (!NILP (list))
        {
          list = Fcdr_safe (list);
          /* We have a cashed list.  Don't have to get the list again.  */
@@ -12276,10 +12945,10 @@ x_list_fonts (f, pattern, size, maxnames)
              int average_width = -1, dashes = 0;
              
              /* Count the number of dashes in NAMES[I].  If there are
-               14 dashes, and the field value following 12th dash
-               (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
-               is usually too ugly to be used for editing.  Let's
-               ignore it.  */
+                14 dashes, and the field value following 12th dash
+                (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
+                is usually too ugly to be used for editing.  Let's
+                ignore it.  */
              while (*p)
                if (*p++ == '-')
                  {
@@ -12289,7 +12958,9 @@ x_list_fonts (f, pattern, size, maxnames)
                    else if (dashes == 12) /* AVERAGE_WIDTH field */
                      average_width = atoi (p);
                  }
-             if (dashes < 14 || average_width != 0)
+             
+             if (allow_scalable_fonts_p
+                 || dashes < 14 || average_width != 0)
                {
                  tem = build_string (names[i]);
                  if (NILP (Fassoc (tem, list)))
@@ -12312,10 +12983,8 @@ x_list_fonts (f, pattern, size, maxnames)
        }
 
       /* Now store the result in the cache.  */
-      if (f != NULL)
-       XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
-         = Fcons (Fcons (key, list),
-                  XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
+      XCDR (dpyinfo->name_list_element)
+        = Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element));
 
     label_cached:
       if (NILP (list)) continue; /* Try the remaining alternatives.  */
@@ -12339,7 +13008,7 @@ x_list_fonts (f, pattern, size, maxnames)
          if (!INTEGERP (XCDR (tem)))
            {
              /* Since we have not yet known the size of this font, we
-               must try slow function call XLoadQueryFont.  */
+                must try slow function call XLoadQueryFont.  */
              XFontStruct *thisinfo;
 
              BLOCK_INPUT;
@@ -12623,13 +13292,6 @@ x_load_font (f, fontname, size)
 
     fontp->size = font->max_bounds.width;
     fontp->height = FONT_HEIGHT (font);
-    {
-      /* For some font, ascent and descent in max_bounds field is
-        larger than the above value.  */
-      int max_height = font->max_bounds.ascent + font->max_bounds.descent;
-      if (max_height > fontp->height)
-       fontp->height = max_height;
-    }
 
     if (NILP (font_names))
       {
@@ -12638,20 +13300,26 @@ x_load_font (f, fontname, size)
           the cache for x_list_fonts.  */
        Lisp_Object lispy_name = build_string (fontname);
        Lisp_Object lispy_full_name = build_string (fontp->full_name);
+       Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
+                                Qnil);
 
        XCDR (dpyinfo->name_list_element)
-         = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
+         = Fcons (Fcons (key,
                          Fcons (Fcons (lispy_full_name,
                                        make_number (fontp->size)),
                                 Qnil)),
                   XCDR (dpyinfo->name_list_element));
        if (full_name)
-         XCDR (dpyinfo->name_list_element)
-           = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
-                           Fcons (Fcons (lispy_full_name,
-                                         make_number (fontp->size)),
-                                  Qnil)),
-                    XCDR (dpyinfo->name_list_element));
+         {
+           key = Fcons (Fcons (lispy_full_name, make_number (256)),
+                        Qnil);
+           XCDR (dpyinfo->name_list_element)
+             = Fcons (Fcons (key,
+                             Fcons (Fcons (lispy_full_name,
+                                           make_number (fontp->size)),
+                                    Qnil)),
+                      XCDR (dpyinfo->name_list_element));
+         }
       }
 
     /* The slot `encoding' specifies how to map a character
@@ -12736,15 +13404,19 @@ x_find_ccl_program (fontp)
 {
   Lisp_Object list, elt;
 
+  elt = Qnil;
   for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
     {
       elt = XCAR (list);
       if (CONSP (elt)
          && STRINGP (XCAR (elt))
-         && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
-             >= 0))
+         && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
+              >= 0)
+             || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
+                 >= 0)))
        break;
     }
+  
   if (! NILP (list))
     {
       struct ccl_program *ccl
@@ -12901,6 +13573,7 @@ x_term_init (display_name, xrm_option, resource_name)
   /* We have definitely succeeded.  Record the new connection.  */
 
   dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
+  bzero (dpyinfo, sizeof *dpyinfo);
 
 #ifdef MULTI_KBOARD
   {
@@ -13113,7 +13786,7 @@ x_term_init (display_name, xrm_option, resource_name)
 
   {
     extern int gray_bitmap_width, gray_bitmap_height;
-    extern unsigned char *gray_bitmap_bits;
+    extern char *gray_bitmap_bits;
     dpyinfo->gray
       = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
                                     gray_bitmap_bits,
@@ -13252,8 +13925,10 @@ x_delete_display (dpyinfo)
   
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->x_id_name);
+  xfree (dpyinfo->color_cells);
   xfree (dpyinfo);
 }
+
 \f
 /* Set up use of X before we make the first connection.  */
 
@@ -13269,6 +13944,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
 };
@@ -13301,7 +13977,7 @@ x_initialize ()
   estimate_mode_line_height_hook = x_estimate_mode_line_height;
 
   scroll_region_ok = 1;                /* we'll scroll partial frames */
-  char_ins_del_ok = 0;         /* just as fast to write the line */
+  char_ins_del_ok = 1;
   line_ins_del_ok = 1;         /* we'll just blt 'em */
   fast_clear_end_of_line = 1;  /* X does this well */
   memory_below_frame = 0;      /* we don't remember what scrolls
@@ -13332,7 +14008,7 @@ x_initialize ()
   }
 #endif
   
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
   xaw3d_arrow_scroll = False;
   xaw3d_pick_top = True;
 #endif
@@ -13369,10 +14045,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\
@@ -13380,12 +14061,20 @@ For example, if a block cursor is over a tab, it will be drawn as\n\
 wide as that tab on the display.");
   x_stretch_cursor_p = 0;
 
-  DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
-    "If not nil, Emacs uses toolkit scroll bars.");
-#if USE_TOOLKIT_SCROLL_BARS
-  x_toolkit_scroll_bars_p = 1;
+  DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
+    "What X toolkit scroll bars Emacs uses.\n\
+A value of nil means Emacs doesn't use X toolkit scroll bars.\n\
+Otherwise, value is a symbol describing the X toolkit.");
+#ifdef USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_MOTIF
+  Vx_toolkit_scroll_bars = intern ("motif");
+#elif defined HAVE_XAW3D
+  Vx_toolkit_scroll_bars = intern ("xaw3d");
+#else
+  Vx_toolkit_scroll_bars = intern ("xaw");
+#endif
 #else
-  x_toolkit_scroll_bars_p = 0;
+  Vx_toolkit_scroll_bars = Qnil;
 #endif
 
   staticpro (&last_mouse_motion_frame);
@@ -13393,4 +14082,3 @@ wide as that tab on the display.");
 }
 
 #endif /* not HAVE_X_WINDOWS */
-