(XTread_socket): Change calls to gen_help_event.
[bpt/emacs.git] / src / xterm.c
index 3b774e3..ccd9f8b 100644 (file)
@@ -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
@@ -246,6 +245,9 @@ int x_toolkit_scroll_bars_p;
    (The display is done in read_char.)  */
    
 static Lisp_Object help_echo;
+static Lisp_Object help_echo_window;
+static Lisp_Object help_echo_object;
+static int help_echo_pos;
 
 /* Temporary variable for XTread_socket.  */
 
@@ -384,8 +386,8 @@ extern int extra_keyboard_modifiers;
 
 static Lisp_Object Qvendor_specific_keysyms;
 
-extern XrmDatabase x_load_resources ();
-extern Lisp_Object x_icon_type ();
+extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
+extern Lisp_Object x_icon_type P_ ((struct frame *));
 
 
 /* Enumeration for overriding/changing the face to use for drawing
@@ -401,7 +403,7 @@ enum draw_glyphs_face
   DRAW_IMAGE_SUNKEN
 };
 
-static void x_update_window_end P_ ((struct window *, int));
+static void x_update_window_end P_ ((struct window *, int, int));
 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
 void x_delete_display P_ ((struct x_display_info *));
 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
@@ -474,7 +476,13 @@ static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
 static void x_flush P_ ((struct frame *f));
-     
+static void x_update_begin P_ ((struct frame *));
+static void x_update_window_begin P_ ((struct window *));
+static void x_draw_vertical_border P_ ((struct window *));
+static void x_after_update_window_line P_ ((struct glyph_row *));
+static INLINE void take_vertical_position_into_account P_ ((struct it *));
+static void x_produce_stretch_glyph P_ ((struct it *));
+
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
@@ -601,6 +609,13 @@ x_update_window_begin (w)
       if (FRAME_GARBAGED_P (f))
        display_info->mouse_face_window = Qnil;
 
+#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
+        their mouse_face_p flag set, which means that they are always
+        unequal to rows in a desired matrix which never have that
+        flag set.  So, rows containing mouse-face glyphs are never
+        scrolled, and we don't have to switch the mouse highlight off
+        here to prevent it from being scrolled.  */
+      
       /* Can we tell that this update does not affect the window
         where the mouse highlight is?  If so, no need to turn off.
         Likewise, don't do anything if the frame is garbaged;
@@ -618,6 +633,7 @@ x_update_window_begin (w)
          if (i < w->desired_matrix->nrows)
            clear_mouse_face (display_info);
        }
+#endif /* 0 */
     }
 
   UNBLOCK_INPUT;
@@ -652,24 +668,45 @@ x_draw_vertical_border (w)
 }
    
    
-/* End update of window W (which is equal to updated_window).  Draw
-   vertical borders between horizontally adjacent windows, and display
-   W's cursor if CURSOR_ON_P is non-zero.  W may be a menu bar
-   pseudo-window in case we don't have X toolkit support.  Such
-   windows don't have a cursor, so don't display it here.  */
+/* End update of window W (which is equal to updated_window).
+
+   Draw vertical borders between horizontally adjacent windows, and
+   display W's cursor if CURSOR_ON_P is non-zero.
+
+   MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
+   glyphs in mouse-face were overwritten.  In that case we have to
+   make sure that the mouse-highlight is properly redrawn.
+
+   W may be a menu bar pseudo-window in case we don't have X toolkit
+   support.  Such windows don't have a cursor, so don't display it
+   here.  */
 
 static void
-x_update_window_end (w, cursor_on_p)
+x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
      struct window *w;
-     int cursor_on_p;
+     int cursor_on_p, mouse_face_overwritten_p;
 {
   if (!w->pseudo_window_p)
     {
+      struct x_display_info *dpyinfo
+       = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+      
       BLOCK_INPUT;
+
+      /* If a row with mouse-face was overwritten, arrange for
+        XTframe_up_to_date to redisplay the mouse highlight.  */
+      if (mouse_face_overwritten_p)
+       {
+         dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+         dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+         dpyinfo->mouse_face_window = Qnil;
+       }
+      
       if (cursor_on_p)
        x_display_and_set_cursor (w, 1, output_cursor.hpos,
                                  output_cursor.vpos,
                                  output_cursor.x, output_cursor.y);
+      
       x_draw_vertical_border (w);
       UNBLOCK_INPUT;
     }
@@ -705,6 +742,7 @@ XTframe_up_to_date (f)
   if (FRAME_X_P (f))
     {
       struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
       if (dpyinfo->mouse_face_deferred_gc
          || f == dpyinfo->mouse_face_mouse_frame)
        {
@@ -1390,24 +1428,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];
     }
 }
