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 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 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 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 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