/* Display generation from window structure and buffer text.
-Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2014 Free Software Foundation,
+Inc.
This file is part of GNU Emacs.
void
wset_redisplay (struct window *w)
{
- redisplay_other_windows ();
+ /* Beware: selected_window can be nil during early stages. */
+ if (!EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
+ redisplay_other_windows ();
w->redisplay = true;
}
/* Non-zero means print traces of redisplay if compiled with
GLYPH_DEBUG defined. */
-int trace_redisplay_p;
+bool trace_redisplay_p;
#endif /* GLYPH_DEBUG */
static int display_prop_string_p (Lisp_Object, Lisp_Object);
static int row_for_charpos_p (struct glyph_row *, ptrdiff_t);
static int cursor_row_p (struct glyph_row *);
-static int redisplay_mode_lines (Lisp_Object, int);
+static int redisplay_mode_lines (Lisp_Object, bool);
static char *decode_mode_spec_coding (Lisp_Object, char *, int);
static Lisp_Object get_it_property (struct it *it, Lisp_Object prop);
static void redisplay_internal (void);
static int echo_area_display (int);
static void redisplay_windows (Lisp_Object);
-static void redisplay_window (Lisp_Object, int);
+static void redisplay_window (Lisp_Object, bool);
static Lisp_Object redisplay_window_error (Lisp_Object);
static Lisp_Object redisplay_window_0 (Lisp_Object);
static Lisp_Object redisplay_window_1 (Lisp_Object);
static void x_consider_frame_title (Lisp_Object);
static void update_tool_bar (struct frame *, int);
static int redisplay_tool_bar (struct frame *);
+static void x_draw_bottom_divider (struct window *w);
static void notice_overwritten_cursor (struct window *,
enum glyph_row_area,
int, int, int, int);
static void produce_special_glyphs (struct it *, enum display_element_type);
static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
-static int coords_in_mouse_face_p (struct window *, int, int);
+static bool coords_in_mouse_face_p (struct window *, int, int);
\f
int
window_text_bottom_y (struct window *w)
{
- int height = WINDOW_TOTAL_HEIGHT (w);
+ int height = WINDOW_PIXEL_HEIGHT (w);
+
+ height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
if (WINDOW_WANTS_MODELINE_P (w))
height -= CURRENT_MODE_LINE_HEIGHT (w);
+
return height;
}
int
window_box_width (struct window *w, enum glyph_row_area area)
{
- int cols = w->total_cols;
- int pixels = 0;
+ int pixels = w->pixel_width;
if (!w->pseudo_window_p)
{
- cols -= WINDOW_SCROLL_BAR_COLS (w);
+ pixels -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
+ pixels -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
if (area == TEXT_AREA)
- {
- cols -= max (0, w->left_margin_cols);
- cols -= max (0, w->right_margin_cols);
- pixels = -WINDOW_TOTAL_FRINGE_WIDTH (w);
- }
+ pixels -= (WINDOW_MARGINS_WIDTH (w)
+ + WINDOW_FRINGES_WIDTH (w));
else if (area == LEFT_MARGIN_AREA)
- {
- cols = max (0, w->left_margin_cols);
- pixels = 0;
- }
+ pixels = WINDOW_LEFT_MARGIN_WIDTH (w);
else if (area == RIGHT_MARGIN_AREA)
- {
- cols = max (0, w->right_margin_cols);
- pixels = 0;
- }
+ pixels = WINDOW_RIGHT_MARGIN_WIDTH (w);
}
- return cols * WINDOW_FRAME_COLUMN_WIDTH (w) + pixels;
+ return pixels;
}
window_box_height (struct window *w)
{
struct frame *f = XFRAME (w->frame);
- int height = WINDOW_TOTAL_HEIGHT (w);
+ int height = WINDOW_PIXEL_HEIGHT (w);
eassert (height >= 0);
+ height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+
/* Note: the code below that determines the mode-line/header-line
height is essentially the same as that contained in the macro
CURRENT_{MODE,HEADER}_LINE_HEIGHT, except that it checks whether
if (top_y < window_top_y)
visible_p = bottom_y > window_top_y;
else if (top_y < it.last_visible_y)
- visible_p = 1;
+ visible_p = true;
if (bottom_y >= it.last_visible_y
&& it.bidi_p && it.bidi_it.scan_dir == -1
&& IT_CHARPOS (it) < charpos)
if (charpos < IT_CHARPOS (it)
|| (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
{
- visible_p = 1;
+ visible_p = true;
RESTORE_IT (&it2, &it2, it2data);
move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
*x = it2.current_x;
FRAME_COLUMN_WIDTH (f) - 1,
FRAME_LINE_HEIGHT (f) - 1);
+ /* PXW: Should we clip pixels before converting to columns/lines? */
if (!noclip)
{
if (pix_x < 0)
{
/* Draw full-width. X coordinates are relative to S->w->left_col. */
r.x = WINDOW_LEFT_EDGE_X (s->w);
- r.width = WINDOW_TOTAL_WIDTH (s->w);
+ if (s->row->mode_line_p)
+ r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
+ else
+ r.width = WINDOW_PIXEL_WIDTH (s->w);
/* Unless displaying a mode or menu bar line, which are always
fully visible, clip to the visible part of the row. */
/* Try to determine frame pixel position and size of the glyph under
frame pixel coordinates X/Y on frame F. */
- if (!f->glyphs_initialized_p
- || (window = window_from_coordinates (f, gx, gy, &part, 0),
- NILP (window)))
+ if (window_resize_pixelwise)
+ {
+ width = height = 1;
+ goto virtual_glyph;
+ }
+ else if (!f->glyphs_initialized_p
+ || (window = window_from_coordinates (f, gx, gy, &part, 0),
+ NILP (window)))
{
width = FRAME_SMALLEST_CHAR_WIDTH (f);
height = FRAME_SMALLEST_FONT_HEIGHT (f);
it->redisplay_end_trigger_charpos
= marker_position (w->redisplay_end_trigger);
else if (INTEGERP (w->redisplay_end_trigger))
- it->redisplay_end_trigger_charpos =
- clip_to_bounds (PTRDIFF_MIN, XINT (w->redisplay_end_trigger), PTRDIFF_MAX);
+ it->redisplay_end_trigger_charpos
+ = clip_to_bounds (PTRDIFF_MIN, XINT (w->redisplay_end_trigger),
+ PTRDIFF_MAX);
it->tab_width = SANE_TAB_WIDTH (current_buffer);
&& ((!NILP (Vtruncate_partial_width_windows)
&& !INTEGERP (Vtruncate_partial_width_windows))
|| (INTEGERP (Vtruncate_partial_width_windows)
+ /* PXW: Shall we do something about this? */
&& (WINDOW_TOTAL_COLS (it->w)
< XINT (Vtruncate_partial_width_windows))))))
it->line_wrap = TRUNCATE;
{
/* Mode lines, menu bar in terminal frames. */
it->first_visible_x = 0;
- it->last_visible_x = WINDOW_TOTAL_WIDTH (w);
+ it->last_visible_x = WINDOW_PIXEL_WIDTH (w);
}
else
{
- it->first_visible_x =
- window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f);
+ it->first_visible_x
+ = window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f);
it->last_visible_x = (it->first_visible_x
+ window_box_width (w, TEXT_AREA));
with a left box line. */
face = FACE_FROM_ID (it->f, remapped_base_face_id);
if (face->box != FACE_NO_BOX)
- it->start_of_box_run_p = 1;
+ it->start_of_box_run_p = true;
}
/* If a buffer position was specified, set the iterator there,
pop_it (it);
else
{
- it->ignore_overlay_strings_at_pos_p = 1;
+ it->ignore_overlay_strings_at_pos_p = true;
it->string_from_display_prop_p = 0;
it->from_disp_prop_p = 0;
handle_overlay_change_p = 0;
prop = Fget_text_property (end_charpos, Qinvisible, it->string);
invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
if (invis_p == 2)
- display_ellipsis_p = 1;
+ display_ellipsis_p = true;
}
}
while (invis_p && endpos < len);
if (display_ellipsis_p)
- it->ellipsis_p = 1;
+ it->ellipsis_p = true;
if (endpos < len)
{
tem = next_stop;
/* If there are adjacent invisible texts, don't lose the
- second one's ellipsis. */
+ second one's ellipsis. */
if (invis_p == 2)
- display_ellipsis_p = 1;
+ display_ellipsis_p = true;
}
while (invis_p);
if (it->bidi_p)
{
ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
- int on_newline =
- bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
- int after_newline =
- newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
+ int on_newline
+ = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
+ int after_newline
+ = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
/* If the invisible text ends on a newline or on a
character after a newline, we can avoid the costly,
it->position.charpos = newpos - 1;
it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
}
- it->ellipsis_p = 1;
+ it->ellipsis_p = true;
/* Let the ellipsis display before
considering any properties of the following char.
Fixes jasonr@gnu.org 01 Oct 07 bug. */
it->saved_face_id = it->face_id = DEFAULT_FACE_ID;
it->method = GET_FROM_DISPLAY_VECTOR;
- it->ellipsis_p = 1;
+ it->ellipsis_p = true;
}
it->method = GET_FROM_IMAGE;
it->from_overlay = Qnil;
it->face_id = face_id;
- it->from_disp_prop_p = 1;
+ it->from_disp_prop_p = true;
/* Say that we haven't consumed the characters with
`display' property yet. The call to pop_it in
when we are finished with the glyph property value. */
push_it (it, position);
it->from_overlay = overlay;
- it->from_disp_prop_p = 1;
+ it->from_disp_prop_p = true;
if (NILP (location))
it->area = TEXT_AREA;
it->stop_charpos = 0;
it->prev_stop = 0;
it->base_level_stop = 0;
- it->string_from_display_prop_p = 1;
+ it->string_from_display_prop_p = true;
/* Say that we haven't consumed the characters with
`display' property yet. The call to pop_it in
set_iterator_to_next will clean this up. */
processed the overlay strings there already, so that
next_element_from_buffer doesn't try it again. */
if (NILP (it->string) && IT_CHARPOS (*it) >= it->end_charpos)
- it->overlay_strings_at_end_processed_p = 1;
+ it->overlay_strings_at_end_processed_p = true;
}
else
{
if (bidi_it_prev)
*bidi_it_prev = bprev;
}
- *skipped_p = newline_found_p = 1;
+ *skipped_p = newline_found_p = true;
}
else
{
it->bidi_it.string.s = NULL;
it->bidi_it.string.lstring = Qnil;
it->bidi_it.string.bufpos = 0;
+ it->bidi_it.string.from_disp_str = 0;
it->bidi_it.string.unibyte = 0;
it->bidi_it.w = it->w;
}
if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
{
if (c == 0xA0)
- nonascii_space_p = 1;
+ nonascii_space_p = true;
else if (c == 0xAD || c == 0x2010 || c == 0x2011)
- nonascii_hyphen_p = 1;
+ nonascii_hyphen_p = true;
}
/* Translate control characters into `\003' or `^C' form.
if (it->method == GET_FROM_STRING
&& it->current.overlay_string_index >= 0
&& it->n_overlay_strings > 0)
- it->ignore_overlay_strings_at_pos_p = 1;
+ it->ignore_overlay_strings_at_pos_p = true;
it->len = it->dpvec_char_len;
set_iterator_to_next (it, reseat_p);
}
- /* Maybe recheck faces after display vector */
+ /* Maybe recheck faces after display vector. */
if (recheck_faces)
it->stop_charpos = IT_CHARPOS (*it);
}
else
{
/* Not an overlay string. There could be padding, so test
- against it->end_charpos . */
+ against it->end_charpos. */
if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
goto consider_string_end;
}
static int
next_element_from_c_string (struct it *it)
{
- int success_p = 1;
+ bool success_p = true;
eassert (it->s);
eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
it->method = GET_FROM_BUFFER;
it->object = it->w->contents;
reseat_at_next_visible_line_start (it, 1);
- it->face_before_selective_p = 1;
+ it->face_before_selective_p = true;
}
return GET_NEXT_DISPLAY_ELEMENT (it);
it->prev_stop = it->stop_charpos;
else
it->prev_stop = BEGV;
- it->bidi_p = 1;
+ it->bidi_p = true;
it->current = save_current;
it->position = save_position;
it->stop_charpos = save_stop_pos;
}
while (charpos <= where_we_are);
- it->bidi_p = 1;
+ it->bidi_p = true;
it->current = save_current;
it->position = save_position;
next_stop = it->stop_charpos;
static int
next_element_from_buffer (struct it *it)
{
- int success_p = 1;
+ bool success_p = true;
eassert (IT_CHARPOS (*it) >= BEGV);
eassert (NILP (it->string) && !it->s);
overlay_strings_follow_p = 0;
else
{
- it->overlay_strings_at_end_processed_p = 1;
+ it->overlay_strings_at_end_processed_p = true;
overlay_strings_follow_p = get_overlay_strings (it, 0);
}
If TO_CHARPOS is in invisible text, e.g. a truncated part of a
screen line, this function will set IT to the next position that is
- displayed to the right of TO_CHARPOS on the screen. */
+ displayed to the right of TO_CHARPOS on the screen.
-void
+ Return the maximum pixel length of any line scanned but never more
+ than it.last_visible_x. */
+
+int
move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
{
enum move_it_result skip, skip2 = MOVE_X_REACHED;
int line_height, line_start_x = 0, reached = 0;
+ int max_current_x = 0;
void *backup_data = NULL;
for (;;)
if (to_y >= it->current_y
&& to_y < it->current_y + line_height)
{
+ if (to_y > it->current_y)
+ max_current_x = max (it->current_x, max_current_x);
+
/* When word-wrap is on, TO_X may lie past the end
of a wrapped line. Then it->current is the
character on the next line, so backtrack to the
skip = move_it_in_display_line_to
(it, -1, prev_x, MOVE_TO_X);
}
+
reached = 6;
}
}
if (reached)
- break;
+ {
+ max_current_x = max (it->current_x, max_current_x);
+ break;
+ }
}
else if (BUFFERP (it->object)
&& (it->method == GET_FROM_BUFFER
switch (skip)
{
case MOVE_POS_MATCH_OR_ZV:
+ max_current_x = max (it->current_x, max_current_x);
reached = 8;
goto out;
case MOVE_NEWLINE_OR_CR:
+ max_current_x = max (it->current_x, max_current_x);
set_iterator_to_next (it, 1);
it->continuation_lines_width = 0;
break;
case MOVE_LINE_TRUNCATED:
+ max_current_x = it->last_visible_x;
it->continuation_lines_width = 0;
reseat_at_next_visible_line_start (it, 0);
if ((op & MOVE_TO_POS) != 0
break;
case MOVE_LINE_CONTINUED:
+ max_current_x = it->last_visible_x;
/* For continued lines ending in a tab, some of the glyphs
associated with the tab are displayed on the current
line. Since it->current_x does not include these glyphs,
bidi_unshelve_cache (backup_data, 1);
TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
+
+ return max_current_x;
}
}
}
-/* Return 1 if IT points into the middle of a display vector. */
+/* Return true if IT points into the middle of a display vector. */
-int
+bool
in_display_vector_p (struct it *it)
{
return (it->method == GET_FROM_DISPLAY_VECTOR
&& it->dpvec + it->current.dpvec_index != it->dpend);
}
+DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 6, 0,
+ doc: /* Return the size of the text of WINDOW's buffer in pixels.
+WINDOW must be a live window and defaults to the selected one. The
+return value is a cons of the maximum pixel-width of any text line and
+the maximum pixel-height of all text lines.
+
+The optional argument FROM, if non-nil, specifies the first text
+position and defaults to the minimum accessible position of the buffer.
+If FROM is t, use the minimum accessible position that is not a newline
+character. TO, if non-nil, specifies the last text position and
+defaults to the maximum accessible position of the buffer. If TO is t,
+use the maximum accessible position that is not a newline character.
+
+The optional argument X_LIMIT, if non-nil, specifies the maximum text
+width that can be returned. X_LIMIT nil or omitted, means to use the
+pixel-width of WINDOW's body; use this if you do not intend to change
+the width of WINDOW. Use the maximum width WINDOW may assume if you
+intend to change WINDOW's width.
+
+The optional argument Y_LIMIT, if non-nil, specifies the maximum text
+height that can be returned. Text lines whose y-coordinate is beyond
+Y_LIMIT are ignored. Since calculating the text height of a large
+buffer can take some time, it makes sense to specify this argument if
+the size of the buffer is unknown.
+
+Optional argument MODE_AND_HEADER_LINE nil or omitted means do not
+include the height of the mode- or header-line of WINDOW in the return
+value. If it is either the symbol `mode-line' or `header-line', include
+only the height of that line, if present, in the return value. If t,
+include the height of both, if present, in the return value. */)
+ (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, Lisp_Object y_limit,
+ Lisp_Object mode_and_header_line)
+{
+ struct window *w = decode_live_window (window);
+ Lisp_Object buf;
+ struct buffer *b;
+ struct it it;
+ struct buffer *old_buffer = NULL;
+ ptrdiff_t start, end, pos;
+ struct text_pos startp;
+ void *itdata = NULL;
+ int c, max_y = -1, x = 0, y = 0;
+
+ buf = w->contents;
+ CHECK_BUFFER (buf);
+ b = XBUFFER (buf);
+
+ if (b != current_buffer)
+ {
+ old_buffer = current_buffer;
+ set_buffer_internal (b);
+ }
+
+ if (NILP (from))
+ start = BEGV;
+ else if (EQ (from, Qt))
+ {
+ start = pos = BEGV;
+ while ((pos++ < ZV) && (c = FETCH_CHAR (pos))
+ && (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
+ start = pos;
+ while ((pos-- > BEGV) && (c = FETCH_CHAR (pos)) && (c == ' ' || c == '\t'))
+ start = pos;
+ }
+ else
+ {
+ CHECK_NUMBER_COERCE_MARKER (from);
+ start = min (max (XINT (from), BEGV), ZV);
+ }
+
+ if (NILP (to))
+ end = ZV;
+ else if (EQ (to, Qt))
+ {
+ end = pos = ZV;
+ while ((pos-- > BEGV) && (c = FETCH_CHAR (pos))
+ && (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
+ end = pos;
+ while ((pos++ < ZV) && (c = FETCH_CHAR (pos)) && (c == ' ' || c == '\t'))
+ end = pos;
+ }
+ else
+ {
+ CHECK_NUMBER_COERCE_MARKER (to);
+ end = max (start, min (XINT (to), ZV));
+ }
+
+ if (!NILP (y_limit))
+ {
+ CHECK_NUMBER (y_limit);
+ max_y = min (XINT (y_limit), INT_MAX);
+ }
+
+ itdata = bidi_shelve_cache ();
+ SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start));
+ start_display (&it, w, startp);
+
+ if (NILP (x_limit))
+ x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y);
+ else
+ {
+ CHECK_NUMBER (x_limit);
+ it.last_visible_x = min (XINT (x_limit), INFINITY);
+ /* Actually, we never want move_it_to stop at to_x. But to make
+ sure that move_it_in_display_line_to always moves far enough,
+ we set it to INT_MAX and specify MOVE_TO_X. */
+ x = move_it_to (&it, end, INT_MAX, max_y, -1,
+ MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+ }
+
+ y = it.current_y + it.max_ascent + it.max_descent;
+
+ if (!EQ (mode_and_header_line, Qheader_line)
+ && !EQ (mode_and_header_line, Qt))
+ /* Do not count the header-line which was counted automatically by
+ start_display. */
+ y = y - WINDOW_HEADER_LINE_HEIGHT (w);
+
+ if (EQ (mode_and_header_line, Qmode_line)
+ || EQ (mode_and_header_line, Qt))
+ /* Do count the mode-line which is not included automatically by
+ start_display. */
+ y = y + WINDOW_MODE_LINE_HEIGHT (w);
+
+ bidi_unshelve_cache (itdata, 0);
+
+ if (old_buffer)
+ set_buffer_internal (old_buffer);
+
+ return Fcons (make_number (x), make_number (y));
+}
\f
/***********************************************************************
Messages
incrementing windows_or_buffers_changed even if *Messages* is
shown in some window. So we must manually set
windows_or_buffers_changed here to make up for that. */
- windows_or_buffers_changed = old_windows_or_buffers_changed;
+ windows_or_buffers_changed = old_windows_or_buffers_changed;
bset_redisplay (current_buffer);
set_buffer_internal (oldbuf);
struct gcpro gcpro1;
GCPRO1 (m);
- clear_message (1,1);
+ clear_message (true, true);
cancel_echoing ();
/* First flush out any partial line written with print. */
echo_message_buffer = Qnil;
}
else
- clear_message (1, 1);
+ clear_message (true, true);
do_pending_window_change (0);
echo_area_display (1);
else
{
this_one = 0, the_other = 1;
- clear_buffer_p = 1;
+ clear_buffer_p = true;
/* We need a fresh one in case the current echo buffer equals
the one containing the last displayed echo area message. */
= (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
? echo_buffer[the_other]
: echo_buffer[this_one]);
- clear_buffer_p = 1;
+ clear_buffer_p = true;
}
buffer = echo_area_buffer[this_one];
if (!FRAME_MINIBUF_ONLY_P (f))
{
struct it it;
- struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
- int total_height = WINDOW_TOTAL_LINES (root) + WINDOW_TOTAL_LINES (w);
- int height;
- EMACS_INT max_height;
+ int total_height = (WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f)))
+ + WINDOW_PIXEL_HEIGHT (w));
int unit = FRAME_LINE_HEIGHT (f);
+ int height, max_height;
struct text_pos start;
struct buffer *old_current_buffer = NULL;
/* Compute the max. number of lines specified by the user. */
if (FLOATP (Vmax_mini_window_height))
- max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_LINES (f);
+ max_height = XFLOATINT (Vmax_mini_window_height) * total_height;
else if (INTEGERP (Vmax_mini_window_height))
- max_height = XINT (Vmax_mini_window_height);
+ max_height = XINT (Vmax_mini_window_height) * unit;
else
max_height = total_height / 4;
/* Correct that max. height if it's bogus. */
- max_height = clip_to_bounds (1, max_height, total_height);
+ max_height = clip_to_bounds (unit, max_height, total_height);
/* Find out the height of the text in the window. */
if (it.line_wrap == TRUNCATE)
- height = 1;
+ height = unit;
else
{
last_height = 0;
else
height = it.current_y + it.max_ascent + it.max_descent;
height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
- height = (height + unit - 1) / unit;
}
/* Compute a suitable window start. */
if (height > max_height)
{
- height = max_height;
+ height = (max_height / unit) * unit;
init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
- move_it_vertically_backward (&it, (height - 1) * unit);
+ move_it_vertically_backward (&it, height - unit);
start = it.current.pos;
}
else
{
/* Let it grow only, until we display an empty message, in which
case the window shrinks again. */
- if (height > WINDOW_TOTAL_LINES (w))
+ if (height > WINDOW_PIXEL_HEIGHT (w))
{
- int old_height = WINDOW_TOTAL_LINES (w);
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
FRAME_WINDOWS_FROZEN (f) = 1;
- grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
- window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+ grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), 1);
+ window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
}
- else if (height < WINDOW_TOTAL_LINES (w)
+ else if (height < WINDOW_PIXEL_HEIGHT (w)
&& (exact_p || BEGV == ZV))
{
- int old_height = WINDOW_TOTAL_LINES (w);
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
FRAME_WINDOWS_FROZEN (f) = 0;
- shrink_mini_window (w);
- window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+ shrink_mini_window (w, 1);
+ window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
}
}
else
{
/* Always resize to exact size needed. */
- if (height > WINDOW_TOTAL_LINES (w))
+ if (height > WINDOW_PIXEL_HEIGHT (w))
{
- int old_height = WINDOW_TOTAL_LINES (w);
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
FRAME_WINDOWS_FROZEN (f) = 1;
- grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
- window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+ grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), 1);
+ window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
}
- else if (height < WINDOW_TOTAL_LINES (w))
+ else if (height < WINDOW_PIXEL_HEIGHT (w))
{
- int old_height = WINDOW_TOTAL_LINES (w);
+ int old_height = WINDOW_PIXEL_HEIGHT (w);
FRAME_WINDOWS_FROZEN (f) = 0;
- shrink_mini_window (w);
+ shrink_mini_window (w, 1);
if (height)
{
FRAME_WINDOWS_FROZEN (f) = 1;
- grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
+ grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), 1);
}
- window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+ window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
}
}
last displayed. */
void
-clear_message (int current_p, int last_displayed_p)
+clear_message (bool current_p, bool last_displayed_p)
{
if (current_p)
{
echo_area_buffer[0] = Qnil;
- message_cleared_p = 1;
+ message_cleared_p = true;
}
if (last_displayed_p)
{
echo_area_window = mini_window;
window_height_changed_p = display_echo_area (w);
- w->must_be_updated_p = 1;
+ w->must_be_updated_p = true;
/* Update the display, unless called from redisplay_internal.
Also don't update the screen during redisplay itself. The
been called, so that mode lines above the echo area are
garbaged. This looks odd, so we prevent it here. */
if (!display_completed)
- n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), 0);
+ n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
if (window_height_changed_p
/* Don't do this if Emacs is shutting down. Redisplay
Menu Bars
***********************************************************************/
+/* Non-zero if we will not redisplay all visible windows. */
+#define REDISPLAY_SOME_P() \
+ ((windows_or_buffers_changed == 0 \
+ || windows_or_buffers_changed == REDISPLAY_SOME) \
+ && (update_mode_lines == 0 \
+ || update_mode_lines == REDISPLAY_SOME))
/* Prepare for redisplay by updating menu-bar item lists when
appropriate. This can call eval. */
prepare_menu_bars (void)
{
bool all_windows = windows_or_buffers_changed || update_mode_lines;
- bool some_windows = ((windows_or_buffers_changed == 0
- || windows_or_buffers_changed == REDISPLAY_SOME)
- && (update_mode_lines == 0
- || update_mode_lines == REDISPLAY_SOME));
+ bool some_windows = REDISPLAY_SOME_P ();
struct gcpro gcpro1, gcpro2;
Lisp_Object tooltip_frame;
#if defined (USE_GTK) || defined (HAVE_NS)
int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
#else
- int do_update = WINDOWP (f->tool_bar_window)
- && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0;
+ int do_update = (WINDOWP (f->tool_bar_window)
+ && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0);
#endif
if (do_update)
int max_x = it->last_visible_x;
struct glyph *last;
- prepare_desired_row (row);
+ /* Don't extend on a previously drawn tool bar items (Bug#16058). */
+ clear_glyph_row (row);
+ row->enabled_p = true;
row->y = it->current_y;
/* Note that this isn't made use of if the face hasn't a box,
}
-/* Max tool-bar height. */
+/* Max tool-bar height. Basically, this is what makes all other windows
+ disappear when the frame gets too small. Rethink this! */
#define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
-/* Value is the number of screen lines needed to make all tool-bar
- items of frame F visible. The number of actual rows needed is
+/* Value is the number of pixels needed to make all tool-bar items of
+ frame F visible. The actual number of glyph rows needed is
returned in *N_ROWS if non-NULL. */
static int
-tool_bar_lines_needed (struct frame *f, int *n_rows)
+tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
{
struct window *w = XWINDOW (f->tool_bar_window);
struct it it;
- /* tool_bar_lines_needed is called from redisplay_tool_bar after building
+ /* tool_bar_height is called from redisplay_tool_bar after building
the desired matrix, so use (unused) mode-line row as temporary row to
avoid destroying the first tool-bar row. */
struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
F->desired_tool_bar_string in the tool-bar window of frame F. */
init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
it.first_visible_x = 0;
- it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+ it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
it.paragraph_embedding = L2R;
if (n_rows)
*n_rows = it.vpos > 0 ? it.vpos : -1;
- return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
+ if (pixelwise)
+ return it.current_y;
+ else
+ return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
}
#endif /* !USE_GTK && !HAVE_NS */
#if defined USE_GTK || defined HAVE_NS
+EXFUN (Ftool_bar_height, 2) ATTRIBUTE_CONST;
EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST;
#endif
-DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
- 0, 1, 0,
+DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
+ 0, 2, 0,
doc: /* Return the number of lines occupied by the tool bar of FRAME.
-If FRAME is nil or omitted, use the selected frame. */)
- (Lisp_Object frame)
+If FRAME is nil or omitted, use the selected frame. Optional argument
+PIXELWISE non-nil means return the height of the tool bar in pixels. */)
+ (Lisp_Object frame, Lisp_Object pixelwise)
{
- int nlines = 0;
+ int height = 0;
+
#if ! defined (USE_GTK) && ! defined (HAVE_NS)
struct frame *f = decode_any_frame (frame);
- struct window *w;
if (WINDOWP (f->tool_bar_window)
- && (w = XWINDOW (f->tool_bar_window),
- WINDOW_TOTAL_LINES (w) > 0))
+ && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
{
update_tool_bar (f, 1);
if (f->n_tool_bar_items)
{
build_desired_tool_bar_string (f);
- nlines = tool_bar_lines_needed (f, NULL);
+ height = tool_bar_height (f, NULL, NILP (pixelwise) ? 0 : 1);
}
}
#endif
- return make_number (nlines);
+
+ return make_number (height);
}
can turn off tool-bars by specifying tool-bar-lines zero. */
if (!WINDOWP (f->tool_bar_window)
|| (w = XWINDOW (f->tool_bar_window),
- WINDOW_TOTAL_LINES (w) == 0))
+ WINDOW_PIXEL_HEIGHT (w) == 0))
return 0;
/* Set up an iterator for the tool-bar window. */
init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
it.first_visible_x = 0;
- it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+ it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
row = it.glyph_row;
/* Build a string that represents the contents of the tool-bar. */
if (f->n_tool_bar_rows == 0)
{
- int nlines;
+ int new_height = tool_bar_height (f, &f->n_tool_bar_rows, 1);
- if ((nlines = tool_bar_lines_needed (f, &f->n_tool_bar_rows),
- nlines != WINDOW_TOTAL_LINES (w)))
+ if (new_height != WINDOW_PIXEL_HEIGHT (w))
{
Lisp_Object frame;
- int old_height = WINDOW_TOTAL_LINES (w);
+ int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
+ / FRAME_LINE_HEIGHT (f));
XSETFRAME (frame, f);
Fmodify_frame_parameters (frame,
list1 (Fcons (Qtool_bar_lines,
- make_number (nlines))));
- if (WINDOW_TOTAL_LINES (w) != old_height)
- {
- clear_glyph_matrix (w->desired_matrix);
- f->fonts_changed = 1;
- return 1;
- }
+ make_number (new_lines))));
+ /* Always do that now. */
+ clear_glyph_matrix (w->desired_matrix);
+ f->fonts_changed = 1;
+ return 1;
}
}
if (!NILP (Vauto_resize_tool_bars))
{
+ /* Do we really allow the toolbar to occupy the whole frame? */
int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f);
int change_height_p = 0;
&& it.current_y < max_tool_bar_height)
change_height_p = 1;
+ /* We subtract 1 because display_tool_bar_line advances the
+ glyph_row pointer before returning to its caller. We want to
+ examine the last glyph row produced by
+ display_tool_bar_line. */
row = it.glyph_row - 1;
/* If there are blank lines at the end, except for a partially
if (change_height_p)
{
Lisp_Object frame;
- int old_height = WINDOW_TOTAL_LINES (w);
int nrows;
- int nlines = tool_bar_lines_needed (f, &nrows);
+ int new_height = tool_bar_height (f, &nrows, 1);
change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
&& !f->minimize_tool_bar_window_p)
- ? (nlines > old_height)
- : (nlines != old_height));
+ ? (new_height > WINDOW_PIXEL_HEIGHT (w))
+ : (new_height != WINDOW_PIXEL_HEIGHT (w)));
f->minimize_tool_bar_window_p = 0;
if (change_height_p)
{
- XSETFRAME (frame, f);
- Fmodify_frame_parameters (frame,
- list1 (Fcons (Qtool_bar_lines,
- make_number (nlines))));
- if (WINDOW_TOTAL_LINES (w) != old_height)
+ /* Current size of the tool-bar window in canonical line
+ units. */
+ int old_lines = WINDOW_TOTAL_LINES (w);
+ /* Required size of the tool-bar window in canonical
+ line units. */
+ int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
+ / FRAME_LINE_HEIGHT (f));
+ /* Maximum size of the tool-bar window in canonical line
+ units that this frame can allow. */
+ int max_lines =
+ WINDOW_TOTAL_LINES (XWINDOW (FRAME_ROOT_WINDOW (f))) - 1;
+
+ /* Don't try to change the tool-bar window size and set
+ the fonts_changed flag unless really necessary. That
+ flag causes redisplay to give up and retry
+ redisplaying the frame from scratch, so setting it
+ unnecessarily can lead to nasty redisplay loops. */
+ if (new_lines <= max_lines
+ && eabs (new_lines - old_lines) >= 1)
{
+ XSETFRAME (frame, f);
+ Fmodify_frame_parameters (frame,
+ list1 (Fcons (Qtool_bar_lines,
+ make_number (new_lines))));
clear_glyph_matrix (w->desired_matrix);
f->n_tool_bar_rows = nrows;
f->fonts_changed = 1;
{
int h_margin;
int text_area_width;
- struct glyph_row *current_cursor_row
- = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
- struct glyph_row *desired_cursor_row
- = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
- struct glyph_row *cursor_row
- = (desired_cursor_row->enabled_p
- ? desired_cursor_row
- : current_cursor_row);
- int row_r2l_p = cursor_row->reversed_p;
+ struct glyph_row *cursor_row;
+ struct glyph_row *bottom_row;
+ int row_r2l_p;
+
+ bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
+ if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
+ cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
+ else
+ cursor_row = bottom_row - 1;
+
+ if (!cursor_row->enabled_p)
+ {
+ bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
+ if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
+ cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+ else
+ cursor_row = bottom_row - 1;
+ }
+ row_r2l_p = cursor_row->reversed_p;
text_area_width = window_box_width (w, TEXT_AREA);
/* For left-to-right rows, hscroll when cursor is either
(i) inside the right hscroll margin, or (ii) if it is
inside the left margin and the window is already
- hscrolled. */
+ hscrolled. */
&& ((!row_r2l_p
&& ((w->hscroll
&& w->cursor.x <= h_margin)
&& ((cursor_row->enabled_p
/* FIXME: It is confusing to set the
truncated_on_right_p flag when R2L rows
- are actually truncated on the left. */
+ are actually truncated on the left. */
&& cursor_row->truncated_on_right_p
&& w->cursor.x <= h_margin)
|| (w->hscroll
static ptrdiff_t debug_end_vpos;
/* Append a string to W->desired_matrix->method. FMT is a printf
- format string. If trace_redisplay_p is non-zero also printf the
+ format string. If trace_redisplay_p is true also printf the
resulting string to stderr. */
static void debug_method_add (struct window *, char const *, ...)
PT == w->last_point
/* Make sure the cursor was last displayed
in this window. Otherwise we have to reposition it. */
+
+ /* PXW: Must be converted to pixels, probably. */
&& 0 <= w->cursor.vpos
&& w->cursor.vpos < WINDOW_TOTAL_LINES (w))
{
cancel:
/* Text changed drastically or point moved off of line. */
- SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
+ SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
}
CHARPOS (this_line_start_pos) = 0;
if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
bool gcscrollbars
- /* Only GC scollbars when we redisplay the whole frame. */
- = f->redisplay || windows_or_buffers_changed != REDISPLAY_SOME;
+ /* Only GC scrollbars when we redisplay the whole frame. */
+ = f->redisplay || !REDISPLAY_SOME_P ();
/* Mark all the scroll bars to be removed; we'll redeem
the ones we want when we redisplay their windows. */
if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
redisplay_windows (FRAME_ROOT_WINDOW (f));
+ /* Remember that the invisible frames need to be redisplayed next
+ time they're visible. */
+ else if (!REDISPLAY_SOME_P ())
+ f->redisplay = true;
/* The X error handler may have deleted that frame. */
if (!FRAME_LIVE_P (f))
/* Prevent various kinds of signals during display
update. stdio is not robust about handling
- signals, which can cause an apparent I/O
- error. */
+ signals, which can cause an apparent I/O error. */
if (interrupt_input)
unrequest_sigio ();
STOP_POLLING;
- /* Mark windows on frame F to update. If we decide to
- update all frames but windows_or_buffers_changed is
- zero, we assume that only the windows that shows
- current buffer should be really updated. */
- set_window_update_flags
- (XWINDOW (f->root_window),
- (windows_or_buffers_changed ? NULL : current_buffer), 1);
pending |= update_frame (f, 0, 0);
f->cursor_type_changed = 0;
f->updated_p = 1;
if (hscroll_windows (selected_window))
goto retry;
- XWINDOW (selected_window)->must_be_updated_p = 1;
+ XWINDOW (selected_window)->must_be_updated_p = true;
pending = update_frame (sf, 0, 0);
sf->cursor_type_changed = 0;
}
if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
{
- XWINDOW (mini_window)->must_be_updated_p = 1;
+ XWINDOW (mini_window)->must_be_updated_p = true;
pending |= update_frame (mini_frame, 0, 0);
mini_frame->cursor_type_changed = 0;
if (!pending && hscroll_windows (mini_window))
#endif /* HAVE_WINDOW_SYSTEM */
end_of_redisplay:
+ if (interrupt_input && interrupts_deferred)
+ request_sigio ();
+
unbind_to (count, Qnil);
RESUME_POLLING;
}
redisplay_window_0 (Lisp_Object window)
{
if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
- redisplay_window (window, 0);
+ redisplay_window (window, false);
return Qnil;
}
redisplay_window_1 (Lisp_Object window)
{
if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
- redisplay_window (window, 1);
+ redisplay_window (window, true);
return Qnil;
}
\f
if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1, 0)
/* It's possible that the cursor is on the first line of the
buffer, which is partially obscured due to a vscroll
- (Bug#7537). In that case, avoid looping forever . */
+ (Bug#7537). In that case, avoid looping forever. */
&& extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
{
clear_glyph_matrix (w->desired_matrix);
/* If the line start is "too far" away from the window start,
say it takes too much time to compute a new window start. */
if (CHARPOS (start_pos) - IT_CHARPOS (it)
+ /* PXW: Do we need upper bounds here? */
< WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))
{
int min_distance, distance;
changed on window's frame. In that case, redisplay_internal will retry. */
static void
-redisplay_window (Lisp_Object window, int just_this_one_p)
+redisplay_window (Lisp_Object window, bool just_this_one_p)
{
struct window *w = XWINDOW (window);
struct frame *f = XFRAME (w->frame);
int tem;
struct it it;
/* Record it now because it's overwritten. */
- int current_matrix_up_to_date_p = 0;
- int used_current_matrix_p = 0;
+ bool current_matrix_up_to_date_p = false;
+ bool used_current_matrix_p = false;
/* This is less strict than current_matrix_up_to_date_p.
It indicates that the buffer contents and narrowing are unchanged. */
- int buffer_unchanged_p = 0;
+ bool buffer_unchanged_p = false;
int temp_scroll_step = 0;
ptrdiff_t count = SPECPDL_INDEX ();
int rc;
#endif
if (!just_this_one_p
- && (update_mode_lines == REDISPLAY_SOME
- || update_mode_lines == 0)
- && (windows_or_buffers_changed == REDISPLAY_SOME
- || windows_or_buffers_changed == 0)
+ && REDISPLAY_SOME_P ()
&& !w->redisplay
&& !f->redisplay
- && !buffer->text->redisplay)
+ && !buffer->text->redisplay
+ && BUF_PT (buffer) == w->last_point)
return;
/* Make sure that both W's markers are valid. */
|| buffer->clip_changed
|| buffer->prevent_redisplay_optimizations_p);
+ if (!just_this_one_p)
+ /* If `just_this_one_p' is set, we apparently set must_be_updated_p more
+ cleverly elsewhere. */
+ w->must_be_updated_p = true;
+
if (MINI_WINDOW_P (w))
{
if (w == XWINDOW (echo_area_window)
if (XMARKER (w->start)->buffer == current_buffer)
compute_window_start_on_continuation_line (w);
- w->window_end_valid = 0;
+ w->window_end_valid = false;
/* If so, we also can't rely on current matrix
and should not fool try_cursor_movement below. */
- current_matrix_up_to_date_p = 0;
+ current_matrix_up_to_date_p = false;
}
/* Some sanity checks. */
this may be a bit late to catch such changes, but the rest of
redisplay goes (non-fatally) haywire when the display table is
changed, so why should we worry about doing any better? */
- if (current_buffer->width_run_cache)
+ if (current_buffer->width_run_cache
+ || (current_buffer->base_buffer
+ && current_buffer->base_buffer->width_run_cache))
{
struct Lisp_Char_Table *disptab = buffer_display_table ();
if (! disptab_matches_widthtab
(disptab, XVECTOR (BVAR (current_buffer, width_table))))
{
- invalidate_region_cache (current_buffer,
- current_buffer->width_run_cache,
- BEG, Z);
+ struct buffer *buf = current_buffer;
+
+ if (buf->base_buffer)
+ buf = buf->base_buffer;
+ invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
recompute_width_table (current_buffer, disptab);
}
}
SET_TEXT_POS_FROM_MARKER (startp, w->start);
w->start_at_line_beg = (CHARPOS (startp) == BEGV
- || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
+ || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
/* Display the mode line, if we must. */
if ((update_mode_line
&& (WINDOW_WANTS_MODELINE_P (w)
|| WINDOW_WANTS_HEADER_LINE_P (w)))
{
+
display_mode_lines (w);
/* If mode line height has changed, arrange for a thorough
redisplay_tool_bar (f);
#else
if (WINDOWP (f->tool_bar_window)
- && (FRAME_TOOL_BAR_LINES (f) > 0
+ && (FRAME_TOOL_BAR_HEIGHT (f) > 0
|| !NILP (Vauto_resize_tool_bars))
&& redisplay_tool_bar (f))
ignore_mouse_drag_p = 1;
update_begin (f);
block_input ();
if (draw_window_fringes (w, 1))
- x_draw_vertical_border (w);
+ {
+ if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+ x_draw_right_divider (w);
+ else
+ x_draw_vertical_border (w);
+ }
unblock_input ();
update_end (f);
}
+
+ if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+ x_draw_bottom_divider (w);
#endif /* HAVE_WINDOW_SYSTEM */
/* We go to this label, with fonts_changed set, if it is
set_buffer_internal_1 (old);
/* Avoid an abort in TEMP_SET_PT_BOTH if the buffer has become
- shorter. This can be caused by log truncation in *Messages*. */
+ shorter. This can be caused by log truncation in *Messages*. */
if (CHARPOS (lpoint) <= ZV)
TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
/* Disable lines that must be updated. */
for (i = 0; i < nrows_scrolled; ++i)
- (start_row + i)->enabled_p = 0;
+ (start_row + i)->enabled_p = false;
/* Re-compute Y positions. */
min_y = WINDOW_HEADER_LINE_HEIGHT (w);
/* Disable rows not reused. */
for (row -= nrows_scrolled; row < bottom_row; ++row)
- row->enabled_p = 0;
+ row->enabled_p = false;
/* Point may have moved to a different line, so we cannot assume that
the previous cursor position is valid; locate the correct row. */
/* Disable frame rows whose corresponding window rows have
been disabled in try_window_id. */
if (!window_row->enabled_p)
- frame_row->enabled_p = 0;
+ frame_row->enabled_p = false;
++window_row, ++frame_row;
}
Value is
- 1 if display has been updated
- 0 if otherwise unsuccessful
+ >= 1 if successful, i.e. display has been updated
+ specifically:
+ 1 means the changes were in front of a newline that precedes
+ the window start, and the whole current matrix was reused
+ 2 means the changes were after the last position displayed
+ in the window, and the whole current matrix was reused
+ 3 means portions of the current matrix were reused, while
+ some of the screen lines were redrawn
-1 if redisplay with same window start is known not to succeed
+ 0 if otherwise unsuccessful
The following steps are performed:
if (windows_or_buffers_changed || f->cursor_type_changed)
GIVE_UP (2);
+ /* This function's optimizations cannot be used if overlays have
+ changed in the buffer displayed by the window, so give up if they
+ have. */
+ if (w->last_overlay_modified != OVERLAY_MODIFF)
+ GIVE_UP (21);
+
/* Verify that narrowing has not changed.
Also verify that we were not told to prevent redisplay optimizations.
It would be nice to further
= run.current_y = run.desired_y = run.height = 0;
first_unchanged_at_end_row = NULL;
}
- IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
+ IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
/* Find the cursor if not already found. We have to decide whether
the current matrix? I don't think so, so we mark rows
displayed invalid in the current matrix by setting their
enabled_p flag to zero. */
- MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
+ SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
if (display_line (&it))
last_text_row_at_end = it.glyph_row - 1;
}
else
emacs_abort ();
- IF_DEBUG (debug_end_pos = w->window_end_pos;
- debug_end_vpos = w->window_end_vpos);
+ IF_DEBUG ((debug_end_pos = w->window_end_pos,
+ debug_end_vpos = w->window_end_vpos));
/* Record that display has not been completed. */
w->window_end_valid = 0;
1-``pixel'' wide, so they hit the equality too early. This grace
is needed only for R2L rows that are not continued, to produce
one extra blank where we could display the cursor. */
- if (it->current_x >= it->last_visible_x
- + (!FRAME_WINDOW_P (f)
- && it->glyph_row->reversed_p
- && !it->glyph_row->continued_p))
+ if ((it->current_x >= it->last_visible_x
+ + (!FRAME_WINDOW_P (f)
+ && it->glyph_row->reversed_p
+ && !it->glyph_row->continued_p))
+ /* If the window has display margins, we will need to extend
+ their face even if the text area is filled. */
+ && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
return;
/* The default face, possibly remapped. */
it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
it->glyph_row->used[TEXT_AREA] = 1;
}
+ /* Mode line and the header line don't have margins, and
+ likewise the frame's tool-bar window, if there is any. */
+ if (!(it->glyph_row->mode_line_p
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
+ || (WINDOWP (f->tool_bar_window)
+ && it->w == XWINDOW (f->tool_bar_window))
+#endif
+ ))
+ {
+ if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
+ {
+ it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
+ it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
+ default_face->id;
+ it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
+ }
+ if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
+ && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
+ {
+ it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
+ it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
+ default_face->id;
+ it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
+ }
+ }
#ifdef HAVE_WINDOW_SYSTEM
if (it->glyph_row->reversed_p)
{
it->object = make_number (0);
it->c = it->char_to_display = ' ';
it->len = 1;
+
+ if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ && (it->glyph_row->used[LEFT_MARGIN_AREA]
+ < WINDOW_LEFT_MARGIN_WIDTH (it->w))
+ && !it->glyph_row->mode_line_p
+ && default_face->background != FRAME_BACKGROUND_PIXEL (f))
+ {
+ struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
+ struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
+
+ for (it->current_x = 0; g < e; g++)
+ it->current_x += g->pixel_width;
+
+ it->area = LEFT_MARGIN_AREA;
+ it->face_id = default_face->id;
+ while (it->glyph_row->used[LEFT_MARGIN_AREA]
+ < WINDOW_LEFT_MARGIN_WIDTH (it->w))
+ {
+ PRODUCE_GLYPHS (it);
+ /* term.c:produce_glyphs advances it->current_x only for
+ TEXT_AREA. */
+ it->current_x += it->pixel_width;
+ }
+
+ it->current_x = saved_x;
+ it->area = TEXT_AREA;
+ }
+
/* The last row's blank glyphs should get the default face, to
avoid painting the rest of the window with the region face,
if the region ends at ZV. */
it->face_id = default_face->id;
else
it->face_id = face->id;
-
PRODUCE_GLYPHS (it);
while (it->current_x <= it->last_visible_x)
PRODUCE_GLYPHS (it);
+ if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
+ && (it->glyph_row->used[RIGHT_MARGIN_AREA]
+ < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
+ && !it->glyph_row->mode_line_p
+ && default_face->background != FRAME_BACKGROUND_PIXEL (f))
+ {
+ struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
+ struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
+
+ for ( ; g < e; g++)
+ it->current_x += g->pixel_width;
+
+ it->area = RIGHT_MARGIN_AREA;
+ it->face_id = default_face->id;
+ while (it->glyph_row->used[RIGHT_MARGIN_AREA]
+ < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
+ {
+ PRODUCE_GLYPHS (it);
+ it->current_x += it->pixel_width;
+ }
+
+ it->area = TEXT_AREA;
+ }
+
/* Don't count these blanks really. It would let us insert a left
truncation glyph below and make us set the cursor on them, maybe. */
it->current_x = saved_x;
}
else if (it->bidi_p)
RECORD_MAX_MIN_POS (it);
+ if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
+ extend_face_to_end_of_line (it);
}
else if (CHAR_GLYPH_PADDING_P (*glyph)
&& !FRAME_WINDOW_P (it->f))
it->max_descent = descent;
it->max_phys_ascent = phys_ascent;
it->max_phys_descent = phys_descent;
+ if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
+ extend_face_to_end_of_line (it);
}
else if (wrap_row_used > 0)
{
row->continued_p = 1;
glyph->pixel_width = it->last_visible_x - x;
it->starts_in_middle_of_char_p = 1;
+ if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+ || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
+ extend_face_to_end_of_line (it);
}
else
{
itb.string.s = NULL;
itb.string.lstring = Qnil;
itb.string.bufpos = 0;
+ itb.string.from_disp_str = 0;
itb.string.unibyte = 0;
/* We have no window to use here for ignoring window-specific
overlays. Using NULL for window pointer will cause
of this or previous line to make sure we are before point in
the logical order (since the move_it_* functions can only
move forward). */
+ reseat:
reseat_at_previous_visible_line_start (&it);
it.current_x = it.hpos = it.current_y = it.vpos = 0;
if (IT_CHARPOS (it) != PT)
- move_it_to (&it, overshoot_expected ? PT - 1 : PT,
- -1, -1, -1, MOVE_TO_POS);
+ {
+ move_it_to (&it, overshoot_expected ? PT - 1 : PT,
+ -1, -1, -1, MOVE_TO_POS);
+ /* If we missed point because the character there is
+ displayed out of a display vector that has more than one
+ glyph, retry expecting overshoot. */
+ if (it.method == GET_FROM_DISPLAY_VECTOR
+ && it.current.dpvec_index > 0
+ && !overshoot_expected)
+ {
+ overshoot_expected = true;
+ goto reseat;
+ }
+ else if (IT_CHARPOS (it) != PT && !overshoot_expected)
+ move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
+ }
pt_x = it.current_x;
pt_vpos = it.vpos;
if (dir > 0 || overshoot_expected)
else if (pixel_width <= 0)
pixel_width = 1;
- /* If there's a display string at point, we are actually at the
- glyph to the left of point, so we need to correct the X
- coordinate. */
+ /* If there's a display string (or something similar) at point,
+ we are actually at the glyph to the left of point, so we need
+ to correct the X coordinate. */
if (overshoot_expected)
- pt_x += pixel_width;
+ {
+ if (it.bidi_p)
+ pt_x += pixel_width * it.bidi_it.scan_dir;
+ else
+ pt_x += pixel_width;
+ }
/* Compute target X coordinate, either to the left or to the
right of point. On TTY frames, all characters have the same
character at point. */
if (FRAME_WINDOW_P (it.f) && dir < 0)
{
- struct text_pos new_pos = it.current.pos;
+ struct text_pos new_pos;
enum move_it_result rc = MOVE_X_REACHED;
+ if (it.current_x == 0)
+ get_next_display_element (&it);
+ if (it.what == IT_COMPOSITION)
+ {
+ new_pos.charpos = it.cmp_it.charpos;
+ new_pos.bytepos = -1;
+ }
+ else
+ new_pos = it.current.pos;
+
while (it.current_x + it.pixel_width <= target_x
&& rc == MOVE_X_REACHED)
{
int new_x = it.current_x + it.pixel_width;
- new_pos = it.current.pos;
+ /* For composed characters, we want the position of the
+ first character in the grapheme cluster (usually, the
+ composition's base character), whereas it.current
+ might give us the position of the _last_ one, e.g. if
+ the composition is rendered in reverse due to bidi
+ reordering. */
+ if (it.what == IT_COMPOSITION)
+ {
+ new_pos.charpos = it.cmp_it.charpos;
+ new_pos.bytepos = -1;
+ }
+ else
+ new_pos = it.current.pos;
if (new_x == it.current_x)
new_x++;
rc = move_it_in_display_line_to (&it, ZV, new_x,
if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
break;
}
- /* If we ended up on a composed character inside
- bidi-reordered text (e.g., Hebrew text with diacritics),
- the iterator gives us the buffer position of the last (in
- logical order) character of the composed grapheme cluster,
- which is not what we want. So we cheat: we compute the
- character position of the character that follows (in the
- logical order) the one where the above loop stopped. That
- character will appear on display to the left of point. */
- if (it.bidi_p
- && it.bidi_it.scan_dir == -1
- && new_pos.charpos - IT_CHARPOS (it) > 1)
- {
- new_pos.charpos = IT_CHARPOS (it) + 1;
- new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
- }
+ /* The previous position we saw in the loop is the one we
+ want. */
+ if (new_pos.bytepos == -1)
+ new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
it.current.pos = new_pos;
}
else
eassert (!FRAME_WINDOW_P (f));
init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
it.first_visible_x = 0;
- it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+ it.last_visible_x = FRAME_PIXEL_WIDTH (f);
#elif defined (HAVE_X_WINDOWS) /* X without toolkit. */
if (FRAME_WINDOW_P (f))
{
init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
MENU_FACE_ID);
it.first_visible_x = 0;
- it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+ it.last_visible_x = FRAME_PIXEL_WIDTH (f);
}
else
#endif /* not USE_X_TOOLKIT and not USE_GTK */
{
struct glyph_row *row = it.glyph_row + i;
clear_glyph_row (row);
- row->enabled_p = 1;
+ row->enabled_p = true;
row->full_width_p = 1;
}
row->full_width_p = 1;
saved_reversed = row->reversed_p;
row->reversed_p = 0;
- row->enabled_p = 1;
+ row->enabled_p = true;
/* Arrange for the menu item glyphs to start at (X,Y) and have the
desired face. */
the number of windows whose mode lines were redisplayed. */
static int
-redisplay_mode_lines (Lisp_Object window, int force)
+redisplay_mode_lines (Lisp_Object window, bool force)
{
int nwindows = 0;
/* Display mode lines. */
clear_glyph_matrix (w->desired_matrix);
if (display_mode_lines (w))
- {
- ++nwindows;
- w->must_be_updated_p = 1;
- }
+ ++nwindows;
/* Restore old settings. */
set_buffer_internal_1 (old);
XFRAME (new_frame)->selected_window = old_frame_selected_window;
selected_frame = old_selected_frame;
selected_window = old_selected_window;
+ if (n > 0)
+ w->must_be_updated_p = true;
return n;
}
init_iterator (&it, w, -1, -1, NULL, face_id);
/* Don't extend on a previously drawn mode-line.
This may happen if called from pos_visible_p. */
- it.glyph_row->enabled_p = 0;
+ it.glyph_row->enabled_p = false;
prepare_desired_row (it.glyph_row);
it.glyph_row->mode_line_p = 1;
the drawing area, set S->extends_to_end_of_line_p. */
if (start == s->row->used[s->area]
- && s->area == TEXT_AREA
&& ((s->row->fill_line_p
&& (s->hl == DRAW_NORMAL_TEXT
|| s->hl == DRAW_IMAGE_RAISED
/* X is relative to the left edge of W, without scroll bars
or fringes. */
area_left = WINDOW_LEFT_EDGE_X (w);
- last_x = WINDOW_LEFT_EDGE_X (w) + WINDOW_TOTAL_WIDTH (w);
+ last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
+ - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
}
else
{
f = XFRAME (w->frame);
if (updated_row->full_width_p)
- max_x = WINDOW_TOTAL_WIDTH (w);
+ max_x = (WINDOW_PIXEL_WIDTH (w)
+ - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
else
max_x = window_box_width (w, updated_area);
max_y = window_text_bottom_y (w);
return cleared;
}
-/* Return non-zero if the coordinates HPOS and VPOS on windows W are
+/* Return true if the coordinates HPOS and VPOS on windows W are
within the mouse face on that window. */
-static int
+static bool
coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
{
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
/* Quickly resolve the easy cases. */
if (!(WINDOWP (hlinfo->mouse_face_window)
&& XWINDOW (hlinfo->mouse_face_window) == w))
- return 0;
+ return false;
if (vpos < hlinfo->mouse_face_beg_row
|| vpos > hlinfo->mouse_face_end_row)
- return 0;
+ return false;
if (vpos > hlinfo->mouse_face_beg_row
&& vpos < hlinfo->mouse_face_end_row)
- return 1;
+ return true;
if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
{
if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
{
if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
- return 1;
+ return true;
}
else if ((vpos == hlinfo->mouse_face_beg_row
&& hpos >= hlinfo->mouse_face_beg_col)
|| (vpos == hlinfo->mouse_face_end_row
&& hpos < hlinfo->mouse_face_end_col))
- return 1;
+ return true;
}
else
{
if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
{
if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
- return 1;
+ return true;
}
else if ((vpos == hlinfo->mouse_face_beg_row
&& hpos <= hlinfo->mouse_face_beg_col)
|| (vpos == hlinfo->mouse_face_end_row
&& hpos > hlinfo->mouse_face_end_col))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* EXPORT:
- Non-zero if physical cursor of window W is within mouse face. */
+ True if physical cursor of window W is within mouse face. */
-int
+bool
cursor_in_mouse_face_p (struct window *w)
{
int hpos = w->phys_cursor.hpos;
cursor = FRAME_X_OUTPUT (f)->text_cursor;
else if (EQ (pointer, intern ("hdrag")))
cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+ else if (EQ (pointer, intern ("nhdrag")))
+ cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
#ifdef HAVE_X_WINDOWS
else if (EQ (pointer, intern ("vdrag")))
cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
help_echo_string = build_string ("drag-mouse-1: resize");
}
+ else if (part == ON_RIGHT_DIVIDER)
+ {
+ cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+ help_echo_string = build_string ("drag-mouse-1: resize");
+ }
+ else if (part == ON_BOTTOM_DIVIDER)
+ {
+ cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
+ help_echo_string = build_string ("drag-mouse-1: resize");
+ }
else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
|| part == ON_SCROLL_BAR)
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
do it for frames with vertical scroll bars because either the
right scroll bar of a window, or the left scroll bar of its
neighbor will suffice as a border. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame)))
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
return;
/* Note: It is necessary to redraw both the left and the right
FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
}
+
if (!WINDOW_LEFTMOST_P (w)
&& !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
{
}
+/* Draw window dividers for window W. */
+
+void
+x_draw_right_divider (struct window *w)
+{
+ struct frame *f = WINDOW_XFRAME (w);
+
+ if (w->mini || w->pseudo_window_p)
+ return;
+ else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+ {
+ int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
+ int x1 = WINDOW_RIGHT_EDGE_X (w);
+ int y0 = WINDOW_TOP_EDGE_Y (w);
+ /* The bottom divider prevails. */
+ int y1 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+
+ FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
+ }
+}
+
+static void
+x_draw_bottom_divider (struct window *w)
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+
+ if (w->mini || w->pseudo_window_p)
+ return;
+ else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+ {
+ int x0 = WINDOW_LEFT_EDGE_X (w);
+ int x1 = WINDOW_RIGHT_EDGE_X (w);
+ int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+ int y1 = WINDOW_BOTTOM_EDGE_Y (w);
+
+ FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
+ }
+}
+
/* Redraw the part of window W intersection rectangle FR. Pixel
coordinates in FR are frame-relative. Call this function with
input blocked. Value is non-zero if the exposure overwrites
/* Frame-relative pixel rectangle of W. */
wr.x = WINDOW_LEFT_EDGE_X (w);
wr.y = WINDOW_TOP_EDGE_Y (w);
- wr.width = WINDOW_TOTAL_WIDTH (w);
- wr.height = WINDOW_TOTAL_HEIGHT (w);
+ wr.width = WINDOW_PIXEL_WIDTH (w);
+ wr.height = WINDOW_PIXEL_HEIGHT (w);
if (x_intersect_rectangles (fr, &wr, &r))
{
fr);
/* Draw border between windows. */
- x_draw_vertical_border (w);
+ if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+ x_draw_right_divider (w);
+ else
+ x_draw_vertical_border (w);
+
+ if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+ x_draw_bottom_divider (w);
/* Turn the cursor on again. */
if (cursor_cleared_p
defsubr (&Strace_to_stderr);
#endif
#ifdef HAVE_WINDOW_SYSTEM
- defsubr (&Stool_bar_lines_needed);
+ defsubr (&Stool_bar_height);
defsubr (&Slookup_image_map);
#endif
defsubr (&Sline_pixel_height);
defsubr (&Sformat_mode_line);
defsubr (&Sinvisible_p);
defsubr (&Scurrent_bidi_paragraph_direction);
+ defsubr (&Swindow_text_pixel_size);
defsubr (&Smove_point_visually);
DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
echo_area_window = minibuf_window;
r->top_line = FRAME_TOP_MARGIN (f);
- r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
+ r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
r->total_cols = FRAME_COLS (f);
+ r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
+ r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
+ r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
m->top_line = FRAME_LINES (f) - 1;
- m->total_lines = 1;
+ m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
m->total_cols = FRAME_COLS (f);
+ m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
+ m->total_lines = 1;
+ m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
scratch_glyph_row.glyphs[TEXT_AREA + 1]