]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
*** empty log message ***
[gnu-emacs] / src / xdisp.c
index b25bebe385731dbc57be65623d7aaa7e491e9ecf..075e05b0e132f28f47223903b61469e44989afb9 100644 (file)
@@ -269,6 +269,12 @@ int auto_raise_tool_bar_buttons_p;
 
 int make_cursor_line_fully_visible_p;
 
+/* Margin below tool bar in pixels.  0 or nil means no margin.
+   If value is `internal-border-width' or `border-width',
+   the corresponding frame parameter is used.  */
+
+Lisp_Object Vtool_bar_border;
+
 /* Margin around tool bar buttons in pixels.  */
 
 Lisp_Object Vtool_bar_button_margin;
@@ -852,7 +858,7 @@ static void store_mode_line_noprop_char P_ ((char));
 static int store_mode_line_noprop P_ ((const unsigned char *, int, int));
 static void x_consider_frame_title P_ ((Lisp_Object));
 static void handle_stop P_ ((struct it *));
-static int tool_bar_lines_needed P_ ((struct frame *));
+static int tool_bar_lines_needed P_ ((struct frame *, int *));
 static int single_display_spec_intangible_p P_ ((Lisp_Object));
 static void ensure_echo_area_buffers P_ ((void));
 static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
@@ -963,7 +969,7 @@ static int in_ellipses_for_invisible_text_p P_ ((struct display_pos *,
 static void update_tool_bar P_ ((struct frame *, int));
 static void build_desired_tool_bar_string P_ ((struct frame *f));
 static int redisplay_tool_bar P_ ((struct frame *));
-static void display_tool_bar_line P_ ((struct it *));
+static void display_tool_bar_line P_ ((struct it *, int));
 static void notice_overwritten_cursor P_ ((struct window *,
                                           enum glyph_row_area,
                                           int, int, int, int));
@@ -1904,7 +1910,7 @@ get_glyph_string_clip_rects (s, rects, n)
     }
 
   if ((s->for_overlaps & OVERLAPS_BOTH) == 0
-      || (s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1)
+      || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
     {
 #ifdef CONVERT_FROM_XRECT
       CONVERT_FROM_XRECT (r, *rects);
@@ -1930,23 +1936,27 @@ get_glyph_string_clip_rects (s, rects, n)
        {
          rs[i] = r;
          if (r.y + r.height > row_y)
-           if (r.y < row_y)
-             rs[i].height = row_y - r.y;
-           else
-             rs[i].height = 0;
+           {
+             if (r.y < row_y)
+               rs[i].height = row_y - r.y;
+             else
+               rs[i].height = 0;
+           }
          i++;
        }
       if (s->for_overlaps & OVERLAPS_SUCC)
        {
          rs[i] = r;
          if (r.y < row_y + s->row->visible_height)
-           if (r.y + r.height > row_y + s->row->visible_height)
-             {
-               rs[i].y = row_y + s->row->visible_height;
-               rs[i].height = r.y + r.height - rs[i].y;
-             }
-           else
-             rs[i].height = 0;
+           {
+             if (r.y + r.height > row_y + s->row->visible_height)
+               {
+                 rs[i].y = row_y + s->row->visible_height;
+                 rs[i].height = r.y + r.height - rs[i].y;
+               }
+             else
+               rs[i].height = 0;
+           }
          i++;
        }
 
@@ -2023,7 +2033,7 @@ get_phys_cursor_geometry (w, row, glyph, heightp)
        }
     }
 
-  *heightp = h - 1;
+  *heightp = h;
   return WINDOW_TO_FRAME_PIXEL_Y (w, y);
 }
 
@@ -3652,8 +3662,11 @@ handle_invisible_prop (it)
                  the invisible text.  Otherwise the cursor would be
                  placed _after_ the ellipsis when the point is after the
                  first invisible character.  */
