if (CHARPOS (top) > ZV)
SET_TEXT_POS (top, BEGV, BEGV_BYTE);
+ /* If the top of the window is after CHARPOS, the latter is surely
+ not visible. */
+ if (charpos >= 0 && CHARPOS (top) > charpos)
+ return visible_p;
+
/* Compute exact mode line heights. */
if (WINDOW_WANTS_MODELINE_P (w))
w->mode_line_height
cache and mode line face are not yet initialized. */
if (FRAME_FACE_CACHE (f))
{
- struct face *face = FACE_OPT_FROM_ID (f, face_id);
+ struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
if (face)
{
if (face->font)
/* If we have a boxed mode line, make the first character appear
with a left box line. */
- face = FACE_OPT_FROM_ID (it->f, remapped_base_face_id);
+ face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
if (face && face->box != FACE_NO_BOX)
it->start_of_box_run_p = true;
}
{
struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
/* If it->face_id is -1, old_face below will be NULL, see
- the definition of FACE_OPT_FROM_ID. This will happen if this
- is the initial call that gets the face. */
- struct face *old_face = FACE_OPT_FROM_ID (it->f, it->face_id);
+ the definition of FACE_FROM_ID_OR_NULL. This will happen
+ if this is the initial call that gets the face. */
+ struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
/* If the value of face_id of the iterator is -1, we have to
look in front of IT's position and see whether there is a
{
int prev_face_id = face_before_it_pos (it);
- old_face = FACE_OPT_FROM_ID (it->f, prev_face_id);
+ old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
}
/* If the new face has a box, but the old face does not,
if (new_face_id != it->face_id)
{
struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
- struct face *old_face = FACE_OPT_FROM_ID (it->f, it->face_id);
+ struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
/* If new face has a box but old face hasn't, this is the
start of a run of characters with box, i.e. it has a
|| EQ (XCAR (spec), Qright_fringe))
&& CONSP (XCDR (spec)))
{
- int fringe_bitmap;
-
if (it)
{
if (!FRAME_WINDOW_P (it->f))
#ifdef HAVE_WINDOW_SYSTEM
value = XCAR (XCDR (spec));
- if (!SYMBOLP (value)
- || !(fringe_bitmap = lookup_fringe_bitmap (value)))
+ int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
+ if (! fringe_bitmap)
/* If we return here, POSITION has been advanced
across the text with this property. */
{
break;
case GET_FROM_STRING:
{
- struct face *face = FACE_OPT_FROM_ID (it->f, it->face_id);
+ struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
/* Restore the face_box_p flag, since it could have been
overwritten by the face of the object that we just finished
|| ((IT)->cmp_it.stop_pos == (CHARPOS) \
&& composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
END_CHARPOS, (IT)->w, \
- FACE_OPT_FROM_ID ((IT)->f, (IT)->face_id), \
+ FACE_FROM_ID_OR_NULL ((IT)->f, \
+ (IT)->face_id), \
(IT)->string)))
if (it->method == GET_FROM_STRING && it->sp)
{
int face_id = underlying_face_id (it);
- struct face *face = FACE_OPT_FROM_ID (it->f, face_id);
+ struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
if (face)
{
/* Glyphs in the display vector could have the box face, so we
need to set the related flags in the iterator, as
appropriate. */
- this_face = FACE_OPT_FROM_ID (it->f, it->face_id);
- prev_face = FACE_OPT_FROM_ID (it->f, prev_face_id);
+ this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
+ prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
/* Is this character the first character of a box-face run? */
it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
it->saved_face_id);
}
}
- next_face = FACE_OPT_FROM_ID (it->f, next_face_id);
+ next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
it->end_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
&& (!next_face
|| next_face->box == FACE_NO_BOX));
void *ppos_data = NULL;
bool may_wrap = false;
enum it_method prev_method = it->method;
- ptrdiff_t closest_pos IF_LINT (= 0), prev_pos = IT_CHARPOS (*it);
+ ptrdiff_t closest_pos UNINIT;
+ ptrdiff_t prev_pos = IT_CHARPOS (*it);
bool saw_smaller_pos = prev_pos < to_charpos;
/* Don't produce glyphs in produce_glyphs. */
&& it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
/* If there's a line-/wrap-prefix, handle it. */
- if (it->hpos == 0 && it->method == GET_FROM_BUFFER
- && it->current_y < it->last_visible_y)
+ if (it->hpos == 0 && it->method == GET_FROM_BUFFER)
handle_line_prefix (it);
if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
? WINDOW_LEFT_FRINGE_WIDTH (it->w)
: WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
{
+ bool moved_forward = false;
+
if (/* IT->hpos == 0 means the very first glyph
doesn't fit on the line, e.g. a wide image. */
it->hpos == 0
now that we know it fits in this row. */
if (BUFFER_POS_REACHED_P ())
{
+ bool can_wrap = true;
+
+ /* If we are at a whitespace character
+ that barely fits on this screen line,
+ but the next character is also
+ whitespace, we cannot wrap here. */
+ if (it->line_wrap == WORD_WRAP
+ && wrap_it.sp >= 0
+ && may_wrap
+ && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+ {
+ struct it tem_it;
+ void *tem_data = NULL;
+
+ SAVE_IT (tem_it, *it, tem_data);
+ set_iterator_to_next (it, true);
+ if (get_next_display_element (it)
+ && IT_DISPLAYING_WHITESPACE (it))
+ can_wrap = false;
+ RESTORE_IT (it, &tem_it, tem_data);
+ }
if (it->line_wrap != WORD_WRAP
|| wrap_it.sp < 0
- /* If we've just found whitespace to
- wrap, effectively ignore the
- previous wrap point -- it is no
- longer relevant, but we won't
- have an opportunity to update it,
- since we've reached the edge of
- this screen line. */
- || (may_wrap
+ /* If we've just found whitespace
+ where we can wrap, effectively
+ ignore the previous wrap point --
+ it is no longer relevant, but we
+ won't have an opportunity to
+ update it, since we've reached
+ the edge of this screen line. */
+ || (may_wrap && can_wrap
&& IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
{
it->hpos = hpos_before_this_char;
result = MOVE_POS_MATCH_OR_ZV;
break;
}
+ moved_forward = true;
if (BUFFER_POS_REACHED_P ())
{
if (ITERATOR_AT_END_OF_LINE_P (it))
longer relevant, but we won't have an opportunity
to update it, since we are done with this screen
line. */
- if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+ if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
+ /* If the character after the one which set the
+ may_wrap flag is also whitespace, we can't
+ wrap here, since the screen line cannot be
+ wrapped in the middle of whitespace.
+ Therefore, wrap_it _is_ relevant in that
+ case. */
+ && !(moved_forward && IT_DISPLAYING_WHITESPACE (it)))
{
/* If we've found TO_X, go back there, as we now
know the last word fits on this screen line. */
}
else
result = MOVE_NEWLINE_OR_CR;
+ /* If we've processed the newline, make sure this flag is
+ reset, as it must only be set when the newline itself is
+ processed. */
+ if (result == MOVE_NEWLINE_OR_CR)
+ it->constrain_row_ascent_descent_p = false;
break;
}
#undef BUFFER_POS_REACHED_P
- /* If we scanned beyond to_pos and didn't find a point to wrap at,
- restore the saved iterator. */
- if (atpos_it.sp >= 0)
+ /* If we scanned beyond TO_POS, restore the saved iterator either to
+ the wrap point (if found), or to atpos/atx location. We decide which
+ data to use to restore the saved iterator state by their X coordinates,
+ since buffer positions might increase non-monotonically with screen
+ coordinates due to bidi reordering. */
+ if (result == MOVE_LINE_CONTINUED
+ && it->line_wrap == WORD_WRAP
+ && wrap_it.sp >= 0
+ && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
+ || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
+ RESTORE_IT (it, &wrap_it, wrap_data);
+ else if (atpos_it.sp >= 0)
RESTORE_IT (it, &atpos_it, atpos_data);
else if (atx_it.sp >= 0)
RESTORE_IT (it, &atx_it, atx_data);
it.last_visible_x = max_x;
/* Actually, we never want move_it_to stop at to_x. But to make
sure that move_it_in_display_line_to always moves far enough,
- we set it to INT_MAX and specify MOVE_TO_X. Also bound width
- value by X-LIMIT. */
- x = min (move_it_to (&it, end, INT_MAX, max_y, -1,
- MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y),
- max_x);
+ we set it to INT_MAX and specify MOVE_TO_X. */
+ x = move_it_to (&it, end, INT_MAX, max_y, -1,
+ MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+ /* Don't return more than X-LIMIT. */
+ if (x > max_x)
+ x = max_x;
}
/* Subtract height of header-line which was counted automatically by
start_display. */
- y = min (it.current_y + it.max_ascent + it.max_descent
- - WINDOW_HEADER_LINE_HEIGHT (w),
- max_y);
+ y = it.current_y + it.max_ascent + it.max_descent
+ - WINDOW_HEADER_LINE_HEIGHT (w);
+ /* Don't return more than Y-LIMIT. */
+ if (y > max_y)
+ y = max_y;
if (EQ (mode_and_header_line, Qheader_line)
|| EQ (mode_and_header_line, Qt))
The new window start will be computed, based on W's width, starting
from the start of the continued line. It is the start of the
- screen line with the minimum distance from the old start W->start. */
+ screen line with the minimum distance from the old start W->start,
+ which is still before point (otherwise point will definitely not
+ be visible in the window). */
static bool
compute_window_start_on_continuation_line (struct window *w)
{
- struct text_pos pos, start_pos;
+ struct text_pos pos, start_pos, pos_before_pt;
bool window_start_changed_p = false;
SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
reseat_at_previous_visible_line_start (&it);
/* If the line start is "too far" away from the window start,
- say it takes too much time to compute a new window start. */
- if (CHARPOS (start_pos) - IT_CHARPOS (it)
- /* PXW: Do we need upper bounds here? */
- < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))
+ say it takes too much time to compute a new window start.
+ Also, give up if the line start is after point, as in that
+ case point will not be visible with any window start we
+ compute. */
+ if (IT_CHARPOS (it) <= PT
+ || (CHARPOS (start_pos) - IT_CHARPOS (it)
+ /* PXW: Do we need upper bounds here? */
+ < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
{
int min_distance, distance;
decreased, the new window start will be < the old start.
So, we're looking for the display line start with the
minimum distance from the old window start. */
- pos = it.current.pos;
+ pos_before_pt = pos = it.current.pos;
min_distance = INFINITY;
while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
distance < min_distance)
{
min_distance = distance;
+ if (CHARPOS (pos) <= PT)
+ pos_before_pt = pos;
pos = it.current.pos;
if (it.line_wrap == WORD_WRAP)
{
move_it_by_lines (&it, 1);
}
+ /* It makes very little sense to make the new window start
+ after point, as point won't be visible. If that's what
+ the loop above finds, fall back on the candidate before
+ or at point that is closest to the old window start. */
+ if (CHARPOS (pos) > PT)
+ pos = pos_before_pt;
+
/* Set the window start there. */
SET_MARKER_FROM_TEXT_POS (w->start, pos);
window_start_changed_p = true;
struct text_pos saved_pos;
Lisp_Object saved_object;
struct face *face;
- struct glyph *g;
saved_object = it->object;
saved_pos = it->position;
/* Make sure this space glyph has the right ascent and
descent values, or else cursor at end of line will look
funny, and height of empty lines will be incorrect. */
- g = it->glyph_row->glyphs[TEXT_AREA] + n;
+ struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
struct font *font = face->font ? face->font : FRAME_FONT (it->f);
if (n == 0)
{
return;
/* The default face, possibly remapped. */
- default_face = FACE_OPT_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID));
+ default_face = FACE_FROM_ID_OR_NULL (f,
+ lookup_basic_face (f, DEFAULT_FACE_ID));
/* Face extension extends the background and box of IT->face_id
to the end of the line. If the background equals the background
of the frame, we don't have to do anything. */
- face = FACE_OPT_FROM_ID (f, (it->face_before_selective_p
- ? it->face_id
- : it->saved_face_id));
+ face = FACE_FROM_ID (f, (it->face_before_selective_p
+ ? it->saved_face_id
+ : it->face_id));
if (FRAME_WINDOW_P (f)
&& MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
struct it wrap_it;
void *wrap_data = NULL;
bool may_wrap = false;
- int wrap_x IF_LINT (= 0);
+ int wrap_x UNINIT;
int wrap_row_used = -1;
- int wrap_row_ascent IF_LINT (= 0), wrap_row_height IF_LINT (= 0);
- int wrap_row_phys_ascent IF_LINT (= 0), wrap_row_phys_height IF_LINT (= 0);
- int wrap_row_extra_line_spacing IF_LINT (= 0);
- ptrdiff_t wrap_row_min_pos IF_LINT (= 0), wrap_row_min_bpos IF_LINT (= 0);
- ptrdiff_t wrap_row_max_pos IF_LINT (= 0), wrap_row_max_bpos IF_LINT (= 0);
+ int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
+ int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
+ int wrap_row_extra_line_spacing UNINIT;
+ ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
+ ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
int cvpos;
ptrdiff_t min_pos = ZV + 1, max_pos = 0;
- ptrdiff_t min_bpos IF_LINT (= 0), max_bpos IF_LINT (= 0);
+ ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
bool pending_handle_line_prefix = false;
/* We always start displaying at hpos zero even if hscrolled. */
}
/* Move to the target X coordinate. */
-#ifdef HAVE_WINDOW_SYSTEM
/* On GUI frames, as we don't know the X coordinate of the
character to the left of point, moving point to the left
requires walking, one grapheme cluster at a time, until we
new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
it.current.pos = new_pos;
}
- else
-#endif
- if (it.current_x != target_x)
+ else if (it.current_x != target_x)
move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
/* If we ended up in a display string that covers point, move to
s->cmp_id = glyph->u.cmp.id;
s->cmp_from = glyph->slice.cmp.from;
s->cmp_to = glyph->slice.cmp.to + 1;
- s->face = FACE_OPT_FROM_ID (s->f, face_id);
+ s->face = FACE_FROM_ID (s->f, face_id);
lgstring = composition_gstring_from_id (s->cmp_id);
s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
glyph++;
{
eassert (s->first_glyph->type == IMAGE_GLYPH);
s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
+ eassert (s->img);
s->slice = s->first_glyph->slice.img;
s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
s->font = s->face->font;
#define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
do { \
int face_id = (row)->glyphs[area][START].face_id; \
- struct face *base_face = FACE_OPT_FROM_ID (f, face_id); \
+ struct face *base_face = FACE_FROM_ID (f, face_id); \
ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
struct composition *cmp = composition_table[cmp_id]; \
XChar2b *char2b; \
{
struct glyph_string *h, *t;
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
- int mouse_beg_col IF_LINT (= 0), mouse_end_col IF_LINT (= 0);
+ int mouse_beg_col UNINIT, mouse_end_col UNINIT;
bool check_mouse_face = false;
int dummy_x = 0;
struct face *face;
face_id = lookup_named_face (it->f, face_name, false);
- if (face_id < 0)
- return make_number (-1);
-
- face = FACE_FROM_ID (it->f, face_id);
- font = face->font;
- if (font == NULL)
+ face = FACE_FROM_ID_OR_NULL (it->f, face_id);
+ if (face == NULL || ((font = face->font) == NULL))
return make_number (-1);
boff = font->baseline_offset;
if (font->vertical_centering)
int leftmost, rightmost, lowest, highest;
int lbearing, rbearing;
int i, width, ascent, descent;
- int c IF_LINT (= 0); /* cmp->glyph_len can't be zero; see Bug#8512 */
+ int c;
XChar2b char2b;
struct font_metrics *pcm;
ptrdiff_t pos;
- for (glyph_len = cmp->glyph_len; glyph_len > 0; glyph_len--)
- if ((c = COMPOSITION_GLYPH (cmp, glyph_len - 1)) != '\t')
- break;
+ eassume (0 < glyph_len); /* See Bug#8512. */
+ do
+ c = COMPOSITION_GLYPH (cmp, --glyph_len);
+ while (c == '\t' && 0 < glyph_len);
+
bool right_padded = glyph_len < cmp->glyph_len;
for (i = 0; i < glyph_len; i++)
{
- if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
+ c = COMPOSITION_GLYPH (cmp, i);
+ if (c != '\t')
break;
cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
}
}
}
-#ifdef HAVE_WINDOW_SYSTEM
/* When we've written over the cursor, arrange for it to
be displayed again. */
if (FRAME_WINDOW_P (f)
&& phys_cursor_on_p && !w->phys_cursor_on_p)
{
+#ifdef HAVE_WINDOW_SYSTEM
int hpos = w->phys_cursor.hpos;
/* When the window is hscrolled, cursor hpos can legitimately be
display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
w->phys_cursor.x, w->phys_cursor.y);
unblock_input ();
- }
#endif /* HAVE_WINDOW_SYSTEM */
+ }
}
#ifdef HAVE_WINDOW_SYSTEM
clip_to_bounds (INT_MIN, XINT (x), INT_MAX),
clip_to_bounds (INT_MIN, XINT (y), INT_MAX));
}
+#endif /* HAVE_WINDOW_SYSTEM */
/* Display frame CURSOR, optionally using shape defined by POINTER. */
static void
define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer)
{
+#ifdef HAVE_WINDOW_SYSTEM
+ if (!FRAME_WINDOW_P (f))
+ return;
+
/* Do not change cursor shape while dragging mouse. */
if (EQ (do_mouse_tracking, Qdragging))
return;
cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
else if (EQ (pointer, intern ("nhdrag")))
cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
-#ifdef HAVE_X_WINDOWS
+# ifdef HAVE_X_WINDOWS
else if (EQ (pointer, intern ("vdrag")))
cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
-#endif
+# endif
else if (EQ (pointer, intern ("hourglass")))
cursor = FRAME_X_OUTPUT (f)->hourglass_cursor;
else if (EQ (pointer, Qmodeline))
if (cursor != No_Cursor)
FRAME_RIF (f)->define_frame_cursor (f, cursor);
+#endif
}
-#endif /* HAVE_WINDOW_SYSTEM */
-
/* Take proper action when mouse has moved to the mode or header line
or marginal area AREA of window W, x-position X and y-position Y.
X is relative to the start of the text display area of W, so the
int dx, dy, width, height;
ptrdiff_t charpos;
Lisp_Object string, object = Qnil;
- Lisp_Object pos IF_LINT (= Qnil), help;
-
+ Lisp_Object pos UNINIT;
Lisp_Object mouse_face;
int original_x_pixel = x;
struct glyph * glyph = NULL, * row_start_glyph = NULL;
- struct glyph_row *row IF_LINT (= 0);
+ struct glyph_row *row UNINIT;
if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
{
&object, &dx, &dy, &width, &height);
}
- help = Qnil;
+ Lisp_Object help = Qnil;
#ifdef HAVE_WINDOW_SYSTEM
if (IMAGEP (object))
if ((area == ON_MODE_LINE || area == ON_HEADER_LINE) && !mouse_face_shown)
clear_mouse_face (hlinfo);
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- define_frame_cursor1 (f, cursor, pointer);
-#endif
+ define_frame_cursor1 (f, cursor, pointer);
}
{
if (clear_mouse_face (hlinfo))
cursor = No_Cursor;
-#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f) && NILP (pointer))
{
+#ifdef HAVE_WINDOW_SYSTEM
if (area != TEXT_AREA)
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
else
pointer = Vvoid_text_area_pointer;
- }
#endif
+ }
goto set_cursor;
}
{
/* The mouse-highlighting, if any, comes from an overlay
or text property in the buffer. */
- Lisp_Object buffer IF_LINT (= Qnil);
- Lisp_Object disp_string IF_LINT (= Qnil);
+ Lisp_Object buffer UNINIT;
+ Lisp_Object disp_string UNINIT;
if (STRINGP (object))
{
}
set_cursor:
-
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- define_frame_cursor1 (f, cursor, pointer);
-#else
- /* This is here to prevent a compiler error, about "label at end of
- compound statement". */
- return;
-#endif
+ define_frame_cursor1 (f, cursor, pointer);
}