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