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