/* Display generation from window structure and buffer text.
-Copyright (C) 1985-1988, 1993-1995, 1997-2012 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation,
+Inc.
This file is part of GNU Emacs.
#include <config.h>
#include <stdio.h>
#include <limits.h>
-#include <setjmp.h>
#include "lisp.h"
+#include "atimer.h"
#include "keyboard.h"
#include "frame.h"
#include "window.h"
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
#include "w32term.h"
#endif
#ifdef HAVE_NS
static Lisp_Object Qbuffer_position, Qposition, Qobject;
static Lisp_Object Qright_to_left, Qleft_to_right;
-/* Cursor shapes */
+/* Cursor shapes. */
Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
-/* Pointer shapes */
+/* Pointer shapes. */
static Lisp_Object Qarrow, Qhand;
Lisp_Object Qtext;
static Lisp_Object Qwrap_prefix;
static Lisp_Object Qline_prefix;
+static Lisp_Object Qredisplay_internal;
/* Non-nil means don't actually do any redisplay. */
static Lisp_Object Qmargin, Qpointer;
static Lisp_Object Qline_height;
+/* These setters are used only in this file, so they can be private. */
+static void
+wset_base_line_number (struct window *w, Lisp_Object val)
+{
+ w->base_line_number = val;
+}
+static void
+wset_base_line_pos (struct window *w, Lisp_Object val)
+{
+ w->base_line_pos = val;
+}
+static void
+wset_column_number_displayed (struct window *w, Lisp_Object val)
+{
+ w->column_number_displayed = val;
+}
+static void
+wset_region_showing (struct window *w, Lisp_Object val)
+{
+ w->region_showing = val;
+}
+
#ifdef HAVE_WINDOW_SYSTEM
/* Test if overflow newline into fringe. Called with iterator IT
static int overlay_arrow_seen;
-/* Number of windows showing the buffer of the selected window (or
- another buffer with the same base buffer). keyboard.c refers to
- this. */
-
-int buffer_shared;
-
/* Vector containing glyphs for an ellipsis `...'. */
static Lisp_Object default_invis_vector[3];
CACHE = NULL; \
} while (0)
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
/* Non-zero means print traces of redisplay if compiled with
- GLYPH_DEBUG != 0. */
+ GLYPH_DEBUG defined. */
int trace_redisplay_p;
static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
#endif
-/* Non-zero while redisplay_internal is in progress. */
+/* True while redisplay_internal is in progress. */
-int redisplaying_p;
+bool redisplaying_p;
static Lisp_Object Qinhibit_free_realized_faces;
static Lisp_Object Qmode_line_default_help_echo;
static struct text_pos display_prop_end (struct it *, Lisp_Object,
struct text_pos);
static int compute_window_start_on_continuation_line (struct window *);
-static Lisp_Object safe_eval_handler (Lisp_Object);
static void insert_left_trunc_glyphs (struct it *);
static struct glyph_row *get_overlay_arrow_glyph_row (struct window *,
Lisp_Object);
static void iterate_out_of_display_property (struct it *);
static void pop_it (struct it *);
static void sync_frame_with_window_matrix_rows (struct window *);
-static void select_frame_for_redisplay (Lisp_Object);
static void redisplay_internal (void);
static int echo_area_display (int);
static void redisplay_windows (Lisp_Object);
move_it_in_display_line_to (struct it *, ptrdiff_t, int,
enum move_operation_enum);
void move_it_vertically_backward (struct it *, int);
+static void get_visually_first_element (struct it *);
static void init_to_row_start (struct it *, struct window *,
struct glyph_row *);
static int init_to_row_end (struct it *, struct window *,
#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);
struct frame *f = XFRAME (w->frame);
int height = WINDOW_TOTAL_HEIGHT (w);
- xassert (height >= 0);
+ eassert (height >= 0);
/* Note: the code below that determines the mode-line/header-line
height is essentially the same as that contained in the macro
*BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
box. */
-static inline void
+static void
window_box_edges (struct window *w, int area, int *top_left_x, int *top_left_y,
int *bottom_right_x, int *bottom_right_y)
{
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 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.
if (WINDOW_WANTS_HEADER_LINE_P (w))
current_header_line_height
= display_mode_line (w, HEADER_LINE_FACE_ID,
- BVAR (current_buffer, header_line_format));
+ BVAR (current_buffer, header_line_format));
start_display (&it, w, top);
- move_it_to (&it, charpos, -1, it.last_visible_y-1, -1,
+ move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
(charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
if (charpos >= 0
&& IT_CHARPOS (it) >= charpos)
/* When scanning backwards under bidi iteration, move_it_to
stops at or _before_ CHARPOS, because it stops at or to
- the _right_ of the character at CHARPOS. */
+ the _right_ of the character at CHARPOS. */
|| (it.bidi_p && it.bidi_it.scan_dir == -1
&& IT_CHARPOS (it) <= charpos)))
{
--g;
top_x -= g->pixel_width;
}
- xassert (g < it3.glyph_row->glyphs[TEXT_AREA]
+ eassert (g < it3.glyph_row->glyphs[TEXT_AREA]
+ it3.glyph_row->used[TEXT_AREA]);
}
}
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. */
returns an invalid character. If we find one, we return a `?', but
with the length of the invalid character. */
-static inline int
+static int
string_char_and_length (const unsigned char *str, int *len)
{
int c;
static struct text_pos
string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
{
- xassert (STRINGP (string) && nchars >= 0);
+ eassert (STRINGP (string) && nchars >= 0);
if (STRING_MULTIBYTE (string))
{
/* Value is the text position, i.e. character and byte position,
for character position CHARPOS in STRING. */
-static inline struct text_pos
+static struct text_pos
string_pos (ptrdiff_t charpos, Lisp_Object string)
{
struct text_pos pos;
- xassert (STRINGP (string));
- xassert (charpos >= 0);
+ eassert (STRINGP (string));
+ eassert (charpos >= 0);
SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
return pos;
}
{
struct text_pos pos;
- xassert (s != NULL);
- xassert (charpos >= 0);
+ eassert (s != NULL);
+ eassert (charpos >= 0);
if (multibyte_p)
{
static void
compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
{
- xassert (STRINGP (string));
- xassert (CHARPOS (*newpos) >= CHARPOS (pos));
+ eassert (STRINGP (string));
+ eassert (CHARPOS (*newpos) >= CHARPOS (pos));
if (STRING_MULTIBYTE (string))
*newpos = string_pos_nchars_ahead (pos, string,
/* Error handler for safe_eval and safe_call. */
static Lisp_Object
-safe_eval_handler (Lisp_Object arg)
+safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
{
- add_to_log ("Error during redisplay: %S", arg, Qnil);
+ add_to_log ("Error during redisplay: %S signaled %S",
+ Flist (nargs, args), arg);
return Qnil;
}
-
-/* Evaluate SEXPR and return the result, or nil if something went
+/* Call function FUNC with the rest of NARGS - 1 arguments
+ following. Return the result, or nil if something went
wrong. Prevent redisplay during the evaluation. */
-/* Call function ARGS[0] with arguments ARGS[1] to ARGS[NARGS - 1].
- Return the result, or nil if something went wrong. Prevent
- redisplay during the evaluation. */
-
Lisp_Object
-safe_call (ptrdiff_t nargs, Lisp_Object *args)
+safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
{
Lisp_Object val;
val = Qnil;
else
{
+ va_list ap;
+ ptrdiff_t i;
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1;
+ Lisp_Object *args = alloca (nargs * word_size);
+
+ args[0] = func;
+ va_start (ap, func);
+ for (i = 1; i < nargs; i++)
+ args[i] = va_arg (ap, Lisp_Object);
+ va_end (ap);
GCPRO1 (args[0]);
gcpro1.nvars = nargs;
Lisp_Object
safe_call1 (Lisp_Object fn, Lisp_Object arg)
{
- Lisp_Object args[2];
- args[0] = fn;
- args[1] = arg;
- return safe_call (2, args);
+ return safe_call (2, fn, arg);
}
static Lisp_Object Qeval;
return safe_call1 (Qeval, sexpr);
}
-/* Call function FN with one argument ARG.
+/* Call function FN with two arguments ARG1 and ARG2.
Return the result, or nil if something went wrong. */
Lisp_Object
safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
{
- Lisp_Object args[3];
- args[0] = fn;
- args[1] = arg1;
- args[2] = arg2;
- return safe_call (3, args);
+ return safe_call (3, fn, arg1, arg2);
}
{
if (it->method == GET_FROM_STRING)
{
- xassert (STRINGP (it->string));
- xassert (IT_STRING_CHARPOS (*it) >= 0);
+ eassert (STRINGP (it->string));
+ eassert (IT_STRING_CHARPOS (*it) >= 0);
}
else
{
- xassert (IT_STRING_CHARPOS (*it) < 0);
+ eassert (IT_STRING_CHARPOS (*it) < 0);
if (it->method == GET_FROM_BUFFER)
{
/* Check that character and byte positions agree. */
- xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
+ eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
}
}
if (it->dpvec)
- xassert (it->current.dpvec_index >= 0);
+ eassert (it->current.dpvec_index >= 0);
else
- xassert (it->current.dpvec_index < 0);
+ eassert (it->current.dpvec_index < 0);
}
#define CHECK_IT(IT) check_it ((IT))
#endif /* not 0 */
-#if GLYPH_DEBUG && XASSERTS
+#if defined GLYPH_DEBUG && defined ENABLE_CHECKING
/* Check that the window end of window W is what we expect it
to be---the last row in the current matrix displaying text. */
&& !NILP (w->window_end_valid))
{
struct glyph_row *row;
- xassert ((row = MATRIX_ROW (w->current_matrix,
+ eassert ((row = MATRIX_ROW (w->current_matrix,
XFASTINT (w->window_end_vpos)),
!row->enabled_p
|| MATRIX_ROW_DISPLAYS_TEXT_P (row)
#define CHECK_WINDOW_END(W) (void) 0
-#endif
+#endif /* GLYPH_DEBUG and ENABLE_CHECKING */
+/* Return mark position if current buffer has the region of non-zero length,
+ or -1 otherwise. */
+
+static ptrdiff_t
+markpos_of_region (void)
+{
+ if (!NILP (Vtransient_mark_mode)
+ && !NILP (BVAR (current_buffer, mark_active))
+ && XMARKER (BVAR (current_buffer, mark))->buffer != NULL)
+ {
+ ptrdiff_t markpos = XMARKER (BVAR (current_buffer, mark))->charpos;
+
+ if (markpos != PT)
+ return markpos;
+ }
+ return -1;
+}
-\f
/***********************************************************************
Iterator initialization
***********************************************************************/
ptrdiff_t charpos, ptrdiff_t bytepos,
struct glyph_row *row, enum face_id base_face_id)
{
- int highlight_region_p;
+ ptrdiff_t markpos;
enum face_id remapped_base_face_id = base_face_id;
/* Some precondition checks. */
- xassert (w != NULL && it != NULL);
- xassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
+ eassert (w != NULL && it != NULL);
+ eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
&& charpos <= ZV));
/* If face attributes have been changed since the last redisplay,
/* Perhaps remap BASE_FACE_ID to a user-specified alternative. */
if (! NILP (Vface_remapping_alist))
- remapped_base_face_id = lookup_basic_face (XFRAME (w->frame), base_face_id);
+ remapped_base_face_id
+ = lookup_basic_face (XFRAME (w->frame), base_face_id);
/* Use one of the mode line rows of W's desired matrix if
appropriate. */
is invisible. >0 means lines indented more than this value are
invisible. */
it->selective = (INTEGERP (BVAR (current_buffer, selective_display))
- ? clip_to_bounds (-1, XINT (BVAR (current_buffer,
- selective_display)),
- PTRDIFF_MAX)
+ ? (clip_to_bounds
+ (-1, XINT (BVAR (current_buffer, selective_display)),
+ PTRDIFF_MAX))
: (!NILP (BVAR (current_buffer, selective_display))
? -1 : 0));
it->selective_display_ellipsis_p
/* Are multibyte characters enabled in current_buffer? */
it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
- /* Non-zero if we should highlight the region. */
- highlight_region_p
- = (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active))
- && XMARKER (BVAR (current_buffer, mark))->buffer != 0);
-
- /* Set IT->region_beg_charpos and IT->region_end_charpos to the
- start and end of a visible region in window IT->w. Set both to
- -1 to indicate no region. */
- if (highlight_region_p
+ /* If visible region is of non-zero length, set IT->region_beg_charpos
+ and IT->region_end_charpos to the start and end of a visible region
+ in window IT->w. Set both to -1 to indicate no region. */
+ markpos = markpos_of_region ();
+ if (0 <= markpos
/* Maybe highlight only in selected window. */
&& (/* Either show region everywhere. */
highlight_nonselected_windows
&& WINDOWP (minibuf_selected_window)
&& w == XWINDOW (minibuf_selected_window))))
{
- ptrdiff_t markpos = marker_position (BVAR (current_buffer, mark));
it->region_beg_charpos = min (PT, markpos);
it->region_end_charpos = max (PT, markpos);
}
/* 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)
{
/* We will need the truncation glyph. */
- xassert (it->glyph_row == NULL);
+ eassert (it->glyph_row == NULL);
produce_special_glyphs (it, IT_TRUNCATION);
it->truncation_pixel_width = it->pixel_width;
}
else
{
/* We will need the continuation glyph. */
- xassert (it->glyph_row == NULL);
+ eassert (it->glyph_row == NULL);
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)
relative_index = (it->current.overlay_string_index
% OVERLAY_STRING_CHUNK_SIZE);
it->string = it->overlay_strings[relative_index];
- xassert (STRINGP (it->string));
+ eassert (STRINGP (it->string));
it->current.string_pos = pos->string_pos;
it->method = GET_FROM_STRING;
+ it->end_charpos = SCHARS (it->string);
+ /* Set up the bidi iterator for this overlay string. */
+ if (it->bidi_p)
+ {
+ it->bidi_it.string.lstring = it->string;
+ it->bidi_it.string.s = NULL;
+ it->bidi_it.string.schars = SCHARS (it->string);
+ it->bidi_it.string.bufpos = it->overlay_strings_charpos;
+ it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
+ it->bidi_it.string.unibyte = !it->multibyte_p;
+ bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
+ FRAME_WINDOW_P (it->f), &it->bidi_it);
+
+ /* Synchronize the state of the bidi iterator with
+ pos->string_pos. For any string position other than
+ zero, this will be done automagically when we resume
+ iteration over the string and get_visually_first_element
+ is called. But if string_pos is zero, and the string is
+ to be reordered for display, we need to resync manually,
+ since it could be that the iteration state recorded in
+ pos ended at string_pos of 0 moving backwards in string. */
+ if (CHARPOS (pos->string_pos) == 0)
+ {
+ get_visually_first_element (it);
+ if (IT_STRING_CHARPOS (*it) != 0)
+ do {
+ /* Paranoia. */
+ eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
+ bidi_move_to_visually_next (&it->bidi_it);
+ } while (it->bidi_it.charpos != 0);
+ }
+ eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
+ && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
+ }
}
if (CHARPOS (pos->string_pos) >= 0)
string. This can only be a string from a `display' property.
IT should already be filled with that string. */
it->current.string_pos = pos->string_pos;
- xassert (STRINGP (it->string));
+ eassert (STRINGP (it->string));
+ if (it->bidi_p)
+ bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
+ FRAME_WINDOW_P (it->f), &it->bidi_it);
}
/* Restore position in display vector translations, control
{
if (it->dpvec == NULL)
get_next_display_element (it);
- xassert (it->dpvec && it->current.dpvec_index == 0);
+ eassert (it->dpvec && it->current.dpvec_index == 0);
it->current.dpvec_index = pos->dpvec_index;
}
interval if there isn't such an interval. */
position = make_number (charpos);
iv = validate_interval_range (object, &position, &position, 0);
- if (!NULL_INTERVAL_P (iv))
+ if (iv)
{
Lisp_Object values_here[LAST_PROP_IDX];
struct props *p;
/* Look for an interval following iv that has different
properties. */
for (next_iv = next_interval (iv);
- (!NULL_INTERVAL_P (next_iv)
+ (next_iv
&& (NILP (limit)
|| XFASTINT (limit) > next_iv->position));
next_iv = next_interval (next_iv))
break;
}
- if (!NULL_INTERVAL_P (next_iv))
+ if (next_iv)
{
if (INTEGERP (limit)
&& next_iv->position >= XFASTINT (limit))
stoppos, it->string);
}
- xassert (STRINGP (it->string)
+ eassert (STRINGP (it->string)
|| (it->stop_charpos >= BEGV
&& it->stop_charpos >= IT_CHARPOS (*it)));
}
val = Vfontification_functions;
specbind (Qfontification_functions, Qnil);
- xassert (it->end_charpos == ZV);
+ eassert (it->end_charpos == ZV);
if (!CONSP (val) || EQ (XCAR (val), Qlambda))
safe_call1 (val, pos);
}
/* There isn't much we can reasonably do to protect against
misbehaving fontification, but here's a fig leaf. */
- else if (!NILP (BVAR (obuf, name)))
+ else if (BUFFER_LIVE_P (obuf))
set_buffer_internal_1 (obuf);
/* The fontification code may have added/removed text.
if (new_face_id != it->face_id)
{
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_FROM_ID. This will happen if this
+ is the initial call that gets the face. */
+ struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
- /* If new face has a box but old face has not, this is
- the start of a run of characters with box, i.e. it has
- a shadow on the left side. The value of face_id of the
- iterator will be -1 if this is the initial call that gets
- the face. In this case, we have to look in front of IT's
- position and see whether there is a face != new_face_id. */
- it->start_of_box_run_p
- = (new_face->box != FACE_NO_BOX
- && (it->face_id >= 0
- || IT_CHARPOS (*it) == BEG
- || new_face_id != face_before_it_pos (it)));
+ /* 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
+ face there that's different from new_face_id. */
+ if (!old_face && IT_CHARPOS (*it) > BEG)
+ {
+ int prev_face_id = face_before_it_pos (it);
+
+ old_face = FACE_FROM_ID (it->f, prev_face_id);
+ }
+
+ /* If the new face has a box, but the old face does not,
+ this is the start of a run of characters with box face,
+ i.e. this character has a shadow on the left side. */
+ it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
+ && (old_face == NULL || !old_face->box));
it->face_box_p = new_face->box != FACE_NO_BOX;
}
}
{
int face_id = it->base_face_id, i;
- xassert (STRINGP (it->string));
+ eassert (STRINGP (it->string));
for (i = it->sp - 1; i >= 0; --i)
if (NILP (it->stack[i].string))
struct it it_copy;
void *it_copy_data = NULL;
- xassert (it->s == NULL);
+ eassert (it->s == NULL);
if (STRINGP (it->string))
{
charpos = it_copy.bidi_it.charpos;
}
}
- xassert (0 <= charpos && charpos <= SCHARS (it->string));
+ eassert (0 <= charpos && charpos <= SCHARS (it->string));
if (it->current.overlay_string_index >= 0)
bufpos = IT_CHARPOS (*it);
it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
}
}
- xassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
+ eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
/* Determine face for CHARSET_ASCII, or unibyte. */
face_id = face_at_buffer_position (it->w,
handle_invisible_prop (struct it *it)
{
enum prop_handled handled = HANDLED_NORMALLY;
+ int invis_p;
+ Lisp_Object prop;
if (STRINGP (it->string))
{
- Lisp_Object prop, end_charpos, limit, charpos;
+ Lisp_Object end_charpos, limit, charpos;
/* Get the value of the invisible text property at the
current position. Value will be nil if there is no such
property. */
charpos = make_number (IT_STRING_CHARPOS (*it));
prop = Fget_text_property (charpos, Qinvisible, it->string);
+ invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
- if (!NILP (prop)
- && IT_STRING_CHARPOS (*it) < it->end_charpos)
+ if (invis_p && IT_STRING_CHARPOS (*it) < it->end_charpos)
{
- ptrdiff_t endpos;
+ /* Record whether we have to display an ellipsis for the
+ invisible text. */
+ int display_ellipsis_p = (invis_p == 2);
+ ptrdiff_t len, endpos;
handled = HANDLED_RECOMPUTE_PROPS;
- /* Get the position at which the next change of the
- invisible text property can be found in IT->string.
- Value will be nil if the property value is the same for
- all the rest of IT->string. */
- XSETINT (limit, SCHARS (it->string));
- end_charpos = Fnext_single_property_change (charpos, Qinvisible,
- it->string, limit);
-
- /* Text at current position is invisible. The next
- change in the property is at position end_charpos.
- Move IT's current position to that position. */
- if (INTEGERP (end_charpos)
- && (endpos = XFASTINT (end_charpos)) < XFASTINT (limit))
+ /* Get the position at which the next visible text can be
+ found in IT->string, if any. */
+ endpos = len = SCHARS (it->string);
+ XSETINT (limit, len);
+ do
+ {
+ end_charpos = Fnext_single_property_change (charpos, Qinvisible,
+ it->string, limit);
+ if (INTEGERP (end_charpos))
+ {
+ endpos = XFASTINT (end_charpos);
+ prop = Fget_text_property (end_charpos, Qinvisible, it->string);
+ invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
+ if (invis_p == 2)
+ display_ellipsis_p = 1;
+ }
+ }
+ while (invis_p && endpos < len);
+
+ if (display_ellipsis_p)
+ it->ellipsis_p = 1;
+
+ if (endpos < len)
{
+ /* Text at END_CHARPOS is visible. Move IT there. */
struct text_pos old;
ptrdiff_t oldpos;
/* The rest of the string is invisible. If this is an
overlay string, proceed with the next overlay string
or whatever comes and return a character from there. */
- if (it->current.overlay_string_index >= 0)
+ if (it->current.overlay_string_index >= 0
+ && !display_ellipsis_p)
{
next_overlay_string (it);
/* Don't check for overlay strings when we just
}
else
{
- int invis_p;
ptrdiff_t newpos, next_stop, start_charpos, tem;
- Lisp_Object pos, prop, overlay;
+ Lisp_Object pos, overlay;
/* First of all, is there invisible text at this position? */
tem = start_charpos = IT_CHARPOS (*it);
it->ellipsis_p = (it->stack[it->sp - 1].display_ellipsis_p != 0);
pop_it (it);
- xassert (it->sp > 0
+ eassert (it->sp > 0
|| (NILP (it->string)
&& it->method == GET_FROM_BUFFER
&& it->stop_charpos >= BEGV
SET_TEXT_POS (it->current.string_pos, 0, 0);
it->method = GET_FROM_STRING;
it->stop_charpos = 0;
+ it->end_charpos = SCHARS (it->string);
if (it->cmp_it.stop_pos >= 0)
it->cmp_it.stop_pos = 0;
it->prev_stop = 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)
for (ov = current_buffer->overlays_before; ov; ov = ov->next)
{
XSETMISC (overlay, ov);
- xassert (OVERLAYP (overlay));
+ eassert (OVERLAYP (overlay));
start = OVERLAY_POSITION (OVERLAY_START (overlay));
end = OVERLAY_POSITION (OVERLAY_END (overlay));
for (ov = current_buffer->overlays_after; ov; ov = ov->next)
{
XSETMISC (overlay, ov);
- xassert (OVERLAYP (overlay));
+ eassert (OVERLAYP (overlay));
start = OVERLAY_POSITION (OVERLAY_START (overlay));
end = OVERLAY_POSITION (OVERLAY_END (overlay));
strings. */
if (compute_stop_p)
compute_stop_pos (it);
- xassert (it->face_id >= 0);
+ eassert (it->face_id >= 0);
/* Save IT's settings. They are restored after all overlay
strings have been processed. */
- xassert (!compute_stop_p || it->sp == 0);
+ eassert (!compute_stop_p || it->sp == 0);
/* When called from handle_stop, there might be an empty display
string loaded. In that case, don't bother saving it. But
it->string = it->overlay_strings[0];
it->from_overlay = Qnil;
it->stop_charpos = 0;
- xassert (STRINGP (it->string));
+ eassert (STRINGP (it->string));
it->end_charpos = SCHARS (it->string);
it->prev_stop = 0;
it->base_level_stop = 0;
{
struct iterator_stack_entry *p;
- xassert (it->sp < IT_STACK_SIZE);
+ eassert (it->sp < IT_STACK_SIZE);
p = it->stack + it->sp;
p->stop_charpos = it->stop_charpos;
p->prev_stop = it->prev_stop;
p->base_level_stop = it->base_level_stop;
p->cmp_it = it->cmp_it;
- xassert (it->face_id >= 0);
+ eassert (it->face_id >= 0);
p->face_id = it->face_id;
p->string = it->string;
p->method = it->method;
ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
ptrdiff_t bob = (buffer_p ? BEGV : 0);
- xassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
+ eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
/* Maybe initialize paragraph direction. If we are at the beginning
of a new paragraph, next_element_from_buffer may not have a
struct iterator_stack_entry *p;
int from_display_prop = it->from_disp_prop_p;
- xassert (it->sp > 0);
+ eassert (it->sp > 0);
--it->sp;
p = it->stack + it->sp;
it->stop_charpos = p->stop_charpos;
&& (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
iterate_out_of_display_property (it);
- xassert ((BUFFERP (it->object)
+ eassert ((BUFFERP (it->object)
&& IT_CHARPOS (*it) == it->bidi_it.charpos
&& IT_BYTEPOS (*it) == it->bidi_it.bytepos)
|| (STRINGP (it->object)
ptrdiff_t limit = find_next_newline_no_quit (start, 1);
Lisp_Object pos;
- xassert (!STRINGP (it->string));
+ eassert (!STRINGP (it->string));
/* If there isn't any `display' property in sight, and no
overlays, we can just use the position of the newline in
{
Lisp_Object prop;
prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1),
- Qinvisible, it->window);
+ Qinvisible, it->window);
if (TEXT_PROP_MEANS_INVISIBLE (prop))
continue;
}
it->continuation_lines_width = 0;
- xassert (IT_CHARPOS (*it) >= BEGV);
- xassert (IT_CHARPOS (*it) == BEGV
+ eassert (IT_CHARPOS (*it) >= BEGV);
+ eassert (IT_CHARPOS (*it) == BEGV
|| FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
CHECK_IT (it);
}
&& indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
it->selective))
{
- xassert (IT_BYTEPOS (*it) == BEGV
+ eassert (IT_BYTEPOS (*it) == BEGV
|| FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
newline_found_p =
forward_to_next_line_start (it, &skipped_p, &bidi_it_prev);
reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
{
/* Don't call this function when scanning a C string. */
- xassert (it->s == NULL);
+ eassert (it->s == NULL);
/* POS must be a reasonable value. */
- xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
+ eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
it->current.pos = it->position = pos;
it->end_charpos = ZV;
it->stop_charpos = CHARPOS (pos);
it->base_level_stop = CHARPOS (pos);
}
+ /* This make the information stored in it->cmp_it invalidate. */
+ it->cmp_it.id = -1;
}
memset (&it->current, 0, sizeof it->current);
it->current.overlay_string_index = -1;
it->current.dpvec_index = -1;
- xassert (charpos >= 0);
+ eassert (charpos >= 0);
/* If STRING is specified, use its multibyteness, otherwise use the
setting of MULTIBYTE, if specified. */
if (s == NULL)
{
- xassert (STRINGP (string));
+ eassert (STRINGP (string));
it->string = string;
it->s = NULL;
it->end_charpos = it->string_nchars = SCHARS (string);
if (! it->multibyte_p && ! ASCII_CHAR_P (c))
{
- xassert (SINGLE_BYTE_CHAR_P (c));
+ eassert (SINGLE_BYTE_CHAR_P (c));
if (unibyte_display_via_language_environment)
{
c = DECODE_CHAR (unibyte, c);
}
else
{
- xassert (it->len != 0);
+ eassert (it->len != 0);
if (!it->bidi_p)
{
IT_BYTEPOS (*it), stop, Qnil);
}
}
- xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
+ eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
}
break;
case GET_FROM_STRING:
/* Current display element is a character from a Lisp string. */
- xassert (it->s == NULL && STRINGP (it->string));
+ eassert (it->s == NULL && STRINGP (it->string));
/* Don't advance past string end. These conditions are true
when set_iterator_to_next is called at the end of
get_next_display_element, in which case the Lisp string is
/* The position etc with which we have to proceed are on
the stack. The position may be at the end of a string,
if the `display' property takes up the whole string. */
- xassert (it->sp > 0);
+ eassert (it->sp > 0);
pop_it (it);
if (it->method == GET_FROM_STRING)
goto consider_string_end;
default:
/* There are no other methods defined, so this should be a bug. */
- abort ();
+ emacs_abort ();
}
- xassert (it->method != GET_FROM_STRING
+ eassert (it->method != GET_FROM_STRING
|| (STRINGP (it->string)
&& IT_STRING_CHARPOS (*it) >= 0));
}
Lisp_Object gc;
/* Precondition. */
- xassert (it->dpvec && it->current.dpvec_index >= 0);
+ eassert (it->dpvec && it->current.dpvec_index >= 0);
it->face_id = it->saved_face_id;
if (STRINGP (it->string))
{
- xassert (!it->s);
+ eassert (!it->s);
stop = SCHARS (it->string);
if (stop > it->end_charpos)
stop = it->end_charpos;
{
struct text_pos position;
- xassert (STRINGP (it->string));
- xassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
- xassert (IT_STRING_CHARPOS (*it) >= 0);
+ eassert (STRINGP (it->string));
+ eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
+ eassert (IT_STRING_CHARPOS (*it) >= 0);
position = it->current.string_pos;
/* With bidi reordering, the character to display might not be the
{
int success_p = 1;
- xassert (it->s);
- xassert (!it->bidi_p || it->s == it->bidi_it.string.s);
+ eassert (it->s);
+ eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
it->what = IT_CHARACTER;
BYTEPOS (it->position) = CHARPOS (it->position) = 0;
it->object = Qnil;
ptrdiff_t save_stop_pos = it->stop_charpos;
ptrdiff_t save_end_pos = it->end_charpos;
- xassert (NILP (it->string) && !it->s);
- xassert (it->bidi_p);
+ eassert (NILP (it->string) && !it->s);
+ eassert (it->bidi_p);
it->bidi_p = 0;
do
{
it->end_charpos = min (charpos + 1, ZV);
charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
- SET_TEXT_POS (pos, charpos, BYTE_TO_CHAR (charpos));
+ SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
reseat_1 (it, pos, 0);
compute_stop_pos (it);
/* We must advance forward, right? */
if (it->stop_charpos <= charpos)
- abort ();
+ emacs_abort ();
}
while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
ptrdiff_t next_stop;
/* Scan in strict logical order. */
- xassert (it->bidi_p);
+ eassert (it->bidi_p);
it->bidi_p = 0;
do
{
compute_stop_pos (it);
/* We must advance forward, right? */
if (it->stop_charpos <= it->prev_stop)
- abort ();
+ emacs_abort ();
charpos = it->stop_charpos;
}
while (charpos <= where_we_are);
{
int success_p = 1;
- xassert (IT_CHARPOS (*it) >= BEGV);
- xassert (NILP (it->string) && !it->s);
- xassert (!it->bidi_p
+ eassert (IT_CHARPOS (*it) >= BEGV);
+ eassert (NILP (it->string) && !it->s);
+ eassert (!it->bidi_p
|| (EQ (it->bidi_it.string.lstring, Qnil)
&& it->bidi_it.string.s == NULL));
}
/* Value is zero if end of buffer reached. */
- xassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
+ eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
return success_p;
}
/* IT->glyph_row should be non-null, i.e. we should be actually
displaying something, or otherwise we should not run the hook. */
- xassert (it->glyph_row);
+ eassert (it->glyph_row);
/* Set up hook arguments. */
args[0] = Qredisplay_end_trigger_functions;
/* Since we are *trying* to run these functions, don't try to run
them again, even if they get an error. */
- it->w->redisplay_end_trigger = Qnil;
+ wset_redisplay_end_trigger (it->w, Qnil);
Frun_hook_with_args (3, args);
/* Notice if it changed the face of the character we are on. */
/* 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))
necessary here because of lines consisting of a line end,
only. The line end will not produce any glyphs and we
would never get MOVE_X_REACHED. */
- xassert (it->nglyphs == 0);
+ eassert (it->nglyphs == 0);
result = MOVE_X_REACHED;
break;
}
&& 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;
break;
default:
- abort ();
+ emacs_abort ();
}
/* Reset/increment for the next run. */
ptrdiff_t start_pos;
move_further_back:
- xassert (dy >= 0);
+ eassert (dy >= 0);
start_pos = IT_CHARPOS (*it);
|| (it2.method == GET_FROM_STRING
&& IT_CHARPOS (it2) == start_pos
&& SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
- xassert (IT_CHARPOS (*it) >= BEGV);
+ eassert (IT_CHARPOS (*it) >= BEGV);
SAVE_IT (it3, it2, it3data);
move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
- xassert (IT_CHARPOS (*it) >= BEGV);
+ eassert (IT_CHARPOS (*it) >= BEGV);
/* H is the actual vertical distance from the position in *IT
and the starting position. */
h = it2.current_y - it->current_y;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
USE_SAFE_ALLOCA;
- /* Do nothing if called asynchronously. Inserting text into
- a buffer may call after-change-functions and alike and
- that would means running Lisp asynchronously. */
- if (handling_signal)
- return;
-
fmt = msg = Qnil;
GCPRO4 (fmt, msg, arg1, arg2);
msg = Fformat (3, args);
len = SBYTES (msg) + 1;
- SAFE_ALLOCA (buffer, char *, len);
+ buffer = SAFE_ALLOCA (len);
memcpy (buffer, SDATA (msg), len);
message_dolog (buffer, len - 1, 1, 0);
int old_windows_or_buffers_changed = windows_or_buffers_changed;
ptrdiff_t point_at_end = 0;
ptrdiff_t zv_at_end = 0;
- Lisp_Object old_deactivate_mark, tem;
+ Lisp_Object old_deactivate_mark;
+ bool shown;
struct gcpro gcpro1;
old_deactivate_mark = Vdeactivate_mark;
oldbuf = current_buffer;
Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
- BVAR (current_buffer, undo_list) = Qt;
+ bset_undo_list (current_buffer, Qt);
oldpoint = message_dolog_marker1;
set_marker_restricted (oldpoint, make_number (PT), Qnil);
{
char dupstr[sizeof " [ times]"
+ INT_STRLEN_BOUND (printmax_t)];
- int duplen;
/* If you change this format, don't forget to also
change message_log_check_duplicate. */
- sprintf (dupstr, " [%"pMd" times]", dups);
- duplen = strlen (dupstr);
+ int duplen = sprintf (dupstr, " [%"pMd" times]", dups);
TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
insert_1 (dupstr, duplen, 1, 0, 1);
}
del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
}
}
- BEGV = XMARKER (oldbegv)->charpos;
+ BEGV = marker_position (oldbegv);
BEGV_BYTE = marker_byte_position (oldbegv);
if (zv_at_end)
}
else
{
- ZV = XMARKER (oldzv)->charpos;
+ ZV = marker_position (oldzv);
ZV_BYTE = marker_byte_position (oldzv);
}
else
/* We can't do Fgoto_char (oldpoint) because it will run some
Lisp code. */
- TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
- XMARKER (oldpoint)->bytepos);
+ TEMP_SET_PT_BOTH (marker_position (oldpoint),
+ marker_byte_position (oldpoint));
UNGCPRO;
unchain_marker (XMARKER (oldpoint));
unchain_marker (XMARKER (oldbegv));
unchain_marker (XMARKER (oldzv));
- tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
+ shown = buffer_window_count (current_buffer) > 0;
set_buffer_internal (oldbuf);
- if (NILP (tem))
+ if (!shown)
windows_or_buffers_changed = old_windows_or_buffers_changed;
message_log_need_newline = !nlflag;
Vdeactivate_mark = old_deactivate_mark;
do_pending_window_change (0);
echo_area_display (1);
do_pending_window_change (0);
- if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+ if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
(*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
}
}
message_log_maybe_newline ();
if (STRINGP (m))
{
- char *buffer;
USE_SAFE_ALLOCA;
-
- SAFE_ALLOCA (buffer, char *, nbytes);
+ char *buffer = SAFE_ALLOCA (nbytes);
memcpy (buffer, SDATA (m), nbytes);
message_dolog (buffer, nbytes, 1, multibyte);
SAFE_FREE ();
do_pending_window_change (0);
echo_area_display (1);
do_pending_window_change (0);
- if (FRAME_TERMINAL (f)->frame_up_to_date_hook != 0 && ! gc_in_progress)
+ if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
(*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
}
}
for (i = 0; i < 2; ++i)
if (!BUFFERP (echo_buffer[i])
- || NILP (BVAR (XBUFFER (echo_buffer[i]), name)))
+ || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
{
char name[30];
Lisp_Object old_buffer;
int j;
old_buffer = echo_buffer[i];
- sprintf (name, " *Echo Area %d*", i);
- echo_buffer[i] = Fget_buffer_create (build_string (name));
- BVAR (XBUFFER (echo_buffer[i]), truncate_lines) = Qnil;
+ echo_buffer[i] = Fget_buffer_create
+ (make_formatted_string (name, " *Echo Area %d*", i));
+ bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
/* to force word wrap in echo area -
it was decided to postpone this*/
/* XBUFFER (echo_buffer[i])->word_wrap = Qt; */
set_buffer_internal_1 (XBUFFER (buffer));
if (w)
{
- w->buffer = buffer;
+ wset_buffer (w, buffer);
set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
}
- BVAR (current_buffer, undo_list) = Qt;
- BVAR (current_buffer, read_only) = Qnil;
+ bset_undo_list (current_buffer, Qt);
+ bset_read_only (current_buffer, Qnil);
specbind (Qinhibit_read_only, Qt);
specbind (Qinhibit_modification_hooks, Qt);
if (clear_buffer_p && Z > BEG)
del_range (BEG, Z);
- xassert (BEGV >= BEG);
- xassert (ZV <= Z && ZV >= BEGV);
+ eassert (BEGV >= BEG);
+ eassert (ZV <= Z && ZV >= BEGV);
rc = fn (a1, a2, a3, a4);
- xassert (BEGV >= BEG);
- xassert (ZV <= Z && ZV >= BEGV);
+ eassert (BEGV >= BEG);
+ eassert (ZV <= Z && ZV >= BEGV);
unbind_to (count, Qnil);
return rc;
{
XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
ASET (vector, i, w->buffer); ++i;
- ASET (vector, i, make_number (XMARKER (w->pointm)->charpos)); ++i;
- ASET (vector, i, make_number (XMARKER (w->pointm)->bytepos)); ++i;
+ ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
+ ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
}
else
{
ASET (vector, i, Qnil);
}
- xassert (i == ASIZE (vector));
+ eassert (i == ASIZE (vector));
return vector;
}
charpos = AREF (vector, 5);
bytepos = AREF (vector, 6);
- w->buffer = buffer;
+ wset_buffer (w, buffer);
set_marker_both (w->pointm, buffer,
XFASTINT (charpos), XFASTINT (bytepos));
}
/* Switch to that buffer and clear it. */
set_buffer_internal (XBUFFER (echo_area_buffer[0]));
- BVAR (current_buffer, truncate_lines) = Qnil;
+ bset_truncate_lines (current_buffer, Qnil);
if (Z > BEG)
{
{
/* Someone switched buffers between print requests. */
set_buffer_internal (XBUFFER (echo_area_buffer[0]));
- BVAR (current_buffer, truncate_lines) = Qnil;
+ bset_truncate_lines (current_buffer, Qnil);
}
}
}
struct frame *f = XFRAME (w->frame);
int window_height_changed_p = 0;
- xassert (MINI_WINDOW_P (w));
+ eassert (MINI_WINDOW_P (w));
/* By default, start display at the beginning. */
set_marker_both (w->start, w->buffer,
max_height = total_height / 4;
/* Correct that max. height if it's bogus. */
- max_height = max (1, max_height);
- max_height = min (total_height, max_height);
+ max_height = clip_to_bounds (1, max_height, total_height);
/* Find out the height of the text in the window. */
if (it.line_wrap == TRUNCATE)
empty. This is a relatively infrequent operation, so it's not
worth optimizing. */
-int
+bool
push_message (void)
{
- Lisp_Object msg;
- msg = current_message ();
+ Lisp_Object msg = current_message ();
Vmessage_stack = Fcons (msg, Vmessage_stack);
return STRINGP (msg);
}
{
Lisp_Object msg;
- xassert (CONSP (Vmessage_stack));
+ eassert (CONSP (Vmessage_stack));
msg = XCAR (Vmessage_stack);
if (STRINGP (msg))
message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
static void
pop_message (void)
{
- xassert (CONSP (Vmessage_stack));
+ eassert (CONSP (Vmessage_stack));
Vmessage_stack = XCDR (Vmessage_stack);
}
check_message_stack (void)
{
if (!NILP (Vmessage_stack))
- abort ();
+ emacs_abort ();
}
return 0;
}
-
/* Set the current message to a substring of S or STRING.
If STRING is a Lisp string, set the message to the first NBYTES
(intptr_t) s, string, nbytes, multibyte_p);
message_buf_print = 0;
help_echo_showing_p = 0;
+
+ if (STRINGP (Vdebug_on_message)
+ && fast_string_match (Vdebug_on_message, string) >= 0)
+ call_debugger (list2 (Qerror, string));
}
!= !NILP (BVAR (current_buffer, enable_multibyte_characters)))
Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
- BVAR (current_buffer, truncate_lines) = message_truncate_lines ? Qt : Qnil;
+ bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
- BVAR (current_buffer, bidi_paragraph_direction) = Qleft_to_right;
+ bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
/* Insert new message at BEG. */
TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
{
if (f->resized_p)
{
- Fredraw_frame (frame);
+ redraw_frame (f);
f->force_flush_display_p = 1;
}
clear_current_matrices (f);
#endif /* HAVE_WINDOW_SYSTEM */
/* Redraw garbaged frames. */
- if (frame_garbaged)
- clear_garbaged_frames ();
+ clear_garbaged_frames ();
if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
{
return window_height_changed_p;
}
+/* Nonzero if the current window's buffer is shown in more than one
+ window and was modified since last redisplay. */
+
+static int
+buffer_shared_and_changed (void)
+{
+ return (buffer_window_count (current_buffer) > 1
+ && UNCHANGED_MODIFIED < MODIFF);
+}
+
+/* Nonzero if W doesn't reflect the actual state of current buffer due
+ to its text or overlays change. FIXME: this may be called when
+ XBUFFER (w->buffer) != current_buffer, which looks suspicious. */
+
+static int
+window_outdated (struct window *w)
+{
+ return (w->last_modified < MODIFF
+ || w->last_overlay_modified < OVERLAY_MODIFF);
+}
+
+/* Nonzero if W's buffer was changed but not saved or Transient Mark mode
+ is enabled and mark of W's buffer was changed since last W's update. */
+
+static int
+window_buffer_changed (struct window *w)
+{
+ struct buffer *b = XBUFFER (w->buffer);
+
+ eassert (BUFFER_LIVE_P (b));
+
+ return (((BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star)
+ || ((!NILP (Vtransient_mark_mode) && !NILP (BVAR (b, mark_active)))
+ != !NILP (w->region_showing)));
+}
+
+/* Nonzero if W has %c in its mode line and mode line should be updated. */
+
+static int
+mode_line_update_needed (struct window *w)
+{
+ return (!NILP (w->column_number_displayed)
+ && !(PT == w->last_point && !window_outdated (w))
+ && (XFASTINT (w->column_number_displayed) != current_column ()));
+}
-\f
/***********************************************************************
Mode Lines and Frame Titles
***********************************************************************/
|| f->explicit_name)
{
/* Do we have more than one visible frame on this X display? */
- Lisp_Object tail;
- Lisp_Object fmt;
+ Lisp_Object tail, other_frame, fmt;
ptrdiff_t title_start;
char *title;
ptrdiff_t len;
struct it it;
ptrdiff_t count = SPECPDL_INDEX ();
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, other_frame)
{
- Lisp_Object other_frame = XCAR (tail);
struct frame *tf = XFRAME (other_frame);
if (tf != f
(f, current_buffer, selected_window, 0));
Fselect_window (f->selected_window, Qt);
- set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer));
+ set_buffer_internal_1
+ (XBUFFER (XWINDOW (f->selected_window)->buffer));
fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
mode_line_target = MODE_LINE_TITLE;
/* Update the menu bar item lists, if appropriate. This has to be
done before any actual redisplay or generation of display lines. */
all_windows = (update_mode_lines
- || buffer_shared > 1
+ || buffer_shared_and_changed ()
|| windows_or_buffers_changed);
if (all_windows)
{
#ifdef HAVE_NS
if (windows_or_buffers_changed
&& FRAME_NS_P (f))
- ns_set_doc_edited (f, Fbuffer_modified_p
- (XWINDOW (f->selected_window)->buffer));
+ ns_set_doc_edited
+ (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->buffer));
#endif
UNGCPRO;
}
/* This used to test w->update_mode_line, but we believe
there is no need to recompute the menu in that case. */
|| update_mode_lines
- || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
- < BUF_MODIFF (XBUFFER (w->buffer)))
- != w->last_had_star)
- || ((!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
- != !NILP (w->region_showing)))
+ || window_buffer_changed (w))
{
struct buffer *prev = current_buffer;
ptrdiff_t count = SPECPDL_INDEX ();
}
XSETFRAME (Vmenu_updating_frame, f);
- FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
+ fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
/* Redisplay the menu bar in case we changed it. */
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
This will also set the cursor position of W. */
if (updated_window == NULL)
{
- BLOCK_INPUT;
+ block_input ();
display_and_set_cursor (w, 1, hpos, vpos, x, y);
if (FRAME_RIF (SELECTED_FRAME ())->flush_display_optional)
FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (SELECTED_FRAME ());
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
int last_tool_bar_item;
-
+/* Select `frame' temporarily without running all the code in
+ do_switch_frame.
+ FIXME: Maybe do_switch_frame should be trimmed down similarly
+ when `norecord' is set. */
static Lisp_Object
-update_tool_bar_unwind (Lisp_Object frame)
+fast_set_selected_frame (Lisp_Object frame)
{
- selected_frame = frame;
+ if (!EQ (selected_frame, frame))
+ {
+ selected_frame = frame;
+ selected_window = XFRAME (frame)->selected_window;
+ }
return Qnil;
}
if (windows_or_buffers_changed
|| w->update_mode_line
|| update_mode_lines
- || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
- < BUF_MODIFF (XBUFFER (w->buffer)))
- != w->last_had_star)
- || ((!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
- != !NILP (w->region_showing)))
+ || window_buffer_changed (w))
{
struct buffer *prev = current_buffer;
ptrdiff_t count = SPECPDL_INDEX ();
before calling tool_bar_items, because the calculation of
the tool-bar keymap uses the selected frame (see
`tool-bar-make-keymap' in tool-bar.el). */
- record_unwind_protect (update_tool_bar_unwind, selected_frame);
+ eassert (EQ (selected_window,
+ /* Since we only explicitly preserve selected_frame,
+ check that selected_window would be redundant. */
+ XFRAME (selected_frame)->selected_window));
+ record_unwind_protect (fast_set_selected_frame, selected_frame);
XSETFRAME (frame, f);
- selected_frame = frame;
+ fast_set_selected_frame (frame);
/* Build desired tool-bar items from keymaps. */
- new_tool_bar = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
- &new_n_tool_bar);
+ new_tool_bar
+ = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
+ &new_n_tool_bar);
/* Redisplay the tool-bar if we changed it. */
if (new_n_tool_bar != f->n_tool_bar_items
/* Redisplay that happens asynchronously due to an expose event
may access f->tool_bar_items. Make sure we update both
variables within BLOCK_INPUT so no such event interrupts. */
- BLOCK_INPUT;
- f->tool_bar_items = new_tool_bar;
+ block_input ();
+ fset_tool_bar_items (f, new_tool_bar);
f->n_tool_bar_items = new_n_tool_bar;
w->update_mode_line = 1;
- UNBLOCK_INPUT;
+ unblock_input ();
}
UNGCPRO;
/* Reuse f->desired_tool_bar_string, if possible. */
if (size < size_needed || NILP (f->desired_tool_bar_string))
- f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
- make_number (' '));
+ fset_desired_tool_bar_string
+ (f, Fmake_string (make_number (size_needed), make_number (' ')));
else
{
props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
is the index of the item in F's tool-bar item vector. */
for (i = 0; i < f->n_tool_bar_items; ++i)
{
-#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
+#define PROP(IDX) \
+ AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
? TOOL_BAR_IMAGE_DISABLED_SELECTED
: TOOL_BAR_IMAGE_DISABLED_DESELECTED);
- xassert (ASIZE (image) >= idx);
+ eassert (ASIZE (image) >= idx);
image = AREF (image, idx);
}
else
DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
0, 1, 0,
- doc: /* Return the number of lines occupied by the tool bar of FRAME. */)
+ doc: /* Return the number of lines occupied by the tool bar of FRAME.
+If FRAME is nil or omitted, use the selected frame. */)
(Lisp_Object frame)
{
- struct frame *f;
+ struct frame *f = decode_any_frame (frame);
struct window *w;
int nlines = 0;
- if (NILP (frame))
- frame = selected_frame;
- else
- CHECK_FRAME (frame);
- f = XFRAME (frame);
-
if (WINDOWP (f->tool_bar_window)
&& (w = XWINDOW (f->tool_bar_window),
WINDOW_TOTAL_LINES (w) > 0))
{
/* Show item in pressed state. */
show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
- hlinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
last_tool_bar_item = prop_idx;
}
else
/* Show item in released state. */
show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
- hlinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
&& last_tool_bar_item != prop_idx)
return;
- hlinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
/* If tool-bar item is not enabled, don't highlight it. */
/* Display it as active. */
show_mouse_face (hlinfo, draw);
- hlinfo->mouse_face_image_state = draw;
}
set_help_echo:
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;
if (w == XWINDOW (selected_window))
pt = PT;
else
- {
- pt = marker_position (w->pointm);
- pt = max (BEGV, pt);
- pt = min (ZV, pt);
- }
+ pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
/* Move iterator to pt starting at cursor_row->start in
a line with infinite width. */
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;
}
}
to a non-zero value. This is sometimes handy to have in a debugger
session. */
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
/* First and last unchanged row for try_window_id. */
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 */
buffer position, END is given as a distance from Z. Used in
redisplay_internal for display optimization. */
-static inline int
+static int
text_outside_line_unchanged_p (struct window *w,
ptrdiff_t start, ptrdiff_t end)
{
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 (window_outdated (w))
{
/* Gap in the line? */
if (GPT < start || Z - GPT < end)
return make_number (fringe_bitmap);
}
#endif
- return make_number (-1); /* Use default arrow bitmap */
+ return make_number (-1); /* Use default arrow bitmap. */
}
return overlay_arrow_string_or_property (var);
}
/* Reconsider the setting of B->clip_changed which is displayed
in window W. */
-static inline void
+static void
reconsider_clip_changes (struct window *w, struct buffer *b)
{
if (b->clip_changed
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;
}
}
\f
-/* Select FRAME to forward the values of frame-local variables into C
- variables so that the redisplay routines can access those values
- directly. */
-
-static void
-select_frame_for_redisplay (Lisp_Object frame)
-{
- Lisp_Object tail, tem;
- Lisp_Object old = selected_frame;
- struct Lisp_Symbol *sym;
-
- xassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame)));
-
- selected_frame = frame;
-
- do {
- for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
- if (CONSP (XCAR (tail))
- && (tem = XCAR (XCAR (tail)),
- SYMBOLP (tem))
- && (sym = indirect_variable (XSYMBOL (tem)),
- sym->redirect == SYMBOL_LOCALIZED)
- && sym->val.blv->frame_local)
- /* Use find_symbol_value rather than Fsymbol_value
- to avoid an error if it is void. */
- find_symbol_value (tem);
- } while (!EQ (frame, old) && (frame = old, 1));
-}
-
-
#define STOP_POLLING \
do { if (! polling_stopped_here) stop_polling (); \
polling_stopped_here = 1; } while (0)
ptrdiff_t count, count1;
struct frame *sf;
int polling_stopped_here = 0;
- Lisp_Object old_frame = selected_frame;
+ Lisp_Object tail, frame;
+ struct backtrace backtrace;
/* Non-zero means redisplay has to consider all windows on all
frames. Zero means, only selected_window is considered. */
int consider_all_windows_p;
- /* Non-zero means redisplay has to redisplay the miniwindow */
+ /* Non-zero means redisplay has to redisplay the miniwindow. */
int update_miniwindow_p = 0;
TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
if (redisplaying_p)
return;
- /* Record a function that resets redisplaying_p to its old value
+ /* Record a function that clears redisplaying_p
when we leave this function. */
count = SPECPDL_INDEX ();
- record_unwind_protect (unwind_redisplay,
- Fcons (make_number (redisplaying_p), selected_frame));
- ++redisplaying_p;
+ record_unwind_protect (unwind_redisplay, selected_frame);
+ redisplaying_p = 1;
specbind (Qinhibit_free_realized_faces, Qnil);
- {
- Lisp_Object tail, frame;
+ /* Record this function, so it appears on the profiler's backtraces. */
+ backtrace.next = backtrace_list;
+ backtrace.function = Qredisplay_internal;
+ backtrace.args = &Qnil;
+ backtrace.nargs = 0;
+ backtrace.debug_on_exit = 0;
+ backtrace_list = &backtrace;
- FOR_EACH_FRAME (tail, frame)
- {
- struct frame *f = XFRAME (frame);
- f->already_hscrolled_p = 0;
- }
- }
+ FOR_EACH_FRAME (tail, frame)
+ XFRAME (frame)->already_hscrolled_p = 0;
retry:
/* Remember the currently selected window. */
sw = w;
- if (!EQ (old_frame, selected_frame)
- && FRAME_LIVE_P (XFRAME (old_frame)))
- /* When running redisplay, we play a bit fast-and-loose and allow e.g.
- selected_frame and selected_window to be temporarily out-of-sync so
- when we come back here via `goto retry', we need to resync because we
- may need to run Elisp code (via prepare_menu_bars). */
- select_frame_for_redisplay (old_frame);
-
pending = 0;
reconsider_clip_changes (w, current_buffer);
last_escape_glyph_frame = NULL;
FRAME_TTY (sf)->previous_frame = sf;
}
- /* Set the visible flags for all frames. Do this before checking
- for resized or garbaged frames; they want to know if their frames
- are visible. See the comment in frame.h for
- FRAME_SAMPLE_VISIBILITY. */
- {
- Lisp_Object tail, frame;
-
- number_of_visible_frames = 0;
+ /* Set the visible flags for all frames. Do this before checking for
+ resized or garbaged frames; they want to know if their frames are
+ visible. See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
+ number_of_visible_frames = 0;
- FOR_EACH_FRAME (tail, frame)
- {
- struct frame *f = XFRAME (frame);
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
- FRAME_SAMPLE_VISIBILITY (f);
- if (FRAME_VISIBLE_P (f))
- ++number_of_visible_frames;
- clear_desired_matrices (f);
- }
- }
+ FRAME_SAMPLE_VISIBILITY (f);
+ if (FRAME_VISIBLE_P (f))
+ ++number_of_visible_frames;
+ clear_desired_matrices (f);
+ }
/* Notice any pending interrupt request to change frame size. */
do_pending_window_change (1);
}
/* Clear frames marked as garbaged. */
- if (frame_garbaged)
- clear_garbaged_frames ();
+ clear_garbaged_frames ();
/* Build menubar and tool-bar items. */
if (NILP (Vmemory_full))
if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
{
w->update_mode_line = 1;
- if (buffer_shared > 1)
+ if (buffer_shared_and_changed ())
update_mode_lines++;
}
count1 = SPECPDL_INDEX ();
specbind (Qinhibit_point_motion_hooks, Qt);
- /* If %c is in the mode line, update it if needed. */
- 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)
- && (XFASTINT (w->column_number_displayed) != current_column ()))
+ if (mode_line_update_needed (w))
w->update_mode_line = 1;
unbind_to (count1, Qnil);
FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
- /* The variable buffer_shared is set in redisplay_window and
- indicates that we redisplay a buffer in different windows. See
- there. */
- consider_all_windows_p = (update_mode_lines || buffer_shared > 1
+ consider_all_windows_p = (update_mode_lines
+ || buffer_shared_and_changed ()
|| cursor_type_changed);
/* If specs for an arrow have changed, do thorough redisplay
/* If window configuration was changed, frames may have been
marked garbaged. Clear them or we will experience
surprises wrt scrolling. */
- if (frame_garbaged)
- clear_garbaged_frames ();
+ clear_garbaged_frames ();
}
}
else if (EQ (selected_window, minibuf_window)
- && (current_buffer->clip_changed
- || XFASTINT (w->last_modified) < MODIFF
- || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
+ && (current_buffer->clip_changed || window_outdated (w))
&& resize_mini_window (w, 0))
{
/* Resized active mini-window to fit the size of what it is
showing if its contents might have changed. */
must_finish = 1;
-/* FIXME: this causes all frames to be updated, which seems unnecessary
- since only the current frame needs to be considered. This function needs
- to be rewritten with two variables, consider_all_windows and
- consider_all_frames. */
+ /* FIXME: this causes all frames to be updated, which seems unnecessary
+ since only the current frame needs to be considered. This function
+ needs to be rewritten with two variables, consider_all_windows and
+ consider_all_frames. */
consider_all_windows_p = 1;
++windows_or_buffers_changed;
++update_mode_lines;
/* If window configuration was changed, frames may have been
marked garbaged. Clear them or we will experience
surprises wrt scrolling. */
- if (frame_garbaged)
- clear_garbaged_frames ();
+ clear_garbaged_frames ();
}
|| 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
- || MINI_WINDOW_P (w))
+ else if (window_outdated (w) || MINI_WINDOW_P (w))
{
/* We have to handle the case of continuation around a
wide-column character (see the comment in indent.c around
if ((it.glyph_row - 1)->displays_text_p)
{
if (XFASTINT (w->window_end_vpos) < this_line_vpos)
- XSETINT (w->window_end_vpos, this_line_vpos);
+ wset_window_end_vpos (w, make_number (this_line_vpos));
}
else if (XFASTINT (w->window_end_vpos) == this_line_vpos
&& this_line_vpos > 0)
- XSETINT (w->window_end_vpos, this_line_vpos - 1);
- w->window_end_valid = Qnil;
+ wset_window_end_vpos (w, make_number (this_line_vpos - 1));
+ wset_window_end_valid (w, Qnil);
/* Update hint: No need to try to scroll in update_window. */
w->desired_matrix->no_scrolling_p = 1;
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
*w->desired_matrix->method = 0;
debug_method_add (w, "optimization 1");
#endif
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
&& (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
row->enabled_p))
{
- xassert (this_line_vpos == it.vpos);
- xassert (this_line_y == it.current_y);
+ 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 GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
*w->desired_matrix->method = 0;
debug_method_add (w, "optimization 3");
#endif
}
CHARPOS (this_line_start_pos) = 0;
- consider_all_windows_p |= buffer_shared > 1;
+ consider_all_windows_p |= buffer_shared_and_changed ();
++clear_face_cache_count;
#ifdef HAVE_WINDOW_SYSTEM
++clear_image_cache_count;
if (consider_all_windows_p)
{
- Lisp_Object tail, frame;
-
FOR_EACH_FRAME (tail, frame)
XFRAME (frame)->updated_p = 0;
- /* Recompute # windows showing selected buffer. This will be
- incremented each time such a window is displayed. */
- buffer_shared = 0;
-
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
- if (! EQ (frame, selected_frame))
- /* Select the frame, for the sake of frame-local
- variables. */
- select_frame_for_redisplay (frame);
-
/* Mark all the scroll bars to be removed; we'll redeem
the ones we want when we redisplay their windows. */
if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
}
}
- if (!EQ (old_frame, selected_frame)
- && FRAME_LIVE_P (XFRAME (old_frame)))
- /* We played a bit fast-and-loose above and allowed selected_frame
- and selected_window to be temporarily out-of-sync but let's make
- sure this stays contained. */
- select_frame_for_redisplay (old_frame);
eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
if (!pending)
frames here explicitly. */
if (!pending)
{
- Lisp_Object tail, frame;
int new_count = 0;
FOR_EACH_FRAME (tail, frame)
#endif /* HAVE_WINDOW_SYSTEM */
end_of_redisplay:
+ backtrace_list = backtrace.next;
unbind_to (count, Qnil);
RESUME_POLLING;
}
}
-/* Function registered with record_unwind_protect in
- redisplay_internal. Reset redisplaying_p to the value it had
- before redisplay_internal was called, and clear
- prevent_freeing_realized_faces_p. It also selects the previously
- selected frame, unless it has been deleted (by an X connection
- failure during redisplay, for example). */
+/* Function registered with record_unwind_protect in redisplay_internal.
+ Clear redisplaying_p. Also select the previously selected frame. */
static Lisp_Object
-unwind_redisplay (Lisp_Object val)
+unwind_redisplay (Lisp_Object old_frame)
{
- Lisp_Object old_redisplaying_p, old_frame;
-
- old_redisplaying_p = XCAR (val);
- redisplaying_p = XFASTINT (old_redisplaying_p);
- old_frame = XCDR (val);
- if (! EQ (old_frame, selected_frame)
- && FRAME_LIVE_P (XFRAME (old_frame)))
- select_frame_for_redisplay (old_frame);
+ redisplaying_p = 0;
return Qnil;
}
{
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 = marker_position (w->pointm);
}
}
if (accurate_p)
{
- w->window_end_valid = w->buffer;
+ wset_window_end_valid (w, w->buffer);
w->update_mode_line = 0;
}
}
/* Don't even try doing anything if called for a mode-line or
header-line row, since the rest of the code isn't prepared to
deal with such calamities. */
- xassert (!row->mode_line_p);
+ eassert (!row->mode_line_p);
if (row->mode_line_p)
return 0;
GLYPH_BEFORE and GLYPH_AFTER. */
if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
&& BUFFERP (glyph->object) && glyph->charpos == pt_old)
- && bpos_covered < pt_old)
+ && !(bpos_max < pt_old && pt_old <= bpos_covered))
{
/* An empty line has a single glyph whose OBJECT is zero and
whose CHARPOS is the position of a newline on that line.
CHARPOS is zero or negative. */
int empty_line_p =
(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
- && INTEGERP (glyph->object) && glyph->charpos > 0;
+ && INTEGERP (glyph->object) && glyph->charpos > 0
+ /* On a TTY, continued and truncated rows also have a glyph at
+ their end whose OBJECT is zero and whose CHARPOS is
+ positive (the continuation and truncation glyphs), but such
+ rows are obviously not "empty". */
+ && !(row->continued_p || row->truncated_on_right_p);
if (row->ends_in_ellipsis_p && pos_after == last_pos)
{
for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
{
if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
- abort ();
+ emacs_abort ();
x += g->pixel_width;
}
}
We assume that the window's buffer is really current. */
-static inline struct text_pos
+static struct text_pos
run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
{
struct window *w = XWINDOW (window);
SET_MARKER_FROM_TEXT_POS (w->start, startp);
if (current_buffer != XBUFFER (w->buffer))
- abort ();
+ emacs_abort ();
if (!NILP (Vwindow_scroll_functions))
{
make_number (CHARPOS (startp)));
SET_TEXT_POS_FROM_MARKER (startp, w->start);
/* In case the hook functions switch buffers. */
- if (current_buffer != XBUFFER (w->buffer))
- set_buffer_internal_1 (XBUFFER (w->buffer));
+ set_buffer_internal (XBUFFER (w->buffer));
}
return startp;
/* We will never try scrolling more than this number of lines. */
int scroll_limit = SCROLL_LIMIT;
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
debug_method_add (w, "try_scrolling");
#endif
if (NUMBERP (aggressive))
{
double float_amount = XFLOATINT (aggressive) * height;
- amount_to_scroll = float_amount;
- if (amount_to_scroll == 0 && float_amount > 0)
- amount_to_scroll = 1;
+ int aggressive_scroll = float_amount;
+ if (aggressive_scroll == 0 && float_amount > 0)
+ aggressive_scroll = 1;
/* Don't let point enter the scroll margin near top of
- the window. */
- if (amount_to_scroll > height - 2*this_scroll_margin + dy)
- amount_to_scroll = height - 2*this_scroll_margin + dy;
+ the window. This could happen if the value of
+ scroll_up_aggressively is too large and there are
+ non-zero margins, because scroll_up_aggressively
+ means put point that fraction of window height
+ _from_the_bottom_margin_. */
+ if (aggressive_scroll + 2*this_scroll_margin > height)
+ aggressive_scroll = height - 2*this_scroll_margin;
+ amount_to_scroll = dy + aggressive_scroll;
}
}
/* Compute the vertical distance from PT to the scroll
margin position. Move as far as scroll_max allows, or
one screenful, or 10 screen lines, whichever is largest.
- Give up if distance is greater than scroll_max. */
+ Give up if distance is greater than scroll_max or if we
+ didn't reach the scroll margin position. */
SET_TEXT_POS (pos, PT, PT_BYTE);
start_display (&it, w, pos);
y0 = it.current_y;
y_to_move, -1,
MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
dy = it.current_y - y0;
- if (dy > scroll_max)
+ if (dy > scroll_max
+ || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
return SCROLLING_FAILED;
/* Compute new window start. */
if (NUMBERP (aggressive))
{
double float_amount = XFLOATINT (aggressive) * height;
- amount_to_scroll = float_amount;
- if (amount_to_scroll == 0 && float_amount > 0)
- amount_to_scroll = 1;
- amount_to_scroll -=
- this_scroll_margin - dy - FRAME_LINE_HEIGHT (f);
+ int aggressive_scroll = float_amount;
+ if (aggressive_scroll == 0 && float_amount > 0)
+ aggressive_scroll = 1;
/* Don't let point enter the scroll margin near
- bottom of the window. */
- if (amount_to_scroll > height - 2*this_scroll_margin + dy)
- amount_to_scroll = height - 2*this_scroll_margin + dy;
+ bottom of the window, if the value of
+ scroll_down_aggressively happens to be too
+ large. */
+ if (aggressive_scroll + 2*this_scroll_margin > height)
+ aggressive_scroll = height - 2*this_scroll_margin;
+ amount_to_scroll = dy + aggressive_scroll;
}
}
if (!just_this_one_p
|| current_buffer->clip_changed
|| BEG_UNCHANGED < CHARPOS (startp))
- w->base_line_number = Qnil;
+ wset_base_line_number (w, Qnil);
/* If cursor ends up on a partially visible line,
treat that as being off the bottom of the screen. */
struct frame *f = XFRAME (w->frame);
int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
if (inhibit_try_cursor_movement)
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. */
/* Can't use this case if highlighting a region. When a
region exists, cursor movement has to do more than just
set the cursor. */
- && !(!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
+ && markpos_of_region () < 0
&& 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 this_scroll_margin, top_scroll_margin;
struct glyph_row *row = NULL;
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
debug_method_add (w, "cursor movement");
#endif
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_BOTTOM_Y (row) < last_y)
{
- xassert (row->enabled_p);
+ eassert (row->enabled_p);
++row;
}
&& !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. */
&& (row->y > top_scroll_margin
|| CHARPOS (startp) == BEGV))
{
- xassert (row->enabled_p);
+ eassert (row->enabled_p);
--row;
}
rc = CURSOR_MOVEMENT_MUST_SCROLL;
break;
}
- xassert (row->enabled_p);
+ eassert (row->enabled_p);
}
}
if (must_scroll)
selected_window is redisplayed.
We can return without actually redisplaying the window if
- fonts_changed_p is nonzero. In that case, redisplay_internal will
+ fonts_changed_p. In that case, redisplay_internal will
retry. */
static void
opoint = lpoint;
/* W must be a leaf window here. */
- xassert (!NILP (w->buffer));
-#if GLYPH_DEBUG
+ eassert (!NILP (w->buffer));
+#ifdef GLYPH_DEBUG
*w->desired_matrix->method = 0;
#endif
= (!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);
+ && !window_outdated (w));
/* 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);
+ && !window_outdated (w));
/* 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 (XMARKER (w->start)->buffer == current_buffer)
compute_window_start_on_continuation_line (w);
- w->window_end_valid = Qnil;
+ wset_window_end_valid (w, Qnil);
}
/* Some sanity checks. */
CHECK_WINDOW_END (w);
if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
- abort ();
+ emacs_abort ();
if (BYTEPOS (opoint) < CHARPOS (opoint))
- abort ();
-
- /* If %c is in mode line, update it if needed. */
- 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)
- && (XFASTINT (w->column_number_displayed) != current_column ()))
- update_mode_line = 1;
+ emacs_abort ();
- /* Count number of windows showing the selected buffer. An indirect
- buffer counts as its base buffer. */
- if (!just_this_one_p)
- {
- struct buffer *current_base, *window_base;
- current_base = current_buffer;
- window_base = XBUFFER (XWINDOW (selected_window)->buffer);
- if (current_base->base_buffer)
- current_base = current_base->base_buffer;
- if (window_base->base_buffer)
- window_base = window_base->base_buffer;
- if (current_base == window_base)
- buffer_shared++;
- }
+ if (mode_line_update_needed (w))
+ update_mode_line = 1;
/* Point refers normally to the selected window. For any other
window, set up appropriate value. */
if (!EQ (window, selected_window))
{
- ptrdiff_t new_pt = XMARKER (w->pointm)->charpos;
+ ptrdiff_t new_pt = marker_position (w->pointm);
ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
if (new_pt < BEGV)
{
{
struct Lisp_Char_Table *disptab = buffer_display_table ();
- if (! disptab_matches_widthtab (disptab,
- XVECTOR (BVAR (current_buffer, width_table))))
+ if (! disptab_matches_widthtab
+ (disptab, XVECTOR (BVAR (current_buffer, width_table))))
{
invalidate_region_cache (current_buffer,
current_buffer->width_run_cache,
w->force_start = 0;
w->vscroll = 0;
- w->window_end_valid = Qnil;
+ wset_window_end_valid (w, Qnil);
/* Forget any recorded base line for line number display. */
if (!buffer_unchanged_p)
- w->base_line_number = Qnil;
+ wset_base_line_number (w, Qnil);
/* Redisplay the mode line. Select the buffer properly for that.
Also, run the hook window-scroll-functions
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)
Move it back to a fully-visible line. */
new_vpos = window_box_height (w);
}
+ else if (w->cursor.vpos >=0)
+ {
+ /* Some people insist on not letting point enter the scroll
+ margin, even though this part handles windows that didn't
+ scroll at all. */
+ int margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+ int pixel_margin = margin * FRAME_LINE_HEIGHT (f);
+ bool header_line = WINDOW_WANTS_HEADER_LINE_P (w);
+
+ /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop
+ below, which finds the row to move point to, advances by
+ the Y coordinate of the _next_ row, see the definition of
+ MATRIX_ROW_BOTTOM_Y. */
+ if (w->cursor.vpos < margin + header_line)
+ new_vpos
+ = pixel_margin + (header_line
+ ? CURRENT_HEADER_LINE_HEIGHT (w)
+ : 0) + FRAME_LINE_HEIGHT (f);
+ else
+ {
+ int window_height = window_box_height (w);
+
+ if (header_line)
+ window_height += CURRENT_HEADER_LINE_HEIGHT (w);
+ if (w->cursor.y >= window_height - pixel_margin)
+ new_vpos = window_height - pixel_margin;
+ }
+ }
/* If we need to move point for either of the above reasons,
now actually do it. */
/* If we are highlighting the region, then we just changed
the region, so redisplay to show it. */
- if (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
+ if (0 <= markpos_of_region ())
{
clear_glyph_matrix (w->desired_matrix);
if (!try_window (window, startp, 0))
}
}
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
debug_method_add (w, "forced window start");
#endif
goto done;
goto try_to_scroll;
default:
- abort ();
+ emacs_abort ();
}
}
/* If current starting point was originally the beginning of a line
&& !(CHARPOS (startp) <= BEGV
|| FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
{
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
debug_method_add (w, "recenter 1");
#endif
goto recenter;
not work. It is 0 if unsuccessful for some other reason. */
else if ((tem = try_window_id (w)) != 0)
{
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
debug_method_add (w, "try_window_id %d", tem);
#endif
&& (CHARPOS (startp) < ZV
/* Avoid starting at end of buffer. */
|| CHARPOS (startp) == BEGV
- || (XFASTINT (w->last_modified) >= MODIFF
- && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
+ || !window_outdated (w)))
{
int d1, d2, d3, d4, d5, d6;
goto force_start;
}
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
debug_method_add (w, "same window start");
#endif
|| current_buffer->clip_changed
|| BEG_UNCHANGED < CHARPOS (startp))
/* Forget any recorded base line for line number display. */
- w->base_line_number = Qnil;
+ wset_base_line_number (w, Qnil);
if (!cursor_row_fully_visible_p (w, 1, 0))
{
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)
break;
default:
- abort ();
+ emacs_abort ();
}
}
recenter:
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
debug_method_add (w, "recenter");
#endif
/* Forget any previously recorded base line for line number display. */
if (!buffer_unchanged_p)
- w->base_line_number = Qnil;
+ wset_base_line_number (w, Qnil);
/* Determine the window start relative to point. */
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
}
move_it_vertically_backward (&it, centering_position);
- xassert (IT_CHARPOS (it) >= BEGV);
+ eassert (IT_CHARPOS (it) >= BEGV);
/* The function move_it_vertically_backward may move over more
than the specified y-distance. If it->w is small, e.g. a
if (!line_number_displayed
&& !BUFFERP (w->base_line_pos))
{
- w->base_line_pos = Qnil;
- w->base_line_number = Qnil;
+ wset_base_line_pos (w, Qnil);
+ wset_base_line_number (w, Qnil);
}
finish_menu_bars:
|| w->pseudo_window_p)))
{
update_begin (f);
- BLOCK_INPUT;
+ block_input ();
if (draw_window_fringes (w, 1))
x_draw_vertical_border (w);
- UNBLOCK_INPUT;
+ unblock_input ();
update_end (f);
}
#endif /* HAVE_WINDOW_SYSTEM */
- /* We go to this label, with fonts_changed_p nonzero,
+ /* We go to this label, with fonts_changed_p set,
if it is necessary to try again using larger glyph matrices.
We have to redeem the scroll bar even in this case,
because the loop in redisplay_internal expects that. */
window_end_vpos to its row number. */
if (last_text_row)
{
- xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
+ eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
w->window_end_bytepos
= Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
- w->window_end_pos
- = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
- w->window_end_vpos
- = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
- xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
- ->displays_text_p);
+ wset_window_end_pos
+ (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
+ wset_window_end_vpos
+ (w, make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix)));
+ eassert
+ (MATRIX_ROW (w->desired_matrix,
+ XFASTINT (w->window_end_vpos))->displays_text_p);
}
else
{
w->window_end_bytepos = Z_BYTE - ZV_BYTE;
- w->window_end_pos = make_number (Z - ZV);
- w->window_end_vpos = make_number (0);
+ wset_window_end_pos (w, make_number (Z - ZV));
+ wset_window_end_vpos (w, make_number (0));
}
/* But that is not valid info until redisplay finishes. */
- w->window_end_valid = Qnil;
+ wset_window_end_valid (w, Qnil);
return 1;
}
struct glyph_row *start_row;
int start_vpos, min_y, max_y;
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
if (inhibit_try_window_reusing)
return 0;
#endif
return 0;
/* Can't do this if region may have changed. */
- if ((!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
+ if (0 <= markpos_of_region ()
|| !NILP (w->region_showing)
|| !NILP (Vshow_trailing_whitespace))
return 0;
{
w->window_end_bytepos
= Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
- w->window_end_pos
- = make_number (Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
- w->window_end_vpos
- = make_number (MATRIX_ROW_VPOS (last_reused_text_row,
- w->current_matrix));
+ wset_window_end_pos
+ (w, make_number (Z
+ - MATRIX_ROW_END_CHARPOS (last_reused_text_row)));
+ wset_window_end_vpos
+ (w, make_number (MATRIX_ROW_VPOS (last_reused_text_row,
+ w->current_matrix)));
}
else if (last_text_row)
{
w->window_end_bytepos
= Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
- w->window_end_pos
- = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
- w->window_end_vpos
- = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+ wset_window_end_pos
+ (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
+ wset_window_end_vpos
+ (w, make_number (MATRIX_ROW_VPOS (last_text_row,
+ w->desired_matrix)));
}
else
{
/* This window must be completely empty. */
w->window_end_bytepos = Z_BYTE - ZV_BYTE;
- w->window_end_pos = make_number (Z - ZV);
- w->window_end_vpos = make_number (0);
+ wset_window_end_pos (w, make_number (Z - ZV));
+ wset_window_end_vpos (w, make_number (0));
}
- w->window_end_valid = Qnil;
+ wset_window_end_valid (w, Qnil);
/* Update hint: don't try scrolling again in update_window. */
w->desired_matrix->no_scrolling_p = 1;
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
debug_method_add (w, "try_window_reusing_current_matrix 1");
#endif
return 1;
}
/* Start displaying at the start of first_row_to_display. */
- xassert (first_row_to_display->y < yb);
+ eassert (first_row_to_display->y < yb);
init_to_row_start (&it, w, first_row_to_display);
nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
}
/* Scroll the current matrix. */
- xassert (nrows_scrolled > 0);
+ eassert (nrows_scrolled > 0);
rotate_matrix (w->current_matrix,
start_vpos,
MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
}
if (row < bottom_row)
{
- struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
- struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
-
- /* Can't use this optimization with bidi-reordered glyph
- rows, unless cursor is already at point. */
+ /* Can't simply scan the row for point with
+ bidi-reordered glyph rows. Let set_cursor_from_row
+ figure out where to put the cursor, and if it fails,
+ give up. */
if (!NILP (BVAR (XBUFFER (w->buffer), bidi_display_reordering)))
{
- if (!(w->cursor.hpos >= 0
- && w->cursor.hpos < row->used[TEXT_AREA]
- && BUFFERP (glyph->object)
- && glyph->charpos == PT))
- return 0;
+ if (!set_cursor_from_row (w, row, w->current_matrix,
+ 0, 0, 0, 0))
+ {
+ clear_glyph_matrix (w->desired_matrix);
+ return 0;
+ }
}
else
- for (; glyph < end
- && (!BUFFERP (glyph->object)
- || glyph->charpos < PT);
- glyph++)
- {
- w->cursor.hpos++;
- w->cursor.x += glyph->pixel_width;
- }
+ {
+ struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
+ struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
+
+ for (; glyph < end
+ && (!BUFFERP (glyph->object)
+ || glyph->charpos < PT);
+ glyph++)
+ {
+ w->cursor.hpos++;
+ w->cursor.x += glyph->pixel_width;
+ }
+ }
}
}
{
w->window_end_bytepos
= Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
- w->window_end_pos
- = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
- w->window_end_vpos
- = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
+ wset_window_end_pos
+ (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
+ wset_window_end_vpos
+ (w, make_number (MATRIX_ROW_VPOS (last_text_row,
+ w->desired_matrix)));
}
else
{
- w->window_end_vpos
- = make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled);
+ wset_window_end_vpos
+ (w, make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled));
}
- w->window_end_valid = Qnil;
+ wset_window_end_valid (w, Qnil);
w->desired_matrix->no_scrolling_p = 1;
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
debug_method_add (w, "try_window_reusing_current_matrix 2");
#endif
return 1;
row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
{
- xassert (row->enabled_p);
+ eassert (row->enabled_p);
row_found = row;
if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
break;
/* Preconditions: W must be a leaf window and full-width. Its frame
must have a frame matrix. */
- xassert (NILP (w->hchild) && NILP (w->vchild));
- xassert (WINDOW_FULL_WIDTH_P (w));
- xassert (!FRAME_WINDOW_P (f));
+ eassert (NILP (w->hchild) && NILP (w->vchild));
+ eassert (WINDOW_FULL_WIDTH_P (w));
+ eassert (!FRAME_WINDOW_P (f));
/* If W is a full-width window, glyph pointers in W's current matrix
have, by definition, to be the same as glyph pointers in the
struct text_pos start;
ptrdiff_t first_changed_charpos, last_changed_charpos;
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
if (inhibit_try_window_id)
return 0;
#endif
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. */
/* Can't use this if highlighting a region because a cursor movement
will do more than just set the cursor. */
- if (!NILP (Vtransient_mark_mode)
- && !NILP (BVAR (current_buffer, mark_active)))
+ if (0 <= markpos_of_region ())
GIVE_UP (9);
/* Likewise if highlighting trailing whitespace. */
if (row)
set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
else
- abort ();
+ emacs_abort ();
return 1;
}
}
{
/* We have to compute the window end anew since text
could have been added/removed after it. */
- w->window_end_pos
- = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+ wset_window_end_pos
+ (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
w->window_end_bytepos
= Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
if (row)
set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
else
- abort ();
+ emacs_abort ();
return 2;
}
}
it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
- xassert (it.hpos == 0 && it.current_x == 0);
+ eassert (it.hpos == 0 && it.current_x == 0);
}
else
{
stop_pos = 0;
if (first_unchanged_at_end_row)
{
- xassert (last_unchanged_at_beg_row == NULL
+ eassert (last_unchanged_at_beg_row == NULL
|| first_unchanged_at_end_row >= last_unchanged_at_beg_row);
/* If this is a continuation line, move forward to the next one
+ delta);
first_unchanged_at_end_vpos
= MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
- xassert (stop_pos >= Z - END_UNCHANGED);
+ eassert (stop_pos >= Z - END_UNCHANGED);
}
}
else if (last_unchanged_at_beg_row == NULL)
GIVE_UP (19);
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
/* Either there is no unchanged row at the end, or the one we have
now displays text. This is a necessary condition for the window
end pos calculation at the end of this function. */
- xassert (first_unchanged_at_end_row == NULL
+ eassert (first_unchanged_at_end_row == NULL
|| MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
debug_last_unchanged_at_beg_vpos
: -1);
debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
-#endif /* GLYPH_DEBUG != 0 */
+#endif /* GLYPH_DEBUG */
/* Display new lines. Set last_text_row to the last new line
{
rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
bottom_vpos, dvpos);
- enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
- bottom_vpos, 0);
+ clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
+ bottom_vpos);
}
else if (dvpos > 0)
{
rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
bottom_vpos, dvpos);
- enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
- first_unchanged_at_end_vpos + dvpos, 0);
+ clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
+ first_unchanged_at_end_vpos + dvpos);
}
/* For frame-based redisplay, make sure that current frame and window
struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
/* If last_row is the window end line, it should display text. */
- xassert (last_row->displays_text_p);
+ eassert (last_row->displays_text_p);
/* If window end line was partially visible before, begin
displaying at that line. Otherwise begin displaying with the
matrix. Set row to the last row displaying text in current
matrix starting at first_unchanged_at_end_row, after
scrolling. */
- xassert (first_unchanged_at_end_row->displays_text_p);
+ eassert (first_unchanged_at_end_row->displays_text_p);
row = find_last_row_displaying_text (w->current_matrix, &it,
first_unchanged_at_end_row);
- xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
+ eassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
- w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+ wset_window_end_pos (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
- w->window_end_vpos
- = make_number (MATRIX_ROW_VPOS (row, w->current_matrix));
- xassert (w->window_end_bytepos >= 0);
+ wset_window_end_vpos
+ (w, make_number (MATRIX_ROW_VPOS (row, w->current_matrix)));
+ eassert (w->window_end_bytepos >= 0);
IF_DEBUG (debug_method_add (w, "A"));
}
else if (last_text_row_at_end)
{
- w->window_end_pos
- = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
+ wset_window_end_pos
+ (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end)));
w->window_end_bytepos
= Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
- w->window_end_vpos
- = make_number (MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
- xassert (w->window_end_bytepos >= 0);
+ wset_window_end_vpos
+ (w, make_number (MATRIX_ROW_VPOS (last_text_row_at_end,
+ desired_matrix)));
+ eassert (w->window_end_bytepos >= 0);
IF_DEBUG (debug_method_add (w, "B"));
}
else if (last_text_row)
/* We have displayed either to the end of the window or at the
end of the window, i.e. the last row with text is to be found
in the desired matrix. */
- w->window_end_pos
- = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
+ wset_window_end_pos
+ (w, make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row)));
w->window_end_bytepos
= Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
- w->window_end_vpos
- = make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix));
- xassert (w->window_end_bytepos >= 0);
+ wset_window_end_vpos
+ (w, make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix)));
+ eassert (w->window_end_bytepos >= 0);
}
else if (first_unchanged_at_end_row == NULL
&& last_text_row == NULL
row = current_row;
}
- xassert (row != NULL);
- w->window_end_vpos = make_number (vpos + 1);
- w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
+ eassert (row != NULL);
+ wset_window_end_vpos (w, make_number (vpos + 1));
+ wset_window_end_pos (w, make_number (Z - MATRIX_ROW_END_CHARPOS (row)));
w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
- xassert (w->window_end_bytepos >= 0);
+ eassert (w->window_end_bytepos >= 0);
IF_DEBUG (debug_method_add (w, "C"));
}
else
- abort ();
+ emacs_abort ();
IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
debug_end_vpos = XFASTINT (w->window_end_vpos));
/* Record that display has not been completed. */
- w->window_end_valid = Qnil;
+ wset_window_end_valid (w, Qnil);
w->desired_matrix->no_scrolling_p = 1;
return 3;
More debugging support
***********************************************************************/
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
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;
- xassert (!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)
{
for (i = 0; i < row->used[TEXT_AREA]; ++i)
row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
- xassert (row->pixel_width >= 0);
- xassert (row->ascent >= 0 && row->height > 0);
+ eassert (row->pixel_width >= 0);
+ eassert (row->ascent >= 0 && row->height > 0);
row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
|| MATRIX_ROW_OVERLAPS_PRED_P (row));
int saved_char_to_display = it->char_to_display;
int saved_x = it->current_x;
int saved_face_id = it->face_id;
+ int saved_box_end = it->end_of_box_run_p;
struct text_pos saved_pos;
Lisp_Object saved_object;
struct face *face;
it->face_id = it->saved_face_id;
face = FACE_FROM_ID (it->f, it->face_id);
it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
+ /* In R2L rows, we will prepend a stretch glyph that will
+ have the end_of_box_run_p flag set for it, so there's no
+ need for the appended newline glyph to have that flag
+ set. */
+ if (it->glyph_row->reversed_p
+ /* But if the appended newline glyph goes all the way to
+ the end of the row, there will be no stretch glyph,
+ so leave the box flag set. */
+ && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x)
+ it->end_of_box_run_p = 0;
PRODUCE_GLYPHS (it);
it->len = saved_len;
it->c = saved_c;
it->char_to_display = saved_char_to_display;
+ it->end_of_box_run_p = saved_box_end;
return 1;
}
}
struct glyph *g;
int row_width, stretch_ascent, stretch_width;
struct text_pos saved_pos;
- int saved_face_id, saved_avoid_cursor;
+ int saved_face_id, saved_avoid_cursor, saved_box_start;
for (row_width = 0, g = row_start; g < row_end; g++)
row_width += g->pixel_width;
saved_avoid_cursor = it->avoid_cursor_p;
it->avoid_cursor_p = 1;
saved_face_id = it->face_id;
+ saved_box_start = it->start_of_box_run_p;
/* The last row's stretch glyph should get the default
face, to avoid painting the rest of the window with
the region face, if the region ends at ZV. */
it->face_id = default_face->id;
else
it->face_id = face->id;
+ it->start_of_box_run_p = 0;
append_stretch_glyph (it, make_number (0), stretch_width,
it->ascent + it->descent, stretch_ascent);
it->position = saved_pos;
it->avoid_cursor_p = saved_avoid_cursor;
it->face_id = saved_face_id;
+ it->start_of_box_run_p = saved_box_start;
}
}
#endif /* HAVE_WINDOW_SYSTEM */
struct text_pos pos =
STRINGP (it->string) ? it->current.string_pos : it->current.pos;
- xassert (it->method == GET_FROM_BUFFER
+ eassert (it->method == GET_FROM_BUFFER
|| it->method == GET_FROM_DISPLAY_VECTOR
|| it->method == GET_FROM_STRING);
{
struct glyph *glyph, *end;
- xassert (it->glyph_row);
- xassert (it->glyph_row->reversed_p);
- xassert (it->area == TEXT_AREA);
- xassert (n <= it->glyph_row->used[TEXT_AREA]);
+ eassert (it->glyph_row);
+ eassert (it->glyph_row->reversed_p);
+ eassert (it->area == TEXT_AREA);
+ eassert (n <= it->glyph_row->used[TEXT_AREA]);
if (n > it->glyph_row->used[TEXT_AREA])
n = it->glyph_row->used[TEXT_AREA];
/* A line that is entirely from a string/image/stretch... */
row->maxpos = row->minpos;
else
- abort ();
+ emacs_abort ();
}
else
row->maxpos = it->current.pos;
ptrdiff_t min_bpos IF_LINT (= 0), max_bpos IF_LINT (= 0);
/* We always start displaying at hpos zero even if hscrolled. */
- xassert (it->hpos == 0 && it->current_x == 0);
+ eassert (it->hpos == 0 && it->current_x == 0);
if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
>= it->w->desired_matrix->nrows)
}
/* Is IT->w showing the region? */
- it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
+ wset_region_showing (it->w, it->region_beg_charpos > 0 ? Qt : Qnil);
/* Clear the result glyph row and enable it. */
prepare_desired_row (row);
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)
move_it_in_display_line at the start of this
function, unless the text display area of the
window is empty. */
- xassert (it->first_visible_x <= it->last_visible_x);
+ eassert (it->first_visible_x <= it->last_visible_x);
}
}
/* Even if this display element produced no glyphs at all,
/* 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
{
- xassert (INTEGERP (overlay_arrow_string));
+ eassert (INTEGERP (overlay_arrow_string));
row->overlay_arrow_bitmap = XINT (overlay_arrow_string);
}
overlay_arrow_seen = 1;
return Qright_to_left;
break;
default:
- abort ();
+ emacs_abort ();
}
}
}
#endif /* HAVE_NS */
#ifdef USE_X_TOOLKIT
- xassert (!FRAME_WINDOW_P (f));
+ eassert (!FRAME_WINDOW_P (f));
init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
it.first_visible_x = 0;
it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
/* Menu bar lines are displayed in the desired matrix of the
dummy window menu_bar_window. */
struct window *menu_w;
- xassert (WINDOWP (f->menu_bar_window));
+ eassert (WINDOWP (f->menu_bar_window));
menu_w = XWINDOW (f->menu_bar_window);
init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
MENU_FACE_ID);
this. */
it.paragraph_embedding = L2R;
- if (! mode_line_inverse_video)
- /* Force the menu-bar to be displayed in the default face. */
- it.base_face_id = it.face_id = DEFAULT_FACE_ID;
-
/* Clear all rows of the menu bar. */
for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
{
static int
display_mode_lines (struct window *w)
{
- Lisp_Object old_selected_window, old_selected_frame;
+ Lisp_Object old_selected_window = selected_window;
+ Lisp_Object old_selected_frame = selected_frame;
+ Lisp_Object new_frame = w->frame;
+ Lisp_Object old_frame_selected_window = XFRAME (new_frame)->selected_window;
int n = 0;
- old_selected_frame = selected_frame;
- selected_frame = w->frame;
- old_selected_window = selected_window;
+ selected_frame = new_frame;
+ /* FIXME: If we were to allow the mode-line's computation changing the buffer
+ or window's point, then we'd need select_window_1 here as well. */
XSETWINDOW (selected_window, w);
+ XFRAME (new_frame)->selected_window = selected_window;
/* These will be set while the mode line specs are processed. */
line_number_displayed = 0;
- w->column_number_displayed = Qnil;
+ wset_column_number_displayed (w, Qnil);
if (WINDOW_WANTS_MODELINE_P (w))
{
++n;
}
+ XFRAME (new_frame)->selected_window = old_frame_selected_window;
selected_frame = old_selected_frame;
selected_window = old_selected_window;
return n;
it.glyph_row->mode_line_p = 1;
- if (! mode_line_inverse_video)
- /* Force the mode-line to be displayed in the default face. */
- it.base_face_id = it.face_id = DEFAULT_FACE_ID;
-
/* FIXME: This should be controlled by a user option. But
supporting such an option is not trivial, since the mode line is
made up of many separate strings. */
depth++;
- switch (SWITCH_ENUM_CAST (XTYPE (elt)))
+ switch (XTYPE (elt))
{
case Lisp_String:
{
Lisp_Object str;
int string_start = 0;
- if (NILP (window))
- window = selected_window;
- CHECK_WINDOW (window);
- w = XWINDOW (window);
+ w = decode_any_window (window);
+ XSETWINDOW (window, w);
if (NILP (buffer))
buffer = w->buffer;
: EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
: DEFAULT_FACE_ID;
- if (XBUFFER (buffer) != current_buffer)
- old_buffer = current_buffer;
+ old_buffer = current_buffer;
/* Save things including mode_line_proptrans_alist,
and set that to nil so that we don't alter the outer value. */
record_unwind_protect (unwind_format_mode_line,
format_mode_line_unwind_data
- (XFRAME (WINDOW_FRAME (XWINDOW (window))),
+ (XFRAME (WINDOW_FRAME (w)),
old_buffer, selected_window, 1));
mode_line_proptrans_alist = Qnil;
Fselect_window (window, Qt);
- if (old_buffer)
- set_buffer_internal_1 (XBUFFER (buffer));
+ set_buffer_internal_1 (XBUFFER (buffer));
init_iterator (&it, w, -1, -1, NULL, face_id);
}
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;
Lisp_Object obj;
struct frame *f = XFRAME (WINDOW_FRAME (w));
char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
+ /* We are going to use f->decode_mode_spec_buffer as the buffer to
+ produce strings from numerical values, so limit preposterously
+ large values of FIELD_WIDTH to avoid overrunning the buffer's
+ end. The size of the buffer is enough for FRAME_MESSAGE_BUF_SIZE
+ bytes plus the terminating null. */
+ int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
struct buffer *b = current_buffer;
obj = Qnil;
register int i;
/* Let lots_of_dashes be a string of infinite length. */
- if (mode_line_target == MODE_LINE_NOPROP ||
- mode_line_target == MODE_LINE_STRING)
+ if (mode_line_target == MODE_LINE_NOPROP
+ || mode_line_target == MODE_LINE_STRING)
return "--";
if (field_width <= 0
|| field_width > sizeof (lots_of_dashes))
else
{
ptrdiff_t col = current_column ();
- w->column_number_displayed = make_number (col);
- pint2str (decode_mode_spec_buf, field_width, col);
+ wset_column_number_displayed (w, make_number (col));
+ pint2str (decode_mode_spec_buf, width, col);
return decode_mode_spec_buf;
}
case 'i':
{
ptrdiff_t size = ZV - BEGV;
- pint2str (decode_mode_spec_buf, field_width, size);
+ pint2str (decode_mode_spec_buf, width, size);
return decode_mode_spec_buf;
}
case 'I':
{
ptrdiff_t size = ZV - BEGV;
- pint2hrstr (decode_mode_spec_buf, field_width, size);
+ pint2hrstr (decode_mode_spec_buf, width, size);
return decode_mode_spec_buf;
}
if (mode_line_target == MODE_LINE_TITLE)
return "";
- startpos = XMARKER (w->start)->charpos;
+ startpos = marker_position (w->start);
startpos_byte = marker_byte_position (w->start);
height = WINDOW_TOTAL_LINES (w);
goto no_value;
/* But do forget it, if the window shows a different buffer now. */
else if (BUFFERP (w->base_line_pos))
- w->base_line_pos = Qnil;
+ wset_base_line_pos (w, Qnil);
/* If the buffer is very big, don't waste time. */
if (INTEGERP (Vline_number_display_limit)
&& BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
{
- w->base_line_pos = Qnil;
- w->base_line_number = Qnil;
+ wset_base_line_pos (w, Qnil);
+ wset_base_line_number (w, Qnil);
goto no_value;
}
go back past it. */
if (startpos == BUF_BEGV (b))
{
- w->base_line_number = make_number (topline);
- w->base_line_pos = make_number (BUF_BEGV (b));
+ wset_base_line_number (w, make_number (topline));
+ wset_base_line_pos (w, make_number (BUF_BEGV (b)));
}
else if (nlines < height + 25 || nlines > height * 3 + 50
|| linepos == BUF_BEGV (b))
give up on line numbers for this window. */
if (position == limit_byte && limit == startpos - distance)
{
- w->base_line_pos = w->buffer;
- w->base_line_number = Qnil;
+ wset_base_line_pos (w, w->buffer);
+ wset_base_line_number (w, Qnil);
goto no_value;
}
- w->base_line_number = make_number (topline - nlines);
- w->base_line_pos = make_number (BYTE_TO_CHAR (position));
+ wset_base_line_number (w, make_number (topline - nlines));
+ wset_base_line_pos (w, make_number (BYTE_TO_CHAR (position)));
}
/* Now count lines from the start pos to point. */
line_number_displayed = 1;
/* Make the string to show. */
- pint2str (decode_mode_spec_buf, field_width, topline + nlines);
+ pint2str (decode_mode_spec_buf, width, topline + nlines);
return decode_mode_spec_buf;
no_value:
{
char* p = decode_mode_spec_buf;
- int pad = field_width - 2;
+ int pad = width - 2;
while (pad-- > 0)
*p++ = ' ';
*p++ = '?';
obj = Fget_buffer_process (Fcurrent_buffer ());
if (PROCESSP (obj))
{
- p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
- p, eol_flag);
- p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
- p, eol_flag);
+ p = decode_mode_spec_coding
+ (XPROCESS (obj)->decode_coding_system, p, eol_flag);
+ p = decode_mode_spec_coding
+ (XPROCESS (obj)->encode_coding_system, p, eol_flag);
}
#endif /* subprocesses */
#endif /* 0 */
{
/* Glyph is off the left margin of the display area.
Should not happen. */
- abort ();
+ emacs_abort ();
}
row->ascent = max (row->ascent, it->max_ascent);
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;
}
if (NILP (prop))
return OK_PIXELS (0);
- xassert (FRAME_LIVE_P (it->f));
+ eassert (FRAME_LIVE_P (it->f));
if (SYMBOLP (prop))
{
#ifdef HAVE_WINDOW_SYSTEM
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
void
dump_glyph_string (struct glyph_string *s)
/* Append the list of glyph strings with head H and tail T to the list
with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
-static inline void
+static void
append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
struct glyph_string *h, struct glyph_string *t)
{
list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
result. */
-static inline void
+static void
prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
struct glyph_string *h, struct glyph_string *t)
{
/* Append glyph string S to the list with head *HEAD and tail *TAIL.
Set *HEAD and *TAIL to the resulting list. */
-static inline void
+static void
append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
struct glyph_string *s)
{
Value is a pointer to a realized face that is ready for display if
DISPLAY_P is non-zero. */
-static inline struct face *
+static struct face *
get_char_face_and_encoding (struct frame *f, int c, int face_id,
XChar2b *char2b, int display_p)
{
if (display_p)
#endif
{
- xassert (face != NULL);
+ eassert (face != NULL);
PREPARE_FACE_FOR_DISPLAY (f, face);
}
The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
a pointer to a realized face that is ready for display. */
-static inline struct face *
+static struct face *
get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
XChar2b *char2b, int *two_byte_p)
{
struct face *face;
- xassert (glyph->type == CHAR_GLYPH);
+ eassert (glyph->type == CHAR_GLYPH);
face = FACE_FROM_ID (f, glyph->face_id);
if (two_byte_p)
}
/* Make sure X resources of the face are allocated. */
- xassert (face != NULL);
+ eassert (face != NULL);
PREPARE_FACE_FOR_DISPLAY (f, face);
return face;
}
/* Get glyph code of character C in FONT in the two-byte form CHAR2B.
Return 1 if FONT has a glyph for C, otherwise return 0. */
-static inline int
+static int
get_char_glyph_code (int c, struct font *font, XChar2b *char2b)
{
unsigned code;
glyph that requires the different face, add it to S. */
struct face *face;
- xassert (s);
+ eassert (s);
s->for_overlaps = overlaps;
s->face = NULL;
struct glyph *glyph, *last;
int voffset;
- xassert (s->first_glyph->type == GLYPHLESS_GLYPH);
+ eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
s->for_overlaps = overlaps;
glyph = s->row->glyphs[s->area] + start;
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++;
int voffset;
int glyph_not_available_p;
- xassert (s->f == XFRAME (s->w->frame));
- xassert (s->nchars == 0);
- xassert (start >= 0 && end > start);
+ eassert (s->f == XFRAME (s->w->frame));
+ eassert (s->nchars == 0);
+ eassert (start >= 0 && end > start);
s->for_overlaps = overlaps;
glyph = s->row->glyphs[s->area] + start;
&two_byte_p);
s->two_byte_p = two_byte_p;
++s->nchars;
- xassert (s->nchars <= end - start);
+ eassert (s->nchars <= end - start);
s->width += glyph->pixel_width;
if (glyph++->padding_p != s->padding_p)
break;
/* Adjust base line for subscript/superscript text. */
s->ybase += voffset;
- xassert (s->face && s->face->gc);
+ eassert (s->face && s->face->gc);
return glyph - s->row->glyphs[s->area];
}
static void
fill_image_glyph_string (struct glyph_string *s)
{
- xassert (s->first_glyph->type == IMAGE_GLYPH);
+ eassert (s->first_glyph->type == IMAGE_GLYPH);
s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
- xassert (s->img);
+ 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;
struct glyph *glyph, *last;
int voffset, face_id;
- xassert (s->first_glyph->type == STRETCH_GLYPH);
+ eassert (s->first_glyph->type == STRETCH_GLYPH);
glyph = s->row->glyphs[s->area] + start;
last = s->row->glyphs[s->area] + end;
/* The case that face->gc == 0 is handled when drawing the glyph
string by calling PREPARE_FACE_FOR_DISPLAY. */
- xassert (s->face);
+ eassert (s->face);
return glyph - s->row->glyphs[s->area];
}
{
int x = 0, i;
struct glyph *glyphs = s->row->glyphs[s->area];
- int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+ int first = (s->first_glyph - glyphs
+ + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
int end = s->row->used[s->area];
for (i = first; i < end && s->right_overhang > x; ++i)
int i, k, x;
int end = s->row->used[s->area];
struct glyph *glyphs = s->row->glyphs[s->area];
- int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+ int first = (s->first_glyph - glyphs
+ + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
k = -1;
x = 0;
first glyph following S. LAST_X is the right-most x-position + 1
in the drawing area. */
-static inline void
+static void
set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
{
/* If the face of this glyph string has to be drawn to the end of
#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); \
break; \
\
default: \
- abort (); \
+ emacs_abort (); \
} \
\
if (s) \
/* Let's rather be paranoid than getting a SEGV. */
end = min (end, row->used[area]);
- start = max (0, start);
- start = min (end, start);
+ start = clip_to_bounds (0, start, end);
/* Translate X to frame coordinates. Set last_x to the right
end of the drawing area. */
/* If mouse highlighting is on, we may need to draw adjacent
glyphs using mouse-face highlighting. */
- if (area == TEXT_AREA && row->mouse_face_p)
+ if (area == TEXT_AREA && row->mouse_face_p
+ && hlinfo->mouse_face_beg_row >= 0
+ && hlinfo->mouse_face_end_row >= 0)
{
struct glyph_row *mouse_beg_row, *mouse_end_row;
/* Store one glyph for IT->char_to_display in IT->glyph_row.
Called from x_produce_glyphs when IT->glyph_row is non-null. */
-static inline void
+static void
append_glyph (struct it *it)
{
struct glyph *glyph;
enum glyph_row_area area = it->area;
- xassert (it->glyph_row);
- xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
+ eassert (it->glyph_row);
+ eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
if (glyph < it->glyph_row->glyphs[area + 1])
glyph->type = CHAR_GLYPH;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->glyph_not_available_p = it->glyph_not_available_p;
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
else
IT->glyph_row. Called from x_produce_glyphs when IT->glyph_row is
non-null. */
-static inline void
+static void
append_composite_glyph (struct it *it)
{
struct glyph *glyph;
enum glyph_row_area area = it->area;
- xassert (it->glyph_row);
+ eassert (it->glyph_row);
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
if (glyph < it->glyph_row->glyphs[area + 1])
}
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->padding_p = 0;
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
++it->glyph_row->used[area];
/* Change IT->ascent and IT->height according to the setting of
IT->voffset. */
-static inline void
+static void
take_vertical_position_into_account (struct it *it)
{
if (it->voffset)
int glyph_ascent, crop;
struct glyph_slice slice;
- xassert (it->what == IT_IMAGE);
+ eassert (it->what == IT_IMAGE);
face = FACE_FROM_ID (it->f, it->face_id);
- xassert (face);
+ eassert (face);
/* Make sure X resources of the face is loaded. */
PREPARE_FACE_FOR_DISPLAY (it->f, face);
}
img = IMAGE_FROM_ID (it->f, it->image_id);
- xassert (img);
+ eassert (img);
/* Make sure X resources of the image is loaded. */
prepare_image_for_display (it->f, img);
glyph->type = IMAGE_GLYPH;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = 0;
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
++it->glyph_row->used[area];
struct glyph *glyph;
enum glyph_row_area area = it->area;
- xassert (ascent >= 0 && ascent <= height);
+ eassert (ascent >= 0 && ascent <= height);
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
if (glyph < it->glyph_row->glyphs[area + 1])
glyph->type = STRETCH_GLYPH;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = 0;
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
else
Lisp_Object prop, plist;
int width = 0, height = 0, align_to = -1;
int zero_width_ok_p = 0;
- int ascent = 0;
double tem;
- struct face *face = NULL;
struct font *font = NULL;
#ifdef HAVE_WINDOW_SYSTEM
+ int ascent = 0;
int zero_height_ok_p = 0;
if (FRAME_WINDOW_P (it->f))
{
- face = FACE_FROM_ID (it->f, it->face_id);
+ struct face *face = FACE_FROM_ID (it->f, it->face_id);
font = face->font ? face->font : FRAME_FONT (it->f);
PREPARE_FACE_FOR_DISPLAY (it->f, face);
}
#endif
/* List should start with `space'. */
- xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
+ eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
plist = XCDR (it->object);
/* Compute the width of the stretch. */
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
+ emacs_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.
glyph->slice.glyphless.lower_yoff = lower_yoff;
glyph->avoid_cursor_p = it->avoid_cursor_p;
glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
+ if (it->glyph_row->reversed_p && area == TEXT_AREA)
+ {
+ /* In R2L rows, the left and the right box edges need to be
+ drawn in reverse direction. */
+ glyph->right_box_line_p = it->start_of_box_run_p;
+ glyph->left_box_line_p = it->end_of_box_run_p;
+ }
+ else
+ {
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ }
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->padding_p = 0;
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
- abort ();
+ emacs_abort ();
glyph->bidi_type = it->bidi_it.type;
}
++it->glyph_row->used[area];
}
else
{
- xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
+ eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c);
str = buf;
}
Vglyphless_char_display. */
Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
- xassert (it->what == IT_GLYPHLESS);
+ eassert (it->what == IT_GLYPHLESS);
produce_glyphless_glyph (it, 1, STRINGP (acronym) ? acronym : Qnil);
goto done;
}
font_descent = FONT_DESCENT (font) - boff;
font_height = FONT_HEIGHT (font);
- cmp->font = (void *) font;
+ cmp->font = font;
pcm = NULL;
if (! font_not_found_p)
done:
/* Accumulate dimensions. Note: can't assume that it->descent > 0
because this isn't true for images with `:ascent 100'. */
- xassert (it->ascent >= 0 && it->descent >= 0);
+ eassert (it->ascent >= 0 && it->descent >= 0);
if (it->area == TEXT_AREA)
it->current_x += it->pixel_width;
{
int x, hpos, chpos = updated_window->phys_cursor.hpos;
- xassert (updated_window && updated_row);
+ eassert (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 >= updated_row->used[TEXT_AREA])
chpos = updated_row->used[TEXT_AREA] - 1;
- BLOCK_INPUT;
+ block_input ();
/* Write glyphs. */
&& chpos < hpos + len)
updated_window->phys_cursor_on_p = 0;
- UNBLOCK_INPUT;
+ unblock_input ();
/* Advance the output cursor. */
output_cursor.hpos += len;
int frame_x, frame_y;
ptrdiff_t hpos;
- xassert (updated_window && updated_row);
- BLOCK_INPUT;
+ eassert (updated_window && updated_row);
+ block_input ();
w = updated_window;
f = XFRAME (WINDOW_FRAME (w));
/* Advance the output cursor. */
output_cursor.hpos += len;
output_cursor.x += shift_by_width;
- UNBLOCK_INPUT;
+ unblock_input ();
}
int max_x, min_y, max_y;
int from_x, from_y, to_y;
- xassert (updated_window && updated_row);
+ eassert (updated_window && updated_row);
f = XFRAME (w->frame);
if (updated_row->full_width_p)
/* Prevent inadvertently clearing to end of the X window. */
if (to_x > from_x && to_y > from_y)
{
- BLOCK_INPUT;
+ block_input ();
FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
to_x - from_x, to_y - from_y);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
{
int i, x;
- BLOCK_INPUT;
+ block_input ();
x = 0;
for (i = 0; i < row->used[area];)
}
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
|| (0 <= hpos && hpos < glyph_row->used[TEXT_AREA]))
glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
- xassert (interrupt_input_blocked);
+ eassert (input_blocked_p ());
/* Set new_cursor_type to the cursor we want to be displayed. */
new_cursor_type = get_window_cursor_type (w, glyph,
if (row->reversed_p && hpos >= row->used[TEXT_AREA])
hpos = row->used[TEXT_AREA] - 1;
- BLOCK_INPUT;
+ block_input ();
display_and_set_cursor (w, on, hpos, vpos,
w->phys_cursor.x, w->phys_cursor.y);
- UNBLOCK_INPUT;
+ unblock_input ();
}
}
if (row->reversed_p && hpos >= row->used[TEXT_AREA])
hpos = row->used[TEXT_AREA] - 1;
- BLOCK_INPUT;
+ block_input ();
display_and_set_cursor (w, 1, hpos, w->phys_cursor.vpos,
w->phys_cursor.x, w->phys_cursor.y);
- UNBLOCK_INPUT;
+ unblock_input ();
}
#endif /* HAVE_WINDOW_SYSTEM */
}
ptrdiff_t ignore, pos;
int x;
- xassert (NILP (disp_string) || STRINGP (disp_string));
- xassert (NILP (before_string) || STRINGP (before_string));
- xassert (NILP (after_string) || STRINGP (after_string));
+ eassert (NILP (disp_string) || STRINGP (disp_string));
+ eassert (NILP (before_string) || STRINGP (before_string));
+ eassert (NILP (after_string) || STRINGP (after_string));
/* Find the rows corresponding to START_CHARPOS and END_CHARPOS. */
rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
if (hlinfo->mouse_face_defer)
return;
- if (gc_in_progress)
- {
- hlinfo->mouse_face_deferred_gc = 1;
- return;
- }
-
/* Which window is that in? */
window = window_from_coordinates (f, x, y, &part, 1);
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;
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
Lisp_Object window;
- BLOCK_INPUT;
+ block_input ();
XSETWINDOW (window, w);
if (EQ (window, hlinfo->mouse_face_window))
clear_mouse_face (hlinfo);
- UNBLOCK_INPUT;
+ unblock_input ();
}
static int
expose_line (struct window *w, struct glyph_row *row, XRectangle *r)
{
- xassert (row->enabled_p);
+ eassert (row->enabled_p);
if (row->mode_line_p || w->pseudo_window_p)
draw_glyphs (w, 0, row, TEXT_AREA,
for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
if (row->overlapping_p)
{
- xassert (row->enabled_p && !row->mode_line_p);
+ eassert (row->enabled_p && !row->mode_line_p);
row->clip = r;
if (row->used[LEFT_MARGIN_AREA])
staticpro (&Vmessage_stack);
DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
+ DEFSYM (Qredisplay_internal, "redisplay_internal (C function)");
message_dolog_marker1 = Fmake_marker ();
staticpro (&message_dolog_marker1);
message_dolog_marker3 = Fmake_marker ();
staticpro (&message_dolog_marker3);
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
defsubr (&Sdump_frame_glyph_matrix);
defsubr (&Sdump_glyph_matrix);
defsubr (&Sdump_glyph_row);
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.
Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI). */);
Vdisplay_pixels_per_inch = make_float (72.0);
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: /* Don't ask. */);
#endif
If `word-wrap' is enabled, you might want to reduce this. */);
Vtruncate_partial_width_windows = make_number (50);
- DEFVAR_BOOL ("mode-line-inverse-video", mode_line_inverse_video,
- doc: /* When nil, display the mode-line/header-line/menu-bar in the default face.
-Any other value means to use the appropriate face, `mode-line',
-`header-line', or `menu' respectively. */);
- mode_line_inverse_video = 1;
-
DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
doc: /* Maximum buffer size for which line number should be displayed.
If the buffer is bigger than this, the line number does not appear
\(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.
If nil, disable message logging. If t, log messages but don't truncate
the buffer when it becomes large. */);
- Vmessage_log_max = make_number (100);
+ Vmessage_log_max = make_number (1000);
DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions,
doc: /* Functions called before redisplay, if window sizes have changed.
doc: /* Non-nil means don't free realized faces. Internal use only. */);
inhibit_free_realized_faces = 0;
-#if GLYPH_DEBUG
+#ifdef GLYPH_DEBUG
DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
doc: /* Inhibit try_window_id display optimization. */);
inhibit_try_window_id = 0;
Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0),
Qempty_box);
+
+ DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
+ doc: /* If non-nil, debug if a message matching this regexp is displayed. */);
+ Vdebug_on_message = Qnil;
}
echo_area_window = minibuf_window;
- XSETFASTINT (r->top_line, FRAME_TOP_MARGIN (f));
- XSETFASTINT (r->total_lines, FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f));
- XSETFASTINT (r->total_cols, FRAME_COLS (f));
- XSETFASTINT (m->top_line, FRAME_LINES (f) - 1);
- XSETFASTINT (m->total_lines, 1);
- XSETFASTINT (m->total_cols, FRAME_COLS (f));
+ wset_top_line (r, make_number (FRAME_TOP_MARGIN (f)));
+ wset_total_lines
+ (r, make_number (FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f)));
+ wset_total_cols (r, make_number (FRAME_COLS (f)));
+ wset_top_line (m, make_number (FRAME_LINES (f) - 1));
+ wset_total_lines (m, make_number (1));
+ wset_total_cols (m, make_number (FRAME_COLS (f)));
scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
scratch_glyph_row.glyphs[TEXT_AREA + 1]
/* 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;
help_echo_showing_p = 0;
}
-/* Since w32 does not support atimers, it defines its own implementation of
- the following three functions in w32fns.c. */
-#ifndef WINDOWSNT
-
-/* Platform-independent portion of hourglass implementation. */
+/* Platform-independent portion of hourglass implementation. */
/* Cancel a currently active hourglass timer, and start a new one. */
void
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);
+
+#ifdef HAVE_NTGUI
+ {
+ extern void w32_note_current_window (void);
+ w32_note_current_window ();
+ }
+#endif /* HAVE_NTGUI */
hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
show_hourglass, NULL);
hide_hourglass ();
#endif
}
-#endif /* ! WINDOWSNT */