summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2011-11-28 10:07:01 +0900
committerYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2011-11-28 10:07:01 +0900
commit1305621bc212d922c5ef8ee89d73ce7aae496b71 (patch)
treec9934aa7e6d362e335934dac0bafab729b6b0ded
parent8c9afb46949ddd9853f38eb8c1a865cb13522d92 (diff)
downloademacs-1305621bc212d922c5ef8ee89d73ce7aae496b71.tar.gz
Truncate scroll runs that copy to where we copied to.
* dispnew.c (scrolling_window): Truncate overlaps in copy destination of scroll runs so as to avoid assigning disabled bogus rows and unnecessary graphics copy operations.
-rw-r--r--src/ChangeLog6
-rw-r--r--src/dispnew.c74
2 files changed, 72 insertions, 8 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index a2d84d901b5..83b625d279e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
+2011-11-28 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
+
+ * dispnew.c (scrolling_window): Truncate overlaps in copy destination
+ of scroll runs so as to avoid assigning disabled bogus rows and
+ unnecessary graphics copy operations.
+
2011-11-27 Eli Zaretskii <eliz@gnu.org>
* s/ms-w32.h (utimbuf) [_MSC_VER]: Don't define.
diff --git a/src/dispnew.c b/src/dispnew.c
index 385ad98e21f..c9e4ec5c20e 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -4554,18 +4554,69 @@ scrolling_window (struct window *w, int header_line_p)
{
rif->clear_window_mouse_face (w);
rif->scroll_run_hook (w, r);
+ }
+
+ /* Truncate runs that copy to where we copied to, and
+ invalidate runs that copy from where we copied to. */
+ for (j = nruns - 1; j > i; --j)
+ {
+ struct run *p = runs[j];
+ int truncated_p = 0;
- /* Invalidate runs that copy from where we copied to. */
- for (j = i + 1; j < nruns; ++j)
+ if (p->nrows > 0
+ && p->desired_y < r->desired_y + r->height
+ && p->desired_y + p->height > r->desired_y)
{
- struct run *p = runs[j];
+ if (p->desired_y < r->desired_y)
+ {
+ p->nrows = r->desired_vpos - p->desired_vpos;
+ p->height = r->desired_y - p->desired_y;
+ truncated_p = 1;
+ }
+ else
+ {
+ int nrows_copied = (r->desired_vpos + r->nrows
+ - p->desired_vpos);
+
+ if (p->nrows <= nrows_copied)
+ p->nrows = 0;
+ else
+ {
+ int height_copied = (r->desired_y + r->height
+ - p->desired_y);
+
+ p->current_vpos += nrows_copied;
+ p->desired_vpos += nrows_copied;
+ p->nrows -= nrows_copied;
+ p->current_y += height_copied;
+ p->desired_y += height_copied;
+ p->height -= height_copied;
+ truncated_p = 1;
+ }
+ }
+ }
- if ((p->current_y >= r->desired_y
+ if (r->current_y != r->desired_y
+ /* The condition below is equivalent to
+ ((p->current_y >= r->desired_y
&& p->current_y < r->desired_y + r->height)
- || (p->current_y + p->height >= r->desired_y
+ || (p->current_y + p->height > r->desired_y
&& (p->current_y + p->height
- < r->desired_y + r->height)))
- p->nrows = 0;
+ <= r->desired_y + r->height)))
+ because we have 0 < p->height <= r->height. */
+ && p->current_y < r->desired_y + r->height
+ && p->current_y + p->height > r->desired_y)
+ p->nrows = 0;
+
+ /* Reorder runs by copied pixel lines if truncated. */
+ if (truncated_p && p->nrows > 0)
+ {
+ int k = nruns - 1;
+
+ while (runs[k]->nrows == 0 || runs[k]->height < p->height)
+ k--;
+ memmove (runs + j, runs + j + 1, (k - j) * sizeof (*runs));
+ runs[k] = p;
}
}
@@ -4580,7 +4631,14 @@ scrolling_window (struct window *w, int header_line_p)
to_overlapped_p = to->overlapped_p;
from->redraw_fringe_bitmaps_p = from->fringe_bitmap_periodic_p;
assign_row (to, from);
- to->enabled_p = 1, from->enabled_p = 0;
+ /* The above `assign_row' actually does swap, so if we had
+ an overlap in the copy destination of two runs, then
+ the second run would assign a previously disabled bogus
+ row. But thanks to the truncation code in the
+ preceding for-loop, we no longer have such an overlap,
+ and thus the assigned row should always be enabled. */
+ xassert (to->enabled_p);
+ from->enabled_p = 0;
to->overlapped_p = to_overlapped_p;
}
}