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