8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / cmd / vi / port / ex_v.c
blobc93a59ea7e8e62661d4453b0c6acbbf595cac54f
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 /* Copyright (c) 1981 Regents of the University of California */
33 #pragma ident "%Z%%M% %I% %E% SMI"
35 #include "ex.h"
36 #include "ex_re.h"
37 #include "ex_tty.h"
38 #include "ex_vis.h"
41 * Entry points to open and visual from command mode processor.
42 * The open/visual code breaks down roughly as follows:
44 * ex_v.c entry points, checking of terminal characteristics
46 * ex_vadj.c logical screen control, use of intelligent operations
47 * insert/delete line and coordination with screen image;
48 * updating of screen after changes.
50 * ex_vget.c input of single keys and reading of input lines
51 * from the echo area, handling of \ escapes on input for
52 * uppercase only terminals, handling of memory for repeated
53 * commands and small saved texts from inserts and partline
54 * deletes, notification of multi line changes in the echo
55 * area.
57 * ex_vmain.c main command decoding, some command processing.
59 * ex_voperate.c decoding of operator/operand sequences and
60 * contextual scans, implementation of word motions.
62 * ex_vops.c major operator interfaces, undos, motions, deletes,
63 * changes, opening new lines, shifts, replacements and yanks
64 * coordinating logical and physical changes.
66 * ex_vops2.c subroutines for operator interfaces in ex_vops.c,
67 * insert mode, read input line processing at lowest level.
69 * ex_vops3.c structured motion definitions of ( ) { } and [ ] operators,
70 * indent for lisp routines, () and {} balancing.
72 * ex_vput.c output routines, clearing, physical mapping of logical cursor
73 * positioning, cursor motions, handling of insert character
74 * and delete character functions of intelligent and unintelligent
75 * terminals, visual mode tracing routines (for debugging),
76 * control of screen image and its updating.
78 * ex_vwind.c window level control of display, forward and backward rolls,
79 * absolute motions, contextual displays, line depth determination
82 void setsize();
83 void winch();
84 void vintr();
85 void ovend(ttymode);
87 wchar_t atube[TUBESIZE];
88 jmp_buf venv;
89 int windowchg;
90 int sigok;
92 /* reinitialize window size after SIGWINCH */
93 void windowinit()
95 windowchg = 0;
96 setsize();
97 if(value(vi_WINDOW) >= lines || options[vi_WINDOW].odefault == value(vi_WINDOW))
98 value(vi_WINDOW) = lines -1;
99 options[vi_WINDOW].odefault = lines - 1;
100 if(options[vi_SCROLL].odefault == value(vi_SCROLL))
101 value(vi_SCROLL) = value(vi_WINDOW)/2;
102 options[vi_SCROLL].odefault = (lines - 1)/2;
103 vsetsiz(value(vi_WINDOW));
104 setwind();
105 vok(atube, 1);
108 void redraw()
110 vsave();
111 windowinit();
112 vclear();
113 vdirty(0, lines);
114 if(state != VISUAL) {
115 vclean();
116 vmoveto(dot, cursor, 0);
117 } else {
118 vredraw(WTOP);
119 vrepaint(cursor);
120 vfixcurs();
124 /*ARGSUSED*/
125 void
126 #ifdef __STDC__
127 winch(int sig)
128 #else
129 winch(sig)
130 int sig;
131 #endif
133 struct winsize jwin;
134 int l;
136 if(ioctl(0, TIOCGWINSZ, &jwin) != -1) {
137 #ifdef XPG4
138 oldlines = jwin.ws_row;
139 oldcolumns = jwin.ws_col;
140 #endif /* XPG4 */
141 if (sigok) {
142 if (columns != jwin.ws_col || lines != jwin.ws_row)
143 redraw();
146 else
147 windowchg++;
148 (void)signal(SIGWINCH, winch);
151 void
152 setsize()
154 struct winsize jwin;
155 int l;
157 if(ioctl(0, TIOCGWINSZ, &jwin) != -1) {
158 if (jwin.ws_col > 0)
159 columns = jwin.ws_col;
160 if (jwin.ws_row > 0)
161 lines = jwin.ws_row;
164 #ifdef XPG4
165 if (envlines != -1) {
166 lines = envlines;
169 if (envcolumns != -1) {
170 columns = envcolumns;
173 if (envlines != -1 || envcolumns != -1) {
174 jwin.ws_row = lines;
175 jwin.ws_col = columns;
177 if (ioctl(0, TIOCSWINSZ, &jwin) == -1) {
178 jwin.ws_row = oldlines;
179 jwin.ws_col = oldcolumns;
181 ioctl(0, TIOCSWINSZ, &jwin);
184 #endif /* XPG4 */
186 if (lines <= 1)
187 lines = 24;
188 l = lines;
189 if (columns <= 4)
190 columns = 1000;
191 value(vi_WINDOW) = options[vi_WINDOW].odefault = l - 1;
195 * Enter open mode
197 void
198 oop(void)
200 unsigned char *ic;
201 ttymode f; /* was register */
202 int resize;
204 windowchg = 0;
205 (void)signal(SIGWINCH, winch);
206 ovbeg();
207 if (peekchar() == '/') {
208 (void)vi_compile(getchar(), 1);
209 savere(&scanre);
210 if (execute(0, dot) == 0)
211 error(value(vi_TERSE) ? gettext("Fail") :
212 gettext("Pattern not found on addressed line"));
213 ic = (unsigned char *)loc1;
214 if (ic > linebuf && *ic == 0)
215 ic--;
216 } else {
217 getDOT();
218 ic = vskipwh(linebuf);
220 donewline();
223 * If overstrike then have to HARDOPEN
224 * else if can move cursor up off current line can use CRTOPEN (~~vi1)
225 * otherwise have to use ONEOPEN (like adm3)
227 if (over_strike && !erase_overstrike)
228 bastate = HARDOPEN;
229 else if (cursor_address || cursor_up)
230 bastate = CRTOPEN;
231 else
232 bastate = ONEOPEN;
233 setwind();
236 * To avoid bombing on glass-crt's when the line is too long
237 * pretend that such terminals are 160 columns wide.
238 * If a line is too wide for display, we will dynamically
239 * switch to hardcopy open mode.
241 if (state != CRTOPEN)
242 WCOLS = TUBECOLS;
243 if (!inglobal)
244 savevis();
245 vok(atube, 0);
246 if (state != CRTOPEN)
247 columns = WCOLS;
248 Outchar = vputchar;
249 f = ostart();
250 if (state == CRTOPEN) {
251 if (outcol == UKCOL)
252 outcol = 0;
253 vmoveitup(1, 1);
254 } else
255 outline = destline = WBOT;
256 vshow(dot, NOLINE);
257 vnline(ic);
258 vmain();
259 if (state != CRTOPEN)
260 vclean();
261 Command = (unsigned char *)"open";
262 ovend(f);
263 (void)signal(SIGWINCH, SIG_DFL);
266 void
267 ovbeg(void)
270 if (inopen)
271 error(gettext("Recursive open/visual not allowed"));
272 Vlines = lineDOL();
273 fixzero();
274 setdot();
275 pastwh();
276 dot = addr2;
279 void
280 ovend(ttymode f)
283 splitw++;
284 vgoto(WECHO, 0);
285 vclreol();
286 vgoto(WECHO, 0);
287 holdcm = 0;
288 splitw = 0;
289 ostop(f);
290 setoutt();
291 undvis();
292 columns = OCOLUMNS;
293 inopen = 0;
294 flusho();
295 netchHAD(Vlines);
299 * Enter visual mode
301 void
302 vop(void)
304 int c;
305 ttymode f; /* was register */
306 extern unsigned char termtype[];
308 if (!cursor_address && !cursor_up) {
309 if (initev) {
310 toopen:
311 if (generic_type)
312 merror(gettext("I don't know what kind of terminal you are on - all I have is '%s'."), termtype);
313 putNFL();
314 merror(gettext("[Using open mode]"));
315 putNFL();
316 oop();
317 return;
319 error(gettext("Visual needs addressable cursor or upline capability"));
321 if (over_strike && !erase_overstrike) {
322 if (initev)
323 goto toopen;
324 error(gettext("Can't use visual on a terminal which overstrikes"));
326 if (!clear_screen) {
327 if (initev)
328 goto toopen;
329 error(gettext("Visual requires clear screen capability"));
331 if (!scroll_forward) {
332 if (initev)
333 goto toopen;
334 error(gettext("Visual requires scrolling"));
336 windowchg = 0;
337 (void)signal(SIGWINCH, winch);
338 ovbeg();
339 bastate = VISUAL;
340 c = 0;
341 if (any(peekchar(), "+-^."))
342 c = getchar();
343 pastwh();
344 vsetsiz(isdigit(peekchar()) ? getnum() : value(vi_WINDOW));
345 setwind();
346 donewline();
347 vok(atube, 0);
348 if (!inglobal)
349 savevis();
350 Outchar = vputchar;
351 vmoving = 0;
352 f = ostart();
353 if (initev == 0) {
354 vcontext(dot, c);
355 vnline((unsigned char *)NOSTR);
357 vmain();
358 Command = (unsigned char *)"visual";
359 ovend(f);
360 (void)signal(SIGWINCH, SIG_DFL);
364 * Hack to allow entry to visual with
365 * empty buffer since routines internally
366 * demand at least one line.
368 void
369 fixzero(void)
372 if (dol == zero) {
373 bool ochng = chng;
375 vdoappend((unsigned char *)"");
376 if (!ochng)
377 sync();
378 addr1 = addr2 = one;
379 } else if (addr2 == zero)
380 addr2 = one;
384 * Save lines before visual between unddol and truedol.
385 * Accomplish this by throwing away current [unddol,truedol]
386 * and then saving all the lines in the buffer and moving
387 * unddol back to dol. Don't do this if in a global.
389 * If you do
390 * g/xxx/vi.
391 * and then do a
392 * :e xxxx
393 * at some point, and then quit from the visual and undo
394 * you get the old file back. Somewhat weird.
396 void
397 savevis(void)
400 if (inglobal)
401 return;
402 truedol = unddol;
403 saveall();
404 unddol = dol;
405 undkind = UNDNONE;
409 * Restore a sensible state after a visual/open, moving the saved
410 * stuff back to [unddol,dol], and killing the partial line kill indicators.
412 void
413 undvis(void)
416 if (ruptible)
417 signal(SIGINT, onintr);
418 squish();
419 pkill[0] = pkill[1] = 0;
420 unddol = truedol;
421 unddel = zero;
422 undap1 = one;
423 undap2 = dol + 1;
424 undkind = UNDALL;
425 if (undadot <= zero || undadot > dol)
426 undadot = zero+1;
430 * Set the window parameters based on the base state bastate
431 * and the available buffer space.
433 void
434 setwind(void)
437 WCOLS = columns;
438 switch (bastate) {
440 case ONEOPEN:
441 if (auto_right_margin)
442 WCOLS--;
443 /* fall into ... */
445 case HARDOPEN:
446 basWTOP = WTOP = WBOT = WECHO = 0;
447 ZERO = 0;
448 holdcm++;
449 break;
451 case CRTOPEN:
452 basWTOP = lines - 2;
453 /* fall into */
455 case VISUAL:
456 ZERO = lines - TUBESIZE / WCOLS;
457 if (ZERO < 0)
458 ZERO = 0;
459 if (ZERO > basWTOP)
460 error(gettext("Screen too large for internal buffer"));
461 WTOP = basWTOP; WBOT = lines - 2; WECHO = lines - 1;
462 break;
464 state = bastate;
465 basWLINES = WLINES = WBOT - WTOP + 1;
469 * Can we hack an open/visual on this terminal?
470 * If so, then divide the screen buffer up into lines,
471 * and initialize a bunch of state variables before we start.
473 static unsigned char vlinebuf[LBSIZE];
475 void
476 vok(wchar_t *atube, int undo)
478 int i;
479 static int beenhere;
481 if (WCOLS == 1000)
482 serror((unsigned char *)
483 gettext("Don't know enough about your terminal to use %s"),
484 Command);
485 if (WCOLS > TUBECOLS)
486 error(gettext("Terminal too wide"));
487 if (WLINES >= TUBELINES || WCOLS * (WECHO - ZERO + 1) > TUBESIZE)
488 error(gettext("Screen too large"));
490 vtube0 = atube;
491 if(beenhere)
492 vclrbyte(atube, WCOLS * (WECHO - ZERO + 1));
493 for (i = 0; i < ZERO; i++)
494 vtube[i] = (wchar_t *) 0;
495 for (; i <= WECHO; i++)
496 vtube[i] = atube, atube += WCOLS;
497 if(beenhere++) {
498 for (; i < TUBELINES; i++)
499 vtube[i] = (wchar_t *) 0;
501 vutmp = vlinebuf;
502 if(!undo) {
503 vundkind = VNONE;
504 vUNDdot = 0;
506 OCOLUMNS = columns;
507 inopen = 1;
508 #ifdef CBREAK
509 signal(SIGINT, vintr);
510 #endif
511 vmoving = 0;
512 splitw = 0;
513 doomed = 0;
514 holdupd = 0;
515 if(!undo)
516 Peekkey = 0;
517 vcnt = vcline = 0;
518 if (vSCROLL == 0)
519 vSCROLL = value(vi_SCROLL);
522 #ifdef CBREAK
523 /*ARGSUSED*/
524 void
525 #ifdef __STDC__
526 vintr(int sig)
527 #else
528 vintr(sig)
529 int sig;
530 #endif
533 signal(SIGINT, vintr);
534 if (vcatch)
535 onintr(0);
536 ungetkey(ATTN);
537 draino();
539 #endif
542 * Set the size of the screen to size lines, to take effect the
543 * next time the screen is redrawn.
545 void
546 vsetsiz(int size)
548 int b;
550 if (bastate != VISUAL)
551 return;
552 b = lines - 1 - size;
553 if (b >= lines - 1)
554 b = lines - 2;
555 if (b < 0)
556 b = 0;
557 basWTOP = b;
558 basWLINES = WBOT - b + 1;