(XTread_socket): Change calls to gen_help_event.
[bpt/emacs.git] / src / xterm.c
index 9664599..ccd9f8b 100644 (file)
@@ -68,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"
@@ -3720,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
@@ -6515,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.  */
@@ -6540,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))
@@ -6626,18 +6638,21 @@ note_mouse_highlight (f, x, y)
 
        /* Look for a `help-echo' property.  */
        {
-         Lisp_Object help, object, position;
+         Lisp_Object help, overlay;
 
          /* Check overlays first.  */
          help = Qnil;
-         for (i = 0; i < noverlays && NILP (help); ++i)
-           help = Foverlay_get (overlay_vec[i], Qhelp_echo);
+         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 = w->buffer;
+             help_echo_object = overlay;
              help_echo_pos = pos;
            }
          else
@@ -9012,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)
     {
@@ -9030,6 +9046,18 @@ XTread_socket (sd, bufp, numchars, expected)
 
   ++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)
@@ -9486,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
@@ -9517,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),
@@ -9547,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;
@@ -9646,14 +9685,54 @@ 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
@@ -9663,8 +9742,8 @@ XTread_socket (sd, bufp, numchars, expected)
                              bufp++;
                            }
 
-                         count += nbytes;
-                         numchars -= nbytes;
+                         count += nchars;
+                         numchars -= nchars;
 
                          if (keysym == NoSymbol)
                            break;
@@ -9811,7 +9890,8 @@ XTread_socket (sd, bufp, numchars, expected)
                      int n;
 
                      XSETFRAME (frame, f);
-                     n = gen_help_event (bufp, Qnil, frame, Qnil, Qnil, 0);
+                     n = gen_help_event (bufp, numchars,
+                                         Qnil, frame, Qnil, Qnil, 0);
                      bufp += n, count += n, numchars -= n;
                    }
 
@@ -9899,7 +9979,7 @@ XTread_socket (sd, bufp, numchars, expected)
                      frame = Qnil;
 
                    any_help_event_p = 1;
-                   n = gen_help_event (bufp, help_echo, frame,
+                   n = gen_help_event (bufp, numchars, help_echo, frame,
                                        help_echo_window, help_echo_object,
                                        help_echo_pos);
                    bufp += n, count += n, numchars -= n;
@@ -10299,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;
@@ -10324,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
@@ -10332,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,