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