xref: /titanic_51/usr/src/cmd/vi/port/ex_v.c (revision f6db9f272f0061301cfaa1c0001b7d636eae31f4)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*f6db9f27Scf46844  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include "ex.h"
367c478bd9Sstevel@tonic-gate #include "ex_re.h"
377c478bd9Sstevel@tonic-gate #include "ex_tty.h"
387c478bd9Sstevel@tonic-gate #include "ex_vis.h"
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /*
417c478bd9Sstevel@tonic-gate  * Entry points to open and visual from command mode processor.
427c478bd9Sstevel@tonic-gate  * The open/visual code breaks down roughly as follows:
437c478bd9Sstevel@tonic-gate  *
447c478bd9Sstevel@tonic-gate  * ex_v.c	entry points, checking of terminal characteristics
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  * ex_vadj.c	logical screen control, use of intelligent operations
477c478bd9Sstevel@tonic-gate  *		insert/delete line and coordination with screen image;
487c478bd9Sstevel@tonic-gate  *		updating of screen after changes.
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  * ex_vget.c	input of single keys and reading of input lines
517c478bd9Sstevel@tonic-gate  *		from the echo area, handling of \ escapes on input for
527c478bd9Sstevel@tonic-gate  *		uppercase only terminals, handling of memory for repeated
537c478bd9Sstevel@tonic-gate  *		commands and small saved texts from inserts and partline
547c478bd9Sstevel@tonic-gate  *		deletes, notification of multi line changes in the echo
557c478bd9Sstevel@tonic-gate  *		area.
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * ex_vmain.c	main command decoding, some command processing.
587c478bd9Sstevel@tonic-gate  *
597c478bd9Sstevel@tonic-gate  * ex_voperate.c   decoding of operator/operand sequences and
607c478bd9Sstevel@tonic-gate  *		contextual scans, implementation of word motions.
617c478bd9Sstevel@tonic-gate  *
627c478bd9Sstevel@tonic-gate  * ex_vops.c	major operator interfaces, undos, motions, deletes,
637c478bd9Sstevel@tonic-gate  *		changes, opening new lines, shifts, replacements and yanks
647c478bd9Sstevel@tonic-gate  *		coordinating logical and physical changes.
657c478bd9Sstevel@tonic-gate  *
667c478bd9Sstevel@tonic-gate  * ex_vops2.c	subroutines for operator interfaces in ex_vops.c,
677c478bd9Sstevel@tonic-gate  *		insert mode, read input line processing at lowest level.
687c478bd9Sstevel@tonic-gate  *
697c478bd9Sstevel@tonic-gate  * ex_vops3.c	structured motion definitions of ( ) { } and [ ] operators,
707c478bd9Sstevel@tonic-gate  *		indent for lisp routines, () and {} balancing.
717c478bd9Sstevel@tonic-gate  *
727c478bd9Sstevel@tonic-gate  * ex_vput.c	output routines, clearing, physical mapping of logical cursor
737c478bd9Sstevel@tonic-gate  *		positioning, cursor motions, handling of insert character
747c478bd9Sstevel@tonic-gate  *		and delete character functions of intelligent and unintelligent
757c478bd9Sstevel@tonic-gate  *		terminals, visual mode tracing routines (for debugging),
767c478bd9Sstevel@tonic-gate  *		control of screen image and its updating.
777c478bd9Sstevel@tonic-gate  *
787c478bd9Sstevel@tonic-gate  * ex_vwind.c	window level control of display, forward and backward rolls,
797c478bd9Sstevel@tonic-gate  *		absolute motions, contextual displays, line depth determination
807c478bd9Sstevel@tonic-gate  */
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate void setsize();
837c478bd9Sstevel@tonic-gate void winch();
847c478bd9Sstevel@tonic-gate void vintr();
85*f6db9f27Scf46844 void ovend(ttymode);
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate wchar_t	atube[TUBESIZE];
887c478bd9Sstevel@tonic-gate jmp_buf	venv;
897c478bd9Sstevel@tonic-gate int windowchg;
907c478bd9Sstevel@tonic-gate int sigok;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /* reinitialize window size after SIGWINCH */
937c478bd9Sstevel@tonic-gate void windowinit()
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate 	windowchg = 0;
967c478bd9Sstevel@tonic-gate 	setsize();
977c478bd9Sstevel@tonic-gate 	if(value(vi_WINDOW) >= lines || options[vi_WINDOW].odefault == value(vi_WINDOW))
987c478bd9Sstevel@tonic-gate 		value(vi_WINDOW) = lines -1;
997c478bd9Sstevel@tonic-gate 	options[vi_WINDOW].odefault = lines - 1;
1007c478bd9Sstevel@tonic-gate 	if(options[vi_SCROLL].odefault == value(vi_SCROLL))
1017c478bd9Sstevel@tonic-gate 		value(vi_SCROLL) = value(vi_WINDOW)/2;
1027c478bd9Sstevel@tonic-gate 	options[vi_SCROLL].odefault = (lines - 1)/2;
1037c478bd9Sstevel@tonic-gate 	vsetsiz(value(vi_WINDOW));
1047c478bd9Sstevel@tonic-gate 	setwind();
1057c478bd9Sstevel@tonic-gate 	vok(atube, 1);
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate void redraw()
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate 	vsave();
1117c478bd9Sstevel@tonic-gate 	windowinit();
1127c478bd9Sstevel@tonic-gate 	vclear();
1137c478bd9Sstevel@tonic-gate 	vdirty(0, lines);
1147c478bd9Sstevel@tonic-gate 	if(state != VISUAL) {
1157c478bd9Sstevel@tonic-gate 		vclean();
1167c478bd9Sstevel@tonic-gate 		vmoveto(dot, cursor, 0);
1177c478bd9Sstevel@tonic-gate 	} else {
1187c478bd9Sstevel@tonic-gate 		vredraw(WTOP);
1197c478bd9Sstevel@tonic-gate 		vrepaint(cursor);
1207c478bd9Sstevel@tonic-gate 		vfixcurs();
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate }
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1257c478bd9Sstevel@tonic-gate void
1267c478bd9Sstevel@tonic-gate #ifdef __STDC__
1277c478bd9Sstevel@tonic-gate winch(int sig)
1287c478bd9Sstevel@tonic-gate #else
1297c478bd9Sstevel@tonic-gate winch(sig)
1307c478bd9Sstevel@tonic-gate int sig;
1317c478bd9Sstevel@tonic-gate #endif
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	struct winsize jwin;
134*f6db9f27Scf46844 	int l;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	if(ioctl(0, TIOCGWINSZ, &jwin) != -1) {
1377c478bd9Sstevel@tonic-gate #ifdef XPG4
1387c478bd9Sstevel@tonic-gate 		oldlines = jwin.ws_row;
1397c478bd9Sstevel@tonic-gate 		oldcolumns = jwin.ws_col;
1407c478bd9Sstevel@tonic-gate #endif /* XPG4 */
1417c478bd9Sstevel@tonic-gate 		if (sigok) {
1427c478bd9Sstevel@tonic-gate 			if (columns != jwin.ws_col || lines != jwin.ws_row)
1437c478bd9Sstevel@tonic-gate 			    redraw();
1447c478bd9Sstevel@tonic-gate 		}
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 	else
1477c478bd9Sstevel@tonic-gate 		windowchg++;
1487c478bd9Sstevel@tonic-gate 	(void)signal(SIGWINCH, winch);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate void
1527c478bd9Sstevel@tonic-gate setsize()
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate 	struct winsize jwin;
155*f6db9f27Scf46844 	int l;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	if(ioctl(0, TIOCGWINSZ, &jwin) != -1) {
1587c478bd9Sstevel@tonic-gate 		if (jwin.ws_col > 0)
1597c478bd9Sstevel@tonic-gate 			columns = jwin.ws_col;
1607c478bd9Sstevel@tonic-gate 		if (jwin.ws_row > 0)
1617c478bd9Sstevel@tonic-gate 			lines = jwin.ws_row;
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate #ifdef XPG4
1657c478bd9Sstevel@tonic-gate 	if (envlines != -1) {
1667c478bd9Sstevel@tonic-gate 		lines = envlines;
1677c478bd9Sstevel@tonic-gate 	}
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	if (envcolumns != -1) {
1707c478bd9Sstevel@tonic-gate 		columns = envcolumns;
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	if (envlines != -1 || envcolumns != -1) {
1747c478bd9Sstevel@tonic-gate 		jwin.ws_row = lines;
1757c478bd9Sstevel@tonic-gate 		jwin.ws_col = columns;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 		if (ioctl(0, TIOCSWINSZ, &jwin) == -1) {
1787c478bd9Sstevel@tonic-gate 			jwin.ws_row = oldlines;
1797c478bd9Sstevel@tonic-gate 			jwin.ws_col = oldcolumns;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 			ioctl(0, TIOCSWINSZ, &jwin);
1827c478bd9Sstevel@tonic-gate 		}
1837c478bd9Sstevel@tonic-gate 	}
1847c478bd9Sstevel@tonic-gate #endif /* XPG4 */
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	if (lines <= 1)
1877c478bd9Sstevel@tonic-gate 		lines = 24;
1887c478bd9Sstevel@tonic-gate 	l = lines;
1897c478bd9Sstevel@tonic-gate 	if (columns <= 4)
1907c478bd9Sstevel@tonic-gate 		columns = 1000;
1917c478bd9Sstevel@tonic-gate 	value(vi_WINDOW) = options[vi_WINDOW].odefault = l - 1;
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * Enter open mode
1967c478bd9Sstevel@tonic-gate  */
197*f6db9f27Scf46844 void
198*f6db9f27Scf46844 oop(void)
1997c478bd9Sstevel@tonic-gate {
200*f6db9f27Scf46844 	unsigned char *ic;
2017c478bd9Sstevel@tonic-gate 	ttymode f;	/* was register */
2027c478bd9Sstevel@tonic-gate 	int resize;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	windowchg = 0;
2057c478bd9Sstevel@tonic-gate 	(void)signal(SIGWINCH, winch);
2067c478bd9Sstevel@tonic-gate 	ovbeg();
2077c478bd9Sstevel@tonic-gate 	if (peekchar() == '/') {
2087c478bd9Sstevel@tonic-gate 		(void)vi_compile(getchar(), 1);
2097c478bd9Sstevel@tonic-gate 		savere(&scanre);
2107c478bd9Sstevel@tonic-gate 		if (execute(0, dot) == 0)
2117c478bd9Sstevel@tonic-gate 			error(value(vi_TERSE) ? gettext("Fail") :
2127c478bd9Sstevel@tonic-gate gettext("Pattern not found on addressed line"));
2137c478bd9Sstevel@tonic-gate 		ic = (unsigned char *)loc1;
2147c478bd9Sstevel@tonic-gate 		if (ic > linebuf && *ic == 0)
2157c478bd9Sstevel@tonic-gate 			ic--;
2167c478bd9Sstevel@tonic-gate 	} else {
2177c478bd9Sstevel@tonic-gate 		getDOT();
2187c478bd9Sstevel@tonic-gate 		ic = vskipwh(linebuf);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 	donewline();
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	/*
2237c478bd9Sstevel@tonic-gate 	 * If overstrike then have to HARDOPEN
2247c478bd9Sstevel@tonic-gate 	 * else if can move cursor up off current line can use CRTOPEN (~~vi1)
2257c478bd9Sstevel@tonic-gate 	 * otherwise have to use ONEOPEN (like adm3)
2267c478bd9Sstevel@tonic-gate 	 */
2277c478bd9Sstevel@tonic-gate 	if (over_strike && !erase_overstrike)
2287c478bd9Sstevel@tonic-gate 		bastate = HARDOPEN;
2297c478bd9Sstevel@tonic-gate 	else if (cursor_address || cursor_up)
2307c478bd9Sstevel@tonic-gate 		bastate = CRTOPEN;
2317c478bd9Sstevel@tonic-gate 	else
2327c478bd9Sstevel@tonic-gate 		bastate = ONEOPEN;
2337c478bd9Sstevel@tonic-gate 	setwind();
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	/*
2367c478bd9Sstevel@tonic-gate 	 * To avoid bombing on glass-crt's when the line is too long
2377c478bd9Sstevel@tonic-gate 	 * pretend that such terminals are 160 columns wide.
2387c478bd9Sstevel@tonic-gate 	 * If a line is too wide for display, we will dynamically
2397c478bd9Sstevel@tonic-gate 	 * switch to hardcopy open mode.
2407c478bd9Sstevel@tonic-gate 	 */
2417c478bd9Sstevel@tonic-gate 	if (state != CRTOPEN)
2427c478bd9Sstevel@tonic-gate 		WCOLS = TUBECOLS;
2437c478bd9Sstevel@tonic-gate 	if (!inglobal)
2447c478bd9Sstevel@tonic-gate 		savevis();
2457c478bd9Sstevel@tonic-gate 	vok(atube, 0);
2467c478bd9Sstevel@tonic-gate 	if (state != CRTOPEN)
2477c478bd9Sstevel@tonic-gate 		columns = WCOLS;
2487c478bd9Sstevel@tonic-gate 	Outchar = vputchar;
2497c478bd9Sstevel@tonic-gate 	f = ostart();
2507c478bd9Sstevel@tonic-gate 	if (state == CRTOPEN) {
2517c478bd9Sstevel@tonic-gate 		if (outcol == UKCOL)
2527c478bd9Sstevel@tonic-gate 			outcol = 0;
2537c478bd9Sstevel@tonic-gate 		vmoveitup(1, 1);
2547c478bd9Sstevel@tonic-gate 	} else
2557c478bd9Sstevel@tonic-gate 		outline = destline = WBOT;
2567c478bd9Sstevel@tonic-gate 	vshow(dot, NOLINE);
2577c478bd9Sstevel@tonic-gate 	vnline(ic);
2587c478bd9Sstevel@tonic-gate 	vmain();
2597c478bd9Sstevel@tonic-gate 	if (state != CRTOPEN)
2607c478bd9Sstevel@tonic-gate 		vclean();
2617c478bd9Sstevel@tonic-gate 	Command = (unsigned char *)"open";
2627c478bd9Sstevel@tonic-gate 	ovend(f);
2637c478bd9Sstevel@tonic-gate 	(void)signal(SIGWINCH, SIG_DFL);
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate 
266*f6db9f27Scf46844 void
267*f6db9f27Scf46844 ovbeg(void)
2687c478bd9Sstevel@tonic-gate {
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	if (inopen)
2717c478bd9Sstevel@tonic-gate 		error(gettext("Recursive open/visual not allowed"));
2727c478bd9Sstevel@tonic-gate 	Vlines = lineDOL();
2737c478bd9Sstevel@tonic-gate 	fixzero();
2747c478bd9Sstevel@tonic-gate 	setdot();
2757c478bd9Sstevel@tonic-gate 	pastwh();
2767c478bd9Sstevel@tonic-gate 	dot = addr2;
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate 
279*f6db9f27Scf46844 void
280*f6db9f27Scf46844 ovend(ttymode f)
2817c478bd9Sstevel@tonic-gate {
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	splitw++;
2847c478bd9Sstevel@tonic-gate 	vgoto(WECHO, 0);
2857c478bd9Sstevel@tonic-gate 	vclreol();
2867c478bd9Sstevel@tonic-gate 	vgoto(WECHO, 0);
2877c478bd9Sstevel@tonic-gate 	holdcm = 0;
2887c478bd9Sstevel@tonic-gate 	splitw = 0;
2897c478bd9Sstevel@tonic-gate 	ostop(f);
2907c478bd9Sstevel@tonic-gate 	setoutt();
2917c478bd9Sstevel@tonic-gate 	undvis();
2927c478bd9Sstevel@tonic-gate 	columns = OCOLUMNS;
2937c478bd9Sstevel@tonic-gate 	inopen = 0;
2947c478bd9Sstevel@tonic-gate 	flusho();
2957c478bd9Sstevel@tonic-gate 	netchHAD(Vlines);
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate  * Enter visual mode
3007c478bd9Sstevel@tonic-gate  */
301*f6db9f27Scf46844 void
302*f6db9f27Scf46844 vop(void)
3037c478bd9Sstevel@tonic-gate {
304*f6db9f27Scf46844 	int c;
3057c478bd9Sstevel@tonic-gate 	ttymode f;	/* was register */
3067c478bd9Sstevel@tonic-gate 	extern unsigned char termtype[];
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	if (!cursor_address && !cursor_up) {
3097c478bd9Sstevel@tonic-gate 		if (initev) {
3107c478bd9Sstevel@tonic-gate toopen:
3117c478bd9Sstevel@tonic-gate 			if (generic_type)
3127c478bd9Sstevel@tonic-gate 				merror(gettext("I don't know what kind of terminal you are on - all I have is '%s'."), termtype);
3137c478bd9Sstevel@tonic-gate 			putNFL();
3147c478bd9Sstevel@tonic-gate 			merror(gettext("[Using open mode]"));
3157c478bd9Sstevel@tonic-gate 			putNFL();
3167c478bd9Sstevel@tonic-gate 			oop();
3177c478bd9Sstevel@tonic-gate 			return;
3187c478bd9Sstevel@tonic-gate 		}
3197c478bd9Sstevel@tonic-gate 		error(gettext("Visual needs addressable cursor or upline capability"));
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate 	if (over_strike && !erase_overstrike) {
3227c478bd9Sstevel@tonic-gate 		if (initev)
3237c478bd9Sstevel@tonic-gate 			goto toopen;
3247c478bd9Sstevel@tonic-gate 		error(gettext("Can't use visual on a terminal which overstrikes"));
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate 	if (!clear_screen) {
3277c478bd9Sstevel@tonic-gate 		if (initev)
3287c478bd9Sstevel@tonic-gate 			goto toopen;
3297c478bd9Sstevel@tonic-gate 		error(gettext("Visual requires clear screen capability"));
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 	if (!scroll_forward) {
3327c478bd9Sstevel@tonic-gate 		if (initev)
3337c478bd9Sstevel@tonic-gate 			goto toopen;
3347c478bd9Sstevel@tonic-gate 		error(gettext("Visual requires scrolling"));
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 	windowchg = 0;
3377c478bd9Sstevel@tonic-gate 	(void)signal(SIGWINCH, winch);
3387c478bd9Sstevel@tonic-gate 	ovbeg();
3397c478bd9Sstevel@tonic-gate 	bastate = VISUAL;
3407c478bd9Sstevel@tonic-gate 	c = 0;
3417c478bd9Sstevel@tonic-gate 	if (any(peekchar(), "+-^."))
3427c478bd9Sstevel@tonic-gate 		c = getchar();
3437c478bd9Sstevel@tonic-gate 	pastwh();
3447c478bd9Sstevel@tonic-gate 	vsetsiz(isdigit(peekchar()) ? getnum() : value(vi_WINDOW));
3457c478bd9Sstevel@tonic-gate 	setwind();
3467c478bd9Sstevel@tonic-gate 	donewline();
3477c478bd9Sstevel@tonic-gate 	vok(atube, 0);
3487c478bd9Sstevel@tonic-gate 	if (!inglobal)
3497c478bd9Sstevel@tonic-gate 		savevis();
3507c478bd9Sstevel@tonic-gate 	Outchar = vputchar;
3517c478bd9Sstevel@tonic-gate 	vmoving = 0;
3527c478bd9Sstevel@tonic-gate 	f = ostart();
3537c478bd9Sstevel@tonic-gate 	if (initev == 0) {
3547c478bd9Sstevel@tonic-gate 		vcontext(dot, c);
355*f6db9f27Scf46844 		vnline((unsigned char *)NOSTR);
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 	vmain();
3587c478bd9Sstevel@tonic-gate 	Command = (unsigned char *)"visual";
3597c478bd9Sstevel@tonic-gate 	ovend(f);
3607c478bd9Sstevel@tonic-gate 	(void)signal(SIGWINCH, SIG_DFL);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate /*
3647c478bd9Sstevel@tonic-gate  * Hack to allow entry to visual with
3657c478bd9Sstevel@tonic-gate  * empty buffer since routines internally
3667c478bd9Sstevel@tonic-gate  * demand at least one line.
3677c478bd9Sstevel@tonic-gate  */
368*f6db9f27Scf46844 void
369*f6db9f27Scf46844 fixzero(void)
3707c478bd9Sstevel@tonic-gate {
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	if (dol == zero) {
373*f6db9f27Scf46844 		bool ochng = chng;
3747c478bd9Sstevel@tonic-gate 
375*f6db9f27Scf46844 		vdoappend((unsigned char *)"");
3767c478bd9Sstevel@tonic-gate 		if (!ochng)
3777c478bd9Sstevel@tonic-gate 			sync();
3787c478bd9Sstevel@tonic-gate 		addr1 = addr2 = one;
3797c478bd9Sstevel@tonic-gate 	} else if (addr2 == zero)
3807c478bd9Sstevel@tonic-gate 		addr2 = one;
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate /*
3847c478bd9Sstevel@tonic-gate  * Save lines before visual between unddol and truedol.
3857c478bd9Sstevel@tonic-gate  * Accomplish this by throwing away current [unddol,truedol]
3867c478bd9Sstevel@tonic-gate  * and then saving all the lines in the buffer and moving
3877c478bd9Sstevel@tonic-gate  * unddol back to dol.  Don't do this if in a global.
3887c478bd9Sstevel@tonic-gate  *
3897c478bd9Sstevel@tonic-gate  * If you do
3907c478bd9Sstevel@tonic-gate  *	g/xxx/vi.
3917c478bd9Sstevel@tonic-gate  * and then do a
3927c478bd9Sstevel@tonic-gate  *	:e xxxx
3937c478bd9Sstevel@tonic-gate  * at some point, and then quit from the visual and undo
3947c478bd9Sstevel@tonic-gate  * you get the old file back.  Somewhat weird.
3957c478bd9Sstevel@tonic-gate  */
396*f6db9f27Scf46844 void
397*f6db9f27Scf46844 savevis(void)
3987c478bd9Sstevel@tonic-gate {
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	if (inglobal)
4017c478bd9Sstevel@tonic-gate 		return;
4027c478bd9Sstevel@tonic-gate 	truedol = unddol;
4037c478bd9Sstevel@tonic-gate 	saveall();
4047c478bd9Sstevel@tonic-gate 	unddol = dol;
4057c478bd9Sstevel@tonic-gate 	undkind = UNDNONE;
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate /*
4097c478bd9Sstevel@tonic-gate  * Restore a sensible state after a visual/open, moving the saved
4107c478bd9Sstevel@tonic-gate  * stuff back to [unddol,dol], and killing the partial line kill indicators.
4117c478bd9Sstevel@tonic-gate  */
412*f6db9f27Scf46844 void
413*f6db9f27Scf46844 undvis(void)
4147c478bd9Sstevel@tonic-gate {
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	if (ruptible)
4177c478bd9Sstevel@tonic-gate 		signal(SIGINT, onintr);
4187c478bd9Sstevel@tonic-gate 	squish();
4197c478bd9Sstevel@tonic-gate 	pkill[0] = pkill[1] = 0;
4207c478bd9Sstevel@tonic-gate 	unddol = truedol;
4217c478bd9Sstevel@tonic-gate 	unddel = zero;
4227c478bd9Sstevel@tonic-gate 	undap1 = one;
4237c478bd9Sstevel@tonic-gate 	undap2 = dol + 1;
4247c478bd9Sstevel@tonic-gate 	undkind = UNDALL;
4257c478bd9Sstevel@tonic-gate 	if (undadot <= zero || undadot > dol)
4267c478bd9Sstevel@tonic-gate 		undadot = zero+1;
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate  * Set the window parameters based on the base state bastate
4317c478bd9Sstevel@tonic-gate  * and the available buffer space.
4327c478bd9Sstevel@tonic-gate  */
433*f6db9f27Scf46844 void
434*f6db9f27Scf46844 setwind(void)
4357c478bd9Sstevel@tonic-gate {
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	WCOLS = columns;
4387c478bd9Sstevel@tonic-gate 	switch (bastate) {
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	case ONEOPEN:
4417c478bd9Sstevel@tonic-gate 		if (auto_right_margin)
4427c478bd9Sstevel@tonic-gate 			WCOLS--;
4437c478bd9Sstevel@tonic-gate 		/* fall into ... */
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	case HARDOPEN:
4467c478bd9Sstevel@tonic-gate 		basWTOP = WTOP = WBOT = WECHO = 0;
4477c478bd9Sstevel@tonic-gate 		ZERO = 0;
4487c478bd9Sstevel@tonic-gate 		holdcm++;
4497c478bd9Sstevel@tonic-gate 		break;
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	case CRTOPEN:
4527c478bd9Sstevel@tonic-gate 		basWTOP = lines - 2;
4537c478bd9Sstevel@tonic-gate 		/* fall into */
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	case VISUAL:
4567c478bd9Sstevel@tonic-gate 		ZERO = lines - TUBESIZE / WCOLS;
4577c478bd9Sstevel@tonic-gate 		if (ZERO < 0)
4587c478bd9Sstevel@tonic-gate 			ZERO = 0;
4597c478bd9Sstevel@tonic-gate 		if (ZERO > basWTOP)
4607c478bd9Sstevel@tonic-gate 			error(gettext("Screen too large for internal buffer"));
4617c478bd9Sstevel@tonic-gate 		WTOP = basWTOP; WBOT = lines - 2; WECHO = lines - 1;
4627c478bd9Sstevel@tonic-gate 		break;
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 	state = bastate;
4657c478bd9Sstevel@tonic-gate 	basWLINES = WLINES = WBOT - WTOP + 1;
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate /*
4697c478bd9Sstevel@tonic-gate  * Can we hack an open/visual on this terminal?
4707c478bd9Sstevel@tonic-gate  * If so, then divide the screen buffer up into lines,
4717c478bd9Sstevel@tonic-gate  * and initialize a bunch of state variables before we start.
4727c478bd9Sstevel@tonic-gate  */
4737c478bd9Sstevel@tonic-gate static unsigned char vlinebuf[LBSIZE];
4747c478bd9Sstevel@tonic-gate 
475*f6db9f27Scf46844 void
476*f6db9f27Scf46844 vok(wchar_t *atube, int undo)
4777c478bd9Sstevel@tonic-gate {
478*f6db9f27Scf46844 	int i;
4797c478bd9Sstevel@tonic-gate 	static int beenhere;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	if (WCOLS == 1000)
482*f6db9f27Scf46844 		serror((unsigned char *)
483*f6db9f27Scf46844 		    gettext("Don't know enough about your terminal to use %s"),
4847c478bd9Sstevel@tonic-gate 		    Command);
4857c478bd9Sstevel@tonic-gate 	if (WCOLS > TUBECOLS)
4867c478bd9Sstevel@tonic-gate 		error(gettext("Terminal too wide"));
4877c478bd9Sstevel@tonic-gate 	if (WLINES >= TUBELINES || WCOLS * (WECHO - ZERO + 1) > TUBESIZE)
4887c478bd9Sstevel@tonic-gate 		error(gettext("Screen too large"));
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	vtube0 = atube;
4917c478bd9Sstevel@tonic-gate 	if(beenhere)
4927c478bd9Sstevel@tonic-gate 		vclrbyte(atube, WCOLS * (WECHO - ZERO + 1));
4937c478bd9Sstevel@tonic-gate 	for (i = 0; i < ZERO; i++)
4947c478bd9Sstevel@tonic-gate 		vtube[i] = (wchar_t *) 0;
4957c478bd9Sstevel@tonic-gate 	for (; i <= WECHO; i++)
4967c478bd9Sstevel@tonic-gate 		vtube[i] = atube, atube += WCOLS;
4977c478bd9Sstevel@tonic-gate 	if(beenhere++) {
4987c478bd9Sstevel@tonic-gate 		for (; i < TUBELINES; i++)
4997c478bd9Sstevel@tonic-gate 			vtube[i] = (wchar_t *) 0;
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 	vutmp = vlinebuf;
5027c478bd9Sstevel@tonic-gate 	if(!undo) {
5037c478bd9Sstevel@tonic-gate 		vundkind = VNONE;
5047c478bd9Sstevel@tonic-gate 		vUNDdot = 0;
5057c478bd9Sstevel@tonic-gate 	}
5067c478bd9Sstevel@tonic-gate 	OCOLUMNS = columns;
5077c478bd9Sstevel@tonic-gate 	inopen = 1;
5087c478bd9Sstevel@tonic-gate #ifdef CBREAK
5097c478bd9Sstevel@tonic-gate 	signal(SIGINT, vintr);
5107c478bd9Sstevel@tonic-gate #endif
5117c478bd9Sstevel@tonic-gate 	vmoving = 0;
5127c478bd9Sstevel@tonic-gate 	splitw = 0;
5137c478bd9Sstevel@tonic-gate 	doomed = 0;
5147c478bd9Sstevel@tonic-gate 	holdupd = 0;
5157c478bd9Sstevel@tonic-gate 	if(!undo)
5167c478bd9Sstevel@tonic-gate 		Peekkey = 0;
5177c478bd9Sstevel@tonic-gate 	vcnt = vcline = 0;
5187c478bd9Sstevel@tonic-gate 	if (vSCROLL == 0)
5197c478bd9Sstevel@tonic-gate 		vSCROLL = value(vi_SCROLL);
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate #ifdef CBREAK
5237c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5247c478bd9Sstevel@tonic-gate void
5257c478bd9Sstevel@tonic-gate #ifdef __STDC__
5267c478bd9Sstevel@tonic-gate vintr(int sig)
5277c478bd9Sstevel@tonic-gate #else
5287c478bd9Sstevel@tonic-gate vintr(sig)
5297c478bd9Sstevel@tonic-gate int sig;
5307c478bd9Sstevel@tonic-gate #endif
5317c478bd9Sstevel@tonic-gate {
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	signal(SIGINT, vintr);
5347c478bd9Sstevel@tonic-gate 	if (vcatch)
5357c478bd9Sstevel@tonic-gate 		onintr(0);
5367c478bd9Sstevel@tonic-gate 	ungetkey(ATTN);
5377c478bd9Sstevel@tonic-gate 	draino();
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate #endif
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate /*
5427c478bd9Sstevel@tonic-gate  * Set the size of the screen to size lines, to take effect the
5437c478bd9Sstevel@tonic-gate  * next time the screen is redrawn.
5447c478bd9Sstevel@tonic-gate  */
545*f6db9f27Scf46844 void
546*f6db9f27Scf46844 vsetsiz(int size)
5477c478bd9Sstevel@tonic-gate {
548*f6db9f27Scf46844 	int b;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	if (bastate != VISUAL)
5517c478bd9Sstevel@tonic-gate 		return;
5527c478bd9Sstevel@tonic-gate 	b = lines - 1 - size;
5537c478bd9Sstevel@tonic-gate 	if (b >= lines - 1)
5547c478bd9Sstevel@tonic-gate 		b = lines - 2;
5557c478bd9Sstevel@tonic-gate 	if (b < 0)
5567c478bd9Sstevel@tonic-gate 		b = 0;
5577c478bd9Sstevel@tonic-gate 	basWTOP = b;
5587c478bd9Sstevel@tonic-gate 	basWLINES = WBOT - b + 1;
5597c478bd9Sstevel@tonic-gate }
560