@@ -1427,23 +1461,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];
     }
 }
@@ -1518,16 +1549,19 @@ x_produce_image_glyph (it)
       glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
       if (glyph < it->glyph_row->glyphs[area + 1])
        {
-         glyph->type = IMAGE_GLYPH;
-         glyph->u.img_id = img->id;
-         glyph->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];
        }
     }
@@ -1554,17 +1588,20 @@ x_append_stretch_glyph (it, object, width, height, ascent)
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
-      glyph->type = STRETCH_GLYPH;
-      glyph->u.stretch.ascent = height * ascent;
-      glyph->u.stretch.height = height;
-      glyph->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];
     }
 }
@@ -2492,6 +2529,9 @@ 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 *));
@@ -2665,7 +2705,6 @@ x_set_mode_line_face_gc (s)
      struct glyph_string *s;
 {     
   s->gc = s->face->gc;
-  xassert (s->gc != 0);
 }
 
 
@@ -2677,6 +2716,8 @@ static INLINE void
 x_set_glyph_string_gc (s)
      struct glyph_string *s;
 {
+  PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+  
   if (s->hl == DRAW_NORMAL_TEXT)
     {
       s->gc = s->face->gc;
@@ -3164,7 +3205,7 @@ static struct frame *x_frame_of_widget P_ ((Widget));
 /* Return the frame on which widget WIDGET is used.. Abort if frame
    cannot be determined.  */
 
-struct frame *
+static struct frame *
 x_frame_of_widget (widget)
      Widget widget;
 {
@@ -3680,8 +3721,18 @@ x_draw_image_foreground (s)
        }
       else
        {
-         XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
+         unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
+         XGCValues xgcv;
+         XRectangle clip_rect, image_rect, r;
+
+         x_get_glyph_string_clip_rect (s, &clip_rect);
+         image_rect.x = x;
+         image_rect.y = y;
+         image_rect.width = s->img->width;
+         image_rect.height = s->img->height;
+         if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
+           XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
+                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
          
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -4138,11 +4189,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.  */
 
@@ -4196,11 +4248,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.  */
 
@@ -4283,19 +4336,48 @@ x_fill_image_glyph_string (s)
 }
 
 
-/* Fill glyph string S from stretch glyph S->first_glyph.  */
+/* Fill glyph string S from a sequence of stretch glyphs.
 
-static void
-x_fill_stretch_glyph_string (s)
+   ROW is the glyph row in which the glyphs are found, AREA is the
+   area within the row.  START is the index of the first glyph to
+   consider, END is the index of the last + 1.
+
+   Value is the index of the first glyph not in S.  */
+
+static int
+x_fill_stretch_glyph_string (s, row, area, start, end)
      struct glyph_string *s;
+     struct glyph_row *row;
+     enum glyph_row_area area;
+     int start, end;
 {
+  struct glyph *glyph, *last;
+  int voffset, face_id;
+  
   xassert (s->first_glyph->type == STRETCH_GLYPH);
-  s->face = FACE_FROM_ID (s->f, s->first_glyph->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];
 }
 
 
@@ -4384,9 +4466,8 @@ x_set_glyph_string_background_width (s, start, last_x)
        {                                                                   \
         s = (struct glyph_string *) alloca (sizeof *s);                    \
         x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL);            \
-        x_fill_stretch_glyph_string (s);                                   \
+        START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END);    \
         x_append_glyph_string (&HEAD, &TAIL, s);                           \
-        ++START;                                                           \
          s->x = (X);                                                       \
        }                                                                   \
      while (0)
@@ -6077,37 +6158,10 @@ construct_mouse_click (result, event, f)
   XSETINT (result->x, event->x);
   XSETINT (result->y, event->y);
   XSETFRAME (result->frame_or_window, f);
+  result->arg = Qnil;
   return Qnil;
 }
 
