xref: /onnv-gate/usr/src/cmd/vi/port/ex_get.c (revision 13093:48f2dbca79a2)
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
5*13093SRoger.Faulkner@Oracle.COM  * Common Development and Distribution License (the "License").
6*13093SRoger.Faulkner@Oracle.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*13093SRoger.Faulkner@Oracle.COM 
22802Scf46844 /*
23*13093SRoger.Faulkner@Oracle.COM  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24802Scf46844  */
25802Scf46844 
260Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved  	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include "ex.h"
330Sstevel@tonic-gate #include "ex_tty.h"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate /*
360Sstevel@tonic-gate  * Input routines for command mode.
370Sstevel@tonic-gate  * Since we translate the end of reads into the implied ^D's
380Sstevel@tonic-gate  * we have different flavors of routines which do/don't return such.
390Sstevel@tonic-gate  */
400Sstevel@tonic-gate static	bool junkbs;
410Sstevel@tonic-gate short	lastc = '\n';
420Sstevel@tonic-gate 
43802Scf46844 void
ignchar(void)44802Scf46844 ignchar(void)
450Sstevel@tonic-gate {
460Sstevel@tonic-gate 	(void)getchar();
470Sstevel@tonic-gate }
480Sstevel@tonic-gate 
49802Scf46844 int
getchar(void)50802Scf46844 getchar(void)
510Sstevel@tonic-gate {
52802Scf46844 	int c;
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	do
550Sstevel@tonic-gate 		c = getcd();
560Sstevel@tonic-gate 	while (!globp && c == CTRL('d'));
570Sstevel@tonic-gate 	return (c);
580Sstevel@tonic-gate }
590Sstevel@tonic-gate 
60802Scf46844 int
getcd(void)61802Scf46844 getcd(void)
620Sstevel@tonic-gate {
63802Scf46844 	int c;
640Sstevel@tonic-gate 	extern short slevel;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate again:
670Sstevel@tonic-gate 	c = getach();
680Sstevel@tonic-gate 	if (c == EOF)
690Sstevel@tonic-gate 		return (c);
700Sstevel@tonic-gate 	if (!inopen && slevel==0)
710Sstevel@tonic-gate 		if (!globp && c == CTRL('d'))
720Sstevel@tonic-gate 			setlastchar('\n');
730Sstevel@tonic-gate 		else if (junk(c)) {
740Sstevel@tonic-gate 			checkjunk(c);
750Sstevel@tonic-gate 			goto again;
760Sstevel@tonic-gate 		}
770Sstevel@tonic-gate 	return (c);
780Sstevel@tonic-gate }
790Sstevel@tonic-gate 
80802Scf46844 int
peekchar(void)81802Scf46844 peekchar(void)
820Sstevel@tonic-gate {
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	if (peekc == 0)
850Sstevel@tonic-gate 		peekc = getchar();
860Sstevel@tonic-gate 	return (peekc);
870Sstevel@tonic-gate }
880Sstevel@tonic-gate 
89802Scf46844 int
peekcd(void)90802Scf46844 peekcd(void)
910Sstevel@tonic-gate {
920Sstevel@tonic-gate 	if (peekc == 0)
930Sstevel@tonic-gate 		peekc = getcd();
940Sstevel@tonic-gate 	return (peekc);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate 
970Sstevel@tonic-gate int verbose;
98802Scf46844 int
getach(void)99802Scf46844 getach(void)
1000Sstevel@tonic-gate {
101802Scf46844 	int c, i, prev;
1020Sstevel@tonic-gate 	static unsigned char inputline[128];
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	c = peekc;
1050Sstevel@tonic-gate 	if (c != 0) {
1060Sstevel@tonic-gate 		peekc = 0;
1070Sstevel@tonic-gate 		return (c);
1080Sstevel@tonic-gate 	}
1090Sstevel@tonic-gate 	if (globp) {
1100Sstevel@tonic-gate 		if (*globp)
1110Sstevel@tonic-gate 			return (*globp++);
1120Sstevel@tonic-gate 		globp = 0;
1130Sstevel@tonic-gate 		return (lastc = EOF);
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate top:
1160Sstevel@tonic-gate 	if (input) {
1170Sstevel@tonic-gate 		if(c = *input++)
1180Sstevel@tonic-gate 			return (lastc = c);
1190Sstevel@tonic-gate 		input = 0;
1200Sstevel@tonic-gate 	}
1210Sstevel@tonic-gate 	flush();
1220Sstevel@tonic-gate 	if (intty) {
1230Sstevel@tonic-gate 		c = read(0, inputline, sizeof inputline - 4);
1240Sstevel@tonic-gate 		if (c < 0)
1250Sstevel@tonic-gate 			return (lastc = EOF);
1260Sstevel@tonic-gate 		if (c == 0 || inputline[c-1] != '\n')
1270Sstevel@tonic-gate 			inputline[c++] = CTRL('d');
1280Sstevel@tonic-gate 		if (inputline[c-1] == '\n')
1290Sstevel@tonic-gate 			noteinp();
1300Sstevel@tonic-gate 		prev = 0;
1310Sstevel@tonic-gate 		/* remove nulls from input buffer */
1320Sstevel@tonic-gate 		for (i = 0; i < c; i++)
1330Sstevel@tonic-gate 			if(inputline[i] != 0)
1340Sstevel@tonic-gate 				inputline[prev++] = inputline[i];
1350Sstevel@tonic-gate 		inputline[prev] = 0;
1360Sstevel@tonic-gate 		input = inputline;
1370Sstevel@tonic-gate 		goto top;
1380Sstevel@tonic-gate 	}
1390Sstevel@tonic-gate 	if (read(0, inputline, 1) != 1)
1400Sstevel@tonic-gate 		lastc = EOF;
1410Sstevel@tonic-gate 	else {
1420Sstevel@tonic-gate 		lastc = inputline[0];
1430Sstevel@tonic-gate 		if (verbose)
1440Sstevel@tonic-gate 			write(2, inputline, 1);
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate 	return (lastc);
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate /*
1500Sstevel@tonic-gate  * Input routine for insert/append/change in command mode.
1510Sstevel@tonic-gate  * Most work here is in handling autoindent.
1520Sstevel@tonic-gate  */
1530Sstevel@tonic-gate static	short	lastin;
1540Sstevel@tonic-gate 
155802Scf46844 int
gettty(void)156802Scf46844 gettty(void)
1570Sstevel@tonic-gate {
158802Scf46844 	int c = 0;
159802Scf46844 	unsigned char *cp = genbuf;
1600Sstevel@tonic-gate 	unsigned char hadup = 0;
1610Sstevel@tonic-gate 	extern int (*Pline)();
1620Sstevel@tonic-gate 	int offset = Pline == numbline ? 8 : 0;
1630Sstevel@tonic-gate 	int ch;
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	if (intty && !inglobal) {
1660Sstevel@tonic-gate 		if (offset) {
1670Sstevel@tonic-gate 			holdcm = 1;
168802Scf46844 			viprintf("  %4d  ", lineDOT() + 1);
1690Sstevel@tonic-gate 			flush();
1700Sstevel@tonic-gate 			holdcm = 0;
1710Sstevel@tonic-gate 		}
1720Sstevel@tonic-gate 		if (value(vi_AUTOINDENT) ^ aiflag) {
1730Sstevel@tonic-gate 			holdcm = 1;
1740Sstevel@tonic-gate 			if (value(vi_LISP))
1750Sstevel@tonic-gate 				lastin = lindent(dot + 1);
1760Sstevel@tonic-gate 			gotab(lastin + offset);
1770Sstevel@tonic-gate 			while ((c = getcd()) == CTRL('d')) {
1780Sstevel@tonic-gate 				if (lastin == 0 && isatty(0) == -1) {
1790Sstevel@tonic-gate 					holdcm = 0;
1800Sstevel@tonic-gate 					return (EOF);
1810Sstevel@tonic-gate 				}
1820Sstevel@tonic-gate 				lastin = backtab(lastin);
1830Sstevel@tonic-gate 				gotab(lastin + offset);
1840Sstevel@tonic-gate 			}
1850Sstevel@tonic-gate 			switch (c) {
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 			case '^':
1880Sstevel@tonic-gate 			case '0':
1890Sstevel@tonic-gate 				ch = getcd();
1900Sstevel@tonic-gate 				if (ch == CTRL('d')) {
1910Sstevel@tonic-gate 					if (c == '0')
1920Sstevel@tonic-gate 						lastin = 0;
1930Sstevel@tonic-gate 					if (!over_strike) {
1940Sstevel@tonic-gate 						putchar((int)('\b' | QUOTE));
1950Sstevel@tonic-gate 						putchar((int)(' ' | QUOTE));
1960Sstevel@tonic-gate 						putchar((int)('\b' | QUOTE));
1970Sstevel@tonic-gate 					}
1980Sstevel@tonic-gate 					gotab(offset);
1990Sstevel@tonic-gate 					hadup = 1;
2000Sstevel@tonic-gate 					c = getchar();
2010Sstevel@tonic-gate 				} else
2020Sstevel@tonic-gate 					ungetchar(ch);
2030Sstevel@tonic-gate 				break;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 			case '.':
2060Sstevel@tonic-gate 				if (peekchar() == '\n') {
2070Sstevel@tonic-gate 					ignchar();
2080Sstevel@tonic-gate 					noteinp();
2090Sstevel@tonic-gate 					holdcm = 0;
2100Sstevel@tonic-gate 					return (EOF);
2110Sstevel@tonic-gate 				}
2120Sstevel@tonic-gate 				break;
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 			case '\n':
2150Sstevel@tonic-gate 				hadup = 1;
2160Sstevel@tonic-gate 				break;
2170Sstevel@tonic-gate 			}
2180Sstevel@tonic-gate 		}
2190Sstevel@tonic-gate 		flush();
2200Sstevel@tonic-gate 		holdcm = 0;
2210Sstevel@tonic-gate 	}
2220Sstevel@tonic-gate 	if (c == 0)
2230Sstevel@tonic-gate 		c = getchar();
2240Sstevel@tonic-gate 	while (c != EOF && c != '\n') {
2250Sstevel@tonic-gate 		if (cp > &genbuf[LBSIZE - 2])
2260Sstevel@tonic-gate 			error(gettext("Input line too long"));
2270Sstevel@tonic-gate 		*cp++ = c;
2280Sstevel@tonic-gate 		c = getchar();
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate 	if (c == EOF) {
2310Sstevel@tonic-gate 		if (inglobal)
2320Sstevel@tonic-gate 			ungetchar(EOF);
2330Sstevel@tonic-gate 		return (EOF);
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate 	*cp = 0;
2360Sstevel@tonic-gate 	cp = linebuf;
2370Sstevel@tonic-gate 	if ((value(vi_AUTOINDENT) ^ aiflag) && hadup == 0 && intty && !inglobal) {
2380Sstevel@tonic-gate 		lastin = c = smunch(lastin, genbuf);
2390Sstevel@tonic-gate 		for (c = lastin; c >= value(vi_TABSTOP); c -= value(vi_TABSTOP))
2400Sstevel@tonic-gate 			*cp++ = '\t';
2410Sstevel@tonic-gate 		for (; c > 0; c--)
2420Sstevel@tonic-gate 			*cp++ = ' ';
2430Sstevel@tonic-gate 	}
2440Sstevel@tonic-gate 	CP(cp, genbuf);
2450Sstevel@tonic-gate 	if (linebuf[0] == '.' && linebuf[1] == 0)
2460Sstevel@tonic-gate 		return (EOF);
2470Sstevel@tonic-gate 	return (0);
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate /*
2510Sstevel@tonic-gate  * Crunch the indent.
2520Sstevel@tonic-gate  * Hard thing here is that in command mode some of the indent
2530Sstevel@tonic-gate  * is only implicit, so we must seed the column counter.
2540Sstevel@tonic-gate  * This should really be done differently so as to use the whitecnt routine
2550Sstevel@tonic-gate  * and also to hack indenting for LISP.
2560Sstevel@tonic-gate  */
257802Scf46844 int
smunch(int col,unsigned char * ocp)258802Scf46844 smunch(int col, unsigned char *ocp)
2590Sstevel@tonic-gate {
260802Scf46844 	unsigned char *cp;
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 	cp = ocp;
2630Sstevel@tonic-gate 	for (;;)
2640Sstevel@tonic-gate 		switch (*cp++) {
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 		case ' ':
2670Sstevel@tonic-gate 			col++;
2680Sstevel@tonic-gate 			continue;
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 		case '\t':
2710Sstevel@tonic-gate 			col += value(vi_TABSTOP) - (col % value(vi_TABSTOP));
2720Sstevel@tonic-gate 			continue;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 		default:
2750Sstevel@tonic-gate 			cp--;
2760Sstevel@tonic-gate 			CP(ocp, cp);
2770Sstevel@tonic-gate 			return (col);
2780Sstevel@tonic-gate 		}
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate unsigned char	*cntrlhm =	(unsigned char *)"^H discarded\n";
2820Sstevel@tonic-gate 
283802Scf46844 void
checkjunk(unsigned char c)284802Scf46844 checkjunk(unsigned char c)
2850Sstevel@tonic-gate {
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	if (junkbs == 0 && c == '\b') {
2880Sstevel@tonic-gate 		write(2, cntrlhm, 13);
2890Sstevel@tonic-gate 		junkbs = 1;
2900Sstevel@tonic-gate 	}
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate 
293802Scf46844 void
setin(line * addr)294802Scf46844 setin(line *addr)
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 	if (addr == zero)
2980Sstevel@tonic-gate 		lastin = 0;
2990Sstevel@tonic-gate 	else
300*13093SRoger.Faulkner@Oracle.COM 		getaline(*addr), lastin = smunch(0, linebuf);
3010Sstevel@tonic-gate }
302