-              it->position.charpos = IT_CHARPOS (*it) - 1;
-              it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
+             if (!STRINGP (it->object))
+               {
+                 it->position.charpos = IT_CHARPOS (*it) - 1;
+                 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
+               }
               setup_for_ellipsis (it, 0);
             }
        }
@@ -9052,14 +9065,15 @@ update_menu_bar (f, save_match_data)
          /* Redisplay the menu bar in case we changed it.  */
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
     || defined (USE_GTK)
-         if (FRAME_WINDOW_P (f)
-#if defined (MAC_OS)
-              /* All frames on Mac OS share the same menubar.  So only the
-                 selected frame should be allowed to set it.  */
-              && f == SELECTED_FRAME ()
+         if (FRAME_WINDOW_P (f))
+           {
+#ifdef MAC_OS
+              /* All frames on Mac OS share the same menubar.  So only
+                 the selected frame should be allowed to set it.  */
+              if (f == SELECTED_FRAME ())
 #endif
-            )
-           set_frame_menubar (f, 0, 0);
+               set_frame_menubar (f, 0, 0);
+           }
          else
            /* On a terminal screen, the menu bar is an ordinary screen
               line, and this makes it get updated.  */
@@ -9423,11 +9437,22 @@ build_desired_tool_bar_string (f)
 }
 
 
-/* Display one line of the tool-bar of frame IT->f.  */
+/* Display one line of the tool-bar of frame IT->f.
+
+   HEIGHT specifies the desired height of the tool-bar line.
+   If the actual height of the glyph row is less than HEIGHT, the
+   row's height is increased to HEIGHT, and the icons are centered
+   vertically in the new height.
+
+   If HEIGHT is -1, we are counting needed tool-bar lines, so don't
+   count a final empty row in case the tool-bar width exactly matches
+   the window width.
+*/
 
 static void
-display_tool_bar_line (it)
+display_tool_bar_line (it, height)
      struct it *it;
+     int height;
 {
   struct glyph_row *row = it->glyph_row;
   int max_x = it->last_visible_x;
@@ -9446,7 +9471,12 @@ display_tool_bar_line (it)
 
       /* Get the next display element.  */
       if (!get_next_display_element (it))
-       break;
+       {
+         /* Don't count empty row if we are counting needed tool-bar lines.  */
+         if (height < 0 && !it->hpos)
+           return;
+         break;
+       }
 
       /* Produce glyphs.  */
       x_before = it->current_x;
@@ -9483,11 +9513,22 @@ display_tool_bar_line (it)
  out:;
 
   row->displays_text_p = row->used[TEXT_AREA] != 0;
+  /* Use default face for the border below the tool bar.  */
+  if (!row->displays_text_p)
+    it->face_id = DEFAULT_FACE_ID;
   extend_face_to_end_of_line (it);
   last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
   last->right_box_line_p = 1;
   if (last == row->glyphs[TEXT_AREA])
     last->left_box_line_p = 1;
+
+  /* Make line the desired height and center it vertically.  */
+  if ((height -= it->max_ascent + it->max_descent) > 0)
+    {
+      it->max_ascent += height / 2;
+      it->max_descent += (height + 1) / 2;
+    }
+
   compute_line_metrics (it);
 
   /* If line is empty, make it occupy the rest of the tool-bar.  */
@@ -9511,11 +9552,13 @@ display_tool_bar_line (it)
 
 
 /* Value is the number of screen lines needed to make all tool-bar
-   items of frame F visible.  */
+   items of frame F visible.  The number of actual rows needed is
+   returned in *N_ROWS if non-NULL.  */
 
 static int
-tool_bar_lines_needed (f)
+tool_bar_lines_needed (f, n_rows)
      struct frame *f;
+     int *n_rows;
 {
   struct window *w = XWINDOW (f->tool_bar_window);
   struct it it;
@@ -9531,9 +9574,13 @@ tool_bar_lines_needed (f)
     {
       it.glyph_row = w->desired_matrix->rows;
       clear_glyph_row (it.glyph_row);
-      display_tool_bar_line (&it);
+      display_tool_bar_line (&it, -1);
     }
 
+  /* f->n_tool_bar_rows == 0 means "unknown"; -1 means no tool-bar.  */
+  if (n_rows)
+    *n_rows = it.vpos > 0 ? it.vpos : -1;
+
   return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
 }
 
@@ -9562,7 +9609,7 @@ DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
       if (f->n_tool_bar_items)
        {
          build_desired_tool_bar_string (f);
-         nlines = tool_bar_lines_needed (f);
+         nlines = tool_bar_lines_needed (f, NULL);
        }
     }
 
