|
|
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.8 (Berkeley) 6/7/85";
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: int resize;
75:
76: if (resize = setjmp(venv)) {
77: setsize();
78: initev = (char *)0;
79: inopen = 0;
80: addr1 = addr2 = dot;
81: }
82: (void)signal(SIGWINCH, winch);
83: ovbeg();
84: if (peekchar() == '/') {
85: ignore(compile(getchar(), 1));
86: savere(scanre);
87: if (execute(0, dot) == 0)
88: error("Fail|Pattern not found on addressed line");
89: ic = loc1;
90: if (ic > linebuf && *ic == 0)
91: ic--;
92: } else {
93: getDOT();
94: ic = vskipwh(linebuf);
95: }
96: newline();
97:
98: /*
99: * If overstrike then have to HARDOPEN
100: * else if can move cursor up off current line can use CRTOPEN (~~vi1)
101: * otherwise (ugh) have to use ONEOPEN (like adm3)
102: */
103: if (OS && !EO)
104: bastate = HARDOPEN;
105: else if (CA || UP)
106: bastate = CRTOPEN;
107: else
108: bastate = ONEOPEN;
109: setwind();
110:
111: /*
112: * To avoid bombing on glass-crt's when the line is too long
113: * pretend that such terminals are 160 columns wide.
114: * If a line is too wide for display, we will dynamically
115: * switch to hardcopy open mode.
116: */
117: if (state != CRTOPEN)
118: WCOLS = TUBECOLS;
119: if (!inglobal)
120: savevis();
121: vok(atube);
122: if (state != CRTOPEN)
123: COLUMNS = WCOLS;
124: Outchar = vputchar;
125: f = ostart();
126: if (state == CRTOPEN) {
127: if (outcol == UKCOL)
128: outcol = 0;
129: vmoveitup(1, 1);
130: } else
131: outline = destline = WBOT;
132: vshow(dot, NOLINE);
133: vnline(ic);
134: vmain();
135: if (state != CRTOPEN)
136: vclean();
137: Command = "open";
138: ovend(f);
139: (void)signal(SIGWINCH, SIG_DFL);
140: }
141:
142: ovbeg()
143: {
144:
145: if (!value(OPEN))
146: error("Can't use open/visual unless open option is set");
147: if (inopen)
148: error("Recursive open/visual not allowed");
149: Vlines = lineDOL();
150: fixzero();
151: setdot();
152: pastwh();
153: dot = addr2;
154: }
155:
156: ovend(f)
157: ttymode f;
158: {
159:
160: splitw++;
161: vgoto(WECHO, 0);
162: vclreol();
163: vgoto(WECHO, 0);
164: holdcm = 0;
165: splitw = 0;
166: ostop(f);
167: setoutt();
168: undvis();
169: COLUMNS = OCOLUMNS;
170: inopen = 0;
171: flusho();
172: netchHAD(Vlines);
173: }
174:
175: /*
176: * Enter visual mode
177: */
178: vop()
179: {
180: register int c;
181: #ifndef u370
182: char atube[TUBESIZE + LBSIZE];
183: #endif
184: ttymode f; /* mjm: was register */
185: int resize;
186:
187: if (!CA && UP == NOSTR) {
188: if (initev) {
189: toopen:
190: merror("[Using open mode]");
191: putNFL();
192: oop();
193: return;
194: }
195: error("Visual needs addressible cursor or upline capability");
196: }
197: if (OS && !EO) {
198: if (initev)
199: goto toopen;
200: error("Can't use visual on a terminal which overstrikes");
201: }
202: if (!CL) {
203: if (initev)
204: goto toopen;
205: error("Visual requires clear screen capability");
206: }
207: if (NS && !SF) {
208: if (initev)
209: goto toopen;
210: error("Visual requires scrolling");
211: }
212: if (resize = setjmp(venv)) {
213: setsize();
214: initev = (char *)0;
215: inopen = 0;
216: addr1 = addr2 = dot;
217: }
218: (void)signal(SIGWINCH, winch);
219: ovbeg();
220: bastate = VISUAL;
221: c = 0;
222: if (any(peekchar(), "+-^."))
223: c = getchar();
224: pastwh();
225: vsetsiz(isdigit(peekchar()) ? getnum() : value(WINDOW));
226: setwind();
227: newline();
228: vok(atube);
229: if (!inglobal)
230: savevis();
231: Outchar = vputchar;
232: vmoving = 0;
233: f = ostart();
234: if (initev == 0) {
235: vcontext(dot, c);
236: vnline(NOSTR);
237: }
238: vmain();
239: Command = "visual";
240: ovend(f);
241: (void)signal(SIGWINCH, SIG_DFL);
242: }
243:
244: /*
245: * Hack to allow entry to visual with
246: * empty buffer since routines internally
247: * demand at least one line.
248: */
249: fixzero()
250: {
251:
252: if (dol == zero) {
253: register bool ochng = chng;
254:
255: vdoappend("");
256: if (!ochng)
257: sync();
258: addr1 = addr2 = one;
259: } else if (addr2 == zero)
260: addr2 = one;
261: }
262:
263: /*
264: * Save lines before visual between unddol and truedol.
265: * Accomplish this by throwing away current [unddol,truedol]
266: * and then saving all the lines in the buffer and moving
267: * unddol back to dol. Don't do this if in a global.
268: *
269: * If you do
270: * g/xxx/vi.
271: * and then do a
272: * :e xxxx
273: * at some point, and then quit from the visual and undo
274: * you get the old file back. Somewhat weird.
275: */
276: savevis()
277: {
278:
279: if (inglobal)
280: return;
281: truedol = unddol;
282: saveall();
283: unddol = dol;
284: undkind = UNDNONE;
285: }
286:
287: /*
288: * Restore a sensible state after a visual/open, moving the saved
289: * stuff back to [unddol,dol], and killing the partial line kill indicators.
290: */
291: undvis()
292: {
293:
294: if (ruptible)
295: signal(SIGINT, onintr);
296: squish();
297: pkill[0] = pkill[1] = 0;
298: unddol = truedol;
299: unddel = zero;
300: undap1 = one;
301: undap2 = dol + 1;
302: undkind = UNDALL;
303: if (undadot <= zero || undadot > dol)
304: undadot = zero+1;
305: }
306:
307: /*
308: * Set the window parameters based on the base state bastate
309: * and the available buffer space.
310: */
311: setwind()
312: {
313:
314: WCOLS = COLUMNS;
315: switch (bastate) {
316:
317: case ONEOPEN:
318: if (AM)
319: WCOLS--;
320: /* fall into ... */
321:
322: case HARDOPEN:
323: basWTOP = WTOP = WBOT = WECHO = 0;
324: ZERO = 0;
325: holdcm++;
326: break;
327:
328: case CRTOPEN:
329: basWTOP = LINES - 2;
330: /* fall into */
331:
332: case VISUAL:
333: ZERO = LINES - TUBESIZE / WCOLS;
334: if (ZERO < 0)
335: ZERO = 0;
336: if (ZERO > basWTOP)
337: error("Screen too large for internal buffer");
338: WTOP = basWTOP; WBOT = LINES - 2; WECHO = LINES - 1;
339: break;
340: }
341: state = bastate;
342: basWLINES = WLINES = WBOT - WTOP + 1;
343: }
344:
345: /*
346: * Can we hack an open/visual on this terminal?
347: * If so, then divide the screen buffer up into lines,
348: * and initialize a bunch of state variables before we start.
349: */
350: vok(atube)
351: register char *atube;
352: {
353: register int i;
354:
355: if (WCOLS == 1000)
356: serror("Don't know enough about your terminal to use %s", Command);
357: if (WCOLS > TUBECOLS)
358: error("Terminal too wide");
359: if (WLINES >= TUBELINES || WCOLS * (WECHO - ZERO + 1) > TUBESIZE)
360: error("Screen too large");
361:
362: vtube0 = atube;
363: vclrbyte(atube, WCOLS * (WECHO - ZERO + 1));
364: for (i = 0; i < ZERO; i++)
365: vtube[i] = (char *) 0;
366: for (; i <= WECHO; i++)
367: vtube[i] = atube, atube += WCOLS;
368: for (; i < TUBELINES; i++)
369: vtube[i] = (char *) 0;
370: vutmp = atube;
371: vundkind = VNONE;
372: vUNDdot = 0;
373: OCOLUMNS = COLUMNS;
374: inopen = 1;
375: #ifdef CBREAK
376: signal(SIGINT, vintr);
377: #endif
378: vmoving = 0;
379: splitw = 0;
380: doomed = 0;
381: holdupd = 0;
382: Peekkey = 0;
383: vcnt = vcline = 0;
384: if (vSCROLL == 0)
385: vSCROLL = (value(WINDOW)+1)/2; /* round up so dft=6,11 */
386: }
387:
388: #ifdef CBREAK
389: vintr()
390: {
391: extern jmp_buf readbuf;
392: extern int doingread;
393:
394: signal(SIGINT, vintr);
395: if (vcatch)
396: onintr();
397: ungetkey(ATTN);
398: draino();
399: if (doingread) {
400: doingread = 0;
401: longjmp(readbuf, 1);
402: }
403: }
404: #endif
405:
406: /*
407: * Set the size of the screen to size lines, to take effect the
408: * next time the screen is redrawn.
409: */
410: vsetsiz(size)
411: int size;
412: {
413: register int b;
414:
415: if (bastate != VISUAL)
416: return;
417: b = LINES - 1 - size;
418: if (b >= LINES - 1)
419: b = LINES - 2;
420: if (b < 0)
421: b = 0;
422: basWTOP = b;
423: basWLINES = WBOT - b + 1;
424: }
425:
426: winch()
427: {
428: vsave();
429: setty(normf);
430: longjmp(venv, 1);
431: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.