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