GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
#include "font.h"
#include "fontset.h"
#include "blockinput.h"
+#include "xwidget.h"
#ifdef HAVE_WINDOW_SYSTEM
#include TERM_HEADER
#endif /* HAVE_WINDOW_SYSTEM */
-#ifdef HAVE_XWIDGETS
-# include "xwidget.h"
-#endif
#ifndef FRAME_X_OUTPUT
#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
#endif
static bool set_cursor_from_row (struct window *, struct glyph_row *,
struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
int, int);
+static bool cursor_row_fully_visible_p (struct window *, bool, bool);
static bool update_menu_bar (struct frame *, bool, bool);
static bool try_window_reusing_current_matrix (struct window *);
static int try_window_id (struct window *);
static bool next_element_from_composition (struct it *);
static bool next_element_from_image (struct it *);
static bool next_element_from_stretch (struct it *);
-#ifdef HAVE_XWIDGETS
static bool next_element_from_xwidget (struct it *);
-#endif
static void load_overlay_strings (struct it *, ptrdiff_t);
static bool get_next_display_element (struct it *);
static enum move_it_result
character properties needed for reordering are not yet
available. */
it->bidi_p =
- NILP (Vpurify_flag)
+ !redisplay__inhibit_bidi
&& !NILP (BVAR (current_buffer, bidi_display_reordering))
&& it->multibyte_p;
&& valid_image_p (value))
#endif /* not HAVE_WINDOW_SYSTEM */
|| (CONSP (value) && EQ (XCAR (value), Qspace))
-#ifdef HAVE_XWIDGETS
|| ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
- && valid_xwidget_spec_p (value))
-#endif
- );
+ && valid_xwidget_spec_p (value)));
if (valid_p && display_replaced == 0)
{
*position = it->position = start_pos;
retval = 1 + (it->area == TEXT_AREA);
}
-#ifdef HAVE_XWIDGETS
- else if (valid_xwidget_spec_p(value))
+ else if (valid_xwidget_spec_p (value))
{
it->what = IT_XWIDGET;
it->method = GET_FROM_XWIDGET;
it->position = start_pos;
it->object = NILP (object) ? it->w->contents : object;
*position = start_pos;
- it->xwidget = lookup_xwidget(value);
+ it->xwidget = lookup_xwidget (value);
}
-#endif
#ifdef HAVE_WINDOW_SYSTEM
else
{
case GET_FROM_STRETCH:
p->u.stretch.object = it->object;
break;
-#ifdef HAVE_XWIDGETS
case GET_FROM_XWIDGET:
p->u.xwidget.object = it->object;
break;
-#endif
case GET_FROM_BUFFER:
case GET_FROM_DISPLAY_VECTOR:
case GET_FROM_STRING:
it->object = p->u.image.object;
it->slice = p->u.image.slice;
break;
-#ifdef HAVE_XWIDGETS
case GET_FROM_XWIDGET:
it->object = p->u.xwidget.object;
break;
-#endif
case GET_FROM_STRETCH:
it->object = p->u.stretch.object;
break;
loading loadup.el, as the necessary character property tables are
not yet available. */
it->bidi_p =
- NILP (Vpurify_flag)
+ !redisplay__inhibit_bidi
&& !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
if (s == NULL)
next_element_from_c_string,
next_element_from_image,
next_element_from_stretch,
-#ifdef HAVE_XWIDGETS
next_element_from_xwidget,
-#endif
};
#define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
{
ptrdiff_t ignore;
int next_face_id;
+ bool text_from_string = false;
+ /* Normally, the next buffer location is stored in
+ IT->current.pos... */
struct text_pos pos = it->current.pos;
- /* For a string from a display property, the next
- buffer position is stored in the 'position'
+ /* ...but for a string from a display property, the
+ next buffer position is stored in the 'position'
member of the iteration stack slot below the
current one, see handle_single_display_spec. By
- contrast, it->current.pos was is not yet updated
- to point to that buffer position; that will
- happen in pop_it, after we finish displaying the
- current string. Note that we already checked
- above that it->sp is positive, so subtracting one
- from it is safe. */
+ contrast, it->current.pos was not yet updated to
+ point to that buffer position; that will happen
+ in pop_it, after we finish displaying the current
+ string. Note that we already checked above that
+ it->sp is positive, so subtracting one from it is
+ safe. */
if (it->from_disp_prop_p)
- pos = (it->stack + it->sp - 1)->position;
+ {
+ int stackp = it->sp - 1;
+
+ /* Find the stack level with data from buffer. */
+ while (stackp >= 0
+ && STRINGP ((it->stack + stackp)->string))
+ stackp--;
+ if (stackp < 0)
+ {
+ /* If no stack slot was found for iterating
+ a buffer, we are displaying text from a
+ string, most probably the mode line or
+ the header line, and that string has a
+ display string on some of its
+ characters. */
+ text_from_string = true;
+ pos = it->stack[it->sp - 1].position;
+ }
+ else
+ pos = (it->stack + stackp)->position;
+ }
else
INC_TEXT_POS (pos, it->multibyte_p);
- if (CHARPOS (pos) >= ZV)
+ if (text_from_string)
+ {
+ Lisp_Object base_string = it->stack[it->sp - 1].string;
+
+ if (CHARPOS (pos) >= SCHARS (base_string) - 1)
+ it->end_of_box_run_p = true;
+ else
+ {
+ next_face_id
+ = face_at_string_position (it->w, base_string,
+ CHARPOS (pos), 0,
+ &ignore, face_id, false);
+ it->end_of_box_run_p
+ = (FACE_FROM_ID (it->f, next_face_id)->box
+ == FACE_NO_BOX);
+ }
+ }
+ else if (CHARPOS (pos) >= ZV)
it->end_of_box_run_p = true;
else
{
- next_face_id = face_at_buffer_position
- (it->w, CHARPOS (pos), &ignore,
- CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, false, -1);
+ next_face_id =
+ face_at_buffer_position (it->w, CHARPOS (pos), &ignore,
+ CHARPOS (pos)
+ + TEXT_PROP_DISTANCE_LIMIT,
+ false, -1);
it->end_of_box_run_p
= (FACE_FROM_ID (it->f, next_face_id)->box
== FACE_NO_BOX);
case GET_FROM_IMAGE:
case GET_FROM_STRETCH:
-#ifdef HAVE_XWIDGETS
case GET_FROM_XWIDGET:
-#endif
/* The position etc with which we have to proceed are on
the stack. The position may be at the end of a string,
return true;
}
-#ifdef HAVE_XWIDGETS
static bool
next_element_from_xwidget (struct it *it)
{
it->what = IT_XWIDGET;
return true;
}
-#endif
/* Fill iterator IT with next display element from a stretch glyph
suitable buffer from echo_buffer[] and clear it.
If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
- that the current message becomes the last displayed one, make
- choose a suitable buffer for echo_area_buffer[0], and clear it.
+ that the current message becomes the last displayed one, choose a
+ suitable buffer for echo_area_buffer[0], and clear it.
Value is what FN returns. */
echo_area_buffer[this_one] = Qnil;
}
- /* Choose a suitable buffer from echo_buffer[] is we don't
+ /* Choose a suitable buffer from echo_buffer[] if we don't
have one. */
if (NILP (echo_area_buffer[this_one]))
{
if (frame_garbaged)
{
Lisp_Object tail, frame;
+ struct frame *sf = SELECTED_FRAME ();
FOR_EACH_FRAME (tail, frame)
{
if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
{
- if (f->resized_p)
+ if (f->resized_p
+ /* It makes no sense to redraw a non-selected TTY
+ frame, since that will actually clear the
+ selected frame, and might leave the selected
+ frame with corrupted display, if it happens not
+ to be marked garbaged. */
+ && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
redraw_frame (f);
else
clear_current_matrices (f);
beginning of a paragraph, before the first strong directional
character, can change the base direction of the paragraph (unless
the buffer specifies a fixed paragraph direction), which will
- require to redisplay the whole paragraph. It might be worthwhile
+ require redisplaying the whole paragraph. It might be worthwhile
to find the paragraph limits and widen the range of redisplayed
lines to that, but for now just give up this optimization. */
if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
eassert (this_line_vpos == it.vpos);
eassert (this_line_y == it.current_y);
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
+ if (cursor_row_fully_visible_p (w, false, true))
+ {
#ifdef GLYPH_DEBUG
- *w->desired_matrix->method = 0;
- debug_method_add (w, "optimization 3");
+ *w->desired_matrix->method = 0;
+ debug_method_add (w, "optimization 3");
#endif
- goto update;
+ goto update;
+ }
+ else
+ goto cancel;
}
else
goto cancel;
if (scroll_conservatively > SCROLL_LIMIT)
{
int window_total_lines
- = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) * frame_line_height;
+ = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
int margin =
scroll_margin > 0
? min (scroll_margin, window_total_lines / 4)
ignore_mouse_drag_p = true;
#endif
}
+ ptrdiff_t count1 = SPECPDL_INDEX ();
+ /* x_consider_frame_title calls select-frame, which calls
+ resize_mini_window, which could resize the mini-window and by
+ that undo the effect of this redisplay cycle wrt minibuffer
+ and echo-area display. Binding inhibit-redisplay to t makes
+ the call to resize_mini_window a no-op, thus avoiding the
+ adverse side effects. */
+ specbind (Qinhibit_redisplay, Qt);
x_consider_frame_title (w->frame);
+ unbind_to (count1, Qnil);
#endif
}
beginning of a paragraph, before the first strong directional
character, can change the base direction of the paragraph (unless
the buffer specifies a fixed paragraph direction), which will
- require to redisplay the whole paragraph. It might be worthwhile
+ require redisplaying the whole paragraph. It might be worthwhile
to find the paragraph limits and widen the range of redisplayed
lines to that, but for now just give up this optimization and
redisplay from scratch. */
glyph->left_box_line_p,
glyph->right_box_line_p);
}
-#ifdef HAVE_XWIDGETS
else if (glyph->type == XWIDGET_GLYPH)
{
+#ifndef HAVE_XWIDGETS
+ eassume (false);
+#else
fprintf (stderr,
" %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
glyph - row->glyphs[TEXT_AREA],
glyph->face_id,
glyph->left_box_line_p,
glyph->right_box_line_p);
-
- }
#endif
+ }
}
|| 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))
+ || redisplay__inhibit_bidi)
return Qleft_to_right;
else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
return BVAR (buf, bidi_paragraph_direction);
/* When we are loading loadup.el, the character property
tables needed for bidi iteration are not yet
available. */
- || !NILP (Vpurify_flag))
+ || redisplay__inhibit_bidi)
return Qnil;
validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
/* When we are loading loadup.el, the character property
tables needed for bidi iteration are not yet
available. */
- || !NILP (Vpurify_flag))
+ || redisplay__inhibit_bidi)
return Qnil;
set_buffer_temp (buf);
return OK_PIXELS (width_p ? img->width : img->height);
}
-# ifdef HAVE_XWIDGETS
if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
{
// TODO: Don't return dummy size.
return OK_PIXELS (100);
}
-# endif
#endif
if (EQ (car, Qplus) || EQ (car, Qminus))
{
} \
while (false)
-#ifdef HAVE_XWIDGETS
-#define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+#ifndef HAVE_XWIDGETS
+# define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+ eassume (false)
+#else
+# define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
do \
{ \
s = alloca (sizeof *s); \
while (false)
#endif
-
/* Add a glyph string for a sequence of character glyphs to the list
of strings between HEAD and TAIL. START is the index of the first
glyph in row area AREA of glyph row ROW that is part of the new
HL, X, LAST_X); \
break;
-#ifdef HAVE_XWIDGETS
-# define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
+#define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
case XWIDGET_GLYPH: \
BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
HL, X, LAST_X); \
break;
-#endif
#define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
case GLYPHLESS_GLYPH: \
break; \
\
default: \
- emacs_abort (); \
+ emacs_abort (); \
} \
\
if (s) \
} while (false)
-#ifdef HAVE_XWIDGETS
-# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
+#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
-#else
-# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
- BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
- BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
-#endif
/* Draw glyphs between START and END in AREA of ROW on window W,
glyph->object = it->object;
if (it->pixel_width > 0)
{
+ eassert (it->pixel_width <= SHRT_MAX);
glyph->pixel_width = it->pixel_width;
glyph->padding_p = false;
}
}
glyph->charpos = it->cmp_it.charpos;
glyph->object = it->object;
+ eassert (it->pixel_width <= SHRT_MAX);
glyph->pixel_width = it->pixel_width;
glyph->ascent = it->ascent;
glyph->descent = it->descent;
{
glyph->charpos = CHARPOS (it->position);
glyph->object = it->object;
- glyph->pixel_width = it->pixel_width;
+ glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
glyph->ascent = glyph_ascent;
glyph->descent = it->descent;
glyph->voffset = it->voffset;
}
}
-#ifdef HAVE_XWIDGETS
static void
produce_xwidget_glyph (struct it *it)
{
+#ifdef HAVE_XWIDGETS
struct xwidget *xw;
int glyph_ascent, crop;
eassert (it->what == IT_XWIDGET);
{
glyph->charpos = CHARPOS (it->position);
glyph->object = it->object;
- glyph->pixel_width = it->pixel_width;
+ glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
glyph->ascent = glyph_ascent;
glyph->descent = it->descent;
glyph->voffset = it->voffset;
else
IT_EXPAND_MATRIX_WIDTH (it, area);
}
-}
#endif
+}
/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
of the glyph, WIDTH and HEIGHT are the width and height of the
}
glyph->charpos = CHARPOS (it->position);
glyph->object = object;
- glyph->pixel_width = width;
+ /* FIXME: It would be better to use TYPE_MAX here, but
+ __typeof__ is not portable enough... */
+ glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
glyph->ascent = ascent;
glyph->descent = height - ascent;
glyph->voffset = it->voffset;
}
glyph->charpos = CHARPOS (it->position);
glyph->object = it->object;
+ eassert (it->pixel_width <= SHRT_MAX);
glyph->pixel_width = it->pixel_width;
glyph->ascent = it->ascent;
glyph->descent = it->descent;
produce_image_glyph (it);
else if (it->what == IT_STRETCH)
produce_stretch_glyph (it);
-#ifdef HAVE_XWIDGETS
else if (it->what == IT_XWIDGET)
produce_xwidget_glyph (it);
-#endif
done:
/* Accumulate dimensions. Note: can't assume that it->descent > 0
/* Use normal cursor if not blinked off. */
if (!w->cursor_off_p)
{
-#ifdef HAVE_XWIDGETS
if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
return NO_CURSOR;
-#endif
if (glyph != NULL && glyph->type == IMAGE_GLYPH)
{
if (cursor_type == FILLED_BOX_CURSOR)
Vtruncate_partial_width_windows,
doc: /* Non-nil means truncate lines in windows narrower than the frame.
For an integer value, truncate lines in each window narrower than the
-full frame width, provided the window width is less than that integer;
-otherwise, respect the value of `truncate-lines'.
+full frame width, provided the total window width in column units is less
+than that integer; otherwise, respect the value of `truncate-lines'.
+The total width of the window is as returned by `window-total-width', it
+includes the fringes, the continuation and truncation glyphs, the
+display margins (if any), and the scroll bar
For any other non-nil value, truncate lines in all windows that do
not span the full frame width.
DEFVAR_LISP ("frame-title-format", Vframe_title_format,
doc: /* Template for displaying the title bar of visible frames.
-(Assuming the window manager supports this feature.)
+\(Assuming the window manager supports this feature.)
This variable has the same structure as `mode-line-format', except that
the %c and %l constructs are ignored. It is used only on frames for
DEFVAR_LISP ("icon-title-format", Vicon_title_format,
doc: /* Template for displaying the title bar of an iconified frame.
-(Assuming the window manager supports this feature.)
+\(Assuming the window manager supports this feature.)
This variable has the same structure as `mode-line-format' (which see),
and is used only on frames for which no explicit name has been set
-(see `modify-frame-parameters'). */);
+\(see `modify-frame-parameters'). */);
Vicon_title_format
= Vframe_title_format
= listn (CONSTYPE_PURE, 3,
A value of `grow-only', the default, means let mini-windows grow only;
they return to their normal size when the minibuffer is closed, or the
echo area becomes empty. */);
- Vresize_mini_windows = Qgrow_only;
+ /* Contrary to the doc string, we initialize this to nil, so that
+ loading loadup.el won't try to resize windows before loading
+ window.el, where some functions we need to call for this live.
+ We assign the 'grow-only' value right after loading window.el
+ during loadup. */
+ Vresize_mini_windows = Qnil;
DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
doc: /* Alist specifying how to blink the cursor off.
DEFVAR_LISP ("redisplay--variables", Vredisplay__variables,
doc: /* A hash-table of variables changing which triggers a thorough redisplay. */);
Vredisplay__variables = Qnil;
+
+ DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
+ doc: /* Non-nil means it is not safe to attempt bidi reordering for display. */);
+ /* Initialize to t, since we need to disable reordering until
+ loadup.el successfully loads charprop.el. */
+ redisplay__inhibit_bidi = true;
}