1 /*- 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)ex_v.c 8.1 (Berkeley) 06/09/93"; 10 #endif /* not lint */ 11 12 #include "ex.h" 13 #include "ex_re.h" 14 #include "ex_tty.h" 15 #include "ex_vis.h" 16 17 /* 18 * Entry points to open and visual from command mode processor. 19 * The open/visual code breaks down roughly as follows: 20 * 21 * ex_v.c entry points, checking of terminal characteristics 22 * 23 * ex_vadj.c logical screen control, use of intelligent operations 24 * insert/delete line and coordination with screen image; 25 * updating of screen after changes. 26 * 27 * ex_vget.c input of single keys and reading of input lines 28 * from the echo area, handling of \ escapes on input for 29 * uppercase only terminals, handling of memory for repeated 30 * commands and small saved texts from inserts and partline 31 * deletes, notification of multi line changes in the echo 32 * area. 33 * 34 * ex_vmain.c main command decoding, some command processing. 35 * 36 * ex_voperate.c decoding of operator/operand sequences and 37 * contextual scans, implementation of word motions. 38 * 39 * ex_vops.c major operator interfaces, undos, motions, deletes, 40 * changes, opening new lines, shifts, replacements and yanks 41 * coordinating logical and physical changes. 42 * 43 * ex_vops2.c subroutines for operator interfaces in ex_vops.c, 44 * insert mode, read input line processing at lowest level. 45 * 46 * ex_vops3.c structured motion definitions of ( ) { } and [ ] operators, 47 * indent for lisp routines, () and {} balancing. 48 * 49 * ex_vput.c output routines, clearing, physical mapping of logical cursor 50 * positioning, cursor motions, handling of insert character 51 * and delete character functions of intelligent and unintelligent 52 * terminals, visual mode tracing routines (for debugging), 53 * control of screen image and its updating. 54 * 55 * ex_vwind.c window level control of display, forward and backward rolls, 56 * absolute motions, contextual displays, line depth determination 57 */ 58 59 jmp_buf venv; 60 void winch(); 61 62 /* 63 * Enter open mode 64 */ 65 #ifdef u370 66 char atube[TUBESIZE+LBSIZE]; 67 #endif 68 oop() 69 { 70 register char *ic; 71 #ifndef u370 72 char atube[TUBESIZE + LBSIZE]; 73 #endif 74 ttymode f; /* mjm: was register */ 75 76 if (setjmp(venv)) { 77 setsize(); 78 initev = (char *)0; 79 inopen = 0; 80 addr1 = addr2 = dot; 81 } 82 #ifdef SIGWINCH 83 (void)signal(SIGWINCH, winch); 84 #endif 85 ovbeg(); 86 if (peekchar() == '/') { 87 ignore(compile(ex_getchar(), 1)); 88 savere(scanre); 89 if (execute(0, dot) == 0) 90 error("Fail|Pattern not found on addressed line"); 91 ic = loc1; 92 if (ic > linebuf && *ic == 0) 93 ic--; 94 } else { 95 getDOT(); 96 ic = vskipwh(linebuf); 97 } 98 newline(); 99 100 /* 101 * If overstrike then have to HARDOPEN 102 * else if can move cursor up off current line can use CRTOPEN (~~vi1) 103 * otherwise (ugh) have to use ONEOPEN (like adm3) 104 */ 105 if (OS && !EO) 106 bastate = HARDOPEN; 107 else if (CA || UP) 108 bastate = CRTOPEN; 109 else 110 bastate = ONEOPEN; 111 setwind(); 112 113 /* 114 * To avoid bombing on glass-crt's when the line is too long 115 * pretend that such terminals are 160 columns wide. 116 * If a line is too wide for display, we will dynamically 117 * switch to hardcopy open mode. 118 */ 119 if (state != CRTOPEN) 120 WCOLS = TUBECOLS; 121 if (!inglobal) 122 savevis(); 123 vok(atube); 124 if (state != CRTOPEN) 125 COLUMNS = WCOLS; 126 Outchar = vputchar; 127 f = ostart(); 128 if (state == CRTOPEN) { 129 if (outcol == UKCOL) 130 outcol = 0; 131 vmoveitup(1, 1); 132 } else 133 outline = destline = WBOT; 134 vshow(dot, NOLINE); 135 vnline(ic); 136 vmain(); 137 if (state != CRTOPEN) 138 vclean(); 139 Command = "open"; 140 ovend(f); 141 #ifdef SIGWINCH 142 (void)signal(SIGWINCH, SIG_DFL); 143 #endif 144 } 145 146 ovbeg() 147 { 148 149 if (!value(OPEN)) 150 error("Can't use open/visual unless open option is set"); 151 if (inopen) 152 error("Recursive open/visual not allowed"); 153 Vlines = lineDOL(); 154 fixzero(); 155 setdot(); 156 pastwh(); 157 dot = addr2; 158 } 159 160 ovend(f) 161 ttymode f; 162 { 163 164 splitw++; 165 vgoto(WECHO, 0); 166 vclreol(); 167 vgoto(WECHO, 0); 168 holdcm = 0; 169 splitw = 0; 170 ostop(f); 171 setoutt(); 172 undvis(); 173 COLUMNS = OCOLUMNS; 174 inopen = 0; 175 flusho(); 176 netchHAD(Vlines); 177 } 178 179 /* 180 * Enter visual mode 181 */ 182 vop() 183 { 184 register int c; 185 #ifndef u370 186 char atube[TUBESIZE + LBSIZE]; 187 #endif 188 ttymode f; /* mjm: was register */ 189 190 if (!CA && UP == NOSTR) { 191 if (initev) { 192 toopen: 193 merror("[Using open mode]"); 194 putNFL(); 195 oop(); 196 return; 197 } 198 error("Visual needs addressible cursor or upline capability"); 199 } 200 if (OS && !EO) { 201 if (initev) 202 goto toopen; 203 error("Can't use visual on a terminal which overstrikes"); 204 } 205 if (!CL) { 206 if (initev) 207 goto toopen; 208 error("Visual requires clear screen capability"); 209 } 210 if (NS && !SF) { 211 if (initev) 212 goto toopen; 213 error("Visual requires scrolling"); 214 } 215 if (setjmp(venv)) { 216 setsize(); 217 initev = (char *)0; 218 inopen = 0; 219 addr1 = addr2 = dot; 220 } 221 #ifdef SIGWINCH 222 (void)signal(SIGWINCH, winch); 223 #endif 224 ovbeg(); 225 bastate = VISUAL; 226 c = 0; 227 if (any(peekchar(), "+-^.")) 228 c = ex_getchar(); 229 pastwh(); 230 vsetsiz(isdigit(peekchar()) ? getnum() : value(WINDOW)); 231 setwind(); 232 newline(); 233 vok(atube); 234 if (!inglobal) 235 savevis(); 236 Outchar = vputchar; 237 vmoving = 0; 238 f = ostart(); 239 if (initev == 0) { 240 vcontext(dot, c); 241 vnline(NOSTR); 242 } 243 vmain(); 244 Command = "visual"; 245 ovend(f); 246 #ifdef SIGWINCH 247 (void)signal(SIGWINCH, SIG_DFL); 248 #endif 249 } 250 251 /* 252 * Hack to allow entry to visual with 253 * empty buffer since routines internally 254 * demand at least one line. 255 */ 256 fixzero() 257 { 258 259 if (dol == zero) { 260 register bool ochng = chng; 261 262 vdoappend(""); 263 if (!ochng) 264 ex_sync(); 265 addr1 = addr2 = one; 266 } else if (addr2 == zero) 267 addr2 = one; 268 } 269 270 /* 271 * Save lines before visual between unddol and truedol. 272 * Accomplish this by throwing away current [unddol,truedol] 273 * and then saving all the lines in the buffer and moving 274 * unddol back to dol. Don't do this if in a global. 275 * 276 * If you do 277 * g/xxx/vi. 278 * and then do a 279 * :e xxxx 280 * at some point, and then quit from the visual and undo 281 * you get the old file back. Somewhat weird. 282 */ 283 savevis() 284 { 285 286 if (inglobal) 287 return; 288 truedol = unddol; 289 saveall(); 290 unddol = dol; 291 undkind = UNDNONE; 292 } 293 294 /* 295 * Restore a sensible state after a visual/open, moving the saved 296 * stuff back to [unddol,dol], and killing the partial line kill indicators. 297 */ 298 undvis() 299 { 300 301 if (ruptible) 302 signal(SIGINT, onintr); 303 squish(); 304 pkill[0] = pkill[1] = 0; 305 unddol = truedol; 306 unddel = zero; 307 undap1 = one; 308 undap2 = dol + 1; 309 undkind = UNDALL; 310 if (undadot <= zero || undadot > dol) 311 undadot = zero+1; 312 } 313 314 /* 315 * Set the window parameters based on the base state bastate 316 * and the available buffer space. 317 */ 318 setwind() 319 { 320 321 WCOLS = COLUMNS; 322 switch (bastate) { 323 324 case ONEOPEN: 325 if (AM) 326 WCOLS--; 327 /* fall into ... */ 328 329 case HARDOPEN: 330 basWTOP = WTOP = WBOT = WECHO = 0; 331 ex_ZERO = 0; 332 holdcm++; 333 break; 334 335 case CRTOPEN: 336 basWTOP = LINES - 2; 337 /* fall into */ 338 339 case VISUAL: 340 ex_ZERO = LINES - TUBESIZE / WCOLS; 341 if (ex_ZERO < 0) 342 ex_ZERO = 0; 343 if (ex_ZERO > basWTOP) 344 error("Screen too large for internal buffer"); 345 WTOP = basWTOP; WBOT = LINES - 2; WECHO = LINES - 1; 346 break; 347 } 348 state = bastate; 349 basWLINES = WLINES = WBOT - WTOP + 1; 350 } 351 352 /* 353 * Can we hack an open/visual on this terminal? 354 * If so, then divide the screen buffer up into lines, 355 * and initialize a bunch of state variables before we start. 356 */ 357 vok(atube) 358 register char *atube; 359 { 360 register int i; 361 362 if (WCOLS == 1000) 363 serror("Don't know enough about your terminal to use %s", Command); 364 if (WCOLS > TUBECOLS) 365 error("Terminal too wide"); 366 if (WLINES >= TUBELINES || WCOLS * (WECHO - ex_ZERO + 1) > TUBESIZE) 367 error("Screen too large"); 368 369 vtube0 = atube; 370 vclrbyte(atube, WCOLS * (WECHO - ex_ZERO + 1)); 371 for (i = 0; i < ex_ZERO; i++) 372 vtube[i] = (char *) 0; 373 for (; i <= WECHO; i++) 374 vtube[i] = atube, atube += WCOLS; 375 for (; i < TUBELINES; i++) 376 vtube[i] = (char *) 0; 377 vutmp = atube; 378 vundkind = VNONE; 379 vUNDdot = 0; 380 OCOLUMNS = COLUMNS; 381 inopen = 1; 382 #ifdef CBREAK 383 signal(SIGINT, vintr); 384 #endif 385 vmoving = 0; 386 splitw = 0; 387 doomed = 0; 388 holdupd = 0; 389 Peek_key = 0; 390 vcnt = vcline = 0; 391 if (ex_vSCROLL == 0) 392 ex_vSCROLL = (value(WINDOW)+1)/2; /* round up so dft=6,11 */ 393 } 394 395 #ifdef CBREAK 396 void 397 vintr() 398 { 399 extern jmp_buf readbuf; 400 extern int doingread; 401 402 signal(SIGINT, vintr); 403 if (vcatch) 404 onintr(); 405 ungetkey(ATTN); 406 draino(); 407 if (doingread) { 408 doingread = 0; 409 longjmp(readbuf, 1); 410 } 411 } 412 #endif 413 414 /* 415 * Set the size of the screen to size lines, to take effect the 416 * next time the screen is redrawn. 417 */ 418 vsetsiz(size) 419 int size; 420 { 421 register int b; 422 423 if (bastate != VISUAL) 424 return; 425 b = LINES - 1 - size; 426 if (b >= LINES - 1) 427 b = LINES - 2; 428 if (b < 0) 429 b = 0; 430 basWTOP = b; 431 basWLINES = WBOT - b + 1; 432 } 433 434 #ifdef SIGWINCH 435 void 436 winch() 437 { 438 vsave(); 439 ignore(setty(normf)); 440 longjmp(venv, 1); 441 } 442 #endif 443