1 /*- 2 * Copyright (c) 1980 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)ex_get.c 7.10 (Berkeley) 04/17/91"; 10 #endif /* not lint */ 11 12 #include "ex.h" 13 #include "ex_tty.h" 14 15 /* 16 * Input routines for command mode. 17 * Since we translate the end of reads into the implied ^D's 18 * we have different flavors of routines which do/don't return such. 19 */ 20 static bool junkbs; 21 short lastc = '\n'; 22 23 ignchar() 24 { 25 ignore(ex_getchar()); 26 } 27 28 ex_getchar() 29 { 30 register int c; 31 32 do 33 c = getcd(); 34 while (!globp && c == CTRL('d')); 35 return (c); 36 } 37 38 getcd() 39 { 40 register int c; 41 42 again: 43 c = getach(); 44 if (c == EOF) 45 return (c); 46 c &= TRIM; 47 if (!inopen) 48 if (!globp && c == CTRL('d')) 49 setlastchar('\n'); 50 else if (junk(c)) { 51 checkjunk(c); 52 goto again; 53 } 54 return (c); 55 } 56 57 peekchar() 58 { 59 60 if (peekc == 0) 61 peekc = ex_getchar(); 62 return (peekc); 63 } 64 65 peekcd() 66 { 67 if (peekc == 0) 68 peekc = getcd(); 69 return (peekc); 70 } 71 72 getach() 73 { 74 register int c; 75 static char inputline[BUFSIZ]; 76 77 c = peekc; 78 if (c != 0) { 79 peekc = 0; 80 return (c); 81 } 82 if (globp) { 83 if (*globp) 84 return (*globp++); 85 globp = 0; 86 return (lastc = EOF); 87 } 88 top: 89 if (input) { 90 if (c = *input++) { 91 if (c &= TRIM) 92 return (lastc = c); 93 goto top; 94 } 95 input = 0; 96 } 97 flush(); 98 if (intty) { 99 c = read(0, inputline, sizeof inputline - 4); 100 if (c < 0) 101 return (lastc = EOF); 102 if (c == 0 || inputline[c-1] != '\n') 103 inputline[c++] = CTRL('d'); 104 if (inputline[c-1] == '\n') 105 noteinp(); 106 inputline[c] = 0; 107 for (c--; c >= 0; c--) 108 if (inputline[c] == 0) 109 inputline[c] = QUOTE; 110 input = inputline; 111 goto top; 112 } 113 c = read(0, inputline, sizeof inputline - 1); 114 if(c <= 0) 115 return(lastc = EOF); 116 inputline[c] = '\0'; 117 input = inputline; 118 goto top; 119 } 120 121 /* 122 * Input routine for insert/append/change in command mode. 123 * Most work here is in handling autoindent. 124 */ 125 static short lastin; 126 127 gettty() 128 { 129 register int c = 0; 130 register char *cp = genbuf; 131 char hadup = 0; 132 int numbline(); 133 extern int (*Pline)(); 134 int offset = Pline == numbline ? 8 : 0; 135 int ch; 136 137 if (intty && !inglobal) { 138 if (offset) { 139 holdcm = 1; 140 ex_printf(" %4d ", lineDOT() + 1); 141 flush(); 142 holdcm = 0; 143 } 144 if (value(AUTOINDENT) ^ aiflag) { 145 holdcm = 1; 146 #ifdef LISPCODE 147 if (value(LISP)) 148 lastin = lindent(dot + 1); 149 #endif 150 tab(lastin + offset); 151 while ((c = getcd()) == CTRL('d')) { 152 if (lastin == 0 && isatty(0) == -1) { 153 holdcm = 0; 154 return (EOF); 155 } 156 lastin = backtab(lastin); 157 tab(lastin + offset); 158 } 159 switch (c) { 160 161 case '^': 162 case '0': 163 ch = getcd(); 164 if (ch == CTRL('d')) { 165 if (c == '0') 166 lastin = 0; 167 if (!OS) { 168 ex_putchar('\b' | QUOTE); 169 ex_putchar(' ' | QUOTE); 170 ex_putchar('\b' | QUOTE); 171 } 172 tab(offset); 173 hadup = 1; 174 c = ex_getchar(); 175 } else 176 ungetchar(ch); 177 break; 178 179 case '.': 180 if (peekchar() == '\n') { 181 ignchar(); 182 noteinp(); 183 holdcm = 0; 184 return (EOF); 185 } 186 break; 187 188 case '\n': 189 hadup = 1; 190 break; 191 } 192 } 193 flush(); 194 holdcm = 0; 195 } 196 if (c == 0) 197 c = ex_getchar(); 198 while (c != EOF && c != '\n') { 199 if (cp > &genbuf[LBSIZE - 2]) 200 error("Input line too long"); 201 *cp++ = c; 202 c = ex_getchar(); 203 } 204 if (c == EOF) { 205 if (inglobal) 206 ungetchar(EOF); 207 return (EOF); 208 } 209 *cp = 0; 210 cp = linebuf; 211 if ((value(AUTOINDENT) ^ aiflag) && hadup == 0 && intty && !inglobal) { 212 lastin = c = smunch(lastin, genbuf); 213 for (c = lastin; c >= value(TABSTOP); c -= value(TABSTOP)) 214 *cp++ = '\t'; 215 for (; c > 0; c--) 216 *cp++ = ' '; 217 } 218 CP(cp, genbuf); 219 if (linebuf[0] == '.' && linebuf[1] == 0) 220 return (EOF); 221 return (0); 222 } 223 224 /* 225 * Crunch the indent. 226 * Hard thing here is that in command mode some of the indent 227 * is only implicit, so we must seed the column counter. 228 * This should really be done differently so as to use the whitecnt routine 229 * and also to hack indenting for LISP. 230 */ 231 smunch(col, ocp) 232 register int col; 233 char *ocp; 234 { 235 register char *cp; 236 237 cp = ocp; 238 for (;;) 239 switch (*cp++) { 240 241 case ' ': 242 col++; 243 continue; 244 245 case '\t': 246 col += value(TABSTOP) - (col % value(TABSTOP)); 247 continue; 248 249 default: 250 cp--; 251 CP(ocp, cp); 252 return (col); 253 } 254 } 255 256 char *cntrlhm = "^H discarded\n"; 257 258 checkjunk(c) 259 char c; 260 { 261 262 if (junkbs == 0 && c == '\b') { 263 write(2, cntrlhm, 13); 264 junkbs = 1; 265 } 266 } 267 268 line * 269 setin(addr) 270 line *addr; 271 { 272 273 if (addr == zero) 274 lastin = 0; 275 else 276 getline(*addr), lastin = smunch(0, linebuf); 277 } 278