xref: /onnv-gate/usr/src/cmd/vi/port/ex_get.c (revision 802:73b56fb6544b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22*802Scf46844 /*
23*802Scf46844  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*802Scf46844  * Use is subject to license terms.
25*802Scf46844  */
26*802Scf46844 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate 
310Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
320Sstevel@tonic-gate 
33*802Scf46844 #pragma ident	"%Z%%M%	%I%	%E% SMI"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #include "ex.h"
360Sstevel@tonic-gate #include "ex_tty.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate  * Input routines for command mode.
400Sstevel@tonic-gate  * Since we translate the end of reads into the implied ^D's
410Sstevel@tonic-gate  * we have different flavors of routines which do/don't return such.
420Sstevel@tonic-gate  */
430Sstevel@tonic-gate static	bool junkbs;
440Sstevel@tonic-gate short	lastc = '\n';
450Sstevel@tonic-gate 
46*802Scf46844 void
47*802Scf46844 ignchar(void)
480Sstevel@tonic-gate {
490Sstevel@tonic-gate 	(void)getchar();
500Sstevel@tonic-gate }
510Sstevel@tonic-gate 
52*802Scf46844 int
53*802Scf46844 getchar(void)
540Sstevel@tonic-gate {
55*802Scf46844 	int c;
560Sstevel@tonic-gate 
570Sstevel@tonic-gate 	do
580Sstevel@tonic-gate 		c = getcd();
590Sstevel@tonic-gate 	while (!globp && c == CTRL('d'));
600Sstevel@tonic-gate 	return (c);
610Sstevel@tonic-gate }
620Sstevel@tonic-gate 
63*802Scf46844 int
64*802Scf46844 getcd(void)
650Sstevel@tonic-gate {
66*802Scf46844 	int c;
670Sstevel@tonic-gate 	extern short slevel;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate again:
700Sstevel@tonic-gate 	c = getach();
710Sstevel@tonic-gate 	if (c == EOF)
720Sstevel@tonic-gate 		return (c);
730Sstevel@tonic-gate 	if (!inopen && slevel==0)
740Sstevel@tonic-gate 		if (!globp && c == CTRL('d'))
750Sstevel@tonic-gate 			setlastchar('\n');
760Sstevel@tonic-gate 		else if (junk(c)) {
770Sstevel@tonic-gate 			checkjunk(c);
780Sstevel@tonic-gate 			goto again;
790Sstevel@tonic-gate 		}
800Sstevel@tonic-gate 	return (c);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate 
83*802Scf46844 int
84*802Scf46844 peekchar(void)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	if (peekc == 0)
880Sstevel@tonic-gate 		peekc = getchar();
890Sstevel@tonic-gate 	return (peekc);
900Sstevel@tonic-gate }
910Sstevel@tonic-gate 
92*802Scf46844 int
93*802Scf46844 peekcd(void)
940Sstevel@tonic-gate {
950Sstevel@tonic-gate 	if (peekc == 0)
960Sstevel@tonic-gate 		peekc = getcd();
970Sstevel@tonic-gate 	return (peekc);
980Sstevel@tonic-gate }
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate int verbose;
101*802Scf46844 int
102*802Scf46844 getach(void)
1030Sstevel@tonic-gate {
104*802Scf46844 	int c, i, prev;
1050Sstevel@tonic-gate 	static unsigned char inputline[128];
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	c = peekc;
1080Sstevel@tonic-gate 	if (c != 0) {
1090Sstevel@tonic-gate 		peekc = 0;
1100Sstevel@tonic-gate 		return (c);
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate 	if (globp) {
1130Sstevel@tonic-gate 		if (*globp)
1140Sstevel@tonic-gate 			return (*globp++);
1150Sstevel@tonic-gate 		globp = 0;
1160Sstevel@tonic-gate 		return (lastc = EOF);
1170Sstevel@tonic-gate 	}
1180Sstevel@tonic-gate top:
1190Sstevel@tonic-gate 	if (input) {
1200Sstevel@tonic-gate 		if(c = *input++)
1210Sstevel@tonic-gate 			return (lastc = c);
1220Sstevel@tonic-gate 		input = 0;
1230Sstevel@tonic-gate 	}
1240Sstevel@tonic-gate 	flush();
1250Sstevel@tonic-gate 	if (intty) {
1260Sstevel@tonic-gate 		c = read(0, inputline, sizeof inputline - 4);
1270Sstevel@tonic-gate 		if (c < 0)
1280Sstevel@tonic-gate 			return (lastc = EOF);
1290Sstevel@tonic-gate 		if (c == 0 || inputline[c-1] != '\n')
1300Sstevel@tonic-gate 			inputline[c++] = CTRL('d');
1310Sstevel@tonic-gate 		if (inputline[c-1] == '\n')
1320Sstevel@tonic-gate 			noteinp();
1330Sstevel@tonic-gate 		prev = 0;
1340Sstevel@tonic-gate 		/* remove nulls from input buffer */
1350Sstevel@tonic-gate 		for (i = 0; i < c; i++)
1360Sstevel@tonic-gate 			if(inputline[i] != 0)
1370Sstevel@tonic-gate 				inputline[prev++] = inputline[i];
1380Sstevel@tonic-gate 		inputline[prev] = 0;
1390Sstevel@tonic-gate 		input = inputline;
1400Sstevel@tonic-gate 		goto top;
1410Sstevel@tonic-gate 	}
1420Sstevel@tonic-gate 	if (read(0, inputline, 1) != 1)
1430Sstevel@tonic-gate 		lastc = EOF;
1440Sstevel@tonic-gate 	else {
1450Sstevel@tonic-gate 		lastc = inputline[0];
1460Sstevel@tonic-gate 		if (verbose)
1470Sstevel@tonic-gate 			write(2, inputline, 1);
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 	return (lastc);
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate /*
1530Sstevel@tonic-gate  * Input routine for insert/append/change in command mode.
1540Sstevel@tonic-gate  * Most work here is in handling autoindent.
1550Sstevel@tonic-gate  */
1560Sstevel@tonic-gate static	short	lastin;
1570Sstevel@tonic-gate 
158*802Scf46844 int
159*802Scf46844 gettty(void)
1600Sstevel@tonic-gate {
161*802Scf46844 	int c = 0;
162*802Scf46844 	unsigned char *cp = genbuf;
1630Sstevel@tonic-gate 	unsigned char hadup = 0;
1640Sstevel@tonic-gate 	extern int (*Pline)();
1650Sstevel@tonic-gate 	int offset = Pline == numbline ? 8 : 0;
1660Sstevel@tonic-gate 	int ch;
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	if (intty && !inglobal) {
1690Sstevel@tonic-gate 		if (offset) {
1700Sstevel@tonic-gate 			holdcm = 1;
171*802Scf46844 			viprintf("  %4d  ", lineDOT() + 1);
1720Sstevel@tonic-gate 			flush();
1730Sstevel@tonic-gate 			holdcm = 0;
1740Sstevel@tonic-gate 		}
1750Sstevel@tonic-gate 		if (value(vi_AUTOINDENT) ^ aiflag) {
1760Sstevel@tonic-gate 			holdcm = 1;
1770Sstevel@tonic-gate 			if (value(vi_LISP))
1780Sstevel@tonic-gate 				lastin = lindent(dot + 1);
1790Sstevel@tonic-gate 			gotab(lastin + offset);
1800Sstevel@tonic-gate 			while ((c = getcd()) == CTRL('d')) {
1810Sstevel@tonic-gate 				if (lastin == 0 && isatty(0) == -1) {
1820Sstevel@tonic-gate 					holdcm = 0;
1830Sstevel@tonic-gate 					return (EOF);
1840Sstevel@tonic-gate 				}
1850Sstevel@tonic-gate 				lastin = backtab(lastin);
1860Sstevel@tonic-gate 				gotab(lastin + offset);
1870Sstevel@tonic-gate 			}
1880Sstevel@tonic-gate 			switch (c) {
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 			case '^':
1910Sstevel@tonic-gate 			case '0':
1920Sstevel@tonic-gate 				ch = getcd();
1930Sstevel@tonic-gate 				if (ch == CTRL('d')) {
1940Sstevel@tonic-gate 					if (c == '0')
1950Sstevel@tonic-gate 						lastin = 0;
1960Sstevel@tonic-gate 					if (!over_strike) {
1970Sstevel@tonic-gate 						putchar((int)('\b' | QUOTE));
1980Sstevel@tonic-gate 						putchar((int)(' ' | QUOTE));
1990Sstevel@tonic-gate 						putchar((int)('\b' | QUOTE));
2000Sstevel@tonic-gate 					}
2010Sstevel@tonic-gate 					gotab(offset);
2020Sstevel@tonic-gate 					hadup = 1;
2030Sstevel@tonic-gate 					c = getchar();
2040Sstevel@tonic-gate 				} else
2050Sstevel@tonic-gate 					ungetchar(ch);
2060Sstevel@tonic-gate 				break;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 			case '.':
2090Sstevel@tonic-gate 				if (peekchar() == '\n') {
2100Sstevel@tonic-gate 					ignchar();
2110Sstevel@tonic-gate 					noteinp();
2120Sstevel@tonic-gate 					holdcm = 0;
2130Sstevel@tonic-gate 					return (EOF);
2140Sstevel@tonic-gate 				}
2150Sstevel@tonic-gate 				break;
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 			case '\n':
2180Sstevel@tonic-gate 				hadup = 1;
2190Sstevel@tonic-gate 				break;
2200Sstevel@tonic-gate 			}
2210Sstevel@tonic-gate 		}
2220Sstevel@tonic-gate 		flush();
2230Sstevel@tonic-gate 		holdcm = 0;
2240Sstevel@tonic-gate 	}
2250Sstevel@tonic-gate 	if (c == 0)
2260Sstevel@tonic-gate 		c = getchar();
2270Sstevel@tonic-gate 	while (c != EOF && c != '\n') {
2280Sstevel@tonic-gate 		if (cp > &genbuf[LBSIZE - 2])
2290Sstevel@tonic-gate 			error(gettext("Input line too long"));
2300Sstevel@tonic-gate 		*cp++ = c;
2310Sstevel@tonic-gate 		c = getchar();
2320Sstevel@tonic-gate 	}
2330Sstevel@tonic-gate 	if (c == EOF) {
2340Sstevel@tonic-gate 		if (inglobal)
2350Sstevel@tonic-gate 			ungetchar(EOF);
2360Sstevel@tonic-gate 		return (EOF);
2370Sstevel@tonic-gate 	}
2380Sstevel@tonic-gate 	*cp = 0;
2390Sstevel@tonic-gate 	cp = linebuf;
2400Sstevel@tonic-gate 	if ((value(vi_AUTOINDENT) ^ aiflag) && hadup == 0 && intty && !inglobal) {
2410Sstevel@tonic-gate 		lastin = c = smunch(lastin, genbuf);
2420Sstevel@tonic-gate 		for (c = lastin; c >= value(vi_TABSTOP); c -= value(vi_TABSTOP))
2430Sstevel@tonic-gate 			*cp++ = '\t';
2440Sstevel@tonic-gate 		for (; c > 0; c--)
2450Sstevel@tonic-gate 			*cp++ = ' ';
2460Sstevel@tonic-gate 	}
2470Sstevel@tonic-gate 	CP(cp, genbuf);
2480Sstevel@tonic-gate 	if (linebuf[0] == '.' && linebuf[1] == 0)
2490Sstevel@tonic-gate 		return (EOF);
2500Sstevel@tonic-gate 	return (0);
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate /*
2540Sstevel@tonic-gate  * Crunch the indent.
2550Sstevel@tonic-gate  * Hard thing here is that in command mode some of the indent
2560Sstevel@tonic-gate  * is only implicit, so we must seed the column counter.
2570Sstevel@tonic-gate  * This should really be done differently so as to use the whitecnt routine
2580Sstevel@tonic-gate  * and also to hack indenting for LISP.
2590Sstevel@tonic-gate  */
260*802Scf46844 int
261*802Scf46844 smunch(int col, unsigned char *ocp)
2620Sstevel@tonic-gate {
263*802Scf46844 	unsigned char *cp;
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	cp = ocp;
2660Sstevel@tonic-gate 	for (;;)
2670Sstevel@tonic-gate 		switch (*cp++) {
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 		case ' ':
2700Sstevel@tonic-gate 			col++;
2710Sstevel@tonic-gate 			continue;
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 		case '\t':
2740Sstevel@tonic-gate 			col += value(vi_TABSTOP) - (col % value(vi_TABSTOP));
2750Sstevel@tonic-gate 			continue;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 		default:
2780Sstevel@tonic-gate 			cp--;
2790Sstevel@tonic-gate 			CP(ocp, cp);
2800Sstevel@tonic-gate 			return (col);
2810Sstevel@tonic-gate 		}
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate unsigned char	*cntrlhm =	(unsigned char *)"^H discarded\n";
2850Sstevel@tonic-gate 
286*802Scf46844 void
287*802Scf46844 checkjunk(unsigned char c)
2880Sstevel@tonic-gate {
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	if (junkbs == 0 && c == '\b') {
2910Sstevel@tonic-gate 		write(2, cntrlhm, 13);
2920Sstevel@tonic-gate 		junkbs = 1;
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate 
296*802Scf46844 void
297*802Scf46844 setin(line *addr)
2980Sstevel@tonic-gate {
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	if (addr == zero)
3010Sstevel@tonic-gate 		lastin = 0;
3020Sstevel@tonic-gate 	else
3030Sstevel@tonic-gate 		getline(*addr), lastin = smunch(0, linebuf);
3040Sstevel@tonic-gate }
305