1 /*
2 * This code contains changes by
3 * Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
4 *
5 * Conditions 1, 2, and 4 and the no-warranty notice below apply
6 * to these changes.
7 *
8 *
9 * Copyright (c) 1980, 1993
10 * The Regents of the University of California. All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 *
41 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * Redistributions of source code and documentation must retain the
47 * above copyright notice, this list of conditions and the following
48 * disclaimer.
49 * Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed or owned by Caldera
55 * International, Inc.
56 * Neither the name of Caldera International, Inc. nor the names of
57 * other contributors may be used to endorse or promote products
58 * derived from this software without specific prior written permission.
59 *
60 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
61 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
62 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
65 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
66 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
67 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
68 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
69 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
70 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
71 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72 */
73
74 #ifndef lint
75 #ifdef DOSCCS
76 static char sccsid[] = "@(#)ex_v.c 1.17 (gritter) 11/27/04";
77 #endif
78 #endif
79
80 /* from ex_v.c 7.8.1 (2.11BSD GTE) 12/9/94 */
81
82 #include "ex.h"
83 #include "ex_re.h"
84 #include "ex_tty.h"
85 #include "ex_vis.h"
86
87 /*
88 * Entry points to open and visual from command mode processor.
89 * The open/visual code breaks down roughly as follows:
90 *
91 * ex_v.c entry points, checking of terminal characteristics
92 *
93 * ex_vadj.c logical screen control, use of intelligent operations
94 * insert/delete line and coordination with screen image;
95 * updating of screen after changes.
96 *
97 * ex_vget.c input of single keys and reading of input lines
98 * from the echo area, handling of memory for repeated
99 * commands and small saved texts from inserts and partline
100 * deletes, notification of multi line changes in the echo
101 * area.
102 *
103 * ex_vmain.c main command decoding, some command processing.
104 *
105 * ex_voperate.c decoding of operator/operand sequences and
106 * contextual scans, implementation of word motions.
107 *
108 * ex_vops.c major operator interfaces, undos, motions, deletes,
109 * changes, opening new lines, shifts, replacements and yanks
110 * coordinating logical and physical changes.
111 *
112 * ex_vops2.c subroutines for operator interfaces in ex_vops.c,
113 * insert mode, read input line processing at lowest level.
114 *
115 * ex_vops3.c structured motion definitions of ( ) { } and [ ] operators,
116 * indent for lisp routines, () and {} balancing.
117 *
118 * ex_vput.c output routines, clearing, physical mapping of logical cursor
119 * positioning, cursor motions, handling of insert character
120 * and delete character functions of intelligent and unintelligent
121 * terminals, visual mode tracing routines (for debugging),
122 * control of screen image and its updating.
123 *
124 * ex_vwind.c window level control of display, forward and backward rolls,
125 * absolute motions, contextual displays, line depth determination
126 */
127
128 JMP_BUF venv;
129
130 /*
131 * Enter open mode
132 */
133 #ifdef u370
134 cell atube[TUBESIZE+LBSIZE];
135 #endif
136 void
oop(void)137 oop(void)
138 {
139 register char *ic;
140 #ifndef u370
141 cell atube[TUBESIZE + LBSIZE];
142 #endif
143 struct termios f; /* mjm: was register */
144 int resize;
145
146 resize = SETJMP(venv);
147 if (resize) {
148 setsize();
149 initev = (char *)0;
150 inopen = 0;
151 addr1 = addr2 = dot;
152 }
153 #ifdef SIGWINCH
154 signal(SIGWINCH, onwinch);
155 #endif
156 ovbeg();
157 if (peekchar() == '/') {
158 ignore(compile(getchar(), 1));
159 savere(&scanre);
160 if (execute(0, dot) == 0)
161 error(catgets(catd, 1, 207,
162 "Fail|Pattern not found on addressed line"));
163 ic = loc1;
164 if (ic > linebuf && *ic == 0)
165 ic--;
166 } else {
167 getDOT();
168 ic = vskipwh(linebuf);
169 }
170 newline();
171
172 /*
173 * If overstrike then have to HARDOPEN
174 * else if can move cursor up off current line can use CRTOPEN (~~vi1)
175 * otherwise (ugh) have to use ONEOPEN (like adm3)
176 */
177 if (OS && !EO)
178 bastate = HARDOPEN;
179 else if (CA || UP)
180 bastate = CRTOPEN;
181 else
182 bastate = ONEOPEN;
183 setwind();
184
185 /*
186 * To avoid bombing on glass-crt's when the line is too long
187 * pretend that such terminals are 160 columns wide.
188 * If a line is too wide for display, we will dynamically
189 * switch to hardcopy open mode.
190 */
191 if (state != CRTOPEN)
192 WCOLS = TUBECOLS;
193 if (!inglobal)
194 savevis();
195 vok(atube);
196 if (state != CRTOPEN)
197 TCOLUMNS = WCOLS;
198 Outchar = vputchar;
199 f = ostart();
200 if (state == CRTOPEN) {
201 if (outcol == UKCOL)
202 outcol = 0;
203 vmoveitup(1, 1);
204 } else
205 outline = destline = WBOT;
206 vshow(dot, NOLINE);
207 vnline(ic);
208 vmain();
209 if (state != CRTOPEN)
210 vclean();
211 Command = "open";
212 ovend(f);
213 #ifdef SIGWINCH
214 signal(SIGWINCH, SIG_DFL);
215 #endif
216 }
217
218 void
ovbeg(void)219 ovbeg(void)
220 {
221
222 if (!value(OPEN))
223 error(catgets(catd, 1, 208,
224 "Can't use open/visual unless open option is set"));
225 if (inopen)
226 error(catgets(catd, 1, 209,
227 "Recursive open/visual not allowed"));
228 Vlines = lineDOL();
229 fixzero();
230 setdot();
231 pastwh();
232 dot = addr2;
233 }
234
235 void
ovend(struct termios f)236 ovend(struct termios f)
237 {
238
239 splitw++;
240 vgoto(WECHO, 0);
241 vclreol();
242 vgoto(WECHO, 0);
243 holdcm = 0;
244 splitw = 0;
245 ostop(f);
246 setoutt();
247 undvis();
248 TCOLUMNS = OCOLUMNS;
249 inopen = 0;
250 flusho();
251 netchHAD(Vlines);
252 }
253
254 /*
255 * Enter visual mode
256 */
257 void
vop(void)258 vop(void)
259 {
260 register int c;
261 #ifndef u370
262 cell atube[TUBESIZE + LBSIZE];
263 #endif
264 struct termios f; /* mjm: was register */
265 int resize;
266
267 if (!CA && UP == NOSTR) {
268 if (initev) {
269 toopen:
270 merror(catgets(catd, 1, 210, "[Using open mode]"));
271 putNFL();
272 oop();
273 return;
274 }
275 error(catgets(catd, 1, 211,
276 "Visual needs addressible cursor or upline capability"));
277 }
278 if (OS && !EO) {
279 if (initev)
280 goto toopen;
281 error(catgets(catd, 1, 212,
282 "Can't use visual on a terminal which overstrikes"));
283 }
284 if (!CL) {
285 if (initev)
286 goto toopen;
287 error(catgets(catd, 1, 213,
288 "Visual requires clear screen capability"));
289 }
290 if (NS && !SF) {
291 if (initev)
292 goto toopen;
293 error(catgets(catd, 1, 214, "Visual requires scrolling"));
294 }
295 resize = SETJMP(venv);
296 if (resize) {
297 setsize();
298 initev = (char *)0;
299 inopen = 0;
300 addr1 = addr2 = dot;
301 }
302 #ifdef SIGWINCH
303 signal(SIGWINCH, onwinch);
304 #endif
305 ovbeg();
306 bastate = VISUAL;
307 c = 0;
308 if (any(peekchar(), "+-^."))
309 c = getchar();
310 pastwh();
311 vsetsiz(isdigit(peekchar()) ? getnum() : value(WINDOW));
312 setwind();
313 newline();
314 vok(atube);
315 if (!inglobal)
316 savevis();
317 Outchar = vputchar;
318 vmoving = 0;
319 f = ostart();
320 if (initev == 0) {
321 vcontext(dot, c);
322 vnline(NOSTR);
323 }
324 vmain();
325 Command = "visual";
326 ovend(f);
327 #ifdef SIGWINCH
328 signal(SIGWINCH, SIG_DFL);
329 #endif
330 }
331
332 /*
333 * Hack to allow entry to visual with
334 * empty buffer since routines internally
335 * demand at least one line.
336 */
337 void
fixzero(void)338 fixzero(void)
339 {
340
341 if (dol == zero) {
342 register bool ochng = chng;
343
344 vdoappend("");
345 if (!ochng)
346 synced();
347 fixedzero++;
348 addr1 = addr2 = one;
349 } else if (addr2 == zero)
350 addr2 = one;
351 }
352
353 /*
354 * Save lines before visual between unddol and truedol.
355 * Accomplish this by throwing away current [unddol,truedol]
356 * and then saving all the lines in the buffer and moving
357 * unddol back to dol. Don't do this if in a global.
358 *
359 * If you do
360 * g/xxx/vi.
361 * and then do a
362 * :e xxxx
363 * at some point, and then quit from the visual and undo
364 * you get the old file back. Somewhat weird.
365 */
366 void
savevis(void)367 savevis(void)
368 {
369
370 if (inglobal)
371 return;
372 truedol = unddol;
373 saveall();
374 unddol = dol;
375 undkind = UNDNONE;
376 }
377
378 /*
379 * Restore a sensible state after a visual/open, moving the saved
380 * stuff back to [unddol,dol], and killing the partial line kill indicators.
381 */
382 void
undvis(void)383 undvis(void)
384 {
385
386 if (ruptible)
387 signal(SIGINT, onintr);
388 squish();
389 pkill[0] = pkill[1] = 0;
390 unddol = truedol;
391 unddel = zero;
392 undap1 = one;
393 undap2 = dol + 1;
394 undkind = UNDALL;
395 if (undadot <= zero || undadot > dol)
396 undadot = zero+1;
397 }
398
399 /*
400 * Set the window parameters based on the base state bastate
401 * and the available buffer space.
402 */
403 void
setwind(void)404 setwind(void)
405 {
406
407 WCOLS = TCOLUMNS;
408 switch (bastate) {
409
410 case ONEOPEN:
411 if (AM)
412 WCOLS--;
413 /* fall into ... */
414
415 case HARDOPEN:
416 basWTOP = WTOP = WBOT = WECHO = 0;
417 ZERO = 0;
418 holdcm++;
419 break;
420
421 case CRTOPEN:
422 basWTOP = TLINES - 2;
423 /* fall into */
424
425 case VISUAL:
426 ZERO = TLINES - TUBESIZE / WCOLS;
427 if (ZERO < 0)
428 ZERO = 0;
429 if (ZERO > basWTOP)
430 error(catgets(catd, 1, 215,
431 "Screen too large for internal buffer"));
432 WTOP = basWTOP; WBOT = TLINES - 2; WECHO = TLINES - 1;
433 break;
434 }
435 state = bastate;
436 basWLINES = WLINES = WBOT - WTOP + 1;
437 }
438
439 /*
440 * Can we hack an open/visual on this terminal?
441 * If so, then divide the screen buffer up into lines,
442 * and initialize a bunch of state variables before we start.
443 */
444 void
vok(register cell * atube)445 vok(register cell *atube)
446 {
447 register int i;
448
449 if (WCOLS == 1000)
450 serror(catgets(catd, 1, 216,
451 "Don't know enough about your terminal to use %s"), Command);
452 if (WCOLS > TUBECOLS)
453 error(catgets(catd, 1, 217, "Terminal too wide"));
454 if (WLINES >= TUBELINES || WCOLS * (WECHO - ZERO + 1) > TUBESIZE)
455 error(catgets(catd, 1, 218, "Screen too large"));
456
457 vtube0 = atube;
458 vclrcell(atube, WCOLS * (WECHO - ZERO + 1));
459 for (i = 0; i < ZERO; i++)
460 vtube[i] = (cell *) 0;
461 for (; i <= WECHO; i++)
462 vtube[i] = atube, atube += WCOLS;
463 for (; i < TUBELINES; i++)
464 vtube[i] = (cell *) 0;
465 vutmp = (char *)atube;
466 vundkind = VNONE;
467 vUNDdot = 0;
468 OCOLUMNS = TCOLUMNS;
469 inopen = 1;
470 signal(SIGINT, vintr);
471 vmoving = 0;
472 splitw = 0;
473 doomed = 0;
474 holdupd = 0;
475 Peekkey = 0;
476 vcnt = vcline = 0;
477 if (vSCROLL == 0)
478 vSCROLL = value(SCROLL);
479 /*old vSCROLL = (value(WINDOW)+1)/2;*//* round up so dft=6,11 */
480 }
481
482 void
vintr(int signum)483 vintr(int signum)
484 {
485 extern JMP_BUF readbuf;
486 extern int doingread;
487
488 signal(SIGINT, vintr);
489 if (vcatch)
490 onintr(SIGINT);
491 ungetkey(ATTN);
492 draino();
493 if (doingread) {
494 doingread = 0;
495 LONGJMP(readbuf, 1);
496 }
497 }
498
499 /*
500 * Set the size of the screen to size lines, to take effect the
501 * next time the screen is redrawn.
502 */
503 void
vsetsiz(int size)504 vsetsiz(int size)
505 {
506 register int b;
507
508 if (bastate != VISUAL)
509 return;
510 b = TLINES - 1 - size;
511 if (b >= TLINES - 1)
512 b = TLINES - 2;
513 if (b < 0)
514 b = 0;
515 basWTOP = b;
516 basWLINES = WBOT - b + 1;
517 }
518
519 #ifdef SIGWINCH
520 void
onwinch(int signum)521 onwinch(int signum)
522 {
523 vsave();
524 setty(normf);
525 LONGJMP(venv, 1);
526 }
527 #endif
528