1: /* Copyright (c) 1981 Regents of the University of California */ 2: static char *sccsid = "@(#)ex_v.c 7.2 9/3/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: }