@@ -9607,9 +9654,46 @@ redisplay_tool_bar (f)
   build_desired_tool_bar_string (f);
   reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
 
+  if (f->n_tool_bar_rows == 0)
+    (void)tool_bar_lines_needed (f, &f->n_tool_bar_rows);
+
   /* Display as many lines as needed to display all tool-bar items.  */
-  while (it.current_y < it.last_visible_y)
-    display_tool_bar_line (&it);
+
+  if (f->n_tool_bar_rows > 0)
+    {
+      int border, rows, height, extra;
+
+      if (INTEGERP (Vtool_bar_border))
+       border = XINT (Vtool_bar_border);
+      else if (EQ (Vtool_bar_border, Qinternal_border_width))
+       border = FRAME_INTERNAL_BORDER_WIDTH (f);
+      else if (EQ (Vtool_bar_border, Qborder_width))
+       border = f->border_width;
+      else
+       border = 0;
+      if (border < 0)
+       border = 0;
+
+      rows = f->n_tool_bar_rows;
+      height = (it.last_visible_y - border) / rows;
+      extra = it.last_visible_y - border - height * rows;
+
+      while (it.current_y < it.last_visible_y)
+       {
+         int h = 0;
+         if (extra > 0 && rows-- > 0)
+           {
+             h = (extra + rows - 1) / rows;
+             extra -= h;
+           }
+         display_tool_bar_line (&it, height + h);
+       }
+    }
+  else
+    {
+      while (it.current_y < it.last_visible_y)
+       display_tool_bar_line (&it, 0);
+    }
 
   /* It doesn't make much sense to try scrolling in the tool-bar
      window, so don't do it.  */
