xref: /freebsd-src/contrib/ncurses/ncurses/tty/hardscroll.c (revision 21817992b3314c908ab50f0bb88d2ee750b9c4ac)
10e3d5408SPeter Wemm /****************************************************************************
2*21817992SBaptiste Daroussin  * Copyright 2020,2023 Thomas E. Dickey                                     *
3e1865124SBaptiste Daroussin  * Copyright 1998-2015,2016 Free Software Foundation, Inc.                  *
40e3d5408SPeter Wemm  *                                                                          *
50e3d5408SPeter Wemm  * Permission is hereby granted, free of charge, to any person obtaining a  *
60e3d5408SPeter Wemm  * copy of this software and associated documentation files (the            *
70e3d5408SPeter Wemm  * "Software"), to deal in the Software without restriction, including      *
80e3d5408SPeter Wemm  * without limitation the rights to use, copy, modify, merge, publish,      *
90e3d5408SPeter Wemm  * distribute, distribute with modifications, sublicense, and/or sell       *
100e3d5408SPeter Wemm  * copies of the Software, and to permit persons to whom the Software is    *
110e3d5408SPeter Wemm  * furnished to do so, subject to the following conditions:                 *
120e3d5408SPeter Wemm  *                                                                          *
130e3d5408SPeter Wemm  * The above copyright notice and this permission notice shall be included  *
140e3d5408SPeter Wemm  * in all copies or substantial portions of the Software.                   *
150e3d5408SPeter Wemm  *                                                                          *
160e3d5408SPeter Wemm  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
170e3d5408SPeter Wemm  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
180e3d5408SPeter Wemm  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
190e3d5408SPeter Wemm  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
200e3d5408SPeter Wemm  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
210e3d5408SPeter Wemm  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
220e3d5408SPeter Wemm  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
230e3d5408SPeter Wemm  *                                                                          *
240e3d5408SPeter Wemm  * Except as contained in this notice, the name(s) of the above copyright   *
250e3d5408SPeter Wemm  * holders shall not be used in advertising or otherwise to promote the     *
260e3d5408SPeter Wemm  * sale, use or other dealings in this Software without prior written       *
270e3d5408SPeter Wemm  * authorization.                                                           *
280e3d5408SPeter Wemm  ****************************************************************************/
290e3d5408SPeter Wemm 
300e3d5408SPeter Wemm /****************************************************************************
310e3d5408SPeter Wemm  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
320e3d5408SPeter Wemm  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
335d08fb1fSRong-En Fan  *     and: Thomas E. Dickey                        1996-on                 *
345d08fb1fSRong-En Fan  *     and: Alexander V Lukyanov                    1997-1998               *
350e3d5408SPeter Wemm  ****************************************************************************/
360e3d5408SPeter Wemm 
370e3d5408SPeter Wemm /******************************************************************************
380e3d5408SPeter Wemm 
390e3d5408SPeter Wemm NAME
400e3d5408SPeter Wemm    hardscroll.c -- hardware-scrolling optimization for ncurses
410e3d5408SPeter Wemm 
420e3d5408SPeter Wemm SYNOPSIS
430e3d5408SPeter Wemm    void _nc_scroll_optimize(void)
440e3d5408SPeter Wemm 
450e3d5408SPeter Wemm DESCRIPTION
460e3d5408SPeter Wemm 			OVERVIEW
470e3d5408SPeter Wemm 
480e3d5408SPeter Wemm This algorithm for computes optimum hardware scrolling to transform an
490e3d5408SPeter Wemm old screen (curscr) into a new screen (newscr) via vertical line moves.
500e3d5408SPeter Wemm 
510e3d5408SPeter Wemm Because the screen has a `grain' (there are insert/delete/scroll line
520e3d5408SPeter Wemm operations but no insert/delete/scroll column operations), it is efficient
530e3d5408SPeter Wemm break the update algorithm into two pieces: a first stage that does only line
540e3d5408SPeter Wemm moves, optimizing the end product of user-invoked insertions, deletions, and
550e3d5408SPeter Wemm scrolls; and a second phase (corresponding to the present doupdate code in
560e3d5408SPeter Wemm ncurses) that does only line transformations.
570e3d5408SPeter Wemm 
580e3d5408SPeter Wemm The common case we want hardware scrolling for is to handle line insertions
590e3d5408SPeter Wemm and deletions in screen-oriented text-editors.  This two-stage approach will
600e3d5408SPeter Wemm accomplish that at a low computation and code-size cost.
610e3d5408SPeter Wemm 
620e3d5408SPeter Wemm 			LINE-MOVE COMPUTATION
630e3d5408SPeter Wemm 
640e3d5408SPeter Wemm Now, to a discussion of the line-move computation.
650e3d5408SPeter Wemm 
660e3d5408SPeter Wemm For expository purposes, consider the screen lines to be represented by
670e3d5408SPeter Wemm integers 0..23 (with the understanding that the value of 23 may vary).
680e3d5408SPeter Wemm Let a new line introduced by insertion, scrolling, or at the bottom of
690e3d5408SPeter Wemm the screen following a line delete be given the index -1.
700e3d5408SPeter Wemm 
710e3d5408SPeter Wemm Assume that the real screen starts with lines 0..23.  Now, we have
720e3d5408SPeter Wemm the following possible line-oriented operations on the screen:
730e3d5408SPeter Wemm 
740e3d5408SPeter Wemm Insertion: inserts a line at a given screen row, forcing all lines below
750e3d5408SPeter Wemm to scroll forward.  The last screen line is lost.  For example, an insertion
760e3d5408SPeter Wemm at line 5 would produce: 0..4 -1 5..23.
770e3d5408SPeter Wemm 
780e3d5408SPeter Wemm Deletion: deletes a line at a given screen row, forcing all lines below
790e3d5408SPeter Wemm to scroll forward.  The last screen line is made new.  For example, a deletion
800e3d5408SPeter Wemm at line 7 would produce: 0..6 8..23 -1.
810e3d5408SPeter Wemm 
820e3d5408SPeter Wemm Scroll up: move a range of lines up 1.  The bottom line of the range
830e3d5408SPeter Wemm becomes new.  For example, scrolling up the region from 9 to 14 will
840e3d5408SPeter Wemm produce 0..8 10..14 -1 15..23.
850e3d5408SPeter Wemm 
860e3d5408SPeter Wemm Scroll down: move a range of lines down 1.  The top line of the range
870e3d5408SPeter Wemm becomes new.  For example, scrolling down the region from 12 to 16 will produce
880e3d5408SPeter Wemm 0..11 -1 12..15 17..23.
890e3d5408SPeter Wemm 
900e3d5408SPeter Wemm Now, an obvious property of all these operations is that they preserve the
910e3d5408SPeter Wemm order of old lines, though not their position in the sequence.
920e3d5408SPeter Wemm 
930e3d5408SPeter Wemm The key trick of this algorithm is that the original line indices described
940e3d5408SPeter Wemm above are actually maintained as _line[].oldindex fields in the window
950e3d5408SPeter Wemm structure, and stick to each line through scroll and insert/delete operations.
960e3d5408SPeter Wemm 
970e3d5408SPeter Wemm Thus, it is possible at update time to look at the oldnum fields and compute
980e3d5408SPeter Wemm an optimal set of il/dl/scroll operations that will take the real screen
990e3d5408SPeter Wemm lines to the virtual screen lines.  Once these vertical moves have been done,
1000e3d5408SPeter Wemm we can hand off to the second stage of the update algorithm, which does line
1010e3d5408SPeter Wemm transformations.
1020e3d5408SPeter Wemm 
1030e3d5408SPeter Wemm Note that the move computation does not need to have the full generality
1040e3d5408SPeter Wemm of a diff algorithm (which it superficially resembles) because lines cannot
1050e3d5408SPeter Wemm be moved out of order.
1060e3d5408SPeter Wemm 
1070e3d5408SPeter Wemm 			THE ALGORITHM
1080e3d5408SPeter Wemm 
1090e3d5408SPeter Wemm The scrolling is done in two passes. The first pass is from top to bottom
1100e3d5408SPeter Wemm scroling hunks UP. The second one is from bottom to top scrolling hunks DOWN.
1110e3d5408SPeter Wemm Obviously enough, no lines to be scrolled will be destroyed. (lav)
1120e3d5408SPeter Wemm 
1130e3d5408SPeter Wemm HOW TO TEST THIS:
1140e3d5408SPeter Wemm 
1150e3d5408SPeter Wemm Use the following production:
1160e3d5408SPeter Wemm 
1170e3d5408SPeter Wemm hardscroll: hardscroll.c
1180e3d5408SPeter Wemm 	$(CC) -g -DSCROLLDEBUG hardscroll.c -o hardscroll
1190e3d5408SPeter Wemm 
1200e3d5408SPeter Wemm Then just type scramble vectors and watch.  The following test loads are
1210e3d5408SPeter Wemm a representative sample of cases:
1220e3d5408SPeter Wemm 
1230e3d5408SPeter Wemm -----------------------------  CUT HERE ------------------------------------
1240e3d5408SPeter Wemm # No lines moved
1250e3d5408SPeter Wemm  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
1260e3d5408SPeter Wemm #
1270e3d5408SPeter Wemm # A scroll up
1280e3d5408SPeter Wemm  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 -1
1290e3d5408SPeter Wemm #
1300e3d5408SPeter Wemm # A scroll down
1310e3d5408SPeter Wemm -1  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22
1320e3d5408SPeter Wemm #
1330e3d5408SPeter Wemm # An insertion (after line 12)
1340e3d5408SPeter Wemm  0  1  2  3  4  5  6  7  8  9 10 11 12 -1 13 14 15 16 17 18 19 20 21 22
1350e3d5408SPeter Wemm #
1360e3d5408SPeter Wemm # A simple deletion (line 10)
1370e3d5408SPeter Wemm  0  1  2  3  4  5  6  7  8  9  11 12 13 14 15 16 17 18 19 20 21 22 23 -1
1380e3d5408SPeter Wemm #
1390e3d5408SPeter Wemm # A more complex case
1400e3d5408SPeter Wemm -1 -1 -1 -1 -1  3  4  5  6  7  -1 -1  8  9 10 11 12 13 14 15 16 17 -1 -1
1410e3d5408SPeter Wemm -----------------------------  CUT HERE ------------------------------------
1420e3d5408SPeter Wemm 
1430e3d5408SPeter Wemm AUTHOR
1440e3d5408SPeter Wemm     Eric S. Raymond <esr@snark.thyrsus.com>, November 1994
1450e3d5408SPeter Wemm     New algorithm by Alexander V. Lukyanov <lav@yars.free.net>, Aug 1997
1460e3d5408SPeter Wemm 
1470e3d5408SPeter Wemm *****************************************************************************/
1480e3d5408SPeter Wemm 
1490e3d5408SPeter Wemm #include <curses.priv.h>
1500e3d5408SPeter Wemm 
151*21817992SBaptiste Daroussin MODULE_ID("$Id: hardscroll.c,v 1.58 2023/09/09 16:04:08 Nicholas.Marriott Exp $")
1520e3d5408SPeter Wemm 
1530e3d5408SPeter Wemm #if defined(SCROLLDEBUG) || defined(HASHDEBUG)
1540e3d5408SPeter Wemm 
1550e3d5408SPeter Wemm # undef screen_lines
15606bfebdeSXin LI # define screen_lines(sp) MAXLINES
1577a69bbfbSPeter Wemm NCURSES_EXPORT_VAR (int)
1587a69bbfbSPeter Wemm   oldnums[MAXLINES];
15906bfebdeSXin LI # define OLDNUM(sp,n)	oldnums[n]
1600e3d5408SPeter Wemm # define _tracef	printf
1610e3d5408SPeter Wemm # undef TR
1620e3d5408SPeter Wemm # define TR(n, a)	if (_nc_tracing & (n)) { _tracef a ; putchar('\n'); }
1630e3d5408SPeter Wemm 
1645ca44d1cSRong-En Fan extern				NCURSES_EXPORT_VAR(unsigned) _nc_tracing;
1655ca44d1cSRong-En Fan 
1660e3d5408SPeter Wemm #else /* no debug */
1670e3d5408SPeter Wemm 
1680e3d5408SPeter Wemm /* OLDNUM(n) indicates which line will be shifted to the position n.
1690e3d5408SPeter Wemm    if OLDNUM(n) == _NEWINDEX, then the line n in new, not shifted from
1700e3d5408SPeter Wemm    somewhere. */
1717a69bbfbSPeter Wemm NCURSES_EXPORT_VAR (int *)
1725ca44d1cSRong-En Fan   _nc_oldnums = 0;		/* obsolete: keep for ABI compat */
1737a69bbfbSPeter Wemm 
1740e3d5408SPeter Wemm # if USE_HASHMAP
17506bfebdeSXin LI #  define oldnums(sp)   (sp)->_oldnum_list
17606bfebdeSXin LI #  define OLDNUM(sp,n)	oldnums(sp)[n]
1770e3d5408SPeter Wemm # else /* !USE_HASHMAP */
17806bfebdeSXin LI #  define OLDNUM(sp,n)	NewScreen(sp)->_line[n].oldindex
1790e3d5408SPeter Wemm # endif	/* !USE_HASHMAP */
1800e3d5408SPeter Wemm 
18106bfebdeSXin LI #define OLDNUM_SIZE(sp) (sp)->_oldnum_size
1825ca44d1cSRong-En Fan 
1830e3d5408SPeter Wemm #endif /* defined(SCROLLDEBUG) || defined(HASHDEBUG) */
1840e3d5408SPeter Wemm 
1857a69bbfbSPeter Wemm NCURSES_EXPORT(void)
NCURSES_SP_NAME(_nc_scroll_optimize)18606bfebdeSXin LI NCURSES_SP_NAME(_nc_scroll_optimize) (NCURSES_SP_DCL0)
1870e3d5408SPeter Wemm /* scroll optimization to transform curscr to newscr */
1880e3d5408SPeter Wemm {
1890e3d5408SPeter Wemm     int i;
1900e3d5408SPeter Wemm     int start, end, shift;
1910e3d5408SPeter Wemm 
19206bfebdeSXin LI     TR(TRACE_ICALLS, (T_CALLED("_nc_scroll_optimize(%p)"), (void *) SP_PARM));
1930e3d5408SPeter Wemm 
1940e3d5408SPeter Wemm #if !defined(SCROLLDEBUG) && !defined(HASHDEBUG)
1950e3d5408SPeter Wemm #if USE_HASHMAP
1960e3d5408SPeter Wemm     /* get enough storage */
19773f0a83dSXin LI     assert(OLDNUM_SIZE(SP_PARM) >= 0);
19873f0a83dSXin LI     assert(screen_lines(SP_PARM) > 0);
19973f0a83dSXin LI     if ((oldnums(SP_PARM) == 0)
20073f0a83dSXin LI 	|| (OLDNUM_SIZE(SP_PARM) < screen_lines(SP_PARM))) {
20173f0a83dSXin LI 	int need_lines = ((OLDNUM_SIZE(SP_PARM) < screen_lines(SP_PARM))
20273f0a83dSXin LI 			  ? screen_lines(SP_PARM)
20373f0a83dSXin LI 			  : OLDNUM_SIZE(SP_PARM));
20406bfebdeSXin LI 	int *new_oldnums = typeRealloc(int,
20573f0a83dSXin LI 				       (size_t) need_lines,
20606bfebdeSXin LI 				       oldnums(SP_PARM));
207*21817992SBaptiste Daroussin 	if (!new_oldnums) {
208*21817992SBaptiste Daroussin 	    TR(TRACE_ICALLS, (T_RETURN("")));
2090e3d5408SPeter Wemm 	    return;
210*21817992SBaptiste Daroussin 	}
21106bfebdeSXin LI 	oldnums(SP_PARM) = new_oldnums;
21273f0a83dSXin LI 	OLDNUM_SIZE(SP_PARM) = need_lines;
2130e3d5408SPeter Wemm     }
2140e3d5408SPeter Wemm     /* calculate the indices */
21506bfebdeSXin LI     NCURSES_SP_NAME(_nc_hash_map) (NCURSES_SP_ARG);
216*21817992SBaptiste Daroussin     if (SP_PARM->hashtab_len < screen_lines(SP_PARM)) {
217*21817992SBaptiste Daroussin 	TR(TRACE_ICALLS, (T_RETURN("")));
218*21817992SBaptiste Daroussin 	return;
219*21817992SBaptiste Daroussin     }
2200e3d5408SPeter Wemm #endif
2210e3d5408SPeter Wemm #endif /* !defined(SCROLLDEBUG) && !defined(HASHDEBUG) */
2220e3d5408SPeter Wemm 
2230e3d5408SPeter Wemm #ifdef TRACE
2245ca44d1cSRong-En Fan     if (USE_TRACEF(TRACE_UPDATE | TRACE_MOVE)) {
22506bfebdeSXin LI 	NCURSES_SP_NAME(_nc_linedump) (NCURSES_SP_ARG);
2265ca44d1cSRong-En Fan 	_nc_unlock_global(tracef);
2275ca44d1cSRong-En Fan     }
2280e3d5408SPeter Wemm #endif /* TRACE */
2290e3d5408SPeter Wemm 
2300e3d5408SPeter Wemm     /* pass 1 - from top to bottom scrolling up */
23106bfebdeSXin LI     for (i = 0; i < screen_lines(SP_PARM);) {
23206bfebdeSXin LI 	while (i < screen_lines(SP_PARM)
23306bfebdeSXin LI 	       && (OLDNUM(SP_PARM, i) == _NEWINDEX || OLDNUM(SP_PARM, i) <= i))
2340e3d5408SPeter Wemm 	    i++;
23506bfebdeSXin LI 	if (i >= screen_lines(SP_PARM))
2360e3d5408SPeter Wemm 	    break;
2370e3d5408SPeter Wemm 
23806bfebdeSXin LI 	shift = OLDNUM(SP_PARM, i) - i;		/* shift > 0 */
2390e3d5408SPeter Wemm 	start = i;
2400e3d5408SPeter Wemm 
2410e3d5408SPeter Wemm 	i++;
24206bfebdeSXin LI 	while (i < screen_lines(SP_PARM)
24306bfebdeSXin LI 	       && OLDNUM(SP_PARM, i) != _NEWINDEX
24406bfebdeSXin LI 	       && OLDNUM(SP_PARM, i) - i == shift)
2450e3d5408SPeter Wemm 	    i++;
2460e3d5408SPeter Wemm 	end = i - 1 + shift;
2470e3d5408SPeter Wemm 
2480e3d5408SPeter Wemm 	TR(TRACE_UPDATE | TRACE_MOVE, ("scroll [%d, %d] by %d", start, end, shift));
2490e3d5408SPeter Wemm #if !defined(SCROLLDEBUG) && !defined(HASHDEBUG)
25006bfebdeSXin LI 	if (NCURSES_SP_NAME(_nc_scrolln) (NCURSES_SP_ARGx
25106bfebdeSXin LI 					  shift,
25206bfebdeSXin LI 					  start,
25306bfebdeSXin LI 					  end,
25406bfebdeSXin LI 					  screen_lines(SP_PARM) - 1) == ERR) {
2550e3d5408SPeter Wemm 	    TR(TRACE_UPDATE | TRACE_MOVE, ("unable to scroll"));
2560e3d5408SPeter Wemm 	    continue;
2570e3d5408SPeter Wemm 	}
2580e3d5408SPeter Wemm #endif /* !defined(SCROLLDEBUG) && !defined(HASHDEBUG) */
2590e3d5408SPeter Wemm     }
2600e3d5408SPeter Wemm 
2610e3d5408SPeter Wemm     /* pass 2 - from bottom to top scrolling down */
26206bfebdeSXin LI     for (i = screen_lines(SP_PARM) - 1; i >= 0;) {
26306bfebdeSXin LI 	while (i >= 0
26406bfebdeSXin LI 	       && (OLDNUM(SP_PARM, i) == _NEWINDEX
26506bfebdeSXin LI 		   || OLDNUM(SP_PARM, i) >= i)) {
2660e3d5408SPeter Wemm 	    i--;
26706bfebdeSXin LI 	}
2680e3d5408SPeter Wemm 	if (i < 0)
2690e3d5408SPeter Wemm 	    break;
2700e3d5408SPeter Wemm 
27106bfebdeSXin LI 	shift = OLDNUM(SP_PARM, i) - i;		/* shift < 0 */
2720e3d5408SPeter Wemm 	end = i;
2730e3d5408SPeter Wemm 
2740e3d5408SPeter Wemm 	i--;
27506bfebdeSXin LI 	while (i >= 0
27606bfebdeSXin LI 	       && OLDNUM(SP_PARM, i) != _NEWINDEX
27706bfebdeSXin LI 	       && OLDNUM(SP_PARM, i) - i == shift) {
2780e3d5408SPeter Wemm 	    i--;
27906bfebdeSXin LI 	}
2800e3d5408SPeter Wemm 	start = i + 1 - (-shift);
2810e3d5408SPeter Wemm 
2820e3d5408SPeter Wemm 	TR(TRACE_UPDATE | TRACE_MOVE, ("scroll [%d, %d] by %d", start, end, shift));
2830e3d5408SPeter Wemm #if !defined(SCROLLDEBUG) && !defined(HASHDEBUG)
28406bfebdeSXin LI 	if (NCURSES_SP_NAME(_nc_scrolln) (NCURSES_SP_ARGx
28506bfebdeSXin LI 					  shift,
28606bfebdeSXin LI 					  start,
28706bfebdeSXin LI 					  end,
28806bfebdeSXin LI 					  screen_lines(SP_PARM) - 1) == ERR) {
2890e3d5408SPeter Wemm 	    TR(TRACE_UPDATE | TRACE_MOVE, ("unable to scroll"));
2900e3d5408SPeter Wemm 	    continue;
2910e3d5408SPeter Wemm 	}
2920e3d5408SPeter Wemm #endif /* !defined(SCROLLDEBUG) && !defined(HASHDEBUG) */
2930e3d5408SPeter Wemm     }
2945ca44d1cSRong-En Fan     TR(TRACE_ICALLS, (T_RETURN("")));
2950e3d5408SPeter Wemm }
2960e3d5408SPeter Wemm 
29706bfebdeSXin LI #if NCURSES_SP_FUNCS
29806bfebdeSXin LI NCURSES_EXPORT(void)
_nc_scroll_optimize(void)29906bfebdeSXin LI _nc_scroll_optimize(void)
30006bfebdeSXin LI {
30106bfebdeSXin LI     NCURSES_SP_NAME(_nc_scroll_optimize) (CURRENT_SCREEN);
30206bfebdeSXin LI }
30306bfebdeSXin LI #endif
30406bfebdeSXin LI 
3050e3d5408SPeter Wemm #if defined(TRACE) || defined(SCROLLDEBUG) || defined(HASHDEBUG)
3067a69bbfbSPeter Wemm NCURSES_EXPORT(void)
NCURSES_SP_NAME(_nc_linedump)30706bfebdeSXin LI NCURSES_SP_NAME(_nc_linedump) (NCURSES_SP_DCL0)
3080e3d5408SPeter Wemm /* dump the state of the real and virtual oldnum fields */
3090e3d5408SPeter Wemm {
310*21817992SBaptiste Daroussin     if (USE_TRACEF(TRACE_UPDATE | TRACE_MOVE)) {
3115ca44d1cSRong-En Fan 	char *buf = 0;
31206bfebdeSXin LI 	size_t want = ((size_t) screen_lines(SP_PARM) + 1) * 4;
313aae38d10SBaptiste Daroussin 	(void) SP_PARM;
3140e3d5408SPeter Wemm 
3155d08fb1fSRong-En Fan 	if ((buf = typeMalloc(char, want)) != 0) {
316aae38d10SBaptiste Daroussin 	    int n;
3170e3d5408SPeter Wemm 
31806bfebdeSXin LI 	    *buf = '\0';
319*21817992SBaptiste Daroussin 	    for (n = 0; n < screen_lines(SP_PARM); n++) {
320*21817992SBaptiste Daroussin 		int number = OLDNUM(SP_PARM, n);
321*21817992SBaptiste Daroussin 		if (number >= -99 && number < 999) {
32273f0a83dSXin LI 		    _nc_SPRINTF(buf + strlen(buf),
32373f0a83dSXin LI 				_nc_SLIMIT(want - strlen(buf))
324*21817992SBaptiste Daroussin 				" %02d", number);
325*21817992SBaptiste Daroussin 		} else {
326*21817992SBaptiste Daroussin 		    _nc_STRCAT(buf, " ??", want - strlen(buf));
327*21817992SBaptiste Daroussin 		}
328*21817992SBaptiste Daroussin 	    }
3290e3d5408SPeter Wemm 	    free(buf);
3300e3d5408SPeter Wemm 	}
3315d08fb1fSRong-En Fan     }
332*21817992SBaptiste Daroussin }
33306bfebdeSXin LI 
33406bfebdeSXin LI #if NCURSES_SP_FUNCS
33506bfebdeSXin LI NCURSES_EXPORT(void)
_nc_linedump(void)33606bfebdeSXin LI _nc_linedump(void)
33706bfebdeSXin LI {
33806bfebdeSXin LI     NCURSES_SP_NAME(_nc_linedump) (CURRENT_SCREEN);
33906bfebdeSXin LI }
34006bfebdeSXin LI #endif
34106bfebdeSXin LI 
3420e3d5408SPeter Wemm #endif /* defined(TRACE) || defined(SCROLLDEBUG) */
3430e3d5408SPeter Wemm 
3440e3d5408SPeter Wemm #ifdef SCROLLDEBUG
3450e3d5408SPeter Wemm 
3460e3d5408SPeter Wemm int
main(int argc GCC_UNUSED,char * argv[]GCC_UNUSED)3470e3d5408SPeter Wemm main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
3480e3d5408SPeter Wemm {
3490e3d5408SPeter Wemm     char line[BUFSIZ], *st;
3500e3d5408SPeter Wemm 
3510e3d5408SPeter Wemm #ifdef TRACE
3520e3d5408SPeter Wemm     _nc_tracing = TRACE_MOVE;
3530e3d5408SPeter Wemm #endif
3547a69bbfbSPeter Wemm     for (;;) {
3550e3d5408SPeter Wemm 	int n;
3560e3d5408SPeter Wemm 
357aae38d10SBaptiste Daroussin 	for (n = 0; n < screen_lines(sp); n++)
3580e3d5408SPeter Wemm 	    oldnums[n] = _NEWINDEX;
3590e3d5408SPeter Wemm 
3600e3d5408SPeter Wemm 	/* grab the test vector */
3610e3d5408SPeter Wemm 	if (fgets(line, sizeof(line), stdin) == (char *) NULL)
3620e3d5408SPeter Wemm 	    exit(EXIT_SUCCESS);
3630e3d5408SPeter Wemm 
3640e3d5408SPeter Wemm 	/* parse it */
3650e3d5408SPeter Wemm 	n = 0;
3667a69bbfbSPeter Wemm 	if (line[0] == '#') {
3670e3d5408SPeter Wemm 	    (void) fputs(line, stderr);
3680e3d5408SPeter Wemm 	    continue;
3690e3d5408SPeter Wemm 	}
3700e3d5408SPeter Wemm 	st = strtok(line, " ");
3710e3d5408SPeter Wemm 	do {
3720e3d5408SPeter Wemm 	    oldnums[n++] = atoi(st);
3730e3d5408SPeter Wemm 	} while
3740e3d5408SPeter Wemm 	    ((st = strtok((char *) NULL, " ")) != 0);
3750e3d5408SPeter Wemm 
3760e3d5408SPeter Wemm 	/* display it */
3770e3d5408SPeter Wemm 	(void) fputs("Initial input:\n", stderr);
3780e3d5408SPeter Wemm 	_nc_linedump();
3790e3d5408SPeter Wemm 
3800e3d5408SPeter Wemm 	_nc_scroll_optimize();
3810e3d5408SPeter Wemm     }
3820e3d5408SPeter Wemm }
3830e3d5408SPeter Wemm 
3840e3d5408SPeter Wemm #endif /* SCROLLDEBUG */
3850e3d5408SPeter Wemm 
3860e3d5408SPeter Wemm /* hardscroll.c ends here */
387