-#if 0 /* This function isn't called. --gerd  */
-
-/* Prepare a menu-event in *RESULT for placement in the input queue.  */
-
-static Lisp_Object
-construct_menu_click (result, event, f)
-     struct input_event *result;
-     XButtonEvent *event;
-     struct frame *f;
-{
-  /* Make the event type no_event; we'll change that when we decide
-     otherwise.  */
-  result->kind = mouse_click;
-  result->code = event->button - Button1;
-  result->timestamp = event->time;
-  result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              event->state)
-                      | (event->type == ButtonRelease
-                         ? up_modifier
-                         : down_modifier));
-
-  XSETINT (result->x, event->x);
-  XSETINT (result->y, -1);
-  XSETFRAME (result->frame_or_window, f);
-}
-
-#endif /* 0 */
-
 \f
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
@@ -6318,14 +6372,26 @@ note_mode_line_highlight (w, x, mode_line_p)
             setting the global variable help_echo to the help string.  */
          help = Fget_text_property (make_number (glyph->charpos),
                                     Qhelp_echo, glyph->object);
-         if (STRINGP (help))
-           help_echo = help;
+         if (!NILP (help))
+           {
+             help_echo = help;
+             XSETWINDOW (help_echo_window, w);
+             help_echo_object = glyph->object;
+             help_echo_pos = glyph->charpos;
+           }
 
          /* Change the mouse pointer according to what is under X/Y.  */
          map = Fget_text_property (make_number (glyph->charpos),
                                    Qlocal_map, glyph->object);
          if (!NILP (Fkeymapp (map)))
            cursor = f->output_data.x->nontext_cursor;
+         else
+           {
+             map = Fget_text_property (make_number (glyph->charpos),
+                                       Qkeymap, glyph->object);
+             if (!NILP (Fkeymapp (map)))
+               cursor = f->output_data.x->nontext_cursor;
+           }
        }
     }
 
@@ -6460,14 +6526,15 @@ note_mouse_highlight (f, x, y)
           enough space for all, and try again.  */
        len = 10;
        overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-       noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
+       noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
        if (noverlays > len)
          {
            len = noverlays;
            overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-           noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
+           noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
          }
-         
+
+       /* Sort overlays into increasing priority order.  */
        noverlays = sort_overlays (overlay_vec, noverlays, w);
 
        /* Check mouse-face highlighting.  */
@@ -6485,7 +6552,7 @@ note_mouse_highlight (f, x, y)
 
            /* Find the highest priority overlay that has a mouse-face prop.  */
            overlay = Qnil;
-           for (i = 0; i < noverlays; i++)
+           for (i = noverlays - 1; i >= 0; --i)
              {
                mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
                if (!NILP (mouse_face))
@@ -6571,26 +6638,43 @@ note_mouse_highlight (f, x, y)
 
        /* Look for a `help-echo' property.  */
        {
-         Lisp_Object help;
+         Lisp_Object help, overlay;
 
          /* Check overlays first.  */
          help = Qnil;
-         for (i = 0; i < noverlays && !STRINGP (help); ++i)
-           help = Foverlay_get (overlay_vec[i], Qhelp_echo); 
-           
-         /* Try text properties.  */
-         if (!STRINGP (help)
-             && ((STRINGP (glyph->object)
+         for (i = noverlays - 1; i >= 0 && NILP (help); --i)
+           {
+             overlay = overlay_vec[i];
+             help = Foverlay_get (overlay, Qhelp_echo);
+           }
+
+         if (!NILP (help))
+           {
+             help_echo = help;
+             help_echo_window = window;
+             help_echo_object = overlay;
+             help_echo_pos = pos;
+           }
+         else
+           {
+             /* Try text properties.  */
+             if ((STRINGP (glyph->object)
                   && glyph->charpos >= 0
                   && glyph->charpos < XSTRING (glyph->object)->size)
                  || (BUFFERP (glyph->object)
                      && glyph->charpos >= BEGV
-                     && glyph->charpos < ZV)))
-           help = Fget_text_property (make_number (glyph->charpos),
-                                      Qhelp_echo, glyph->object);
+                     && glyph->charpos < ZV))
+               help = Fget_text_property (make_number (glyph->charpos),
+                                          Qhelp_echo, glyph->object);
            
-         if (STRINGP (help))
-           help_echo = help;
+             if (!NILP (help))
+               {
+                 help_echo = help;
+                 help_echo_window = window;
+                 help_echo_object = glyph->object;
+                 help_echo_pos = glyph->charpos;
+               }
+           }
        }
          
        BEGV = obegv;
@@ -6720,11 +6804,13 @@ x_handle_tool_bar_click (f, button_event)
 
       XSETFRAME (frame, f);
       event.kind = TOOL_BAR_EVENT;
-      event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
+      event.frame_or_window = frame;
+      event.arg = frame;
       kbd_buffer_store_event (&event);
 
       event.kind = TOOL_BAR_EVENT;
-      event.frame_or_window = Fcons (frame, key);
+      event.frame_or_window = frame;
+      event.arg = key;
       event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
                                                button_event->state);
       kbd_buffer_store_event (&event);
