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 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 /* Copyright (c) 1981 Regents of the University of California */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" 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 void 47 ignchar(void) 48 { 49 (void)getchar(); 50 } 51 52 int 53 getchar(void) 54 { 55 int c; 56 57 do 58 c = getcd(); 59 while (!globp && c == CTRL('d')); 60 return (c); 61 } 62 63 int 64 getcd(void) 65 { 66 int c; 67 extern short slevel; 68 69 again: 70 c = getach(); 71 if (c == EOF) 72 return (c); 73 if (!inopen && slevel==0) 74 if (!globp && c == CTRL('d')) 75 setlastchar('\n'); 76 else if (junk(c)) { 77 checkjunk(c); 78 goto again; 79 } 80 return (c); 81 } 82 83 int 84 peekchar(void) 85 { 86 87 if (peekc == 0) 88 peekc = getchar(); 89 return (peekc); 90 } 91 92 int 93 peekcd(void) 94 { 95 if (peekc == 0) 96 peekc = getcd(); 97 return (peekc); 98 } 99 100 int verbose; 101 int 102 getach(void) 103 { 104 int c, i, prev; 105 static unsigned char inputline[128]; 106 107 c = peekc; 108 if (c != 0) { 109 peekc = 0; 110 return (c); 111 } 112 if (globp) { 113 if (*globp) 114 return (*globp++); 115 globp = 0; 116 return (lastc = EOF); 117 } 118 top: 119 if (input) { 120 if(c = *input++) 121 return (lastc = c); 122 input = 0; 123 } 124 flush(); 125 if (intty) { 126 c = read(0, inputline, sizeof inputline - 4); 127 if (c < 0) 128 return (lastc = EOF); 129 if (c == 0 || inputline[c-1] != '\n') 130 inputline[c++] = CTRL('d'); 131 if (inputline[c-1] == '\n') 132 noteinp(); 133 prev = 0; 134 /* remove nulls from input buffer */ 135 for (i = 0; i < c; i++) 136 if(inputline[i] != 0) 137 inputline[prev++] = inputline[i]; 138 inputline[prev] = 0; 139 input = inputline; 140 goto top; 141 } 142 if (read(0, inputline, 1) != 1) 143 lastc = EOF; 144 else { 145 lastc = inputline[0]; 146 if (verbose) 147 write(2, inputline, 1); 148 } 149 return (lastc); 150 } 151 152 /* 153 * Input routine for insert/append/change in command mode. 154 * Most work here is in handling autoindent. 155 */ 156 static short lastin; 157 158 int 159 gettty(void) 160 { 161 int c = 0; 162 unsigned char *cp = genbuf; 163 unsigned char hadup = 0; 164 extern int (*Pline)(); 165 int offset = Pline == numbline ? 8 : 0; 166 int ch; 167 168 if (intty && !inglobal) { 169 if (offset) { 170 holdcm = 1; 171 viprintf(" %4d ", lineDOT() + 1); 172 flush(); 173 holdcm = 0; 174 } 175 if (value(vi_AUTOINDENT) ^ aiflag) { 176 holdcm = 1; 177 if (value(vi_LISP)) 178 lastin = lindent(dot + 1); 179 gotab(lastin + offset); 180 while ((c = getcd()) == CTRL('d')) { 181 if (lastin == 0 && isatty(0) == -1) { 182 holdcm = 0; 183 return (EOF); 184 } 185 lastin = backtab(lastin); 186 gotab(lastin + offset); 187 } 188 switch (c) { 189 190 case '^': 191 case '0': 192 ch = getcd(); 193 if (ch == CTRL('d')) { 194 if (c == '0') 195 lastin = 0; 196 if (!over_strike) { 197 putchar((int)('\b' | QUOTE)); 198 putchar((int)(' ' | QUOTE)); 199 putchar((int)('\b' | QUOTE)); 200 } 201 gotab(offset); 202 hadup = 1; 203 c = getchar(); 204 } else 205 ungetchar(ch); 206 break; 207 208 case '.': 209 if (peekchar() == '\n') { 210 ignchar(); 211 noteinp(); 212 holdcm = 0; 213 return (EOF); 214 } 215 break; 216 217 case '\n': 218 hadup = 1; 219 break; 220 } 221 } 222 flush(); 223 holdcm = 0; 224 } 225 if (c == 0) 226 c = getchar(); 227 while (c != EOF && c != '\n') { 228 if (cp > &genbuf[LBSIZE - 2]) 229 error(gettext("Input line too long")); 230 *cp++ = c; 231 c = getchar(); 232 } 233 if (c == EOF) { 234 if (inglobal) 235 ungetchar(EOF); 236 return (EOF); 237 } 238 *cp = 0; 239 cp = linebuf; 240 if ((value(vi_AUTOINDENT) ^ aiflag) && hadup == 0 && intty && !inglobal) { 241 lastin = c = smunch(lastin, genbuf); 242 for (c = lastin; c >= value(vi_TABSTOP); c -= value(vi_TABSTOP)) 243 *cp++ = '\t'; 244 for (; c > 0; c--) 245 *cp++ = ' '; 246 } 247 CP(cp, genbuf); 248 if (linebuf[0] == '.' && linebuf[1] == 0) 249 return (EOF); 250 return (0); 251 } 252 253 /* 254 * Crunch the indent. 255 * Hard thing here is that in command mode some of the indent 256 * is only implicit, so we must seed the column counter. 257 * This should really be done differently so as to use the whitecnt routine 258 * and also to hack indenting for LISP. 259 */ 260 int 261 smunch(int col, unsigned char *ocp) 262 { 263 unsigned char *cp; 264 265 cp = ocp; 266 for (;;) 267 switch (*cp++) { 268 269 case ' ': 270 col++; 271 continue; 272 273 case '\t': 274 col += value(vi_TABSTOP) - (col % value(vi_TABSTOP)); 275 continue; 276 277 default: 278 cp--; 279 CP(ocp, cp); 280 return (col); 281 } 282 } 283 284 unsigned char *cntrlhm = (unsigned char *)"^H discarded\n"; 285 286 void 287 checkjunk(unsigned char c) 288 { 289 290 if (junkbs == 0 && c == '\b') { 291 write(2, cntrlhm, 13); 292 junkbs = 1; 293 } 294 } 295 296 void 297 setin(line *addr) 298 { 299 300 if (addr == zero) 301 lastin = 0; 302 else 303 getline(*addr), lastin = smunch(0, linebuf); 304 } 305