setgid to group "write" so that terminals need not be world writable
[unix-history] / usr / src / usr.bin / ex / ex_v.c
CommitLineData
19d73a0e
DF
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
70190965 8static char *sccsid = "@(#)ex_v.c 7.8 (Berkeley) %G%";
19d73a0e
DF
9#endif not lint
10
59ae3464
MH
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
2de97448
JB
58jmp_buf venv;
59int winch();
60
59ae3464
MH
61/*
62 * Enter open mode
63 */
3c7b865a
MH
64#ifdef u370
65char atube[TUBESIZE+LBSIZE];
66#endif
59ae3464
MH
67oop()
68{
69 register char *ic;
3c7b865a 70#ifndef u370
59ae3464 71 char atube[TUBESIZE + LBSIZE];
3c7b865a 72#endif
299f2784 73 ttymode f; /* mjm: was register */
2de97448 74 int resize;
59ae3464 75
2de97448
JB
76 if (resize = setjmp(venv)) {
77 setsize();
78 initev = (char *)0;
79 inopen = 0;
80 addr1 = addr2 = dot;
81 }
82 (void)signal(SIGWINCH, winch);
59ae3464
MH
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);
2de97448 139 (void)signal(SIGWINCH, SIG_DFL);
59ae3464
MH
140}
141
142ovbeg()
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
156ovend(f)
d266c416 157 ttymode f;
59ae3464
MH
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 */
178vop()
179{
180 register int c;
3c7b865a 181#ifndef u370
59ae3464 182 char atube[TUBESIZE + LBSIZE];
3c7b865a 183#endif
299f2784 184 ttymode f; /* mjm: was register */
2de97448 185 int resize;
59ae3464
MH
186
187 if (!CA && UP == NOSTR) {
188 if (initev) {
189toopen:
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 }
d266c416
MH
207 if (NS && !SF) {
208 if (initev)
209 goto toopen;
210 error("Visual requires scrolling");
211 }
2de97448
JB
212 if (resize = setjmp(venv)) {
213 setsize();
214 initev = (char *)0;
215 inopen = 0;
216 addr1 = addr2 = dot;
217 }
218 (void)signal(SIGWINCH, winch);
59ae3464
MH
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);
2de97448 241 (void)signal(SIGWINCH, SIG_DFL);
59ae3464
MH
242}
243
244/*
245 * Hack to allow entry to visual with
246 * empty buffer since routines internally
247 * demand at least one line.
248 */
249fixzero()
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 */
276savevis()
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 */
291undvis()
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;
d266c416
MH
303 if (undadot <= zero || undadot > dol)
304 undadot = zero+1;
59ae3464
MH
305}
306
307/*
308 * Set the window parameters based on the base state bastate
309 * and the available buffer space.
310 */
311setwind()
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 */
350vok(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++)
887e3e0d 365 vtube[i] = (char *) 0;
59ae3464
MH
366 for (; i <= WECHO; i++)
367 vtube[i] = atube, atube += WCOLS;
368 for (; i < TUBELINES; i++)
887e3e0d 369 vtube[i] = (char *) 0;
59ae3464
MH
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
389vintr()
390{
b3c5103a 391 extern jmp_buf readbuf;
47bdd628 392 extern int doingread;
59ae3464
MH
393
394 signal(SIGINT, vintr);
395 if (vcatch)
396 onintr();
397 ungetkey(ATTN);
398 draino();
47bdd628
SL
399 if (doingread) {
400 doingread = 0;
401 longjmp(readbuf, 1);
402 }
59ae3464
MH
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 */
410vsetsiz(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}
2de97448
JB
425
426winch()
427{
428 vsave();
451adf7e 429 setty(normf);
2de97448
JB
430 longjmp(venv, 1);
431}