(read_char_minibuf_menu_prompt): Add new parameter
[bpt/emacs.git] / src / xterm.c
index 0fe9505..aec7d3b 100644 (file)
@@ -101,8 +101,9 @@ Boston, MA 02111-1307, USA.  */
 
 #ifdef USE_X_TOOLKIT
 
-extern void free_frame_menubar ();
-extern FRAME_PTR x_menubar_window_to_frame ();
+extern void free_frame_menubar P_ ((struct frame *));
+extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
+                                                   int));
 
 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
 #define HACK_EDITRES
@@ -243,6 +244,9 @@ int x_toolkit_scroll_bars_p;
    (The display is done in read_char.)  */
    
 static Lisp_Object help_echo;
+static Lisp_Object help_echo_window;
+static Lisp_Object help_echo_object;
+static int help_echo_pos;
 
 /* Temporary variable for XTread_socket.  */
 
@@ -381,8 +385,8 @@ extern int extra_keyboard_modifiers;
 
 static Lisp_Object Qvendor_specific_keysyms;
 
-extern XrmDatabase x_load_resources ();
-extern Lisp_Object x_icon_type ();
+extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
+extern Lisp_Object x_icon_type P_ ((struct frame *));
 
 
 /* Enumeration for overriding/changing the face to use for drawing
@@ -398,7 +402,7 @@ enum draw_glyphs_face
   DRAW_IMAGE_SUNKEN
 };
 
-static void x_update_window_end P_ ((struct window *, int));
+static void x_update_window_end P_ ((struct window *, int, int));
 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
 void x_delete_display P_ ((struct x_display_info *));
 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
@@ -471,7 +475,13 @@ static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
 static void x_flush P_ ((struct frame *f));
-     
+static void x_update_begin P_ ((struct frame *));
+static void x_update_window_begin P_ ((struct window *));
+static void x_draw_vertical_border P_ ((struct window *));
+static void x_after_update_window_line P_ ((struct glyph_row *));
+static INLINE void take_vertical_position_into_account P_ ((struct it *));
+static void x_produce_stretch_glyph P_ ((struct it *));
+
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
@@ -657,24 +667,45 @@ x_draw_vertical_border (w)
 }
    
    
-/* End update of window W (which is equal to updated_window).  Draw
-   vertical borders between horizontally adjacent windows, and display
-   W's cursor if CURSOR_ON_P is non-zero.  W may be a menu bar
-   pseudo-window in case we don't have X toolkit support.  Such
-   windows don't have a cursor, so don't display it here.  */
+/* End update of window W (which is equal to updated_window).
+
+   Draw vertical borders between horizontally adjacent windows, and
+   display W's cursor if CURSOR_ON_P is non-zero.
+
+   MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
+   glyphs in mouse-face were overwritten.  In that case we have to
+   make sure that the mouse-highlight is properly redrawn.
+
+   W may be a menu bar pseudo-window in case we don't have X toolkit
+   support.  Such windows don't have a cursor, so don't display it
+   here.  */
 
 static void
-x_update_window_end (w, cursor_on_p)
+x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
      struct window *w;
-     int cursor_on_p;
+     int cursor_on_p, mouse_face_overwritten_p;
 {
   if (!w->pseudo_window_p)
     {
+      struct x_display_info *dpyinfo
+       = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+      
       BLOCK_INPUT;
+
+      /* If a row with mouse-face was overwritten, arrange for
+        XTframe_up_to_date to redisplay the mouse highlight.  */
+      if (mouse_face_overwritten_p)
+       {
+         dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+         dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+         dpyinfo->mouse_face_window = Qnil;
+       }
+      
       if (cursor_on_p)
        x_display_and_set_cursor (w, 1, output_cursor.hpos,
                                  output_cursor.vpos,
                                  output_cursor.x, output_cursor.y);
+      
       x_draw_vertical_border (w);
       UNBLOCK_INPUT;
     }
@@ -710,6 +741,7 @@ XTframe_up_to_date (f)
   if (FRAME_X_P (f))
     {
       struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
       if (dpyinfo->mouse_face_deferred_gc
          || f == dpyinfo->mouse_face_mouse_frame)
        {
@@ -6115,37 +6147,10 @@ construct_mouse_click (result, event, f)
   XSETINT (result->x, event->x);
   XSETINT (result->y, event->y);
   XSETFRAME (result->frame_or_window, f);
+  result->arg = Qnil;
   return Qnil;
 }
 
-#if 0 /* This function isn't called. --gerd  */
-
-/* Prepare a menu-event in *RESULT for placement in the input queue.  */
-
-static Lisp_Object
-construct_menu_click (result, event, f)
-     struct input_event *result;
-     XButtonEvent *event;
-     struct frame *f;
-{
-  /* Make the event type no_event; we'll change that when we decide
-     otherwise.  */
-  result->kind = mouse_click;
-  result->code = event->button - Button1;
-  result->timestamp = event->time;
-  result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              event->state)
-                      | (event->type == ButtonRelease
-                         ? up_modifier
-                         : down_modifier));
-
-  XSETINT (result->x, event->x);
-  XSETINT (result->y, -1);
-  XSETFRAME (result->frame_or_window, f);
-}
-
-#endif /* 0 */
-
 \f
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
@@ -6357,13 +6362,25 @@ note_mode_line_highlight (w, x, mode_line_p)
          help = Fget_text_property (make_number (glyph->charpos),
                                     Qhelp_echo, glyph->object);
          if (!NILP (help))
