X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/802c6e56829f7d7ac9b6312e5c97066874d0e461..75e6b97059b6e5b012b1084677070add5c5b0c19:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 04851288e4..8ed0adfc89 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -342,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. */ @@ -807,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)); @@ -831,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 *)); @@ -925,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 *)); @@ -3227,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); } } @@ -3235,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; @@ -3255,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; } @@ -3271,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) @@ -3279,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)) @@ -3326,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; } @@ -3335,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; } @@ -3373,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)) @@ -3434,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); @@ -3483,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]); @@ -3497,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)) @@ -3533,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); @@ -3551,186 +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; - int fringe_bitmap; + /* 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 (!SYMBOLP (value) - || !(fringe_bitmap = lookup_fringe_bitmap (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 = fringe_bitmap; - it->left_user_fringe_face_id = face_id; - } - else - { - it->right_user_fringe_bitmap = fringe_bitmap; - 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'. */ @@ -3783,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); } @@ -3793,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; } @@ -3806,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)) @@ -3851,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); } @@ -3861,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; } @@ -4049,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 { @@ -4841,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) { @@ -4873,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. @@ -4905,7 +4938,9 @@ get_next_display_element (it) || (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 && (!unibyte_display_via_language_environment || it->c == unibyte_char_to_multibyte (it->c))))) @@ -4916,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) { @@ -4925,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 { @@ -4952,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; @@ -4979,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; } } @@ -5117,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); @@ -5185,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) @@ -5198,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))) { @@ -5385,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 @@ -6604,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 @@ -11600,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); @@ -14532,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) @@ -14625,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. */ @@ -14955,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)) { @@ -18269,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. */ @@ -18306,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. @@ -18348,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); } @@ -18522,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); } } @@ -18570,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); } @@ -18805,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); @@ -20117,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) @@ -20124,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. */ @@ -20947,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)) @@ -22159,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");