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 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 /*LINTLIBRARY*/
43
44 #include <stdlib.h>
45 #include "curses_inc.h"
46
47
48 /* Functions to make use of insert/delete line caps */
49
50 #define scrco COLS
51
52 typedef struct
53 {
54 int _wy, /* matching lines */
55 _sy;
56 } IDST;
57 static IDST *sid, *eid; /* list of idln actions */
58 static int scrli, /* screen dimensions */
59 cy, cx; /* current cursor positions */
60 static bool didcsr; /* scrolling region was used */
61 static int _use_idln(void), _set_idln(void);
62 static void _do_idln(int, int, int, int);
63
64 /* Set insert/delete line mode for win */
65
66 int
idlok(WINDOW * win,bool bf)67 idlok(WINDOW *win, bool bf)
68 {
69 _useidln = _use_idln;
70 _setidln = _set_idln;
71
72 SP->yesidln = (delete_line || parm_delete_line ||
73 (change_scroll_region && (parm_index || scroll_forward))) &&
74 (insert_line || parm_insert_line ||
75 (change_scroll_region && (parm_rindex || scroll_reverse)));
76
77 win->_use_idl = bf;
78 return (OK);
79 }
80
81 /*
82 * Set the places to do insert/delete lines
83 * Return the start line for such action.
84 */
85
86 static int
_set_idln(void)87 _set_idln(void)
88 {
89 /*
90 * The value we want to return is the lower line
91 * number of the top-most range.
92 *
93 * If there is more than one range of lines on which
94 * we're operating, _find_idln will get called more
95 * then once; we need to search all the IDST for the
96 * desired return value.
97 */
98 {
99 IDST *idp;
100 int rval = scrli;
101
102 for (idp = sid; idp != eid; idp++) {
103 int tmp;
104
105 if ((tmp = _MIN(idp->_wy, idp->_sy)) < rval)
106 rval = tmp;
107 }
108 return (rval);
109 }
110 }
111
112 /* Use hardware line delete/insert */
113
114 static int
_use_idln(void)115 _use_idln(void)
116 {
117 int tsy, bsy, idn, dir, nomore;
118 IDST *ip, *ep, *eip;
119
120 cy = curscr->_cury;
121 cx = curscr->_curx;
122 didcsr = FALSE;
123
124 /* first cycle do deletions, second cycle do insertions */
125 for (dir = 1; dir > -2; dir -= 2) {
126 if (dir > 0) {
127 ip = sid;
128 eip = eid;
129 } else {
130 ip = eid - 1;
131 eip = sid - 1;
132 }
133
134 nomore = TRUE;
135 while (ip != eip) {
136 /* skip deletions or insertions */
137 if ((dir > 0 && ip->_wy > ip->_sy) ||
138 (dir < 0 && ip->_wy < ip->_sy)) {
139 nomore = FALSE;
140 ip += dir;
141 continue;
142 }
143
144 /* find a contiguous block */
145 for (ep = ip+dir; ep != eip; ep += dir)
146 if (ep->_wy != (ep - dir)->_wy + dir ||
147 ep->_sy != (ep - dir)->_sy + dir) {
148 break;
149 }
150 ep -= dir;
151
152 /* top and bottom lines of the affected region */
153 if (dir > 0) {
154 tsy = _MIN(ip->_wy, ip->_sy);
155 bsy = _MAX(ep->_wy, ep->_sy) + 1;
156 } else {
157 tsy = _MIN(ep->_wy, ep->_sy);
158 bsy = _MAX(ip->_wy, ip->_sy) + 1;
159 }
160
161 /* amount to insert/delete */
162 if ((idn = ip->_wy - ip->_sy) < 0)
163 idn = -idn;
164
165 /* do the actual output */
166 _do_idln(tsy, bsy, idn, dir == -1);
167
168 /* update change structure */
169 (void) wtouchln(_virtscr, tsy, bsy - tsy, -1);
170
171 /* update screen image */
172 /*LINTED*/
173 curscr->_tmarg = (short)tsy;
174 curscr->_bmarg = bsy - 1;
175 /*LINTED*/
176 curscr->_cury = (short)tsy;
177 (void) winsdelln(curscr, dir > 0 ? -idn : idn);
178 curscr->_tmarg = 0;
179 curscr->_bmarg = scrli - 1;
180
181 /* for next while cycle */
182 ip = ep + dir;
183 }
184
185 if (nomore)
186 break;
187 }
188
189 /* reset scrolling region */
190 if (didcsr) {
191 _PUTS(tparm_p2(change_scroll_region, 0, scrli - 1), scrli);
192 cy = cx = -1;
193 }
194
195 /*LINTED*/
196 curscr->_cury = (short)cy;
197 /*LINTED*/
198 curscr->_curx = (short)cx;
199 return (OK);
200 }
201
202 /* Do the actual insert/delete lines */
203
204 static void
_do_idln(int tsy,int bsy,int idn,int doinsert)205 _do_idln(int tsy, int bsy, int idn, int doinsert)
206 {
207 int y, usecsr, yesscrl;
208 short *begns;
209
210 /* change scrolling region */
211 yesscrl = usecsr = FALSE;
212 if (tsy > 0 || bsy < scrli) {
213 if (change_scroll_region) {
214 _PUTS(tparm_p2(change_scroll_region, tsy, bsy - 1),
215 bsy - tsy);
216 cy = cx = -1;
217 yesscrl = usecsr = didcsr = TRUE;
218 }
219 } else {
220 if (didcsr) {
221 _PUTS(tparm_p2(change_scroll_region, 0, scrli - 1), scrli);
222 cy = cx = -1;
223 didcsr = FALSE;
224 }
225 yesscrl = TRUE;
226 }
227
228 if (doinsert) {
229 /* memory below, clobber it now */
230 if (memory_below && clr_eol &&
231 ((usecsr && non_dest_scroll_region) || bsy == scrli)) {
232 for (y = bsy - idn, begns = _BEGNS + y;
233 y < bsy; ++y, ++begns)
234 if (*begns < scrco) {
235 (void) mvcur(cy, cx, y, 0);
236 cy = y;
237 cx = 0;
238 _PUTS(clr_eol, 1);
239 }
240 }
241
242 /* if not change_scroll_region, delete, then insert */
243 if (!usecsr && bsy < scrli) {
244 /* delete appropriate number of lines */
245 (void) mvcur(cy, cx, bsy - idn, 0);
246 cy = bsy - idn;
247 cx = 0;
248 if (parm_delete_line && (idn > 1 || !delete_line))
249 _PUTS(tparm_p1(parm_delete_line, idn),
250 scrli - cy);
251 else
252 for (y = 0; y < idn; ++y)
253 _PUTS(delete_line, scrli - cy);
254 }
255
256 /* now do insert */
257 (void) mvcur(cy, cx, tsy, 0);
258 cy = tsy;
259 cx = 0;
260 if (yesscrl) {
261 if (!parm_rindex && (!scroll_reverse ||
262 (parm_insert_line && idn > 1))) {
263 goto hardinsert;
264 }
265 if (parm_rindex && (idn > 1 || !scroll_reverse))
266 _PUTS(tparm_p1(parm_rindex, idn), scrli - cy);
267 else
268 for (y = 0; y < idn; ++y)
269 _PUTS(scroll_reverse, scrli - cy);
270 } else {
271 hardinsert:
272 if (parm_insert_line && (idn > 1 || !insert_line))
273 _PUTS(tparm_p1(parm_insert_line, idn),
274 scrli - cy);
275 else
276 for (y = 0; y < idn; ++y)
277 _PUTS(insert_line, scrli - cy);
278 }
279 } else {
280 /* doing deletion */
281 /* memory above, clobber it now */
282 if (memory_above && clr_eol &&
283 ((usecsr && non_dest_scroll_region) || tsy == 0)) {
284 for (y = 0, begns = _BEGNS + y + tsy;
285 y < idn; ++y, ++begns)
286 if (*begns < scrco) {
287 (void) mvcur(cy, cx, tsy + y, 0);
288 cy = tsy + y;
289 cx = 0;
290 _PUTS(clr_eol, 1);
291 }
292 }
293
294 if (yesscrl) {
295 if (!parm_index && (!scroll_forward ||
296 (parm_delete_line && idn > 1))) {
297 goto harddelete;
298 }
299 (void) mvcur(cy, cx, bsy - 1, 0);
300 cy = bsy - 1;
301 cx = 0;
302 if (parm_index && (idn > 1 || !scroll_forward))
303 _PUTS(tparm_p1(parm_index, idn), scrli - cy);
304 else
305 for (y = 0; y < idn; ++y)
306 _PUTS(scroll_forward, scrli - cy);
307 } else {
308 harddelete:
309 /* do deletion */
310 (void) mvcur(cy, cx, tsy, 0);
311 cy = tsy;
312 cx = 0;
313 if (parm_delete_line && (idn > 1 || !delete_line))
314 _PUTS(tparm_p1(parm_delete_line, idn),
315 scrli - cy);
316 else
317 for (y = 0; y < idn; ++y)
318 _PUTS(delete_line, scrli - cy);
319 }
320
321 /* if not change_scroll_region, do insert to restore bottom */
322 if (!usecsr && bsy < scrli) {
323 y = scrli - 1;
324 begns = _BEGNS + y;
325 for (; y >= bsy; --y, --begns)
326 if (*begns < scrco)
327 break;
328 if (y >= bsy) {
329 (void) mvcur(cy, cx, bsy - idn, 0);
330 cy = bsy - idn;
331 cx = 0;
332 if (parm_insert_line &&
333 (idn > 1 || !insert_line))
334 _PUTS(tparm_p1(parm_insert_line, idn),
335 scrli - cy);
336 else
337 for (y = 0; y < idn; ++y)
338 _PUTS(insert_line, scrli - cy);
339 }
340 }
341 }
342 }
343