-           help_echo = 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;
+           }
        }
     }
 
@@ -6505,7 +6522,8 @@ note_mouse_highlight (f, x, y)
            overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
            noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
          }
-         
+
+       /* Sort overlays into increasing priority order.  */
        noverlays = sort_overlays (overlay_vec, noverlays, w);
 
        /* Check mouse-face highlighting.  */
@@ -6523,7 +6541,7 @@ note_mouse_highlight (f, x, y)
 
            /* Find the highest priority overlay that has a mouse-face prop.  */
            overlay = Qnil;
-           for (i = 0; i < noverlays; i++)
+           for (i = noverlays - 1; i >= 0; --i)
              {
                mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
                if (!NILP (mouse_face))
@@ -6609,26 +6627,43 @@ note_mouse_highlight (f, x, y)
 
        /* Look for a `help-echo' property.  */
        {
-         Lisp_Object help;
+         Lisp_Object help, overlay;
 
          /* Check overlays first.  */
          help = Qnil;
-         for (i = 0; i < noverlays && NILP (help); ++i)
-           help = Foverlay_get (overlay_vec[i], Qhelp_echo); 
-           
-         /* Try text properties.  */
-         if (NILP (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 (!NILP (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;
@@ -6758,11 +6793,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);
@@ -6858,6 +6895,8 @@ 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 (NILP (help_echo))
@@ -7079,6 +7118,24 @@ clear_mouse_face (dpyinfo)
   dpyinfo->mouse_face_window = Qnil;
 }
 
+
+/* Clear any mouse-face on window W.  This function is part of the
+   redisplay interface, and is called from try_window_id and similar
+   functions to ensure the mouse-highlight is off.  */
+
+static void
+x_clear_mouse_face (w)
+     struct window *w;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+  Lisp_Object window;
+
+  XSETWINDOW (window, w);
+  if (EQ (window, dpyinfo->mouse_face_window))
+    clear_mouse_face (dpyinfo);
+}
+
+
 /* Just discard the mouse face information for frame F, if any.
    This is used when the size of F is changed.  */
 
@@ -7521,6 +7578,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];
@@ -8567,6 +8625,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
          ? up_modifier
          : down_modifier));
   emacs_event->frame_or_window = bar->window;
