#include "font.h"
#include "fontset.h"
#include "blockinput.h"
-
-#ifdef HAVE_X_WINDOWS
-#include "xterm.h"
-#endif
-#ifdef HAVE_NTGUI
-#include "w32term.h"
-#endif
-#ifdef HAVE_NS
-#include "nsterm.h"
-#endif
-#ifdef USE_GTK
-#include "gtkutil.h"
-#endif
-
-#include "font.h"
+#ifdef HAVE_WINDOW_SYSTEM
+#include TERM_HEADER
+#endif /* HAVE_WINDOW_SYSTEM */
#ifndef FRAME_X_OUTPUT
#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
&& ((IT)->bidi_it.paragraph_dir == R2L \
? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
: (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
- && (IT)->current_x == (IT)->last_visible_x \
- && (IT)->line_wrap != WORD_WRAP)
+ && (IT)->current_x == (IT)->last_visible_x)
#else /* !HAVE_WINDOW_SYSTEM */
#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) 0
int windows_or_buffers_changed;
-/* Nonzero means a frame's cursor type has been changed. */
-
-int cursor_type_changed;
-
/* Nonzero after display_mode_line if %l was used and it displayed a
line number. */
int help_echo_showing_p;
-/* If >= 0, computed, exact values of mode-line and header-line height
- to use in the macros CURRENT_MODE_LINE_HEIGHT and
- CURRENT_HEADER_LINE_HEIGHT. */
-
-int current_mode_line_height, current_header_line_height;
-
/* The maximum distance to look ahead for text properties. Values
that are too small let us call compute_char_face and similar
functions too often which is expensive. Values that are too large
/* Platform-independent portion of hourglass implementation. */
+#ifdef HAVE_WINDOW_SYSTEM
+
/* Non-zero means an hourglass cursor is currently shown. */
int hourglass_shown_p;
an hourglass cursor on all frames. */
struct atimer *hourglass_atimer;
+#endif /* HAVE_WINDOW_SYSTEM */
+
/* Name of the face used to display glyphless characters. */
Lisp_Object Qglyphless_char;
/* Method symbols for Vglyphless_char_display. */
static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width;
-/* Default pixel width of `thin-space' display method. */
-#define THIN_SPACE_WIDTH 1
-
/* Default number of seconds to wait before displaying an hourglass
cursor. */
#define DEFAULT_HOURGLASS_DELAY 1
-\f
+#ifdef HAVE_WINDOW_SYSTEM
+
+/* Default pixel width of `thin-space' display method. */
+#define THIN_SPACE_WIDTH 1
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
/* Function prototypes. */
static void setup_for_ellipsis (struct it *, int);
static void pint2hrstr (char *, int, ptrdiff_t);
static struct text_pos run_window_scroll_functions (Lisp_Object,
struct text_pos);
-static void reconsider_clip_changes (struct window *, struct buffer *);
static int text_outside_line_unchanged_p (struct window *,
ptrdiff_t, ptrdiff_t);
static void store_mode_line_noprop_char (char);
static void handle_stop_backwards (struct it *, ptrdiff_t);
static void vmessage (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
static void ensure_echo_area_buffers (void);
-static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object);
+static void unwind_with_echo_area_buffer (Lisp_Object);
static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
static int with_echo_area_buffer (struct window *, int,
int (*) (ptrdiff_t, Lisp_Object),
ptrdiff_t, Lisp_Object);
static void clear_garbaged_frames (void);
static int current_message_1 (ptrdiff_t, Lisp_Object);
-static void pop_message (void);
static int truncate_message_1 (ptrdiff_t, Lisp_Object);
static void set_message (Lisp_Object);
static int set_message_1 (ptrdiff_t, Lisp_Object);
static int display_echo_area (struct window *);
static int display_echo_area_1 (ptrdiff_t, Lisp_Object);
static int resize_mini_window_1 (ptrdiff_t, Lisp_Object);
-static Lisp_Object unwind_redisplay (Lisp_Object);
+static void unwind_redisplay (void);
static int string_char_and_length (const unsigned char *, int *);
static struct text_pos display_prop_end (struct it *, Lisp_Object,
struct text_pos);
return height;
}
-/* Return the pixel width of display area AREA of window W. AREA < 0
- means return the total width of W, not including fringes to
- the left and right of the window. */
+/* Return the pixel width of display area AREA of window W.
+ ANY_AREA means return the total width of W, not including
+ fringes to the left and right of the window. */
int
-window_box_width (struct window *w, int area)
+window_box_width (struct window *w, enum glyph_row_area area)
{
int cols = w->total_cols;
int pixels = 0;
if (area == TEXT_AREA)
{
- if (INTEGERP (w->left_margin_cols))
- cols -= XFASTINT (w->left_margin_cols);
- if (INTEGERP (w->right_margin_cols))
- cols -= XFASTINT (w->right_margin_cols);
+ cols -= max (0, w->left_margin_cols);
+ cols -= max (0, w->right_margin_cols);
pixels = -WINDOW_TOTAL_FRINGE_WIDTH (w);
}
else if (area == LEFT_MARGIN_AREA)
{
- cols = (INTEGERP (w->left_margin_cols)
- ? XFASTINT (w->left_margin_cols) : 0);
+ cols = max (0, w->left_margin_cols);
pixels = 0;
}
else if (area == RIGHT_MARGIN_AREA)
{
- cols = (INTEGERP (w->right_margin_cols)
- ? XFASTINT (w->right_margin_cols) : 0);
+ cols = max (0, w->right_margin_cols);
pixels = 0;
}
}
}
/* Return the window-relative coordinate of the left edge of display
- area AREA of window W. AREA < 0 means return the left edge of the
+ area AREA of window W. ANY_AREA means return the left edge of the
whole window, to the right of the left fringe of W. */
int
-window_box_left_offset (struct window *w, int area)
+window_box_left_offset (struct window *w, enum glyph_row_area area)
{
int x;
/* Return the window-relative coordinate of the right edge of display
- area AREA of window W. AREA < 0 means return the right edge of the
+ area AREA of window W. ANY_AREA means return the right edge of the
whole window, to the left of the right fringe of W. */
int
-window_box_right_offset (struct window *w, int area)
+window_box_right_offset (struct window *w, enum glyph_row_area area)
{
return window_box_left_offset (w, area) + window_box_width (w, area);
}
/* Return the frame-relative coordinate of the left edge of display
- area AREA of window W. AREA < 0 means return the left edge of the
+ area AREA of window W. ANY_AREA means return the left edge of the
whole window, to the right of the left fringe of W. */
int
-window_box_left (struct window *w, int area)
+window_box_left (struct window *w, enum glyph_row_area area)
{
struct frame *f = XFRAME (w->frame);
int x;
/* Return the frame-relative coordinate of the right edge of display
- area AREA of window W. AREA < 0 means return the right edge of the
+ area AREA of window W. ANY_AREA means return the right edge of the
whole window, to the left of the right fringe of W. */
int
-window_box_right (struct window *w, int area)
+window_box_right (struct window *w, enum glyph_row_area area)
{
return window_box_left (w, area) + window_box_width (w, area);
}
/* Get the bounding box of the display area AREA of window W, without
- mode lines, in frame-relative coordinates. AREA < 0 means the
+ mode lines, in frame-relative coordinates. ANY_AREA means the
whole window, not including the left and right fringes of
the window. Return in *BOX_X and *BOX_Y the frame-relative pixel
coordinates of the upper-left corner of the box. Return in
*BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
void
-window_box (struct window *w, int area, int *box_x, int *box_y,
- int *box_width, int *box_height)
+window_box (struct window *w, enum glyph_row_area area, int *box_x,
+ int *box_y, int *box_width, int *box_height)
{
if (box_width)
*box_width = window_box_width (w, area);
}
}
+#ifdef HAVE_WINDOW_SYSTEM
/* Get the bounding box of the display area AREA of window W, without
- mode lines. AREA < 0 means the whole window, not including the
- left and right fringe of the window. Return in *TOP_LEFT_X
+ mode lines and both fringes of the window. Return in *TOP_LEFT_X
and TOP_LEFT_Y the frame-relative pixel coordinates of the
upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and
*BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
box. */
static void
-window_box_edges (struct window *w, int area, int *top_left_x, int *top_left_y,
- int *bottom_right_x, int *bottom_right_y)
+window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
+ int *bottom_right_x, int *bottom_right_y)
{
- window_box (w, area, top_left_x, top_left_y, bottom_right_x,
- bottom_right_y);
+ window_box (w, ANY_AREA, top_left_x, top_left_y,
+ bottom_right_x, bottom_right_y);
*bottom_right_x += *top_left_x;
*bottom_right_y += *top_left_y;
}
+#endif /* HAVE_WINDOW_SYSTEM */
-\f
/***********************************************************************
Utilities
***********************************************************************/
return make_number (line_bottom_y (&it));
}
+/* Return the default pixel height of text lines in window W. The
+ value is the canonical height of the W frame's default font, plus
+ any extra space required by the line-spacing variable or frame
+ parameter.
+
+ Implementation note: this ignores any line-spacing text properties
+ put on the newline characters. This is because those properties
+ only affect the _screen_ line ending in the newline (i.e., in a
+ continued line, only the last screen line will be affected), which
+ means only a small number of lines in a buffer can ever use this
+ feature. Since this function is used to compute the default pixel
+ equivalent of text lines in a window, we can safely ignore those
+ few lines. For the same reasons, we ignore the line-height
+ properties. */
+int
+default_line_pixel_height (struct window *w)
+{
+ struct frame *f = WINDOW_XFRAME (w);
+ int height = FRAME_LINE_HEIGHT (f);
+
+ if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
+ {
+ struct buffer *b = XBUFFER (w->contents);
+ Lisp_Object val = BVAR (b, extra_line_spacing);
+
+ if (NILP (val))
+ val = BVAR (&buffer_defaults, extra_line_spacing);
+ if (!NILP (val))
+ {
+ if (RANGED_INTEGERP (0, val, INT_MAX))
+ height += XFASTINT (val);
+ else if (FLOATP (val))
+ {
+ int addon = XFLOAT_DATA (val) * height + 0.5;
+
+ if (addon >= 0)
+ height += addon;
+ }
+ }
+ else
+ height += f->extra_line_spacing;
+ }
+
+ return height;
+}
+
/* Subroutine of pos_visible_p below. Extracts a display string, if
any, from the display spec given as its argument. */
static Lisp_Object
/* Compute exact mode line heights. */
if (WINDOW_WANTS_MODELINE_P (w))
- current_mode_line_height
+ w->mode_line_height
= display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
BVAR (current_buffer, mode_line_format));
if (WINDOW_WANTS_HEADER_LINE_P (w))
- current_header_line_height
+ w->header_line_height
= display_mode_line (w, HEADER_LINE_FACE_ID,
BVAR (current_buffer, header_line_format));
struct it save_it = it;
/* Why 10? because we don't know how many canonical lines
will the height of the next line(s) be. So we guess. */
- int ten_more_lines =
- 10 * FRAME_LINE_HEIGHT (XFRAME (WINDOW_FRAME (w)));
+ int ten_more_lines = 10 * default_line_pixel_height (w);
move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
MOVE_TO_POS | MOVE_TO_Y);
if (old_buffer)
set_buffer_internal_1 (old_buffer);
- current_header_line_height = current_mode_line_height = -1;
-
if (visible_p && w->hscroll > 0)
*x -=
window_hscroll_limited (w, WINDOW_XFRAME (w))
not force the value into range. */
void
-pixel_to_glyph_coords (FRAME_PTR f, register int pix_x, register int pix_y,
+pixel_to_glyph_coords (struct frame *f, register int pix_x, register int pix_y,
int *x, int *y, NativeRectangle *bounds, int noclip)
{
#endif /* HAVE_WINDOW_SYSTEM */
-\f
+static void
+adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
+{
+ eassert (w);
+ w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
+ w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
+ w->window_end_vpos
+ = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
+}
+
/***********************************************************************
Lisp form evaluation
***********************************************************************/
if (!MINI_WINDOW_P (w) && w->window_end_valid)
{
struct glyph_row *row;
- eassert ((row = MATRIX_ROW (w->current_matrix,
- XFASTINT (w->window_end_vpos)),
+ eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
!row->enabled_p
|| MATRIX_ROW_DISPLAYS_TEXT_P (row)
|| MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
/* For strings from a `display' property, use the face at
IT's current buffer position as the base face to merge
with, so that overlay strings appear in the same face as
- surrounding text, unless they specify their own
- faces. */
+ surrounding text, unless they specify their own faces.
+ For strings from wrap-prefix and line-prefix properties,
+ use the default face, possibly remapped via
+ Vface_remapping_alist. */
base_face_id = it->string_from_prefix_prop_p
- ? DEFAULT_FACE_ID
+ ? (!NILP (Vface_remapping_alist)
+ ? lookup_basic_face (it->f, DEFAULT_FACE_ID)
+ : DEFAULT_FACE_ID)
: underlying_face_id (it);
}
composition (in the case that the composition is from the current
buffer), draw a glyph composed from the composition components. */
if (find_composition (pos, -1, &start, &end, &prop, string)
- && COMPOSITION_VALID_P (start, end, prop)
+ && composition_valid_p (start, end, prop)
&& (STRINGP (it->string) || (PT <= start || PT >= end)))
{
if (start < pos)
static int
compare_overlay_entries (const void *e1, const void *e2)
{
- struct overlay_entry *entry1 = (struct overlay_entry *) e1;
- struct overlay_entry *entry2 = (struct overlay_entry *) e2;
+ struct overlay_entry const *entry1 = e1;
+ struct overlay_entry const *entry2 = e2;
int result;
if (entry1->after_string_p != entry2->after_string_p)
return glyphless_method;
}
-/* Load IT's display element fields with information about the next
- display element from the current position of IT. Value is zero if
- end of buffer (or C string) is reached. */
+/* Merge escape glyph face and cache the result. */
static struct frame *last_escape_glyph_frame = NULL;
static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
static int last_escape_glyph_merged_face_id = 0;
-struct frame *last_glyphless_glyph_frame = NULL;
-int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
-int last_glyphless_glyph_merged_face_id = 0;
+static int
+merge_escape_glyph_face (struct it *it)
+{
+ int face_id;
+
+ 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;
+ }
+ return face_id;
+}
+
+/* Likewise for glyphless glyph face. */
+
+static struct frame *last_glyphless_glyph_frame = NULL;
+static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
+static int last_glyphless_glyph_merged_face_id = 0;
+
+int
+merge_glyphless_glyph_face (struct it *it)
+{
+ int face_id;
+
+ if (it->f == last_glyphless_glyph_frame
+ && it->face_id == last_glyphless_glyph_face_id)
+ face_id = last_glyphless_glyph_merged_face_id;
+ else
+ {
+ /* Merge the `glyphless-char' face into the current face. */
+ face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
+ last_glyphless_glyph_frame = it->f;
+ last_glyphless_glyph_face_id = it->face_id;
+ last_glyphless_glyph_merged_face_id = face_id;
+ }
+ return face_id;
+}
+
+/* Load IT's display element fields with information about the next
+ display element from the current position of IT. Value is zero if
+ end of buffer (or C string) is reached. */
static int
get_next_display_element (struct it *it)
g = GLYPH_CODE_CHAR (gc);
lface_id = GLYPH_CODE_FACE (gc);
}
- if (lface_id)
- {
- 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;
- }
+
+ face_id = (lface_id
+ ? merge_faces (it->f, Qt, lface_id, it->face_id)
+ : merge_escape_glyph_face (it));
XSETINT (it->ctl_chars[0], g);
XSETINT (it->ctl_chars[1], c ^ 0100);
escape_glyph = GLYPH_CODE_CHAR (gc);
lface_id = GLYPH_CODE_FACE (gc);
}
- if (lface_id)
- {
- /* The display table specified a face.
- Merge it into face_id and also into escape_glyph. */
- 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;
- }
+
+ face_id = (lface_id
+ ? merge_faces (it->f, Qt, lface_id, it->face_id)
+ : merge_escape_glyph_face (it));
/* Draw non-ASCII hyphen with just highlighting: */
}
}
}
- else
+ /* next_element_from_display_vector sets this flag according to
+ faces of the display vector glyphs, see there. */
+ else if (it->method != GET_FROM_DISPLAY_VECTOR)
{
int face_id = face_after_it_pos (it);
it->end_of_box_run_p
next_element_from_display_vector (struct it *it)
{
Lisp_Object gc;
+ int prev_face_id = it->face_id;
+ int next_face_id;
/* Precondition. */
eassert (it->dpvec && it->current.dpvec_index >= 0);
if (GLYPH_CODE_P (gc))
{
+ struct face *this_face, *prev_face, *next_face;
+
it->c = GLYPH_CODE_CHAR (gc);
it->len = CHAR_BYTES (it->c);
it->face_id = merge_faces (it->f, Qt, lface_id,
it->saved_face_id);
}
+
+ /* Glyphs in the display vector could have the box face, so we
+ need to set the related flags in the iterator, as
+ appropriate. */
+ this_face = FACE_FROM_ID (it->f, it->face_id);
+ prev_face = FACE_FROM_ID (it->f, prev_face_id);
+
+ /* Is this character the first character of a box-face run? */
+ it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
+ && (!prev_face
+ || prev_face->box == FACE_NO_BOX));
+
+ /* For the last character of the box-face run, we need to look
+ either at the next glyph from the display vector, or at the
+ face we saw before the display vector. */
+ next_face_id = it->saved_face_id;
+ if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
+ {
+ if (it->dpvec_face_id >= 0)
+ next_face_id = it->dpvec_face_id;
+ else
+ {
+ int lface_id =
+ GLYPH_CODE_FACE (it->dpvec[it->current.dpvec_index + 1]);
+
+ if (lface_id > 0)
+ next_face_id = merge_faces (it->f, Qt, lface_id,
+ it->saved_face_id);
+ }
+ }
+ next_face = FACE_FROM_ID (it->f, next_face_id);
+ it->end_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
+ && (!next_face
+ || next_face->box == FACE_NO_BOX));
+ it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
}
else
/* Display table entry is invalid. Return a space. */
result = MOVE_LINE_CONTINUED;
break;
}
- if (ITERATOR_AT_END_OF_LINE_P (it))
+ if (ITERATOR_AT_END_OF_LINE_P (it)
+ && (it->line_wrap != WORD_WRAP
+ || wrap_it.sp < 0))
{
result = MOVE_NEWLINE_OR_CR;
break;
&& it->current_x == it->last_visible_x - 1
&& it->c != '\n'
&& it->c != '\t'
- && it->vpos < XFASTINT (it->w->window_end_vpos))
+ && it->vpos < it->w->window_end_vpos)
{
it->continuation_lines_width += it->current_x;
it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
start_pos = IT_CHARPOS (*it);
/* Estimate how many newlines we must move back. */
- nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
+ nlines = max (1, dy / default_line_pixel_height (it->w));
if (it->line_wrap == TRUNCATE)
pos_limit = BEGV;
else
void
message1 (const char *m)
{
- message3 (m ? make_unibyte_string (m, strlen (m)) : Qnil);
+ message3 (m ? build_unibyte_string (m) : Qnil);
}
void
message1_nolog (const char *m)
{
- message3_nolog (m ? make_unibyte_string (m, strlen (m)) : Qnil);
+ message3_nolog (m ? build_unibyte_string (m) : Qnil);
}
/* Display a message M which contains a single %s
ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
char *message_buf = alloca (maxsize + 1);
- len = doprnt (message_buf, maxsize, m, (char *)0, ap);
+ len = doprnt (message_buf, maxsize, m, 0, ap);
message3 (make_string (message_buf, len));
}
/* Restore global state from VECTOR which was created by
with_echo_area_buffer_unwind_data. */
-static Lisp_Object
+static void
unwind_with_echo_area_buffer (Lisp_Object vector)
{
set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
}
Vwith_echo_area_save_vector = vector;
- return Qnil;
}
if (height > WINDOW_TOTAL_LINES (w))
{
int old_height = WINDOW_TOTAL_LINES (w);
- freeze_window_starts (f, 1);
+
+ FRAME_WINDOWS_FROZEN (f) = 1;
grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
}
&& (exact_p || BEGV == ZV))
{
int old_height = WINDOW_TOTAL_LINES (w);
- freeze_window_starts (f, 0);
+
+ FRAME_WINDOWS_FROZEN (f) = 0;
shrink_mini_window (w);
window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
}
if (height > WINDOW_TOTAL_LINES (w))
{
int old_height = WINDOW_TOTAL_LINES (w);
- freeze_window_starts (f, 1);
+
+ FRAME_WINDOWS_FROZEN (f) = 1;
grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
}
else if (height < WINDOW_TOTAL_LINES (w))
{
int old_height = WINDOW_TOTAL_LINES (w);
- freeze_window_starts (f, 0);
+
+ FRAME_WINDOWS_FROZEN (f) = 0;
shrink_mini_window (w);
if (height)
{
- freeze_window_starts (f, 1);
+ FRAME_WINDOWS_FROZEN (f) = 1;
grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
}
}
-/* Handler for record_unwind_protect calling pop_message. */
-
-Lisp_Object
-pop_message_unwind (Lisp_Object dummy)
-{
- pop_message ();
- return Qnil;
-}
-
-/* Pop the top-most entry off Vmessage_stack. */
+/* Handler for unwind-protect calling pop_message. */
-static void
-pop_message (void)
+void
+pop_message_unwind (void)
{
+ /* Pop the top-most entry off Vmessage_stack. */
eassert (CONSP (Vmessage_stack));
Vmessage_stack = XCDR (Vmessage_stack);
}
&& UNCHANGED_MODIFIED < MODIFF);
}
-/* Nonzero if W doesn't reflect the actual state of current buffer due
- to its text or overlays change. FIXME: this may be called when
- XBUFFER (w->contents) != current_buffer, which looks suspicious. */
-
-static int
-window_outdated (struct window *w)
-{
- return (w->last_modified < MODIFF
- || w->last_overlay_modified < OVERLAY_MODIFF);
-}
-
/* Nonzero if W's buffer was changed but not saved or Transient Mark mode
is enabled and mark of W's buffer was changed since last W's update. */
&& (w->column_number_displayed != current_column ()));
}
+/* Nonzero if window start of W is frozen and may not be changed during
+ redisplay. */
+
+static bool
+window_frozen_p (struct window *w)
+{
+ if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
+ {
+ Lisp_Object window;
+
+ XSETWINDOW (window, w);
+ if (MINI_WINDOW_P (w))
+ return 0;
+ else if (EQ (window, selected_window))
+ return 0;
+ else if (MINI_WINDOW_P (XWINDOW (selected_window))
+ && EQ (window, Vminibuf_scroll_window))
+ /* This special window can't be frozen too. */
+ return 0;
+ else
+ return 1;
+ }
+ return 0;
+}
+
/***********************************************************************
Mode Lines and Frame Titles
***********************************************************************/
return vector;
}
-static Lisp_Object
+static void
unwind_format_mode_line (Lisp_Object vector)
{
Lisp_Object old_window = AREF (vector, 7);
}
Vmode_line_unwind_vector = vector;
- return Qnil;
}
{
f = XFRAME (frame);
if (!EQ (frame, tooltip_frame)
- && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
+ && (FRAME_ICONIFIED_P (f)
+ || FRAME_VISIBLE_P (f) == 1
+ /* Exclude TTY frames that are obscured because they
+ are not the top frame on their console. This is
+ because x_consider_frame_title actually switches
+ to the frame, which for TTY frames means it is
+ marked as garbaged, and will be completely
+ redrawn on the next redisplay cycle. This causes
+ TTY frames to be completely redrawn, when there
+ are more than one of them, even though nothing
+ should be changed on display. */
+ || (FRAME_VISIBLE_P (f) == 2 && FRAME_WINDOW_P (f))))
x_consider_frame_title (frame);
}
}
return hooks_run;
}
-
-\f
-/***********************************************************************
- Output Cursor
- ***********************************************************************/
-
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* EXPORT:
- Nominal cursor position -- where to draw output.
- HPOS and VPOS are window relative glyph matrix coordinates.
- X and Y are window relative pixel coordinates. */
-
-struct cursor_pos output_cursor;
-
-
-/* EXPORT:
- Set the global variable output_cursor to CURSOR. All cursor
- positions are relative to updated_window. */
-
-void
-set_output_cursor (struct cursor_pos *cursor)
-{
- output_cursor.hpos = cursor->hpos;
- output_cursor.vpos = cursor->vpos;
- output_cursor.x = cursor->x;
- output_cursor.y = cursor->y;
-}
-
-
-/* EXPORT for RIF:
- Set a nominal cursor position.
-
- HPOS and VPOS are column/row positions in a window glyph matrix. X
- and Y are window text area relative pixel positions.
-
- If this is done during an update, updated_window will contain the
- window that is being updated and the position is the future output
- cursor position for that window. If updated_window is null, use
- selected_window and display the cursor at the given position. */
-
-void
-x_cursor_to (int vpos, int hpos, int y, int x)
-{
- struct window *w;
-
- /* If updated_window is not set, work on selected_window. */
- if (updated_window)
- w = updated_window;
- else
- w = XWINDOW (selected_window);
-
- /* Set the output cursor. */
- output_cursor.hpos = hpos;
- output_cursor.vpos = vpos;
- output_cursor.x = x;
- output_cursor.y = y;
-
- /* If not called as part of an update, really display the cursor.
- This will also set the cursor position of W. */
- if (updated_window == NULL)
- {
- block_input ();
- display_and_set_cursor (w, 1, hpos, vpos, x, y);
- if (FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
- FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (SELECTED_FRAME ());
- unblock_input ();
- }
-}
-
-#endif /* HAVE_WINDOW_SYSTEM */
-
-\f
/***********************************************************************
Tool-bars
***********************************************************************/
/* Where the mouse was last time we reported a mouse event. */
-FRAME_PTR last_mouse_frame;
+struct frame *last_mouse_frame;
/* Tool-bar item index of the item on which a mouse button was pressed
or -1. */
do_switch_frame.
FIXME: Maybe do_switch_frame should be trimmed down similarly
when `norecord' is set. */
-static Lisp_Object
+static void
fast_set_selected_frame (Lisp_Object frame)
{
if (!EQ (selected_frame, frame))
selected_frame = frame;
selected_window = XFRAME (frame)->selected_window;
}
- return Qnil;
}
/* Update the tool-bar item list for frame F. This has to be done
XSETFRAME (frame, f);
Fmodify_frame_parameters (frame,
- Fcons (Fcons (Qtool_bar_lines,
- make_number (nlines)),
- Qnil));
+ list1 (Fcons (Qtool_bar_lines,
+ make_number (nlines))));
if (WINDOW_TOTAL_LINES (w) != old_height)
{
clear_glyph_matrix (w->desired_matrix);
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
return 1;
}
}
{
XSETFRAME (frame, f);
Fmodify_frame_parameters (frame,
- Fcons (Fcons (Qtool_bar_lines,
- make_number (nlines)),
- Qnil));
+ list1 (Fcons (Qtool_bar_lines,
+ make_number (nlines))));
if (WINDOW_TOTAL_LINES (w) != old_height)
{
clear_glyph_matrix (w->desired_matrix);
f->n_tool_bar_rows = nrows;
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
return 1;
}
}
hlinfo->mouse_face_beg_col = hpos;
hlinfo->mouse_face_beg_row = vpos;
hlinfo->mouse_face_beg_x = x;
- hlinfo->mouse_face_beg_y = row->y;
hlinfo->mouse_face_past_end = 0;
hlinfo->mouse_face_end_col = hpos + 1;
hlinfo->mouse_face_end_row = vpos;
hlinfo->mouse_face_end_x = x + glyph->pixel_width;
- hlinfo->mouse_face_end_y = row->y;
hlinfo->mouse_face_window = window;
hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
static void
debug_method_add (struct window *w, char const *fmt, ...)
{
+ void *ptr = w;
char *method = w->desired_matrix->method;
int len = strlen (method);
int size = sizeof w->desired_matrix->method;
if (trace_redisplay_p)
fprintf (stderr, "%p (%s): %s\n",
- w,
+ ptr,
((BUFFERP (w->contents)
&& STRINGP (BVAR (XBUFFER (w->contents), name)))
? SSDATA (BVAR (XBUFFER (w->contents), name))
if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
&& find_composition (prev_pt, -1, &start, &end, &prop, buffer)
- && COMPOSITION_VALID_P (start, end, prop)
+ && composition_valid_p (start, end, prop)
&& start < prev_pt && end > prev_pt)
/* The last point was within the composition. Return 1 iff
point moved out of the composition. */
/* Check a composition at the current point. */
return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
&& find_composition (pt, -1, &start, &end, &prop, buffer)
- && COMPOSITION_VALID_P (start, end, prop)
+ && composition_valid_p (start, end, prop)
&& start < pt && end > pt);
}
-
-/* Reconsider the setting of B->clip_changed which is displayed
- in window W. */
+/* Reconsider the clip changes of buffer which is displayed in W. */
static void
-reconsider_clip_changes (struct window *w, struct buffer *b)
+reconsider_clip_changes (struct window *w)
{
+ struct buffer *b = XBUFFER (w->contents);
+
if (b->clip_changed
&& w->window_end_valid
&& w->current_matrix->buffer == b
we set b->clip_changed to 1 to force updating the screen. If
b->clip_changed has already been set to 1, we can skip this
check. */
- if (!b->clip_changed && BUFFERP (w->contents) && w->window_end_valid)
+ if (!b->clip_changed && w->window_end_valid)
{
- ptrdiff_t pt;
+ ptrdiff_t pt = (w == XWINDOW (selected_window)
+ ? PT : marker_position (w->pointm));
- if (w == XWINDOW (selected_window))
- pt = PT;
- else
- pt = marker_position (w->pointm);
-
- if ((w->current_matrix->buffer != XBUFFER (w->contents)
- || pt != w->last_point)
+ if ((w->current_matrix->buffer != b || pt != w->last_point)
&& check_point_in_composition (w->current_matrix->buffer,
- w->last_point,
- XBUFFER (w->contents), pt))
+ w->last_point, b, pt))
b->clip_changed = 1;
}
}
-\f
#define STOP_POLLING \
do { if (! polling_stopped_here) stop_polling (); \
struct window *sw;
struct frame *fr;
int pending;
- int must_finish = 0;
+ bool must_finish = 0, match_p;
struct text_pos tlbufpos, tlendpos;
int number_of_visible_frames;
- ptrdiff_t count, count1;
+ ptrdiff_t count;
struct frame *sf;
int polling_stopped_here = 0;
Lisp_Object tail, frame;
/* Record a function that clears redisplaying_p
when we leave this function. */
count = SPECPDL_INDEX ();
- record_unwind_protect (unwind_redisplay, selected_frame);
+ record_unwind_protect_void (unwind_redisplay);
redisplaying_p = 1;
specbind (Qinhibit_free_realized_faces, Qnil);
sw = w;
pending = 0;
- reconsider_clip_changes (w, current_buffer);
last_escape_glyph_frame = NULL;
last_escape_glyph_face_id = (1 << FACE_ID_BITS);
last_glyphless_glyph_frame = NULL;
last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
- /* If new fonts have been loaded that make a glyph matrix adjustment
- necessary, do it. */
- if (fonts_changed_p)
- {
- adjust_glyphs (NULL);
- ++windows_or_buffers_changed;
- fonts_changed_p = 0;
- }
-
/* If face_change_count is non-zero, init_iterator will free all
realized faces, which includes the faces referenced from current
matrices. So, we can't reuse current matrices in this case. */
struct frame *f = XFRAME (frame);
if (FRAME_VISIBLE_P (f))
- ++number_of_visible_frames;
+ {
+ ++number_of_visible_frames;
+ /* Adjust matrices for visible frames only. */
+ if (f->fonts_changed)
+ {
+ adjust_frame_glyphs (f);
+ f->fonts_changed = 0;
+ }
+ /* If cursor type has been changed on the frame
+ other than selected, consider all frames. */
+ if (f != sf && f->cursor_type_changed)
+ update_mode_lines++;
+ }
clear_desired_matrices (f);
}
/* do_pending_window_change could change the selected_window due to
frame resizing which makes the selected window too small. */
if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
- {
- sw = w;
- reconsider_clip_changes (w, current_buffer);
- }
+ sw = w;
/* Clear frames marked as garbaged. */
clear_garbaged_frames ();
if (windows_or_buffers_changed)
update_mode_lines++;
- /* Detect case that we need to write or remove a star in the mode line. */
- if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
+ reconsider_clip_changes (w);
+
+ /* In most cases selected window displays current buffer. */
+ match_p = XBUFFER (w->contents) == current_buffer;
+ if (match_p)
{
- w->update_mode_line = 1;
- if (buffer_shared_and_changed ())
- update_mode_lines++;
- }
+ ptrdiff_t count1;
- /* Avoid invocation of point motion hooks by `current_column' below. */
- count1 = SPECPDL_INDEX ();
- specbind (Qinhibit_point_motion_hooks, Qt);
+ /* Detect case that we need to write or remove a star in the mode line. */
+ if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
+ {
+ w->update_mode_line = 1;
+ if (buffer_shared_and_changed ())
+ update_mode_lines++;
+ }
- if (mode_line_update_needed (w))
- w->update_mode_line = 1;
+ /* Avoid invocation of point motion hooks by `current_column' below. */
+ count1 = SPECPDL_INDEX ();
+ specbind (Qinhibit_point_motion_hooks, Qt);
- unbind_to (count1, Qnil);
+ if (mode_line_update_needed (w))
+ w->update_mode_line = 1;
+
+ unbind_to (count1, Qnil);
+ }
consider_all_windows_p = (update_mode_lines
- || buffer_shared_and_changed ()
- || cursor_type_changed);
+ || buffer_shared_and_changed ());
/* If specs for an arrow have changed, do thorough redisplay
to ensure we remove any arrow that should no longer exist. */
if (!display_last_displayed_message_p)
message_cleared_p = 0;
- if (fonts_changed_p)
- goto retry;
- else if (window_height_changed_p)
+ if (window_height_changed_p)
{
consider_all_windows_p = 1;
++update_mode_lines;
&& !current_buffer->prevent_redisplay_optimizations_p
&& FRAME_VISIBLE_P (XFRAME (w->frame))
&& !FRAME_OBSCURED_P (XFRAME (w->frame))
+ && !XFRAME (w->frame)->cursor_type_changed
/* Make sure recorded data applies to current buffer, etc. */
&& this_line_buffer == current_buffer
- && current_buffer == XBUFFER (w->contents)
+ && match_p
&& !w->force_start
&& !w->optional_new_start
/* Point must be on the line that we have info recorded about. */
adjusted. */
if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
{
- if (XFASTINT (w->window_end_vpos) < this_line_vpos)
- wset_window_end_vpos (w, make_number (this_line_vpos));
+ if (w->window_end_vpos < this_line_vpos)
+ w->window_end_vpos = this_line_vpos;
}
- else if (XFASTINT (w->window_end_vpos) == this_line_vpos
+ else if (w->window_end_vpos == this_line_vpos
&& this_line_vpos > 0)
- wset_window_end_vpos (w, make_number (this_line_vpos - 1));
+ w->window_end_vpos = this_line_vpos - 1;
w->window_end_valid = 0;
/* Update hint: No need to try to scroll in update_window. */
&& !EQ (FRAME_TTY (f)->top_frame, frame))
continue;
+ retry_frame:
+
if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
/* Mark all the scroll bars to be removed; we'll redeem
if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
- /* If fonts changed, display again. */
- /* ??? rms: I suspect it is a mistake to jump all the way
- back to retry here. It should just retry this frame. */
- if (fonts_changed_p)
- goto retry;
-
if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
{
+ /* If fonts changed on visible frame, display again. */
+ if (f->fonts_changed)
+ {
+ adjust_frame_glyphs (f);
+ f->fonts_changed = 0;
+ goto retry_frame;
+ }
+
/* See if we have to hscroll. */
if (!f->already_hscrolled_p)
{
f->already_hscrolled_p = 1;
if (hscroll_windows (f->root_window))
- goto retry;
+ goto retry_frame;
}
/* Prevent various kinds of signals during display
/* Update the display. */
set_window_update_flags (XWINDOW (f->root_window), 1);
pending |= update_frame (f, 0, 0);
+ f->cursor_type_changed = 0;
f->updated_p = 1;
}
}
update:
/* If fonts changed, display again. */
- if (fonts_changed_p)
+ if (sf->fonts_changed)
goto retry;
/* Prevent various kinds of signals during display update.
XWINDOW (selected_window)->must_be_updated_p = 1;
pending = update_frame (sf, 0, 0);
+ sf->cursor_type_changed = 0;
}
/* We may have called echo_area_display at the top of this
{
XWINDOW (mini_window)->must_be_updated_p = 1;
pending |= update_frame (mini_frame, 0, 0);
+ mini_frame->cursor_type_changed = 0;
if (!pending && hscroll_windows (mini_window))
goto retry;
}
update_mode_lines = 0;
windows_or_buffers_changed = 0;
- cursor_type_changed = 0;
}
/* Start SIGIO interrupts coming again. Having them off during the
}
-/* Function registered with record_unwind_protect in redisplay_internal.
- Clear redisplaying_p. Also select the previously selected frame. */
+/* Function registered with record_unwind_protect in redisplay_internal. */
-static Lisp_Object
-unwind_redisplay (Lisp_Object old_frame)
+static void
+unwind_redisplay (void)
{
redisplaying_p = 0;
- return Qnil;
}
w->current_matrix->begv = BUF_BEGV (b);
w->current_matrix->zv = BUF_ZV (b);
- w->last_cursor = w->cursor;
+ w->last_cursor_vpos = w->cursor.vpos;
w->last_cursor_off_p = w->cursor_off_p;
if (w == XWINDOW (selected_window))
struct window *w = XWINDOW (window);
SET_MARKER_FROM_TEXT_POS (w->start, startp);
- if (current_buffer != XBUFFER (w->contents))
- emacs_abort ();
+ eassert (current_buffer == XBUFFER (w->contents));
if (!NILP (Vwindow_scroll_functions))
{
Lisp_Object aggressive;
/* We will never try scrolling more than this number of lines. */
int scroll_limit = SCROLL_LIMIT;
+ int frame_line_height = default_line_pixel_height (w);
+ int window_total_lines
+ = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
#ifdef GLYPH_DEBUG
debug_method_add (w, "try_scrolling");
/* Compute scroll margin height in pixels. We scroll when point is
within this distance from the top or bottom of the window. */
if (scroll_margin > 0)
- this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
- * FRAME_LINE_HEIGHT (f);
+ this_scroll_margin = min (scroll_margin, window_total_lines / 4)
+ * frame_line_height;
else
this_scroll_margin = 0;
if (arg_scroll_conservatively > scroll_limit)
{
arg_scroll_conservatively = scroll_limit + 1;
- scroll_max = scroll_limit * FRAME_LINE_HEIGHT (f);
+ scroll_max = scroll_limit * frame_line_height;
}
else if (scroll_step || arg_scroll_conservatively || temp_scroll_step)
/* Compute how much we should try to scroll maximally to bring
point into view. */
scroll_max = (max (scroll_step,
max (arg_scroll_conservatively, temp_scroll_step))
- * FRAME_LINE_HEIGHT (f));
+ * frame_line_height);
else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
|| NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
/* We're trying to scroll because of aggressive scrolling but no
scroll_step is set. Choose an arbitrary one. */
- scroll_max = 10 * FRAME_LINE_HEIGHT (f);
+ scroll_max = 10 * frame_line_height;
else
scroll_max = 0;
either that ypos or PT, whichever comes first. */
start_display (&it, w, startp);
scroll_margin_y = it.last_visible_y - this_scroll_margin
- - FRAME_LINE_HEIGHT (f) * extra_scroll_margin_lines;
+ - frame_line_height * extra_scroll_margin_lines;
move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
(MOVE_TO_POS | MOVE_TO_Y));
the user limited scrolling by a small number of lines, but
always finds PT if scroll_conservatively is set to a large
number, such as most-positive-fixnum. */
- int slack = max (scroll_max, 10 * FRAME_LINE_HEIGHT (f));
+ int slack = max (scroll_max, 10 * frame_line_height);
int y_to_move = it.last_visible_y + slack;
/* Compute the distance from the scroll margin to PT or to
move it down by scroll_step. */
if (arg_scroll_conservatively)
amount_to_scroll
- = min (max (dy, FRAME_LINE_HEIGHT (f)),
- FRAME_LINE_HEIGHT (f) * arg_scroll_conservatively);
+ = min (max (dy, frame_line_height),
+ frame_line_height * arg_scroll_conservatively);
else if (scroll_step || temp_scroll_step)
amount_to_scroll = scroll_max;
else
start_display (&it, w, pos);
y0 = it.current_y;
y_to_move = max (it.last_visible_y,
- max (scroll_max, 10 * FRAME_LINE_HEIGHT (f)));
+ max (scroll_max, 10 * frame_line_height));
move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
y_to_move, -1,
MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
start_display (&it, w, startp);
if (arg_scroll_conservatively)
- amount_to_scroll = max (dy, FRAME_LINE_HEIGHT (f) *
+ amount_to_scroll = max (dy, frame_line_height *
max (scroll_step, temp_scroll_step));
else if (scroll_step || temp_scroll_step)
amount_to_scroll = scroll_max;
{
min_distance = distance;
pos = it.current.pos;
- move_it_by_lines (&it, 1);
+ if (it.line_wrap == WORD_WRAP)
+ {
+ /* Under WORD_WRAP, move_it_by_lines is likely to
+ overshoot and stop not at the first, but the
+ second character from the left margin. So in
+ that case, we need a more tight control on the X
+ coordinate of the iterator than move_it_by_lines
+ promises in its contract. The method is to first
+ go to the last (rightmost) visible character of a
+ line, then move to the leftmost character on the
+ next line in a separate call. */
+ move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
+ MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+ move_it_to (&it, ZV, 0,
+ it.current_y + it.max_ascent + it.max_descent, -1,
+ MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+ }
+ else
+ move_it_by_lines (&it, 1);
}
/* Set the window start there. */
if-statement below. Now, this field is converted to
ptrdiff_t, thus zero means invalid position in a buffer. */
eassert (w->last_point > 0);
+ /* Likewise there was a check whether window_end_vpos is nil or larger
+ than the window. Now window_end_vpos is int and so never nil, but
+ let's leave eassert to check whether it fits in the window. */
+ eassert (w->window_end_vpos < w->current_matrix->nrows);
/* Handle case where text has not changed, only point, and it has
not moved off the frame. */
cases. */
&& !update_mode_lines
&& !windows_or_buffers_changed
- && !cursor_type_changed
+ && !f->cursor_type_changed
/* Can't use this case if highlighting a region. When a
region exists, cursor movement has to do more than just
set the cursor. */
since the handling of this_line_start_pos, etc., in redisplay
handles the same cases. */
&& !EQ (window, minibuf_window)
- /* When splitting windows or for new windows, it happens that
- redisplay is called with a nil window_end_vpos or one being
- larger than the window. This should really be fixed in
- window.c. I don't have this on my list, now, so we do
- approximately the same as the old redisplay code. --gerd. */
- && INTEGERP (w->window_end_vpos)
- && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
&& (FRAME_WINDOW_P (f)
|| !overlay_arrow_in_current_buffer_p ()))
{
int this_scroll_margin, top_scroll_margin;
struct glyph_row *row = NULL;
+ int frame_line_height = default_line_pixel_height (w);
+ int window_total_lines
+ = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
#ifdef GLYPH_DEBUG
debug_method_add (w, "cursor movement");
of the window. This is a pixel value. */
if (scroll_margin > 0)
{
- this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
- this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+ this_scroll_margin = min (scroll_margin, window_total_lines / 4);
+ this_scroll_margin *= frame_line_height;
}
else
this_scroll_margin = 0;
/* Start with the row the cursor was displayed during the last
not paused redisplay. Give up if that row is not valid. */
- if (w->last_cursor.vpos < 0
- || w->last_cursor.vpos >= w->current_matrix->nrows)
+ if (w->last_cursor_vpos < 0
+ || w->last_cursor_vpos >= w->current_matrix->nrows)
rc = CURSOR_MOVEMENT_MUST_SCROLL;
else
{
- row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
+ row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
if (row->mode_line_p)
++row;
if (!row->enabled_p)
start = marker_position (w->start) - BUF_BEGV (buf);
/* I don't think this is guaranteed to be right. For the
moment, we'll pretend it is. */
- end = BUF_Z (buf) - XFASTINT (w->window_end_pos) - BUF_BEGV (buf);
+ end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
if (end < start)
end = start;
/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
selected_window is redisplayed.
- We can return without actually redisplaying the window if
- fonts_changed_p. In that case, redisplay_internal will
- retry. */
+ We can return without actually redisplaying the window if fonts has been
+ changed on window's frame. In that case, redisplay_internal will retry. */
static void
redisplay_window (Lisp_Object window, int just_this_one_p)
int centering_position = -1;
int last_line_misfit = 0;
ptrdiff_t beg_unchanged, end_unchanged;
+ int frame_line_height;
SET_TEXT_POS (lpoint, PT, PT_BYTE);
opoint = lpoint;
eassert (XMARKER (w->pointm)->buffer == buffer);
restart:
- reconsider_clip_changes (w, buffer);
+ reconsider_clip_changes (w);
+ frame_line_height = default_line_pixel_height (w);
/* Has the mode line to be updated? */
update_mode_line = (w->update_mode_line
&& !current_buffer->clip_changed
&& !window_outdated (w));
- /* When windows_or_buffers_changed is non-zero, we can't rely on
- the window end being valid, so set it to nil there. */
+ /* When windows_or_buffers_changed is non-zero, we can't rely
+ on the window end being valid, so set it to zero there. */
if (windows_or_buffers_changed)
{
/* If window starts on a continuation line, maybe adjust the
compute_window_start_on_continuation_line (w);
w->window_end_valid = 0;
+ /* 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;
}
/* Some sanity checks. */
/* Handle case where place to start displaying has been specified,
unless the specified location is outside the accessible range. */
- if (w->force_start || w->frozen_window_start_p)
+ if (w->force_start || window_frozen_p (w))
{
/* We set this later on if we have to adjust point. */
int new_vpos = -1;
startp = run_window_scroll_functions (window, startp);
}
- w->last_modified = 0;
- w->last_overlay_modified = 0;
if (CHARPOS (startp) < BEGV)
SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
else if (CHARPOS (startp) > ZV)
goto need_larger_matrices;
}
- if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
+ if (w->cursor.vpos < 0 && !window_frozen_p (w))
{
/* If point does not appear, try to move point so it does
appear. The desired matrix has been built above, so we
/* Some people insist on not letting point enter the scroll
margin, even though this part handles windows that didn't
scroll at all. */
- int margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
- int pixel_margin = margin * FRAME_LINE_HEIGHT (f);
+ int window_total_lines
+ = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
+ int margin = min (scroll_margin, window_total_lines / 4);
+ int pixel_margin = margin * frame_line_height;
bool header_line = WINDOW_WANTS_HEADER_LINE_P (w);
/* Note: We add an extra FRAME_LINE_HEIGHT, because the loop
the Y coordinate of the _next_ row, see the definition of
MATRIX_ROW_BOTTOM_Y. */
if (w->cursor.vpos < margin + header_line)
- new_vpos
- = pixel_margin + (header_line
- ? CURRENT_HEADER_LINE_HEIGHT (w)
- : 0) + FRAME_LINE_HEIGHT (f);
+ {
+ w->cursor.vpos = -1;
+ clear_glyph_matrix (w->desired_matrix);
+ goto try_to_scroll;
+ }
else
{
int window_height = window_box_height (w);
if (header_line)
window_height += CURRENT_HEADER_LINE_HEIGHT (w);
if (w->cursor.y >= window_height - pixel_margin)
- new_vpos = window_height - pixel_margin;
+ {
+ w->cursor.vpos = -1;
+ clear_glyph_matrix (w->desired_matrix);
+ goto try_to_scroll;
+ }
}
}
debug_method_add (w, "try_window_id %d", tem);
#endif
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
if (tem > 0)
goto done;
IF_DEBUG (debug_method_add (w, "1"));
if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
/* -1 means we need to scroll.
- 0 means we need new matrices, but fonts_changed_p
+ 0 means we need new matrices, but fonts_changed
is set in that case, so we will detect it below. */
goto try_to_scroll;
}
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
if (w->cursor.vpos >= 0)
try_to_scroll:
- w->last_modified = 0;
- w->last_overlay_modified = 0;
-
/* Redisplay the mode line. Select the buffer properly for that. */
if (!update_mode_line)
{
it.current_y = it.last_visible_y;
if (centering_position < 0)
{
+ int window_total_lines
+ = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
int margin =
scroll_margin > 0
- ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
+ ? min (scroll_margin, window_total_lines / 4)
: 0;
ptrdiff_t margin_pos = CHARPOS (startp);
Lisp_Object aggressive;
SAVE_IT (it1, it, it1data);
start_display (&it1, w, startp);
- move_it_vertically (&it1, margin * FRAME_LINE_HEIGHT (f));
+ move_it_vertically (&it1, margin * frame_line_height);
margin_pos = IT_CHARPOS (it1);
RESTORE_IT (&it, &it, it1data);
}
if (pt_offset)
centering_position -= pt_offset;
centering_position -=
- FRAME_LINE_HEIGHT (f) * (1 + margin + (last_line_misfit != 0))
+ frame_line_height * (1 + margin + (last_line_misfit != 0))
+ WINDOW_HEADER_LINE_HEIGHT (w);
/* Don't let point enter the scroll margin near top of
the window. */
- if (centering_position < margin * FRAME_LINE_HEIGHT (f))
- centering_position = margin * FRAME_LINE_HEIGHT (f);
+ if (centering_position < margin * frame_line_height)
+ centering_position = margin * frame_line_height;
}
else
- centering_position = margin * FRAME_LINE_HEIGHT (f) + pt_offset;
+ centering_position = margin * frame_line_height + pt_offset;
}
else
/* Set the window start half the height of the window backward
/* Redisplay the window. */
if (!current_matrix_up_to_date_p
|| windows_or_buffers_changed
- || cursor_type_changed
+ || f->cursor_type_changed
/* Don't use try_window_reusing_current_matrix in this case
because it can have changed the buffer. */
|| !NILP (Vwindow_scroll_functions)
/* If new fonts have been loaded (due to fontsets), give up. We
have to start a new redisplay since we need to re-adjust glyph
matrices. */
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
/* If cursor did not appear assume that the middle of the window is
line.) */
if (w->cursor.vpos < 0)
{
- if (w->window_end_valid && PT >= Z - XFASTINT (w->window_end_pos))
+ if (w->window_end_valid && PT >= Z - w->window_end_pos)
{
clear_glyph_matrix (w->desired_matrix);
move_it_by_lines (&it, 1);
make that row fully visible and out of the margin. */
if (scroll_conservatively > SCROLL_LIMIT)
{
+ int window_total_lines
+ = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) * frame_line_height;
int margin =
scroll_margin > 0
- ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
+ ? min (scroll_margin, window_total_lines / 4)
: 0;
- int move_down = w->cursor.vpos >= WINDOW_TOTAL_LINES (w) / 2;
+ int move_down = w->cursor.vpos >= window_total_lines / 2;
move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
clear_glyph_matrix (w->desired_matrix);
if (WINDOW_WANTS_MODELINE_P (w)
&& CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
{
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
+ w->mode_line_height = -1;
MATRIX_MODE_LINE_ROW (w->current_matrix)->height
= DESIRED_MODE_LINE_HEIGHT (w);
}
if (WINDOW_WANTS_HEADER_LINE_P (w)
&& CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
{
- fonts_changed_p = 1;
+ f->fonts_changed = 1;
+ w->header_line_height = -1;
MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
= DESIRED_HEADER_LINE_HEIGHT (w);
}
- if (fonts_changed_p)
+ if (f->fonts_changed)
goto need_larger_matrices;
}
}
#endif /* HAVE_WINDOW_SYSTEM */
- /* We go to this label, with fonts_changed_p set,
- if it is necessary to try again using larger glyph matrices.
+ /* We go to this label, with fonts_changed set, if it is
+ necessary to try again using larger glyph matrices.
We have to redeem the scroll bar even in this case,
because the loop in redisplay_internal expects that. */
need_larger_matrices:
struct it it;
struct glyph_row *last_text_row = NULL;
struct frame *f = XFRAME (w->frame);
+ int frame_line_height = default_line_pixel_height (w);
/* Make POS the new window start. */
set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
{
if (display_line (&it))
last_text_row = it.glyph_row - 1;
- if (fonts_changed_p && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
+ if (f->fonts_changed && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
return 0;
}
&& !MINI_WINDOW_P (w))
{
int this_scroll_margin;
+ int window_total_lines
+ = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
if (scroll_margin > 0)
{
- this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
- this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+ this_scroll_margin = min (scroll_margin, window_total_lines / 4);
+ this_scroll_margin *= frame_line_height;
}
else
this_scroll_margin = 0;
}
/* If bottom moved off end of frame, change mode line percentage. */
- if (XFASTINT (w->window_end_pos) <= 0
- && Z != IT_CHARPOS (it))
+ if (w->window_end_pos <= 0 && Z != IT_CHARPOS (it))
w->update_mode_line = 1;
/* Set window_end_pos to the offset of the last character displayed
if (last_text_row)
{
eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
- w->window_end_bytepos
- = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
- wset_window_end_pos
- (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
- wset_window_end_vpos
- (w, make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix)));
+ adjust_window_ends (w, last_text_row, 0);
eassert
(MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
- XFASTINT (w->window_end_vpos))));
+ w->window_end_vpos)));
}
else
{
w->window_end_bytepos = Z_BYTE - ZV_BYTE;
- wset_window_end_pos (w, make_number (Z - ZV));
- wset_window_end_vpos (w, make_number (0));
+ w->window_end_pos = Z - ZV;
+ w->window_end_vpos = 0;
}
/* But that is not valid info until redisplay finishes. */
/* Don't try to reuse the display if windows have been split
or such. */
|| windows_or_buffers_changed
- || cursor_type_changed)
+ || f->cursor_type_changed)
return 0;
/* Can't do this if region may have changed. */
w->cursor.vpos = -1;
last_text_row = last_reused_text_row = NULL;
- while (it.current_y < it.last_visible_y
- && !fonts_changed_p)
+ while (it.current_y < it.last_visible_y && !f->fonts_changed)
{
/* If we have reached into the characters in the START row,
that means the line boundaries have changed. So we
The value of last_text_row is the last displayed line
containing text. */
if (last_reused_text_row)
- {
- w->window_end_bytepos
- = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
- wset_window_end_pos
- (w, make_number (Z
- - MATRIX_ROW_END_CHARPOS (last_reused_text_row)));
- wset_window_end_vpos
- (w, make_number (MATRIX_ROW_VPOS (last_reused_text_row,
- w->current_matrix)));
- }
+ adjust_window_ends (w, last_reused_text_row, 1);
else if (last_text_row)
- {
- w->window_end_bytepos
- = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
- wset_window_end_pos
- (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
- wset_window_end_vpos
- (w, make_number (MATRIX_ROW_VPOS (last_text_row,
- w->desired_matrix)));
- }
+ adjust_window_ends (w, last_text_row, 0);
else
{
/* This window must be completely empty. */
w->window_end_bytepos = Z_BYTE - ZV_BYTE;
- wset_window_end_pos (w, make_number (Z - ZV));
- wset_window_end_vpos (w, make_number (0));
+ w->window_end_pos = Z - ZV;
+ w->window_end_vpos = 0;
}
w->window_end_valid = 0;
if (pt_row == NULL)
w->cursor.vpos = -1;
last_text_row = NULL;
- while (it.current_y < it.last_visible_y && !fonts_changed_p)
+ while (it.current_y < it.last_visible_y && !f->fonts_changed)
if (display_line (&it))
last_text_row = it.glyph_row - 1;
the window end is in reused rows which in turn means that
only its vpos can have changed. */
if (last_text_row)
- {
- w->window_end_bytepos
- = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
- wset_window_end_pos
- (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
- wset_window_end_vpos
- (w, make_number (MATRIX_ROW_VPOS (last_text_row,
- w->desired_matrix)));
- }
+ adjust_window_ends (w, last_text_row, 0);
else
- {
- wset_window_end_vpos
- (w, make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled));
- }
+ w->window_end_vpos -= nrows_scrolled;
w->window_end_valid = 0;
w->desired_matrix->no_scrolling_p = 1;
/* A value of window_end_pos >= END_UNCHANGED means that the window
end is in the range of changed text. If so, there is no
unchanged row at the end of W's current matrix. */
- if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
+ if (w->window_end_pos >= END_UNCHANGED)
return NULL;
/* Set row to the last row in W's current matrix displaying text. */
- row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+ row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
/* If matrix is entirely empty, no unchanged row exists. */
if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
buffer positions in the current matrix to current buffer
positions for characters not in changed text. */
ptrdiff_t Z_old =
- MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
+ MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
ptrdiff_t Z_BYTE_old =
MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
GIVE_UP (1);
/* This flag is used to prevent redisplay optimizations. */
- if (windows_or_buffers_changed || cursor_type_changed)
+ if (windows_or_buffers_changed || f->cursor_type_changed)
GIVE_UP (2);
/* Verify that narrowing has not changed.
This case happens with stealth-fontification. Note that although
the display is unchanged, glyph positions in the matrix have to
be adjusted, of course. */
- row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+ row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
&& ((last_changed_charpos < CHARPOS (start)
&& CHARPOS (start) == BEGV)
/* Compute how many chars/bytes have been added to or removed
from the buffer. */
- Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
+ Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
Z_delta = Z - Z_old;
Z_delta_bytes = Z_BYTE - Z_BYTE_old;
{
/* We have to compute the window end anew since text
could have been added/removed after it. */
- wset_window_end_pos
- (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
- w->window_end_bytepos
- = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
+ w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
+ w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
/* Set the cursor. */
row = row_containing_pos (w, PT, r0, NULL, 0);
/* Give up if the window ends in strings. Overlay strings
at the end are difficult to handle, so don't try. */
- row = MATRIX_ROW (current_matrix, XFASTINT (w->window_end_vpos));
+ row = MATRIX_ROW (current_matrix, w->window_end_vpos);
if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
GIVE_UP (20);
last_text_row = NULL;
overlay_arrow_seen = 0;
while (it.current_y < it.last_visible_y
- && !fonts_changed_p
+ && !f->fonts_changed
&& (first_unchanged_at_end_row == NULL
|| IT_CHARPOS (it) < stop_pos))
{
last_text_row = it.glyph_row - 1;
}
- if (fonts_changed_p)
+ if (f->fonts_changed)
return -1;
/* Don't let the cursor end in the scroll margins. */
{
int this_scroll_margin, cursor_height;
+ int frame_line_height = default_line_pixel_height (w);
+ int window_total_lines
+ = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (it.f) / frame_line_height;
this_scroll_margin =
- max (0, min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4));
- this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
+ max (0, min (scroll_margin, window_total_lines / 4));
+ this_scroll_margin *= frame_line_height;
cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
if ((w->cursor.y < this_scroll_margin
/* Set last_row to the glyph row in the current matrix where the
window end line is found. It has been moved up or down in
the matrix by dvpos. */
- int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
+ int last_vpos = w->window_end_vpos + dvpos;
struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
/* If last_row is the window end line, it should display text. */
/* Display the rest of the lines at the window end. */
it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
- while (it.current_y < it.last_visible_y
- && !fonts_changed_p)
+ while (it.current_y < it.last_visible_y && !f->fonts_changed)
{
/* Is it always sure that the display agrees with lines in
the current matrix? I don't think so, so we mark rows
}
/* Update window_end_pos and window_end_vpos. */
- if (first_unchanged_at_end_row
- && !last_text_row_at_end)
+ if (first_unchanged_at_end_row && !last_text_row_at_end)
{
/* Window end line if one of the preserved rows from the current
matrix. Set row to the last row displaying text in current
row = find_last_row_displaying_text (w->current_matrix, &it,
first_unchanged_at_end_row);
eassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
-
- wset_window_end_pos (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
- w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
- wset_window_end_vpos
- (w, make_number (MATRIX_ROW_VPOS (row, w->current_matrix)));
+ adjust_window_ends (w, row, 1);
eassert (w->window_end_bytepos >= 0);
IF_DEBUG (debug_method_add (w, "A"));
}
else if (last_text_row_at_end)
{
- wset_window_end_pos
- (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end)));
- w->window_end_bytepos
- = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
- wset_window_end_vpos
- (w, make_number (MATRIX_ROW_VPOS (last_text_row_at_end,
- desired_matrix)));
+ adjust_window_ends (w, last_text_row_at_end, 0);
eassert (w->window_end_bytepos >= 0);
IF_DEBUG (debug_method_add (w, "B"));
}
/* We have displayed either to the end of the window or at the
end of the window, i.e. the last row with text is to be found
in the desired matrix. */
- wset_window_end_pos
- (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
- w->window_end_bytepos
- = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
- wset_window_end_vpos
- (w, make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix)));
+ adjust_window_ends (w, last_text_row, 0);
eassert (w->window_end_bytepos >= 0);
}
else if (first_unchanged_at_end_row == NULL
/* Displayed to end of window, but no line containing text was
displayed. Lines were deleted at the end of the window. */
int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
- int vpos = XFASTINT (w->window_end_vpos);
+ int vpos = w->window_end_vpos;
struct glyph_row *current_row = current_matrix->rows + vpos;
struct glyph_row *desired_row = desired_matrix->rows + vpos;
}
eassert (row != NULL);
- wset_window_end_vpos (w, make_number (vpos + 1));
- wset_window_end_pos (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
+ w->window_end_vpos = vpos + 1;
+ w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
eassert (w->window_end_bytepos >= 0);
IF_DEBUG (debug_method_add (w, "C"));
else
emacs_abort ();
- IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
- debug_end_vpos = XFASTINT (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;
>= it->w->desired_matrix->nrows)
{
it->w->nrows_scale_factor++;
- fonts_changed_p = 1;
+ it->f->fonts_changed = 1;
return 0;
}
(Lisp_Object direction)
{
struct window *w = XWINDOW (selected_window);
- struct buffer *b = NULL;
+ struct buffer *b = XBUFFER (w->contents);
struct glyph_row *row;
int dir;
Lisp_Object paragraph_dir;
else
dir = -1;
- if (BUFFERP (w->contents))
- b = XBUFFER (w->contents);
-
/* If current matrix is up-to-date, we can use the information
recorded in the glyphs, at least as long as the goal is on the
screen. */
&& b
&& !b->clip_changed
&& !b->prevent_redisplay_optimizations_p
- && w->last_modified >= BUF_MODIFF (b)
- && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)
+ && !window_outdated (w)
&& w->cursor.vpos >= 0
&& w->cursor.vpos < w->current_matrix->nrows
&& (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
w->cursor.vpos = -1;
return make_number (PT);
}
- else if (!INTEGERP (g->object) && g->object != gpt->object)
+ else if (!INTEGERP (g->object) && !EQ (g->object, gpt->object))
{
ptrdiff_t new_pos;
break;
}
/* If we ended up on a composed character inside
- bidi-reordered text (e.g., Hebrew text with diacriticals),
+ 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
{
struct text_pos pt;
- SET_TEXT_POS_FROM_MARKER (pt, w->pointm);
- if (CHARPOS (pt) < BEGV)
- TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
- else if (CHARPOS (pt) > (ZV - 1))
- TEMP_SET_PT_BOTH (ZV, ZV_BYTE);
- else
- TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
+ CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
+ TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
}
/* Display mode lines. */
if (NILP (face))
face = mode_line_string_face;
else
- face = Fcons (face, Fcons (mode_line_string_face, Qnil));
+ face = list2 (face, mode_line_string_face);
props = Fplist_put (props, Qface, face);
}
Fadd_text_properties (make_number (0), make_number (len),
if (NILP (face))
face = mode_line_string_face;
else
- face = Fcons (face, Fcons (mode_line_string_face, Qnil));
- props = Fcons (Qface, Fcons (face, Qnil));
+ face = list2 (face, mode_line_string_face);
+ props = list2 (Qface, face);
if (copy_string)
lisp_string = Fcopy_sequence (lisp_string);
}
mode_line_string_list = Qnil;
mode_line_string_face = face;
mode_line_string_face_prop
- = (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil)));
+ = NILP (face) ? Qnil : list2 (Qface, face);
}
push_kboard (FRAME_KBOARD (it.f));
ptrdiff_t pos = marker_position (w->start);
ptrdiff_t total = BUF_ZV (b) - BUF_BEGV (b);
- if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
+ if (w->window_end_pos <= BUF_Z (b) - BUF_ZV (b))
{
if (pos <= BUF_BEGV (b))
return "All";
case 'P':
{
ptrdiff_t toppos = marker_position (w->start);
- ptrdiff_t botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
+ ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
ptrdiff_t total = BUF_ZV (b) - BUF_BEGV (b);
if (botpos >= BUF_ZV (b))
&& hlinfo->mouse_face_beg_row >= 0
&& hlinfo->mouse_face_end_row >= 0)
{
- struct glyph_row *mouse_beg_row, *mouse_end_row;
+ ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
- mouse_beg_row = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
- mouse_end_row = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
-
- if (row >= mouse_beg_row && row <= mouse_end_row)
+ if (row_vpos >= hlinfo->mouse_face_beg_row
+ && row_vpos <= hlinfo->mouse_face_end_row)
{
check_mouse_face = 1;
- mouse_beg_col = (row == mouse_beg_row)
+ mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
? hlinfo->mouse_face_beg_col : 0;
- mouse_end_col = (row == mouse_end_row)
+ mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
? hlinfo->mouse_face_end_col
: row->used[TEXT_AREA];
}
#define IT_EXPAND_MATRIX_WIDTH(it, area) \
{ \
- if (!fonts_changed_p \
+ if (!it->f->fonts_changed \
&& (it->glyph_row->glyphs[area] \
< it->glyph_row->glyphs[area + 1])) \
{ \
it->w->ncols_scale_factor++; \
- fonts_changed_p = 1; \
+ it->f->fonts_changed = 1; \
} \
}
base_height = it->ascent + it->descent;
base_width = font->average_width;
- /* Get a face ID for the glyph by utilizing a cache (the same way as
- done for `escape-glyph' in get_next_display_element). */
- if (it->f == last_glyphless_glyph_frame
- && it->face_id == last_glyphless_glyph_face_id)
- {
- face_id = last_glyphless_glyph_merged_face_id;
- }
- else
- {
- /* Merge the `glyphless-char' face into the current face. */
- face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
- last_glyphless_glyph_frame = it->f;
- last_glyphless_glyph_face_id = it->face_id;
- last_glyphless_glyph_merged_face_id = face_id;
- }
+ face_id = merge_glyphless_glyph_face (it);
if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
{
/* EXPORT for RIF:
Output LEN glyphs starting at START at the nominal cursor position.
- Advance the nominal cursor over the text. The global variable
- updated_window contains the window being updated, updated_row is
- the glyph row being updated, and updated_area is the area of that
- row being updated. */
+ Advance the nominal cursor over the text. UPDATED_ROW is the glyph row
+ being updated, and UPDATED_AREA is the area of that row being updated. */
void
-x_write_glyphs (struct glyph *start, int len)
+x_write_glyphs (struct window *w, struct glyph_row *updated_row,
+ struct glyph *start, enum glyph_row_area updated_area, int len)
{
- int x, hpos, chpos = updated_window->phys_cursor.hpos;
+ int x, hpos, chpos = w->phys_cursor.hpos;
- eassert (updated_window && updated_row);
+ eassert (updated_row);
/* When the window is hscrolled, cursor hpos can legitimately be out
of bounds, but we draw the cursor at the corresponding window
margin in that case. */
/* Write glyphs. */
hpos = start - updated_row->glyphs[updated_area];
- x = draw_glyphs (updated_window, output_cursor.x,
+ x = draw_glyphs (w, w->output_cursor.x,
updated_row, updated_area,
hpos, hpos + len,
DRAW_NORMAL_TEXT, 0);
/* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
if (updated_area == TEXT_AREA
- && updated_window->phys_cursor_on_p
- && updated_window->phys_cursor.vpos == output_cursor.vpos
+ && w->phys_cursor_on_p
+ && w->phys_cursor.vpos == w->output_cursor.vpos
&& chpos >= hpos
&& chpos < hpos + len)
- updated_window->phys_cursor_on_p = 0;
+ w->phys_cursor_on_p = 0;
unblock_input ();
/* Advance the output cursor. */
- output_cursor.hpos += len;
- output_cursor.x = x;
+ w->output_cursor.hpos += len;
+ w->output_cursor.x = x;
}
Insert LEN glyphs from START at the nominal cursor position. */
void
-x_insert_glyphs (struct glyph *start, int len)
+x_insert_glyphs (struct window *w, struct glyph_row *updated_row,
+ struct glyph *start, enum glyph_row_area updated_area, int len)
{
struct frame *f;
- struct window *w;
int line_height, shift_by_width, shifted_region_width;
struct glyph_row *row;
struct glyph *glyph;
int frame_x, frame_y;
ptrdiff_t hpos;
- eassert (updated_window && updated_row);
+ eassert (updated_row);
block_input ();
- w = updated_window;
f = XFRAME (WINDOW_FRAME (w));
/* Get the height of the line we are in. */
/* Get the width of the region to shift right. */
shifted_region_width = (window_box_width (w, updated_area)
- - output_cursor.x
+ - w->output_cursor.x
- shift_by_width);
/* Shift right. */
- frame_x = window_box_left (w, updated_area) + output_cursor.x;
- frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
+ frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
+ frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
line_height, shift_by_width);
/* Write the glyphs. */
hpos = start - row->glyphs[updated_area];
- draw_glyphs (w, output_cursor.x, row, updated_area,
+ draw_glyphs (w, w->output_cursor.x, row, updated_area,
hpos, hpos + len,
DRAW_NORMAL_TEXT, 0);
/* Advance the output cursor. */
- output_cursor.hpos += len;
- output_cursor.x += shift_by_width;
+ w->output_cursor.hpos += len;
+ w->output_cursor.x += shift_by_width;
unblock_input ();
}
(inclusive) to pixel column TO_X (exclusive). The idea is that
everything from TO_X onward is already erased.
- TO_X is a pixel position relative to updated_area of
- updated_window. TO_X == -1 means clear to the end of this area. */
+ TO_X is a pixel position relative to UPDATED_AREA of currently
+ updated window W. TO_X == -1 means clear to the end of this area. */
void
-x_clear_end_of_line (int to_x)
+x_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
+ enum glyph_row_area updated_area, int to_x)
{
struct frame *f;
- struct window *w = updated_window;
int max_x, min_y, max_y;
int from_x, from_y, to_y;
- eassert (updated_window && updated_row);
+ eassert (updated_row);
f = XFRAME (w->frame);
if (updated_row->full_width_p)
else
to_x = min (to_x, max_x);
- to_y = min (max_y, output_cursor.y + updated_row->height);
+ to_y = min (max_y, w->output_cursor.y + updated_row->height);
/* Notice if the cursor will be cleared by this operation. */
if (!updated_row->full_width_p)
notice_overwritten_cursor (w, updated_area,
- output_cursor.x, -1,
+ w->output_cursor.x, -1,
updated_row->y,
MATRIX_ROW_BOTTOM_Y (updated_row));
- from_x = output_cursor.x;
+ from_x = w->output_cursor.x;
/* Translate to frame coordinates. */
if (updated_row->full_width_p)
}
min_y = WINDOW_HEADER_LINE_HEIGHT (w);
- from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
+ from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
/* Prevent inadvertently clearing to end of the X window. */
}
else
FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
+
+ /* Make sure the cursor gets redrawn. */
+ f->cursor_type_changed = 1;
}
where to put the cursor is specified by HPOS, VPOS, X and Y. */
void
-display_and_set_cursor (struct window *w, int on,
+display_and_set_cursor (struct window *w, bool on,
int hpos, int vpos, int x, int y)
{
struct frame *f = XFRAME (w->frame);
of ON. */
static void
-update_window_cursor (struct window *w, int on)
+update_window_cursor (struct window *w, bool on)
{
/* Don't update cursor in windows whose frame is in the process
of being deleted. */
in the window tree rooted at W. */
static void
-update_cursor_in_window_tree (struct window *w, int on_p)
+update_cursor_in_window_tree (struct window *w, bool on_p)
{
while (w)
{
Don't change the cursor's position. */
void
-x_update_cursor (struct frame *f, int on_p)
+x_update_cursor (struct frame *f, bool on_p)
{
update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
}
cleared = 1;
}
- hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
- hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
- hlinfo->mouse_face_window = Qnil;
- hlinfo->mouse_face_overlay = Qnil;
+ reset_mouse_highlight (hlinfo);
return cleared;
}
/* Find the rows corresponding to START_CHARPOS and END_CHARPOS. */
rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
if (r1 == NULL)
- r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+ r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
/* If the before-string or display-string contains newlines,
rows_from_pos_range skips to its last row. Move back. */
if (!NILP (before_string) || !NILP (disp_string))
}
if (r2 == NULL)
{
- r2 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+ r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
hlinfo->mouse_face_past_end = 1;
}
else if (!NILP (after_string))
/* If the after-string has newlines, advance to its last row. */
struct glyph_row *next;
struct glyph_row *last
- = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+ = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
for (next = r2 + 1;
next <= last
r1 = tem;
}
- hlinfo->mouse_face_beg_y = r1->y;
hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
- hlinfo->mouse_face_end_y = r2->y;
hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
/* For a bidi-reordered row, the positions of BEFORE_STRING,
{
hlinfo->mouse_face_beg_row
= MATRIX_ROW_VPOS (r, w->current_matrix);
- hlinfo->mouse_face_beg_y = r->y;
hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
hlinfo->mouse_face_beg_x = gx;
found = 1;
{
hlinfo->mouse_face_beg_row
= MATRIX_ROW_VPOS (r, w->current_matrix);
- hlinfo->mouse_face_beg_y = r->y;
hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
gx += g1->pixel_width;
/* The highlighted region ends on the previous row. */
r--;
- /* Set the end row and its vertical pixel coordinate. */
+ /* Set the end row. */
hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
- hlinfo->mouse_face_end_y = r->y;
/* Compute and set the end column and the end column's horizontal
pixel coordinate. */
hlinfo->mouse_face_beg_row = vpos;
hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
- hlinfo->mouse_face_beg_y = 0;
- hlinfo->mouse_face_end_y = 0;
hlinfo->mouse_face_past_end = 0;
hlinfo->mouse_face_window = window;
/* Are we in a window whose display is up to date?
And verify the buffer's text has not changed. */
b = XBUFFER (w->contents);
- if (part == ON_TEXT
- && w->window_end_valid
- && w->last_modified == BUF_MODIFF (b)
- && w->last_overlay_modified == BUF_OVERLAY_MODIFF (b))
+ if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
{
int hpos, vpos, dx, dy, area = LAST_AREA;
ptrdiff_t pos;
: Qnil;
Lisp_Object lim2 =
NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
- ? make_number (BUF_Z (XBUFFER (buffer))
- - XFASTINT (w->window_end_pos))
+ ? make_number (BUF_Z (XBUFFER (buffer)) - w->window_end_pos)
: Qnil;
if (NILP (overlay))
window = hlinfo->mouse_face_window;
if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
- {
- hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
- hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
- hlinfo->mouse_face_window = Qnil;
- }
+ reset_mouse_highlight (hlinfo);
}
{
int x0, x1, y0, y1;
- window_box_edges (w, -1, &x0, &y0, &x1, &y1);
+ window_box_edges (w, &x0, &y0, &x1, &y1);
y1 -= 1;
if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
{
int x0, x1, y0, y1;
- window_box_edges (w, -1, &x0, &y0, &x1, &y1);
+ window_box_edges (w, &x0, &y0, &x1, &y1);
y1 -= 1;
if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
/* When we're currently updating the window, display and current
matrix usually don't agree. Arrange for a thorough display
later. */
- if (w == updated_window)
+ if (w->must_be_updated_p)
{
SET_FRAME_GARBAGED (f);
return 0;
DEFSYM (Qarrow, "arrow");
DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
- list_of_error = Fcons (Fcons (intern_c_string ("error"),
- Fcons (intern_c_string ("void-variable"), Qnil)),
- Qnil);
+ list_of_error = list1 (list2 (intern_c_string ("error"),
+ intern_c_string ("void-variable")));
staticpro (&list_of_error);
DEFSYM (Qlast_arrow_position, "last-arrow-position");
The symbols on this list are examined during redisplay to determine
where to display overlay arrows. */);
Voverlay_arrow_variable_list
- = Fcons (intern_c_string ("overlay-arrow-position"), Qnil);
+ = list1 (intern_c_string ("overlay-arrow-position"));
DEFVAR_INT ("scroll-step", emacs_scroll_step,
doc: /* The number of lines to try scrolling a window by when point moves out.
doc: /* Seconds to wait before displaying an hourglass pointer when Emacs is busy. */);
Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
+#ifdef HAVE_WINDOW_SYSTEM
hourglass_atimer = NULL;
hourglass_shown_p = 0;
+#endif /* HAVE_WINDOW_SYSTEM */
DEFSYM (Qglyphless_char, "glyphless-char");
DEFSYM (Qhex_code, "hex-code");
DEFSYM (Qzero_width, "zero-width");
DEFSYM (Qglyphless_char_display, "glyphless-char-display");
- /* Intern this now in case it isn't already done.
- Setting this variable twice is harmless.
- But don't staticpro it here--that is done in alloc.c. */
- Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots");
Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_number (1));
DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
void
init_xdisp (void)
{
- current_header_line_height = current_mode_line_height = -1;
-
CHARPOS (this_line_start_pos) = 0;
if (!noninteractive)
help_echo_showing_p = 0;
}
+#ifdef HAVE_WINDOW_SYSTEM
+
/* Platform-independent portion of hourglass implementation. */
/* Cancel a currently active hourglass timer, and start a new one. */
void
start_hourglass (void)
{
-#if defined (HAVE_WINDOW_SYSTEM)
- EMACS_TIME delay;
+ struct timespec delay;
cancel_hourglass ();
if (INTEGERP (Vhourglass_delay)
&& XINT (Vhourglass_delay) > 0)
- delay = make_emacs_time (min (XINT (Vhourglass_delay),
+ delay = make_timespec (min (XINT (Vhourglass_delay),
TYPE_MAXIMUM (time_t)),
- 0);
+ 0);
else if (FLOATP (Vhourglass_delay)
&& XFLOAT_DATA (Vhourglass_delay) > 0)
- delay = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (Vhourglass_delay));
+ delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
else
- delay = make_emacs_time (DEFAULT_HOURGLASS_DELAY, 0);
+ delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
#ifdef HAVE_NTGUI
{
hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
show_hourglass, NULL);
-#endif
}
void
cancel_hourglass (void)
{
-#if defined (HAVE_WINDOW_SYSTEM)
if (hourglass_atimer)
{
cancel_atimer (hourglass_atimer);
if (hourglass_shown_p)
hide_hourglass ();
-#endif
}
+
+#endif /* HAVE_WINDOW_SYSTEM */