1 /****************************************************************************
2 * Copyright (c) 1998 Free Software Foundation, Inc. *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
27 ****************************************************************************/
29 /****************************************************************************
30 * Author: Thomas E. Dickey <dickey@clark.net> 1997 *
31 ****************************************************************************/
32 #include <curses.priv.h>
35 MODULE_ID("$Id: softscroll.c,v 1.6 1998/02/11 12:13:56 tom Exp $")
38 * Compute indices for the given WINDOW, preparing it for scrolling.
40 * TODO (this implementation is only for proof-of-concept)
41 * (a) ensure that curscr's oldindex values are cached properly so we
42 * don't have to recompute them on each pass.
43 * (b) investigate if there are gains to be made by iterating newscr's
44 * row indices outward from the current position, rather than by
47 static void compute_curscr(void)
50 for (y = 0; y < screen_lines; y++) {
51 struct ldat *nline = &curscr->_line[y];
53 for (z = 0; z < y; z++) {
55 struct ldat *oline = &curscr->_line[z];
56 for (x = 0; x < screen_columns; x++) {
57 if (nline->text[x] != oline->text[x]) {
67 nline->oldindex = found;
71 static void compute_newscr(void)
74 for (y = 0; y < screen_lines; y++) {
75 struct ldat *nline = &newscr->_line[y];
76 int found = _NEWINDEX;
77 for (z = 0; z < screen_lines; z++) {
79 struct ldat *oline = &curscr->_line[z];
80 for (x = 0; x < screen_columns; x++) {
81 if (nline->text[x] != oline->text[x]) {
91 nline->oldindex = found;
96 _nc_setup_scroll(void)
99 if (_nc_tracing & TRACE_UPDATE) {
100 _tracef("_nc_setup_scroll");
107 if (_nc_tracing & TRACE_UPDATE) {
108 _tracef("..._nc_setup_scroll");
115 #define NEWNUM(n) newscr->_line[n].oldindex
116 #define OLDNUM(n) curscr->_line[n].oldindex
119 * This performs essentially the same function as _nc_scroll_optimize(), but
120 * uses different assumptions about the .oldindex values. More than one line
121 * may have the same .oldindex value. We don't assume the values are ordered.
123 * (Neither algorithm takes into account the cost of constructing the lines
124 * which are scrolled)
127 _nc_perform_scroll(void)
131 int top, bottom, maxdisp;
135 * Find the top/bottom lines that are different between curscr and
136 * newscr, limited by the terminal's ability to scroll portions of the
139 * FIXME: this doesn't account for special cases of insert/delete line.
141 if (change_scroll_region
142 && (scroll_forward || parm_index)
143 && (scroll_reverse || parm_rindex)) {
145 for (row = 0, top = -1; row < screen_lines; row++) {
146 if (OLDNUM(row) != NEWNUM(row)) {
153 for (row = screen_lines-1, bottom = screen_lines; row >= 0; row--) {
154 if (OLDNUM(row) != NEWNUM(row)) {
163 bottom = screen_lines - 1;
166 maxdisp = (bottom - top + 1) / 2;
167 if (maxdisp < MINDISP)
170 T(("_nc_perform_scroll %d..%d (maxdisp=%d)", top, bottom, maxdisp));
172 for (disp = 1; disp < maxdisp; disp++) {
180 /* check for forward-movement */
181 for (fn = top + disp; fn < screen_lines - disp; fn++) {
183 for (n = fn, fwd = 0; n < screen_lines; n++) {
184 if (NEWNUM(n) == _NEWINDEX
185 || NEWNUM(n) != OLDNUM(n-disp))
188 if (OLDNUM(n) == NEWNUM(n))
198 /* check for backward-movement */
199 for (bn = top + disp; bn < screen_lines - disp; bn++) {
201 for (n = bn, bak = 0; n < screen_lines; n++) {
202 if (OLDNUM(n) == _NEWINDEX
203 || OLDNUM(n) != NEWNUM(n-disp))
206 if (OLDNUM(n-disp) == NEWNUM(n-disp))
216 /* choose only one, in case they overlap */
229 TR(TRACE_UPDATE | TRACE_MOVE, ("scroll [%d, %d] by %d", first, last, moved));
230 if (_nc_scrolln(moved, first, last, screen_lines - 1) == ERR)
232 TR(TRACE_UPDATE | TRACE_MOVE, ("unable to scroll"));
236 /* If the scrolled text was at one end of the range
237 * of changed lines, adjust the loop limits.
244 maxdisp = (bottom - top + 1) / 2;
245 if (maxdisp < MINDISP)
248 /* In any case, mark the lines so we don't try to
249 * use them in a subsequent scroll.
251 for (fn = first; fn <= last; fn++) {
253 NEWNUM(fn) = _NEWINDEX;