+  emacs_event->arg = Qnil;
   emacs_event->timestamp = event->xbutton.time;
   {
 #if 0
@@ -8922,6 +8981,7 @@ static struct x_display_info *next_noop_dpyinfo;
            {                                                           \
              bufp->kind = menu_bar_activate_event;                     \
              XSETFRAME (bufp->frame_or_window, f);                     \
+             bufp->arg = Qnil;                                         \
              bufp++;                                                   \
              count++;                                                  \
              numchars--;                                               \
@@ -9125,6 +9185,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                            bufp->kind = delete_window_event;
                            XSETFRAME (bufp->frame_or_window, f);
+                           bufp->arg = Qnil;
                            bufp++;
 
                            count += 1;
@@ -9217,6 +9278,7 @@ XTread_socket (sd, bufp, numchars, expected)
                SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
                SELECTION_EVENT_TIME (bufp) = eventp->time;
                bufp->frame_or_window = Qnil;
+               bufp->arg = Qnil;
                bufp++;
 
                count += 1;
@@ -9247,6 +9309,7 @@ XTread_socket (sd, bufp, numchars, expected)
                  SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
                  SELECTION_EVENT_TIME (bufp) = eventp->time;
                  bufp->frame_or_window = Qnil;
+                 bufp->arg = Qnil;
                  bufp++;
 
                  count += 1;
@@ -9360,6 +9423,7 @@ XTread_socket (sd, bufp, numchars, expected)
 
                      bufp->kind = iconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
@@ -9391,6 +9455,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      bufp->kind = deiconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
@@ -9573,6 +9638,7 @@ XTread_socket (sd, bufp, numchars, expected)
                          bufp->kind = non_ascii_keystroke;
                          bufp->code = keysym;
                          XSETFRAME (bufp->frame_or_window, f);
+                         bufp->arg = Qnil;
                          bufp->modifiers
                            = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
                                                      modifiers);
@@ -9593,6 +9659,7 @@ XTread_socket (sd, bufp, numchars, expected)
                              bufp->kind = ascii_keystroke;
                              bufp->code = copy_buffer[i];
                              XSETFRAME (bufp->frame_or_window, f);
+                             bufp->arg = Qnil;
                              bufp->modifiers
                                = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
                                                          modifiers);
@@ -9711,6 +9778,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    {
                      bufp->kind = FOCUS_IN_EVENT;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      ++bufp, ++count, --numchars;
                    }
                }
@@ -9743,10 +9811,12 @@ XTread_socket (sd, bufp, numchars, expected)
                     the mouse leaves the frame.  */
                  if (any_help_event_p)
                    {
+                     Lisp_Object frame;
+                     int n;
+
                      XSETFRAME (frame, f);
-                     bufp->kind = HELP_EVENT;
-                     bufp->frame_or_window = Fcons (frame, Qnil);
-                     ++bufp, ++count, --numchars;
+                     n = gen_help_event (bufp, Qnil, frame, Qnil, Qnil, 0);
+                     bufp += n, count += n, numchars -= n;
                    }
 
 #ifdef LESSTIF_VERSION
@@ -9793,7 +9863,8 @@ XTread_socket (sd, bufp, numchars, expected)
            case MotionNotify:
              {
                previous_help_echo = help_echo;
-               help_echo = Qnil;
+               help_echo = help_echo_object = help_echo_window = Qnil;
+               help_echo_pos = -1;
                
                if (dpyinfo->grabbed && last_mouse_frame
                    && FRAME_LIVE_P (last_mouse_frame))
@@ -9824,6 +9895,7 @@ XTread_socket (sd, bufp, numchars, expected)
                    || !NILP (previous_help_echo))
                  {
                    Lisp_Object frame;
+                   int n;
 
                    if (f)
                      XSETFRAME (frame, f);
@@ -9831,9 +9903,10 @@ XTread_socket (sd, bufp, numchars, expected)
                      frame = Qnil;
 
                    any_help_event_p = 1;
-                   bufp->kind = HELP_EVENT;
-                   bufp->frame_or_window = Fcons (frame, help_echo);
-                   ++bufp, ++count, --numchars;
+                   n = gen_help_event (bufp, help_echo, frame,
+                                       help_echo_window, help_echo_object,
+                                       help_echo_pos);
+                   bufp += n, count += n, numchars -= n;
                  }
                
                goto OTHER;
@@ -13435,6 +13508,7 @@ static struct redisplay_interface x_redisplay_interface =
   x_update_window_end,
   XTcursor_to,
   x_flush,
+  x_clear_mouse_face,
   x_get_glyph_overhangs,
   x_fix_overlapping_area
 };
@@ -13535,10 +13609,15 @@ syms_of_xterm ()
   staticpro (&last_mouse_press_frame);
   last_mouse_press_frame = Qnil;
 
-  staticpro (&help_echo);
   help_echo = Qnil;
-  staticpro (&previous_help_echo);
+  staticpro (&help_echo);
+  help_echo_object = Qnil;
+  staticpro (&help_echo_object);
+  help_echo_window = Qnil;
+  staticpro (&help_echo_window);
   previous_help_echo = Qnil;
+  staticpro (&previous_help_echo);
+  help_echo_pos = -1;
 
   DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
     "*Non-nil means draw block cursor as wide as the glyph under it.\n\