This is the height of W minus the height of a mode line, if any. */
-inline int
+int
window_text_bottom_y (struct window *w)
{
int height = WINDOW_TOTAL_HEIGHT (w);
means return the total width of W, not including fringes to
the left and right of the window. */
-inline int
+int
window_box_width (struct window *w, int area)
{
int cols = XFASTINT (w->total_cols);
/* Return the pixel height of the display area of window W, not
including mode lines of W, if any. */
-inline int
+int
window_box_height (struct window *w)
{
struct frame *f = XFRAME (w->frame);
area AREA of window W. AREA < 0 means return the left edge of the
whole window, to the right of the left fringe of W. */
-inline int
+int
window_box_left_offset (struct window *w, int area)
{
int x;
area AREA of window W. AREA < 0 means return the right edge of the
whole window, to the left of the right fringe of W. */
-inline int
+int
window_box_right_offset (struct window *w, int area)
{
return window_box_left_offset (w, area) + window_box_width (w, area);
area AREA of window W. AREA < 0 means return the left edge of the
whole window, to the right of the left fringe of W. */
-inline int
+int
window_box_left (struct window *w, int area)
{
struct frame *f = XFRAME (w->frame);
area AREA of window W. AREA < 0 means return the right edge of the
whole window, to the left of the right fringe of W. */
-inline int
+int
window_box_right (struct window *w, int area)
{
return window_box_left (w, area) + window_box_width (w, area);
coordinates of the upper-left corner of the box. Return in
*BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
-inline void
+void
window_box (struct window *w, int area, int *box_x, int *box_y,
int *box_width, int *box_height)
{
return line_top_y + line_height;
}
+/* Subroutine of pos_visible_p below. Extracts a display string, if
+ any, from the display spec given as its argument. */
+static Lisp_Object
+string_from_display_spec (Lisp_Object spec)
+{
+ if (CONSP (spec))
+ {
+ while (CONSP (spec))
+ {
+ if (STRINGP (XCAR (spec)))
+ return XCAR (spec);
+ spec = XCDR (spec);
+ }
+ }
+ else if (VECTORP (spec))
+ {
+ ptrdiff_t i;
+
+ for (i = 0; i < ASIZE (spec); i++)
+ {
+ if (STRINGP (AREF (spec, i)))
+ return AREF (spec, i);
+ }
+ return Qnil;
+ }
+
+ return spec;
+}
/* Return 1 if position CHARPOS is visible in window W.
CHARPOS < 0 means return info about WINDOW_END position.
}
}
}
+ else if (IT_CHARPOS (it) != charpos)
+ {
+ Lisp_Object cpos = make_number (charpos);
+ Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
+ Lisp_Object string = string_from_display_spec (spec);
+ int newline_in_string = 0;
+
+ if (STRINGP (string))
+ {
+ const char *s = SSDATA (string);
+ const char *e = s + SBYTES (string);
+ while (s < e)
+ {
+ if (*s++ == '\n')
+ {
+ newline_in_string = 1;
+ break;
+ }
+ }
+ }
+ /* The tricky code below is needed because there's a
+ discrepancy between move_it_to and how we set cursor
+ when the display line ends in a newline from a
+ display string. move_it_to will stop _after_ such
+ display strings, whereas set_cursor_from_row
+ conspires with cursor_row_p to place the cursor on
+ the first glyph produced from the display string. */
+
+ /* We have overshoot PT because it is covered by a
+ display property whose value is a string. If the
+ string includes embedded newlines, we are also in the
+ wrong display line. Backtrack to the correct line,
+ where the display string begins. */
+ if (newline_in_string)
+ {
+ Lisp_Object startpos, endpos;
+ EMACS_INT start, end;
+ struct it it3;
+
+ /* Find the first and the last buffer positions
+ covered by the display string. */
+ endpos =
+ Fnext_single_char_property_change (cpos, Qdisplay,
+ Qnil, Qnil);
+ startpos =
+ Fprevious_single_char_property_change (endpos, Qdisplay,
+ Qnil, Qnil);
+ start = XFASTINT (startpos);
+ end = XFASTINT (endpos);
+ /* Move to the last buffer position before the
+ display property. */
+ start_display (&it3, w, top);
+ move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
+ /* Move forward one more line if the position before
+ the display string is a newline or if it is the
+ rightmost character on a line that is
+ continued or word-wrapped. */
+ if (it3.method == GET_FROM_BUFFER
+ && it3.c == '\n')
+ move_it_by_lines (&it3, 1);
+ else if (move_it_in_display_line_to (&it3, -1,
+ it3.current_x
+ + it3.pixel_width,
+ MOVE_TO_X)
+ == MOVE_LINE_CONTINUED)
+ {
+ move_it_by_lines (&it3, 1);
+ /* When we are under word-wrap, the #$@%!
+ move_it_by_lines moves 2 lines, so we need to
+ fix that up. */
+ if (it3.line_wrap == WORD_WRAP)
+ move_it_by_lines (&it3, -1);
+ }
+
+ /* Record the vertical coordinate of the display
+ line where we wound up. */
+ top_y = it3.current_y;
+ if (it3.bidi_p)
+ {
+ /* When characters are reordered for display,
+ the character displayed to the left of the
+ display string could be _after_ the display
+ property in the logical order. Use the
+ smallest vertical position of these two. */
+ start_display (&it3, w, top);
+ move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
+ if (it3.current_y < top_y)
+ top_y = it3.current_y;
+ }
+ /* Move from the top of the window to the beginning
+ of the display line where the display string
+ begins. */
+ start_display (&it3, w, top);
+ move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
+ /* Finally, advance the iterator until we hit the
+ first display element whose character position is
+ CHARPOS, or until the first newline from the
+ display string, which signals the end of the
+ display line. */
+ while (get_next_display_element (&it3))
+ {
+ PRODUCE_GLYPHS (&it3);
+ if (IT_CHARPOS (it3) == charpos
+ || ITERATOR_AT_END_OF_LINE_P (&it3))
+ break;
+ set_iterator_to_next (&it3, 0);
+ }
+ top_x = it3.current_x - it3.pixel_width;
+ /* Normally, we would exit the above loop because we
+ found the display element whose character
+ position is CHARPOS. For the contingency that we
+ didn't, and stopped at the first newline from the
+ display string, move back over the glyphs
+ produced from the string, until we find the
+ rightmost glyph not from the string. */
+ if (IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
+ {
+ struct glyph *g = it3.glyph_row->glyphs[TEXT_AREA]
+ + it3.glyph_row->used[TEXT_AREA];
+
+ while (EQ ((g - 1)->object, string))
+ {
+ --g;
+ top_x -= g->pixel_width;
+ }
+ xassert (g < it3.glyph_row->glyphs[TEXT_AREA]
+ + it3.glyph_row->used[TEXT_AREA]);
+ }
+ }
+ }
*x = top_x;
*y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
environments with anti-aliased text: if the same text is
drawn onto the same place multiple times, it gets thicker.
If the overlap we are processing is for the erased cursor, we
- take the intersection with the rectagle of the cursor. */
+ take the intersection with the rectangle of the cursor. */
if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
{
XRectangle rc, r_save = r;
/* Do we need to reorder bidirectional text? Not if this is a
unibyte buffer: by definition, none of the single-byte
characters are strong R2L, so no reordering is needed. And
- bidi.c doesn't support unibyte buffers anyway. */
+ bidi.c doesn't support unibyte buffers anyway. Also, don't
+ reorder while we are loading loadup.el, since the tables of
+ character properties needed for reordering are not yet
+ available. */
it->bidi_p =
- !NILP (BVAR (current_buffer, bidi_display_reordering))
+ NILP (Vpurify_flag)
+ && !NILP (BVAR (current_buffer, bidi_display_reordering))
&& it->multibyte_p;
/* If we are to reorder bidirectional text, init the bidi
|| (new_x == it->last_visible_x
&& FRAME_WINDOW_P (it->f))))
{
- if (it->current.dpvec_index >= 0
- || it->current.overlay_string_index >= 0)
+ if ((it->current.dpvec_index >= 0
+ || it->current.overlay_string_index >= 0)
+ /* If we are on a newline from a display vector or
+ overlay string, then we are already at the end of
+ a screen line; no need to go to the next line in
+ that case, as this line is not really continued.
+ (If we do go to the next line, C-e will not DTRT.) */
+ && it->c != '\n')
{
set_iterator_to_next (it, 1);
move_it_in_display_line_to (it, -1, -1, 0);
it->continuation_lines_width += it->current_x;
}
+ /* If the character at POS is displayed via a display
+ vector, move_it_to above stops at the final glyph of
+ IT->dpvec. To make the caller redisplay that character
+ again (a.k.a. start at POS), we need to reset the
+ dpvec_index to the beginning of IT->dpvec. */
+ else if (it->current.dpvec_index >= 0)
+ it->current.dpvec_index = 0;
/* We're starting a new display line, not affected by the
height of the continued line, so clear the appropriate
Lisp_Object object, limit, position;
EMACS_INT charpos, bytepos;
- /* If nowhere else, stop at the end. */
- it->stop_charpos = it->end_charpos;
-
if (STRINGP (it->string))
{
/* Strings are usually short, so don't limit the search for
properties. */
+ it->stop_charpos = it->end_charpos;
object = it->string;
limit = Qnil;
charpos = IT_STRING_CHARPOS (*it);
{
EMACS_INT pos;
+ /* If end_charpos is out of range for some reason, such as a
+ misbehaving display function, rationalize it (Bug#5984). */
+ if (it->end_charpos > ZV)
+ it->end_charpos = ZV;
+ it->stop_charpos = it->end_charpos;
+
/* If next overlay change is in front of the current stop pos
(which is IT->end_charpos), stop there. Note: value of
next_overlay_change is point-max if no overlay change
}
/* Return the character position of the end of the display string that
- started at CHARPOS. A display string is either an overlay with
- `display' property whose value is a string or a `display' text
- property whose value is a string. */
+ started at CHARPOS. If there's no display string at CHARPOS,
+ return -1. A display string is either an overlay with `display'
+ property whose value is a string or a `display' text property whose
+ value is a string. */
EMACS_INT
compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string)
{
if (charpos >= eob || (string->s && !STRINGP (object)))
return eob;
+ /* It could happen that the display property or overlay was removed
+ since we found it in compute_display_string_pos above. One way
+ this can happen is if JIT font-lock was called (through
+ handle_fontified_prop), and jit-lock-functions remove text
+ properties or overlays from the portion of buffer that includes
+ CHARPOS. Muse mode is known to do that, for example. In this
+ case, we return -1 to the caller, to signal that no display
+ string is actually present at CHARPOS. See bidi_fetch_char for
+ how this is handled.
+
+ An alternative would be to never look for display properties past
+ it->stop_charpos. But neither compute_display_string_pos nor
+ bidi_fetch_char that calls it know or care where the next
+ stop_charpos is. */
if (NILP (Fget_char_property (pos, Qdisplay, object)))
- abort ();
+ return -1;
/* Look forward for the first character where the `display' property
changes. */
while (invis_p);
/* The position newpos is now either ZV or on visible text. */
- if (it->bidi_p && newpos < ZV)
+ if (it->bidi_p)
{
- /* With bidi iteration, the region of invisible text
- could start and/or end in the middle of a non-base
- embedding level. Therefore, we need to skip
- invisible text using the bidi iterator, starting at
- IT's current position, until we find ourselves
- outside the invisible text. Skipping invisible text
- _after_ bidi iteration avoids affecting the visual
- order of the displayed text when invisible properties
- are added or removed. */
- if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
+ EMACS_INT bpos = CHAR_TO_BYTE (newpos);
+ int on_newline =
+ bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
+ int after_newline =
+ newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
+
+ /* If the invisible text ends on a newline or on a
+ character after a newline, we can avoid the costly,
+ character by character, bidi iteration to NEWPOS, and
+ instead simply reseat the iterator there. That's
+ because all bidi reordering information is tossed at
+ the newline. This is a big win for modes that hide
+ complete lines, like Outline, Org, etc. */
+ if (on_newline || after_newline)
{
- /* If we were `reseat'ed to a new paragraph,
- determine the paragraph base direction. We need
- to do it now because next_element_from_buffer may
- not have a chance to do it, if we are going to
- skip any text at the beginning, which resets the
- FIRST_ELT flag. */
- bidi_paragraph_init (it->paragraph_embedding,
- &it->bidi_it, 1);
+ struct text_pos tpos;
+ bidi_dir_t pdir = it->bidi_it.paragraph_dir;
+
+ SET_TEXT_POS (tpos, newpos, bpos);
+ reseat_1 (it, tpos, 0);
+ /* If we reseat on a newline/ZV, we need to prep the
+ bidi iterator for advancing to the next character
+ after the newline/EOB, keeping the current paragraph
+ direction (so that PRODUCE_GLYPHS does TRT wrt
+ prepending/appending glyphs to a glyph row). */
+ if (on_newline)
+ {
+ it->bidi_it.first_elt = 0;
+ it->bidi_it.paragraph_dir = pdir;
+ it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
+ it->bidi_it.nchars = 1;
+ it->bidi_it.ch_len = 1;
+ }
}
- do
+ else /* Must use the slow method. */
{
- bidi_move_to_visually_next (&it->bidi_it);
+ /* With bidi iteration, the region of invisible text
+ could start and/or end in the middle of a
+ non-base embedding level. Therefore, we need to
+ skip invisible text using the bidi iterator,
+ starting at IT's current position, until we find
+ ourselves outside of the invisible text.
+ Skipping invisible text _after_ bidi iteration
+ avoids affecting the visual order of the
+ displayed text when invisible properties are
+ added or removed. */
+ if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
+ {
+ /* If we were `reseat'ed to a new paragraph,
+ determine the paragraph base direction. We
+ need to do it now because
+ next_element_from_buffer may not have a
+ chance to do it, if we are going to skip any
+ text at the beginning, which resets the
+ FIRST_ELT flag. */
+ bidi_paragraph_init (it->paragraph_embedding,
+ &it->bidi_it, 1);
+ }
+ do
+ {
+ bidi_move_to_visually_next (&it->bidi_it);
+ }
+ while (it->stop_charpos <= it->bidi_it.charpos
+ && it->bidi_it.charpos < newpos);
+ IT_CHARPOS (*it) = it->bidi_it.charpos;
+ IT_BYTEPOS (*it) = it->bidi_it.bytepos;
+ /* If we overstepped NEWPOS, record its position in
+ the iterator, so that we skip invisible text if
+ later the bidi iteration lands us in the
+ invisible region again. */
+ if (IT_CHARPOS (*it) >= newpos)
+ it->prev_stop = newpos;
}
- while (it->stop_charpos <= it->bidi_it.charpos
- && it->bidi_it.charpos < newpos);
- IT_CHARPOS (*it) = it->bidi_it.charpos;
- IT_BYTEPOS (*it) = it->bidi_it.bytepos;
- /* If we overstepped NEWPOS, record its position in the
- iterator, so that we skip invisible text if later the
- bidi iteration lands us in the invisible region
- again. */
- if (IT_CHARPOS (*it) >= newpos)
- it->prev_stop = newpos;
}
else
{
&& IT_BYTEPOS (*it) == it->bidi_it.bytepos)
|| (STRINGP (it->object)
&& IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
- && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos));
+ && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
+ || (CONSP (it->object) && it->method == GET_FROM_STRETCH));
}
}
it->multibyte_p = multibyte > 0;
/* Bidirectional reordering of strings is controlled by the default
- value of bidi-display-reordering. */
- it->bidi_p = !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
+ value of bidi-display-reordering. Don't try to reorder while
+ loading loadup.el, as the necessary character property tables are
+ not yet available. */
+ it->bidi_p =
+ NILP (Vpurify_flag)
+ && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
if (s == NULL)
{
{
Lisp_Object dv;
struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
- enum { char_is_other = 0, char_is_nbsp, char_is_soft_hyphen }
- nbsp_or_shy = char_is_other;
+ int nonascii_space_p = 0;
+ int nonascii_hyphen_p = 0;
int c = it->c; /* This is the character to display. */
if (! it->multibyte_p && ! ASCII_CHAR_P (c))
goto get_next;
}
+ /* If `nobreak-char-display' is non-nil, we display
+ non-ASCII spaces and hyphens specially. */
if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
- nbsp_or_shy = (c == 0xA0 ? char_is_nbsp
- : c == 0xAD ? char_is_soft_hyphen
- : char_is_other);
+ {
+ if (c == 0xA0)
+ nonascii_space_p = 1;
+ else if (c == 0xAD || c == 0x2010 || c == 0x2011)
+ nonascii_hyphen_p = 1;
+ }
/* Translate control characters into `\003' or `^C' form.
Control characters coming from a display table entry are
the translation. This could easily be changed but I
don't believe that it is worth doing.
- NBSP and SOFT-HYPEN are property translated too.
+ The characters handled by `nobreak-char-display' must be
+ translated too.
Non-printable characters and raw-byte characters are also
translated to octal form. */
&& it->glyph_row
&& (it->glyph_row->mode_line_p || it->avoid_cursor_p))
|| (c != '\n' && c != '\t'))
- : (nbsp_or_shy
+ : (nonascii_space_p
+ || nonascii_hyphen_p
|| CHAR_BYTE8_P (c)
|| ! CHAR_PRINTABLE_P (c))))
{
- /* C is a control character, NBSP, SOFT-HYPEN, raw-byte,
- or a non-printable character which must be displayed
- either as '\003' or as `^C' where the '\\' and '^'
- can be defined in the display table. Fill
+ /* C is a control character, non-ASCII space/hyphen,
+ raw-byte, or a non-printable character which must be
+ displayed either as '\003' or as `^C' where the '\\'
+ and '^' can be defined in the display table. Fill
IT->ctl_chars with glyphs for what we have to
display. Then, set IT->dpvec to these glyphs. */
Lisp_Object gc;
goto display_control;
}
- /* Handle non-break space in the mode where it only gets
+ /* Handle non-ascii space in the mode where it only gets
highlighting. */
- if (EQ (Vnobreak_char_display, Qt)
- && nbsp_or_shy == char_is_nbsp)
+ if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
{
- /* Merge the no-break-space face into the current face. */
+ /* Merge `nobreak-space' into the current face. */
face_id = merge_faces (it->f, Qnobreak_space, 0,
it->face_id);
-
- c = ' ';
XSETINT (it->ctl_chars[0], ' ');
ctl_len = 1;
goto display_control;
last_escape_glyph_merged_face_id = face_id;
}
- /* Handle soft hyphens in the mode where they only get
- highlighting. */
+ /* Draw non-ASCII hyphen with just highlighting: */
- if (EQ (Vnobreak_char_display, Qt)
- && nbsp_or_shy == char_is_soft_hyphen)
+ if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
{
XSETINT (it->ctl_chars[0], '-');
ctl_len = 1;
goto display_control;
}
- /* Handle non-break space and soft hyphen
- with the escape glyph. */
+ /* Draw non-ASCII space/hyphen with escape glyph: */
- if (nbsp_or_shy)
+ if (nonascii_space_p || nonascii_hyphen_p)
{
XSETINT (it->ctl_chars[0], escape_glyph);
- c = (nbsp_or_shy == char_is_nbsp ? ' ' : '-');
- XSETINT (it->ctl_chars[1], c);
+ XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
ctl_len = 2;
goto display_control;
}
}
else if (it->bidi_it.charpos == bob
|| (!string_p
- /* FIXME: Should support all Unicode line separators. */
&& (FETCH_CHAR (it->bidi_it.bytepos - 1) == '\n'
|| FETCH_CHAR (it->bidi_it.bytepos) == '\n')))
{
((op & MOVE_TO_POS) != 0 \
&& BUFFERP (it->object) \
&& (IT_CHARPOS (*it) == to_charpos \
- || (!it->bidi_p && IT_CHARPOS (*it) > to_charpos) \
+ || ((!it->bidi_p \
+ || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
+ && IT_CHARPOS (*it) > to_charpos) \
|| (it->what == IT_COMPOSITION \
&& ((IT_CHARPOS (*it) > to_charpos \
&& to_charpos >= it->cmp_it.charpos) \
if ((op & MOVE_TO_POS) != 0
&& BUFFERP (it->object)
&& it->method == GET_FROM_BUFFER
- && ((!it->bidi_p && IT_CHARPOS (*it) > to_charpos)
+ && (((!it->bidi_p
+ /* When the iterator is at base embedding level, we
+ are guaranteed that characters are delivered for
+ display in strictly increasing order of their
+ buffer positions. */
+ || BIDI_AT_BASE_LEVEL (it->bidi_it))
+ && IT_CHARPOS (*it) > to_charpos)
|| (it->bidi_p
&& (prev_method == GET_FROM_IMAGE
|| prev_method == GET_FROM_STRETCH
move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
MOVE_TO_POS | MOVE_TO_VPOS);
}
- while (!IT_POS_VALID_AFTER_MOVE_P (&it2));
+ while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
+ /* If we are in a display string which starts at START_POS,
+ and that display string includes a newline, and we are
+ right after that newline (i.e. at the beginning of a
+ display line), exit the loop, because otherwise we will
+ infloop, since move_it_to will see that it is already at
+ START_POS and will not move. */
+ || (it2.method == GET_FROM_STRING
+ && IT_CHARPOS (it2) == start_pos
+ && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
xassert (IT_CHARPOS (*it) >= BEGV);
SAVE_IT (it3, it2, it3data);
reordering. We want to get to the character position
that is immediately after the newline of the previous
line. */
- if (it->bidi_p && IT_CHARPOS (*it) > BEGV
+ if (it->bidi_p
+ && !it->continuation_lines_width
+ && !STRINGP (it->string)
+ && IT_CHARPOS (*it) > BEGV
&& FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
{
EMACS_INT nl_pos =
}
-/* Push the current message on Vmessage_stack for later restauration
+/* Push the current message on Vmessage_stack for later restoration
by restore_message. Value is non-zero if the current message isn't
empty. This is a relatively infrequent operation, so it's not
worth optimizing. */
= (desired_cursor_row->enabled_p
? desired_cursor_row
: current_cursor_row);
+ int row_r2l_p = cursor_row->reversed_p;
text_area_width = window_box_width (w, TEXT_AREA);
h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->buffer))
- && ((XFASTINT (w->hscroll)
- && w->cursor.x <= h_margin)
- || (cursor_row->enabled_p
- && cursor_row->truncated_on_right_p
- && (w->cursor.x >= text_area_width - h_margin))))
+ /* For left-to-right rows, hscroll when cursor is either
+ (i) inside the right hscroll margin, or (ii) if it is
+ inside the left margin and the window is already
+ hscrolled. */
+ && ((!row_r2l_p
+ && ((XFASTINT (w->hscroll)
+ && w->cursor.x <= h_margin)
+ || (cursor_row->enabled_p
+ && cursor_row->truncated_on_right_p
+ && (w->cursor.x >= text_area_width - h_margin))))
+ /* For right-to-left rows, the logic is similar,
+ except that rules for scrolling to left and right
+ are reversed. E.g., if cursor.x <= h_margin, we
+ need to hscroll "to the right" unconditionally,
+ and that will scroll the screen to the left so as
+ to reveal the next portion of the row. */
+ || (row_r2l_p
+ && ((cursor_row->enabled_p
+ /* FIXME: It is confusing to set the
+ truncated_on_right_p flag when R2L rows
+ are actually truncated on the left. */
+ && cursor_row->truncated_on_right_p
+ && w->cursor.x <= h_margin)
+ || (XFASTINT (w->hscroll)
+ && (w->cursor.x >= text_area_width - h_margin))))))
{
struct it it;
int hscroll;
? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
: (text_area_width / 2))))
/ FRAME_COLUMN_WIDTH (it.f);
- else if (w->cursor.x >= text_area_width - h_margin)
+ else if ((!row_r2l_p
+ && w->cursor.x >= text_area_width - h_margin)
+ || (row_r2l_p && w->cursor.x <= h_margin))
{
if (hscroll_relative_p)
wanted_x = text_area_width * (1 - hscroll_step_rel)
/* Non-zero means we've seen at least one glyph that came from a
display string. */
int string_seen = 0;
- /* Largest and smalles buffer positions seen so far during scan of
+ /* Largest and smallest buffer positions seen so far during scan of
glyph row. */
EMACS_INT bpos_max = pos_before;
EMACS_INT bpos_min = pos_after;
glyph--;
}
}
- else if (match_with_avoid_cursor
- /* A truncated row may not include PT among its
- character positions. Setting the cursor inside the
- scroll margin will trigger recalculation of hscroll
- in hscroll_window_tree. But if a display string
- covers point, defer to the string-handling code
- below to figure this out. */
- || (!string_seen
- && ((row->truncated_on_left_p && pt_old < bpos_min)
- || (row->truncated_on_right_p && pt_old > bpos_max)
- /* Zero-width characters produce no glyphs. */
- || (!empty_line_p
- && (row->reversed_p
- ? glyph_after > glyphs_end
- : glyph_after < glyphs_end)))))
+ else if (match_with_avoid_cursor)
{
cursor = glyph_after;
x = -1;
&& row->continued_p)
return 0;
}
+ /* A truncated row may not include PT among its character positions.
+ Setting the cursor inside the scroll margin will trigger
+ recalculation of hscroll in hscroll_window_tree. But if a
+ display string covers point, defer to the string-handling
+ code below to figure this out. */
+ else if (row->truncated_on_left_p && pt_old < bpos_min)
+ {
+ cursor = glyph_before;
+ x = -1;
+ }
+ else if ((row->truncated_on_right_p && pt_old > bpos_max)
+ /* Zero-width characters produce no glyphs. */
+ || (!empty_line_p
+ && (row->reversed_p
+ ? glyph_after > glyphs_end
+ : glyph_after < glyphs_end)))
+ {
+ cursor = glyph_after;
+ x = -1;
+ }
}
compute_x:
|| (STRINGP (g1->object)
&& (!NILP (Fget_char_property (make_number (g1->charpos),
Qcursor, g1->object))
- /* pevious candidate is from the same display
+ /* previous candidate is from the same display
string as this one, and the display string
came from a text property */
|| (EQ (g1->object, glyph->object)
{
int scroll_margin_y;
- /* Compute the pixel ypos of the scroll margin, then move it to
+ /* Compute the pixel ypos of the scroll margin, then move IT to
either that ypos or PT, whichever comes first. */
start_display (&it, w, startp);
scroll_margin_y = it.last_visible_y - this_scroll_margin
if (dy > scroll_max)
return SCROLLING_FAILED;
- scroll_down_p = 1;
+ if (dy > 0)
+ scroll_down_p = 1;
}
}
bidi-reordered rows. */
while (MATRIX_ROW_CONTINUATION_LINE_P (row))
{
- xassert (row->enabled_p);
- --row;
/* If we hit the beginning of the displayed portion
without finding the first row of a continued
line, give up. */
rc = CURSOR_MOVEMENT_MUST_SCROLL;
break;
}
-
+ xassert (row->enabled_p);
+ --row;
}
}
if (must_scroll)
int current_matrix_up_to_date_p = 0;
int used_current_matrix_p = 0;
/* This is less strict than current_matrix_up_to_date_p.
- It indictes that the buffer contents and narrowing are unchanged. */
+ It indicates that the buffer contents and narrowing are unchanged. */
int buffer_unchanged_p = 0;
int temp_scroll_step = 0;
int count = SPECPDL_INDEX ();
? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
: 0;
EMACS_INT margin_pos = CHARPOS (startp);
- int scrolling_up;
Lisp_Object aggressive;
+ int scrolling_up;
/* If there is a scroll margin at the top of the window, find
its character position. */
pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
if (pt_offset == 0 && float_amount > 0)
pt_offset = 1;
- if (pt_offset)
+ if (pt_offset && margin > 0)
margin -= 1;
}
/* Compute how much to move the window start backward from
goto recenter;
}
+ /* Users who set scroll-conservatively to a large number want
+ point just above/below the scroll margin. If we ended up
+ with point's row partially visible, move the window start to
+ make that row fully visible and out of the margin. */
+ if (scroll_conservatively > SCROLL_LIMIT)
+ {
+ int margin =
+ scroll_margin > 0
+ ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
+ : 0;
+ int move_down = w->cursor.vpos >= WINDOW_TOTAL_LINES (w) / 2;
+
+ move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
+ clear_glyph_matrix (w->desired_matrix);
+ if (1 == try_window (window, it.current.pos,
+ TRY_WINDOW_CHECK_MARGINS))
+ goto done;
+ }
+
/* If centering point failed to make the whole line visible,
put point at the top instead. That has to make the whole line
visible, if it can be done. */
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))
+ /* If we have reached alignment, we can copy the rest of the
+ rows. */
+ if (IT_CHARPOS (it) == CHARPOS (start)
+ /* Don't accept "alignment" inside a display vector,
+ since start_row could have started in the middle of
+ that same display vector (thus their character
+ positions match), and we have no way of telling if
+ that is the case. */
+ && it.current.dpvec_index < 0)
break;
if (display_line (&it))
last_text_row = it.glyph_row - 1;
+
}
/* A value of current_y < last_visible_y means that we stopped
last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
if (last_unchanged_at_beg_row)
{
- /* Avoid starting to display in the moddle of a character, a TAB
+ /* Avoid starting to display in the middle of a character, a TAB
for instance. This is easier than to set up the iterator
exactly, and it's not a frequent case, so the additional
effort wouldn't really pay off. */
}
}
+/* Compute the hash code for ROW. */
+unsigned
+row_hash (struct glyph_row *row)
+{
+ int area, k;
+ unsigned hashval = 0;
+
+ for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
+ for (k = 0; k < row->used[area]; ++k)
+ hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
+ + row->glyphs[area][k].u.val
+ + row->glyphs[area][k].face_id
+ + row->glyphs[area][k].padding_p
+ + (row->glyphs[area][k].type << 2));
+
+ return hashval;
+}
/* Compute the pixel height and width of IT->glyph_row.
}
/* Compute a hash code for this row. */
- {
- int area, i;
- row->hash = 0;
- for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
- for (i = 0; i < row->used[area]; ++i)
- row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
- + row->glyphs[area][i].u.val
- + row->glyphs[area][i].face_id
- + row->glyphs[area][i].padding_p
- + (row->glyphs[area][i].type << 2));
- }
+ row->hash = row_hash (row);
it->max_ascent = it->max_descent = 0;
it->max_phys_ascent = it->max_phys_descent = 0;
push_display_prop (struct it *it, Lisp_Object prop)
{
struct text_pos pos =
- (it->method == GET_FROM_STRING) ? it->current.string_pos : it->current.pos;
+ STRINGP (it->string) ? it->current.string_pos : it->current.pos;
xassert (it->method == GET_FROM_BUFFER
+ || it->method == GET_FROM_DISPLAY_VECTOR
|| it->method == GET_FROM_STRING);
/* We need to save the current buffer/string position, so it will be
seen_this_string = 1;
}
else
- abort ();
+ /* If all the glyphs of the previous row were inserted
+ by redisplay, it means the previous row was
+ produced from a single newline, which is only
+ possible if that newline came from the same string
+ as the one which produced this ROW. */
+ seen_this_string = 1;
}
else
{
seen_this_string = 1;
}
else
- abort ();
+ seen_this_string = 1;
}
}
/* Take note of each display string that covers a newline only
#define RECORD_MAX_MIN_POS(IT) \
do \
{ \
- int composition_p = (IT)->what == IT_COMPOSITION; \
+ int composition_p = !STRINGP ((IT)->string) \
+ && ((IT)->what == IT_COMPOSITION); \
EMACS_INT current_pos = \
composition_p ? (IT)->cmp_it.charpos \
: IT_CHARPOS (*(IT)); \
overlay_arrow_seen = 1;
}
+ /* Highlight trailing whitespace. */
+ if (!NILP (Vshow_trailing_whitespace))
+ highlight_trailing_whitespace (it->f, it->glyph_row);
+
/* Compute pixel dimensions of this line. */
compute_line_metrics (it);
+ /* Implementation note: No changes in the glyphs of ROW or in their
+ faces can be done past this point, because compute_line_metrics
+ computes ROW's hash value and stores it within the glyph_row
+ structure. */
+
/* Record whether this row ends inside an ellipsis. */
row->ends_in_ellipsis_p
= (it->method == GET_FROM_DISPLAY_VECTOR
&& cursor_row_p (row))
set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
- /* Highlight trailing whitespace. */
- if (!NILP (Vshow_trailing_whitespace))
- highlight_trailing_whitespace (it->f, it->glyph_row);
-
/* Prepare for the next line. This line starts horizontally at (X
HPOS) = (0 0). Vertical positions are incremented. As a
convenience for the caller, IT->glyph_row is set to the next
}
if (NILP (BVAR (buf, bidi_display_reordering))
- || NILP (BVAR (buf, enable_multibyte_characters)))
+ || NILP (BVAR (buf, enable_multibyte_characters))
+ /* When we are loading loadup.el, the character property tables
+ needed for bidi iteration are not yet available. */
+ || !NILP (Vpurify_flag))
return Qleft_to_right;
else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
return BVAR (buf, bidi_paragraph_direction);
EMACS_INT pos = BUF_PT (buf);
EMACS_INT bytepos = BUF_PT_BYTE (buf);
int c;
+ void *itb_data = bidi_shelve_cache ();
set_buffer_temp (buf);
/* bidi_paragraph_init finds the base direction of the paragraph
pos--;
bytepos = CHAR_TO_BYTE (pos);
}
- while ((c = FETCH_BYTE (bytepos)) == '\n'
- || c == ' ' || c == '\t' || c == '\f')
+ if (fast_looking_at (build_string ("[\f\t ]*\n"),
+ pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
{
- if (bytepos <= BEGV_BYTE)
- break;
- bytepos--;
- pos--;
+ while ((c = FETCH_BYTE (bytepos)) == '\n'
+ || c == ' ' || c == '\t' || c == '\f')
+ {
+ if (bytepos <= BEGV_BYTE)
+ break;
+ bytepos--;
+ pos--;
+ }
+ while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
+ bytepos--;
}
- while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
- bytepos--;
- itb.charpos = pos;
- itb.bytepos = bytepos;
- itb.nchars = -1;
+ bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
+ itb.paragraph_dir = NEUTRAL_DIR;
itb.string.s = NULL;
itb.string.lstring = Qnil;
- itb.frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ()); /* guesswork */
- itb.first_elt = 1;
- itb.separator_limit = -1;
- itb.paragraph_dir = NEUTRAL_DIR;
-
+ itb.string.bufpos = 0;
+ itb.string.unibyte = 0;
bidi_paragraph_init (NEUTRAL_DIR, &itb, 1);
+ bidi_unshelve_cache (itb_data, 0);
set_buffer_temp (old);
switch (itb.paragraph_dir)
{
/* Get glyph code of character C in FONT in the two-byte form CHAR2B.
- Retunr 1 if FONT has a glyph for C, otherwise return 0. */
+ Return 1 if FONT has a glyph for C, otherwise return 0. */
static inline int
get_char_glyph_code (int c, struct font *font, XChar2b *char2b)
}
s->cmp_to = i;
+ if (s->face == NULL)
+ {
+ s->face = base_face->ascii_face;
+ s->font = s->face->font;
+ }
+
/* All glyph strings for the same composition has the same width,
i.e. the width set for the first component of the composition. */
s->width = s->first_glyph->pixel_width;
{
width = it->last_visible_x - it->current_x;
#ifdef HAVE_WINDOW_SYSTEM
- /* Subtact one more pixel from the stretch width, but only on
+ /* Subtract one more pixel from the stretch width, but only on
GUI frames, since on a TTY each glyph is one "pixel" wide. */
width -= FRAME_WINDOW_P (it->f);
#endif
void
x_write_glyphs (struct glyph *start, int len)
{
- int x, hpos;
+ int x, hpos, chpos = updated_window->phys_cursor.hpos;
xassert (updated_window && updated_row);
+ /* When the window is hscrolled, cursor hpos can legitimately be out
+ of bounds, but we draw the cursor at the corresponding window
+ margin in that case. */
+ if (!updated_row->reversed_p && chpos < 0)
+ chpos = 0;
+ if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
+ chpos = updated_row->used[TEXT_AREA] - 1;
+
BLOCK_INPUT;
/* Write glyphs. */
if (updated_area == TEXT_AREA
&& updated_window->phys_cursor_on_p
&& updated_window->phys_cursor.vpos == output_cursor.vpos
- && updated_window->phys_cursor.hpos >= hpos
- && updated_window->phys_cursor.hpos < hpos + len)
+ && chpos >= hpos
+ && chpos < hpos + len)
updated_window->phys_cursor_on_p = 0;
UNBLOCK_INPUT;
{
int on_p = w->phys_cursor_on_p;
int x1;
- x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
- w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
+ int hpos = w->phys_cursor.hpos;
+
+ /* When the window is hscrolled, cursor hpos can legitimately be
+ out of bounds, but we draw the cursor at the corresponding
+ window margin in that case. */
+ if (!row->reversed_p && hpos < 0)
+ hpos = 0;
+ if (row->reversed_p && hpos >= row->used[TEXT_AREA])
+ hpos = row->used[TEXT_AREA] - 1;
+
+ x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
hl, 0);
w->phys_cursor_on_p = on_p;
: (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
goto mark_cursor_off;
+ /* When the window is hscrolled, cursor hpos can legitimately be out
+ of bounds, but we draw the cursor at the corresponding window
+ margin in that case. */
+ if (!cursor_row->reversed_p && hpos < 0)
+ hpos = 0;
+ if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
+ hpos = cursor_row->used[TEXT_AREA] - 1;
+
/* If the cursor is in the mouse face area, redisplay that when
we clear the cursor. */
if (! NILP (hlinfo->mouse_face_window)
of being deleted. */
if (w->current_matrix)
{
+ int hpos = w->phys_cursor.hpos;
+ int vpos = w->phys_cursor.vpos;
+ struct glyph_row *row;
+
+ if (vpos >= w->current_matrix->nrows
+ || hpos >= w->current_matrix->matrix_w)
+ return;
+
+ row = MATRIX_ROW (w->current_matrix, vpos);
+
+ /* When the window is hscrolled, cursor hpos can legitimately be
+ out of bounds, but we draw the cursor at the corresponding
+ window margin in that case. */
+ if (!row->reversed_p && hpos < 0)
+ hpos = 0;
+ if (row->reversed_p && hpos >= row->used[TEXT_AREA])
+ hpos = row->used[TEXT_AREA] - 1;
+
BLOCK_INPUT;
- display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
+ display_and_set_cursor (w, on, hpos, vpos,
w->phys_cursor.x, w->phys_cursor.y);
UNBLOCK_INPUT;
}
if (FRAME_WINDOW_P (f)
&& phys_cursor_on_p && !w->phys_cursor_on_p)
{
+ int hpos = w->phys_cursor.hpos;
+
+ /* When the window is hscrolled, cursor hpos can legitimately be
+ out of bounds, but we draw the cursor at the corresponding
+ window margin in that case. */
+ if (!row->reversed_p && hpos < 0)
+ hpos = 0;
+ if (row->reversed_p && hpos >= row->used[TEXT_AREA])
+ hpos = row->used[TEXT_AREA] - 1;
+
BLOCK_INPUT;
- display_and_set_cursor (w, 1,
- w->phys_cursor.hpos, w->phys_cursor.vpos,
+ display_and_set_cursor (w, 1, hpos, w->phys_cursor.vpos,
w->phys_cursor.x, w->phys_cursor.y);
UNBLOCK_INPUT;
}
int
cursor_in_mouse_face_p (struct window *w)
{
- return coords_in_mouse_face_p (w, w->phys_cursor.hpos, w->phys_cursor.vpos);
+ int hpos = w->phys_cursor.hpos;
+ int vpos = w->phys_cursor.vpos;
+ struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
+
+ /* When the window is hscrolled, cursor hpos can legitimately be out
+ of bounds, but we draw the cursor at the corresponding window
+ margin in that case. */
+ if (!row->reversed_p && hpos < 0)
+ hpos = 0;
+ if (row->reversed_p && hpos >= row->used[TEXT_AREA])
+ hpos = row->used[TEXT_AREA] - 1;
+
+ return coords_in_mouse_face_p (w, hpos, vpos);
}
for the overlay or run of text properties specifying the mouse
face. BEFORE_STRING and AFTER_STRING, if non-nil, are a
before-string and after-string that must also be highlighted.
- COVER_STRING, if non-nil, is a display string that may cover some
+ DISP_STRING, if non-nil, is a display string that may cover some
or all of the highlighted text. */
static void
EMACS_INT end_charpos,
Lisp_Object before_string,
Lisp_Object after_string,
- Lisp_Object cover_string)
+ Lisp_Object disp_string)
{
struct window *w = XWINDOW (window);
struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
EMACS_INT ignore, pos;
int x;
- xassert (NILP (cover_string) || STRINGP (cover_string));
+ xassert (NILP (disp_string) || STRINGP (disp_string));
xassert (NILP (before_string) || STRINGP (before_string));
xassert (NILP (after_string) || STRINGP (after_string));
r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
/* If the before-string or display-string contains newlines,
rows_from_pos_range skips to its last row. Move back. */
- if (!NILP (before_string) || !NILP (cover_string))
+ if (!NILP (before_string) || !NILP (disp_string))
{
struct glyph_row *prev;
while ((prev = r1 - 1, prev >= first)
while (--glyph >= beg && INTEGERP (glyph->object));
if (glyph < beg
|| !(EQ (glyph->object, before_string)
- || EQ (glyph->object, cover_string)))
+ || EQ (glyph->object, disp_string)))
break;
r1 = prev;
}
r2 = next;
}
/* The rest of the display engine assumes that mouse_face_beg_row is
- either above below mouse_face_end_row or identical to it. But
- with bidi-reordered continued lines, the row for START_CHARPOS
- could be below the row for END_CHARPOS. If so, swap the rows and
- store them in correct order. */
+ either above mouse_face_end_row or identical to it. But with
+ bidi-reordered continued lines, the row for START_CHARPOS could
+ be below the row for END_CHARPOS. If so, swap the rows and store
+ them in correct order. */
if (r1->y > r2->y)
{
struct glyph_row *tem = r2;
hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
/* For a bidi-reordered row, the positions of BEFORE_STRING,
- AFTER_STRING, COVER_STRING, START_CHARPOS, and END_CHARPOS
+ AFTER_STRING, DISP_STRING, START_CHARPOS, and END_CHARPOS
could be anywhere in the row and in any order. The strategy
below is to find the leftmost and the rightmost glyph that
belongs to either of these 3 strings, or whose position is
x += glyph->pixel_width;
/* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING,
- or COVER_STRING, and the first glyph from buffer whose
+ or DISP_STRING, and the first glyph from buffer whose
position is between START_CHARPOS and END_CHARPOS. */
for (; glyph < end
&& !INTEGERP (glyph->object)
- && !EQ (glyph->object, cover_string)
+ && !EQ (glyph->object, disp_string)
&& !(BUFFERP (glyph->object)
&& (glyph->charpos >= start_charpos
&& glyph->charpos < end_charpos));
;
/* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING,
- or COVER_STRING, and the first glyph from buffer whose
+ or DISP_STRING, and the first glyph from buffer whose
position is between START_CHARPOS and END_CHARPOS. */
for (; glyph > end
&& !INTEGERP (glyph->object)
- && !EQ (glyph->object, cover_string)
+ && !EQ (glyph->object, disp_string)
&& !(BUFFERP (glyph->object)
&& (glyph->charpos >= start_charpos
&& glyph->charpos < end_charpos));
row, and also blanks and stretch glyphs inserted by
extend_face_to_end_of_line. */
while (end > glyph
- && INTEGERP ((end - 1)->object)
- && (end - 1)->charpos <= 0)
+ && INTEGERP ((end - 1)->object))
--end;
/* Scan the rest of the glyph row from the end, looking for the
first glyph that comes from BEFORE_STRING, AFTER_STRING, or
- COVER_STRING, or whose position is between START_CHARPOS
+ DISP_STRING, or whose position is between START_CHARPOS
and END_CHARPOS */
for (--end;
end > glyph
&& !INTEGERP (end->object)
- && !EQ (end->object, cover_string)
+ && !EQ (end->object, disp_string)
&& !(BUFFERP (end->object)
&& (end->charpos >= start_charpos
&& end->charpos < end_charpos));
x = r2->x;
end++;
while (end < glyph
- && INTEGERP (end->object)
- && end->charpos <= 0)
+ && INTEGERP (end->object))
{
x += end->pixel_width;
++end;
}
/* Scan the rest of the glyph row from the end, looking for the
first glyph that comes from BEFORE_STRING, AFTER_STRING, or
- COVER_STRING, or whose position is between START_CHARPOS
+ DISP_STRING, or whose position is between START_CHARPOS
and END_CHARPOS */
for ( ;
end < glyph
&& !INTEGERP (end->object)
- && !EQ (end->object, cover_string)
+ && !EQ (end->object, disp_string)
&& !(BUFFERP (end->object)
&& (end->charpos >= start_charpos
&& end->charpos < end_charpos));
note_mouse_highlight (struct frame *f, int x, int y)
{
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
- enum window_part part;
+ enum window_part part = ON_NOTHING;
Lisp_Object window;
struct window *w;
Cursor cursor = No_Cursor;
/* Which window is that in? */
window = window_from_coordinates (f, x, y, &part, 1);
- /* If we were displaying active text in another window, clear that.
- Also clear if we move out of text area in same window. */
+ /* If displaying active text in another window, clear that. */
if (! EQ (window, hlinfo->mouse_face_window)
- || (part != ON_TEXT && part != ON_MODE_LINE && part != ON_HEADER_LINE
- && !NILP (hlinfo->mouse_face_window)))
+ /* Also clear if we move out of text area in same window. */
+ || (!NILP (hlinfo->mouse_face_window)
+ && !NILP (window)
+ && part != ON_TEXT
+ && part != ON_MODE_LINE
+ && part != ON_HEADER_LINE))
clear_mouse_face (hlinfo);
/* Not on a window -> return. */
&& XFASTINT (w->last_modified) == BUF_MODIFF (b)
&& XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
{
- int hpos, vpos, dx, dy, area;
+ int hpos, vpos, dx, dy, area = LAST_AREA;
EMACS_INT pos;
struct glyph *glyph;
Lisp_Object object;
/* The mouse-highlighting, if any, comes from an overlay
or text property in the buffer. */
Lisp_Object buffer IF_LINT (= Qnil);
- Lisp_Object cover_string IF_LINT (= Qnil);
+ Lisp_Object disp_string IF_LINT (= Qnil);
if (STRINGP (object))
{
mouse_face = get_char_property_and_overlay
(make_number (pos), Qmouse_face, w->buffer, &overlay);
buffer = w->buffer;
- cover_string = object;
+ disp_string = object;
}
}
else
{
buffer = object;
- cover_string = Qnil;
+ disp_string = Qnil;
}
if (!NILP (mouse_face))
}
mouse_face_from_buffer_pos (window, hlinfo, pos,
- XFASTINT (before),
- XFASTINT (after),
+ NILP (before)
+ ? 1
+ : XFASTINT (before),
+ NILP (after)
+ ? BUF_Z (XBUFFER (buffer))
+ : XFASTINT (after),
before_string, after_string,
- cover_string);
+ disp_string);
cursor = No_Cursor;
}
}
DEFSYM (Qhollow, "hollow");
DEFSYM (Qhand, "hand");
DEFSYM (Qarrow, "arrow");
- DEFSYM (Qtext, "text");
DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
list_of_error = Fcons (Fcons (intern_c_string ("error"),
Vshow_trailing_whitespace = Qnil;
DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
- doc: /* *Control highlighting of nobreak space and soft hyphen.
-A value of t means highlight the character itself (for nobreak space,
-use face `nobreak-space').
-A value of nil means no highlighting.
-Other values mean display the escape glyph followed by an ordinary
-space or ordinary hyphen. */);
+ doc: /* Control highlighting of non-ASCII space and hyphen chars.
+If the value is t, Emacs highlights non-ASCII chars which have the
+same appearance as an ASCII space or hyphen, using the `nobreak-space'
+or `escape-glyph' face respectively.
+
+U+00A0 (no-break space), U+00AD (soft hyphen), U+2010 (hyphen), and
+U+2011 (non-breaking hyphen) are affected.
+
+Any other non-nil value means to display these characters as a escape
+glyph followed by an ordinary space or hyphen.
+
+A value of nil means no special handling of these characters. */);
Vnobreak_char_display = Qt;
DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
DEFVAR_INT ("overline-margin", overline_margin,
doc: /* *Space between overline and text, in pixels.
The default value is 2: the height of the overline (1 pixel) plus 1 pixel
-margin to the caracter height. */);
+margin to the character height. */);
overline_margin = 2;
DEFVAR_INT ("underline-minimum-offset",
/* Platform-independent portion of hourglass implementation. */
-/* Return non-zero if houglass timer has been started or hourglass is shown. */
+/* Return non-zero if hourglass timer has been started or hourglass is
+ shown. */
int
hourglass_started (void)
{