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.6 (Berkeley) 06/07/85"; 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(getchar()); 25 } 26 27 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 = 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 struct stat statb; 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, inline, sizeof inline - 4); 100 if (c < 0) 101 return (lastc = EOF); 102 if (c == 0 || inline[c-1] != '\n') 103 inline[c++] = CTRL(d); 104 if (inline[c-1] == '\n') 105 noteinp(); 106 inline[c] = 0; 107 for (c--; c >= 0; c--) 108 if (inline[c] == 0) 109 inline[c] = QUOTE; 110 input = inline; 111 goto top; 112 } 113 c = read(0, inline, sizeof inline - 1); 114 if(c <= 0) 115 return(lastc = EOF); 116 inline[c] = '\0'; 117 input = inline; 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 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 putchar('\b' | QUOTE); 169 putchar(' ' | QUOTE); 170 putchar('\b' | QUOTE); 171 } 172 tab(offset); 173 hadup = 1; 174 c = 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 = getchar(); 198 while (c != EOF && c != '\n') { 199 if (cp > &genbuf[LBSIZE - 2]) 200 error("Input line too long"); 201 *cp++ = c; 202 c = 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