changed the way the INDEX operator is evaluated to better
[unix-history] / usr / src / usr.bin / ex / ex_v.c
CommitLineData
299f2784 1/* Copyright (c) 1981 Regents of the University of California */
3c7b865a 2static char *sccsid = "@(#)ex_v.c 7.2 %G%";
59ae3464
MH
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 */
3c7b865a
MH
53#ifdef u370
54char atube[TUBESIZE+LBSIZE];
55#endif
59ae3464
MH
56oop()
57{
58 register char *ic;
3c7b865a 59#ifndef u370
59ae3464 60 char atube[TUBESIZE + LBSIZE];
3c7b865a 61#endif
299f2784 62 ttymode f; /* mjm: was register */
59ae3464
MH
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
122ovbeg()
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
136ovend(f)
d266c416 137 ttymode f;
59ae3464
MH
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 */
158vop()
159{
160 register int c;
3c7b865a 161#ifndef u370
59ae3464 162 char atube[TUBESIZE + LBSIZE];
3c7b865a 163#endif
299f2784 164 ttymode f; /* mjm: was register */
59ae3464
MH
165
166 if (!CA && UP == NOSTR) {
167 if (initev) {
168toopen:
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 }
d266c416
MH
186 if (NS && !SF) {
187 if (initev)
188 goto toopen;
189 error("Visual requires scrolling");
190 }
59ae3464
MH
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 */
220fixzero()
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 */
247savevis()
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 */
262undvis()
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;
d266c416
MH
274 if (undadot <= zero || undadot > dol)
275 undadot = zero+1;
59ae3464
MH
276}
277
278/*
279 * Set the window parameters based on the base state bastate
280 * and the available buffer space.
281 */
282setwind()
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 */
321vok(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++)
887e3e0d 336 vtube[i] = (char *) 0;
59ae3464
MH
337 for (; i <= WECHO; i++)
338 vtube[i] = atube, atube += WCOLS;
339 for (; i < TUBELINES; i++)
887e3e0d 340 vtube[i] = (char *) 0;
59ae3464
MH
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
360vintr()
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 */
375vsetsiz(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}