1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1995-1999 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 /* LINTLIBRARY */
28 
29 /*
30  * wscrl.c
31  *
32  * XCurses Library
33  *
34  * Copyright 1990, 1995 by Mortice Kern Systems Inc.  All rights reserved.
35  *
36  */
37 
38 #ifdef M_RCSID
39 #ifndef lint
40 static char rcsID[] =
41 "$Header: /team/ps/sun_xcurses/archive/local_changes/xcurses/src/lib/"
42 "libxcurses/src/libc/xcurses/rcs/wscrl.c 1.8 1998/06/04 17:52:07 "
43 "cbates Exp $";
44 #endif
45 #endif
46 
47 #include <private.h>
48 #include <string.h>
49 
50 /*
51  * For positive n scroll the window up n lines (line i+n becomes i);
52  * otherwise scroll the window down n lines.
53  */
54 int
wscrl(WINDOW * w,int n)55 wscrl(WINDOW *w, int n)
56 {
57 	int	start, finish, to;
58 
59 	if (!(w->_flags & W_CAN_SCROLL))
60 		return (ERR);
61 
62 	if (n == 0)
63 		return (OK);
64 
65 	if (w->_parent) {
66 		/* Sub-window should not shuffle pointers (parent owns them) */
67 		int	row;
68 		cchar_t	save;
69 		int	first;
70 
71 		if (n > 0) {
72 			for (row = w->_top; row < w->_bottom; row++) {
73 				if (row < w->_bottom - n) {
74 					if (!w->_line[row+n][0]._f)	{
75 						/*
76 						 * Tail end of
77 						 * a multi-col-char
78 						 */
79 						(void) __m_cc_erase(w, row + n,
80 							0, row + n, 0);
81 					}
82 					/*
83 					 * Erase trailing multi-col-chars
84 					 * where they hang into parent window
85 					 */
86 					first = __m_cc_first(w, row + n,
87 						w->_maxx - 1);
88 					save = w->_line[row + n][first];
89 					(void) __m_cc_erase(w, row + n,
90 						first, row + n, first);
91 					w->_line[row + n][first] = save;
92 					(void) memcpy(w->_line[row],
93 						w->_line[row + n],
94 						sizeof (cchar_t) * w->_maxx);
95 				} else {
96 					(void) __m_cc_erase(w, row, 0,
97 						w->_bottom -1, w->_maxx - 1);
98 					break;
99 				}
100 			}
101 		} else {
102 			abort();
103 		}
104 	} else {
105 		/*
106 		 * Shuffle pointers in order to scroll.  The region
107 		 * from start to finish inclusive will be moved to
108 		 * either the top or bottom of _line[].
109 		 */
110 		if (0 < n) {
111 			start = w->_top;
112 			finish = w->_top + n - 1;
113 			to = w->_bottom;
114 		} else {
115 			start = w->_bottom + n;
116 			finish = w->_bottom - 1;
117 			to = w->_top;
118 		}
119 
120 		/* Blank out new lines. */
121 		(void) __m_cc_erase(w, start, 0, finish, w->_maxx - 1);
122 
123 		/* Scroll lines by shuffling pointers. */
124 		(void) __m_ptr_move((void **) w->_line, w->_maxy,
125 			start, finish, to);
126 	}
127 
128 	if ((w->_flags & W_FULL_WINDOW) &&
129 		w->_top == 0 && w->_bottom == w->_maxy)
130 		w->_scroll += (short) n;
131 	else
132 		w->_scroll = 0;
133 
134 	(void) wtouchln(w, 0, w->_maxy, 1);
135 	wtouchln_hard(w, 0, w->_maxy);
136 
137 #ifdef	BREAKS_fimmedok_fimmedok1_2
138 	w->_flags |= W_FLUSH;
139 #endif	/* BREAKS_fimmedok_fimmedok1_2 */
140 
141 	WSYNC(w);
142 
143 	return (WFLUSH(w));
144 }
145