summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2011-07-03 21:36:56 +0300
committerEli Zaretskii <eliz@gnu.org>2011-07-03 21:36:56 +0300
commited94e6d7bf6751592ff3dadb2b87f03ffaab3bfa (patch)
tree0d06ed1743bb484cac818ef7ff75d68f107a6332 /src
parent6eec759623c7d77e01370c504543a29887c28034 (diff)
Save and restore bidi cache when saving and restoring the iterator.
Not tested, just compiled. src/bidi.c (bidi_shelve_cache, bidi_unshelve_cache): New functions. src/dispextern.h (bidi_shelve_cache, bidi_unshelve_cache): Declare prototypes. src/xdisp.c (SAVE_IT, RESTORE_IT): New macros. (pos_visible_p, face_before_or_after_it_pos) (back_to_previous_visible_line_start) (move_it_in_display_line_to, move_it_in_display_line) (move_it_to, move_it_vertically_backward, move_it_by_lines) (try_scrolling, redisplay_window, display_line): Use them when saving a temporary copy of the iterator and restoring it back.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog15
-rw-r--r--src/bidi.c80
-rw-r--r--src/dispextern.h2
-rw-r--r--src/xdisp.c152
4 files changed, 204 insertions, 45 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 1a443e848a..fdb6657e13 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,18 @@
+2011-07-03 Eli Zaretskii <eliz@gnu.org>
+
+ * bidi.c (bidi_shelve_cache, bidi_unshelve_cache): New functions.
+
+ * dispextern.h (bidi_shelve_cache, bidi_unshelve_cache): Declare
+ prototypes.
+
+ * xdisp.c (SAVE_IT, RESTORE_IT): New macros.
+ (pos_visible_p, face_before_or_after_it_pos)
+ (back_to_previous_visible_line_start)
+ (move_it_in_display_line_to, move_it_in_display_line)
+ (move_it_to, move_it_vertically_backward, move_it_by_lines)
+ (try_scrolling, redisplay_window, display_line): Use them when
+ saving a temporary copy of the iterator and restoring it back.
+
2011-07-02 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (reseat_1): Call bidi_init_it to resync the bidi
diff --git a/src/bidi.c b/src/bidi.c
index 05c16a70f9..be34f0352d 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -603,6 +603,86 @@ bidi_pop_it (struct bidi_it *bidi_it)
bidi_cache_last_idx = -1;
}
+/* Stash away a copy of the cache and its control variables. */
+void *
+bidi_shelve_cache (void)
+{
+ unsigned char *databuf;
+
+ if (bidi_cache_idx == 0)
+ return NULL;
+
+ databuf = xmalloc (sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack)
+ + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start)
+ + sizeof (bidi_cache_last_idx));
+ memcpy (databuf, &bidi_cache_idx, sizeof (bidi_cache_idx));
+ memcpy (databuf + sizeof (bidi_cache_idx),
+ bidi_cache, bidi_cache_idx * sizeof (struct bidi_it));
+ memcpy (databuf + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it),
+ bidi_cache_start_stack, sizeof (bidi_cache_start_stack));
+ memcpy (databuf + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack),
+ &bidi_cache_sp, sizeof (bidi_cache_sp));
+ memcpy (databuf + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp),
+ &bidi_cache_start, sizeof (bidi_cache_start));
+ memcpy (databuf + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+ + sizeof (bidi_cache_start),
+ &bidi_cache_last_idx, sizeof (bidi_cache_last_idx));
+
+ return databuf;
+}
+
+/* Restore the cache state from a copy stashed away by bidi_shelve_cache. */
+void
+bidi_unshelve_cache (void *databuf)
+{
+ unsigned char *p = databuf;
+
+ if (!p)
+ {
+ /* A NULL pointer means an empty cache. */
+ bidi_cache_start = 0;
+ bidi_cache_sp = 0;
+ bidi_cache_reset ();
+ }
+ else
+ {
+ memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx));
+ memcpy (bidi_cache, p + sizeof (bidi_cache_idx),
+ bidi_cache_idx * sizeof (struct bidi_it));
+ memcpy (bidi_cache_start_stack,
+ p + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it),
+ sizeof (bidi_cache_start_stack));
+ memcpy (&bidi_cache_sp,
+ p + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack),
+ sizeof (bidi_cache_sp));
+ memcpy (&bidi_cache_start,
+ p + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp),
+ sizeof (bidi_cache_start));
+ memcpy (&bidi_cache_last_idx,
+ p + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+ + sizeof (bidi_cache_start),
+ sizeof (bidi_cache_last_idx));
+
+ xfree (p);
+ }
+}
+
/***********************************************************************
Initialization
diff --git a/src/dispextern.h b/src/dispextern.h
index 997ef6df08..5bb72ff760 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2974,6 +2974,8 @@ extern void bidi_paragraph_init (bidi_dir_t, struct bidi_it *, int);
extern int bidi_mirror_char (int);
extern void bidi_push_it (struct bidi_it *);
extern void bidi_pop_it (struct bidi_it *);
+extern void *bidi_shelve_cache (void);
+extern void bidi_unshelve_cache (void *);
/* Defined in xdisp.c */
diff --git a/src/xdisp.c b/src/xdisp.c
index c3d5fd9479..c1f4d44dbc 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -594,6 +594,29 @@ int current_mode_line_height, current_header_line_height;
#define TEXT_PROP_DISTANCE_LIMIT 100
+/* SAVE_IT and RESTORE_IT are called when we save a snapshot of the
+ iterator state and later restore it. This is needed because the
+ bidi iterator on bidi.c keeps a stacked cache of its states, which
+ is really a singleton. When we use scratch iterator objects to
+ move around the buffer, we can cause the bidi cache to be pushed or
+ popped, and therefore we need to restore the cache state when we
+ return to the original iterator. */
+#define SAVE_IT(ITCOPY,ITORIG,CACHE) \
+ do { \
+ if (CACHE) \
+ xfree (CACHE); \
+ ITCOPY = ITORIG; \
+ CACHE = bidi_shelve_cache(); \
+ } while (0)
+
+#define RESTORE_IT(pITORIG,pITCOPY,CACHE) \
+ do { \
+ if (pITORIG != pITCOPY) \
+ *(pITORIG) = *(pITCOPY); \
+ bidi_unshelve_cache (CACHE); \
+ CACHE = NULL; \
+ } while (0)
+
#if GLYPH_DEBUG
/* Non-zero means print traces of redisplay if compiled with
@@ -1285,14 +1308,16 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
else
{
struct it it2;
+ void *it2data = NULL;
- it2 = it;
+ SAVE_IT (it2, it, it2data);
if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
move_it_by_lines (&it, 1);
if (charpos < IT_CHARPOS (it)
|| (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
{
visible_p = 1;
+ RESTORE_IT (&it2, &it2, it2data);
move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
*x = it2.current_x;
*y = it2.current_y + it2.max_ascent - it2.ascent;
@@ -1305,6 +1330,8 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
WINDOW_HEADER_LINE_HEIGHT (w))));
*vpos = it2.vpos;
}
+ else
+ xfree (it2data);
}
if (old_buffer)
@@ -3484,6 +3511,7 @@ face_before_or_after_it_pos (struct it *it, int before_p)
int face_id, limit;
EMACS_INT next_check_charpos;
struct it it_copy;
+ void *it_copy_data = NULL;
xassert (it->s == NULL);
@@ -3526,7 +3554,7 @@ face_before_or_after_it_pos (struct it *it, int before_p)
character on this display line. */
if (it->current_x <= it->first_visible_x)
return it->face_id;
- it_copy = *it;
+ SAVE_IT (it_copy, *it, it_copy_data);
/* Implementation note: Since move_it_in_display_line
works in the iterator geometry, and thinks the first
character is always the leftmost, even in R2L lines,
@@ -3535,6 +3563,7 @@ face_before_or_after_it_pos (struct it *it, int before_p)
move_it_in_display_line (&it_copy, SCHARS (it_copy.string),
it_copy.current_x - 1, MOVE_TO_X);
charpos = IT_STRING_CHARPOS (it_copy);
+ RESTORE_IT (it, it, it_copy_data);
}
else
{
@@ -3624,7 +3653,7 @@ face_before_or_after_it_pos (struct it *it, int before_p)
character on this display line. */
if (it->current_x <= it->first_visible_x)
return it->face_id;
- it_copy = *it;
+ SAVE_IT (it_copy, *it, it_copy_data);
/* Implementation note: Since move_it_in_display_line
works in the iterator geometry, and thinks the first
character is always the leftmost, even in R2L lines,
@@ -3633,6 +3662,7 @@ face_before_or_after_it_pos (struct it *it, int before_p)
move_it_in_display_line (&it_copy, ZV,
it_copy.current_x - 1, MOVE_TO_X);
pos = it_copy.current.pos;
+ RESTORE_IT (it, it, it_copy_data);
}
else
{
@@ -5527,6 +5557,7 @@ back_to_previous_visible_line_start (struct it *it)
{
struct it it2;
+ void *it2data = NULL;
EMACS_INT pos;
EMACS_INT beg, end;
Lisp_Object val, overlay;
@@ -5538,7 +5569,7 @@ back_to_previous_visible_line_start (struct it *it)
/* If newline is replaced by a display property, find start of overlay
or interval and continue search from that point. */
- it2 = *it;
+ SAVE_IT (it2, *it, it2data);
pos = --IT_CHARPOS (it2);
--IT_BYTEPOS (it2);
it2.sp = 0;
@@ -5551,21 +5582,12 @@ back_to_previous_visible_line_start (struct it *it)
? (beg = OVERLAY_POSITION (OVERLAY_START (overlay)))
: get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
{
- /* If the call to handle_display_prop above pushed the
- iterator state, that causes side effects for the bidi
- iterator by calling bidi_push_it. Undo those side
- effects. */
- while (it2.sp > 0)
- {
- /* push_it calls bidi_push_it only if the bidi_p flag
- is set in the iterator being pushed. */
- if (it2.stack[--it2.sp].bidi_p)
- bidi_pop_it (&it2.bidi_it);
- }
+ RESTORE_IT (it, it, it2data);
goto replaced;
}
/* Newline is not replaced by anything -- so we are done. */
+ RESTORE_IT (it, it, it2data);
break;
replaced:
@@ -7495,6 +7517,7 @@ move_it_in_display_line_to (struct it *it,
enum move_it_result result = MOVE_UNDEFINED;
struct glyph_row *saved_glyph_row;
struct it wrap_it, atpos_it, atx_it;
+ void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
int may_wrap = 0;
enum it_method prev_method = it->method;
EMACS_INT prev_pos = IT_CHARPOS (*it);
@@ -7563,7 +7586,7 @@ move_it_in_display_line_to (struct it *it,
/* If wrap_it is valid, the current position might be in a
word that is wrapped. So, save the iterator in
atpos_it and continue to see if wrapping happens. */
- atpos_it = *it;
+ SAVE_IT (atpos_it, *it, atpos_data);
}
prev_method = it->method;
@@ -7600,18 +7623,18 @@ move_it_in_display_line_to (struct it *it,
already found, we are done. */
if (atpos_it.sp >= 0)
{
- *it = atpos_it;
+ RESTORE_IT (it, &atpos_it, atpos_data);
result = MOVE_POS_MATCH_OR_ZV;
goto done;
}
if (atx_it.sp >= 0)
{
- *it = atx_it;
+ RESTORE_IT (it, &atx_it, atx_data);
result = MOVE_X_REACHED;
goto done;
}
/* Otherwise, we can wrap here. */
- wrap_it = *it;
+ SAVE_IT (wrap_it, *it, wrap_data);
may_wrap = 0;
}
}
@@ -7679,7 +7702,7 @@ move_it_in_display_line_to (struct it *it,
goto buffer_pos_reached;
if (atpos_it.sp < 0)
{
- atpos_it = *it;
+ SAVE_IT (atpos_it, *it, atpos_data);
IT_RESET_X_ASCENT_DESCENT (&atpos_it);
}
}
@@ -7693,7 +7716,7 @@ move_it_in_display_line_to (struct it *it,
}
if (atx_it.sp < 0)
{
- atx_it = *it;
+ SAVE_IT (atx_it, *it, atx_data);
IT_RESET_X_ASCENT_DESCENT (&atx_it);
}
}
@@ -7737,7 +7760,7 @@ move_it_in_display_line_to (struct it *it,
if (it->line_wrap == WORD_WRAP
&& atpos_it.sp < 0)
{
- atpos_it = *it;
+ SAVE_IT (atpos_it, *it, atpos_data);
atpos_it.current_x = x_before_this_char;
atpos_it.hpos = hpos_before_this_char;
}
@@ -7782,7 +7805,7 @@ move_it_in_display_line_to (struct it *it,
if (wrap_it.sp >= 0)
{
- *it = wrap_it;
+ RESTORE_IT (it, &wrap_it, wrap_data);
atpos_it.sp = -1;
atx_it.sp = -1;
}
@@ -7799,7 +7822,7 @@ move_it_in_display_line_to (struct it *it,
goto buffer_pos_reached;
if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
{
- atpos_it = *it;
+ SAVE_IT (atpos_it, *it, atpos_data);
IT_RESET_X_ASCENT_DESCENT (&atpos_it);
}
}
@@ -7879,12 +7902,19 @@ move_it_in_display_line_to (struct it *it,
/* If we scanned beyond to_pos and didn't find a point to wrap at,
restore the saved iterator. */
if (atpos_it.sp >= 0)
- *it = atpos_it;
+ RESTORE_IT (it, &atpos_it, atpos_data);
else if (atx_it.sp >= 0)
- *it = atx_it;
+ RESTORE_IT (it, &atx_it, atx_data);
done:
+ if (atpos_data)
+ xfree (atpos_data);
+ if (atx_data)
+ xfree (atx_data);
+ if (wrap_data)
+ xfree (wrap_data);
+
/* Restore the iterator settings altered at the beginning of this
function. */
it->glyph_row = saved_glyph_row;
@@ -7900,8 +7930,12 @@ move_it_in_display_line (struct it *it,
if (it->line_wrap == WORD_WRAP
&& (op & MOVE_TO_X))
{
- struct it save_it = *it;
- int skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
+ struct it save_it;
+ void *save_data = NULL;
+ int skip;
+
+ SAVE_IT (save_it, *it, save_data);
+ skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
/* When word-wrap is on, TO_X may lie past the end
of a wrapped line. Then it->current is the
character on the next line, so backtrack to the
@@ -7909,10 +7943,12 @@ move_it_in_display_line (struct it *it,
if (skip == MOVE_LINE_CONTINUED)
{
int prev_x = max (it->current_x - 1, 0);
- *it = save_it;
+ RESTORE_IT (it, &save_it, save_data);
move_it_in_display_line_to
(it, -1, prev_x, MOVE_TO_X);
}
+ else
+ xfree (save_data);
}
else
move_it_in_display_line_to (it, to_charpos, to_x, op);
@@ -7935,6 +7971,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos
{
enum move_it_result skip, skip2 = MOVE_X_REACHED;
int line_height, line_start_x = 0, reached = 0;
+ void *backup_data = NULL;
for (;;)
{
@@ -7987,7 +8024,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos
struct it it_backup;
if (it->line_wrap == WORD_WRAP)
- it_backup = *it;
+ SAVE_IT (it_backup, *it, backup_data);
/* TO_Y specified means stop at TO_X in the line containing
TO_Y---or at TO_CHARPOS if this is reached first. The
@@ -8021,7 +8058,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos
reached = 6;
break;
}
- it_backup = *it;
+ SAVE_IT (it_backup, *it, backup_data);
TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
skip2 = move_it_in_display_line_to (it, to_charpos, -1,
op & MOVE_TO_POS);
@@ -8035,7 +8072,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos
/* If TO_Y is in this line and TO_X was reached
above, we scanned too far. We have to restore
IT's settings to the ones before skipping. */
- *it = it_backup;
+ RESTORE_IT (it, &it_backup, backup_data);
reached = 6;
}
else
@@ -8062,7 +8099,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos
&& it->line_wrap == WORD_WRAP)
{
int prev_x = max (it->current_x - 1, 0);
- *it = it_backup;
+ RESTORE_IT (it, &it_backup, backup_data);
skip = move_it_in_display_line_to
(it, -1, prev_x, MOVE_TO_X);
}
@@ -8169,6 +8206,9 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos
last_max_ascent = it->max_ascent;
}
+ if (backup_data)
+ xfree (backup_data);
+
TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
}
@@ -8186,6 +8226,7 @@ move_it_vertically_backward (struct it *it, int dy)
{
int nlines, h;
struct it it2, it3;
+ void *it2data = NULL, *it3data = NULL;
EMACS_INT start_pos;
move_further_back:
@@ -8214,7 +8255,7 @@ move_it_vertically_backward (struct it *it, int dy)
start of the next line so that we get its height. We need this
height to be able to tell whether we reached the specified
y-distance. */
- it2 = *it;
+ SAVE_IT (it2, *it, it2data);
it2.max_ascent = it2.max_descent = 0;
do
{
@@ -8223,7 +8264,7 @@ move_it_vertically_backward (struct it *it, int dy)
}
while (!IT_POS_VALID_AFTER_MOVE_P (&it2));
xassert (IT_CHARPOS (*it) >= BEGV);
- it3 = it2;
+ SAVE_IT (it3, it2, it3data);
move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
xassert (IT_CHARPOS (*it) >= BEGV);
@@ -8242,8 +8283,10 @@ move_it_vertically_backward (struct it *it, int dy)
{
/* DY == 0 means move to the start of the screen line. The
value of nlines is > 0 if continuation lines were involved. */
+ RESTORE_IT (it, it, it2data);
if (nlines > 0)
move_it_by_lines (it, nlines);
+ xfree (it3data);
}
else
{
@@ -8251,9 +8294,13 @@ move_it_vertically_backward (struct it *it, int dy)
Note that H has been subtracted in front of the if-statement. */
int target_y = it->current_y + h - dy;
int y0 = it3.current_y;
- int y1 = line_bottom_y (&it3);
- int line_height = y1 - y0;
+ int y1;
+ int line_height;
+ RESTORE_IT (&it3, &it3, it3data);
+ y1 = line_bottom_y (&it3);
+ line_height = y1 - y0;
+ RESTORE_IT (it, it, it2data);
/* If we did not reach target_y, try to move further backward if
we can. If we moved too far backward, try to move forward. */
if (target_y < it->current_y
@@ -8380,6 +8427,7 @@ move_it_by_lines (struct it *it, int dvpos)
else
{
struct it it2;
+ void *it2data = NULL;
EMACS_INT start_charpos, i;
/* Start at the beginning of the screen line containing IT's
@@ -8415,7 +8463,7 @@ move_it_by_lines (struct it *it, int dvpos)
/* Above call may have moved too far if continuation lines
are involved. Scan forward and see if it did. */
- it2 = *it;
+ SAVE_IT (it2, *it, it2data);
it2.vpos = it2.current_y = 0;
move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
it->vpos -= it2.vpos;
@@ -8426,12 +8474,18 @@ move_it_by_lines (struct it *it, int dvpos)
if (it2.vpos > -dvpos)
{
int delta = it2.vpos + dvpos;
- it2 = *it;
+
+ RESTORE_IT (&it2, &it2, it2data);
+ SAVE_IT (it2, *it, it2data);
move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
/* Move back again if we got too far ahead. */
if (IT_CHARPOS (*it) >= start_charpos)
- *it = it2;
+ RESTORE_IT (it, &it2, it2data);
+ else
+ xfree (it2data);
}
+ else
+ RESTORE_IT (it, it, it2data);
}
}
@@ -13776,14 +13830,18 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
which was computed as distance from window bottom to
point. This matters when lines at window top and lines
below window bottom have different height. */
- struct it it1 = it;
+ struct it it1;
+ void *it1data = NULL;
/* We use a temporary it1 because line_bottom_y can modify
its argument, if it moves one line down; see there. */
- int start_y = line_bottom_y (&it1);
+ int start_y;
+ SAVE_IT (it1, it, it1data);
+ start_y = line_bottom_y (&it1);
do {
+ RESTORE_IT (&it, &it, it1data);
move_it_by_lines (&it, 1);
- it1 = it;
+ SAVE_IT (it1, it, it1data);
} while (line_bottom_y (&it1) - start_y < amount_to_scroll);
}
@@ -14891,10 +14949,13 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
&& BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
{
struct it it1;
+ void *it1data = NULL;
+ SAVE_IT (it1, it, it1data);
start_display (&it1, w, startp);
move_it_vertically (&it1, margin);
margin_pos = IT_CHARPOS (it1);
+ RESTORE_IT (&it, &it, it1data);
}
scrolling_up = PT > margin_pos;
aggressive =
@@ -17991,6 +18052,7 @@ display_line (struct it *it)
struct glyph_row *row = it->glyph_row;
Lisp_Object overlay_arrow_string;
struct it wrap_it;
+ void *wrap_data = NULL;
int may_wrap = 0, wrap_x IF_LINT (= 0);
int wrap_row_used = -1;
int wrap_row_ascent IF_LINT (= 0), wrap_row_height IF_LINT (= 0);
@@ -18145,7 +18207,7 @@ display_line (struct it *it)
may_wrap = 1;
else if (may_wrap)
{
- wrap_it = *it;
+ SAVE_IT (wrap_it, *it, wrap_data);
wrap_x = x;
wrap_row_used = row->used[TEXT_AREA];
wrap_row_ascent = row->ascent;
@@ -18315,7 +18377,7 @@ display_line (struct it *it)
if (row->reversed_p)
unproduce_glyphs (it,
row->used[TEXT_AREA] - wrap_row_used);
- *it = wrap_it;
+ RESTORE_IT (it, &wrap_it, wrap_data);
it->continuation_lines_width += wrap_x;
row->used[TEXT_AREA] = wrap_row_used;
row->ascent = wrap_row_ascent;