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