@@ -6820,9 +6906,11 @@ note_tool_bar_highlight (f, x, y)
   
   /* Set help_echo to a help string.to display for this tool-bar item.
      XTread_socket does the rest.  */
+  help_echo_object = help_echo_window = Qnil;
+  help_echo_pos = -1;
   help_echo = (XVECTOR (f->current_tool_bar_items)
               ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
-  if (!STRINGP (help_echo))
+  if (NILP (help_echo))
     help_echo = (XVECTOR (f->current_tool_bar_items)
                 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
 }
@@ -6994,8 +7082,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.  */
@@ -7038,6 +7129,24 @@ clear_mouse_face (dpyinfo)
   dpyinfo->mouse_face_window = Qnil;
 }
 
+
+/* Clear any mouse-face on window W.  This function is part of the
+   redisplay interface, and is called from try_window_id and similar
+   functions to ensure the mouse-highlight is off.  */
+
+static void
+x_clear_mouse_face (w)
+     struct window *w;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+  Lisp_Object window;
+
+  XSETWINDOW (window, w);
+  if (EQ (window, dpyinfo->mouse_face_window))
+    clear_mouse_face (dpyinfo);
+}
+
+
 /* Just discard the mouse face information for frame F, if any.
    This is used when the size of F is changed.  */
 
@@ -7480,6 +7589,7 @@ x_scroll_bar_to_input_event (event, ievent)
   
   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];
@@ -8526,6 +8636,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
          ? up_modifier
          : down_modifier));
   emacs_event->frame_or_window = bar->window;
