xref: /illumos-gate/usr/src/cmd/vi/port/ex_get.c (revision 6a634c9d)
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
5*23a1cceaSRoger A. Faulkner  * Common Development and Distribution License (the "License").
6*23a1cceaSRoger A. Faulkner  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*23a1cceaSRoger A. Faulkner 
22f6db9f27Scf /*
23*23a1cceaSRoger A. Faulkner  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24f6db9f27Scf  */
25f6db9f27Scf 
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include "ex.h"
337c478bd9Sstevel@tonic-gate #include "ex_tty.h"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * Input routines for command mode.
377c478bd9Sstevel@tonic-gate  * Since we translate the end of reads into the implied ^D's
387c478bd9Sstevel@tonic-gate  * we have different flavors of routines which do/don't return such.
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate static	bool junkbs;
417c478bd9Sstevel@tonic-gate short	lastc = '\n';
427c478bd9Sstevel@tonic-gate 
43f6db9f27Scf void
ignchar(void)44f6db9f27Scf ignchar(void)
457c478bd9Sstevel@tonic-gate {
467c478bd9Sstevel@tonic-gate 	(void)getchar();
477c478bd9Sstevel@tonic-gate }
487c478bd9Sstevel@tonic-gate 
49f6db9f27Scf int
getchar(void)50f6db9f27Scf getchar(void)
517c478bd9Sstevel@tonic-gate {
52f6db9f27Scf 	int c;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	do
557c478bd9Sstevel@tonic-gate 		c = getcd();
567c478bd9Sstevel@tonic-gate 	while (!globp && c == CTRL('d'));
577c478bd9Sstevel@tonic-gate 	return (c);
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate 
60f6db9f27Scf int
getcd(void)61f6db9f27Scf getcd(void)
627c478bd9Sstevel@tonic-gate {
63f6db9f27Scf 	int c;
647c478bd9Sstevel@tonic-gate 	extern short slevel;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate again:
677c478bd9Sstevel@tonic-gate 	c = getach();
687c478bd9Sstevel@tonic-gate 	if (c == EOF)
697c478bd9Sstevel@tonic-gate 		return (c);
707c478bd9Sstevel@tonic-gate 	if (!inopen && slevel==0)
717c478bd9Sstevel@tonic-gate 		if (!globp && c == CTRL('d'))
727c478bd9Sstevel@tonic-gate 			setlastchar('\n');
737c478bd9Sstevel@tonic-gate 		else if (junk(c)) {
747c478bd9Sstevel@tonic-gate 			checkjunk(c);
757c478bd9Sstevel@tonic-gate 			goto again;
767c478bd9Sstevel@tonic-gate 		}
777c478bd9Sstevel@tonic-gate 	return (c);
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate 
80f6db9f27Scf int
peekchar(void)81f6db9f27Scf peekchar(void)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	if (peekc == 0)
857c478bd9Sstevel@tonic-gate 		peekc = getchar();
867c478bd9Sstevel@tonic-gate 	return (peekc);
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate 
89f6db9f27Scf int
peekcd(void)90f6db9f27Scf peekcd(void)
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 	if (peekc == 0)
937c478bd9Sstevel@tonic-gate 		peekc = getcd();
947c478bd9Sstevel@tonic-gate 	return (peekc);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate int verbose;
98f6db9f27Scf int
getach(void)99f6db9f27Scf getach(void)
1007c478bd9Sstevel@tonic-gate {
101f6db9f27Scf 	int c, i, prev;
1027c478bd9Sstevel@tonic-gate 	static unsigned char inputline[128];
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	c = peekc;
1057c478bd9Sstevel@tonic-gate 	if (c != 0) {
1067c478bd9Sstevel@tonic-gate 		peekc = 0;
1077c478bd9Sstevel@tonic-gate 		return (c);
1087c478bd9Sstevel@tonic-gate 	}
1097c478bd9Sstevel@tonic-gate 	if (globp) {
1107c478bd9Sstevel@tonic-gate 		if (*globp)
1117c478bd9Sstevel@tonic-gate 			return (*globp++);
1127c478bd9Sstevel@tonic-gate 		globp = 0;
1137c478bd9Sstevel@tonic-gate 		return (lastc = EOF);
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate top:
1167c478bd9Sstevel@tonic-gate 	if (input) {
1177c478bd9Sstevel@tonic-gate 		if(c = *input++)
1187c478bd9Sstevel@tonic-gate 			return (lastc = c);
1197c478bd9Sstevel@tonic-gate 		input = 0;
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 	flush();
1227c478bd9Sstevel@tonic-gate 	if (intty) {
1237c478bd9Sstevel@tonic-gate 		c = read(0, inputline, sizeof inputline - 4);
1247c478bd9Sstevel@tonic-gate 		if (c < 0)
1257c478bd9Sstevel@tonic-gate 			return (lastc = EOF);
1267c478bd9Sstevel@tonic-gate 		if (c == 0 || inputline[c-1] != '\n')
1277c478bd9Sstevel@tonic-gate 			inputline[c++] = CTRL('d');
1287c478bd9Sstevel@tonic-gate 		if (inputline[c-1] == '\n')
1297c478bd9Sstevel@tonic-gate 			noteinp();
1307c478bd9Sstevel@tonic-gate 		prev = 0;
1317c478bd9Sstevel@tonic-gate 		/* remove nulls from input buffer */
1327c478bd9Sstevel@tonic-gate 		for (i = 0; i < c; i++)
1337c478bd9Sstevel@tonic-gate 			if(inputline[i] != 0)
1347c478bd9Sstevel@tonic-gate 				inputline[prev++] = inputline[i];
1357c478bd9Sstevel@tonic-gate 		inputline[prev] = 0;
1367c478bd9Sstevel@tonic-gate 		input = inputline;
1377c478bd9Sstevel@tonic-gate 		goto top;
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 	if (read(0, inputline, 1) != 1)
1407c478bd9Sstevel@tonic-gate 		lastc = EOF;
1417c478bd9Sstevel@tonic-gate 	else {
1427c478bd9Sstevel@tonic-gate 		lastc = inputline[0];
1437c478bd9Sstevel@tonic-gate 		if (verbose)
1447c478bd9Sstevel@tonic-gate 			write(2, inputline, 1);
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 	return (lastc);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate  * Input routine for insert/append/change in command mode.
1517c478bd9Sstevel@tonic-gate  * Most work here is in handling autoindent.
1527c478bd9Sstevel@tonic-gate  */
1537c478bd9Sstevel@tonic-gate static	short	lastin;
1547c478bd9Sstevel@tonic-gate 
155f6db9f27Scf int
gettty(void)156f6db9f27Scf gettty(void)
1577c478bd9Sstevel@tonic-gate {
158f6db9f27Scf 	int c = 0;
159f6db9f27Scf 	unsigned char *cp = genbuf;
1607c478bd9Sstevel@tonic-gate 	unsigned char hadup = 0;
1617c478bd9Sstevel@tonic-gate 	extern int (*Pline)();
1627c478bd9Sstevel@tonic-gate 	int offset = Pline == numbline ? 8 : 0;
1637c478bd9Sstevel@tonic-gate 	int ch;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	if (intty && !inglobal) {
1667c478bd9Sstevel@tonic-gate 		if (offset) {
1677c478bd9Sstevel@tonic-gate 			holdcm = 1;
168f6db9f27Scf 			viprintf("  %4d  ", lineDOT() + 1);
1697c478bd9Sstevel@tonic-gate 			flush();
1707c478bd9Sstevel@tonic-gate 			holdcm = 0;
1717c478bd9Sstevel@tonic-gate 		}
1727c478bd9Sstevel@tonic-gate 		if (value(vi_AUTOINDENT) ^ aiflag) {
1737c478bd9Sstevel@tonic-gate 			holdcm = 1;
1747c478bd9Sstevel@tonic-gate 			if (value(vi_LISP))
1757c478bd9Sstevel@tonic-gate 				lastin = lindent(dot + 1);
1767c478bd9Sstevel@tonic-gate 			gotab(lastin + offset);
1777c478bd9Sstevel@tonic-gate 			while ((c = getcd()) == CTRL('d')) {
1787c478bd9Sstevel@tonic-gate 				if (lastin == 0 && isatty(0) == -1) {
1797c478bd9Sstevel@tonic-gate 					holdcm = 0;
1807c478bd9Sstevel@tonic-gate 					return (EOF);
1817c478bd9Sstevel@tonic-gate 				}
1827c478bd9Sstevel@tonic-gate 				lastin = backtab(lastin);
1837c478bd9Sstevel@tonic-gate 				gotab(lastin + offset);
1847c478bd9Sstevel@tonic-gate 			}
1857c478bd9Sstevel@tonic-gate 			switch (c) {
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 			case '^':
1887c478bd9Sstevel@tonic-gate 			case '0':
1897c478bd9Sstevel@tonic-gate 				ch = getcd();
1907c478bd9Sstevel@tonic-gate 				if (ch == CTRL('d')) {
1917c478bd9Sstevel@tonic-gate 					if (c == '0')
1927c478bd9Sstevel@tonic-gate 						lastin = 0;
1937c478bd9Sstevel@tonic-gate 					if (!over_strike) {
1947c478bd9Sstevel@tonic-gate 						putchar((int)('\b' | QUOTE));
1957c478bd9Sstevel@tonic-gate 						putchar((int)(' ' | QUOTE));
1967c478bd9Sstevel@tonic-gate 						putchar((int)('\b' | QUOTE));
1977c478bd9Sstevel@tonic-gate 					}
1987c478bd9Sstevel@tonic-gate 					gotab(offset);
1997c478bd9Sstevel@tonic-gate 					hadup = 1;
2007c478bd9Sstevel@tonic-gate 					c = getchar();
2017c478bd9Sstevel@tonic-gate 				} else
2027c478bd9Sstevel@tonic-gate 					ungetchar(ch);
2037c478bd9Sstevel@tonic-gate 				break;
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 			case '.':
2067c478bd9Sstevel@tonic-gate 				if (peekchar() == '\n') {
2077c478bd9Sstevel@tonic-gate 					ignchar();
2087c478bd9Sstevel@tonic-gate 					noteinp();
2097c478bd9Sstevel@tonic-gate 					holdcm = 0;
2107c478bd9Sstevel@tonic-gate 					return (EOF);
2117c478bd9Sstevel@tonic-gate 				}
2127c478bd9Sstevel@tonic-gate 				break;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 			case '\n':
2157c478bd9Sstevel@tonic-gate 				hadup = 1;
2167c478bd9Sstevel@tonic-gate 				break;
2177c478bd9Sstevel@tonic-gate 			}
2187c478bd9Sstevel@tonic-gate 		}
2197c478bd9Sstevel@tonic-gate 		flush();
2207c478bd9Sstevel@tonic-gate 		holdcm = 0;
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 	if (c == 0)
2237c478bd9Sstevel@tonic-gate 		c = getchar();
2247c478bd9Sstevel@tonic-gate 	while (c != EOF && c != '\n') {
2257c478bd9Sstevel@tonic-gate 		if (cp > &genbuf[LBSIZE - 2])
2267c478bd9Sstevel@tonic-gate 			error(gettext("Input line too long"));
2277c478bd9Sstevel@tonic-gate 		*cp++ = c;
2287c478bd9Sstevel@tonic-gate 		c = getchar();
2297c478bd9Sstevel@tonic-gate 	}
2307c478bd9Sstevel@tonic-gate 	if (c == EOF) {
2317c478bd9Sstevel@tonic-gate 		if (inglobal)
2327c478bd9Sstevel@tonic-gate 			ungetchar(EOF);
2337c478bd9Sstevel@tonic-gate 		return (EOF);
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate 	*cp = 0;
2367c478bd9Sstevel@tonic-gate 	cp = linebuf;
2377c478bd9Sstevel@tonic-gate 	if ((value(vi_AUTOINDENT) ^ aiflag) && hadup == 0 && intty && !inglobal) {
2387c478bd9Sstevel@tonic-gate 		lastin = c = smunch(lastin, genbuf);
2397c478bd9Sstevel@tonic-gate 		for (c = lastin; c >= value(vi_TABSTOP); c -= value(vi_TABSTOP))
2407c478bd9Sstevel@tonic-gate 			*cp++ = '\t';
2417c478bd9Sstevel@tonic-gate 		for (; c > 0; c--)
2427c478bd9Sstevel@tonic-gate 			*cp++ = ' ';
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 	CP(cp, genbuf);
2457c478bd9Sstevel@tonic-gate 	if (linebuf[0] == '.' && linebuf[1] == 0)
2467c478bd9Sstevel@tonic-gate 		return (EOF);
2477c478bd9Sstevel@tonic-gate 	return (0);
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate /*
2517c478bd9Sstevel@tonic-gate  * Crunch the indent.
2527c478bd9Sstevel@tonic-gate  * Hard thing here is that in command mode some of the indent
2537c478bd9Sstevel@tonic-gate  * is only implicit, so we must seed the column counter.
2547c478bd9Sstevel@tonic-gate  * This should really be done differently so as to use the whitecnt routine
2557c478bd9Sstevel@tonic-gate  * and also to hack indenting for LISP.
2567c478bd9Sstevel@tonic-gate  */
257f6db9f27Scf int
smunch(int col,unsigned char * ocp)258f6db9f27Scf smunch(int col, unsigned char *ocp)
2597c478bd9Sstevel@tonic-gate {
260f6db9f27Scf 	unsigned char *cp;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	cp = ocp;
2637c478bd9Sstevel@tonic-gate 	for (;;)
2647c478bd9Sstevel@tonic-gate 		switch (*cp++) {
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 		case ' ':
2677c478bd9Sstevel@tonic-gate 			col++;
2687c478bd9Sstevel@tonic-gate 			continue;
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 		case '\t':
2717c478bd9Sstevel@tonic-gate 			col += value(vi_TABSTOP) - (col % value(vi_TABSTOP));
2727c478bd9Sstevel@tonic-gate 			continue;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 		default:
2757c478bd9Sstevel@tonic-gate 			cp--;
2767c478bd9Sstevel@tonic-gate 			CP(ocp, cp);
2777c478bd9Sstevel@tonic-gate 			return (col);
2787c478bd9Sstevel@tonic-gate 		}
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate unsigned char	*cntrlhm =	(unsigned char *)"^H discarded\n";
2827c478bd9Sstevel@tonic-gate 
283f6db9f27Scf void
checkjunk(unsigned char c)284f6db9f27Scf checkjunk(unsigned char c)
2857c478bd9Sstevel@tonic-gate {
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	if (junkbs == 0 && c == '\b') {
2887c478bd9Sstevel@tonic-gate 		write(2, cntrlhm, 13);
2897c478bd9Sstevel@tonic-gate 		junkbs = 1;
2907c478bd9Sstevel@tonic-gate 	}
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate 
293f6db9f27Scf void
setin(line * addr)294f6db9f27Scf setin(line *addr)
2957c478bd9Sstevel@tonic-gate {
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	if (addr == zero)
2987c478bd9Sstevel@tonic-gate 		lastin = 0;
2997c478bd9Sstevel@tonic-gate 	else
300*23a1cceaSRoger A. Faulkner 		getaline(*addr), lastin = smunch(0, linebuf);
3017c478bd9Sstevel@tonic-gate }
302