/* Display generation from window structure and buffer text.
Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005 Free Software Foundation, Inc.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
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;
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));
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));
}
}
- *heightp = h - 1;
+ *heightp = h;
return WINDOW_TO_FRAME_PIXEL_Y (w, y);
}
skip starting with next_stop. */
if (invis_p)
IT_CHARPOS (*it) = next_stop;
+
+ /* If there are adjacent invisible texts, don't lose the
+ second one's ellipsis. */
+ if (invis_p == 2)
+ display_ellipsis_p = 1;
}
while (invis_p);
it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
}
else if (display_ellipsis_p)
- setup_for_ellipsis (it, 0);
+ {
+ /* Make sure that the glyphs of the ellipsis will get
+ correct `charpos' values. If we would not update
+ it->position here, the glyphs would belong to the
+ last visible character _before_ the invisible
+ text, which confuses `set_cursor_from_row'.
+
+ We use the last invisible position instead of the
+ first because this way the cursor is always drawn on
+ the first "." of the ellipsis, whenever PT is inside
+ the invisible text. Otherwise the cursor would be
+ placed _after_ the ellipsis when the point is after the
+ first invisible character. */
+ 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);
+ }
}
}
{
it->method = GET_FROM_STRETCH;
it->object = value;
- it->current.pos = it->position = start_pos;
+ *position = it->position = start_pos;
}
#ifdef HAVE_WINDOW_SYSTEM
else
display element from the current position of IT. Value is zero if
end of buffer (or C string) is reached. */
+static struct frame *last_escape_glyph_frame = NULL;
+static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS);
+static int last_escape_glyph_merged_face_id = 0;
+
int
get_next_display_element (it)
struct it *it;
face_id = merge_faces (it->f, Qt, lface_id,
it->face_id);
}
+ else if (it->f == last_escape_glyph_frame
+ && it->face_id == last_escape_glyph_face_id)
+ {
+ face_id = last_escape_glyph_merged_face_id;
+ }
else
{
/* Merge the escape-glyph face into the current face. */
face_id = merge_faces (it->f, Qescape_glyph, 0,
it->face_id);
+ last_escape_glyph_frame = it->f;
+ last_escape_glyph_face_id = it->face_id;
+ last_escape_glyph_merged_face_id = face_id;
}
XSETINT (it->ctl_chars[0], g);
face_id = merge_faces (it->f, Qt, lface_id,
it->face_id);
}
+ else if (it->f == last_escape_glyph_frame
+ && it->face_id == last_escape_glyph_face_id)
+ {
+ face_id = last_escape_glyph_merged_face_id;
+ }
else
{
/* Merge the escape-glyph face into the current face. */
face_id = merge_faces (it->f, Qescape_glyph, 0,
it->face_id);
+ last_escape_glyph_frame = it->f;
+ last_escape_glyph_face_id = it->face_id;
+ last_escape_glyph_merged_face_id = face_id;
}
/* Handle soft hyphens in the mode where they only get
if (it->dpvec + it->current.dpvec_index == it->dpend)
{
+ int recheck_faces = it->ellipsis_p;
+
if (it->s)
it->method = GET_FROM_C_STRING;
else if (STRINGP (it->string))
set_iterator_to_next (it, reseat_p);
}
- /* Recheck faces after display vector */
- it->stop_charpos = IT_CHARPOS (*it);
+ /* Maybe recheck faces after display vector */
+ if (recheck_faces)
+ it->stop_charpos = IT_CHARPOS (*it);
}
break;
/* 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. */
}
-/* 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. */
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;
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. */
/* 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;
{
it.glyph_row = w->desired_matrix->rows;
clear_glyph_row (it.glyph_row);
- display_tool_bar_line (&it);
+ display_tool_bar_line (&it, 0);
}
+ if (n_rows)
+ *n_rows = it.vpos;
+
return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
}
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);
}
}
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);
+ if (f->n_tool_bar_rows == 0)
+ f->n_tool_bar_rows = -1;
+ }
+
/* 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. */
/* 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;
retry:
pause = 0;
reconsider_clip_changes (w, current_buffer);
+ last_escape_glyph_frame = NULL;
+ last_escape_glyph_face_id = (1 << FACE_ID_BITS);
/* If new fonts have been loaded that make a glyph matrix adjustment
necessary, do it. */
{
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;
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,
else
ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
+ if (width > 0 && !it->truncate_lines_p
+ && it->current_x + width > it->last_visible_x)
+ width = it->last_visible_x - it->current_x - 1;
+
if (width > 0 && height > 0 && it->glyph_row)
{
Lisp_Object object = it->stack[it->sp - 1].string;
/* RIF:
Produce glyphs/get display metrics for the display element IT is
- loaded with. See the description of struct display_iterator in
- dispextern.h for an overview of struct display_iterator. */
+ loaded with. See the description of struct it in dispextern.h
+ for an overview of struct it. */
void
x_produce_glyphs (it)
{
if (w == XWINDOW (echo_area_window))
{
- *width = FRAME_CURSOR_WIDTH (f);
- return FRAME_DESIRED_CURSOR (f);
+ if (EQ (b->cursor_type, Qt) || NILP (b->cursor_type))
+ {
+ *width = FRAME_CURSOR_WIDTH (f);
+ return FRAME_DESIRED_CURSOR (f);
+ }
+ else
+ return get_specified_cursor_type (b->cursor_type, width);
}
*active_cursor = 0;
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.