+  emacs_event->arg = Qnil;
   emacs_event->timestamp = event->xbutton.time;
   {
 #if 0
@@ -8881,6 +8992,7 @@ static struct x_display_info *next_noop_dpyinfo;
            {                                                           \
              bufp->kind = menu_bar_activate_event;                     \
              XSETFRAME (bufp->frame_or_window, f);                     \
+             bufp->arg = Qnil;                                         \
              bufp++;                                                   \
              count++;                                                  \
              numchars--;                                               \
@@ -8915,6 +9027,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)
     {
@@ -8931,6 +9044,20 @@ XTread_socket (sd, bufp, numchars, expected)
   if (numchars <= 0)
     abort ();                  /* Don't think this happens.  */
 
+  ++handling_signal;
+  
+  /* The input should be decoded if it is from XIM.  Currently the
+     locale of XIM is the same as that of the system.  So, we can use
+     Vlocale_coding_system which is initialized properly at Emacs
+     startup time.  */
+  setup_coding_system (Vlocale_coding_system, &coding);
+  coding.src_multibyte = 0;
+  coding.dst_multibyte = 1;
+  /* The input is converted to events, thus we can't handle
+     composition.  Anyway, there's no XIM that gives us composition
+     information.  */
+  coding.composing = COMPOSITION_DISABLED;
+
   /* Find the display we are supposed to read input for.
      It's the one communicating on descriptor SD.  */
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
@@ -9082,6 +9209,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                            bufp->kind = delete_window_event;
                            XSETFRAME (bufp->frame_or_window, f);
+                           bufp->arg = Qnil;
                            bufp++;
 
                            count += 1;
@@ -9174,6 +9302,7 @@ XTread_socket (sd, bufp, numchars, expected)
                SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
                SELECTION_EVENT_TIME (bufp) = eventp->time;
                bufp->frame_or_window = Qnil;
+               bufp->arg = Qnil;
                bufp++;
 
                count += 1;
@@ -9204,6 +9333,7 @@ XTread_socket (sd, bufp, numchars, expected)
                  SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
                  SELECTION_EVENT_TIME (bufp) = eventp->time;
                  bufp->frame_or_window = Qnil;
+                 bufp->arg = Qnil;
                  bufp++;
 
                  count += 1;
@@ -9317,6 +9447,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                      bufp->kind = iconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
@@ -9348,6 +9479,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      bufp->kind = deiconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
@@ -9382,9 +9514,20 @@ XTread_socket (sd, bufp, numchars, expected)
              if (f != 0)
                {
                  KeySym keysym, orig_keysym;
-                 /* al%imercury@uunet.uu.net says that making this 81 instead of
-                    80 fixed a bug whereby meta chars made his Emacs hang.  */
-                 unsigned char copy_buffer[81];
+                 /* al%imercury@uunet.uu.net says that making this 81
+                    instead of 80 fixed a bug whereby meta chars made
+                    his Emacs hang.
+
+                    It seems that some version of XmbLookupString has
+                    a bug of not returning XBufferOverflow in
+                    status_return even if the input is too long to
+                    fit in 81 bytes.  So, we must prepare sufficient
+                    bytes for copy_buffer.  513 bytes (256 chars for
+                    two-byte character set) seems to be a faily good
+                    approximation.  -- 2000.8.10 handa@etl.go.jp  */
+                 unsigned char copy_buffer[513];
+                 unsigned char *copy_bufptr = copy_buffer;
+                 int copy_bufsiz = sizeof (copy_buffer);
                  int modifiers;
 
                  event.xkey.state
@@ -9413,8 +9556,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),
@@ -9443,11 +9584,13 @@ XTread_socket (sd, bufp, numchars, expected)
                        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;
@@ -9530,6 +9673,7 @@ XTread_socket (sd, bufp, numchars, expected)
                          bufp->kind = non_ascii_keystroke;
                          bufp->code = keysym;
                          XSETFRAME (bufp->frame_or_window, f);
+                         bufp->arg = Qnil;
                          bufp->modifiers
                            = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
                                                      modifiers);
@@ -9541,15 +9685,56 @@ XTread_socket (sd, bufp, numchars, expected)
                      else if (numchars > nbytes)
                        {
                          register int i;
+                         register int c;
+                         unsigned char *p, *pend;
+                         int nchars, len;
 
                          for (i = 0; i < nbytes; i++)
                            {
-                             if (temp_index == sizeof temp_buffer / sizeof (short))
+                             if (temp_index == (sizeof temp_buffer
+                                                / sizeof (short)))
                                temp_index = 0;
-                             temp_buffer[temp_index++] = copy_buffer[i];
-                             bufp->kind = ascii_keystroke;
-                             bufp->code = copy_buffer[i];
+                             temp_buffer[temp_index++] = copy_bufptr[i];
+                           }
+
+                         if (/* If the event is not from XIM, */
+                             event.xkey.keycode != 0
+                             /* or the current locale doesn't request
+                                decoding of the intup data, ... */
+                             || coding.type == coding_type_raw_text
+                             || coding.type == coding_type_no_conversion)
+                           {
+                             /* ... we can use the input data as is.  */
+                             nchars = nbytes;
+                           }
+                         else
+                           { 
+                             /* We have to decode the input data.  */
+                             int require;
+                             unsigned char *p;
+
+                             require = decoding_buffer_size (&coding, nbytes);
+                             p = (unsigned char *) alloca (require);
+                             coding.mode |= CODING_MODE_LAST_BLOCK;
+                             decode_coding (&coding, copy_bufptr, p,
+                                            nbytes, require);
+                             nbytes = coding.produced;
+                             nchars = coding.produced_char;
+                             copy_bufptr = p;
+                           }
+
+                         /* Convert the input data to a sequence of
+                            character events.  */
+                         for (i = 0; i < nbytes; i += len)
+                           {
+                             c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
+                                                         nbytes - i, len);
+                             bufp->kind = (SINGLE_BYTE_CHAR_P (c)
+                                           ? ascii_keystroke
+                                           : multibyte_char_keystroke);
+                             bufp->code = c;
                              XSETFRAME (bufp->frame_or_window, f);
+                             bufp->arg = Qnil;
                              bufp->modifiers
                                = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
                                                          modifiers);
@@ -9557,8 +9742,8 @@ XTread_socket (sd, bufp, numchars, expected)
                              bufp++;
                            }
 
-                         count += nbytes;
-                         numchars -= nbytes;
+                         count += nchars;
+                         numchars -= nchars;
 
                          if (keysym == NoSymbol)
                            break;