@@ -9642,7 +9726,7 @@ redisplay_tool_bar (f)
       /* Resize windows as needed by changing the `tool-bar-lines'
         frame parameter.  */
       if (change_height_p
-         && (nlines = tool_bar_lines_needed (f),
+         && (nlines = tool_bar_lines_needed (f, &f->n_tool_bar_rows),
              nlines != WINDOW_TOTAL_LINES (w)))
        {
          extern Lisp_Object Qtool_bar_lines;
@@ -11524,7 +11608,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
          x += glyph->pixel_width;
          ++glyph;
          if (cursor_from_overlay_pos
-             && last_pos > cursor_from_overlay_pos)
+             && last_pos >= cursor_from_overlay_pos)
            {
              cursor_from_overlay_pos = 0;
              cursor = 0;
@@ -11538,10 +11622,12 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
          /* Skip all glyphs from string.  */
          do
            {
+             Lisp_Object cprop;
              int pos;
              if ((cursor == NULL || glyph > cursor)
-                 && !NILP (Fget_char_property (make_number ((glyph)->charpos),
-                                               Qcursor, (glyph)->object))
+                 && (cprop = Fget_char_property (make_number ((glyph)->charpos),
+                                                 Qcursor, (glyph)->object),
+                     !NILP (cprop))
                  && (pos = string_buffer_position (w, glyph->object,
                                                    string_before_pos),
                      (pos == 0   /* From overlay */
@@ -11552,14 +11638,15 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
                     Add 1 to last_pos so that if point corresponds to the
                     glyph right after the overlay, we still use a 'cursor'
                     property found in that overlay.  */
-                 cursor_from_overlay_pos = pos == 0 ? last_pos+1 : 0;
+                 cursor_from_overlay_pos = (pos ? 0 : last_pos
+                                            + (INTEGERP (cprop) ? XINT (cprop) : 0));
                  cursor = glyph;
                  cursor_x = x;
                }
              x += glyph->pixel_width;
              ++glyph;
            }
-         while (glyph < end && STRINGP (glyph->object));
+         while (glyph < end && EQ (glyph->object, string_start->object));
        }
     }
 
@@ -14781,7 +14868,7 @@ dump_glyph_row (row, vpos, glyphs)
 {
   if (glyphs != 1)
     {
-      fprintf (stderr, "Row Start   End Used oEI><\\CTZFesm     X    Y    W    H    V    A    P\n");
+      fprintf (stderr, "Row Start   End Used oE><\\CTZFesm     X    Y    W    H    V    A    P\n");
       fprintf (stderr, "======================================================================\n");
 
       fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d\
@@ -15285,6 +15372,7 @@ extend_face_to_end_of_line (it)
     face = FACE_FROM_ID (f, it->face_id);
 
   if (FRAME_WINDOW_P (f)
+      && it->glyph_row->displays_text_p
       && face->box == FACE_NO_BOX
       && face->background == FRAME_BACKGROUND_PIXEL (f)
       && !face->stipple)
@@ -16477,8 +16565,11 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                    {
                      int bytepos = last_offset;
                      int charpos = string_byte_to_char (elt, bytepos);
+
+                     if (precision <= 0)
+                       nchars = string_byte_to_char (elt, offset) - charpos;
                      n += display_string (NULL, elt, Qnil, 0, charpos,
-                                          it, 0, prec, 0,
+                                          it, 0, nchars, 0,
                                           STRING_MULTIBYTE (elt));
                    }
                    break;
@@ -17727,7 +17818,7 @@ display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
    display them, and < 0 means obey the current buffer's value of
    enable_multibyte_characters.
 
-   Value is the number of glyphs produced.  */
+   Value is the number of columns displayed.  */
 
 static int
 display_string (string, lisp_string, face_string, face_string_pos,
@@ -22267,7 +22358,10 @@ note_mouse_highlight (f, x, y)
     }
 
   if (part == ON_VERTICAL_BORDER)
-    cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+    {
+      cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+      help_echo_string = make_string ("drag-mouse-1: resize", 20);
+    }
   else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
           || part == ON_SCROLL_BAR)
     cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
@@ -23638,6 +23732,14 @@ otherwise.  */);
     doc: /* *Non-nil means to scroll (recenter) cursor line if it is not fully visible.  */);
   make_cursor_line_fully_visible_p = 1;
 
+  DEFVAR_LISP ("tool-bar-border", &Vtool_bar_border,
+    doc: /* *Border below tool-bar in pixels.
+If an integer, use it as the height of the border.
+If it is one of `internal-border-width' or `border-width', use the
+value of the corresponding frame parameter.
+Otherwise, no border is added below the tool-bar.  */);
+  Vtool_bar_border = Qinternal_border_width;
+
   DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
     doc: /* *Margin around tool-bar buttons in pixels.
 If an integer, use that for both horizontal and vertical margins.
@@ -23705,7 +23807,7 @@ before automatic hscrolling will horizontally scroll the window.  */);
 
   DEFVAR_LISP ("hscroll-step", &Vhscroll_step,
     doc: /* *How many columns to scroll the window when point gets too close to the edge.
-When point is less than `automatic-hscroll-margin' columns from the window
+When point is less than `hscroll-margin' columns from the window
 edge, automatic hscrolling will scroll the window by the amount of columns
 determined by this variable.  If its value is a positive integer, scroll that
 many columns.  If it's a positive floating-point number, it specifies the