1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* Copyright (c) 1981 Regents of the University of California */ 27 28 /* 29 * Copyright (c) 2001 by Sun Microsystems, Inc. 30 * All rights reserved. 31 */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.10 */ 34 35 #include "ex.h" 36 #include "ex_tty.h" 37 38 /* 39 * Input routines for command mode. 40 * Since we translate the end of reads into the implied ^D's 41 * we have different flavors of routines which do/don't return such. 42 */ 43 static bool junkbs; 44 short lastc = '\n'; 45 46 ignchar() 47 { 48 (void)getchar(); 49 } 50 51 getchar() 52 { 53 register int c; 54 55 do 56 c = getcd(); 57 while (!globp && c == CTRL('d')); 58 return (c); 59 } 60 61 getcd() 62 { 63 register int c; 64 extern short slevel; 65 66 again: 67 c = getach(); 68 if (c == EOF) 69 return (c); 70 if (!inopen && slevel==0) 71 if (!globp && c == CTRL('d')) 72 setlastchar('\n'); 73 else if (junk(c)) { 74 checkjunk(c); 75 goto again; 76 } 77 return (c); 78 } 79 80 peekchar() 81 { 82 83 if (peekc == 0) 84 peekc = getchar(); 85 return (peekc); 86 } 87 88 peekcd() 89 { 90 if (peekc == 0) 91 peekc = getcd(); 92 return (peekc); 93 } 94 95 int verbose; 96 getach() 97 { 98 register int c, i, prev; 99 static unsigned char inputline[128]; 100 101 c = peekc; 102 if (c != 0) { 103 peekc = 0; 104 return (c); 105 } 106 if (globp) { 107 if (*globp) 108 return (*globp++); 109 globp = 0; 110 return (lastc = EOF); 111 } 112 top: 113 if (input) { 114 if(c = *input++) 115 return (lastc = c); 116 input = 0; 117 } 118 flush(); 119 if (intty) { 120 c = read(0, inputline, sizeof inputline - 4); 121 if (c < 0) 122 return (lastc = EOF); 123 if (c == 0 || inputline[c-1] != '\n') 124 inputline[c++] = CTRL('d'); 125 if (inputline[c-1] == '\n') 126 noteinp(); 127 prev = 0; 128 /* remove nulls from input buffer */ 129 for (i = 0; i < c; i++) 130 if(inputline[i] != 0) 131 inputline[prev++] = inputline[i]; 132 inputline[prev] = 0; 133 input = inputline; 134 goto top; 135 } 136 if (read(0, inputline, 1) != 1) 137 lastc = EOF; 138 else { 139 lastc = inputline[0]; 140 if (verbose) 141 write(2, inputline, 1); 142 } 143 return (lastc); 144 } 145 146 /* 147 * Input routine for insert/append/change in command mode. 148 * Most work here is in handling autoindent. 149 */ 150 static short lastin; 151 152 gettty() 153 { 154 register int c = 0; 155 register unsigned char *cp = genbuf; 156 unsigned char hadup = 0; 157 int numbline(); 158 extern int (*Pline)(); 159 int offset = Pline == numbline ? 8 : 0; 160 int ch; 161 162 if (intty && !inglobal) { 163 if (offset) { 164 holdcm = 1; 165 printf(" %4d ", lineDOT() + 1); 166 flush(); 167 holdcm = 0; 168 } 169 if (value(vi_AUTOINDENT) ^ aiflag) { 170 holdcm = 1; 171 if (value(vi_LISP)) 172 lastin = lindent(dot + 1); 173 gotab(lastin + offset); 174 while ((c = getcd()) == CTRL('d')) { 175 if (lastin == 0 && isatty(0) == -1) { 176 holdcm = 0; 177 return (EOF); 178 } 179 lastin = backtab(lastin); 180 gotab(lastin + offset); 181 } 182 switch (c) { 183 184 case '^': 185 case '0': 186 ch = getcd(); 187 if (ch == CTRL('d')) { 188 if (c == '0') 189 lastin = 0; 190 if (!over_strike) { 191 putchar((int)('\b' | QUOTE)); 192 putchar((int)(' ' | QUOTE)); 193 putchar((int)('\b' | QUOTE)); 194 } 195 gotab(offset); 196 hadup = 1; 197 c = getchar(); 198 } else 199 ungetchar(ch); 200 break; 201 202 case '.': 203 if (peekchar() == '\n') { 204 ignchar(); 205 noteinp(); 206 holdcm = 0; 207 return (EOF); 208 } 209 break; 210 211 case '\n': 212 hadup = 1; 213 break; 214 } 215 } 216 flush(); 217 holdcm = 0; 218 } 219 if (c == 0) 220 c = getchar(); 221 while (c != EOF && c != '\n') { 222 if (cp > &genbuf[LBSIZE - 2]) 223 error(gettext("Input line too long")); 224 *cp++ = c; 225 c = getchar(); 226 } 227 if (c == EOF) { 228 if (inglobal) 229 ungetchar(EOF); 230 return (EOF); 231 } 232 *cp = 0; 233 cp = linebuf; 234 if ((value(vi_AUTOINDENT) ^ aiflag) && hadup == 0 && intty && !inglobal) { 235 lastin = c = smunch(lastin, genbuf); 236 for (c = lastin; c >= value(vi_TABSTOP); c -= value(vi_TABSTOP)) 237 *cp++ = '\t'; 238 for (; c > 0; c--) 239 *cp++ = ' '; 240 } 241 CP(cp, genbuf); 242 if (linebuf[0] == '.' && linebuf[1] == 0) 243 return (EOF); 244 return (0); 245 } 246 247 /* 248 * Crunch the indent. 249 * Hard thing here is that in command mode some of the indent 250 * is only implicit, so we must seed the column counter. 251 * This should really be done differently so as to use the whitecnt routine 252 * and also to hack indenting for LISP. 253 */ 254 smunch(col, ocp) 255 register int col; 256 unsigned char *ocp; 257 { 258 register unsigned char *cp; 259 260 cp = ocp; 261 for (;;) 262 switch (*cp++) { 263 264 case ' ': 265 col++; 266 continue; 267 268 case '\t': 269 col += value(vi_TABSTOP) - (col % value(vi_TABSTOP)); 270 continue; 271 272 default: 273 cp--; 274 CP(ocp, cp); 275 return (col); 276 } 277 } 278 279 unsigned char *cntrlhm = (unsigned char *)"^H discarded\n"; 280 281 checkjunk(c) 282 unsigned char c; 283 { 284 285 if (junkbs == 0 && c == '\b') { 286 write(2, cntrlhm, 13); 287 junkbs = 1; 288 } 289 } 290 291 line * 292 setin(addr) 293 line *addr; 294 { 295 296 if (addr == zero) 297 lastin = 0; 298 else 299 getline(*addr), lastin = smunch(0, linebuf); 300 } 301