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