xref: /illumos-gate/usr/src/cmd/vi/port/ex_v.c (revision 55fea89d)
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 /*
23f6db9f27Scf  * 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 #include "ex.h"
347c478bd9Sstevel@tonic-gate #include "ex_re.h"
357c478bd9Sstevel@tonic-gate #include "ex_tty.h"
367c478bd9Sstevel@tonic-gate #include "ex_vis.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * Entry points to open and visual from command mode processor.
407c478bd9Sstevel@tonic-gate  * The open/visual code breaks down roughly as follows:
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * ex_v.c	entry points, checking of terminal characteristics
437c478bd9Sstevel@tonic-gate  *
447c478bd9Sstevel@tonic-gate  * ex_vadj.c	logical screen control, use of intelligent operations
457c478bd9Sstevel@tonic-gate  *		insert/delete line and coordination with screen image;
467c478bd9Sstevel@tonic-gate  *		updating of screen after changes.
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  * ex_vget.c	input of single keys and reading of input lines
497c478bd9Sstevel@tonic-gate  *		from the echo area, handling of \ escapes on input for
507c478bd9Sstevel@tonic-gate  *		uppercase only terminals, handling of memory for repeated
517c478bd9Sstevel@tonic-gate  *		commands and small saved texts from inserts and partline
527c478bd9Sstevel@tonic-gate  *		deletes, notification of multi line changes in the echo
537c478bd9Sstevel@tonic-gate  *		area.
547c478bd9Sstevel@tonic-gate  *
557c478bd9Sstevel@tonic-gate  * ex_vmain.c	main command decoding, some command processing.
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * ex_voperate.c   decoding of operator/operand sequences and
587c478bd9Sstevel@tonic-gate  *		contextual scans, implementation of word motions.
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  * ex_vops.c	major operator interfaces, undos, motions, deletes,
617c478bd9Sstevel@tonic-gate  *		changes, opening new lines, shifts, replacements and yanks
627c478bd9Sstevel@tonic-gate  *		coordinating logical and physical changes.
637c478bd9Sstevel@tonic-gate  *
647c478bd9Sstevel@tonic-gate  * ex_vops2.c	subroutines for operator interfaces in ex_vops.c,
657c478bd9Sstevel@tonic-gate  *		insert mode, read input line processing at lowest level.
667c478bd9Sstevel@tonic-gate  *
677c478bd9Sstevel@tonic-gate  * ex_vops3.c	structured motion definitions of ( ) { } and [ ] operators,
68*55fea89dSDan Cross  *		indent for lisp routines, () and {} balancing.
697c478bd9Sstevel@tonic-gate  *
707c478bd9Sstevel@tonic-gate  * ex_vput.c	output routines, clearing, physical mapping of logical cursor
717c478bd9Sstevel@tonic-gate  *		positioning, cursor motions, handling of insert character
727c478bd9Sstevel@tonic-gate  *		and delete character functions of intelligent and unintelligent
737c478bd9Sstevel@tonic-gate  *		terminals, visual mode tracing routines (for debugging),
747c478bd9Sstevel@tonic-gate  *		control of screen image and its updating.
757c478bd9Sstevel@tonic-gate  *
767c478bd9Sstevel@tonic-gate  * ex_vwind.c	window level control of display, forward and backward rolls,
777c478bd9Sstevel@tonic-gate  *		absolute motions, contextual displays, line depth determination
787c478bd9Sstevel@tonic-gate  */
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate void setsize();
817c478bd9Sstevel@tonic-gate void winch();
827c478bd9Sstevel@tonic-gate void vintr();
83f6db9f27Scf void ovend(ttymode);
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate wchar_t	atube[TUBESIZE];
867c478bd9Sstevel@tonic-gate jmp_buf	venv;
877c478bd9Sstevel@tonic-gate int windowchg;
887c478bd9Sstevel@tonic-gate int sigok;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate /* reinitialize window size after SIGWINCH */
windowinit()917c478bd9Sstevel@tonic-gate void windowinit()
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate 	windowchg = 0;
947c478bd9Sstevel@tonic-gate 	setsize();
957c478bd9Sstevel@tonic-gate 	if(value(vi_WINDOW) >= lines || options[vi_WINDOW].odefault == value(vi_WINDOW))
967c478bd9Sstevel@tonic-gate 		value(vi_WINDOW) = lines -1;
977c478bd9Sstevel@tonic-gate 	options[vi_WINDOW].odefault = lines - 1;
987c478bd9Sstevel@tonic-gate 	if(options[vi_SCROLL].odefault == value(vi_SCROLL))
997c478bd9Sstevel@tonic-gate 		value(vi_SCROLL) = value(vi_WINDOW)/2;
1007c478bd9Sstevel@tonic-gate 	options[vi_SCROLL].odefault = (lines - 1)/2;
1017c478bd9Sstevel@tonic-gate 	vsetsiz(value(vi_WINDOW));
1027c478bd9Sstevel@tonic-gate 	setwind();
1037c478bd9Sstevel@tonic-gate 	vok(atube, 1);
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
redraw()1067c478bd9Sstevel@tonic-gate void redraw()
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	vsave();
1097c478bd9Sstevel@tonic-gate 	windowinit();
1107c478bd9Sstevel@tonic-gate 	vclear();
1117c478bd9Sstevel@tonic-gate 	vdirty(0, lines);
1127c478bd9Sstevel@tonic-gate 	if(state != VISUAL) {
1137c478bd9Sstevel@tonic-gate 		vclean();
1147c478bd9Sstevel@tonic-gate 		vmoveto(dot, cursor, 0);
1157c478bd9Sstevel@tonic-gate 	} else {
1167c478bd9Sstevel@tonic-gate 		vredraw(WTOP);
1177c478bd9Sstevel@tonic-gate 		vrepaint(cursor);
1187c478bd9Sstevel@tonic-gate 		vfixcurs();
1197c478bd9Sstevel@tonic-gate 	}
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate /*ARGSUSED*/
123*55fea89dSDan Cross void
1247c478bd9Sstevel@tonic-gate #ifdef __STDC__
winch(int sig)1257c478bd9Sstevel@tonic-gate winch(int sig)
1267c478bd9Sstevel@tonic-gate #else
1277c478bd9Sstevel@tonic-gate winch(sig)
1287c478bd9Sstevel@tonic-gate int sig;
1297c478bd9Sstevel@tonic-gate #endif
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate 	struct winsize jwin;
132f6db9f27Scf 	int l;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	if(ioctl(0, TIOCGWINSZ, &jwin) != -1) {
1357c478bd9Sstevel@tonic-gate #ifdef XPG4
1367c478bd9Sstevel@tonic-gate 		oldlines = jwin.ws_row;
1377c478bd9Sstevel@tonic-gate 		oldcolumns = jwin.ws_col;
1387c478bd9Sstevel@tonic-gate #endif /* XPG4 */
1397c478bd9Sstevel@tonic-gate 		if (sigok) {
1407c478bd9Sstevel@tonic-gate 			if (columns != jwin.ws_col || lines != jwin.ws_row)
1417c478bd9Sstevel@tonic-gate 			    redraw();
1427c478bd9Sstevel@tonic-gate 		}
143*55fea89dSDan Cross 	}
1447c478bd9Sstevel@tonic-gate 	else
1457c478bd9Sstevel@tonic-gate 		windowchg++;
1467c478bd9Sstevel@tonic-gate 	(void)signal(SIGWINCH, winch);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
149*55fea89dSDan Cross void
setsize()1507c478bd9Sstevel@tonic-gate setsize()
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate 	struct winsize jwin;
153f6db9f27Scf 	int l;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	if(ioctl(0, TIOCGWINSZ, &jwin) != -1) {
1567c478bd9Sstevel@tonic-gate 		if (jwin.ws_col > 0)
1577c478bd9Sstevel@tonic-gate 			columns = jwin.ws_col;
1587c478bd9Sstevel@tonic-gate 		if (jwin.ws_row > 0)
1597c478bd9Sstevel@tonic-gate 			lines = jwin.ws_row;
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate #ifdef XPG4
1637c478bd9Sstevel@tonic-gate 	if (envlines != -1) {
1647c478bd9Sstevel@tonic-gate 		lines = envlines;
1657c478bd9Sstevel@tonic-gate 	}
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	if (envcolumns != -1) {
1687c478bd9Sstevel@tonic-gate 		columns = envcolumns;
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	if (envlines != -1 || envcolumns != -1) {
1727c478bd9Sstevel@tonic-gate 		jwin.ws_row = lines;
1737c478bd9Sstevel@tonic-gate 		jwin.ws_col = columns;
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 		if (ioctl(0, TIOCSWINSZ, &jwin) == -1) {
1767c478bd9Sstevel@tonic-gate 			jwin.ws_row = oldlines;
1777c478bd9Sstevel@tonic-gate 			jwin.ws_col = oldcolumns;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 			ioctl(0, TIOCSWINSZ, &jwin);
1807c478bd9Sstevel@tonic-gate 		}
1817c478bd9Sstevel@tonic-gate 	}
1827c478bd9Sstevel@tonic-gate #endif /* XPG4 */
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	if (lines <= 1)
1857c478bd9Sstevel@tonic-gate 		lines = 24;
1867c478bd9Sstevel@tonic-gate 	l = lines;
1877c478bd9Sstevel@tonic-gate 	if (columns <= 4)
1887c478bd9Sstevel@tonic-gate 		columns = 1000;
1897c478bd9Sstevel@tonic-gate 	value(vi_WINDOW) = options[vi_WINDOW].odefault = l - 1;
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate /*
1937c478bd9Sstevel@tonic-gate  * Enter open mode
1947c478bd9Sstevel@tonic-gate  */
195f6db9f27Scf void
oop(void)196f6db9f27Scf oop(void)
1977c478bd9Sstevel@tonic-gate {
198f6db9f27Scf 	unsigned char *ic;
1997c478bd9Sstevel@tonic-gate 	ttymode f;	/* was register */
2007c478bd9Sstevel@tonic-gate 	int resize;
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	windowchg = 0;
2037c478bd9Sstevel@tonic-gate 	(void)signal(SIGWINCH, winch);
2047c478bd9Sstevel@tonic-gate 	ovbeg();
2057c478bd9Sstevel@tonic-gate 	if (peekchar() == '/') {
2067c478bd9Sstevel@tonic-gate 		(void)vi_compile(getchar(), 1);
2077c478bd9Sstevel@tonic-gate 		savere(&scanre);
2087c478bd9Sstevel@tonic-gate 		if (execute(0, dot) == 0)
2097c478bd9Sstevel@tonic-gate 			error(value(vi_TERSE) ? gettext("Fail") :
2107c478bd9Sstevel@tonic-gate gettext("Pattern not found on addressed line"));
2117c478bd9Sstevel@tonic-gate 		ic = (unsigned char *)loc1;
2127c478bd9Sstevel@tonic-gate 		if (ic > linebuf && *ic == 0)
2137c478bd9Sstevel@tonic-gate 			ic--;
2147c478bd9Sstevel@tonic-gate 	} else {
2157c478bd9Sstevel@tonic-gate 		getDOT();
2167c478bd9Sstevel@tonic-gate 		ic = vskipwh(linebuf);
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 	donewline();
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	/*
2217c478bd9Sstevel@tonic-gate 	 * If overstrike then have to HARDOPEN
2227c478bd9Sstevel@tonic-gate 	 * else if can move cursor up off current line can use CRTOPEN (~~vi1)
2237c478bd9Sstevel@tonic-gate 	 * otherwise have to use ONEOPEN (like adm3)
2247c478bd9Sstevel@tonic-gate 	 */
2257c478bd9Sstevel@tonic-gate 	if (over_strike && !erase_overstrike)
2267c478bd9Sstevel@tonic-gate 		bastate = HARDOPEN;
2277c478bd9Sstevel@tonic-gate 	else if (cursor_address || cursor_up)
2287c478bd9Sstevel@tonic-gate 		bastate = CRTOPEN;
2297c478bd9Sstevel@tonic-gate 	else
2307c478bd9Sstevel@tonic-gate 		bastate = ONEOPEN;
2317c478bd9Sstevel@tonic-gate 	setwind();
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	/*
2347c478bd9Sstevel@tonic-gate 	 * To avoid bombing on glass-crt's when the line is too long
2357c478bd9Sstevel@tonic-gate 	 * pretend that such terminals are 160 columns wide.
2367c478bd9Sstevel@tonic-gate 	 * If a line is too wide for display, we will dynamically
2377c478bd9Sstevel@tonic-gate 	 * switch to hardcopy open mode.
2387c478bd9Sstevel@tonic-gate 	 */
2397c478bd9Sstevel@tonic-gate 	if (state != CRTOPEN)
2407c478bd9Sstevel@tonic-gate 		WCOLS = TUBECOLS;
2417c478bd9Sstevel@tonic-gate 	if (!inglobal)
2427c478bd9Sstevel@tonic-gate 		savevis();
2437c478bd9Sstevel@tonic-gate 	vok(atube, 0);
2447c478bd9Sstevel@tonic-gate 	if (state != CRTOPEN)
2457c478bd9Sstevel@tonic-gate 		columns = WCOLS;
2467c478bd9Sstevel@tonic-gate 	Outchar = vputchar;
2477c478bd9Sstevel@tonic-gate 	f = ostart();
2487c478bd9Sstevel@tonic-gate 	if (state == CRTOPEN) {
2497c478bd9Sstevel@tonic-gate 		if (outcol == UKCOL)
2507c478bd9Sstevel@tonic-gate 			outcol = 0;
2517c478bd9Sstevel@tonic-gate 		vmoveitup(1, 1);
2527c478bd9Sstevel@tonic-gate 	} else
2537c478bd9Sstevel@tonic-gate 		outline = destline = WBOT;
2547c478bd9Sstevel@tonic-gate 	vshow(dot, NOLINE);
2557c478bd9Sstevel@tonic-gate 	vnline(ic);
2567c478bd9Sstevel@tonic-gate 	vmain();
2577c478bd9Sstevel@tonic-gate 	if (state != CRTOPEN)
2587c478bd9Sstevel@tonic-gate 		vclean();
2597c478bd9Sstevel@tonic-gate 	Command = (unsigned char *)"open";
2607c478bd9Sstevel@tonic-gate 	ovend(f);
2617c478bd9Sstevel@tonic-gate 	(void)signal(SIGWINCH, SIG_DFL);
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate 
264f6db9f27Scf void
ovbeg(void)265f6db9f27Scf ovbeg(void)
2667c478bd9Sstevel@tonic-gate {
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	if (inopen)
2697c478bd9Sstevel@tonic-gate 		error(gettext("Recursive open/visual not allowed"));
2707c478bd9Sstevel@tonic-gate 	Vlines = lineDOL();
2717c478bd9Sstevel@tonic-gate 	fixzero();
2727c478bd9Sstevel@tonic-gate 	setdot();
2737c478bd9Sstevel@tonic-gate 	pastwh();
2747c478bd9Sstevel@tonic-gate 	dot = addr2;
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
277f6db9f27Scf void
ovend(ttymode f)278f6db9f27Scf ovend(ttymode f)
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	splitw++;
2827c478bd9Sstevel@tonic-gate 	vgoto(WECHO, 0);
2837c478bd9Sstevel@tonic-gate 	vclreol();
2847c478bd9Sstevel@tonic-gate 	vgoto(WECHO, 0);
2857c478bd9Sstevel@tonic-gate 	holdcm = 0;
2867c478bd9Sstevel@tonic-gate 	splitw = 0;
2877c478bd9Sstevel@tonic-gate 	ostop(f);
2887c478bd9Sstevel@tonic-gate 	setoutt();
2897c478bd9Sstevel@tonic-gate 	undvis();
2907c478bd9Sstevel@tonic-gate 	columns = OCOLUMNS;
2917c478bd9Sstevel@tonic-gate 	inopen = 0;
2927c478bd9Sstevel@tonic-gate 	flusho();
2937c478bd9Sstevel@tonic-gate 	netchHAD(Vlines);
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate /*
2977c478bd9Sstevel@tonic-gate  * Enter visual mode
2987c478bd9Sstevel@tonic-gate  */
299f6db9f27Scf void
vop(void)300f6db9f27Scf vop(void)
3017c478bd9Sstevel@tonic-gate {
302f6db9f27Scf 	int c;
3037c478bd9Sstevel@tonic-gate 	ttymode f;	/* was register */
3047c478bd9Sstevel@tonic-gate 	extern unsigned char termtype[];
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	if (!cursor_address && !cursor_up) {
3077c478bd9Sstevel@tonic-gate 		if (initev) {
3087c478bd9Sstevel@tonic-gate toopen:
3097c478bd9Sstevel@tonic-gate 			if (generic_type)
3107c478bd9Sstevel@tonic-gate 				merror(gettext("I don't know what kind of terminal you are on - all I have is '%s'."), termtype);
3117c478bd9Sstevel@tonic-gate 			putNFL();
3127c478bd9Sstevel@tonic-gate 			merror(gettext("[Using open mode]"));
3137c478bd9Sstevel@tonic-gate 			putNFL();
3147c478bd9Sstevel@tonic-gate 			oop();
3157c478bd9Sstevel@tonic-gate 			return;
3167c478bd9Sstevel@tonic-gate 		}
3177c478bd9Sstevel@tonic-gate 		error(gettext("Visual needs addressable cursor or upline capability"));
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate 	if (over_strike && !erase_overstrike) {
3207c478bd9Sstevel@tonic-gate 		if (initev)
3217c478bd9Sstevel@tonic-gate 			goto toopen;
3227c478bd9Sstevel@tonic-gate 		error(gettext("Can't use visual on a terminal which overstrikes"));
3237c478bd9Sstevel@tonic-gate 	}
3247c478bd9Sstevel@tonic-gate 	if (!clear_screen) {
3257c478bd9Sstevel@tonic-gate 		if (initev)
3267c478bd9Sstevel@tonic-gate 			goto toopen;
3277c478bd9Sstevel@tonic-gate 		error(gettext("Visual requires clear screen capability"));
3287c478bd9Sstevel@tonic-gate 	}
3297c478bd9Sstevel@tonic-gate 	if (!scroll_forward) {
3307c478bd9Sstevel@tonic-gate 		if (initev)
3317c478bd9Sstevel@tonic-gate 			goto toopen;
3327c478bd9Sstevel@tonic-gate 		error(gettext("Visual requires scrolling"));
3337c478bd9Sstevel@tonic-gate 	}
3347c478bd9Sstevel@tonic-gate 	windowchg = 0;
3357c478bd9Sstevel@tonic-gate 	(void)signal(SIGWINCH, winch);
3367c478bd9Sstevel@tonic-gate 	ovbeg();
3377c478bd9Sstevel@tonic-gate 	bastate = VISUAL;
3387c478bd9Sstevel@tonic-gate 	c = 0;
3397c478bd9Sstevel@tonic-gate 	if (any(peekchar(), "+-^."))
3407c478bd9Sstevel@tonic-gate 		c = getchar();
3417c478bd9Sstevel@tonic-gate 	pastwh();
3427c478bd9Sstevel@tonic-gate 	vsetsiz(isdigit(peekchar()) ? getnum() : value(vi_WINDOW));
3437c478bd9Sstevel@tonic-gate 	setwind();
3447c478bd9Sstevel@tonic-gate 	donewline();
3457c478bd9Sstevel@tonic-gate 	vok(atube, 0);
3467c478bd9Sstevel@tonic-gate 	if (!inglobal)
3477c478bd9Sstevel@tonic-gate 		savevis();
3487c478bd9Sstevel@tonic-gate 	Outchar = vputchar;
3497c478bd9Sstevel@tonic-gate 	vmoving = 0;
3507c478bd9Sstevel@tonic-gate 	f = ostart();
3517c478bd9Sstevel@tonic-gate 	if (initev == 0) {
3527c478bd9Sstevel@tonic-gate 		vcontext(dot, c);
353f6db9f27Scf 		vnline((unsigned char *)NOSTR);
3547c478bd9Sstevel@tonic-gate 	}
3557c478bd9Sstevel@tonic-gate 	vmain();
3567c478bd9Sstevel@tonic-gate 	Command = (unsigned char *)"visual";
3577c478bd9Sstevel@tonic-gate 	ovend(f);
3587c478bd9Sstevel@tonic-gate 	(void)signal(SIGWINCH, SIG_DFL);
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate /*
3627c478bd9Sstevel@tonic-gate  * Hack to allow entry to visual with
3637c478bd9Sstevel@tonic-gate  * empty buffer since routines internally
3647c478bd9Sstevel@tonic-gate  * demand at least one line.
3657c478bd9Sstevel@tonic-gate  */
366f6db9f27Scf void
fixzero(void)367f6db9f27Scf fixzero(void)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	if (dol == zero) {
371f6db9f27Scf 		bool ochng = chng;
3727c478bd9Sstevel@tonic-gate 
373f6db9f27Scf 		vdoappend((unsigned char *)"");
3747c478bd9Sstevel@tonic-gate 		if (!ochng)
3757c478bd9Sstevel@tonic-gate 			sync();
3767c478bd9Sstevel@tonic-gate 		addr1 = addr2 = one;
3777c478bd9Sstevel@tonic-gate 	} else if (addr2 == zero)
3787c478bd9Sstevel@tonic-gate 		addr2 = one;
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate /*
3827c478bd9Sstevel@tonic-gate  * Save lines before visual between unddol and truedol.
3837c478bd9Sstevel@tonic-gate  * Accomplish this by throwing away current [unddol,truedol]
3847c478bd9Sstevel@tonic-gate  * and then saving all the lines in the buffer and moving
3857c478bd9Sstevel@tonic-gate  * unddol back to dol.  Don't do this if in a global.
3867c478bd9Sstevel@tonic-gate  *
3877c478bd9Sstevel@tonic-gate  * If you do
3887c478bd9Sstevel@tonic-gate  *	g/xxx/vi.
3897c478bd9Sstevel@tonic-gate  * and then do a
3907c478bd9Sstevel@tonic-gate  *	:e xxxx
3917c478bd9Sstevel@tonic-gate  * at some point, and then quit from the visual and undo
3927c478bd9Sstevel@tonic-gate  * you get the old file back.  Somewhat weird.
3937c478bd9Sstevel@tonic-gate  */
394f6db9f27Scf void
savevis(void)395f6db9f27Scf savevis(void)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	if (inglobal)
3997c478bd9Sstevel@tonic-gate 		return;
4007c478bd9Sstevel@tonic-gate 	truedol = unddol;
4017c478bd9Sstevel@tonic-gate 	saveall();
4027c478bd9Sstevel@tonic-gate 	unddol = dol;
4037c478bd9Sstevel@tonic-gate 	undkind = UNDNONE;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate  * Restore a sensible state after a visual/open, moving the saved
4087c478bd9Sstevel@tonic-gate  * stuff back to [unddol,dol], and killing the partial line kill indicators.
4097c478bd9Sstevel@tonic-gate  */
410f6db9f27Scf void
undvis(void)411f6db9f27Scf undvis(void)
4127c478bd9Sstevel@tonic-gate {
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	if (ruptible)
4157c478bd9Sstevel@tonic-gate 		signal(SIGINT, onintr);
4167c478bd9Sstevel@tonic-gate 	squish();
4177c478bd9Sstevel@tonic-gate 	pkill[0] = pkill[1] = 0;
4187c478bd9Sstevel@tonic-gate 	unddol = truedol;
4197c478bd9Sstevel@tonic-gate 	unddel = zero;
4207c478bd9Sstevel@tonic-gate 	undap1 = one;
4217c478bd9Sstevel@tonic-gate 	undap2 = dol + 1;
4227c478bd9Sstevel@tonic-gate 	undkind = UNDALL;
4237c478bd9Sstevel@tonic-gate 	if (undadot <= zero || undadot > dol)
4247c478bd9Sstevel@tonic-gate 		undadot = zero+1;
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate /*
4287c478bd9Sstevel@tonic-gate  * Set the window parameters based on the base state bastate
4297c478bd9Sstevel@tonic-gate  * and the available buffer space.
4307c478bd9Sstevel@tonic-gate  */
431f6db9f27Scf void
setwind(void)432f6db9f27Scf setwind(void)
4337c478bd9Sstevel@tonic-gate {
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	WCOLS = columns;
4367c478bd9Sstevel@tonic-gate 	switch (bastate) {
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	case ONEOPEN:
4397c478bd9Sstevel@tonic-gate 		if (auto_right_margin)
4407c478bd9Sstevel@tonic-gate 			WCOLS--;
4419097ca5cSToomas Soome 		/* FALLTHROUGH */
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	case HARDOPEN:
4447c478bd9Sstevel@tonic-gate 		basWTOP = WTOP = WBOT = WECHO = 0;
4457c478bd9Sstevel@tonic-gate 		ZERO = 0;
4467c478bd9Sstevel@tonic-gate 		holdcm++;
4477c478bd9Sstevel@tonic-gate 		break;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	case CRTOPEN:
4507c478bd9Sstevel@tonic-gate 		basWTOP = lines - 2;
4519097ca5cSToomas Soome 		/* FALLTHROUGH */
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	case VISUAL:
4547c478bd9Sstevel@tonic-gate 		ZERO = lines - TUBESIZE / WCOLS;
4557c478bd9Sstevel@tonic-gate 		if (ZERO < 0)
4567c478bd9Sstevel@tonic-gate 			ZERO = 0;
4577c478bd9Sstevel@tonic-gate 		if (ZERO > basWTOP)
4587c478bd9Sstevel@tonic-gate 			error(gettext("Screen too large for internal buffer"));
4597c478bd9Sstevel@tonic-gate 		WTOP = basWTOP; WBOT = lines - 2; WECHO = lines - 1;
4607c478bd9Sstevel@tonic-gate 		break;
4617c478bd9Sstevel@tonic-gate 	}
4627c478bd9Sstevel@tonic-gate 	state = bastate;
4637c478bd9Sstevel@tonic-gate 	basWLINES = WLINES = WBOT - WTOP + 1;
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate /*
4677c478bd9Sstevel@tonic-gate  * Can we hack an open/visual on this terminal?
4687c478bd9Sstevel@tonic-gate  * If so, then divide the screen buffer up into lines,
4697c478bd9Sstevel@tonic-gate  * and initialize a bunch of state variables before we start.
4707c478bd9Sstevel@tonic-gate  */
4717c478bd9Sstevel@tonic-gate static unsigned char vlinebuf[LBSIZE];
4727c478bd9Sstevel@tonic-gate 
473f6db9f27Scf void
vok(wchar_t * atube,int undo)474f6db9f27Scf vok(wchar_t *atube, int undo)
4757c478bd9Sstevel@tonic-gate {
476f6db9f27Scf 	int i;
4777c478bd9Sstevel@tonic-gate 	static int beenhere;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	if (WCOLS == 1000)
480f6db9f27Scf 		serror((unsigned char *)
481f6db9f27Scf 		    gettext("Don't know enough about your terminal to use %s"),
482f6db9f27Scf 		    Command);
4837c478bd9Sstevel@tonic-gate 	if (WCOLS > TUBECOLS)
4847c478bd9Sstevel@tonic-gate 		error(gettext("Terminal too wide"));
4857c478bd9Sstevel@tonic-gate 	if (WLINES >= TUBELINES || WCOLS * (WECHO - ZERO + 1) > TUBESIZE)
4867c478bd9Sstevel@tonic-gate 		error(gettext("Screen too large"));
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	vtube0 = atube;
489*55fea89dSDan Cross 	if(beenhere)
4907c478bd9Sstevel@tonic-gate 		vclrbyte(atube, WCOLS * (WECHO - ZERO + 1));
4917c478bd9Sstevel@tonic-gate 	for (i = 0; i < ZERO; i++)
4927c478bd9Sstevel@tonic-gate 		vtube[i] = (wchar_t *) 0;
4937c478bd9Sstevel@tonic-gate 	for (; i <= WECHO; i++)
4947c478bd9Sstevel@tonic-gate 		vtube[i] = atube, atube += WCOLS;
4957c478bd9Sstevel@tonic-gate 	if(beenhere++) {
4967c478bd9Sstevel@tonic-gate 		for (; i < TUBELINES; i++)
4977c478bd9Sstevel@tonic-gate 			vtube[i] = (wchar_t *) 0;
4987c478bd9Sstevel@tonic-gate 	}
4997c478bd9Sstevel@tonic-gate 	vutmp = vlinebuf;
5007c478bd9Sstevel@tonic-gate 	if(!undo) {
5017c478bd9Sstevel@tonic-gate 		vundkind = VNONE;
5027c478bd9Sstevel@tonic-gate 		vUNDdot = 0;
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 	OCOLUMNS = columns;
5057c478bd9Sstevel@tonic-gate 	inopen = 1;
5067c478bd9Sstevel@tonic-gate #ifdef CBREAK
5077c478bd9Sstevel@tonic-gate 	signal(SIGINT, vintr);
5087c478bd9Sstevel@tonic-gate #endif
5097c478bd9Sstevel@tonic-gate 	vmoving = 0;
5107c478bd9Sstevel@tonic-gate 	splitw = 0;
5117c478bd9Sstevel@tonic-gate 	doomed = 0;
5127c478bd9Sstevel@tonic-gate 	holdupd = 0;
5137c478bd9Sstevel@tonic-gate 	if(!undo)
5147c478bd9Sstevel@tonic-gate 		Peekkey = 0;
5157c478bd9Sstevel@tonic-gate 	vcnt = vcline = 0;
5167c478bd9Sstevel@tonic-gate 	if (vSCROLL == 0)
5177c478bd9Sstevel@tonic-gate 		vSCROLL = value(vi_SCROLL);
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate #ifdef CBREAK
5217c478bd9Sstevel@tonic-gate /*ARGSUSED*/
522*55fea89dSDan Cross void
5237c478bd9Sstevel@tonic-gate #ifdef __STDC__
vintr(int sig)5247c478bd9Sstevel@tonic-gate vintr(int sig)
5257c478bd9Sstevel@tonic-gate #else
5267c478bd9Sstevel@tonic-gate vintr(sig)
5277c478bd9Sstevel@tonic-gate int sig;
5287c478bd9Sstevel@tonic-gate #endif
5297c478bd9Sstevel@tonic-gate {
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	signal(SIGINT, vintr);
5327c478bd9Sstevel@tonic-gate 	if (vcatch)
5337c478bd9Sstevel@tonic-gate 		onintr(0);
5347c478bd9Sstevel@tonic-gate 	ungetkey(ATTN);
5357c478bd9Sstevel@tonic-gate 	draino();
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate #endif
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate /*
5407c478bd9Sstevel@tonic-gate  * Set the size of the screen to size lines, to take effect the
5417c478bd9Sstevel@tonic-gate  * next time the screen is redrawn.
5427c478bd9Sstevel@tonic-gate  */
543f6db9f27Scf void
vsetsiz(int size)544f6db9f27Scf vsetsiz(int size)
5457c478bd9Sstevel@tonic-gate {
546f6db9f27Scf 	int b;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	if (bastate != VISUAL)
5497c478bd9Sstevel@tonic-gate 		return;
5507c478bd9Sstevel@tonic-gate 	b = lines - 1 - size;
5517c478bd9Sstevel@tonic-gate 	if (b >= lines - 1)
5527c478bd9Sstevel@tonic-gate 		b = lines - 2;
5537c478bd9Sstevel@tonic-gate 	if (b < 0)
5547c478bd9Sstevel@tonic-gate 		b = 0;
5557c478bd9Sstevel@tonic-gate 	basWTOP = b;
5567c478bd9Sstevel@tonic-gate 	basWLINES = WBOT - b + 1;
5577c478bd9Sstevel@tonic-gate }
558