@@ -9668,6 +9853,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      bufp->kind = FOCUS_IN_EVENT;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      ++bufp, ++count, --numchars;
                    }
                }
@@ -9700,10 +9886,13 @@ XTread_socket (sd, bufp, numchars, expected)
                     the mouse leaves the frame.  */
                  if (any_help_event_p)
                    {
+                     Lisp_Object frame;
+                     int n;
+
                      XSETFRAME (frame, f);
-                     bufp->kind = HELP_EVENT;
-                     bufp->frame_or_window = Fcons (frame, Qnil);
-                     ++bufp, ++count, --numchars;
+                     n = gen_help_event (bufp, numchars,
+                                         Qnil, frame, Qnil, Qnil, 0);
+                     bufp += n, count += n, numchars -= n;
                    }
 
 #ifdef LESSTIF_VERSION
@@ -9750,7 +9939,8 @@ XTread_socket (sd, bufp, numchars, expected)
            case MotionNotify:
              {
                previous_help_echo = help_echo;
-               help_echo = Qnil;
+               help_echo = help_echo_object = help_echo_window = Qnil;
+               help_echo_pos = -1;
                
                if (dpyinfo->grabbed && last_mouse_frame
                    && FRAME_LIVE_P (last_mouse_frame))
@@ -9777,10 +9967,11 @@ XTread_socket (sd, bufp, numchars, expected)
 
                /* If the contents of the global variable help_echo
                   has changed, generate a HELP_EVENT.  */
-               if (STRINGP (help_echo)
-                   || STRINGP (previous_help_echo))
+               if (!NILP (help_echo)
+                   || !NILP (previous_help_echo))
                  {
                    Lisp_Object frame;
+                   int n;
 
                    if (f)
                      XSETFRAME (frame, f);
@@ -9788,9 +9979,10 @@ XTread_socket (sd, bufp, numchars, expected)
                      frame = Qnil;
 
                    any_help_event_p = 1;
-                   bufp->kind = HELP_EVENT;
-                   bufp->frame_or_window = Fcons (frame, help_echo);
-                   ++bufp, ++count, --numchars;
+                   n = gen_help_event (bufp, numchars, help_echo, frame,
+                                       help_echo_window, help_echo_object,
+                                       help_echo_pos);
+                   bufp += n, count += n, numchars -= n;
                  }
                
                goto OTHER;
@@ -10050,6 +10242,7 @@ XTread_socket (sd, bufp, numchars, expected)
     }
 
   UNBLOCK_INPUT;
+  --handling_signal;
   return count;
 }
 
@@ -10186,24 +10379,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;
@@ -10211,7 +10413,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
@@ -10219,10 +10421,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,
@@ -11097,6 +11299,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);
@@ -11114,9 +11317,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 */
 }
 
 
@@ -11190,6 +11398,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;
@@ -11211,6 +11420,10 @@ xim_initialize (dpyinfo, resource_name)
   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 */
 }
 
 
@@ -11220,6 +11433,7 @@ 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,
@@ -11228,6 +11442,7 @@ xim_close_dpy (dpyinfo)
   XCloseIM (dpyinfo->xim);
   dpyinfo->xim = NULL;
   XFree (dpyinfo->xim_styles);
+#endif /* USE_XIM */
 }
 
 #endif /* not HAVE_X11R6_XIM */
@@ -13378,6 +13593,7 @@ static struct redisplay_interface x_redisplay_interface =
   x_update_window_end,
   XTcursor_to,
   x_flush,
+  x_clear_mouse_face,
   x_get_glyph_overhangs,
   x_fix_overlapping_area
 };
@@ -13478,10 +13694,15 @@ syms_of_xterm ()
   staticpro (&last_mouse_press_frame);
   last_mouse_press_frame = Qnil;
 
-  staticpro (&help_echo);
   help_echo = Qnil;
-  staticpro (&previous_help_echo);
+  staticpro (&help_echo);
+  help_echo_object = Qnil;
+  staticpro (&help_echo_object);
+  help_echo_window = Qnil;
+  staticpro (&help_echo_window);
   previous_help_echo = Qnil;
+  staticpro (&previous_help_echo);
+  help_echo_pos = -1;
 
   DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
     "*Non-nil means draw block cursor as wide as the glyph under it.\n\