#endif /* HAVE_WINDOW_SYSTEM */
+static void produce_special_glyphs (struct it *, enum display_element_type);
static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
static int coords_in_mouse_face_p (struct window *, int, int);
return spec;
}
+
+/* Limit insanely large values of W->hscroll on frame F to the largest
+ value that will still prevent first_visible_x and last_visible_x of
+ 'struct it' from overflowing an int. */
+static inline int
+window_hscroll_limited (struct window *w, struct frame *f)
+{
+ ptrdiff_t window_hscroll = w->hscroll;
+ int window_text_width = window_box_width (w, TEXT_AREA);
+ int colwidth = FRAME_COLUMN_WIDTH (f);
+
+ if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
+ window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
+
+ return window_hscroll;
+}
+
/* Return 1 if position CHARPOS is visible in window W.
CHARPOS < 0 means return info about WINDOW_END position.
If visible, set *X and *Y to pixel coordinates of top left corner.
current_header_line_height = current_mode_line_height = -1;
- if (visible_p && XFASTINT (w->hscroll) > 0)
- *x -= XFASTINT (w->hscroll) * WINDOW_FRAME_COLUMN_WIDTH (w);
+ if (visible_p && w->hscroll > 0)
+ *x -=
+ window_hscroll_limited (w, WINDOW_XFRAME (w))
+ * WINDOW_FRAME_COLUMN_WIDTH (w);
#if 0
/* Debugging code. */
/* Are lines in the display truncated? */
if (base_face_id != DEFAULT_FACE_ID
- || XINT (it->w->hscroll)
+ || it->w->hscroll
|| (! WINDOW_FULL_WIDTH_P (it->w)
&& ((!NILP (Vtruncate_partial_width_windows)
&& !INTEGERP (Vtruncate_partial_width_windows))
it->line_wrap = TRUNCATE;
/* Get dimensions of truncation and continuation glyphs. These are
- displayed as fringe bitmaps under X, so we don't need them for such
- frames. */
- if (!FRAME_WINDOW_P (it->f))
+ displayed as fringe bitmaps under X, but we need them for such
+ frames when the fringes are turned off. But leave the dimensions
+ zero for tooltip frames, as these glyphs look ugly there and also
+ sabotage calculations of tooltip dimensions in x-show-tip. */
+#ifdef HAVE_WINDOW_SYSTEM
+ if (!(FRAME_WINDOW_P (it->f)
+ && FRAMEP (tip_frame)
+ && it->f == XFRAME (tip_frame)))
+#endif
{
if (it->line_wrap == TRUNCATE)
{
produce_special_glyphs (it, IT_CONTINUATION);
it->continuation_pixel_width = it->pixel_width;
}
-
- /* Reset these values to zero because the produce_special_glyphs
- above has changed them. */
- it->pixel_width = it->ascent = it->descent = 0;
- it->phys_ascent = it->phys_descent = 0;
}
+ /* Reset these values to zero because the produce_special_glyphs
+ above has changed them. */
+ it->pixel_width = it->ascent = it->descent = 0;
+ it->phys_ascent = it->phys_descent = 0;
+
/* Set this after getting the dimensions of truncation and
continuation glyphs, so that we don't produce glyphs when calling
produce_special_glyphs, above. */
}
else
{
- it->first_visible_x
- = XFASTINT (it->w->hscroll) * FRAME_COLUMN_WIDTH (it->f);
+ it->first_visible_x =
+ window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f);
it->last_visible_x = (it->first_visible_x
+ window_box_width (w, TEXT_AREA));
- /* If we truncate lines, leave room for the truncator glyph(s) at
+ /* If we truncate lines, leave room for the truncation glyph(s) at
the right margin. Otherwise, leave room for the continuation
- glyph(s). Truncation and continuation glyphs are not inserted
- for window-based redisplay. */
- if (!FRAME_WINDOW_P (it->f))
+ glyph(s). Done only if the window has no fringes. Since we
+ don't know at this point whether there will be any R2L lines in
+ the window, we reserve space for truncation/continuation glyphs
+ even if only one of the fringes is absent. */
+ if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
+ || (it->bidi_p && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
{
if (it->line_wrap == TRUNCATE)
it->last_visible_x -= it->truncation_pixel_width;
/* Or it fits exactly and we're on a window
system frame. */
|| (new_x == it->last_visible_x
- && FRAME_WINDOW_P (it->f))))
+ && FRAME_WINDOW_P (it->f)
+ && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
{
if ((it->current.dpvec_index >= 0
|| it->current.overlay_string_index >= 0)
ptrdiff_t size = 20;
ptrdiff_t n = 0, i, j;
int invis_p;
- struct overlay_entry *entries
- = (struct overlay_entry *) alloca (size * sizeof *entries);
+ struct overlay_entry *entries = alloca (size * sizeof *entries);
USE_SAFE_ALLOCA;
if (charpos <= 0)
/* Or it fits exactly and we're on a window
system frame. */
|| (new_x == it->last_visible_x
- && FRAME_WINDOW_P (it->f))))
+ && FRAME_WINDOW_P (it->f)
+ && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
{
if (/* IT->hpos == 0 means the very first glyph
doesn't fit on the line, e.g. a wide image. */
/* On graphical terminals, newlines may
"overflow" into the fringe if
overflow-newline-into-fringe is non-nil.
- On text terminals, newlines may overflow
- into the last glyph on the display
- line.*/
+ On text terminals, and on graphical
+ terminals with no right margin, newlines
+ may overflow into the last glyph on the
+ display line.*/
if (!FRAME_WINDOW_P (it->f)
+ || ((it->bidi_p
+ && it->bidi_it.paragraph_dir == R2L)
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
|| IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
{
if (!get_next_display_element (it))
&& it->current_x >= it->last_visible_x)
{
if (!FRAME_WINDOW_P (it->f)
+ || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
|| IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
{
int at_eob_p = 0;
int j;
old_buffer = echo_buffer[i];
- sprintf (name, " *Echo Area %d*", i);
- echo_buffer[i] = Fget_buffer_create (build_string (name));
+ echo_buffer[i] = Fget_buffer_create
+ (make_formatted_string (name, " *Echo Area %d*", i));
BVAR (XBUFFER (echo_buffer[i]), truncate_lines) = Qnil;
/* to force word wrap in echo area -
it was decided to postpone this*/
inside the left margin and the window is already
hscrolled. */
&& ((!row_r2l_p
- && ((XFASTINT (w->hscroll)
+ && ((w->hscroll
&& w->cursor.x <= h_margin)
|| (cursor_row->enabled_p
&& cursor_row->truncated_on_right_p
are actually truncated on the left. */
&& cursor_row->truncated_on_right_p
&& w->cursor.x <= h_margin)
- || (XFASTINT (w->hscroll)
+ || (w->hscroll
&& (w->cursor.x >= text_area_width - h_margin))))))
{
struct it it;
hscroll
= max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
}
- hscroll = max (hscroll, XFASTINT (w->min_hscroll));
+ hscroll = max (hscroll, w->min_hscroll);
/* Don't prevent redisplay optimizations if hscroll
hasn't changed, as it will unnecessarily slow down
redisplay. */
- if (XFASTINT (w->hscroll) != hscroll)
+ if (w->hscroll != hscroll)
{
XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
- w->hscroll = make_number (hscroll);
+ w->hscroll = hscroll;
hscrolled_p = 1;
}
}
static void
debug_method_add (struct window *w, char const *fmt, ...)
{
- char buffer[512];
char *method = w->desired_matrix->method;
int len = strlen (method);
int size = sizeof w->desired_matrix->method;
int remaining = size - len - 1;
va_list ap;
- va_start (ap, fmt);
- vsprintf (buffer, fmt, ap);
- va_end (ap);
if (len && remaining)
{
method[len] = '|';
--remaining, ++len;
}
- strncpy (method + len, buffer, remaining);
+ va_start (ap, fmt);
+ vsnprintf (method + len, remaining + 1, fmt, ap);
+ va_end (ap);
if (trace_redisplay_p)
fprintf (stderr, "%p (%s): %s\n",
&& STRINGP (BVAR (XBUFFER (w->buffer), name)))
? SSDATA (BVAR (XBUFFER (w->buffer), name))
: "no buffer"),
- buffer);
+ method + len);
}
#endif /* GLYPH_DEBUG */
int unchanged_p = 1;
/* If text or overlays have changed, see where. */
- if (XFASTINT (w->last_modified) < MODIFF
- || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
+ if (w->last_modified < MODIFF
+ || w->last_overlay_modified < OVERLAY_MODIFF)
{
/* Gap in the line? */
if (GPT < start || Z - GPT < end)
pt = marker_position (w->pointm);
if ((w->current_matrix->buffer != XBUFFER (w->buffer)
- || pt != XINT (w->last_point))
+ || pt != w->last_point)
&& check_point_in_composition (w->current_matrix->buffer,
- XINT (w->last_point),
+ w->last_point,
XBUFFER (w->buffer), pt))
b->clip_changed = 1;
}
if (!NILP (w->column_number_displayed)
/* This alternative quickly identifies a common case
where no change is needed. */
- && !(PT == XFASTINT (w->last_point)
- && XFASTINT (w->last_modified) >= MODIFF
- && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
+ && !(PT == w->last_point
+ && w->last_modified >= MODIFF
+ && w->last_overlay_modified >= OVERLAY_MODIFF)
&& (XFASTINT (w->column_number_displayed) != current_column ()))
w->update_mode_line = 1;
}
else if (EQ (selected_window, minibuf_window)
&& (current_buffer->clip_changed
- || XFASTINT (w->last_modified) < MODIFF
- || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
+ || w->last_modified < MODIFF
+ || w->last_overlay_modified < OVERLAY_MODIFF)
&& resize_mini_window (w, 0))
{
/* Resized active mini-window to fit the size of what it is
|| FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
/* Former continuation line has disappeared by becoming empty. */
goto cancel;
- else if (XFASTINT (w->last_modified) < MODIFF
- || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
+ else if (w->last_modified < MODIFF
+ || w->last_overlay_modified < OVERLAY_MODIFF
|| MINI_WINDOW_P (w))
{
/* We have to handle the case of continuation around a
goto cancel;
}
else if (/* Cursor position hasn't changed. */
- PT == XFASTINT (w->last_point)
+ PT == w->last_point
/* Make sure the cursor was last displayed
in this window. Otherwise we have to reposition it. */
&& 0 <= w->cursor.vpos
{
struct buffer *b = XBUFFER (w->buffer);
- w->last_modified
- = make_number (accurate_p ? BUF_MODIFF (b) : 0);
- w->last_overlay_modified
- = make_number (accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
+ w->last_modified = accurate_p ? BUF_MODIFF(b) : 0;
+ w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF(b) : 0;
w->last_had_star
= BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
w->last_cursor_off_p = w->cursor_off_p;
if (w == XWINDOW (selected_window))
- w->last_point = make_number (BUF_PT (b));
+ w->last_point = BUF_PT (b);
else
- w->last_point = make_number (XMARKER (w->pointm)->charpos);
+ w->last_point = XMARKER (w->pointm)->charpos;
}
}
return rc;
#endif
+ /* Previously, there was a check for Lisp integer in the
+ if-statement below. Now, this field is converted to
+ ptrdiff_t, thus zero means invalid position in a buffer. */
+ eassert (w->last_point > 0);
+
/* Handle case where text has not changed, only point, and it has
not moved off the frame. */
if (/* Point may be in this window. */
&& !NILP (BVAR (current_buffer, mark_active)))
&& NILP (w->region_showing)
&& NILP (Vshow_trailing_whitespace)
- /* Right after splitting windows, last_point may be nil. */
- && INTEGERP (w->last_point)
/* This code is not used for mini-buffer for the sake of the case
of redisplaying to replace an echo area message; since in
that case the mini-buffer contents per se are usually
int scroll_p = 0, must_scroll = 0;
int last_y = window_text_bottom_y (w) - this_scroll_margin;
- if (PT > XFASTINT (w->last_point))
+ if (PT > w->last_point)
{
/* Point has moved forward. */
while (MATRIX_ROW_END_CHARPOS (row) < PT
&& !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
scroll_p = 1;
}
- else if (PT < XFASTINT (w->last_point))
+ else if (PT < w->last_point)
{
/* Cursor has to be moved backward. Note that PT >=
CHARPOS (startp) because of the outer if-statement. */
= (!NILP (w->window_end_valid)
&& !current_buffer->clip_changed
&& !current_buffer->prevent_redisplay_optimizations_p
- && XFASTINT (w->last_modified) >= MODIFF
- && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
+ && w->last_modified >= MODIFF
+ && w->last_overlay_modified >= OVERLAY_MODIFF);
/* Run the window-bottom-change-functions
if it is possible that the text on the screen has changed
buffer_unchanged_p
= (!NILP (w->window_end_valid)
&& !current_buffer->clip_changed
- && XFASTINT (w->last_modified) >= MODIFF
- && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
+ && w->last_modified >= MODIFF
+ && w->last_overlay_modified >= OVERLAY_MODIFF);
/* When windows_or_buffers_changed is non-zero, we can't rely on
the window end being valid, so set it to nil there. */
if (!NILP (w->column_number_displayed)
/* This alternative quickly identifies a common case
where no change is needed. */
- && !(PT == XFASTINT (w->last_point)
- && XFASTINT (w->last_modified) >= MODIFF
- && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
+ && !(PT == w->last_point
+ && w->last_modified >= MODIFF
+ && w->last_overlay_modified >= OVERLAY_MODIFF)
&& (XFASTINT (w->column_number_displayed) != current_column ()))
update_mode_line = 1;
startp = run_window_scroll_functions (window, startp);
}
- w->last_modified = make_number (0);
- w->last_overlay_modified = make_number (0);
+ w->last_modified = 0;
+ w->last_overlay_modified = 0;
if (CHARPOS (startp) < BEGV)
SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
else if (CHARPOS (startp) > ZV)
&& (CHARPOS (startp) < ZV
/* Avoid starting at end of buffer. */
|| CHARPOS (startp) == BEGV
- || (XFASTINT (w->last_modified) >= MODIFF
- && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
+ || (w->last_modified >= MODIFF
+ && w->last_overlay_modified >= OVERLAY_MODIFF)))
{
int d1, d2, d3, d4, d5, d6;
try_to_scroll:
- w->last_modified = make_number (0);
- w->last_overlay_modified = make_number (0);
+ w->last_modified = 0;
+ w->last_overlay_modified = 0;
/* Redisplay the mode line. Select the buffer properly for that. */
if (!update_mode_line)
GIVE_UP (5);
/* Another way to prevent redisplay optimizations. */
- if (XFASTINT (w->last_modified) == 0)
+ if (w->last_modified == 0)
GIVE_UP (6);
/* Verify that window is not hscrolled. */
- if (XFASTINT (w->hscroll) != 0)
+ if (w->hscroll != 0)
GIVE_UP (7);
/* Verify that display wasn't paused. */
for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
{
- char *s = (char *) alloca (row->used[area] + 1);
+ char *s = alloca (row->used[area] + 1);
int i;
for (i = 0; i < row->used[area]; ++i)
}
-/* Insert truncation glyphs at the start of IT->glyph_row. Truncation
- glyphs are only inserted for terminal frames since we can't really
- win with truncation glyphs when partially visible glyphs are
- involved. Which glyphs to insert is determined by
- produce_special_glyphs. */
+/* Insert truncation glyphs at the start of IT->glyph_row. Which
+ glyphs to insert is determined by produce_special_glyphs. */
static void
insert_left_trunc_glyphs (struct it *it)
struct it truncate_it;
struct glyph *from, *end, *to, *toend;
- eassert (!FRAME_WINDOW_P (it->f));
+ eassert (!FRAME_WINDOW_P (it->f)
+ || (!it->glyph_row->reversed_p
+ && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
+ || (it->glyph_row->reversed_p
+ && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
/* Get the truncation glyphs. */
truncate_it = *it;
/* Overwrite glyphs from IT with truncation glyphs. */
if (!it->glyph_row->reversed_p)
{
+ short tused = truncate_it.glyph_row->used[TEXT_AREA];
+
from = truncate_it.glyph_row->glyphs[TEXT_AREA];
- end = from + truncate_it.glyph_row->used[TEXT_AREA];
+ end = from + tused;
to = it->glyph_row->glyphs[TEXT_AREA];
toend = to + it->glyph_row->used[TEXT_AREA];
+ if (FRAME_WINDOW_P (it->f))
+ {
+ /* On GUI frames, when variable-size fonts are displayed,
+ the truncation glyphs may need more pixels than the row's
+ glyphs they overwrite. We overwrite more glyphs to free
+ enough screen real estate, and enlarge the stretch glyph
+ on the right (see display_line), if there is one, to
+ preserve the screen position of the truncation glyphs on
+ the right. */
+ int w = 0;
+ struct glyph *g = to;
+ short used;
+
+ /* The first glyph could be partially visible, in which case
+ it->glyph_row->x will be negative. But we want the left
+ truncation glyphs to be aligned at the left margin of the
+ window, so we override the x coordinate at which the row
+ will begin. */
+ it->glyph_row->x = 0;
+ while (g < toend && w < it->truncation_pixel_width)
+ {
+ w += g->pixel_width;
+ ++g;
+ }
+ if (g - to - tused > 0)
+ {
+ memmove (to + tused, g, (toend - g) * sizeof(*g));
+ it->glyph_row->used[TEXT_AREA] -= g - to - tused;
+ }
+ used = it->glyph_row->used[TEXT_AREA];
+ if (it->glyph_row->truncated_on_right_p
+ && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
+ && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
+ == STRETCH_GLYPH)
+ {
+ int extra = w - it->truncation_pixel_width;
+
+ it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
+ }
+ }
while (from < end)
*to++ = *from++;
/* There may be padding glyphs left over. Overwrite them too. */
- while (to < toend && CHAR_GLYPH_PADDING_P (*to))
+ if (!FRAME_WINDOW_P (it->f))
{
- from = truncate_it.glyph_row->glyphs[TEXT_AREA];
- while (from < end)
- *to++ = *from++;
+ while (to < toend && CHAR_GLYPH_PADDING_P (*to))
+ {
+ from = truncate_it.glyph_row->glyphs[TEXT_AREA];
+ while (from < end)
+ *to++ = *from++;
+ }
}
if (to > toend)
}
else
{
+ short tused = truncate_it.glyph_row->used[TEXT_AREA];
+
/* In R2L rows, overwrite the last (rightmost) glyphs, and do
that back to front. */
end = truncate_it.glyph_row->glyphs[TEXT_AREA];
from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
toend = it->glyph_row->glyphs[TEXT_AREA];
to = toend + it->glyph_row->used[TEXT_AREA] - 1;
+ if (FRAME_WINDOW_P (it->f))
+ {
+ int w = 0;
+ struct glyph *g = to;
+
+ while (g >= toend && w < it->truncation_pixel_width)
+ {
+ w += g->pixel_width;
+ --g;
+ }
+ if (to - g - tused > 0)
+ to = g + tused;
+ if (it->glyph_row->truncated_on_right_p
+ && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
+ && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
+ {
+ int extra = w - it->truncation_pixel_width;
+
+ it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
+ }
+ }
while (from >= end && to >= toend)
*to-- = *from--;
- while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
+ if (!FRAME_WINDOW_P (it->f))
{
- from =
- truncate_it.glyph_row->glyphs[TEXT_AREA]
- + truncate_it.glyph_row->used[TEXT_AREA] - 1;
- while (from >= end && to >= toend)
- *to-- = *from--;
+ while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
+ {
+ from =
+ truncate_it.glyph_row->glyphs[TEXT_AREA]
+ + truncate_it.glyph_row->used[TEXT_AREA] - 1;
+ while (from >= end && to >= toend)
+ *to-- = *from--;
+ }
}
if (from >= end)
{
if the first glyph is partially visible or if we hit a line end. */
if (it->current_x < it->first_visible_x)
{
+ enum move_it_result move_result;
+
this_line_min_pos = row->start.pos;
- move_it_in_display_line_to (it, ZV, it->first_visible_x,
- MOVE_TO_POS | MOVE_TO_X);
+ move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
+ MOVE_TO_POS | MOVE_TO_X);
+ /* If we are under a large hscroll, move_it_in_display_line_to
+ could hit the end of the line without reaching
+ it->first_visible_x. Pretend that we did reach it. This is
+ especially important on a TTY, where we will call
+ extend_face_to_end_of_line, which needs to know how many
+ blank glyphs to produce. */
+ if (it->current_x < it->first_visible_x
+ && (move_result == MOVE_NEWLINE_OR_CR
+ || move_result == MOVE_POS_MATCH_OR_ZV))
+ it->current_x = it->first_visible_x;
+
/* Record the smallest positions seen while we moved over
display elements that are not visible. This is needed by
redisplay_internal for optimizing the case where the cursor
new_x > it->last_visible_x
/* Or it fits exactly on a window system frame. */
|| (new_x == it->last_visible_x
- && FRAME_WINDOW_P (it->f))))
+ && FRAME_WINDOW_P (it->f)
+ && (row->reversed_p
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
{
/* End of a continued line. */
if (it->hpos == 0
|| (new_x == it->last_visible_x
- && FRAME_WINDOW_P (it->f)))
+ && FRAME_WINDOW_P (it->f)
+ && (row->reversed_p
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
{
/* Current glyph is the only one on the line or
fits exactly on the line. We must continue
window system frames. We leave the glyph in
this row and let it fill the row, but don't
consume the TAB. */
+ if ((row->reversed_p
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
+ produce_special_glyphs (it, IT_CONTINUATION);
it->continuation_lines_width += it->last_visible_x;
row->ends_in_middle_of_char_p = 1;
row->continued_p = 1;
row->used[TEXT_AREA] = n_glyphs_before + i;
/* Display continuation glyphs. */
- if (!FRAME_WINDOW_P (it->f))
+ it->current_x = x_before;
+ it->continuation_lines_width += x;
+ if (!FRAME_WINDOW_P (it->f)
+ || (row->reversed_p
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
produce_special_glyphs (it, IT_CONTINUATION);
row->continued_p = 1;
- it->current_x = x_before;
- it->continuation_lines_width += x;
extend_face_to_end_of_line (it);
if (nglyphs > 1 && i > 0)
/* If we truncate lines, we are done when the last displayed
glyphs reach past the right margin of the window. */
if (it->line_wrap == TRUNCATE
- && (FRAME_WINDOW_P (it->f)
+ && (FRAME_WINDOW_P (it->f) && WINDOW_RIGHT_FRINGE_WIDTH (it->w)
? (it->current_x >= it->last_visible_x)
: (it->current_x > it->last_visible_x)))
{
/* Maybe add truncation glyphs. */
- if (!FRAME_WINDOW_P (it->f))
+ if (!FRAME_WINDOW_P (it->f)
+ || (row->reversed_p
+ ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
{
int i, n;
i = row->used[TEXT_AREA] - (i + 1);
}
- for (n = row->used[TEXT_AREA]; i < n; ++i)
+ it->current_x = x_before;
+ if (!FRAME_WINDOW_P (it->f))
+ {
+ for (n = row->used[TEXT_AREA]; i < n; ++i)
+ {
+ row->used[TEXT_AREA] = i;
+ produce_special_glyphs (it, IT_TRUNCATION);
+ }
+ }
+ else
{
row->used[TEXT_AREA] = i;
produce_special_glyphs (it, IT_TRUNCATION);
row->exact_window_width_line_p = 1;
goto at_end_of_line;
}
+ it->current_x = x_before;
}
row->truncated_on_right_p = 1;
reseat_at_next_visible_line_start (it, 0);
row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
it->hpos = hpos_before;
- it->current_x = x_before;
break;
}
}
if (it->first_visible_x
&& IT_CHARPOS (*it) != CHARPOS (row->start.pos))
{
- if (!FRAME_WINDOW_P (it->f))
+ if (!FRAME_WINDOW_P (it->f)
+ || (row->reversed_p
+ ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+ : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
insert_left_trunc_glyphs (it);
row->truncated_on_left_p = 1;
}
}
else if (CHARACTERP (eoltype))
{
- unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
+ unsigned char *tmp = alloca (MAX_MULTIBYTE_LENGTH);
int c = XFASTINT (eoltype);
eol_str_len = CHAR_STRING (c, tmp);
eol_str = tmp;
if (it->first_visible_x
&& it_charpos > 0)
{
- if (!FRAME_WINDOW_P (it->f))
+ if (!FRAME_WINDOW_P (it->f)
+ || (row->reversed_p
+ ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+ : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
insert_left_trunc_glyphs (it);
row->truncated_on_left_p = 1;
}
last = s->row->glyphs[s->area] + end;
voffset = glyph->voffset;
s->face = FACE_FROM_ID (s->f, face_id);
- s->font = s->face->font;
+ s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
s->nchars = 1;
s->width = glyph->pixel_width;
glyph++;
#define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
do \
{ \
- s = (struct glyph_string *) alloca (sizeof *s); \
+ s = alloca (sizeof *s); \
INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
START = fill_stretch_glyph_string (s, START, END); \
append_glyph_string (&HEAD, &TAIL, s); \
#define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
do \
{ \
- s = (struct glyph_string *) alloca (sizeof *s); \
+ s = alloca (sizeof *s); \
INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
fill_image_glyph_string (s); \
append_glyph_string (&HEAD, &TAIL, s); \
\
face_id = (row)->glyphs[area][START].face_id; \
\
- s = (struct glyph_string *) alloca (sizeof *s); \
- char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
+ s = alloca (sizeof *s); \
+ char2b = alloca ((END - START) * sizeof *char2b); \
INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
append_glyph_string (&HEAD, &TAIL, s); \
s->x = (X); \
struct glyph_string *first_s = NULL; \
int n; \
\
- char2b = (XChar2b *) alloca ((sizeof *char2b) * cmp->glyph_len); \
+ char2b = alloca (cmp->glyph_len * sizeof *char2b); \
\
/* Make glyph_strings for each glyph sequence that is drawable by \
the same face, and append them to HEAD/TAIL. */ \
for (n = 0; n < cmp->glyph_len;) \
{ \
- s = (struct glyph_string *) alloca (sizeof *s); \
+ s = alloca (sizeof *s); \
INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
append_glyph_string (&(HEAD), &(TAIL), s); \
s->cmp = cmp; \
face_id = (row)->glyphs[area][START].face_id; \
gstring = (composition_gstring_from_id \
((row)->glyphs[area][START].u.cmp.id)); \
- s = (struct glyph_string *) alloca (sizeof *s); \
- char2b = (XChar2b *) alloca ((sizeof *char2b) \
- * LGSTRING_GLYPH_LEN (gstring)); \
+ s = alloca (sizeof *s); \
+ char2b = alloca (LGSTRING_GLYPH_LEN (gstring) * sizeof *char2b); \
INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
append_glyph_string (&(HEAD), &(TAIL), s); \
s->x = (X); \
\
face_id = (row)->glyphs[area][START].face_id; \
\
- s = (struct glyph_string *) alloca (sizeof *s); \
+ s = alloca (sizeof *s); \
INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
append_glyph_string (&HEAD, &TAIL, s); \
s->x = (X); \
it->nglyphs = width;
}
+/* Get information about special display element WHAT in an
+ environment described by IT. WHAT is one of IT_TRUNCATION or
+ IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
+ non-null glyph_row member. This function ensures that fields like
+ face_id, c, len of IT are left untouched. */
+
+static void
+produce_special_glyphs (struct it *it, enum display_element_type what)
+{
+ struct it temp_it;
+ Lisp_Object gc;
+ GLYPH glyph;
+
+ temp_it = *it;
+ temp_it.object = make_number (0);
+ memset (&temp_it.current, 0, sizeof temp_it.current);
+
+ if (what == IT_CONTINUATION)
+ {
+ /* Continuation glyph. For R2L lines, we mirror it by hand. */
+ if (it->bidi_it.paragraph_dir == R2L)
+ SET_GLYPH_FROM_CHAR (glyph, '/');
+ else
+ SET_GLYPH_FROM_CHAR (glyph, '\\');
+ if (it->dp
+ && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
+ {
+ /* FIXME: Should we mirror GC for R2L lines? */
+ SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
+ spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
+ }
+ }
+ else if (what == IT_TRUNCATION)
+ {
+ /* Truncation glyph. */
+ SET_GLYPH_FROM_CHAR (glyph, '$');
+ if (it->dp
+ && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
+ {
+ /* FIXME: Should we mirror GC for R2L lines? */
+ SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
+ spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
+ }
+ }
+ else
+ abort ();
+
+#ifdef HAVE_WINDOW_SYSTEM
+ /* On a GUI frame, when the right fringe (left fringe for R2L rows)
+ is turned off, we precede the truncation/continuation glyphs by a
+ stretch glyph whose width is computed such that these special
+ glyphs are aligned at the window margin, even when very different
+ fonts are used in different glyph rows. */
+ if (FRAME_WINDOW_P (temp_it.f)
+ /* init_iterator calls this with it->glyph_row == NULL, and it
+ wants only the pixel width of the truncation/continuation
+ glyphs. */
+ && temp_it.glyph_row
+ /* insert_left_trunc_glyphs calls us at the beginning of the
+ row, and it has its own calculation of the stretch glyph
+ width. */
+ && temp_it.glyph_row->used[TEXT_AREA] > 0
+ && (temp_it.glyph_row->reversed_p
+ ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
+ : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
+ {
+ int stretch_width = temp_it.last_visible_x - temp_it.current_x;
+
+ if (stretch_width > 0)
+ {
+ struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
+ struct font *font =
+ face->font ? face->font : FRAME_FONT (temp_it.f);
+ int stretch_ascent =
+ (((temp_it.ascent + temp_it.descent)
+ * FONT_BASE (font)) / FONT_HEIGHT (font));
+
+ append_stretch_glyph (&temp_it, make_number (0), stretch_width,
+ temp_it.ascent + temp_it.descent,
+ stretch_ascent);
+ }
+ }
+#endif
+
+ temp_it.dp = NULL;
+ temp_it.what = IT_CHARACTER;
+ temp_it.len = 1;
+ temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
+ temp_it.face_id = GLYPH_FACE (glyph);
+ temp_it.len = CHAR_BYTES (temp_it.c);
+
+ PRODUCE_GLYPHS (&temp_it);
+ it->pixel_width = temp_it.pixel_width;
+ it->nglyphs = temp_it.pixel_width;
+}
+
#ifdef HAVE_WINDOW_SYSTEM
/* Calculate line-height and line-spacing properties.
b = XBUFFER (w->buffer);
if (part == ON_TEXT
&& EQ (w->window_end_valid, w->buffer)
- && XFASTINT (w->last_modified) == BUF_MODIFF (b)
- && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
+ && w->last_modified == BUF_MODIFF (b)
+ && w->last_overlay_modified == BUF_OVERLAY_MODIFF (b))
{
int hpos, vpos, dx, dy, area = LAST_AREA;
ptrdiff_t pos;
staticpro (&echo_area_buffer[0]);
staticpro (&echo_area_buffer[1]);
- Vmessages_buffer_name = make_pure_c_string ("*Messages*");
+ Vmessages_buffer_name = build_pure_c_string ("*Messages*");
staticpro (&Vmessages_buffer_name);
mode_line_proptrans_alist = Qnil;
DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
doc: /* String to display as an arrow in non-window frames.
See also `overlay-arrow-position'. */);
- Voverlay_arrow_string = make_pure_c_string ("=>");
+ Voverlay_arrow_string = build_pure_c_string ("=>");
DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
doc: /* List of variables (symbols) which hold markers for overlay arrows.
\(see `modify-frame-parameters'). */);
Vicon_title_format
= Vframe_title_format
- = pure_cons (intern_c_string ("multiple-frames"),
- pure_cons (make_pure_c_string ("%b"),
- pure_cons (pure_cons (empty_unibyte_string,
- pure_cons (intern_c_string ("invocation-name"),
- pure_cons (make_pure_c_string ("@"),
- pure_cons (intern_c_string ("system-name"),
- Qnil)))),
- Qnil)));
+ = listn (CONSTYPE_PURE, 3,
+ intern_c_string ("multiple-frames"),
+ build_pure_c_string ("%b"),
+ listn (CONSTYPE_PURE, 4,
+ empty_unibyte_string,
+ intern_c_string ("invocation-name"),
+ build_pure_c_string ("@"),
+ intern_c_string ("system-name")));
DEFVAR_LISP ("message-log-max", Vmessage_log_max,
doc: /* Maximum number of lines to keep in the message log buffer.
/* Allocate the buffer for frame titles.
Also used for `format-mode-line'. */
int size = 100;
- mode_line_noprop_buf = (char *) xmalloc (size);
+ mode_line_noprop_buf = xmalloc (size);
mode_line_noprop_buf_end = mode_line_noprop_buf + size;
mode_line_noprop_ptr = mode_line_noprop_buf;
mode_line_target = MODE_LINE_DISPLAY;
if (INTEGERP (Vhourglass_delay)
&& XINT (Vhourglass_delay) > 0)
- EMACS_SET_SECS_NSECS (delay,
- min (XINT (Vhourglass_delay), TYPE_MAXIMUM (time_t)),
- 0);
+ delay = make_emacs_time (min (XINT (Vhourglass_delay),
+ TYPE_MAXIMUM (time_t)),
+ 0);
else if (FLOATP (Vhourglass_delay)
&& XFLOAT_DATA (Vhourglass_delay) > 0)
delay = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (Vhourglass_delay));
else
- EMACS_SET_SECS_NSECS (delay, DEFAULT_HOURGLASS_DELAY, 0);
+ delay = make_emacs_time (DEFAULT_HOURGLASS_DELAY, 0);
hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
show_hourglass, NULL);