summaryrefslogtreecommitdiff
path: root/src/xdisp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xdisp.c')
-rw-r--r--src/xdisp.c592
1 files changed, 405 insertions, 187 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index 80d4d52531a..ad28dacf4e5 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -816,11 +816,11 @@ Lisp_Object previous_help_echo_string;
#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 */
@@ -1024,6 +1024,8 @@ window_text_bottom_y (struct window *w)
if (WINDOW_WANTS_MODELINE_P (w))
height -= CURRENT_MODE_LINE_HEIGHT (w);
+ height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
+
return height;
}
@@ -1068,6 +1070,7 @@ window_box_height (struct window *w)
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
@@ -1141,7 +1144,7 @@ window_box_left_offset (struct window *w, enum glyph_row_area area)
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. */
@@ -1957,8 +1960,8 @@ pixel_to_glyph_coords (struct frame *f, register int pix_x, register int pix_y,
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
@@ -2174,7 +2177,10 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
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);
@@ -2296,10 +2302,7 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
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)
@@ -2501,7 +2504,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
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)
@@ -2535,7 +2538,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
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;
@@ -2623,15 +2626,14 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
{
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);
@@ -2639,7 +2641,7 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
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);
}
@@ -2971,10 +2973,6 @@ init_iterator (struct it *it, struct window *w,
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
@@ -3669,6 +3667,7 @@ next_overlay_change (ptrdiff_t pos)
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);
@@ -3685,6 +3684,7 @@ next_overlay_change (ptrdiff_t pos)
endpos = min (endpos, oendpos);
}
+ SAFE_FREE ();
return endpos;
}
@@ -5130,7 +5130,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
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))))
{
@@ -5745,10 +5745,11 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
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)
@@ -6931,7 +6932,8 @@ get_next_display_element (struct it *it)
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
@@ -8344,7 +8346,7 @@ next_element_from_buffer (struct it *it)
/* 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;
@@ -10027,9 +10029,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
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);
}
}
@@ -10204,9 +10204,9 @@ message3 (Lisp_Object m)
{
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 ();
}
@@ -10311,19 +10311,17 @@ message_with_string (const char *m, Lisp_Object string, int log)
{
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)
@@ -10410,11 +10408,13 @@ vmessage (const char *m, va_list ap)
{
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);
@@ -10580,6 +10580,7 @@ with_echo_area_buffer (struct window *w, int which,
{
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);
@@ -10618,7 +10619,7 @@ with_echo_area_buffer_unwind_data (struct window *w)
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;
@@ -10630,12 +10631,14 @@ with_echo_area_buffer_unwind_data (struct window *w)
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);
}
@@ -10667,9 +10670,12 @@ unwind_with_echo_area_buffer (Lisp_Object vector)
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;
@@ -11918,11 +11924,6 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
#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
@@ -11949,7 +11950,7 @@ update_tool_bar (struct frame *f, int save_match_data)
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)
@@ -12045,11 +12046,11 @@ static void
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. */
@@ -12068,9 +12069,12 @@ build_desired_tool_bar_string (struct frame *f)
(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,
@@ -12181,8 +12185,10 @@ build_desired_tool_bar_string (struct frame *f)
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
@@ -12193,6 +12199,7 @@ build_desired_tool_bar_string (struct frame *f)
end = i + 1;
Fadd_text_properties (make_number (i), make_number (end),
props, f->desired_tool_bar_string);
+ UNGCPRO;
#undef PROP
}
@@ -12333,16 +12340,9 @@ display_tool_bar_line (struct it *it, int height)
}
-/* 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)
{
@@ -12356,6 +12356,7 @@ 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);
@@ -12381,11 +12382,6 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
#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.
@@ -12416,7 +12412,6 @@ PIXELWISE non-nil means return the height of the tool bar in pixels. */)
/* 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)
{
@@ -12438,7 +12433,7 @@ 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. */
@@ -12446,6 +12441,7 @@ redisplay_tool_bar (struct frame *f)
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);
@@ -12465,14 +12461,7 @@ redisplay_tool_bar (struct frame *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);
/* Always do that now. */
clear_glyph_matrix (w->desired_matrix);
f->fonts_changed = 1;
@@ -12525,14 +12514,11 @@ redisplay_tool_bar (struct frame *f)
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
@@ -12551,15 +12537,13 @@ redisplay_tool_bar (struct frame *f)
/* 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);
@@ -12571,35 +12555,12 @@ redisplay_tool_bar (struct frame *f)
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);
+ clear_glyph_matrix (w->desired_matrix);
+ f->n_tool_bar_rows = nrows;
+ f->fonts_changed = 1;
+
+ return 1;
}
}
}
@@ -12724,7 +12685,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
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);
@@ -12736,7 +12697,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_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
{
@@ -12761,7 +12722,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
event.arg = key;
event.modifiers = modifiers;
kbd_buffer_store_event (&event);
- last_tool_bar_item = -1;
+ f->last_tool_bar_item = -1;
}
}
@@ -12811,8 +12772,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
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;
@@ -12934,7 +12894,20 @@ hscroll_window_tree (Lisp_Object window)
/* 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
@@ -12947,8 +12920,7 @@ hscroll_window_tree (Lisp_Object window)
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))))
@@ -15839,9 +15811,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
return rc;
}
-#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK
-static
-#endif
+
void
set_vertical_scroll_bar (struct window *w)
{
@@ -15880,6 +15850,71 @@ 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.
@@ -16093,6 +16128,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
{
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;
@@ -16866,7 +16902,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
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;
@@ -16906,10 +16942,15 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
;
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. */
@@ -16965,6 +17006,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
/* 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)
@@ -17148,6 +17190,7 @@ try_window_reusing_current_matrix (struct window *w)
&& it.current.dpvec_index < 0)
break;
+ it.glyph_row->reversed_p = false;
if (display_line (&it))
last_text_row = it.glyph_row - 1;
@@ -18168,6 +18211,11 @@ try_window_id (struct window *w)
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
@@ -18712,10 +18760,10 @@ dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
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)
@@ -18868,7 +18916,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
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;
@@ -18877,6 +18925,7 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
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);
@@ -20915,7 +20964,8 @@ See also `bidi-paragraph-direction'. */)
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'
@@ -21026,7 +21076,7 @@ Value is the new character position of point. */)
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;
@@ -21416,6 +21466,114 @@ Value is the new character position of point. */)
#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
+ && INTEGERP (g->object)
+ && g->charpos < 0)
+ g++;
+ g1 = g;
+
+ /* Count the "interesting" glyphs in this row. */
+ for (nglyphs = 0; g < e && !INTEGERP (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
+ && INTEGERP (g->object)
+ && g->charpos < 0)
+ g--;
+ g1 = g;
+ for (nglyphs = 0; g > e && !INTEGERP (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;
+}
+
+
/***********************************************************************
Menu Bar
@@ -21494,6 +21652,7 @@ display_menu_bar (struct window *w)
clear_glyph_row (row);
row->enabled_p = true;
row->full_width_p = 1;
+ row->reversed_p = false;
}
/* Display all items of the menu bar. */
@@ -22727,10 +22886,8 @@ decode_mode_spec_coding (Lisp_Object coding_system, register char *buf, int eol_
}
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
{
@@ -22866,7 +23023,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
}
case 'e':
-#ifndef SYSTEM_MALLOC
+#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
{
if (NILP (Vmemory_full))
return "";
@@ -23007,7 +23164,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
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++ = ' ';
@@ -23759,7 +23916,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
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;
}
@@ -23811,7 +23968,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
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;
}
@@ -23988,7 +24145,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
#endif
{
eassert (face != NULL);
- PREPARE_FACE_FOR_DISPLAY (f, face);
+ prepare_face_for_display (f, face);
}
return face;
@@ -24011,7 +24168,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
/* 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;
@@ -24328,7 +24485,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
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];
}
@@ -24646,7 +24803,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
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); \
@@ -24674,7 +24831,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
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. */ \
@@ -24709,7 +24866,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
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); \
@@ -24861,6 +25018,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
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;
@@ -24926,13 +25084,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
else
overlap_hl = DRAW_NORMAL_TEXT;
+ if (hl != overlap_hl)
+ clip_head = head;
j = i;
BUILD_GLYPH_STRINGS (j, start, h, t,
overlap_hl, dummy_x, last_x);
start = i;
compute_overhangs_and_x (t, head->x, 1);
prepend_glyph_string_lists (&head, &tail, h, t);
- clip_head = head;
+ if (clip_head == NULL)
+ clip_head = head;
}
/* Prepend glyph strings for glyphs in front of the first glyph
@@ -24953,7 +25114,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
else
overlap_hl = DRAW_NORMAL_TEXT;
- clip_head = head;
+ if (hl == overlap_hl || clip_head == NULL)
+ clip_head = head;
BUILD_GLYPH_STRINGS (i, start, h, t,
overlap_hl, dummy_x, last_x);
for (s = h; s; s = s->next)
@@ -24977,13 +25139,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
else
overlap_hl = DRAW_NORMAL_TEXT;
+ if (hl != overlap_hl)
+ clip_tail = tail;
BUILD_GLYPH_STRINGS (end, i, h, t,
overlap_hl, x, last_x);
/* Because BUILD_GLYPH_STRINGS updates the first argument,
we don't have `end = i;' here. */
compute_overhangs_and_x (h, tail->x + tail->width, 0);
append_glyph_string_lists (&head, &tail, h, t);
- clip_tail = tail;
+ if (clip_tail == NULL)
+ clip_tail = tail;
}
/* Append glyph strings for glyphs following the last glyph
@@ -25001,7 +25166,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
else
overlap_hl = DRAW_NORMAL_TEXT;
- clip_tail = tail;
+ if (hl == overlap_hl || clip_tail == NULL)
+ clip_tail = tail;
i++; /* We must include the Ith glyph. */
BUILD_GLYPH_STRINGS (end, i, h, t,
overlap_hl, x, last_x);
@@ -25052,6 +25218,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
RELEASE_HDC (hdc, f);
+ SAFE_FREE ();
return x_reached;
}
@@ -25137,8 +25304,7 @@ append_glyph (struct it *it)
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
@@ -25221,8 +25387,7 @@ append_composite_glyph (struct it *it)
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];
@@ -25269,7 +25434,7 @@ produce_image_glyph (struct it *it)
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)
{
@@ -25410,8 +25575,7 @@ produce_image_glyph (struct it *it)
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];
@@ -25499,8 +25663,7 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
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
@@ -25565,7 +25728,7 @@ produce_stretch_glyph (struct it *it)
{
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
@@ -25959,8 +26122,7 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len,
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];
@@ -26028,7 +26190,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
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)
{
@@ -26044,7 +26206,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object 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,
@@ -27369,9 +27531,6 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
/* Erase the image of a cursor of window W from the screen. */
-#ifndef HAVE_NTGUI
-static
-#endif
void
erase_phys_cursor (struct window *w)
{
@@ -27451,7 +27610,7 @@ erase_phys_cursor (struct window *w)
/* Maybe clear the display under the cursor. */
if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
{
- int x, y, left_x;
+ int x, y;
int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
int width;
@@ -27460,13 +27619,15 @@ erase_phys_cursor (struct window *w)
goto mark_cursor_off;
width = cursor_glyph->pixel_width;
- left_x = window_box_left_offset (w, TEXT_AREA);
x = w->phys_cursor.x;
- if (x < left_x)
- width -= left_x - x;
+ if (x < 0)
+ {
+ width += x;
+ x = 0;
+ }
width = min (width, window_box_width (w, TEXT_AREA) - x);
y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
- x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, max (x, left_x));
+ x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
if (width > 0)
FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
@@ -28901,8 +29062,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
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))
{
@@ -29196,7 +29357,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
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;
@@ -29319,6 +29481,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
/* 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. */
@@ -29600,6 +29764,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
BEGV = obegv;
ZV = ozv;
current_buffer = obuf;
+ SAFE_FREE ();
}
set_cursor:
@@ -30117,8 +30282,8 @@ expose_frame (struct frame *f, int x, int y, int w, int h)
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
{
@@ -30373,6 +30538,7 @@ syms_of_xdisp (void)
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,
@@ -30404,8 +30570,9 @@ A value of nil means no special handling of these characters. */);
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,
@@ -30778,6 +30945,12 @@ To add a prefix to continuation lines, use `wrap-prefix'. */);
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. */);
@@ -30900,10 +31073,10 @@ init_xdisp (void)
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);
@@ -30936,7 +31109,38 @@ init_xdisp (void)
/* 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)
{
@@ -30955,20 +31159,13 @@ 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)
{
@@ -30979,7 +31176,28 @@ 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 */