X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/9ef6111b7cab7e28e74c0763696a38b34285dc4f..77394d40d90fe4ba150444c0160654c608ef227d:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 6e39135081..d5def06593 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -299,21 +299,9 @@ along with GNU Emacs. If not, see . */ #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) @@ -378,8 +366,7 @@ static Lisp_Object Qline_height; && ((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 @@ -525,10 +512,6 @@ int update_mode_lines; 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. */ @@ -586,12 +569,6 @@ static int last_height; 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 @@ -763,6 +740,8 @@ Lisp_Object previous_help_echo_string; /* Platform-independent portion of hourglass implementation. */ +#ifdef HAVE_WINDOW_SYSTEM + /* Non-zero means an hourglass cursor is currently shown. */ int hourglass_shown_p; @@ -770,6 +749,8 @@ 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; @@ -779,14 +760,17 @@ static Lisp_Object Qglyphless_char_display; /* 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 - +#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); @@ -807,7 +791,6 @@ static void pint2str (char *, int, ptrdiff_t); 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); @@ -816,21 +799,20 @@ static void handle_stop (struct it *); 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); @@ -971,12 +953,12 @@ window_text_bottom_y (struct window *w) 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; @@ -987,22 +969,18 @@ window_box_width (struct window *w, int area) 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; } } @@ -1058,11 +1036,11 @@ window_box_height (struct window *w) } /* 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; @@ -1090,21 +1068,21 @@ window_box_left_offset (struct window *w, int area) /* 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; @@ -1120,25 +1098,25 @@ window_box_left (struct window *w, int area) /* 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); @@ -1154,27 +1132,27 @@ window_box (struct window *w, int area, int *box_x, int *box_y, } } +#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 */ - /*********************************************************************** Utilities ***********************************************************************/ @@ -1217,6 +1195,70 @@ line_bottom_y (struct it *it) return line_top_y + line_height; } +DEFUN ("line-pixel-height", Fline_pixel_height, + Sline_pixel_height, 0, 0, 0, + doc: /* Return height in pixels of text line in the selected window. + +Value is the height in pixels of the line at point. */) + (void) +{ + struct it it; + struct text_pos pt; + struct window *w = XWINDOW (selected_window); + + SET_TEXT_POS (pt, PT, PT_BYTE); + start_display (&it, w, pt); + it.vpos = it.current_y = 0; + last_height = 0; + 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 @@ -1297,12 +1339,12 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, /* 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)); @@ -1351,8 +1393,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, 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); @@ -1596,8 +1637,6 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *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)) @@ -1795,7 +1834,7 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id) 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) { @@ -2407,7 +2446,16 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) #endif /* HAVE_WINDOW_SYSTEM */ - +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 ***********************************************************************/ @@ -2543,8 +2591,7 @@ check_window_end (struct window *w) 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)); @@ -2650,6 +2697,7 @@ init_iterator (struct it *it, struct window *w, it->bidi_it.string.lstring = Qnil; it->bidi_it.string.s = NULL; it->bidi_it.string.bufpos = 0; + it->bidi_it.w = w; /* The window in which we iterate over current_buffer: */ XSETWINDOW (it->window, w); @@ -3124,6 +3172,7 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos) it->bidi_it.string.bufpos = it->overlay_strings_charpos; it->bidi_it.string.from_disp_str = it->string_from_display_prop_p; it->bidi_it.string.unibyte = !it->multibyte_p; + it->bidi_it.w = it->w; bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it), FRAME_WINDOW_P (it->f), &it->bidi_it); @@ -3490,11 +3539,11 @@ next_overlay_change (ptrdiff_t pos) ptrdiff_t compute_display_string_pos (struct text_pos *position, struct bidi_string_data *string, + struct window *w, int frame_window_p, int *disp_prop) { /* OBJECT = nil means current buffer. */ - Lisp_Object object = - (string && STRINGP (string->lstring)) ? string->lstring : Qnil; + Lisp_Object object, object1; Lisp_Object pos, spec, limpos; int string_p = (string && (STRINGP (string->lstring) || string->s)); ptrdiff_t eob = string_p ? string->schars : ZV; @@ -3505,6 +3554,16 @@ compute_display_string_pos (struct text_pos *position, struct text_pos tpos; int rv = 0; + if (string && STRINGP (string->lstring)) + object1 = object = string->lstring; + else if (w && !string_p) + { + XSETWINDOW (object, w); + object1 = Qnil; + } + else + object1 = object = Qnil; + *disp_prop = 1; if (charpos >= eob @@ -3543,7 +3602,7 @@ compute_display_string_pos (struct text_pos *position, that will replace the underlying text when displayed. */ limpos = make_number (lim); do { - pos = Fnext_single_char_property_change (pos, Qdisplay, object, limpos); + pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos); CHARPOS (tpos) = XFASTINT (pos); if (CHARPOS (tpos) >= lim) { @@ -3838,10 +3897,14 @@ handle_face_prop (struct it *it) /* 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); } @@ -5031,6 +5094,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, it->bidi_it.string.bufpos = bufpos; it->bidi_it.string.from_disp_str = 1; it->bidi_it.string.unibyte = !it->multibyte_p; + it->bidi_it.w = it->w; bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it); } } @@ -5274,7 +5338,7 @@ handle_composition_prop (struct it *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) @@ -5409,6 +5473,7 @@ next_overlay_string (struct it *it) it->bidi_it.string.bufpos = it->overlay_strings_charpos; it->bidi_it.string.from_disp_str = it->string_from_display_prop_p; it->bidi_it.string.unibyte = !it->multibyte_p; + it->bidi_it.w = it->w; bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it); } } @@ -5436,8 +5501,8 @@ next_overlay_string (struct it *it) 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) @@ -5712,6 +5777,7 @@ get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, int compute_stop_p) it->bidi_it.string.bufpos = pos; it->bidi_it.string.from_disp_str = it->string_from_display_prop_p; it->bidi_it.string.unibyte = !it->multibyte_p; + it->bidi_it.w = it->w; bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it); } return 1; @@ -6344,6 +6410,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p) it->bidi_it.string.lstring = Qnil; it->bidi_it.string.bufpos = 0; it->bidi_it.string.unibyte = 0; + it->bidi_it.w = it->w; } if (set_stop_p) @@ -6421,6 +6488,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, it->bidi_it.string.bufpos = 0; it->bidi_it.string.from_disp_str = 0; it->bidi_it.string.unibyte = !it->multibyte_p; + it->bidi_it.w = it->w; bidi_init_it (charpos, IT_STRING_BYTEPOS (*it), FRAME_WINDOW_P (it->f), &it->bidi_it); } @@ -6452,6 +6520,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, it->bidi_it.string.bufpos = 0; it->bidi_it.string.from_disp_str = 0; it->bidi_it.string.unibyte = !it->multibyte_p; + it->bidi_it.w = it->w; bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f), &it->bidi_it); } @@ -6597,17 +6666,59 @@ lookup_glyphless_char_display (int c, struct it *it) 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) @@ -6755,24 +6866,10 @@ 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); @@ -6804,27 +6901,10 @@ get_next_display_element (struct it *it) 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: */ @@ -6966,7 +7046,9 @@ get_next_display_element (struct it *it) } } } - 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 @@ -7381,6 +7463,8 @@ static int 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); @@ -7393,6 +7477,8 @@ next_element_from_display_vector (struct it *it) 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); @@ -7408,6 +7494,41 @@ next_element_from_display_vector (struct it *it) 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. */ @@ -8503,7 +8624,9 @@ move_it_in_display_line_to (struct it *it, 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; @@ -8980,7 +9103,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos && 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; @@ -9021,7 +9144,7 @@ move_it_vertically_backward (struct it *it, int dy) 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 @@ -9711,7 +9834,7 @@ message3_nolog (Lisp_Object m) void message1 (const char *m) { - message3 (m ? make_unibyte_string (m, strlen (m)) : Qnil); + message3 (m ? build_unibyte_string (m) : Qnil); } @@ -9720,7 +9843,7 @@ message1 (const char *m) 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 @@ -9830,7 +9953,7 @@ vmessage (const char *m, va_list ap) 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)); } @@ -10066,7 +10189,7 @@ with_echo_area_buffer_unwind_data (struct window *w) /* 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))); @@ -10091,7 +10214,6 @@ unwind_with_echo_area_buffer (Lisp_Object vector) } Vwith_echo_area_save_vector = vector; - return Qnil; } @@ -10383,7 +10505,8 @@ resize_mini_window (struct window *w, int exact_p) 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; } @@ -10391,7 +10514,8 @@ resize_mini_window (struct window *w, int exact_p) && (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; } @@ -10402,19 +10526,21 @@ resize_mini_window (struct window *w, int exact_p) 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)); } @@ -10490,20 +10616,12 @@ restore_message (void) } -/* Handler for record_unwind_protect calling pop_message. */ +/* Handler for 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. */ - -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); } @@ -10780,17 +10898,6 @@ buffer_shared_and_changed (void) && 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. */ @@ -10816,6 +10923,31 @@ mode_line_update_needed (struct window *w) && (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 ***********************************************************************/ @@ -10899,7 +11031,7 @@ format_mode_line_unwind_data (struct frame *target_frame, return vector; } -static Lisp_Object +static void unwind_format_mode_line (Lisp_Object vector) { Lisp_Object old_window = AREF (vector, 7); @@ -10942,7 +11074,6 @@ unwind_format_mode_line (Lisp_Object vector) } Vmode_line_unwind_vector = vector; - return Qnil; } @@ -11112,7 +11243,18 @@ prepare_menu_bars (void) { 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); } } @@ -11299,79 +11441,6 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run) return hooks_run; } - - -/*********************************************************************** - 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 */ - - /*********************************************************************** Tool-bars ***********************************************************************/ @@ -11380,7 +11449,7 @@ x_cursor_to (int vpos, int hpos, int y, int x) /* 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. */ @@ -11391,7 +11460,7 @@ int last_tool_bar_item; 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)) @@ -11399,7 +11468,6 @@ fast_set_selected_frame (Lisp_Object 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 @@ -11919,13 +11987,12 @@ redisplay_tool_bar (struct frame *f) 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; } } @@ -12020,14 +12087,13 @@ redisplay_tool_bar (struct frame *f) { 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; } } @@ -12258,13 +12324,11 @@ note_tool_bar_highlight (struct frame *f, int x, int y) 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; @@ -12509,6 +12573,7 @@ static void debug_method_add (struct window *, char const *, ...) 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; @@ -12527,7 +12592,7 @@ debug_method_add (struct window *w, char const *fmt, ...) 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)) @@ -12785,7 +12850,7 @@ check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt, 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. */ @@ -12795,17 +12860,17 @@ check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt, /* 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 @@ -12818,24 +12883,17 @@ reconsider_clip_changes (struct window *w, struct 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; - - if (w == XWINDOW (selected_window)) - pt = PT; - else - pt = marker_position (w->pointm); + ptrdiff_t pt = (w == XWINDOW (selected_window) + ? 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; } } - #define STOP_POLLING \ do { if (! polling_stopped_here) stop_polling (); \ @@ -12856,10 +12914,10 @@ redisplay_internal (void) 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; @@ -12901,7 +12959,7 @@ redisplay_internal (void) /* 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); @@ -12916,21 +12974,11 @@ redisplay_internal (void) 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. */ @@ -12961,7 +13009,19 @@ redisplay_internal (void) 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); } @@ -12971,10 +13031,7 @@ redisplay_internal (void) /* 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 (); @@ -12986,26 +13043,34 @@ redisplay_internal (void) 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. */ @@ -13039,9 +13104,7 @@ redisplay_internal (void) 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; @@ -13098,9 +13161,10 @@ redisplay_internal (void) && !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. */ @@ -13196,12 +13260,12 @@ redisplay_internal (void) 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. */ @@ -13316,6 +13380,8 @@ redisplay_internal (void) && !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 @@ -13335,20 +13401,22 @@ redisplay_internal (void) 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 @@ -13362,6 +13430,7 @@ redisplay_internal (void) /* 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; } } @@ -13406,7 +13475,7 @@ redisplay_internal (void) update: /* If fonts changed, display again. */ - if (fonts_changed_p) + if (sf->fonts_changed) goto retry; /* Prevent various kinds of signals during display update. @@ -13423,6 +13492,7 @@ redisplay_internal (void) 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 @@ -13437,6 +13507,7 @@ redisplay_internal (void) { 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; } @@ -13477,7 +13548,6 @@ redisplay_internal (void) update_mode_lines = 0; windows_or_buffers_changed = 0; - cursor_type_changed = 0; } /* Start SIGIO interrupts coming again. Having them off during the @@ -13581,14 +13651,12 @@ redisplay_preserve_echo_area (int from_where) } -/* 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; } @@ -13620,7 +13688,7 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p) 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)) @@ -14393,8 +14461,7 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp) 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)) { @@ -14501,6 +14568,9 @@ try_scrolling (Lisp_Object window, int just_this_one_p, 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"); @@ -14511,8 +14581,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p, /* 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; @@ -14523,19 +14593,19 @@ try_scrolling (Lisp_Object window, int just_this_one_p, 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; @@ -14550,7 +14620,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p, 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)); @@ -14562,7 +14632,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p, 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 @@ -14589,8 +14659,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p, 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 @@ -14687,7 +14757,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p, 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); @@ -14703,7 +14773,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p, 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; @@ -14832,7 +14902,25 @@ compute_window_start_on_continuation_line (struct window *w) { 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. */ @@ -14884,6 +14972,10 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste 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. */ @@ -14897,7 +14989,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste 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. */ @@ -14911,18 +15003,14 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste 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"); @@ -14932,8 +15020,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste 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; @@ -14944,12 +15032,12 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste /* 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) @@ -15228,7 +15316,7 @@ set_vertical_scroll_bar (struct window *w) 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; @@ -15248,9 +15336,8 @@ set_vertical_scroll_bar (struct window *w) /* 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) @@ -15275,6 +15362,7 @@ 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; @@ -15288,7 +15376,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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 @@ -15367,8 +15456,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p) && !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 @@ -15377,6 +15466,9 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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. */ @@ -15458,7 +15550,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) /* 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; @@ -15486,8 +15578,6 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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) @@ -15505,7 +15595,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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 @@ -15524,8 +15614,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p) /* 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 @@ -15533,10 +15625,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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); @@ -15544,7 +15637,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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; + } } } @@ -15625,7 +15722,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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; @@ -15695,12 +15792,12 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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) @@ -15726,9 +15823,6 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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) { @@ -15785,9 +15879,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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; @@ -15809,7 +15905,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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); } @@ -15845,15 +15941,15 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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 @@ -15889,7 +15985,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) /* 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) @@ -15902,7 +15998,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) /* 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 @@ -15912,7 +16008,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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); @@ -15958,11 +16054,13 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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); @@ -16013,7 +16111,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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); } @@ -16023,12 +16122,13 @@ redisplay_window (Lisp_Object window, int just_this_one_p) 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; } @@ -16093,8 +16193,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p) } #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: @@ -16149,6 +16249,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags) 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)); @@ -16165,7 +16266,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags) { 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; } @@ -16174,11 +16275,13 @@ try_window (Lisp_Object window, struct text_pos pos, int flags) && !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; @@ -16200,8 +16303,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags) } /* 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 @@ -16210,21 +16312,16 @@ try_window (Lisp_Object window, struct text_pos pos, int flags) 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. */ @@ -16267,7 +16364,7 @@ try_window_reusing_current_matrix (struct window *w) /* 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. */ @@ -16315,8 +16412,7 @@ try_window_reusing_current_matrix (struct window *w) 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 @@ -16448,32 +16544,15 @@ try_window_reusing_current_matrix (struct window *w) 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; @@ -16544,7 +16623,7 @@ try_window_reusing_current_matrix (struct window *w) 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; @@ -16658,20 +16737,9 @@ try_window_reusing_current_matrix (struct window *w) 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; @@ -16811,11 +16879,11 @@ find_first_unchanged_at_end_row (struct window *w, /* 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)) @@ -16826,7 +16894,7 @@ find_first_unchanged_at_end_row (struct window *w, 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; @@ -17067,7 +17135,7 @@ try_window_id (struct window *w) 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. @@ -17160,7 +17228,7 @@ try_window_id (struct window *w) 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) @@ -17172,7 +17240,7 @@ try_window_id (struct window *w) /* 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; @@ -17243,10 +17311,8 @@ try_window_id (struct window *w) { /* 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); @@ -17279,7 +17345,7 @@ try_window_id (struct window *w) /* 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); @@ -17400,7 +17466,7 @@ try_window_id (struct window *w) 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)) { @@ -17408,7 +17474,7 @@ try_window_id (struct window *w) last_text_row = it.glyph_row - 1; } - if (fonts_changed_p) + if (f->fonts_changed) return -1; @@ -17479,10 +17545,13 @@ try_window_id (struct window *w) /* 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 @@ -17622,7 +17691,7 @@ try_window_id (struct window *w) /* 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. */ @@ -17652,8 +17721,7 @@ try_window_id (struct window *w) /* 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 @@ -17666,8 +17734,7 @@ try_window_id (struct window *w) } /* 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 @@ -17677,23 +17744,13 @@ try_window_id (struct window *w) 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")); } @@ -17702,12 +17759,7 @@ try_window_id (struct window *w) /* 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 @@ -17717,7 +17769,7 @@ try_window_id (struct window *w) /* 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; @@ -17735,8 +17787,8 @@ try_window_id (struct window *w) } 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")); @@ -17744,8 +17796,8 @@ try_window_id (struct window *w) 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; @@ -18921,6 +18973,7 @@ push_prefix_prop (struct it *it, Lisp_Object prop) it->bidi_it.string.bufpos = IT_CHARPOS (*it); it->bidi_it.string.from_disp_str = it->string_from_display_prop_p; it->bidi_it.string.unibyte = !it->multibyte_p; + it->bidi_it.w = it->w; bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it); } } @@ -18951,16 +19004,19 @@ push_prefix_prop (struct it *it, Lisp_Object prop) static Lisp_Object get_it_property (struct it *it, Lisp_Object prop) { - Lisp_Object position; + Lisp_Object position, object = it->object; - if (STRINGP (it->object)) + if (STRINGP (object)) position = make_number (IT_STRING_CHARPOS (*it)); - else if (BUFFERP (it->object)) - position = make_number (IT_CHARPOS (*it)); + else if (BUFFERP (object)) + { + position = make_number (IT_CHARPOS (*it)); + object = it->window; + } else return Qnil; - return Fget_char_property (position, prop, it->object); + return Fget_char_property (position, prop, object); } /* See if there's a line- or wrap-prefix, and if so, push it on IT. */ @@ -19201,7 +19257,7 @@ display_line (struct it *it) >= it->w->desired_matrix->nrows) { it->w->nrows_scale_factor++; - fonts_changed_p = 1; + it->f->fonts_changed = 1; return 0; } @@ -19990,6 +20046,10 @@ See also `bidi-paragraph-direction'. */) itb.string.lstring = Qnil; itb.string.bufpos = 0; itb.string.unibyte = 0; + /* We have no window to use here for ignoring window-specific + overlays. Using NULL for window pointer will cause + compute_display_string_pos to use the current buffer. */ + itb.w = NULL; bidi_paragraph_init (NEUTRAL_DIR, &itb, 1); bidi_unshelve_cache (itb_data, 0); set_buffer_temp (old); @@ -20007,6 +20067,400 @@ See also `bidi-paragraph-direction'. */) } } +DEFUN ("move-point-visually", Fmove_point_visually, + Smove_point_visually, 1, 1, 0, + doc: /* Move point in the visual order in the specified DIRECTION. +DIRECTION can be 1, meaning move to the right, or -1, which moves to the +left. + +Value is the new character position of point. */) + (Lisp_Object direction) +{ + struct window *w = XWINDOW (selected_window); + struct buffer *b = XBUFFER (w->contents); + struct glyph_row *row; + int dir; + Lisp_Object paragraph_dir; + +#define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \ + (!(ROW)->continued_p \ + && INTEGERP ((GLYPH)->object) \ + && (GLYPH)->type == CHAR_GLYPH \ + && (GLYPH)->u.ch == ' ' \ + && (GLYPH)->charpos >= 0 \ + && !(GLYPH)->avoid_cursor_p) + + CHECK_NUMBER (direction); + dir = XINT (direction); + if (dir > 0) + dir = 1; + else + dir = -1; + + /* 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. */ + if (w->window_end_valid + && !windows_or_buffers_changed + && b + && !b->clip_changed + && !b->prevent_redisplay_optimizations_p + && !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) + { + struct glyph *g = row->glyphs[TEXT_AREA]; + struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1; + struct glyph *gpt = g + w->cursor.hpos; + + for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir) + { + if (BUFFERP (g->object) && g->charpos != PT) + { + SET_PT (g->charpos); + w->cursor.vpos = -1; + return make_number (PT); + } + else if (!INTEGERP (g->object) && !EQ (g->object, gpt->object)) + { + ptrdiff_t new_pos; + + if (BUFFERP (gpt->object)) + { + new_pos = PT; + if ((gpt->resolved_level - row->reversed_p) % 2 == 0) + new_pos += (row->reversed_p ? -dir : dir); + else + new_pos -= (row->reversed_p ? -dir : dir);; + } + else if (BUFFERP (g->object)) + new_pos = g->charpos; + else + break; + SET_PT (new_pos); + w->cursor.vpos = -1; + return make_number (PT); + } + else if (ROW_GLYPH_NEWLINE_P (row, g)) + { + /* Glyphs inserted at the end of a non-empty line for + positioning the cursor have zero charpos, so we must + deduce the value of point by other means. */ + if (g->charpos > 0) + SET_PT (g->charpos); + else if (row->ends_at_zv_p && PT != ZV) + SET_PT (ZV); + else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1) + SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1); + else + break; + w->cursor.vpos = -1; + return make_number (PT); + } + } + if (g == e || INTEGERP (g->object)) + { + if (row->truncated_on_left_p || row->truncated_on_right_p) + goto simulate_display; + if (!row->reversed_p) + row += dir; + else + row -= dir; + if (row < MATRIX_FIRST_TEXT_ROW (w->current_matrix) + || row > MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)) + goto simulate_display; + + if (dir > 0) + { + if (row->reversed_p && !row->continued_p) + { + SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1); + w->cursor.vpos = -1; + return make_number (PT); + } + g = row->glyphs[TEXT_AREA]; + e = g + row->used[TEXT_AREA]; + for ( ; g < e; g++) + { + if (BUFFERP (g->object) + /* Empty lines have only one glyph, which stands + for the newline, and whose charpos is the + buffer position of the newline. */ + || ROW_GLYPH_NEWLINE_P (row, g) + /* When the buffer ends in a newline, the line at + EOB also has one glyph, but its charpos is -1. */ + || (row->ends_at_zv_p + && !row->reversed_p + && INTEGERP (g->object) + && g->type == CHAR_GLYPH + && g->u.ch == ' ')) + { + if (g->charpos > 0) + SET_PT (g->charpos); + else if (!row->reversed_p + && row->ends_at_zv_p + && PT != ZV) + SET_PT (ZV); + else + continue; + w->cursor.vpos = -1; + return make_number (PT); + } + } + } + else + { + if (!row->reversed_p && !row->continued_p) + { + SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1); + w->cursor.vpos = -1; + return make_number (PT); + } + e = row->glyphs[TEXT_AREA]; + g = e + row->used[TEXT_AREA] - 1; + for ( ; g >= e; g--) + { + if (BUFFERP (g->object) + || (ROW_GLYPH_NEWLINE_P (row, g) + && g->charpos > 0) + /* Empty R2L lines on GUI frames have the buffer + position of the newline stored in the stretch + glyph. */ + || g->type == STRETCH_GLYPH + || (row->ends_at_zv_p + && row->reversed_p + && INTEGERP (g->object) + && g->type == CHAR_GLYPH + && g->u.ch == ' ')) + { + if (g->charpos > 0) + SET_PT (g->charpos); + else if (row->reversed_p + && row->ends_at_zv_p + && PT != ZV) + SET_PT (ZV); + else + continue; + w->cursor.vpos = -1; + return make_number (PT); + } + } + } + } + } + + simulate_display: + + /* If we wind up here, we failed to move by using the glyphs, so we + need to simulate display instead. */ + + if (b) + paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents); + else + paragraph_dir = Qleft_to_right; + if (EQ (paragraph_dir, Qright_to_left)) + dir = -dir; + if (PT <= BEGV && dir < 0) + xsignal0 (Qbeginning_of_buffer); + else if (PT >= ZV && dir > 0) + xsignal0 (Qend_of_buffer); + else + { + struct text_pos pt; + struct it it; + int pt_x, target_x, pixel_width, pt_vpos; + bool at_eol_p; + bool overshoot_expected = false; + bool target_is_eol_p = false; + + /* Setup the arena. */ + SET_TEXT_POS (pt, PT, PT_BYTE); + start_display (&it, w, pt); + + if (it.cmp_it.id < 0 + && it.method == GET_FROM_STRING + && it.area == TEXT_AREA + && it.string_from_display_prop_p + && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER)) + overshoot_expected = true; + + /* Find the X coordinate of point. We start from the beginning + 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_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); + pt_x = it.current_x; + pt_vpos = it.vpos; + if (dir > 0 || overshoot_expected) + { + struct glyph_row *row = it.glyph_row; + + /* When point is at beginning of line, we don't have + information about the glyph there loaded into struct + it. Calling get_next_display_element fixes that. */ + if (pt_x == 0) + get_next_display_element (&it); + at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it); + it.glyph_row = NULL; + PRODUCE_GLYPHS (&it); /* compute it.pixel_width */ + it.glyph_row = row; + /* PRODUCE_GLYPHS advances it.current_x, so we must restore + it, lest it will become out of sync with it's buffer + position. */ + it.current_x = pt_x; + } + else + at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it); + pixel_width = it.pixel_width; + if (overshoot_expected && at_eol_p) + pixel_width = 0; + 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 (overshoot_expected) + 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 + pixel width of 1, so we can use that. On GUI frames we don't + have an easy way of getting at the pixel width of the + character to the left of point, so we use a different method + of getting to that place. */ + if (dir > 0) + target_x = pt_x + pixel_width; + else + target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width; + + /* Target X coordinate could be one line above or below the line + of point, in which case we need to adjust the target X + coordinate. Also, if moving to the left, we need to begin at + the left edge of the point's screen line. */ + if (dir < 0) + { + if (pt_x > 0) + { + start_display (&it, w, pt); + reseat_at_previous_visible_line_start (&it); + it.current_x = it.current_y = it.hpos = 0; + if (pt_vpos != 0) + move_it_by_lines (&it, pt_vpos); + } + else + { + move_it_by_lines (&it, -1); + target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f); + target_is_eol_p = true; + } + } + else + { + if (at_eol_p + || (target_x >= it.last_visible_x + && it.line_wrap != TRUNCATE)) + { + if (pt_x > 0) + move_it_by_lines (&it, 0); + move_it_by_lines (&it, 1); + target_x = 0; + } + } + + /* Move to the target X coordinate. */ +#ifdef HAVE_WINDOW_SYSTEM + /* On GUI frames, as we don't know the X coordinate of the + character to the left of point, moving point to the left + requires walking, one grapheme cluster at a time, until we + find ourself at a place immediately to the left of the + character at point. */ + if (FRAME_WINDOW_P (it.f) && dir < 0) + { + struct text_pos new_pos = it.current.pos; + enum move_it_result rc = MOVE_X_REACHED; + + 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; + if (new_x == it.current_x) + new_x++; + rc = move_it_in_display_line_to (&it, ZV, new_x, + MOVE_TO_POS | MOVE_TO_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); + } + it.current.pos = new_pos; + } + else +#endif + if (it.current_x != target_x) + move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X); + + /* When lines are truncated, the above loop will stop at the + window edge. But we want to get to the end of line, even if + it is beyond the window edge; automatic hscroll will then + scroll the window to show point as appropriate. */ + if (target_is_eol_p && it.line_wrap == TRUNCATE + && get_next_display_element (&it)) + { + struct text_pos new_pos = it.current.pos; + + while (!ITERATOR_AT_END_OF_LINE_P (&it)) + { + set_iterator_to_next (&it, 0); + if (it.method == GET_FROM_BUFFER) + new_pos = it.current.pos; + if (!get_next_display_element (&it)) + break; + } + + it.current.pos = new_pos; + } + + /* If we ended up in a display string that covers point, move to + buffer position to the right in the visual order. */ + if (dir > 0) + { + while (IT_CHARPOS (it) == PT) + { + set_iterator_to_next (&it, 0); + if (!get_next_display_element (&it)) + break; + } + } + + /* Move point to that position. */ + SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); + } + + return make_number (PT); + +#undef ROW_GLYPH_NEWLINE_P +} /*********************************************************************** @@ -20155,13 +20609,8 @@ redisplay_mode_lines (Lisp_Object window, int force) { 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. */ @@ -20838,7 +21287,7 @@ store_mode_line_string (const char *string, Lisp_Object lisp_string, int copy_st 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), @@ -20862,8 +21311,8 @@ store_mode_line_string (const char *string, Lisp_Object lisp_string, int copy_st 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); } @@ -20977,7 +21426,7 @@ are the selected window and the WINDOW's buffer). */) 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)); @@ -21511,7 +21960,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, 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"; @@ -21540,7 +21989,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, 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)) @@ -23360,17 +23809,15 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, && hlinfo->mouse_face_beg_row >= 0 && hlinfo->mouse_face_end_row >= 0) { - struct glyph_row *mouse_beg_row, *mouse_end_row; - - 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); + ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix); - 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]; } @@ -23538,12 +23985,12 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, #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; \ } \ } @@ -24459,21 +24906,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) 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) { @@ -25261,17 +25694,16 @@ x_produce_glyphs (struct it *it) /* 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. */ @@ -25285,24 +25717,24 @@ x_write_glyphs (struct glyph *start, int len) /* 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; } @@ -25310,19 +25742,18 @@ x_write_glyphs (struct glyph *start, int len) 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. */ @@ -25336,25 +25767,25 @@ x_insert_glyphs (struct glyph *start, int len) /* 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 (); } @@ -25364,18 +25795,18 @@ x_insert_glyphs (struct glyph *start, int len) (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) @@ -25393,16 +25824,16 @@ x_clear_end_of_line (int to_x) 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) @@ -25418,7 +25849,7 @@ x_clear_end_of_line (int to_x) } 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. */ @@ -25514,6 +25945,9 @@ set_frame_cursor_types (struct frame *f, Lisp_Object arg) } else FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR; + + /* Make sure the cursor gets redrawn. */ + f->cursor_type_changed = 1; } @@ -25962,7 +26396,7 @@ erase_phys_cursor (struct window *w) 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); @@ -26046,7 +26480,7 @@ display_and_set_cursor (struct window *w, int on, 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. */ @@ -26082,7 +26516,7 @@ update_window_cursor (struct window *w, int on) 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) { @@ -26101,7 +26535,7 @@ update_cursor_in_window_tree (struct window *w, int on_p) 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); } @@ -26288,10 +26722,7 @@ clear_mouse_face (Mouse_HLInfo *hlinfo) 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; } @@ -26552,7 +26983,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, /* 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)) @@ -26574,7 +27005,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, } 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)) @@ -26582,7 +27013,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, /* 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 @@ -26604,9 +27035,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, 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, @@ -26970,7 +27399,6 @@ mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo, { 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; @@ -26989,7 +27417,6 @@ mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo, { 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; @@ -27026,9 +27453,8 @@ mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo, /* 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. */ @@ -27526,8 +27952,6 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, 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; @@ -27646,10 +28070,7 @@ note_mouse_highlight (struct frame *f, int x, int y) /* 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; @@ -27891,8 +28312,7 @@ note_mouse_highlight (struct frame *f, int x, int y) : 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)) @@ -28090,11 +28510,7 @@ cancel_mouse_face (struct frame *f) 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); } @@ -28294,7 +28710,7 @@ x_draw_vertical_border (struct window *w) { 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) @@ -28307,7 +28723,7 @@ x_draw_vertical_border (struct window *w) { 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) @@ -28340,7 +28756,7 @@ expose_window (struct window *w, XRectangle *fr) /* 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; @@ -28665,9 +29081,11 @@ syms_of_xdisp (void) defsubr (&Stool_bar_lines_needed); defsubr (&Slookup_image_map); #endif + defsubr (&Sline_pixel_height); defsubr (&Sformat_mode_line); defsubr (&Sinvisible_p); defsubr (&Scurrent_bidi_paragraph_direction); + defsubr (&Smove_point_visually); DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook"); DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map"); @@ -28725,9 +29143,8 @@ syms_of_xdisp (void) 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"); @@ -28831,7 +29248,7 @@ See also `overlay-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. @@ -29215,8 +29632,10 @@ cursor shapes. */); 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"); @@ -29225,10 +29644,6 @@ cursor shapes. */); 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, @@ -29262,8 +29677,6 @@ Its value should be an ASCII acronym string, `hex-code', `empty-box', or void init_xdisp (void) { - current_header_line_height = current_mode_line_height = -1; - CHARPOS (this_line_start_pos) = 0; if (!noninteractive) @@ -29307,27 +29720,28 @@ init_xdisp (void) 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 { @@ -29338,7 +29752,6 @@ start_hourglass (void) hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay, show_hourglass, NULL); -#endif } @@ -29347,7 +29760,6 @@ start_hourglass (void) void cancel_hourglass (void) { -#if defined (HAVE_WINDOW_SYSTEM) if (hourglass_atimer) { cancel_atimer (hourglass_atimer); @@ -29356,5 +29768,6 @@ cancel_hourglass (void) if (hourglass_shown_p) hide_hourglass (); -#endif } + +#endif /* HAVE_WINDOW_SYSTEM */