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