#define INFINITY 10000000
-Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-Lisp_Object Qwindow_scroll_functions;
-static Lisp_Object Qwindow_text_change_functions;
-static Lisp_Object Qredisplay_end_trigger_functions;
-Lisp_Object Qinhibit_point_motion_hooks;
-static Lisp_Object QCeval, QCpropertize;
-Lisp_Object QCfile, QCdata;
-static Lisp_Object Qfontified;
-static Lisp_Object Qgrow_only;
-static Lisp_Object Qinhibit_eval_during_redisplay;
-static Lisp_Object Qbuffer_position, Qposition, Qobject;
-static Lisp_Object Qright_to_left, Qleft_to_right;
-
-/* Cursor shapes. */
-Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
-
-/* Pointer shapes. */
-static Lisp_Object Qarrow, Qhand;
-Lisp_Object Qtext;
-
/* Holds the list (error). */
static Lisp_Object list_of_error;
-static Lisp_Object Qfontification_functions;
-
-static Lisp_Object Qwrap_prefix;
-static Lisp_Object Qline_prefix;
-static Lisp_Object Qredisplay_internal;
-
-/* Non-nil means don't actually do any redisplay. */
-
-Lisp_Object Qinhibit_redisplay;
-
-/* Names of text properties relevant for redisplay. */
-
-Lisp_Object Qdisplay;
-
-Lisp_Object Qspace, QCalign_to;
-static Lisp_Object QCrelative_width, QCrelative_height;
-Lisp_Object Qleft_margin, Qright_margin;
-static Lisp_Object Qspace_width, Qraise;
-static Lisp_Object Qslice;
-Lisp_Object Qcenter;
-static Lisp_Object Qmargin, Qpointer;
-static Lisp_Object Qline_height;
-
#ifdef HAVE_WINDOW_SYSTEM
/* Test if overflow newline into fringe. Called with iterator IT
&& (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
|| *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t')))) \
-/* Name of the face used to highlight trailing whitespace. */
-
-static Lisp_Object Qtrailing_whitespace;
-
-/* Name and number of the face used to highlight escape glyphs. */
-
-static Lisp_Object Qescape_glyph;
-
-/* Name and number of the face used to highlight non-breaking spaces. */
-
-static Lisp_Object Qnobreak_space;
-
-/* The symbol `image' which is the car of the lists used to represent
- images in Lisp. Also a tool bar style. */
-
-Lisp_Object Qimage;
-
-/* The image map types. */
-Lisp_Object QCmap;
-static Lisp_Object QCpointer;
-static Lisp_Object Qrect, Qcircle, Qpoly;
-
-/* Tool bar styles */
-Lisp_Object Qboth, Qboth_horiz, Qtext_image_horiz;
-
/* Non-zero means print newline to stdout before next mini-buffer
message. */
static struct buffer *this_line_buffer;
-
-/* Values of those variables at last redisplay are stored as
- properties on `overlay-arrow-position' symbol. However, if
- Voverlay_arrow_position is a marker, last-arrow-position is its
- numerical position. */
-
-static Lisp_Object Qlast_arrow_position, Qlast_arrow_string;
-
-/* Alternative overlay-arrow-string and overlay-arrow-bitmap
- properties on a symbol in overlay-arrow-variable-list. */
-
-static Lisp_Object Qoverlay_arrow_string, Qoverlay_arrow_bitmap;
-
-Lisp_Object Qmenu_bar_update_hook;
-
/* Nonzero if an overlay arrow has been displayed in this window. */
static bool overlay_arrow_seen;
static bool message_buf_print;
-/* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable. */
-
-static Lisp_Object Qinhibit_menubar_update;
-static Lisp_Object Qmessage_truncate_lines;
-
/* Set to 1 in clear_message to make redisplay_internal aware
of an emptied echo area. */
#define TRACE_MOVE(x) (void) 0
#endif
-static Lisp_Object Qauto_hscroll_mode;
-
/* Buffer being redisplayed -- for redisplay_window_error. */
static struct buffer *displayed_buffer;
struct props
{
- /* The name of the property. */
- Lisp_Object *name;
+ /* The symbol index of the name of the property. */
+ short name;
/* A unique index for the property. */
enum prop_idx idx;
static struct props it_props[] =
{
- {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
+ {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
/* Handle `face' before `display' because some sub-properties of
`display' need to know the face. */
- {&Qface, FACE_PROP_IDX, handle_face_prop},
- {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
- {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
- {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop},
- {NULL, 0, NULL}
+ {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
+ {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
+ {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
+ {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
+ {0, 0, NULL}
};
/* Value is the position described by X. If X is a marker, value is
bool redisplaying_p;
-static Lisp_Object Qinhibit_free_realized_faces;
-static Lisp_Object Qmode_line_default_help_echo;
-
/* If a string, XTread_socket generates an event to display that string.
(The display is done in read_char.) */
#ifdef HAVE_WINDOW_SYSTEM
/* Non-zero means an hourglass cursor is currently shown. */
-bool hourglass_shown_p;
+static bool hourglass_shown_p;
/* If non-null, an asynchronous timer that, when it expires, displays
an hourglass cursor on all frames. */
-struct atimer *hourglass_atimer;
+static struct atimer *hourglass_atimer;
#endif /* HAVE_WINDOW_SYSTEM */
-/* Name of the face used to display glyphless characters. */
-static Lisp_Object Qglyphless_char;
-
-/* Symbol for the purpose of Vglyphless_char_display. */
-static Lisp_Object Qglyphless_char_display;
-
-/* Method symbols for Vglyphless_char_display. */
-static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width;
-
/* Default number of seconds to wait before displaying an hourglass
cursor. */
#define DEFAULT_HOURGLASS_DELAY 1
static void pop_it (struct it *);
static void sync_frame_with_window_matrix_rows (struct window *);
static void redisplay_internal (void);
-static int echo_area_display (int);
+static bool echo_area_display (bool);
static void redisplay_windows (Lisp_Object);
static void redisplay_window (Lisp_Object, bool);
static Lisp_Object redisplay_window_error (Lisp_Object);
if (WINDOW_WANTS_MODELINE_P (w))
height -= CURRENT_MODE_LINE_HEIGHT (w);
+ height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
+
return height;
}
eassert (height >= 0);
height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+ height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
/* Note: the code below that determines the mode-line/header-line
height is essentially the same as that contained in the macro
area AREA of window W. ANY_AREA means return the right edge of the
whole window, to the left of the right fringe of W. */
-int
+static int
window_box_right_offset (struct window *w, enum glyph_row_area area)
{
/* Don't return more than the window's pixel width. */
if (pix_y < 0)
pix_y = 0;
- else if (pix_y > FRAME_LINES (f))
- pix_y = FRAME_LINES (f);
+ else if (pix_y > FRAME_TOTAL_LINES (f))
+ pix_y = FRAME_TOTAL_LINES (f);
}
}
#endif
if (s->x > r.x)
{
- r.width -= s->x - r.x;
+ if (r.width >= s->x - r.x)
+ r.width -= s->x - r.x;
+ else /* R2L hscrolled row with cursor outside text area */
+ r.width = 0;
r.x = s->x;
}
r.width = min (r.width, glyph->pixel_width);
glyph, and `x-stretch-block-cursor' is nil, don't draw a
rectangle as wide as the glyph, but use a canonical character
width instead. */
- wd = glyph->pixel_width - 1;
-#if defined (HAVE_NTGUI) || defined (HAVE_NS)
- wd++; /* Why? */
-#endif
+ wd = glyph->pixel_width;
x = w->phys_cursor.x;
if (x < 0)
gx = WINDOW_PIXEL_WIDTH (w) - width;
goto row_glyph;
- case ON_SCROLL_BAR:
+ case ON_VERTICAL_SCROLL_BAR:
gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
? 0
: (window_box_right_offset (w, RIGHT_MARGIN_AREA)
gy = 0;
/* The bottom divider prevails. */
height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
- goto add_edge;;
+ goto add_edge;
case ON_BOTTOM_DIVIDER:
gx = 0;
{
ptrdiff_t i;
ptrdiff_t count = SPECPDL_INDEX ();
- struct gcpro gcpro1;
- Lisp_Object *args = alloca (nargs * word_size);
+ Lisp_Object *args;
+ USE_SAFE_ALLOCA;
+ SAFE_ALLOCA_LISP (args, nargs);
args[0] = func;
for (i = 1; i < nargs; i++)
args[i] = va_arg (ap, Lisp_Object);
- GCPRO1 (args[0]);
- gcpro1.nvars = nargs;
specbind (Qinhibit_redisplay, Qt);
if (inhibit_quit)
specbind (Qinhibit_quit, Qt);
so there is no possibility of wanting to redisplay. */
val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
safe_eval_handler);
- UNGCPRO;
+ SAFE_FREE ();
val = unbind_to (count, val);
}
return retval;
}
-static Lisp_Object Qeval;
-
Lisp_Object
safe_eval (Lisp_Object sexpr)
{
row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
}
- /* Clear IT. */
- memset (it, 0, sizeof *it);
+ /* Clear IT, and set it->object and other IT's Lisp objects to Qnil.
+ Other parts of redisplay rely on that. */
+ memclear (it, sizeof *it);
it->current.overlay_string_index = -1;
it->current.dpvec_index = -1;
it->base_face_id = remapped_base_face_id;
- it->string = Qnil;
IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
it->paragraph_embedding = L2R;
- it->bidi_it.string.lstring = Qnil;
- it->bidi_it.string.s = NULL;
- it->bidi_it.string.bufpos = 0;
it->bidi_it.w = w;
/* The window in which we iterate over current_buffer: */
* FRAME_LINE_HEIGHT (it->f));
else if (it->f->extra_line_spacing > 0)
it->extra_line_spacing = it->f->extra_line_spacing;
- it->max_extra_line_spacing = 0;
}
/* If realized faces have been removed, e.g. because of face
if (FRAME_FACE_CACHE (it->f)->used == 0)
recompute_basic_faces (it->f);
- /* Current value of the `slice', `space-width', and 'height' properties. */
- it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
- it->space_width = Qnil;
- it->font_height = Qnil;
it->override_ascent = -1;
/* Are control characters displayed as `^C'? */
it->tab_width = SANE_TAB_WIDTH (current_buffer);
/* Are lines in the display truncated? */
- if (base_face_id != DEFAULT_FACE_ID
- || it->w->hscroll
- || (! WINDOW_FULL_WIDTH_P (it->w)
- && ((!NILP (Vtruncate_partial_width_windows)
- && !INTEGERP (Vtruncate_partial_width_windows))
- || (INTEGERP (Vtruncate_partial_width_windows)
- /* PXW: Shall we do something about this? */
- && (WINDOW_TOTAL_COLS (it->w)
- < XINT (Vtruncate_partial_width_windows))))))
+ if (TRUNCATE != 0)
it->line_wrap = TRUNCATE;
- else if (NILP (BVAR (current_buffer, truncate_lines)))
+ if (base_face_id == DEFAULT_FACE_ID
+ && !it->w->hscroll
+ && (WINDOW_FULL_WIDTH_P (it->w)
+ || NILP (Vtruncate_partial_width_windows)
+ || (INTEGERP (Vtruncate_partial_width_windows)
+ /* PXW: Shall we do something about this? */
+ && (XINT (Vtruncate_partial_width_windows)
+ <= WINDOW_TOTAL_COLS (it->w))))
+ && NILP (BVAR (current_buffer, truncate_lines)))
it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
? WINDOW_WRAP : WORD_WRAP;
- else
- it->line_wrap = TRUNCATE;
/* Get dimensions of truncation and continuation glyphs. These are
displayed as fringe bitmaps under X, but we need them for such
it->glyph_row = row;
it->area = TEXT_AREA;
- /* Forget any previous info about this row being reversed. */
- if (it->glyph_row)
- it->glyph_row->reversed_p = 0;
-
/* Get the dimensions of the display area. The display area
consists of the visible window area plus a horizontally scrolled
part to the left of the window. All x-values are relative to the
/* Get properties here. */
for (p = it_props; p->handler; ++p)
- values_here[p->idx] = textget (iv->plist, *p->name);
+ values_here[p->idx] = textget (iv->plist,
+ builtin_lisp_symbol (p->name));
/* Look for an interval following iv that has different
properties. */
{
for (p = it_props; p->handler; ++p)
{
- Lisp_Object new_value;
-
- new_value = textget (next_iv->plist, *p->name);
+ Lisp_Object new_value = textget (next_iv->plist,
+ builtin_lisp_symbol (p->name));
if (!EQ (values_here[p->idx], new_value))
break;
}
ptrdiff_t i, noverlays;
ptrdiff_t endpos;
Lisp_Object *overlays;
+ USE_SAFE_ALLOCA;
/* Get all overlays at the given position. */
GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, 1);
endpos = min (endpos, oendpos);
}
+ SAFE_FREE ();
return endpos;
}
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
- 0, it->base_face_id);
+ false, it->base_face_id);
/* Is this a start of a run of characters with box face?
Caveat: this can be called for a freshly initialized
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
- 0,
+ false,
from_overlay);
}
else
IT_STRING_CHARPOS (*it),
bufpos,
&next_stop,
- base_face_id, 0);
+ base_face_id, false);
/* Is this a start of a run of characters with box? Caveat:
this can be called for a freshly allocated iterator; face_id
charpos,
bufpos,
&next_check_charpos,
- base_face_id, 0);
+ base_face_id, false);
/* Correct the face for charsets different from ASCII. Do it
for the multibyte case only. The face returned above is
face_id = face_at_buffer_position (it->w,
CHARPOS (pos),
&next_check_charpos,
- limit, 0, -1);
+ limit, false, -1);
/* Correct the face for charsets different from ASCII. Do it
for the multibyte case only. The face returned above is
if (it)
{
- int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);;
+ int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
if (CONSP (XCDR (XCDR (spec))))
{
Lisp_Object overlay, window, str, invisible;
struct Lisp_Overlay *ov;
ptrdiff_t start, end;
- ptrdiff_t size = 20;
ptrdiff_t n = 0, i, j;
int invis_p;
- struct overlay_entry *entries = alloca (size * sizeof *entries);
+ struct overlay_entry entriesbuf[20];
+ ptrdiff_t size = ARRAYELTS (entriesbuf);
+ struct overlay_entry *entries = entriesbuf;
USE_SAFE_ALLOCA;
if (charpos <= 0)
is R..." */
/* FIXME: Do we need an exception for characters from display
tables? */
- if (it->bidi_p && it->bidi_it.type == STRONG_R)
+ if (it->bidi_p && it->bidi_it.type == STRONG_R
+ && !inhibit_bidi_mirroring)
it->c = bidi_mirror_char (it->c);
/* Map via display table or translate control characters.
IT->c, IT->len etc. have been set to the next character by
{
next_face_id = face_at_buffer_position
(it->w, CHARPOS (pos), &ignore,
- CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, 0, -1);
+ CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, false, -1);
it->end_of_box_run_p
= (FACE_FROM_ID (it->f, next_face_id)->box
== FACE_NO_BOX);
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;
+ it->object = make_number (0);
/* With bidi reordering, the character to display might not be the
character at IT_CHARPOS. BIDI_IT.FIRST_ELT non-zero means that
/* Get the next character, maybe multibyte. */
p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
- if (it->multibyte_p && !ASCII_BYTE_P (*p))
+ if (it->multibyte_p && !ASCII_CHAR_P (*p))
it->c = STRING_CHAR_AND_LENGTH (p, it->len);
else
it->c = *p, it->len = 1;
static void
run_redisplay_end_trigger_hook (struct it *it)
{
- Lisp_Object args[3];
-
/* IT->glyph_row should be non-null, i.e. we should be actually
displaying something, or otherwise we should not run the hook. */
eassert (it->glyph_row);
- /* Set up hook arguments. */
- args[0] = Qredisplay_end_trigger_functions;
- args[1] = it->window;
- XSETINT (args[2], it->redisplay_end_trigger_charpos);
+ ptrdiff_t charpos = it->redisplay_end_trigger_charpos;
it->redisplay_end_trigger_charpos = 0;
/* Since we are *trying* to run these functions, don't try to run
them again, even if they get an error. */
wset_redisplay_end_trigger (it->w, Qnil);
- Frun_hook_with_args (3, args);
+ CALLN (Frun_hook_with_args, Qredisplay_end_trigger_functions, it->window,
+ make_number (charpos));
/* Notice if it changed the face of the character we are on. */
handle_face_prop (it);
void
add_to_log (const char *format, Lisp_Object arg1, Lisp_Object arg2)
{
- Lisp_Object args[3];
Lisp_Object msg, fmt;
char *buffer;
ptrdiff_t len;
fmt = msg = Qnil;
GCPRO4 (fmt, msg, arg1, arg2);
- args[0] = fmt = build_string (format);
- args[1] = arg1;
- args[2] = arg2;
- msg = Fformat (3, args);
+ fmt = build_string (format);
+ msg = CALLN (Fformat, fmt, arg1, arg2);
len = SBYTES (msg) + 1;
buffer = SAFE_ALLOCA (len);
for (i = 0; i < nbytes; i += char_bytes)
{
c = string_char_and_length (msg + i, &char_bytes);
- work[0] = (ASCII_CHAR_P (c)
- ? c
- : multibyte_char_to_unibyte (c));
+ work[0] = CHAR_TO_BYTE8 (c);
insert_1_both (work, 1, 1, 1, 0, 0);
}
}
{
ptrdiff_t nbytes = SBYTES (m);
bool multibyte = STRING_MULTIBYTE (m);
+ char *buffer;
USE_SAFE_ALLOCA;
- char *buffer = SAFE_ALLOCA (nbytes);
- memcpy (buffer, SDATA (m), nbytes);
+ SAFE_ALLOCA_STRING (buffer, m);
message_dolog (buffer, nbytes, 1, multibyte);
SAFE_FREE ();
}
else
clear_message (true, true);
- do_pending_window_change (0);
- echo_area_display (1);
- do_pending_window_change (0);
+ do_pending_window_change (false);
+ echo_area_display (true);
+ do_pending_window_change (false);
if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
(*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
}
{
if (m)
{
- /* ENCODE_SYSTEM below can GC and/or relocate the Lisp
- String whose data pointer might be passed to us in M. So
- we use a local copy. */
- char *fmt = xstrdup (m);
+ /* ENCODE_SYSTEM below can GC and/or relocate the
+ Lisp data, so make sure we don't use it here. */
+ eassert (relocatable_string_data_p (m) != 1);
if (noninteractive_need_newline)
putc ('\n', stderr);
noninteractive_need_newline = 0;
- fprintf (stderr, fmt, SDATA (ENCODE_SYSTEM (string)));
+ fprintf (stderr, m, SDATA (ENCODE_SYSTEM (string)));
if (!cursor_in_echo_area)
fprintf (stderr, "\n");
fflush (stderr);
- xfree (fmt);
}
}
else if (INTERACTIVE)
initialized yet, just toss it. */
if (f->glyphs_initialized_p)
{
- Lisp_Object args[2], msg;
struct gcpro gcpro1, gcpro2;
- args[0] = build_string (m);
- args[1] = msg = string;
- GCPRO2 (args[0], msg);
- gcpro1.nvars = 2;
+ Lisp_Object fmt = build_string (m);
+ Lisp_Object msg = string;
+ GCPRO2 (fmt, msg);
- msg = Fformat (2, args);
+ msg = CALLN (Fformat, fmt, msg);
if (log)
message3 (msg);
{
ptrdiff_t len;
ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
- char *message_buf = alloca (maxsize + 1);
+ USE_SAFE_ALLOCA;
+ char *message_buf = SAFE_ALLOCA (maxsize + 1);
len = doprnt (message_buf, maxsize, m, 0, ap);
message3 (make_string (message_buf, len));
+ SAFE_FREE ();
}
else
message1 (0);
{
wset_buffer (w, buffer);
set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
+ set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
}
bset_undo_list (current_buffer, Qt);
Vwith_echo_area_save_vector = Qnil;
if (NILP (vector))
- vector = Fmake_vector (make_number (9), Qnil);
+ vector = Fmake_vector (make_number (11), Qnil);
XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
ASET (vector, i, Vdeactivate_mark); ++i;
ASET (vector, i, w->contents); ++i;
ASET (vector, i, make_number (marker_position (w->pointm))); ++i;
ASET (vector, i, make_number (marker_byte_position (w->pointm))); ++i;
+ ASET (vector, i, make_number (marker_position (w->old_pointm))); ++i;
+ ASET (vector, i, make_number (marker_byte_position (w->old_pointm))); ++i;
ASET (vector, i, make_number (marker_position (w->start))); ++i;
ASET (vector, i, make_number (marker_byte_position (w->start))); ++i;
}
else
{
- int end = i + 6;
+ int end = i + 8;
for (; i < end; ++i)
ASET (vector, i, Qnil);
}
set_marker_both (w->pointm, buffer,
XFASTINT (AREF (vector, 5)),
XFASTINT (AREF (vector, 6)));
- set_marker_both (w->start, buffer,
+ set_marker_both (w->old_pointm, buffer,
XFASTINT (AREF (vector, 7)),
XFASTINT (AREF (vector, 8)));
+ set_marker_both (w->start, buffer,
+ XFASTINT (AREF (vector, 9)),
+ XFASTINT (AREF (vector, 10)));
}
Vwith_echo_area_save_vector = vector;
is non-zero update selected_frame. Value is non-zero if the
mini-windows height has been changed. */
-static int
-echo_area_display (int update_frame_p)
+static bool
+echo_area_display (bool update_frame_p)
{
Lisp_Object mini_window;
struct window *w;
struct frame *f;
- int window_height_changed_p = 0;
+ bool window_height_changed_p = false;
struct frame *sf = SELECTED_FRAME ();
mini_window = FRAME_MINIBUF_WINDOW (sf);
/* Window configuration is the same as before.
Can do with a display update of the echo area,
unless we displayed some mode lines. */
- update_single_window (w, 1);
+ update_single_window (w);
flush_frame (f);
}
else
- update_frame (f, 1, 1);
+ update_frame (f, true, true);
/* If cursor is in the echo area, make sure that the next
redisplay displays the minibuffer, so that the cursor will
#ifdef HAVE_WINDOW_SYSTEM
-/* Tool-bar item index of the item on which a mouse button was pressed
- or -1. */
-
-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
int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
#else
int do_update = (WINDOWP (f->tool_bar_window)
- && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0);
+ && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
#endif
if (do_update)
build_desired_tool_bar_string (struct frame *f)
{
int i, size, size_needed;
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object image, plist, props;
+ struct gcpro gcpro1, gcpro2;
+ Lisp_Object image, plist;
- image = plist = props = Qnil;
- GCPRO3 (image, plist, props);
+ image = plist = Qnil;
+ GCPRO2 (image, plist);
/* Prepare F->desired_tool_bar_string. If we can reuse it, do so.
Otherwise, make a new string. */
(f, Fmake_string (make_number (size_needed), make_number (' ')));
else
{
- props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
+ AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
+ struct gcpro gcpro1;
+ GCPRO1 (props);
Fremove_text_properties (make_number (0), make_number (size),
props, f->desired_tool_bar_string);
+ UNGCPRO;
}
/* Put a `display' property on the string for the images to display,
the start of this item's properties in the tool-bar items
vector. */
image = Fcons (Qimage, plist);
- props = list4 (Qdisplay, image,
- Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS));
+ AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
+ make_number (i * TOOL_BAR_ITEM_NSLOTS));
+ struct gcpro gcpro1;
+ GCPRO1 (props);
/* Let the last image hide all remaining spaces in the tool bar
string. The string can be longer than needed when we reuse a
end = i + 1;
Fadd_text_properties (make_number (i), make_number (end),
props, f->desired_tool_bar_string);
+ UNGCPRO;
#undef PROP
}
}
-/* Max tool-bar height. Basically, this is what makes all other windows
- disappear when the frame gets too small. Rethink this! */
-
-#define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
- ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
-
/* Value is the number of pixels needed to make all tool-bar items of
frame F visible. The actual number of glyph rows needed is
returned in *N_ROWS if non-NULL. */
-
static int
tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
{
/* Initialize an iterator for iteration over
F->desired_tool_bar_string in the tool-bar window of frame F. */
init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
+ temp_row->reversed_p = false;
it.first_visible_x = 0;
it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
#endif /* !USE_GTK && !HAVE_NS */
-#if defined USE_GTK || defined HAVE_NS
-EXFUN (Ftool_bar_height, 2) ATTRIBUTE_CONST;
-EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST;
-#endif
-
DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
0, 2, 0,
doc: /* Return the number of lines occupied by the tool bar of FRAME.
/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
height should be changed. */
-
static int
redisplay_tool_bar (struct frame *f)
{
can turn off tool-bars by specifying tool-bar-lines zero. */
if (!WINDOWP (f->tool_bar_window)
|| (w = XWINDOW (f->tool_bar_window),
- WINDOW_PIXEL_HEIGHT (w) == 0))
+ WINDOW_TOTAL_LINES (w) == 0))
return 0;
/* Set up an iterator for the tool-bar window. */
it.first_visible_x = 0;
it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
row = it.glyph_row;
+ row->reversed_p = false;
/* Build a string that represents the contents of the tool-bar. */
build_desired_tool_bar_string (f);
if (new_height != WINDOW_PIXEL_HEIGHT (w))
{
- Lisp_Object frame;
- int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
- / FRAME_LINE_HEIGHT (f));
-
- XSETFRAME (frame, f);
- Fmodify_frame_parameters (frame,
- list1 (Fcons (Qtool_bar_lines,
- make_number (new_lines))));
+ x_change_tool_bar_height (f, new_height);
+ frame_default_tool_bar_height = new_height;
/* Always do that now. */
clear_glyph_matrix (w->desired_matrix);
f->fonts_changed = 1;
if (!NILP (Vauto_resize_tool_bars))
{
- /* Do we really allow the toolbar to occupy the whole frame? */
- int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f);
int change_height_p = 0;
/* If we couldn't display everything, change the tool-bar's
height if there is room for more. */
- if (IT_STRING_CHARPOS (it) < it.end_charpos
- && it.current_y < max_tool_bar_height)
+ if (IT_STRING_CHARPOS (it) < it.end_charpos)
change_height_p = 1;
/* We subtract 1 because display_tool_bar_line advances the
/* If row displays tool-bar items, but is partially visible,
change the tool-bar's height. */
if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
- && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y
- && MATRIX_ROW_BOTTOM_Y (row) < max_tool_bar_height)
+ && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
change_height_p = 1;
/* Resize windows as needed by changing the `tool-bar-lines'
frame parameter. */
if (change_height_p)
{
- Lisp_Object frame;
int nrows;
int new_height = tool_bar_height (f, &nrows, 1);
if (change_height_p)
{
- /* Current size of the tool-bar window in canonical line
- units. */
- int old_lines = WINDOW_TOTAL_LINES (w);
- /* Required size of the tool-bar window in canonical
- line units. */
- int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
- / FRAME_LINE_HEIGHT (f));
- /* Maximum size of the tool-bar window in canonical line
- units that this frame can allow. */
- int max_lines =
- WINDOW_TOTAL_LINES (XWINDOW (FRAME_ROOT_WINDOW (f))) - 1;
-
- /* Don't try to change the tool-bar window size and set
- the fonts_changed flag unless really necessary. That
- flag causes redisplay to give up and retry
- redisplaying the frame from scratch, so setting it
- unnecessarily can lead to nasty redisplay loops. */
- if (new_lines <= max_lines
- && eabs (new_lines - old_lines) >= 1)
- {
- XSETFRAME (frame, f);
- Fmodify_frame_parameters (frame,
- list1 (Fcons (Qtool_bar_lines,
- make_number (new_lines))));
- clear_glyph_matrix (w->desired_matrix);
- f->n_tool_bar_rows = nrows;
- f->fonts_changed = 1;
- return 1;
- }
+ x_change_tool_bar_height (f, new_height);
+ frame_default_tool_bar_height = new_height;
+ clear_glyph_matrix (w->desired_matrix);
+ f->n_tool_bar_rows = nrows;
+ f->fonts_changed = 1;
+
+ return 1;
}
}
}
where the button was pressed, disregarding where it was
released. */
if (NILP (Vmouse_highlight) && !down_p)
- prop_idx = last_tool_bar_item;
+ prop_idx = f->last_tool_bar_item;
/* If item is disabled, do nothing. */
enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
/* Show item in pressed state. */
if (!NILP (Vmouse_highlight))
show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
- last_tool_bar_item = prop_idx;
+ f->last_tool_bar_item = prop_idx;
}
else
{
event.arg = key;
event.modifiers = modifiers;
kbd_buffer_store_event (&event);
- last_tool_bar_item = -1;
+ f->last_tool_bar_item = -1;
}
}
mouse_down_p = (x_mouse_grabbed (dpyinfo)
&& f == dpyinfo->last_mouse_frame);
- if (mouse_down_p
- && last_tool_bar_item != prop_idx)
+ if (mouse_down_p && f->last_tool_bar_item != prop_idx)
return;
draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
/* Scroll when cursor is inside this scroll margin. */
h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
+ /* If the position of this window's point has explicitly
+ changed, no more suspend auto hscrolling. */
+ if (NILP (Fequal (Fwindow_point (window), Fwindow_old_point (window))))
+ w->suspend_auto_hscroll = 0;
+
+ /* Remember window point. */
+ Fset_marker (w->old_pointm,
+ ((w == XWINDOW (selected_window))
+ ? make_number (BUF_PT (XBUFFER (w->contents)))
+ : Fmarker_position (w->pointm)),
+ w->contents);
+
if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
+ && w->suspend_auto_hscroll == 0
/* In some pathological cases, like restoring a window
configuration into a frame that is much smaller than
the one from which the configuration was saved, we
inside the left margin and the window is already
hscrolled. */
&& ((!row_r2l_p
- && ((w->hscroll
- && w->cursor.x <= h_margin)
+ && ((w->hscroll && w->cursor.x <= h_margin)
|| (cursor_row->enabled_p
&& cursor_row->truncated_on_right_p
&& (w->cursor.x >= text_area_width - h_margin))))
struct window *w = XWINDOW (selected_window);
struct window *sw;
struct frame *fr;
- int pending;
+ bool pending;
bool must_finish = 0, match_p;
struct text_pos tlbufpos, tlendpos;
int number_of_visible_frames;
specbind (Qinhibit_free_realized_faces, Qnil);
/* Record this function, so it appears on the profiler's backtraces. */
- record_in_backtrace (Qredisplay_internal, &Qnil, 0);
+ record_in_backtrace (Qredisplay_internal, 0, 0);
FOR_EACH_FRAME (tail, frame)
XFRAME (frame)->already_hscrolled_p = 0;
/* Remember the currently selected window. */
sw = w;
- pending = 0;
+ pending = false;
last_escape_glyph_frame = NULL;
last_escape_glyph_face_id = (1 << FACE_ID_BITS);
last_glyphless_glyph_frame = NULL;
}
/* Notice any pending interrupt request to change frame size. */
- do_pending_window_change (1);
+ do_pending_window_change (true);
/* do_pending_window_change could change the selected_window due to
frame resizing which makes the selected window too small. */
echo-area doesn't show through. */
&& !MINI_WINDOW_P (XWINDOW (selected_window))))
{
- int window_height_changed_p = echo_area_display (0);
+ int window_height_changed_p = echo_area_display (false);
if (message_cleared_p)
update_miniwindow_p = true;
{
if (!must_finish)
{
- do_pending_window_change (1);
+ do_pending_window_change (true);
/* If selected_window changed, redisplay again. */
if (WINDOWP (selected_window)
&& (w = XWINDOW (selected_window)) != sw)
retry_frame:
+#if defined (HAVE_WINDOW_SYSTEM) && !defined (USE_GTK) && !defined (HAVE_NS)
+ /* Redisplay internal tool bar if this is the first time so we
+ can adjust the frame height right now, if necessary. */
+ if (!f->tool_bar_redisplayed_once)
+ {
+ if (redisplay_tool_bar (f))
+ adjust_frame_glyphs (f);
+ f->tool_bar_redisplayed_once = true;
+ }
+#endif
+
if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
{
bool gcscrollbars
if (f->fonts_changed)
{
adjust_frame_glyphs (f);
- f->fonts_changed = 0;
+ f->fonts_changed = false;
goto retry_frame;
}
/* See if we have to hscroll. */
if (!f->already_hscrolled_p)
{
- f->already_hscrolled_p = 1;
+ f->already_hscrolled_p = true;
if (hscroll_windows (f->root_window))
goto retry_frame;
}
unrequest_sigio ();
STOP_POLLING;
- pending |= update_frame (f, 0, 0);
- f->cursor_type_changed = 0;
- f->updated_p = 1;
+ pending |= update_frame (f, false, false);
+ f->cursor_type_changed = false;
+ f->updated_p = true;
}
}
}
goto retry;
XWINDOW (selected_window)->must_be_updated_p = true;
- pending = update_frame (sf, 0, 0);
- sf->cursor_type_changed = 0;
+ pending = update_frame (sf, false, false);
+ sf->cursor_type_changed = false;
}
/* We may have called echo_area_display at the top of this
if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
{
XWINDOW (mini_window)->must_be_updated_p = true;
- pending |= update_frame (mini_frame, 0, 0);
- mini_frame->cursor_type_changed = 0;
+ pending |= update_frame (mini_frame, false, false);
+ mini_frame->cursor_type_changed = false;
if (!pending && hscroll_windows (mini_window))
goto retry;
}
}
/* Change frame size now if a change is pending. */
- do_pending_window_change (1);
+ do_pending_window_change (true);
/* If we just did a pending size change, or have additional
visible frames, or selected_window changed, redisplay again. */
if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
{
- clear_face_cache (0);
+ clear_face_cache (false);
clear_face_cache_count = 0;
}
{
/* We have a previously displayed message, but no current
message. Redisplay the previous message. */
- display_last_displayed_message_p = 1;
+ display_last_displayed_message_p = true;
redisplay_internal ();
- display_last_displayed_message_p = 0;
+ display_last_displayed_message_p = false;
}
else
redisplay_internal ();
if (!row->reversed_p)
{
while (glyph < end
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->charpos < 0)
{
x += glyph->pixel_width;
++glyph;
}
while (end > glyph
- && INTEGERP ((end - 1)->object)
+ && NILP ((end - 1)->object)
/* CHARPOS is zero for blanks and stretch glyphs
inserted by extend_face_to_end_of_line. */
&& (end - 1)->charpos <= 0)
glyph += row->used[TEXT_AREA] - 1;
while (glyph > end + 1
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->charpos < 0)
{
--glyph;
x -= glyph->pixel_width;
}
- if (INTEGERP (glyph->object) && glyph->charpos < 0)
+ if (NILP (glyph->object) && glyph->charpos < 0)
--glyph;
/* By default, in reversed rows we put the cursor on the
rightmost (first in the reading order) glyph. */
for (g = end + 1; g < glyph; g++)
x += g->pixel_width;
while (end < glyph
- && INTEGERP ((end + 1)->object)
+ && NILP ((end + 1)->object)
&& (end + 1)->charpos <= 0)
++end;
glyph_before = glyph + 1;
while (/* not marched to end of glyph row */
glyph < end
/* glyph was not inserted by redisplay for internal purposes */
- && !INTEGERP (glyph->object))
+ && !NILP (glyph->object))
{
if (BUFFERP (glyph->object))
{
++glyph;
}
else if (glyph > end) /* row is reversed */
- while (!INTEGERP (glyph->object))
+ while (!NILP (glyph->object))
{
if (BUFFERP (glyph->object))
{
&& BUFFERP (glyph->object) && glyph->charpos == pt_old)
&& !(bpos_max <= pt_old && pt_old <= bpos_covered))
{
- /* An empty line has a single glyph whose OBJECT is zero and
+ /* An empty line has a single glyph whose OBJECT is nil and
whose CHARPOS is the position of a newline on that line.
Note that on a TTY, there are more glyphs after that, which
were produced by extend_face_to_end_of_line, but their
CHARPOS is zero or negative. */
int empty_line_p =
(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
- && INTEGERP (glyph->object) && glyph->charpos > 0
+ && NILP (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
+ their end whose OBJECT is nil 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);
&& string_from_text_prop)
/* this candidate is from newline and its
position is not an exact match */
- || (INTEGERP (glyph->object)
+ || (NILP (glyph->object)
&& glyph->charpos != pt_old)))))
return 0;
/* If this candidate gives an exact match, use that. */
terminating newline of a line, and point is on that
newline, it wins because it's an exact match. */
|| (!row->continued_p
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->charpos == 0
&& pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
/* Otherwise, keep the candidate that comes from a row
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;
+ if (aggressive_scroll + 2 * this_scroll_margin > height)
+ aggressive_scroll = height - 2 * this_scroll_margin;
amount_to_scroll = dy + aggressive_scroll;
}
}
start_display (&it, w, startp);
if (arg_scroll_conservatively)
- amount_to_scroll = max (dy, frame_line_height *
- max (scroll_step, temp_scroll_step));
+ amount_to_scroll = max (dy, frame_line_height
+ * max (scroll_step, temp_scroll_step));
else if (scroll_step || temp_scroll_step)
amount_to_scroll = scroll_max;
else
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;
+ if (aggressive_scroll + 2 * this_scroll_margin > height)
+ aggressive_scroll = height - 2 * this_scroll_margin;
amount_to_scroll = dy + aggressive_scroll;
}
}
exact_match_p =
(BUFFERP (g->object) && g->charpos == PT)
- || (INTEGERP (g->object)
+ || (NILP (g->object)
&& (g->charpos == PT
|| (g->charpos == 0 && endpos - 1 == PT)));
}
return rc;
}
-#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK
-static
-#endif
+
void
set_vertical_scroll_bar (struct window *w)
{
}
+void
+set_horizontal_scroll_bar (struct window *w)
+{
+ int start, end, whole, portion;
+
+ if (!MINI_WINDOW_P (w)
+ || (w == XWINDOW (minibuf_window)
+ && NILP (echo_area_buffer[0])))
+ {
+ struct buffer *b = XBUFFER (w->contents);
+ struct buffer *old_buffer = NULL;
+ struct it it;
+ struct text_pos startp;
+
+ if (b != current_buffer)
+ {
+ old_buffer = current_buffer;
+ set_buffer_internal (b);
+ }
+
+ SET_TEXT_POS_FROM_MARKER (startp, w->start);
+ start_display (&it, w, startp);
+ it.last_visible_x = INT_MAX;
+ whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
+ MOVE_TO_X | MOVE_TO_Y);
+ /* whole = move_it_to (&it, w->window_end_pos, INT_MAX,
+ window_box_height (w), -1,
+ MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); */
+
+ start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
+ end = start + window_box_width (w, TEXT_AREA);
+ portion = end - start;
+ /* After enlarging a horizontally scrolled window such that it
+ gets at least as wide as the text it contains, make sure that
+ the thumb doesn't fill the entire scroll bar so we can still
+ drag it back to see the entire text. */
+ whole = max (whole, end);
+
+ if (it.bidi_p)
+ {
+ Lisp_Object pdir;
+
+ pdir = Fcurrent_bidi_paragraph_direction (Qnil);
+ if (EQ (pdir, Qright_to_left))
+ {
+ start = whole - end;
+ end = start + portion;
+ }
+ }
+
+ if (old_buffer)
+ set_buffer_internal (old_buffer);
+ }
+ else
+ start = end = whole = portion = 0;
+
+ w->hscroll_whole = whole;
+
+ /* Indicate what this scroll bar ought to be displaying now. */
+ if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
+ (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
+ (w, portion, whole, start);
+}
+
+
/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
selected_window is redisplayed.
{
ptrdiff_t new_pt = marker_position (w->pointm);
ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
+
if (new_pt < BEGV)
{
new_pt = BEGV;
{
int window_total_lines
= WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
- int margin =
- scroll_margin > 0
+ int margin
+ = scroll_margin > 0
? min (scroll_margin, window_total_lines / 4)
: 0;
ptrdiff_t margin_pos = CHARPOS (startp);
redisplay_tool_bar (f);
#else
if (WINDOWP (f->tool_bar_window)
- && (FRAME_TOOL_BAR_HEIGHT (f) > 0
+ && (FRAME_TOOL_BAR_LINES (f) > 0
|| !NILP (Vauto_resize_tool_bars))
&& redisplay_tool_bar (f))
ignore_mouse_drag_p = 1;
;
finish_scroll_bars:
- if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
+ if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
{
- /* Set the thumb's position and size. */
- set_vertical_scroll_bar (w);
+ if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
+ /* Set the thumb's position and size. */
+ set_vertical_scroll_bar (w);
+
+ if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
+ /* Set the thumb's position and size. */
+ set_horizontal_scroll_bar (w);
/* Note that we actually used the scroll bar attached to this
window, so it shouldn't be deleted at the end of redisplay. */
/* Initialize iterator and info to start at POS. */
start_display (&it, w, pos);
+ it.glyph_row->reversed_p = false;
/* Display all lines of W. */
while (it.current_y < it.last_visible_y)
&& it.current.dpvec_index < 0)
break;
+ it.glyph_row->reversed_p = false;
if (display_line (&it))
last_text_row = it.glyph_row - 1;
w->cursor.vpos = -1;
last_text_row = NULL;
overlay_arrow_seen = 0;
+ if (it.current_y < it.last_visible_y
+ && !f->fonts_changed
+ && (first_unchanged_at_end_row == NULL
+ || IT_CHARPOS (it) < stop_pos))
+ it.glyph_row->reversed_p = false;
while (it.current_y < it.last_visible_y
&& !f->fonts_changed
&& (first_unchanged_at_end_row == NULL
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : (INTEGERP (glyph->object)
+ : (NILP (glyph->object)
? '0'
: '-'))),
glyph->pixel_width,
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : (INTEGERP (glyph->object)
+ : (NILP (glyph->object)
? '0'
: '-'))),
glyph->pixel_width,
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : (INTEGERP (glyph->object)
+ : (NILP (glyph->object)
? '0'
: '-'))),
glyph->pixel_width,
? 'B'
: (STRINGP (glyph->object)
? 'S'
- : (INTEGERP (glyph->object)
+ : (NILP (glyph->object)
? '0'
: '-'))),
glyph->pixel_width,
else if (glyphs == 1)
{
int area;
+ char s[SHRT_MAX + 4];
for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
{
- char *s = alloca (row->used[area] + 4);
int i;
for (i = 0; i < row->used[area]; ++i)
struct glyph *glyph = row->glyphs[area] + i;
if (i == row->used[area] - 1
&& area == TEXT_AREA
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->type == CHAR_GLYPH
&& glyph->u.ch == ' ')
{
(ptrdiff_t nargs, Lisp_Object *args)
{
Lisp_Object s = Fformat (nargs, args);
- fprintf (stderr, "%s", SDATA (s));
+ fwrite (SDATA (s), 1, SBYTES (s), stderr);
return Qnil;
}
struct buffer *buffer = XBUFFER (w->contents);
struct buffer *old = current_buffer;
const unsigned char *arrow_string = SDATA (overlay_arrow_string);
- int arrow_len = SCHARS (overlay_arrow_string);
+ ptrdiff_t arrow_len = SCHARS (overlay_arrow_string);
const unsigned char *arrow_end = arrow_string + arrow_len;
const unsigned char *p;
struct it it;
set_buffer_temp (buffer);
init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
+ scratch_glyph_row.reversed_p = false;
it.glyph_row->used[TEXT_AREA] = 0;
SET_TEXT_POS (it.position, 0, 0);
truncate_it.area = TEXT_AREA;
truncate_it.glyph_row->used[TEXT_AREA] = 0;
CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
- truncate_it.object = make_number (0);
+ truncate_it.object = Qnil;
produce_special_glyphs (&truncate_it, IT_TRUNCATION);
/* Overwrite glyphs from IT with truncation glyphs. */
it->what = IT_CHARACTER;
memset (&it->position, 0, sizeof it->position);
- it->object = make_number (0);
+ it->object = Qnil;
it->c = it->char_to_display = ' ';
it->len = 1;
else
it->face_id = face->id;
it->start_of_box_run_p = 0;
- append_stretch_glyph (it, make_number (0), stretch_width,
+ append_stretch_glyph (it, Qnil, stretch_width,
it->ascent + it->descent, stretch_ascent);
it->position = saved_pos;
it->avoid_cursor_p = saved_avoid_cursor;
it->what = IT_CHARACTER;
memset (&it->position, 0, sizeof it->position);
- it->object = make_number (0);
+ it->object = Qnil;
it->c = it->char_to_display = ' ';
it->len = 1;
{
while (glyph >= start
&& glyph->type == CHAR_GLYPH
- && INTEGERP (glyph->object))
+ && NILP (glyph->object))
--glyph;
}
else
{
while (glyph <= start
&& glyph->type == CHAR_GLYPH
- && INTEGERP (glyph->object))
+ && NILP (glyph->object))
++glyph;
}
&& glyph->u.ch == ' '))
&& trailing_whitespace_p (glyph->charpos))
{
- int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
+ int face_id = lookup_named_face (f, Qtrailing_whitespace, false);
if (face_id < 0)
return;
{
start = r1->glyphs[TEXT_AREA];
end = start + r1->used[TEXT_AREA];
- /* Glyphs inserted by redisplay have an integer (zero)
- as their object. */
+ /* Glyphs inserted by redisplay have nil as their object. */
while (end > start
- && INTEGERP ((end - 1)->object)
+ && NILP ((end - 1)->object)
&& (end - 1)->charpos <= 0)
--end;
if (end > start)
end = r1->glyphs[TEXT_AREA] - 1;
start = end + r1->used[TEXT_AREA];
while (end < start
- && INTEGERP ((end + 1)->object)
+ && NILP ((end + 1)->object)
&& (end + 1)->charpos <= 0)
++end;
if (end < start)
the previous non-empty line. */
if (pos >= ZV && pos > BEGV)
DEC_BOTH (pos, bytepos);
- if (fast_looking_at (build_string ("[\f\t ]*\n"),
+ AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
+ if (fast_looking_at (trailing_white_space,
pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
{
while ((c = FETCH_BYTE (bytepos)) == '\n'
}
}
+DEFUN ("bidi-find-overridden-directionality",
+ Fbidi_find_overridden_directionality,
+ Sbidi_find_overridden_directionality, 2, 3, 0,
+ doc: /* Return position between FROM and TO where directionality was overridden.
+
+This function returns the first character position in the specified
+region of OBJECT where there is a character whose `bidi-class' property
+is `L', but which was forced to display as `R' by a directional
+override, and likewise with characters whose `bidi-class' is `R'
+or `AL' that were forced to display as `L'.
+
+If no such character is found, the function returns nil.
+
+OBJECT is a Lisp string or buffer to search for overridden
+directionality, and defaults to the current buffer if nil or omitted.
+OBJECT can also be a window, in which case the function will search
+the buffer displayed in that window. Passing the window instead of
+a buffer is preferable when the buffer is displayed in some window,
+because this function will then be able to correctly account for
+window-specific overlays, which can affect the results.
+
+Strong directional characters `L', `R', and `AL' can have their
+intrinsic directionality overridden by directional override
+control characters RLO \(u+202e) and LRO \(u+202d). See the
+function `get-char-code-property' for a way to inquire about
+the `bidi-class' property of a character. */)
+ (Lisp_Object from, Lisp_Object to, Lisp_Object object)
+{
+ struct buffer *buf = current_buffer;
+ struct buffer *old = buf;
+ struct window *w = NULL;
+ bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
+ struct bidi_it itb;
+ ptrdiff_t from_pos, to_pos, from_bpos;
+ void *itb_data;
+
+ if (!NILP (object))
+ {
+ if (BUFFERP (object))
+ buf = XBUFFER (object);
+ else if (WINDOWP (object))
+ {
+ w = decode_live_window (object);
+ buf = XBUFFER (w->contents);
+ frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
+ }
+ else
+ CHECK_STRING (object);
+ }
+
+ if (STRINGP (object))
+ {
+ /* Characters in unibyte strings are always treated by bidi.c as
+ strong LTR. */
+ if (!STRING_MULTIBYTE (object)
+ /* When we are loading loadup.el, the character property
+ tables needed for bidi iteration are not yet
+ available. */
+ || !NILP (Vpurify_flag))
+ return Qnil;
+
+ validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
+ if (from_pos >= SCHARS (object))
+ return Qnil;
+
+ /* Set up the bidi iterator. */
+ itb_data = bidi_shelve_cache ();
+ itb.paragraph_dir = NEUTRAL_DIR;
+ itb.string.lstring = object;
+ itb.string.s = NULL;
+ itb.string.schars = SCHARS (object);
+ itb.string.bufpos = 0;
+ itb.string.from_disp_str = 0;
+ itb.string.unibyte = 0;
+ itb.w = w;
+ bidi_init_it (0, 0, frame_window_p, &itb);
+ }
+ else
+ {
+ /* Nothing this fancy can happen in unibyte buffers, or in a
+ buffer that disabled reordering, or if FROM is at EOB. */
+ if (NILP (BVAR (buf, bidi_display_reordering))
+ || NILP (BVAR (buf, enable_multibyte_characters))
+ /* When we are loading loadup.el, the character property
+ tables needed for bidi iteration are not yet
+ available. */
+ || !NILP (Vpurify_flag))
+ return Qnil;
+
+ set_buffer_temp (buf);
+ validate_region (&from, &to);
+ from_pos = XINT (from);
+ to_pos = XINT (to);
+ if (from_pos >= ZV)
+ return Qnil;
+
+ /* Set up the bidi iterator. */
+ itb_data = bidi_shelve_cache ();
+ from_bpos = CHAR_TO_BYTE (from_pos);
+ if (from_pos == BEGV)
+ {
+ itb.charpos = BEGV;
+ itb.bytepos = BEGV_BYTE;
+ }
+ else if (FETCH_CHAR (from_bpos - 1) == '\n')
+ {
+ itb.charpos = from_pos;
+ itb.bytepos = from_bpos;
+ }
+ else
+ itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
+ -1, &itb.bytepos);
+ itb.paragraph_dir = NEUTRAL_DIR;
+ itb.string.s = NULL;
+ itb.string.lstring = Qnil;
+ itb.string.bufpos = 0;
+ itb.string.from_disp_str = 0;
+ itb.string.unibyte = 0;
+ itb.w = w;
+ bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
+ }
+
+ ptrdiff_t found;
+ do {
+ /* For the purposes of this function, the actual base direction of
+ the paragraph doesn't matter, so just set it to L2R. */
+ bidi_paragraph_init (L2R, &itb, 0);
+ while ((found = bidi_find_first_overridden (&itb)) < from_pos)
+ ;
+ } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
+
+ bidi_unshelve_cache (itb_data, 0);
+ set_buffer_temp (old);
+
+ return (from_pos <= found && found < to_pos) ? make_number (found) : Qnil;
+}
+
DEFUN ("move-point-visually", Fmove_point_visually,
Smove_point_visually, 1, 1, 0,
doc: /* Move point in the visual order in the specified DIRECTION.
#define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
(!(ROW)->continued_p \
- && INTEGERP ((GLYPH)->object) \
+ && NILP ((GLYPH)->object) \
&& (GLYPH)->type == CHAR_GLYPH \
&& (GLYPH)->u.ch == ' ' \
&& (GLYPH)->charpos >= 0 \
w->cursor.vpos = -1;
return make_number (PT);
}
- else if (!INTEGERP (g->object) && !EQ (g->object, gpt->object))
+ else if (!NILP (g->object) && !EQ (g->object, gpt->object))
{
ptrdiff_t new_pos;
if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
new_pos += (row->reversed_p ? -dir : dir);
else
- new_pos -= (row->reversed_p ? -dir : dir);;
+ new_pos -= (row->reversed_p ? -dir : dir);
}
else if (BUFFERP (g->object))
new_pos = g->charpos;
return make_number (PT);
}
}
- if (g == e || INTEGERP (g->object))
+ if (g == e || NILP (g->object))
{
if (row->truncated_on_left_p || row->truncated_on_right_p)
goto simulate_display;
EOB also has one glyph, but its charpos is -1. */
|| (row->ends_at_zv_p
&& !row->reversed_p
- && INTEGERP (g->object)
+ && NILP (g->object)
&& g->type == CHAR_GLYPH
&& g->u.ch == ' '))
{
|| g->type == STRETCH_GLYPH
|| (row->ends_at_zv_p
&& row->reversed_p
- && INTEGERP (g->object)
+ && NILP (g->object)
&& g->type == CHAR_GLYPH
&& g->u.ch == ' '))
{
#undef ROW_GLYPH_NEWLINE_P
}
+DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
+ Sbidi_resolved_levels, 0, 1, 0,
+ doc: /* Return the resolved bidirectional levels of characters at VPOS.
+
+The resolved levels are produced by the Emacs bidi reordering engine
+that implements the UBA, the Unicode Bidirectional Algorithm. Please
+read the Unicode Standard Annex 9 (UAX#9) for background information
+about these levels.
+
+VPOS is the zero-based number of the current window's screen line
+for which to produce the resolved levels. If VPOS is nil or omitted,
+it defaults to the screen line of point. If the window displays a
+header line, VPOS of zero will report on the header line, and first
+line of text in the window will have VPOS of 1.
+
+Value is an array of resolved levels, indexed by glyph number.
+Glyphs are numbered from zero starting from the beginning of the
+screen line, i.e. the left edge of the window for left-to-right lines
+and from the right edge for right-to-left lines. The resolved levels
+are produced only for the window's text area; text in display margins
+is not included.
+
+If the selected window's display is not up-to-date, or if the specified
+screen line does not display text, this function returns nil. It is
+highly recommended to bind this function to some simple key, like F8,
+in order to avoid these problems.
+
+This function exists mainly for testing the correctness of the
+Emacs UBA implementation, in particular with the test suite. */)
+ (Lisp_Object vpos)
+{
+ struct window *w = XWINDOW (selected_window);
+ struct buffer *b = XBUFFER (w->contents);
+ int nrow;
+ struct glyph_row *row;
+
+ if (NILP (vpos))
+ {
+ int d1, d2, d3, d4, d5;
+
+ pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
+ }
+ else
+ {
+ CHECK_NUMBER_COERCE_MARKER (vpos);
+ nrow = XINT (vpos);
+ }
+
+ /* We require up-to-date glyph matrix for this window. */
+ if (w->window_end_valid
+ && !windows_or_buffers_changed
+ && b
+ && !b->clip_changed
+ && !b->prevent_redisplay_optimizations_p
+ && !window_outdated (w)
+ && nrow >= 0
+ && nrow < w->current_matrix->nrows
+ && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
+ && MATRIX_ROW_DISPLAYS_TEXT_P (row))
+ {
+ struct glyph *g, *e, *g1;
+ int nglyphs, i;
+ Lisp_Object levels;
+
+ if (!row->reversed_p) /* Left-to-right glyph row. */
+ {
+ g = g1 = row->glyphs[TEXT_AREA];
+ e = g + row->used[TEXT_AREA];
+
+ /* Skip over glyphs at the start of the row that was
+ generated by redisplay for its own needs. */
+ while (g < e
+ && NILP (g->object)
+ && g->charpos < 0)
+ g++;
+ g1 = g;
+
+ /* Count the "interesting" glyphs in this row. */
+ for (nglyphs = 0; g < e && !NILP (g->object); g++)
+ nglyphs++;
+
+ /* Create and fill the array. */
+ levels = make_uninit_vector (nglyphs);
+ for (i = 0; g1 < g; i++, g1++)
+ ASET (levels, i, make_number (g1->resolved_level));
+ }
+ else /* Right-to-left glyph row. */
+ {
+ g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
+ e = row->glyphs[TEXT_AREA] - 1;
+ while (g > e
+ && NILP (g->object)
+ && g->charpos < 0)
+ g--;
+ g1 = g;
+ for (nglyphs = 0; g > e && !NILP (g->object); g--)
+ nglyphs++;
+ levels = make_uninit_vector (nglyphs);
+ for (i = 0; g1 > g; i++, g1--)
+ ASET (levels, i, make_number (g1->resolved_level));
+ }
+ return levels;
+ }
+ else
+ return Qnil;
+}
+
+
\f
/***********************************************************************
Menu Bar
clear_glyph_row (row);
row->enabled_p = true;
row->full_width_p = 1;
+ row->reversed_p = false;
}
/* Display all items of the menu bar. */
}
else if (CHARACTERP (eoltype))
{
- unsigned char *tmp = alloca (MAX_MULTIBYTE_LENGTH);
int c = XFASTINT (eoltype);
- eol_str_len = CHAR_STRING (c, tmp);
- eol_str = tmp;
+ return buf + CHAR_STRING (c, (unsigned char *) buf);
}
else
{
}
case 'e':
-#ifndef SYSTEM_MALLOC
+#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
{
if (NILP (Vmemory_full))
return "";
return decode_mode_spec_buf;
no_value:
{
- char* p = decode_mode_spec_buf;
+ char *p = decode_mode_spec_buf;
int pad = width - 2;
while (pad-- > 0)
*p++ = ' ';
it->face_id
= face_at_string_position (it->w, face_string, face_string_pos,
- 0, &endptr, it->base_face_id, 0);
+ 0, &endptr, it->base_face_id, false);
face = FACE_FROM_ID (it->f, it->face_id);
it->face_box_p = face->box != FACE_NO_BOX;
}
return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
}
- prop = buffer_local_value_1 (prop, it->w->contents);
+ prop = buffer_local_value (prop, it->w->contents);
if (EQ (prop, Qunbound))
prop = Qnil;
}
return OK_PIXELS (pixels);
}
- car = buffer_local_value_1 (car, it->w->contents);
+ car = buffer_local_value (car, it->w->contents);
if (EQ (car, Qunbound))
car = Qnil;
}
#endif
{
eassert (face != NULL);
- PREPARE_FACE_FOR_DISPLAY (f, face);
+ prepare_face_for_display (f, face);
}
return face;
/* Make sure X resources of the face are allocated. */
eassert (face != NULL);
- PREPARE_FACE_FOR_DISPLAY (f, face);
+ prepare_face_for_display (f, face);
if (two_byte_p)
*two_byte_p = 0;
s->ybase += voffset;
/* The case that face->gc == 0 is handled when drawing the glyph
- string by calling PREPARE_FACE_FOR_DISPLAY. */
+ string by calling prepare_face_for_display. */
eassert (s->face);
return glyph - s->row->glyphs[s->area];
}
face_id = (row)->glyphs[area][START].face_id; \
\
s = alloca (sizeof *s); \
- char2b = alloca ((END - START) * sizeof *char2b); \
+ SAFE_NALLOCA (char2b, 1, (END) - (START)); \
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 = alloca (cmp->glyph_len * sizeof *char2b); \
+ SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
\
/* Make glyph_strings for each glyph sequence that is drawable by \
the same face, and append them to HEAD/TAIL. */ \
gstring = (composition_gstring_from_id \
((row)->glyphs[area][START].u.cmp.id)); \
s = alloca (sizeof *s); \
- char2b = alloca (LGSTRING_GLYPH_LEN (gstring) * sizeof *char2b); \
+ SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
append_glyph_string (&(HEAD), &(TAIL), s); \
s->x = (X); \
BUILD_GLYPH_STRINGS will modify its start parameter. That's
the reason we use a separate variable `i'. */
i = start;
+ USE_SAFE_ALLOCA;
BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
if (tail)
x_reached = tail->x + tail->background_width;
RELEASE_HDC (hdc, f);
+ SAFE_FREE ();
return x_reached;
}
if (it->bidi_p)
{
glyph->resolved_level = it->bidi_it.resolved_level;
- if ((it->bidi_it.type & 7) != it->bidi_it.type)
- emacs_abort ();
+ eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
glyph->bidi_type = it->bidi_it.type;
}
else
if (it->bidi_p)
{
glyph->resolved_level = it->bidi_it.resolved_level;
- if ((it->bidi_it.type & 7) != it->bidi_it.type)
- emacs_abort ();
+ eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
glyph->bidi_type = it->bidi_it.type;
}
++it->glyph_row->used[area];
face = FACE_FROM_ID (it->f, it->face_id);
eassert (face);
/* Make sure X resources of the face is loaded. */
- PREPARE_FACE_FOR_DISPLAY (it->f, face);
+ prepare_face_for_display (it->f, face);
if (it->image_id < 0)
{
if (it->bidi_p)
{
glyph->resolved_level = it->bidi_it.resolved_level;
- if ((it->bidi_it.type & 7) != it->bidi_it.type)
- emacs_abort ();
+ eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
glyph->bidi_type = it->bidi_it.type;
}
++it->glyph_row->used[area];
if (it->bidi_p)
{
glyph->resolved_level = it->bidi_it.resolved_level;
- if ((it->bidi_it.type & 7) != it->bidi_it.type)
- emacs_abort ();
+ eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
glyph->bidi_type = it->bidi_it.type;
}
else
{
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);
+ prepare_face_for_display (it->f, face);
}
#endif
GLYPH glyph;
temp_it = *it;
- temp_it.object = make_number (0);
+ temp_it.object = Qnil;
memset (&temp_it.current, 0, sizeof temp_it.current);
if (what == IT_CONTINUATION)
(((temp_it.ascent + temp_it.descent)
* FONT_BASE (font)) / FONT_HEIGHT (font));
- append_stretch_glyph (&temp_it, make_number (0), stretch_width,
+ append_stretch_glyph (&temp_it, Qnil, stretch_width,
temp_it.ascent + temp_it.descent,
stretch_ascent);
}
int face_id;
struct face *face;
- face_id = lookup_named_face (it->f, face_name, 0);
+ face_id = lookup_named_face (it->f, face_name, false);
if (face_id < 0)
return make_number (-1);
if (it->bidi_p)
{
glyph->resolved_level = it->bidi_it.resolved_level;
- if ((it->bidi_it.type & 7) != it->bidi_it.type)
- emacs_abort ();
+ eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
glyph->bidi_type = it->bidi_it.type;
}
++it->glyph_row->used[area];
face = FACE_FROM_ID (it->f, face_id);
font = face->font ? face->font : FRAME_FONT (it->f);
- PREPARE_FACE_FOR_DISPLAY (it->f, face);
+ prepare_face_for_display (it->f, face);
if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
{
sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c);
str = buf;
}
- for (len = 0; str[len] && ASCII_BYTE_P (str[len]) && len < 6; len++)
+ for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
code[len] = font->driver->encode_char (font, str[len]);
upper_len = (len + 1) / 2;
font->driver->text_extents (font, code, upper_len,
/* Erase the image of a cursor of window W from the screen. */
-#ifndef HAVE_NTGUI
-static
-#endif
void
erase_phys_cursor (struct window *w)
{
#ifdef HAVE_WINDOW_SYSTEM
/* Change the mouse cursor. */
- if (FRAME_WINDOW_P (f))
+ if (FRAME_WINDOW_P (f) && NILP (do_mouse_tracking))
{
#if ! defined (USE_GTK) && ! defined (HAVE_NS)
if (draw == DRAW_NORMAL_TEXT
while (g < e)
{
- if (((BUFFERP (g->object) || INTEGERP (g->object))
+ if (((BUFFERP (g->object) || NILP (g->object))
&& start_charpos <= g->charpos && g->charpos < end_charpos)
/* A glyph that comes from DISP_STRING is by
definition to be highlighted. */
while (g < e)
{
- if (((BUFFERP (g->object) || INTEGERP (g->object))
+ if (((BUFFERP (g->object) || NILP (g->object))
&& ((start_charpos <= g->charpos && g->charpos < end_charpos)
/* If the buffer position of the first glyph in
the row is equal to END_CHARPOS, it means
{
struct glyph *beg = prev->glyphs[TEXT_AREA];
glyph = beg + prev->used[TEXT_AREA];
- while (--glyph >= beg && INTEGERP (glyph->object));
+ while (--glyph >= beg && NILP (glyph->object));
if (glyph < beg
|| !(EQ (glyph->object, before_string)
|| EQ (glyph->object, disp_string)))
/* Skip truncation glyphs at the start of the glyph row. */
if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
for (; glyph < end
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->charpos < 0;
++glyph)
x += glyph->pixel_width;
or DISP_STRING, and the first glyph from buffer whose
position is between START_CHARPOS and END_CHARPOS. */
for (; glyph < end
- && !INTEGERP (glyph->object)
+ && !NILP (glyph->object)
&& !EQ (glyph->object, disp_string)
&& !(BUFFERP (glyph->object)
&& (glyph->charpos >= start_charpos
/* Skip truncation glyphs at the start of the glyph row. */
if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
for (; glyph > end
- && INTEGERP (glyph->object)
+ && NILP (glyph->object)
&& glyph->charpos < 0;
--glyph)
;
or DISP_STRING, and the first glyph from buffer whose
position is between START_CHARPOS and END_CHARPOS. */
for (; glyph > end
- && !INTEGERP (glyph->object)
+ && !NILP (glyph->object)
&& !EQ (glyph->object, disp_string)
&& !(BUFFERP (glyph->object)
&& (glyph->charpos >= start_charpos
row, and also blanks and stretch glyphs inserted by
extend_face_to_end_of_line. */
while (end > glyph
- && INTEGERP ((end - 1)->object))
+ && NILP ((end - 1)->object))
--end;
/* Scan the rest of the glyph row from the end, looking for the
first glyph that comes from BEFORE_STRING, AFTER_STRING, or
and END_CHARPOS */
for (--end;
end > glyph
- && !INTEGERP (end->object)
+ && !NILP (end->object)
&& !EQ (end->object, disp_string)
&& !(BUFFERP (end->object)
&& (end->charpos >= start_charpos
x = r2->x;
end++;
while (end < glyph
- && INTEGERP (end->object))
+ && NILP (end->object))
{
x += end->pixel_width;
++end;
and END_CHARPOS */
for ( ;
end < glyph
- && !INTEGERP (end->object)
+ && !NILP (end->object)
&& !EQ (end->object, disp_string)
&& !(BUFFERP (end->object)
&& (end->charpos >= start_charpos
else if (area == ON_MODE_LINE)
{
Lisp_Object default_help
- = buffer_local_value_1 (Qmode_line_default_help_echo,
- w->contents);
+ = buffer_local_value (Qmode_line_default_help_echo,
+ w->contents);
if (STRINGP (default_help))
{
charpos,
0, &ignore,
glyph->face_id,
- 1);
+ true);
show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
if (NILP (pointer))
else
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
- || part == ON_SCROLL_BAR)
+ || part == ON_VERTICAL_SCROLL_BAR
+ || part == ON_HORIZONTAL_SCROLL_BAR)
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
else
cursor = FRAME_X_OUTPUT (f)->text_cursor;
if (glyph == NULL
|| area != TEXT_AREA
|| !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
- /* Glyph's OBJECT is an integer for glyphs inserted by the
+ /* Glyph's OBJECT is nil for glyphs inserted by the
display engine for its internal purposes, like truncation
and continuation glyphs and blanks beyond the end of
line's text on text terminals. If we are over such a
glyph, we are not over any text. */
- || INTEGERP (glyph->object)
+ || NILP (glyph->object)
/* R2L rows have a stretch glyph at their front, which
stands for no text, whereas L2R rows have no glyphs at
all beyond the end of text. Treat such stretch glyphs
/* Is this char mouse-active or does it have help-echo? */
position = make_number (pos);
+ USE_SAFE_ALLOCA;
+
if (BUFFERP (object))
{
/* Put all the overlays we want in a vector in overlay_vec. */
hlinfo->mouse_face_window = window;
hlinfo->mouse_face_face_id
= face_at_string_position (w, object, pos, 0, &ignore,
- glyph->face_id, 1);
+ glyph->face_id, true);
show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
cursor = No_Cursor;
}
BEGV = obegv;
ZV = ozv;
current_buffer = obuf;
+ SAFE_FREE ();
}
set_cursor:
if (w == 0 || h == 0)
{
r.x = r.y = 0;
- r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f);
- r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f);
+ r.width = FRAME_TEXT_WIDTH (f);
+ r.height = FRAME_TEXT_HEIGHT (f);
}
else
{
Vmessage_stack = Qnil;
staticpro (&Vmessage_stack);
+ /* Non-nil means don't actually do any redisplay. */
DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
+
DEFSYM (Qredisplay_internal, "redisplay_internal (C function)");
message_dolog_marker1 = Fmake_marker ();
defsubr (&Scurrent_bidi_paragraph_direction);
defsubr (&Swindow_text_pixel_size);
defsubr (&Smove_point_visually);
+ defsubr (&Sbidi_find_overridden_directionality);
DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
DEFSYM (Qeval, "eval");
DEFSYM (QCdata, ":data");
+
+ /* Names of text properties relevant for redisplay. */
DEFSYM (Qdisplay, "display");
DEFSYM (Qspace_width, "space-width");
DEFSYM (Qraise, "raise");
DEFSYM (QCfile, ":file");
DEFSYM (Qfontified, "fontified");
DEFSYM (Qfontification_functions, "fontification-functions");
+
+ /* Name of the face used to highlight trailing whitespace. */
DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
+
+ /* Name and number of the face used to highlight escape glyphs. */
DEFSYM (Qescape_glyph, "escape-glyph");
+
+ /* Name and number of the face used to highlight non-breaking spaces. */
DEFSYM (Qnobreak_space, "nobreak-space");
+
+ /* The symbol 'image' which is the car of the lists used to represent
+ images in Lisp. Also a tool bar style. */
DEFSYM (Qimage, "image");
+
+ /* Tool bar styles. */
DEFSYM (Qtext, "text");
DEFSYM (Qboth, "both");
DEFSYM (Qboth_horiz, "both-horiz");
DEFSYM (Qtext_image_horiz, "text-image-horiz");
+
+ /* The image map types. */
DEFSYM (QCmap, ":map");
DEFSYM (QCpointer, ":pointer");
DEFSYM (Qrect, "rect");
DEFSYM (Qcircle, "circle");
DEFSYM (Qpoly, "poly");
+
+ /* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable. */
+ DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
DEFSYM (Qmessage_truncate_lines, "message-truncate-lines");
+
DEFSYM (Qgrow_only, "grow-only");
- DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
DEFSYM (Qposition, "position");
DEFSYM (Qbuffer_position, "buffer-position");
DEFSYM (Qobject, "object");
+
+ /* Cursor shapes. */
DEFSYM (Qbar, "bar");
DEFSYM (Qhbar, "hbar");
DEFSYM (Qbox, "box");
DEFSYM (Qhollow, "hollow");
+
+ /* Pointer shapes. */
DEFSYM (Qhand, "hand");
DEFSYM (Qarrow, "arrow");
+ /* also Qtext */
+
DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
list_of_error = list1 (list2 (intern_c_string ("error"),
intern_c_string ("void-variable")));
staticpro (&list_of_error);
+ /* Values of those variables at last redisplay are stored as
+ properties on 'overlay-arrow-position' symbol. However, if
+ Voverlay_arrow_position is a marker, last-arrow-position is its
+ numerical position. */
DEFSYM (Qlast_arrow_position, "last-arrow-position");
DEFSYM (Qlast_arrow_string, "last-arrow-string");
+
+ /* Alternative overlay-arrow-string and overlay-arrow-bitmap
+ properties on a symbol in overlay-arrow-variable-list. */
DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
DEFSYM (Qright_to_left, "right-to-left");
DEFSYM (Qleft_to_right, "left-to-right");
+ defsubr (&Sbidi_resolved_levels);
#ifdef HAVE_WINDOW_SYSTEM
DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
doc: /* The pointer shape to show in void text areas.
-A value of nil means to show the text pointer. Other options are `arrow',
-`text', `hand', `vdrag', `hdrag', `modeline', and `hourglass'. */);
+A value of nil means to show the text pointer. Other options are
+`arrow', `text', `hand', `vdrag', `hdrag', `nhdrag', `modeline', and
+`hourglass'. */);
Vvoid_text_area_pointer = Qarrow;
DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
doc: /* List of functions to call before redisplaying a window with scrolling.
Each function is called with two arguments, the window and its new
-display-start position. Note that these functions are also called by
-`set-window-buffer'. Also note that the value of `window-end' is not
-valid when these functions are called.
+display-start position.
+These functions are called whenever the `window-start' marker is modified,
+either to point into another buffer (e.g. via `set-window-buffer') or another
+place in the same buffer.
+Note that the value of `window-end' is not valid when these functions are
+called.
Warning: Do not use this feature to alter the way the window
is scrolled. It is not designed for that, and such use probably won't
doc: /* Non-nil means don't free realized faces. Internal use only. */);
inhibit_free_realized_faces = 0;
+ DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
+ doc: /* Non-nil means don't mirror characters even when bidi context requires that.
+Intended for use during debugging and for testing bidi display;
+see biditest.el in the test suite. */);
+ inhibit_bidi_mirroring = 0;
+
#ifdef GLYPH_DEBUG
DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
doc: /* Inhibit try_window_id display optimization. */);
hourglass_shown_p = 0;
#endif /* HAVE_WINDOW_SYSTEM */
+ /* Name of the face used to display glyphless characters. */
DEFSYM (Qglyphless_char, "glyphless-char");
+
+ /* Method symbols for Vglyphless_char_display. */
DEFSYM (Qhex_code, "hex-code");
DEFSYM (Qempty_box, "empty-box");
DEFSYM (Qthin_space, "thin-space");
or t (meaning all windows). */);
Vpre_redisplay_function = intern ("ignore");
+ /* Symbol for the purpose of Vglyphless_char_display. */
DEFSYM (Qglyphless_char_display, "glyphless-char-display");
Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_number (1));
r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
r->total_cols = FRAME_COLS (f);
r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
- r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
+ r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
- m->top_line = FRAME_LINES (f) - 1;
+ m->top_line = FRAME_TOTAL_LINES (f) - 1;
m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
m->total_cols = FRAME_COLS (f);
m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
/* Platform-independent portion of hourglass implementation. */
+/* Timer function of hourglass_atimer. */
+
+static void
+show_hourglass (struct atimer *timer)
+{
+ /* The timer implementation will cancel this timer automatically
+ after this function has run. Set hourglass_atimer to null
+ so that we know the timer doesn't have to be canceled. */
+ hourglass_atimer = NULL;
+
+ if (!hourglass_shown_p)
+ {
+ Lisp_Object tail, frame;
+
+ block_input ();
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
+
+ if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
+ && FRAME_RIF (f)->show_hourglass)
+ FRAME_RIF (f)->show_hourglass (f);
+ }
+
+ hourglass_shown_p = 1;
+ unblock_input ();
+ }
+}
+
/* Cancel a currently active hourglass timer, and start a new one. */
+
void
start_hourglass (void)
{
else
delay = make_timespec (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);
}
-
/* Cancel the hourglass cursor timer if active, hide a busy cursor if
shown. */
+
void
cancel_hourglass (void)
{
}
if (hourglass_shown_p)
- hide_hourglass ();
+ {
+ Lisp_Object tail, frame;
+
+ block_input ();
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
+
+ if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
+ && FRAME_RIF (f)->hide_hourglass)
+ FRAME_RIF (f)->hide_hourglass (f);
+#ifdef HAVE_NTGUI
+ /* No cursors on non GUI frames - restore to stock arrow cursor. */
+ else if (!FRAME_W32_P (f))
+ w32_arrow_cursor ();
+#endif
+ }
+
+ hourglass_shown_p = 0;
+ unblock_input ();
+ }
}
#endif /* HAVE_WINDOW_SYSTEM */