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