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