X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/3553184981479cadb0af5e64f55f7ebe00415f25..75e6b97059b6e5b012b1084677070add5c5b0c19:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 7a727938a2..8ed0adfc89 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -215,6 +215,8 @@ extern int pending_menu_activation; extern int interrupt_input; extern int command_loop_level; +extern Lisp_Object do_mouse_tracking; + extern int minibuffer_auto_raise; extern Lisp_Object Vminibuffer_list; @@ -262,6 +264,10 @@ int mouse_autoselect_window; int auto_raise_tool_bar_buttons_p; +/* Non-zero means to reposition window if cursor line is only partially visible. */ + +int make_cursor_line_fully_visible_p; + /* Margin around tool bar buttons in pixels. */ Lisp_Object Vtool_bar_button_margin; @@ -306,6 +312,7 @@ Lisp_Object Qline_height, Qtotal; extern Lisp_Object Qheight; extern Lisp_Object QCwidth, QCheight, QCascent; extern Lisp_Object Qscroll_bar; +extern Lisp_Object Qcursor; /* Non-nil means highlight trailing whitespace. */ @@ -335,6 +342,11 @@ Lisp_Object Vvoid_text_area_pointer; Lisp_Object Qtrailing_whitespace; +/* Name and number of the face used to highlight escape glyphs. */ + +Lisp_Object Qescape_glyph; +int escape_glyph_face; + /* The symbol `image' which is the car of the lists used to represent images in Lisp. */ @@ -800,9 +812,9 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 }; /* Function prototypes. */ -static void setup_for_ellipsis P_ ((struct it *)); +static void setup_for_ellipsis P_ ((struct it *, int)); static void mark_window_display_accurate_1 P_ ((struct window *, int)); -static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object)); +static int single_display_spec_string_p P_ ((Lisp_Object, Lisp_Object)); static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object)); static int cursor_row_p P_ ((struct window *, struct glyph_row *)); static int redisplay_mode_lines P_ ((Lisp_Object, int)); @@ -824,7 +836,7 @@ static int store_frame_title P_ ((const unsigned char *, int, int)); static void x_consider_frame_title P_ ((Lisp_Object)); static void handle_stop P_ ((struct it *)); static int tool_bar_lines_needed P_ ((struct frame *)); -static int single_display_prop_intangible_p P_ ((Lisp_Object)); +static int single_display_spec_intangible_p P_ ((Lisp_Object)); static void ensure_echo_area_buffers P_ ((void)); static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object)); static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *)); @@ -885,7 +897,7 @@ static void next_overlay_string P_ ((struct it *)); static void reseat P_ ((struct it *, struct text_pos, int)); static void reseat_1 P_ ((struct it *, struct text_pos, int)); static void back_to_previous_visible_line_start P_ ((struct it *)); -static void reseat_at_previous_visible_line_start P_ ((struct it *)); +void reseat_at_previous_visible_line_start P_ ((struct it *)); static void reseat_at_next_visible_line_start P_ ((struct it *, int)); static int next_element_from_display_vector P_ ((struct it *)); static int next_element_from_string P_ ((struct it *)); @@ -918,7 +930,7 @@ static void compute_string_pos P_ ((struct text_pos *, struct text_pos, Lisp_Object)); static int face_before_or_after_it_pos P_ ((struct it *, int)); static int next_overlay_change P_ ((int)); -static int handle_single_display_prop P_ ((struct it *, Lisp_Object, +static int handle_single_display_spec P_ ((struct it *, Lisp_Object, Lisp_Object, struct text_pos *, int)); static int underlying_face_id P_ ((struct it *)); @@ -1782,7 +1794,8 @@ get_glyph_string_clip_rect (s, nr) /* If drawing a tool-bar window, draw it over the internal border at the top of the window. */ - if (s->w == XWINDOW (s->f->tool_bar_window)) + if (WINDOWP (s->f->tool_bar_window) + && s->w == XWINDOW (s->f->tool_bar_window)) r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f); } @@ -2072,6 +2085,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id) * FRAME_LINE_HEIGHT (it->f)); else if (it->f->extra_line_spacing > 0) it->extra_line_spacing = it->f->extra_line_spacing; + it->max_extra_line_spacing = 0; } /* If realized faces have been removed, e.g. because of face @@ -3218,7 +3232,7 @@ handle_invisible_prop (it) it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p; } else if (display_ellipsis_p) - setup_for_ellipsis (it); + setup_for_ellipsis (it, 0); } } @@ -3226,14 +3240,17 @@ handle_invisible_prop (it) } -/* Make iterator IT return `...' next. */ +/* Make iterator IT return `...' next. + Replaces LEN characters from buffer. */ static void -setup_for_ellipsis (it) +setup_for_ellipsis (it, len) struct it *it; + int len; { - if (it->dp - && VECTORP (DISP_INVIS_VECTOR (it->dp))) + /* Use the display table definition for `...'. Invalid glyphs + will be handled by the method returning elements from dpvec. */ + if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp))) { struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp)); it->dpvec = v->contents; @@ -3246,12 +3263,12 @@ setup_for_ellipsis (it) it->dpend = default_invis_vector + 3; } - /* The ellipsis display does not replace the display of the - character at the new position. Indicate this by setting - IT->dpvec_char_len to zero. */ - it->dpvec_char_len = 0; - + it->dpvec_char_len = len; it->current.dpvec_index = 0; + + /* Remember the current face id in case glyphs specify faces. + IT's face is restored in set_iterator_to_next. */ + it->saved_face_id = it->face_id; it->method = next_element_from_display_vector; } @@ -3262,7 +3279,10 @@ setup_for_ellipsis (it) ***********************************************************************/ /* Set up iterator IT from `display' property at its current position. - Called from handle_stop. */ + Called from handle_stop. + We return HANDLED_RETURN if some part of the display property + overrides the display of the buffer text itself. + Otherwise we return HANDLED_NORMALLY. */ static enum prop_handled handle_display_prop (it) @@ -3270,6 +3290,7 @@ handle_display_prop (it) { Lisp_Object prop, object; struct text_pos *position; + /* Nonzero if some property replaces the display of the text itself. */ int display_replaced_p = 0; if (STRINGP (it->string)) @@ -3317,7 +3338,7 @@ handle_display_prop (it) { for (; CONSP (prop); prop = XCDR (prop)) { - if (handle_single_display_prop (it, XCAR (prop), object, + if (handle_single_display_spec (it, XCAR (prop), object, position, display_replaced_p)) display_replaced_p = 1; } @@ -3326,13 +3347,13 @@ handle_display_prop (it) { int i; for (i = 0; i < ASIZE (prop); ++i) - if (handle_single_display_prop (it, AREF (prop, i), object, + if (handle_single_display_spec (it, AREF (prop, i), object, position, display_replaced_p)) display_replaced_p = 1; } else { - if (handle_single_display_prop (it, prop, object, position, 0)) + if (handle_single_display_spec (it, prop, object, position, 0)) display_replaced_p = 1; } @@ -3364,42 +3385,44 @@ display_prop_end (it, object, start_pos) } -/* Set up IT from a single `display' sub-property value PROP. OBJECT +/* Set up IT from a single `display' specification PROP. OBJECT is the object in which the `display' property was found. *POSITION is the position at which it was found. DISPLAY_REPLACED_P non-zero - means that we previously saw a display sub-property which already + means that we previously saw a display specification which already replaced text display with something else, for example an image; - ignore such properties after the first one has been processed. + we ignore such properties after the first one has been processed. - If PROP is a `space' or `image' sub-property, set *POSITION to the - end position of the `display' property. + If PROP is a `space' or `image' specification, and in some other + cases too, set *POSITION to the position where the `display' + property ends. Value is non-zero if something was found which replaces the display of buffer or string text. */ static int -handle_single_display_prop (it, prop, object, position, +handle_single_display_spec (it, spec, object, position, display_replaced_before_p) struct it *it; - Lisp_Object prop; + Lisp_Object spec; Lisp_Object object; struct text_pos *position; int display_replaced_before_p; { - Lisp_Object value; - int replaces_text_display_p = 0; Lisp_Object form; + Lisp_Object location, value; + struct text_pos start_pos; + int valid_p; - /* If PROP is a list of the form `(when FORM . VALUE)', FORM is - evaluated. If the result is nil, VALUE is ignored. */ + /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM. + If the result is non-nil, use VALUE instead of SPEC. */ form = Qt; - if (CONSP (prop) && EQ (XCAR (prop), Qwhen)) + if (CONSP (spec) && EQ (XCAR (spec), Qwhen)) { - prop = XCDR (prop); - if (!CONSP (prop)) + spec = XCDR (spec); + if (!CONSP (spec)) return 0; - form = XCAR (prop); - prop = XCDR (prop); + form = XCAR (spec); + spec = XCDR (spec); } if (!NILP (form) && !EQ (form, Qt)) @@ -3425,15 +3448,15 @@ handle_single_display_prop (it, prop, object, position, if (NILP (form)) return 0; - if (CONSP (prop) - && EQ (XCAR (prop), Qheight) - && CONSP (XCDR (prop))) + /* Handle `(height HEIGHT)' specifications. */ + if (CONSP (spec) + && EQ (XCAR (spec), Qheight) + && CONSP (XCDR (spec))) { if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f)) return 0; - - /* `(height HEIGHT)'. */ - it->font_height = XCAR (XCDR (prop)); + + it->font_height = XCAR (XCDR (spec)); if (!NILP (it->font_height)) { struct face *face = FACE_FROM_ID (it->f, it->face_id); @@ -3474,7 +3497,6 @@ handle_single_display_prop (it, prop, object, position, { /* Evaluate IT->font_height with `height' bound to the current specified height to get the new height. */ - Lisp_Object value; int count = SPECPDL_INDEX (); specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]); @@ -3488,29 +3510,35 @@ handle_single_display_prop (it, prop, object, position, if (new_height > 0) it->face_id = face_with_height (it->f, it->face_id, new_height); } + + return 0; } - else if (CONSP (prop) - && EQ (XCAR (prop), Qspace_width) - && CONSP (XCDR (prop))) + + /* Handle `(space_width WIDTH)'. */ + if (CONSP (spec) + && EQ (XCAR (spec), Qspace_width) + && CONSP (XCDR (spec))) { - /* `(space_width WIDTH)'. */ if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f)) return 0; - value = XCAR (XCDR (prop)); + value = XCAR (XCDR (spec)); if (NUMBERP (value) && XFLOATINT (value) > 0) it->space_width = value; + + return 0; } - else if (CONSP (prop) - && EQ (XCAR (prop), Qslice)) + + /* Handle `(slice X Y WIDTH HEIGHT)'. */ + if (CONSP (spec) + && EQ (XCAR (spec), Qslice)) { - /* `(slice X Y WIDTH HEIGHT)'. */ Lisp_Object tem; if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f)) return 0; - if (tem = XCDR (prop), CONSP (tem)) + if (tem = XCDR (spec), CONSP (tem)) { it->slice.x = XCAR (tem); if (tem = XCDR (tem), CONSP (tem)) @@ -3524,17 +3552,20 @@ handle_single_display_prop (it, prop, object, position, } } } + + return 0; } - else if (CONSP (prop) - && EQ (XCAR (prop), Qraise) - && CONSP (XCDR (prop))) + + /* Handle `(raise FACTOR)'. */ + if (CONSP (spec) + && EQ (XCAR (spec), Qraise) + && CONSP (XCDR (spec))) { - /* `(raise FACTOR)'. */ if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f)) return 0; #ifdef HAVE_WINDOW_SYSTEM - value = XCAR (XCDR (prop)); + value = XCAR (XCDR (spec)); if (NUMBERP (value)) { struct face *face = FACE_FROM_ID (it->f, it->face_id); @@ -3542,185 +3573,194 @@ handle_single_display_prop (it, prop, object, position, * (FONT_HEIGHT (face->font))); } #endif /* HAVE_WINDOW_SYSTEM */ + + return 0; } - else if (!it->string_from_display_prop_p) - { - /* `((margin left-margin) VALUE)' or `((margin right-margin) - VALUE) or `((margin nil) VALUE)' or VALUE. */ - Lisp_Object location, value; - struct text_pos start_pos; - int valid_p; - /* Characters having this form of property are not displayed, so - we have to find the end of the property. */ - start_pos = *position; - *position = display_prop_end (it, object, start_pos); - value = Qnil; + /* Don't handle the other kinds of display specifications + inside a string that we got from a `display' property. */ + if (it->string_from_display_prop_p) + return 0; - /* Let's stop at the new position and assume that all - text properties change there. */ - it->stop_charpos = position->charpos; + /* Characters having this form of property are not displayed, so + we have to find the end of the property. */ + start_pos = *position; + *position = display_prop_end (it, object, start_pos); + value = Qnil; - if (CONSP (prop) - && (EQ (XCAR (prop), Qleft_fringe) - || EQ (XCAR (prop), Qright_fringe)) - && CONSP (XCDR (prop))) - { - unsigned face_id = DEFAULT_FACE_ID; + /* Stop the scan at that end position--we assume that all + text properties change there. */ + it->stop_charpos = position->charpos; - /* Save current settings of IT so that we can restore them - when we are finished with the glyph property value. */ + /* Handle `(left-fringe BITMAP [FACE])' + and `(right-fringe BITMAP [FACE])'. */ + if (CONSP (spec) + && (EQ (XCAR (spec), Qleft_fringe) + || EQ (XCAR (spec), Qright_fringe)) + && CONSP (XCDR (spec))) + { + int face_id = DEFAULT_FACE_ID; + int fringe_bitmap; - /* `(left-fringe BITMAP FACE)'. */ - if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f)) - return 0; + if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f)) + /* If we return here, POSITION has been advanced + across the text with this property. */ + return 0; #ifdef HAVE_WINDOW_SYSTEM - value = XCAR (XCDR (prop)); - if (!NUMBERP (value) - || !valid_fringe_bitmap_id_p (XINT (value))) - return 0; + value = XCAR (XCDR (spec)); + if (!SYMBOLP (value) + || !(fringe_bitmap = lookup_fringe_bitmap (value))) + /* If we return here, POSITION has been advanced + across the text with this property. */ + return 0; - if (CONSP (XCDR (XCDR (prop)))) - { - Lisp_Object face_name = XCAR (XCDR (XCDR (prop))); + if (CONSP (XCDR (XCDR (spec)))) + { + Lisp_Object face_name = XCAR (XCDR (XCDR (spec))); + int face_id2 = lookup_named_face (it->f, face_name, 'A', 0); + if (face_id2 >= 0) + face_id = face_id2; + } - face_id = lookup_named_face (it->f, face_name, 'A'); - if (face_id < 0) - return 0; - } + /* Save current settings of IT so that we can restore them + when we are finished with the glyph property value. */ - push_it (it); + push_it (it); - it->area = TEXT_AREA; - it->what = IT_IMAGE; - it->image_id = -1; /* no image */ - it->position = start_pos; - it->object = NILP (object) ? it->w->buffer : object; - it->method = next_element_from_image; - it->face_id = face_id; + it->area = TEXT_AREA; + it->what = IT_IMAGE; + it->image_id = -1; /* no image */ + it->position = start_pos; + it->object = NILP (object) ? it->w->buffer : object; + it->method = next_element_from_image; + it->face_id = face_id; - /* Say that we haven't consumed the characters with - `display' property yet. The call to pop_it in - set_iterator_to_next will clean this up. */ - *position = start_pos; + /* Say that we haven't consumed the characters with + `display' property yet. The call to pop_it in + set_iterator_to_next will clean this up. */ + *position = start_pos; - if (EQ (XCAR (prop), Qleft_fringe)) - { - it->left_user_fringe_bitmap = XINT (value); - it->left_user_fringe_face_id = face_id; - } - else - { - it->right_user_fringe_bitmap = XINT (value); - it->right_user_fringe_face_id = face_id; - } -#endif /* HAVE_WINDOW_SYSTEM */ - return 1; + if (EQ (XCAR (spec), Qleft_fringe)) + { + it->left_user_fringe_bitmap = fringe_bitmap; + it->left_user_fringe_face_id = face_id; } - - location = Qunbound; - if (CONSP (prop) && CONSP (XCAR (prop))) + else { - Lisp_Object tem; + it->right_user_fringe_bitmap = fringe_bitmap; + it->right_user_fringe_face_id = face_id; + } +#endif /* HAVE_WINDOW_SYSTEM */ + return 1; + } - value = XCDR (prop); - if (CONSP (value)) - value = XCAR (value); + /* Prepare to handle `((margin left-margin) ...)', + `((margin right-margin) ...)' and `((margin nil) ...)' + prefixes for display specifications. */ + location = Qunbound; + if (CONSP (spec) && CONSP (XCAR (spec))) + { + Lisp_Object tem; - tem = XCAR (prop); - if (EQ (XCAR (tem), Qmargin) - && (tem = XCDR (tem), - tem = CONSP (tem) ? XCAR (tem) : Qnil, - (NILP (tem) - || EQ (tem, Qleft_margin) - || EQ (tem, Qright_margin)))) - location = tem; - } + value = XCDR (spec); + if (CONSP (value)) + value = XCAR (value); - if (EQ (location, Qunbound)) - { - location = Qnil; - value = prop; - } + tem = XCAR (spec); + if (EQ (XCAR (tem), Qmargin) + && (tem = XCDR (tem), + tem = CONSP (tem) ? XCAR (tem) : Qnil, + (NILP (tem) + || EQ (tem, Qleft_margin) + || EQ (tem, Qright_margin)))) + location = tem; + } + + if (EQ (location, Qunbound)) + { + location = Qnil; + value = spec; + } - valid_p = (STRINGP (value) + /* After this point, VALUE is the property after any + margin prefix has been stripped. It must be a string, + an image specification, or `(space ...)'. + + LOCATION specifies where to display: `left-margin', + `right-margin' or nil. */ + + valid_p = (STRINGP (value) #ifdef HAVE_WINDOW_SYSTEM - || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value)) + || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value)) #endif /* not HAVE_WINDOW_SYSTEM */ - || (CONSP (value) && EQ (XCAR (value), Qspace))); + || (CONSP (value) && EQ (XCAR (value), Qspace))); - if ((EQ (location, Qleft_margin) - || EQ (location, Qright_margin) - || NILP (location)) - && valid_p - && !display_replaced_before_p) - { - replaces_text_display_p = 1; - - /* Save current settings of IT so that we can restore them - when we are finished with the glyph property value. */ - push_it (it); + if (valid_p && !display_replaced_before_p) + { + /* Save current settings of IT so that we can restore them + when we are finished with the glyph property value. */ + push_it (it); - if (NILP (location)) - it->area = TEXT_AREA; - else if (EQ (location, Qleft_margin)) - it->area = LEFT_MARGIN_AREA; - else - it->area = RIGHT_MARGIN_AREA; + if (NILP (location)) + it->area = TEXT_AREA; + else if (EQ (location, Qleft_margin)) + it->area = LEFT_MARGIN_AREA; + else + it->area = RIGHT_MARGIN_AREA; - if (STRINGP (value)) - { - it->string = value; - it->multibyte_p = STRING_MULTIBYTE (it->string); - it->current.overlay_string_index = -1; - IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0; - it->end_charpos = it->string_nchars = SCHARS (it->string); - it->method = next_element_from_string; - it->stop_charpos = 0; - it->string_from_display_prop_p = 1; - /* Say that we haven't consumed the characters with - `display' property yet. The call to pop_it in - set_iterator_to_next will clean this up. */ - *position = start_pos; - } - else if (CONSP (value) && EQ (XCAR (value), Qspace)) - { - it->method = next_element_from_stretch; - it->object = value; - it->current.pos = it->position = start_pos; - } -#ifdef HAVE_WINDOW_SYSTEM - else - { - it->what = IT_IMAGE; - it->image_id = lookup_image (it->f, value); - it->position = start_pos; - it->object = NILP (object) ? it->w->buffer : object; - it->method = next_element_from_image; - - /* Say that we haven't consumed the characters with - `display' property yet. The call to pop_it in - set_iterator_to_next will clean this up. */ - *position = start_pos; - } -#endif /* HAVE_WINDOW_SYSTEM */ + if (STRINGP (value)) + { + it->string = value; + it->multibyte_p = STRING_MULTIBYTE (it->string); + it->current.overlay_string_index = -1; + IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0; + it->end_charpos = it->string_nchars = SCHARS (it->string); + it->method = next_element_from_string; + it->stop_charpos = 0; + it->string_from_display_prop_p = 1; + /* Say that we haven't consumed the characters with + `display' property yet. The call to pop_it in + set_iterator_to_next will clean this up. */ + *position = start_pos; + } + else if (CONSP (value) && EQ (XCAR (value), Qspace)) + { + it->method = next_element_from_stretch; + it->object = value; + it->current.pos = it->position = start_pos; } +#ifdef HAVE_WINDOW_SYSTEM else - /* Invalid property or property not supported. Restore - the position to what it was before. */ - *position = start_pos; + { + it->what = IT_IMAGE; + it->image_id = lookup_image (it->f, value); + it->position = start_pos; + it->object = NILP (object) ? it->w->buffer : object; + it->method = next_element_from_image; + + /* Say that we haven't consumed the characters with + `display' property yet. The call to pop_it in + set_iterator_to_next will clean this up. */ + *position = start_pos; + } +#endif /* HAVE_WINDOW_SYSTEM */ + + return 1; } - return replaces_text_display_p; + /* Invalid property or property not supported. Restore + POSITION to what it was before. */ + *position = start_pos; + return 0; } -/* Check if PROP is a display sub-property value whose text should be +/* Check if SPEC is a display specification value whose text should be treated as intangible. */ static int -single_display_prop_intangible_p (prop) +single_display_spec_intangible_p (prop) Lisp_Object prop; { /* Skip over `when FORM'. */ @@ -3773,7 +3813,7 @@ display_prop_intangible_p (prop) /* A list of sub-properties. */ while (CONSP (prop)) { - if (single_display_prop_intangible_p (XCAR (prop))) + if (single_display_spec_intangible_p (XCAR (prop))) return 1; prop = XCDR (prop); } @@ -3783,11 +3823,11 @@ display_prop_intangible_p (prop) /* A vector of sub-properties. */ int i; for (i = 0; i < ASIZE (prop); ++i) - if (single_display_prop_intangible_p (AREF (prop, i))) + if (single_display_spec_intangible_p (AREF (prop, i))) return 1; } else - return single_display_prop_intangible_p (prop); + return single_display_spec_intangible_p (prop); return 0; } @@ -3796,7 +3836,7 @@ display_prop_intangible_p (prop) /* Return 1 if PROP is a display sub-property value containing STRING. */ static int -single_display_prop_string_p (prop, string) +single_display_spec_string_p (prop, string) Lisp_Object prop, string; { if (EQ (string, prop)) @@ -3841,7 +3881,7 @@ display_prop_string_p (prop, string) /* A list of sub-properties. */ while (CONSP (prop)) { - if (single_display_prop_string_p (XCAR (prop), string)) + if (single_display_spec_string_p (XCAR (prop), string)) return 1; prop = XCDR (prop); } @@ -3851,11 +3891,11 @@ display_prop_string_p (prop, string) /* A vector of sub-properties. */ int i; for (i = 0; i < ASIZE (prop); ++i) - if (single_display_prop_string_p (AREF (prop, i), string)) + if (single_display_spec_string_p (AREF (prop, i), string)) return 1; } else - return single_display_prop_string_p (prop, string); + return single_display_spec_string_p (prop, string); return 0; } @@ -4039,7 +4079,7 @@ next_overlay_string (it) /* If we have to display `...' for invisible text, set the iterator up for that. */ if (display_ellipsis_p) - setup_for_ellipsis (it); + setup_for_ellipsis (it, 0); } else { @@ -4551,7 +4591,8 @@ back_to_previous_visible_line_start (it) { Lisp_Object prop; - prop = Fget_char_property (make_number (IT_CHARPOS (*it)), + /* Check the newline before point for invisibility. */ + prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1), Qinvisible, it->window); if (TEXT_PROP_MEANS_INVISIBLE (prop)) visible_p = 0; @@ -4582,7 +4623,7 @@ back_to_previous_visible_line_start (it) selective display. At the end, update IT's overlay information, face information etc. */ -static void +void reseat_at_previous_visible_line_start (it) struct it *it; { @@ -4830,7 +4871,10 @@ get_next_display_element (it) we hit the end of what we iterate over. Performance note: the function pointer `method' used here turns out to be faster than using a sequence of if-statements. */ - int success_p = (*it->method) (it); + int success_p; + + get_next: + success_p = (*it->method) (it); if (it->what == IT_CHARACTER) { @@ -4862,14 +4906,14 @@ get_next_display_element (it) it->dpvec = v->contents; it->dpend = v->contents + v->size; it->current.dpvec_index = 0; + it->saved_face_id = it->face_id; it->method = next_element_from_display_vector; - success_p = get_next_display_element (it); } else { set_iterator_to_next (it, 0); - success_p = get_next_display_element (it); } + goto get_next; } /* Translate control characters into `\003' or `^C' form. @@ -4887,13 +4931,19 @@ get_next_display_element (it) translated to octal form. */ else if ((it->c < ' ' && (it->area != TEXT_AREA + /* In mode line, treat \n like other crl chars. */ + || (it->c != '\n' + && it->glyph_row && it->glyph_row->mode_line_p) || (it->c != '\n' && it->c != '\t'))) || (it->multibyte_p ? ((it->c >= 127 && it->len == 1) - || !CHAR_PRINTABLE_P (it->c)) + || !CHAR_PRINTABLE_P (it->c) + || it->c == 0x8ad + || it->c == 0x8a0) : (it->c >= 127 - && it->c == unibyte_char_to_multibyte (it->c)))) + && (!unibyte_display_via_language_environment + || it->c == unibyte_char_to_multibyte (it->c))))) { /* IT->c is a control character which must be displayed either as '\003' or as `^C' where the '\\' and '^' @@ -4901,6 +4951,22 @@ get_next_display_element (it) IT->ctl_chars with glyphs for what we have to display. Then, set IT->dpvec to these glyphs. */ GLYPH g; + int ctl_len; + int face_id = escape_glyph_face; + + /* Find the face id if `escape-glyph' unless we recently did. */ + if (face_id < 0) + { + Lisp_Object tem = Fget (Qescape_glyph, Qface); + if (INTEGERP (tem)) + face_id = XINT (tem); + else + face_id = 0; + /* If there's overflow, use 0 instead. */ + if (FAST_GLYPH_FACE (FAST_MAKE_GLYPH (0, face_id)) != face_id) + face_id = 0; + escape_glyph_face = face_id; + } if (it->c < 128 && it->ctl_arrow_p) { @@ -4910,19 +4976,27 @@ get_next_display_element (it) && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp)))) g = XINT (DISP_CTRL_GLYPH (it->dp)); else - g = FAST_MAKE_GLYPH ('^', 0); + g = FAST_MAKE_GLYPH ('^', face_id); XSETINT (it->ctl_chars[0], g); - g = FAST_MAKE_GLYPH (it->c ^ 0100, 0); + g = FAST_MAKE_GLYPH (it->c ^ 0100, face_id); XSETINT (it->ctl_chars[1], g); + ctl_len = 2; + } + else if (it->c == 0x8a0 || it->c == 0x8ad) + { + /* Set IT->ctl_chars[0] to the glyph for `\\'. */ + if (it->dp + && INTEGERP (DISP_ESCAPE_GLYPH (it->dp)) + && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (it->dp)))) + g = XINT (DISP_ESCAPE_GLYPH (it->dp)); + else + g = FAST_MAKE_GLYPH ('\\', face_id); + XSETINT (it->ctl_chars[0], g); - /* Set up IT->dpvec and return first character from it. */ - it->dpvec_char_len = it->len; - it->dpvec = it->ctl_chars; - it->dpend = it->dpvec + 2; - it->current.dpvec_index = 0; - it->method = next_element_from_display_vector; - get_next_display_element (it); + g = FAST_MAKE_GLYPH (it->c == 0x8ad ? '-' : ' ', face_id); + XSETINT (it->ctl_chars[1], g); + ctl_len = 2; } else { @@ -4937,7 +5011,7 @@ get_next_display_element (it) && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp)))) escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp)); else - escape_glyph = FAST_MAKE_GLYPH ('\\', 0); + escape_glyph = FAST_MAKE_GLYPH ('\\', face_id); if (SINGLE_BYTE_CHAR_P (it->c)) str[0] = it->c, len = 1; @@ -4964,23 +5038,27 @@ get_next_display_element (it) XSETINT (it->ctl_chars[i * 4], escape_glyph); /* Insert three more glyphs into IT->ctl_chars for the octal display of the character. */ - g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0); + g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', + face_id); XSETINT (it->ctl_chars[i * 4 + 1], g); - g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0); + g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', + face_id); XSETINT (it->ctl_chars[i * 4 + 2], g); - g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0); + g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', + face_id); XSETINT (it->ctl_chars[i * 4 + 3], g); } - - /* Set up IT->dpvec and return the first character - from it. */ - it->dpvec_char_len = it->len; - it->dpvec = it->ctl_chars; - it->dpend = it->dpvec + len * 4; - it->current.dpvec_index = 0; - it->method = next_element_from_display_vector; - get_next_display_element (it); + ctl_len = len * 4; } + + /* Set up IT->dpvec and return first character from it. */ + it->dpvec_char_len = it->len; + it->dpvec = it->ctl_chars; + it->dpend = it->dpvec + ctl_len; + it->current.dpvec_index = 0; + it->saved_face_id = it->face_id; + it->method = next_element_from_display_vector; + goto get_next; } } @@ -5102,6 +5180,9 @@ set_iterator_to_next (it, reseat_p) it->dpvec = NULL; it->current.dpvec_index = -1; + /* Recheck faces after display vector */ + it->stop_charpos = 0; + /* Skip over characters which were displayed via IT->dpvec. */ if (it->dpvec_char_len < 0) reseat_at_next_visible_line_start (it, 1); @@ -5170,11 +5251,14 @@ set_iterator_to_next (it, reseat_p) && IT_STRING_CHARPOS (*it) >= 0)); } - /* Load IT's display element fields with information about the next display element which comes from a display table entry or from the result of translating a control character to one of the forms `^C' - or `\003'. IT->dpvec holds the glyphs to return as characters. */ + or `\003'. + + IT->dpvec holds the glyphs to return as characters. + IT->saved_face_id holds the face id before the display vector-- + it is restored into IT->face_idin set_iterator_to_next. */ static int next_element_from_display_vector (it) @@ -5183,10 +5267,6 @@ next_element_from_display_vector (it) /* Precondition. */ xassert (it->dpvec && it->current.dpvec_index >= 0); - /* Remember the current face id in case glyphs specify faces. - IT's face is restored in set_iterator_to_next. */ - it->saved_face_id = it->face_id; - if (INTEGERP (*it->dpvec) && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec))) { @@ -5370,28 +5450,7 @@ next_element_from_ellipsis (it) struct it *it; { if (it->selective_display_ellipsis_p) - { - if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp))) - { - /* Use the display table definition for `...'. Invalid glyphs - will be handled by the method returning elements from dpvec. */ - struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp)); - it->dpvec_char_len = it->len; - it->dpvec = v->contents; - it->dpend = v->contents + v->size; - it->current.dpvec_index = 0; - it->method = next_element_from_display_vector; - } - else - { - /* Use default `...' which is stored in default_invis_vector. */ - it->dpvec_char_len = it->len; - it->dpvec = default_invis_vector; - it->dpend = default_invis_vector + 3; - it->current.dpvec_index = 0; - it->method = next_element_from_display_vector; - } - } + setup_for_ellipsis (it, it->len); else { /* The face at the current position may be different from the @@ -6059,10 +6118,13 @@ move_it_vertically_backward (it, dy) { int nlines, h; struct it it2, it3; - int start_pos = IT_CHARPOS (*it); + int start_pos; + move_further_back: xassert (dy >= 0); + start_pos = IT_CHARPOS (*it); + /* Estimate how many newlines we must move back. */ nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f)); @@ -6128,13 +6190,13 @@ move_it_vertically_backward (it, dy) a line height of 13 pixels each, recentering with point on the bottom line will try to move -39/2 = 19 pixels backward. Try to avoid moving into the first line. */ - && it->current_y - target_y > line_height / 3 * 2 + && it->current_y - target_y > line_height * 2 / 3 && IT_CHARPOS (*it) > BEGV) { TRACE_MOVE ((stderr, " not far enough -> move_vert %d\n", target_y - it->current_y)); - move_it_vertically (it, target_y - it->current_y); - xassert (IT_CHARPOS (*it) >= BEGV); + dy = it->current_y - target_y; + goto move_further_back; } else if (target_y >= it->current_y + line_height && IT_CHARPOS (*it) < ZV) @@ -6175,7 +6237,7 @@ move_it_vertically (it, dy) { if (dy <= 0) move_it_vertically_backward (it, -dy); - else if (dy > 0) + else { TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy)); move_it_to (it, ZV, -1, it->current_y + dy, -1, @@ -6272,6 +6334,8 @@ move_it_by_lines (it, dvpos, need_y_p) /* DVPOS == 0 means move to the start of the screen line. */ move_it_vertically_backward (it, 0); xassert (it->current_x == 0 && it->hpos == 0); + /* Let next call to line_bottom_y calculate real line height */ + last_height = 0; } else if (dvpos > 0) move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS); @@ -6360,7 +6424,7 @@ add_to_log (format, arg1, arg2) bcopy (SDATA (msg), buffer, len); message_dolog (buffer, len - 1, 1, 0); - SAFE_FREE (len); + SAFE_FREE (); UNGCPRO; } @@ -6584,7 +6648,7 @@ message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte) } return 0; } - + /* Display an echo area message M with a specified length of NBYTES bytes. The string may include null characters. If M is 0, clear @@ -6683,6 +6747,7 @@ message3 (m, nbytes, multibyte) struct gcpro gcpro1; GCPRO1 (m); + clear_message (1,1); /* First flush out any partial line written with print. */ message_log_maybe_newline (); @@ -7415,7 +7480,7 @@ resize_mini_window (w, exact_p) height = it.current_y + last_height; else height = it.current_y + it.max_ascent + it.max_descent; - height -= it.extra_line_spacing; + height -= min (it.extra_line_spacing, it.max_extra_line_spacing); height = (height + unit - 1) / unit; } @@ -7971,7 +8036,7 @@ store_frame_title (str, field_width, precision) /* Copy at most PRECISION chars from STR. */ nbytes = strlen (str); - n+= c_string_width (str, nbytes, precision, &dummy, &nbytes); + n += c_string_width (str, nbytes, precision, &dummy, &nbytes); while (nbytes--) store_frame_title_char (*str++); @@ -8409,7 +8474,8 @@ update_tool_bar (f, save_match_data) { struct buffer *prev = current_buffer; int count = SPECPDL_INDEX (); - Lisp_Object old_tool_bar; + Lisp_Object new_tool_bar; + int new_n_tool_bar; struct gcpro gcpro1; /* Set current_buffer to the buffer of the selected @@ -8428,18 +8494,24 @@ update_tool_bar (f, save_match_data) specbind (Qoverriding_local_map, Qnil); } - old_tool_bar = f->tool_bar_items; - GCPRO1 (old_tool_bar); + GCPRO1 (new_tool_bar); /* Build desired tool-bar items from keymaps. */ - BLOCK_INPUT; - f->tool_bar_items - = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items); - UNBLOCK_INPUT; + new_tool_bar = tool_bar_items (Fcopy_sequence (f->tool_bar_items), + &new_n_tool_bar); /* Redisplay the tool-bar if we changed it. */ - if (! NILP (Fequal (old_tool_bar, f->tool_bar_items))) - w->update_mode_line = Qt; + if (NILP (Fequal (new_tool_bar, f->tool_bar_items))) + { + /* Redisplay that happens asynchronously due to an expose event + may access f->tool_bar_items. Make sure we update both + variables within BLOCK_INPUT so no such event interrupts. */ + BLOCK_INPUT; + f->tool_bar_items = new_tool_bar; + f->n_tool_bar_items = new_n_tool_bar; + w->update_mode_line = Qt; + UNBLOCK_INPUT; + } UNGCPRO; @@ -8686,6 +8758,7 @@ display_tool_bar_line (it) { row->height = row->phys_height = it->last_visible_y - row->y; row->ascent = row->phys_ascent = 0; + row->extra_line_spacing = 0; } row->full_width_p = 1; @@ -9518,11 +9591,13 @@ update_overlay_arrows (up_to_date) } -/* Return overlay arrow string at row, or nil. */ +/* Return overlay arrow string to display at row. + Return t if display as bitmap in left fringe. + Return nil if no overlay arrow. */ static Lisp_Object -overlay_arrow_at_row (f, row, pbitmap) - struct frame *f; +overlay_arrow_at_row (it, row, pbitmap) + struct it *it; struct glyph_row *row; int *pbitmap; { @@ -9545,9 +9620,10 @@ overlay_arrow_at_row (f, row, pbitmap) && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val))) { val = overlay_arrow_string_or_property (var, pbitmap); - if (FRAME_WINDOW_P (f)) + if (FRAME_WINDOW_P (it->f) + && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0) return Qt; - else if (STRINGP (val)) + if (STRINGP (val)) return val; break; } @@ -10381,7 +10457,7 @@ redisplay_internal (preserve_echo_area) This is useful in situations where you need to redisplay but no user action has occurred, making it inappropriate for the message area to be cleared. See tracking_off and - wait_reading_process_input for examples of these situations. + wait_reading_process_output for examples of these situations. FROM_WHERE is an integer saying from where this function was called. This is useful for debugging. */ @@ -10402,6 +10478,9 @@ redisplay_preserve_echo_area (from_where) } else redisplay_internal (1); + + if (rif != NULL && rif->flush_display_optional) + rif->flush_display_optional (NULL); } @@ -10647,6 +10726,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) { struct glyph *glyph = row->glyphs[TEXT_AREA]; struct glyph *end = glyph + row->used[TEXT_AREA]; + struct glyph *cursor = NULL; /* The first glyph that starts a sequence of glyphs from string. */ struct glyph *string_start; /* The X coordinate of string_start. */ @@ -10656,6 +10736,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) /* The last known character position before string_start. */ int string_before_pos; int x = row->x; + int cursor_x = x; + int cursor_from_overlay_pos = 0; int pt_old = PT - delta; /* Skip over glyphs not having an object at the start of the row. @@ -10681,6 +10763,12 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) string_start = NULL; x += glyph->pixel_width; ++glyph; + if (cursor_from_overlay_pos + && last_pos > cursor_from_overlay_pos) + { + cursor_from_overlay_pos = 0; + cursor = 0; + } } else { @@ -10688,12 +10776,40 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos) string_start = glyph; string_start_x = x; /* Skip all glyphs from string. */ - SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object)); + do + { + int pos; + if ((cursor == NULL || glyph > cursor) + && !NILP (Fget_char_property (make_number ((glyph)->charpos), + Qcursor, (glyph)->object)) + && (pos = string_buffer_position (w, glyph->object, + string_before_pos), + (pos == 0 /* From overlay */ + || pos == pt_old))) + { + /* Estimate overlay buffer position from the buffer + positions of the glyphs before and after the overlay. + Add 1 to last_pos so that if point corresponds to the + glyph right after the overlay, we still use a 'cursor' + property found in that overlay. */ + cursor_from_overlay_pos = pos == 0 ? last_pos+1 : 0; + cursor = glyph; + cursor_x = x; + } + x += glyph->pixel_width; + ++glyph; + } + while (glyph < end && STRINGP (glyph->object)); } } - if (string_start - && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old)) + if (cursor != NULL) + { + glyph = cursor; + x = cursor_x; + } + else if (string_start + && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old)) { /* We may have skipped over point because the previous glyphs are from string. As there's no easy way to know the @@ -10822,6 +10938,9 @@ make_cursor_line_fully_visible (w, force_p) struct glyph_row *row; int window_height; + if (!make_cursor_line_fully_visible_p) + return 1; + /* It's not always possible to find the cursor, e.g, when a window is full of overlay strings. Don't do anything in that case. */ if (w->cursor.vpos < 0) @@ -10831,7 +10950,7 @@ make_cursor_line_fully_visible (w, force_p) row = MATRIX_ROW (matrix, w->cursor.vpos); /* If the cursor row is not partially visible, there's nothing to do. */ - if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row)) + if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)) return 1; /* If the row the cursor is in is taller than the window's height, @@ -10985,7 +11104,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, { start_display (&it, w, scroll_margin_pos); if (this_scroll_margin) - move_it_vertically (&it, - this_scroll_margin); + move_it_vertically_backward (&it, this_scroll_margin); if (extra_scroll_margin_lines) move_it_by_lines (&it, - extra_scroll_margin_lines, 0); scroll_margin_pos = it.current.pos; @@ -11085,8 +11204,8 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, start_display (&it, w, startp); if (scroll_conservatively) - amount_to_scroll = - max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step)); + amount_to_scroll + = max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step)); else if (scroll_step || temp_scroll_step) amount_to_scroll = scroll_max; else @@ -11105,7 +11224,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, if (amount_to_scroll <= 0) return SCROLLING_FAILED; - move_it_vertically (&it, - amount_to_scroll); + move_it_vertically_backward (&it, amount_to_scroll); startp = it.current.pos; } } @@ -11365,8 +11484,7 @@ try_cursor_movement (window, startp, scroll_step) else if (PT < XFASTINT (w->last_point)) { /* Cursor has to be moved backward. Note that PT >= - CHARPOS (startp) because of the outer - if-statement. */ + CHARPOS (startp) because of the outer if-statement. */ while (!row->mode_line_p && (MATRIX_ROW_START_CHARPOS (row) > PT || (MATRIX_ROW_START_CHARPOS (row) == PT @@ -11410,7 +11528,8 @@ try_cursor_movement (window, startp, scroll_step) /* if PT is not in the glyph row, give up. */ rc = CURSOR_MOVEMENT_MUST_SCROLL; } - else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row)) + else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row) + && make_cursor_line_fully_visible_p) { if (PT == MATRIX_ROW_END_CHARPOS (row) && !row->ends_at_zv_p @@ -11525,6 +11644,9 @@ redisplay_window (window, just_this_one_p) *w->desired_matrix->method = 0; #endif + /* Force this to be looked up again for each redisp of each window. */ + escape_glyph_face = -1; + specbind (Qinhibit_point_motion_hooks, Qt); reconsider_clip_changes (w, buffer); @@ -11878,8 +12000,8 @@ redisplay_window (window, just_this_one_p) buffer. */ || !NILP (Vwindow_scroll_functions) || MINI_WINDOW_P (w) - || !(used_current_matrix_p = - try_window_reusing_current_matrix (w))) + || !(used_current_matrix_p + = try_window_reusing_current_matrix (w))) { IF_DEBUG (debug_method_add (w, "1")); try_window (window, startp); @@ -11985,7 +12107,7 @@ redisplay_window (window, just_this_one_p) if (it.current_y <= 0) { init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); - move_it_vertically (&it, 0); + move_it_vertically_backward (&it, 0); xassert (IT_CHARPOS (it) <= PT); it.current_y = 0; } @@ -12008,8 +12130,8 @@ redisplay_window (window, just_this_one_p) || !NILP (Vwindow_scroll_functions) || !just_this_one_p || MINI_WINDOW_P (w) - || !(used_current_matrix_p = - try_window_reusing_current_matrix (w))) + || !(used_current_matrix_p + = try_window_reusing_current_matrix (w))) try_window (window, startp); /* If new fonts have been loaded (due to fontsets), give up. We @@ -12173,14 +12295,16 @@ redisplay_window (window, just_this_one_p) } #ifdef HAVE_WINDOW_SYSTEM - if (update_window_fringes (w, 0) + if (FRAME_WINDOW_P (f) + && update_window_fringes (w, 0) && !just_this_one_p && (used_current_matrix_p || overlay_arrow_seen) && !w->pseudo_window_p) { update_begin (f); BLOCK_INPUT; - draw_window_fringes (w); + if (draw_window_fringes (w, 1)) + x_draw_vertical_border (w); UNBLOCK_INPUT; update_end (f); } @@ -12332,7 +12456,7 @@ try_window_reusing_current_matrix (w) /* Give up if old or new display is scrolled vertically. We could make this function handle this, but right now it doesn't. */ start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); - if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row)) + if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)) return 0; /* The variable new_start now holds the new window start. The old @@ -12367,10 +12491,36 @@ try_window_reusing_current_matrix (w) last_text_row = last_reused_text_row = NULL; while (it.current_y < it.last_visible_y - && IT_CHARPOS (it) < CHARPOS (start) && !fonts_changed_p) - if (display_line (&it)) - last_text_row = it.glyph_row - 1; + { + /* If we have reached into the characters in the START row, + that means the line boundaries have changed. So we + can't start copying with the row START. Maybe it will + work to start copying with the following row. */ + while (IT_CHARPOS (it) > CHARPOS (start)) + { + /* Advance to the next row as the "start". */ + start_row++; + start = start_row->start.pos; + /* If there are no more rows to try, or just one, give up. */ + if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1 + || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row) + || CHARPOS (start) == ZV) + { + clear_glyph_matrix (w->desired_matrix); + return 0; + } + + start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix); + } + /* If we have reached alignment, + we can copy the rest of the rows. */ + if (IT_CHARPOS (it) == CHARPOS (start)) + break; + + if (display_line (&it)) + last_text_row = it.glyph_row - 1; + } /* A value of current_y < last_visible_y means that we stopped at the previous window start, which in turn means that we @@ -12378,12 +12528,12 @@ try_window_reusing_current_matrix (w) if (it.current_y < it.last_visible_y) { /* IT.vpos always starts from 0; it counts text lines. */ - nrows_scrolled = it.vpos; + nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix)); /* Find PT if not already found in the lines displayed. */ if (w->cursor.vpos < 0) { - int dy = it.current_y - first_row_y; + int dy = it.current_y - start_row->y; row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); row = row_containing_pos (w, PT, row, NULL, dy); @@ -12403,7 +12553,7 @@ try_window_reusing_current_matrix (w) scroll_run_hook will clear the cursor, and use the current matrix to get the height of the row the cursor is in. */ - run.current_y = first_row_y; + run.current_y = start_row->y; run.desired_y = it.current_y; run.height = it.last_visible_y - it.current_y; @@ -13423,7 +13573,9 @@ try_window_id (w) && CHARPOS (start) > BEGV) /* Old redisplay didn't take scroll margin into account at the bottom, but then global-hl-line-mode doesn't scroll. KFS 2004-06-14 */ - || w->cursor.y + cursor_height + this_scroll_margin > it.last_visible_y) + || (w->cursor.y + (make_cursor_line_fully_visible_p + ? cursor_height + this_scroll_margin + : 1)) > it.last_visible_y) { w->cursor.vpos = -1; clear_glyph_matrix (w->desired_matrix); @@ -14001,8 +14153,8 @@ usage: (trace-to-stderr STRING &rest OBJECTS) */) Building Desired Matrix Rows ***********************************************************************/ -/* Return a temporary glyph row holding the glyphs of an overlay - arrow. Only used for non-window-redisplay windows. */ +/* Return a temporary glyph row holding the glyphs of an overlay arrow. + Used for non-window-redisplay windows, and for windows w/o left fringe. */ static struct glyph_row * get_overlay_arrow_glyph_row (w, overlay_arrow_string) @@ -14148,6 +14300,7 @@ compute_line_metrics (it) row->height = it->max_ascent + it->max_descent; row->phys_ascent = it->max_phys_ascent; row->phys_height = it->max_phys_ascent + it->max_phys_descent; + row->extra_line_spacing = it->max_extra_line_spacing; } /* Compute the width of this line. */ @@ -14191,6 +14344,7 @@ compute_line_metrics (it) row->pixel_width -= it->truncation_pixel_width; row->ascent = row->phys_ascent = 0; row->height = row->phys_height = row->visible_height = 1; + row->extra_line_spacing = 0; } /* Compute a hash code for this row. */ @@ -14425,7 +14579,9 @@ highlight_trailing_whitespace (f, row) && glyph->u.ch == ' ')) && trailing_whitespace_p (glyph->charpos)) { - int face_id = lookup_named_face (f, Qtrailing_whitespace, 0); + int face_id = lookup_named_face (f, Qtrailing_whitespace, 0, 0); + if (face_id < 0) + return; while (glyph >= start && BUFFERP (glyph->object) @@ -14518,8 +14674,10 @@ display_line (it) hscrolled. This may stop at an x-position < IT->first_visible_x if the first glyph is partially visible or if we hit a line end. */ if (it->current_x < it->first_visible_x) - move_it_in_display_line_to (it, ZV, it->first_visible_x, - MOVE_TO_POS | MOVE_TO_X); + { + move_it_in_display_line_to (it, ZV, it->first_visible_x, + MOVE_TO_POS | MOVE_TO_X); + } /* Get the initial row height. This is either the height of the text hscrolled, if there is any, or zero. */ @@ -14527,6 +14685,7 @@ display_line (it) row->height = it->max_ascent + it->max_descent; row->phys_ascent = it->max_phys_ascent; row->phys_height = it->max_phys_ascent + it->max_phys_descent; + row->extra_line_spacing = it->max_extra_line_spacing; /* Loop generating characters. The loop is left with IT on the next character to display. */ @@ -14592,6 +14751,8 @@ display_line (it) row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent); row->phys_height = max (row->phys_height, it->max_phys_ascent + it->max_phys_descent); + row->extra_line_spacing = max (row->extra_line_spacing, + it->max_extra_line_spacing); set_iterator_to_next (it, 1); continue; } @@ -14620,6 +14781,8 @@ display_line (it) row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent); row->phys_height = max (row->phys_height, it->max_phys_ascent + it->max_phys_descent); + row->extra_line_spacing = max (row->extra_line_spacing, + it->max_extra_line_spacing); if (it->current_x - it->pixel_width < it->first_visible_x) row->x = x - it->first_visible_x; } @@ -14771,6 +14934,8 @@ display_line (it) row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent); row->phys_height = max (row->phys_height, it->max_phys_ascent + it->max_phys_descent); + row->extra_line_spacing = max (row->extra_line_spacing, + it->max_extra_line_spacing); /* End of this display line if row is continued. */ if (row->continued_p || row->ends_at_zv_p) @@ -14841,12 +15006,10 @@ display_line (it) { if (!get_next_display_element (it)) { -#ifdef HAVE_WINDOW_SYSTEM it->continuation_lines_width = 0; row->ends_at_zv_p = 1; row->exact_window_width_line_p = 1; break; -#endif /* HAVE_WINDOW_SYSTEM */ } if (ITERATOR_AT_END_OF_LINE_P (it)) { @@ -14883,11 +15046,11 @@ display_line (it) better to let it be displayed like cursors under X. */ if (! overlay_arrow_seen && (overlay_arrow_string - = overlay_arrow_at_row (it->f, row, &overlay_arrow_bitmap), + = overlay_arrow_at_row (it, row, &overlay_arrow_bitmap), !NILP (overlay_arrow_string))) { /* Overlay arrow in window redisplay is a fringe bitmap. */ - if (!FRAME_WINDOW_P (it->f)) + if (STRINGP (overlay_arrow_string)) { struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string); @@ -14912,10 +15075,12 @@ display_line (it) row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA]; } } - + else + { + it->w->overlay_arrow_bitmap = overlay_arrow_bitmap; + row->overlay_arrow_p = 1; + } overlay_arrow_seen = 1; - it->w->overlay_arrow_bitmap = overlay_arrow_bitmap; - row->overlay_arrow_p = 1; } /* Compute pixel dimensions of this line. */ @@ -15298,6 +15463,10 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) Lisp_Object oprops, aelt; oprops = Ftext_properties_at (make_number (0), elt); + /* If the starting string's properties are not what + we want, translate the string. Also, if the string + is risky, do that anyway. */ + if (NILP (Fequal (props, oprops)) || risky) { /* If the starting string has properties, @@ -15376,14 +15545,15 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) if (this - 1 != last) { + int nchars, nbytes; + /* Output to end of string or up to '%'. Field width is length of string. Don't output more than PRECISION allows us. */ --this; - prec = chars_in_text (last, this - last); - if (precision > 0 && prec > precision - n) - prec = precision - n; + prec = c_string_width (last, this - last, precision - n, + &nchars, &nbytes); if (frame_title_ptr) n += store_frame_title (last, 0, prec); @@ -15391,9 +15561,14 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) { int bytepos = last - lisp_string; int charpos = string_byte_to_char (elt, bytepos); + int endpos = (precision <= 0 + ? string_byte_to_char (elt, + this - lisp_string) + : charpos + nchars); + n += store_mode_line_string (NULL, Fsubstring (elt, make_number (charpos), - make_number (charpos + prec)), + make_number (endpos)), 0, 0, 0, Qnil); } else @@ -15674,7 +15849,8 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky) The mode_line_string_face face property is always added to the string. */ -static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props) +static int +store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props) char *string; Lisp_Object lisp_string; int copy_string; @@ -15695,7 +15871,7 @@ static int store_mode_line_string (string, lisp_string, copy_string, field_width props = mode_line_string_face_prop; else if (!NILP (mode_line_string_face)) { - Lisp_Object face = Fplist_get (props, Qface); + Lisp_Object face = Fsafe_plist_get (props, Qface); props = Fcopy_sequence (props); if (NILP (face)) face = mode_line_string_face; @@ -15720,7 +15896,7 @@ static int store_mode_line_string (string, lisp_string, copy_string, field_width Lisp_Object face; if (NILP (props)) props = Ftext_properties_at (make_number (0), lisp_string); - face = Fplist_get (props, Qface); + face = Fsafe_plist_get (props, Qface); if (NILP (face)) face = mode_line_string_face; else @@ -15756,15 +15932,16 @@ static int store_mode_line_string (string, lisp_string, copy_string, field_width DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line, - 0, 3, 0, + 0, 4, 0, doc: /* Return the mode-line of selected window as a string. First optional arg FORMAT specifies a different format string (see `mode-line-format' for details) to use. If FORMAT is t, return the buffer's header-line. Second optional arg WINDOW specifies a different window to use as the context for the formatting. -If third optional arg NO-PROPS is non-nil, string is not propertized. */) - (format, window, no_props) - Lisp_Object format, window, no_props; +If third optional arg NO-PROPS is non-nil, string is not propertized. +Fourth optional arg BUFFER specifies which buffer to use. */) + (format, window, no_props, buffer) + Lisp_Object format, window, no_props, buffer; { struct it it; int len; @@ -15776,42 +15953,46 @@ If third optional arg NO-PROPS is non-nil, string is not propertized. */) window = selected_window; CHECK_WINDOW (window); w = XWINDOW (window); - CHECK_BUFFER (w->buffer); - if (XBUFFER (w->buffer) != current_buffer) + if (NILP (buffer)) + buffer = w->buffer; + + CHECK_BUFFER (buffer); + + if (XBUFFER (buffer) != current_buffer) { old_buffer = current_buffer; - set_buffer_internal_1 (XBUFFER (w->buffer)); + set_buffer_internal_1 (XBUFFER (buffer)); } if (NILP (format) || EQ (format, Qt)) { - face_id = NILP (format) - ? CURRENT_MODE_LINE_FACE_ID (w) : - HEADER_LINE_FACE_ID; - format = NILP (format) - ? current_buffer->mode_line_format - : current_buffer->header_line_format; + face_id = (NILP (format) + ? CURRENT_MODE_LINE_FACE_ID (w) + : HEADER_LINE_FACE_ID); + format = (NILP (format) + ? current_buffer->mode_line_format + : current_buffer->header_line_format); } init_iterator (&it, w, -1, -1, NULL, face_id); if (NILP (no_props)) { - mode_line_string_face = - (face_id == MODE_LINE_FACE_ID ? Qmode_line : - face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive : - face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil); + mode_line_string_face + = (face_id == MODE_LINE_FACE_ID ? Qmode_line + : face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive + : face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil); - mode_line_string_face_prop = - NILP (mode_line_string_face) ? Qnil : - Fcons (Qface, Fcons (mode_line_string_face, Qnil)); + mode_line_string_face_prop + = (NILP (mode_line_string_face) ? Qnil + : Fcons (Qface, Fcons (mode_line_string_face, Qnil))); /* We need a dummy last element in mode_line_string_list to indicate we are building the propertized mode-line string. Using mode_line_string_face_prop here GC protects it. */ - mode_line_string_list = - Fcons (mode_line_string_face_prop, Qnil); + mode_line_string_list + = Fcons (mode_line_string_face_prop, Qnil); frame_title_ptr = NULL; } else @@ -15940,27 +16121,31 @@ pint2hrstr (buf, width, d) { tenths = remainder / 100; if (50 <= remainder % 100) - if (tenths < 9) - tenths++; - else - { - quotient++; - if (quotient == 10) - tenths = -1; - else - tenths = 0; - } + { + if (tenths < 9) + tenths++; + else + { + quotient++; + if (quotient == 10) + tenths = -1; + else + tenths = 0; + } + } } else if (500 <= remainder) - if (quotient < 999) - quotient++; - else - { - quotient = 1; - exponent++; - tenths = 0; - } + { + if (quotient < 999) + quotient++; + else + { + quotient = 1; + exponent++; + tenths = 0; + } + } } /* Calculate the LENGTH of QUOTIENT.TENTHS as a string. */ @@ -16084,7 +16269,10 @@ decode_mode_spec_coding (coding_system, buf, eol_flag) generated by character C. PRECISION >= 0 means don't return a string longer than that value. FIELD_WIDTH > 0 means pad the string returned with spaces to that value. Return 1 in *MULTIBYTE - if the result is multibyte text. */ + if the result is multibyte text. + + Note we operate on the current buffer for most purposes, + the exception being w->base_line_pos. */ static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; @@ -16098,7 +16286,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte) Lisp_Object obj; struct frame *f = XFRAME (WINDOW_FRAME (w)); char *decode_mode_spec_buf = f->decode_mode_spec_buffer; - struct buffer *b = XBUFFER (w->buffer); + struct buffer *b = current_buffer; obj = Qnil; *multibyte = 0; @@ -16400,7 +16588,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte) case 's': /* status of process */ - obj = Fget_buffer_process (w->buffer); + obj = Fget_buffer_process (Fcurrent_buffer ()); if (NILP (obj)) return "no process"; #ifdef subprocesses @@ -16659,6 +16847,7 @@ display_string (string, lisp_string, face_string, face_string_pos, row->height = it->max_ascent + it->max_descent; row->phys_ascent = it->max_phys_ascent; row->phys_height = it->max_phys_ascent + it->max_phys_descent; + row->extra_line_spacing = it->max_extra_line_spacing; /* This condition is for the case that we are called with current_x past last_visible_x. */ @@ -16718,6 +16907,8 @@ display_string (string, lisp_string, face_string, face_string_pos, row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent); row->phys_height = max (row->phys_height, it->max_phys_ascent + it->max_phys_descent); + row->extra_line_spacing = max (row->extra_line_spacing, + it->max_extra_line_spacing); x += glyph->pixel_width; ++i; } @@ -17154,7 +17345,8 @@ init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl) s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); /* Display the internal border below the tool-bar window. */ - if (s->w == XWINDOW (s->f->tool_bar_window)) + if (WINDOWP (s->f->tool_bar_window) + && s->w == XWINDOW (s->f->tool_bar_window)) s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f); s->ybase = s->y + row->ascent; @@ -18126,6 +18318,19 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) return x_reached; } +/* Expand row matrix if too narrow. Don't expand if area + is not present. */ + +#define IT_EXPAND_MATRIX_WIDTH(it, area) \ + { \ + if (!fonts_changed_p \ + && (it->glyph_row->glyphs[area] \ + < it->glyph_row->glyphs[area + 1])) \ + { \ + it->w->ncols_scale_factor++; \ + fonts_changed_p = 1; \ + } \ + } /* Store one glyph for IT->char_to_display in IT->glyph_row. Called from x_produce_glyphs when IT->glyph_row is non-null. */ @@ -18163,11 +18368,8 @@ append_glyph (it) glyph->font_type = FONT_TYPE_UNKNOWN; ++it->glyph_row->used[area]; } - else if (!fonts_changed_p) - { - it->w->ncols_scale_factor++; - fonts_changed_p = 1; - } + else + IT_EXPAND_MATRIX_WIDTH (it, area); } /* Store one glyph for the composition IT->cmp_id in IT->glyph_row. @@ -18205,11 +18407,8 @@ append_composite_glyph (it) glyph->font_type = FONT_TYPE_UNKNOWN; ++it->glyph_row->used[area]; } - else if (!fonts_changed_p) - { - it->w->ncols_scale_factor++; - fonts_changed_p = 1; - } + else + IT_EXPAND_MATRIX_WIDTH (it, area); } @@ -18244,7 +18443,7 @@ produce_image_glyph (it) { struct image *img; struct face *face; - int face_ascent, glyph_ascent; + int glyph_ascent; struct glyph_slice slice; xassert (it->what == IT_IMAGE); @@ -18327,7 +18526,7 @@ produce_image_glyph (it) #if 0 /* this breaks image tiling */ /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent. */ - face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f); + int face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f); if (face_ascent > it->ascent) it->ascent = it->phys_ascent = face_ascent; #endif @@ -18379,11 +18578,8 @@ produce_image_glyph (it) glyph->font_type = FONT_TYPE_UNKNOWN; ++it->glyph_row->used[area]; } - else if (!fonts_changed_p) - { - it->w->ncols_scale_factor++; - fonts_changed_p = 1; - } + else + IT_EXPAND_MATRIX_WIDTH (it, area); } } @@ -18427,11 +18623,8 @@ append_stretch_glyph (it, object, width, height, ascent) glyph->font_type = FONT_TYPE_UNKNOWN; ++it->glyph_row->used[area]; } - else if (!fonts_changed_p) - { - it->w->ncols_scale_factor++; - fonts_changed_p = 1; - } + else + IT_EXPAND_MATRIX_WIDTH (it, area); } @@ -18486,14 +18679,14 @@ produce_stretch_glyph (it) plist = XCDR (it->object); /* Compute the width of the stretch. */ - if ((prop = Fplist_get (plist, QCwidth), !NILP (prop)) + if ((prop = Fsafe_plist_get (plist, QCwidth), !NILP (prop)) && calc_pixel_width_or_height (&tem, it, prop, font, 1, 0)) { /* Absolute width `:width WIDTH' specified and valid. */ zero_width_ok_p = 1; width = (int)tem; } - else if (prop = Fplist_get (plist, QCrelative_width), + else if (prop = Fsafe_plist_get (plist, QCrelative_width), NUMVAL (prop) > 0) { /* Relative width `:relative-width FACTOR' specified and valid. @@ -18517,7 +18710,7 @@ produce_stretch_glyph (it) x_produce_glyphs (&it2); width = NUMVAL (prop) * it2.pixel_width; } - else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop)) + else if ((prop = Fsafe_plist_get (plist, QCalign_to), !NILP (prop)) && calc_pixel_width_or_height (&tem, it, prop, font, 1, &align_to)) { if (it->glyph_row == NULL || !it->glyph_row->mode_line_p) @@ -18537,13 +18730,13 @@ produce_stretch_glyph (it) width = 1; /* Compute height. */ - if ((prop = Fplist_get (plist, QCheight), !NILP (prop)) + if ((prop = Fsafe_plist_get (plist, QCheight), !NILP (prop)) && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0)) { height = (int)tem; zero_height_ok_p = 1; } - else if (prop = Fplist_get (plist, QCrelative_height), + else if (prop = Fsafe_plist_get (plist, QCrelative_height), NUMVAL (prop) > 0) height = FONT_HEIGHT (font) * NUMVAL (prop); else @@ -18555,7 +18748,7 @@ produce_stretch_glyph (it) /* Compute percentage of height used for ascent. If `:ascent ASCENT' is present and valid, use that. Otherwise, derive the ascent from the font in use. */ - if (prop = Fplist_get (plist, QCascent), + if (prop = Fsafe_plist_get (plist, QCascent), NUMVAL (prop) > 0 && NUMVAL (prop) <= 100) ascent = height * NUMVAL (prop) / 100.0; else if (!NILP (prop) @@ -18615,8 +18808,10 @@ calc_line_height_property (it, prop, font, boff, total) if (STRINGP (it->object)) position = make_number (IT_STRING_CHARPOS (*it)); - else + else if (BUFFERP (it->object)) position = make_number (IT_CHARPOS (*it)); + else + return Qnil; val = Fget_char_property (position, prop, it->object); @@ -18660,7 +18855,7 @@ calc_line_height_property (it, prop, font, boff, total) struct face *face; struct font_info *font_info; - face_id = lookup_named_face (it->f, face_name, ' '); + face_id = lookup_named_face (it->f, face_name, ' ', 0); if (face_id < 0) return make_number (-1); @@ -19338,7 +19533,11 @@ x_produce_glyphs (it) it->current_x += it->pixel_width; if (extra_line_spacing > 0) - it->descent += extra_line_spacing; + { + it->descent += extra_line_spacing; + if (extra_line_spacing > it->max_extra_line_spacing) + it->max_extra_line_spacing = extra_line_spacing; + } it->max_ascent = max (it->max_ascent, it->ascent); it->max_descent = max (it->max_descent, it->descent); @@ -19920,6 +20119,11 @@ erase_phys_cursor (w) if (!cursor_row->enabled_p) goto mark_cursor_off; + /* If line spacing is > 0, old cursor may only be partially visible in + window after split-window. So adjust visible height. */ + cursor_row->visible_height = min (cursor_row->visible_height, + window_text_bottom_y (w) - cursor_row->y); + /* If row is completely invisible, don't attempt to delete a cursor which isn't there. This can happen if cursor is at top of a window, and we switch to a buffer with a header line in that window. */ @@ -19963,6 +20167,7 @@ erase_phys_cursor (w) { int x, y; int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); + int width; cursor_glyph = get_phys_cursor_glyph (w); if (cursor_glyph == NULL) @@ -19970,9 +20175,10 @@ erase_phys_cursor (w) x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y)); + width = min (cursor_glyph->pixel_width, + window_box_width (w, TEXT_AREA) - w->phys_cursor.x); - rif->clear_frame_area (f, x, y, - cursor_glyph->pixel_width, cursor_row->visible_height); + rif->clear_frame_area (f, x, y, width, cursor_row->visible_height); } /* Erase the cursor by redrawing the character underneath it. */ @@ -20305,19 +20511,20 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop) int past_end = 0; first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); + if (charpos < MATRIX_ROW_START_CHARPOS (first)) + { + *x = first->x; + *y = first->y; + *hpos = 0; + *vpos = MATRIX_ROW_VPOS (first, w->current_matrix); + return 1; + } + row = row_containing_pos (w, charpos, first, NULL, 0); if (row == NULL) { - if (charpos < MATRIX_ROW_START_CHARPOS (first)) - { - *x = *y = *hpos = *vpos = 0; - return 1; - } - else - { - row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); - past_end = 1; - } + row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); + past_end = 1; } *x = row->x; @@ -20687,6 +20894,10 @@ define_frame_cursor1 (f, cursor, pointer) Cursor cursor; Lisp_Object pointer; { + /* Do not change cursor shape while dragging mouse. */ + if (!NILP (do_mouse_tracking)) + return; + if (!NILP (pointer)) { if (EQ (pointer, Qarrow)) @@ -20748,7 +20959,7 @@ note_mode_line_or_margin_highlight (w, x, y, area) if (IMAGEP (object)) { Lisp_Object image_map, hotspot; - if ((image_map = Fplist_get (XCDR (object), QCmap), + if ((image_map = Fsafe_plist_get (XCDR (object), QCmap), !NILP (image_map)) && (hotspot = find_hot_spot (image_map, dx, dy), CONSP (hotspot)) @@ -20760,12 +20971,14 @@ note_mode_line_or_margin_highlight (w, x, y, area) /* Could check AREA_ID to see if we enter/leave this hot-spot. If so, we could look for mouse-enter, mouse-leave properties in PLIST (and do something...). */ - if ((plist = XCDR (hotspot), CONSP (plist))) + hotspot = XCDR (hotspot); + if (CONSP (hotspot) + && (plist = XCAR (hotspot), CONSP (plist))) { - pointer = Fplist_get (plist, Qpointer); + pointer = Fsafe_plist_get (plist, Qpointer); if (NILP (pointer)) pointer = Qhand; - help = Fplist_get (plist, Qhelp_echo); + help = Fsafe_plist_get (plist, Qhelp_echo); if (!NILP (help)) { help_echo_string = help; @@ -20776,7 +20989,7 @@ note_mode_line_or_margin_highlight (w, x, y, area) } } if (NILP (pointer)) - pointer = Fplist_get (XCDR (object), QCpointer); + pointer = Fsafe_plist_get (XCDR (object), QCpointer); } } @@ -20786,13 +20999,16 @@ note_mode_line_or_margin_highlight (w, x, y, area) /* If we're on a string with `help-echo' text property, arrange for the help to be displayed. This is done by setting the global variable help_echo_string to the help string. */ - help = Fget_text_property (pos, Qhelp_echo, string); - if (!NILP (help)) + if (NILP (help)) { - help_echo_string = help; - XSETWINDOW (help_echo_window, w); - help_echo_object = string; - help_echo_pos = charpos; + help = Fget_text_property (pos, Qhelp_echo, string); + if (!NILP (help)) + { + help_echo_string = help; + XSETWINDOW (help_echo_window, w); + help_echo_object = string; + help_echo_pos = charpos; + } } if (NILP (pointer)) @@ -20859,8 +21075,10 @@ note_mouse_highlight (f, x, y) /* Which window is that in? */ window = window_from_coordinates (f, x, y, &part, 0, 0, 1); - /* If we were displaying active text in another window, clear that. */ - if (! EQ (window, dpyinfo->mouse_face_window)) + /* If we were displaying active text in another window, clear that. + Also clear if we move out of text area in same window. */ + if (! EQ (window, dpyinfo->mouse_face_window) + || (part != ON_TEXT && !NILP (dpyinfo->mouse_face_window))) clear_mouse_face (dpyinfo); /* Not on a window -> return. */ @@ -20892,7 +21110,8 @@ note_mouse_highlight (f, x, y) if (part == ON_VERTICAL_BORDER) cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; - else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE) + else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE + || part == ON_SCROLL_BAR) cursor = FRAME_X_OUTPUT (f)->nontext_cursor; else cursor = FRAME_X_OUTPUT (f)->text_cursor; @@ -20924,7 +21143,7 @@ note_mouse_highlight (f, x, y) if (img != NULL && IMAGEP (img->spec)) { Lisp_Object image_map, hotspot; - if ((image_map = Fplist_get (XCDR (img->spec), QCmap), + if ((image_map = Fsafe_plist_get (XCDR (img->spec), QCmap), !NILP (image_map)) && (hotspot = find_hot_spot (image_map, glyph->slice.x + dx, @@ -20938,12 +21157,14 @@ note_mouse_highlight (f, x, y) /* Could check AREA_ID to see if we enter/leave this hot-spot. If so, we could look for mouse-enter, mouse-leave properties in PLIST (and do something...). */ - if ((plist = XCDR (hotspot), CONSP (plist))) + hotspot = XCDR (hotspot); + if (CONSP (hotspot) + && (plist = XCAR (hotspot), CONSP (plist))) { - pointer = Fplist_get (plist, Qpointer); + pointer = Fsafe_plist_get (plist, Qpointer); if (NILP (pointer)) pointer = Qhand; - help_echo_string = Fplist_get (plist, Qhelp_echo); + help_echo_string = Fsafe_plist_get (plist, Qhelp_echo); if (!NILP (help_echo_string)) { help_echo_window = window; @@ -20953,7 +21174,7 @@ note_mouse_highlight (f, x, y) } } if (NILP (pointer)) - pointer = Fplist_get (XCDR (img->spec), QCpointer); + pointer = Fsafe_plist_get (XCDR (img->spec), QCpointer); } } @@ -21547,6 +21768,9 @@ x_draw_vertical_border (w) do it for frames with vertical scroll bars because either the right scroll bar of a window, or the left scroll bar of its neighbor will suffice as a border. */ + if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame))) + return; + if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)) { @@ -21990,6 +22214,8 @@ syms_of_xdisp () staticpro (&Qfontification_functions); Qtrailing_whitespace = intern ("trailing-whitespace"); staticpro (&Qtrailing_whitespace); + Qescape_glyph = intern ("escape-glyph"); + staticpro (&Qescape_glyph); Qimage = intern ("image"); staticpro (&Qimage); QCmap = intern (":map"); @@ -22247,6 +22473,10 @@ otherwise. */); doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */); auto_raise_tool_bar_buttons_p = 1; + DEFVAR_BOOL ("make-cursor-line-fully-visible", &make_cursor_line_fully_visible_p, + doc: /* *Non-nil means to scroll (recenter) cursor line if it is not fully visible. */); + make_cursor_line_fully_visible_p = 1; + DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin, doc: /* *Margin around tool-bar buttons in pixels. If an integer, use that for both horizontal and vertical margins.