1: /*************************************************************************** 2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * 3: * is provided to you without charge, and with no warranty. You may give * 4: * away copies of JOVE, including sources, provided that this notice is * 5: * included in all the files. * 6: ***************************************************************************/ 7: 8: #include "jove.h" 9: #include "io.h" 10: #include "termcap.h" 11: 12: #ifdef MAC 13: # include "mac.h" 14: #else 15: # include <varargs.h> 16: #endif 17: 18: #ifdef MAC 19: # undef private 20: # define private 21: #endif 22: 23: #ifdef LINT_ARGS 24: private void 25: doformat(File *, char *, ...), 26: outld(long, int), 27: pad(int, int), 28: PPchar(int, char *), 29: putld(long, int), 30: puts(char *); 31: #else 32: private void 33: doformat(), 34: outld(), 35: pad(), 36: PPchar(), 37: putld(), 38: puts(); 39: #endif /* LINT_ARGS */ 40: 41: #ifdef MAC 42: # undef private 43: # define private static 44: #endif 45: 46: 47: char mesgbuf[MESG_SIZE]; 48: 49: /* VARARGS2 */ 50: 51: void 52: format(buf, len, fmt, ap) 53: char *buf, 54: *fmt; 55: va_list ap; 56: { 57: File strbuf, 58: *sp = &strbuf; 59: 60: sp->f_ptr = sp->f_base = buf; 61: sp->f_fd = -1; /* Not legit for files */ 62: sp->f_cnt = len; 63: sp->f_flags = F_STRING; 64: sp->f_bufsize = len; 65: 66: doformat(sp, fmt, ap); 67: putc('\0', sp); 68: } 69: 70: #ifdef IBMPC 71: int specialmap = 0, 72: specialkey = 0; 73: 74: #define Empty "" 75: 76: char *altseq[133] = { 77: Empty, Empty, Empty, "Ctrl-@", Empty, Empty, Empty, Empty, 78: Empty, Empty, Empty, Empty, Empty, Empty, Empty, "Left", 79: "Alt-Q", "Alt-W", "Alt-E", "Alt-R", "Alt-T", "Alt-Y", "Alt-U", "Alt-I", 80: "Alt-O", "Alt-P", Empty, Empty, Empty, Empty, "Alt-A", "Alt-S", 81: "Alt-D", "Alt-F", "Alt-G", "Alt-H", "Alt-J", "Alt-K", "Alt-L", Empty, 82: Empty, Empty, Empty, Empty, "Alt-Z", "Alt-X", "Alt-C", "Alt-V", 83: "Alt-B", "Alt-N", "Alt-M", Empty, Empty, Empty, Empty, Empty, 84: Empty, Empty, Empty, "F1", "F2", "F3", "F4", "F5", 85: "F6", "F7", "F8", "F9", "F10", Empty, Empty, "Home", 86: "Up", "PageUp", Empty, "Left", Empty, "Right", Empty, "End", 87: "Down", "PageDown", "Ins", "Del", "Shift F1", "Shift F2", "Shift F3", "Shift F4", 88: "Shift F5", "Shift F6", "Shift F7", "Shift F8", "Shift F9", "Shift F10", "Ctrl F1", "Ctrl F2", 89: "Ctrl F3", "Ctrl F4", "Ctrl F5", "Ctrl F6", "Ctrl F7", "Ctrl F8", "Ctrl F9", "Ctrl F10", 90: "Alt F1", "Alt F2", "Alt F3", "Alt F4", "Alt F5", "Alt F6", "Alt F7", "Alt F8", 91: "Alt F9", "Alt F10", "Ctrl PrtSc", "Ctrl Left", "Ctrl Right", "Ctrl End", "Ctrl PageDown", "Ctrl Home", 92: "Alt 1", "Alt 2", "Alt 3", "Alt 4", "Alt 5", "Alt 6", "Alt 7", "Alt 8", 93: "Alt 9", "Alt 0", "Alt Minus", "Alt Equals", "Ctrl PageUp" 94: }; 95: #endif 96: 97: 98: private void 99: PPchar(c, str) 100: int c; 101: char *str; 102: { 103: char *cp = str; 104: 105: #ifdef IBMPC 106: if (specialmap || specialkey) { 107: if (c < 0 || c > 132) 108: c = 0; 109: strcpy(cp, altseq[c]); 110: } else 111: #endif 112: if (c == '\033') 113: strcpy(cp, "ESC"); 114: #ifdef IBMPC /* this character is invisible */ 115: else if (c == '\377') { 116: *cp = 0; 117: } 118: #endif /* IBMPC */ 119: else if (c < ' ') 120: sprintf(cp, "C-%c", c + '@'); 121: else if (c == '\177') 122: strcpy(cp, "^?"); 123: else 124: sprintf(cp, "%c", c); 125: } 126: 127: private struct fmt_state { 128: int precision, 129: width, 130: leftadj; 131: char padc; 132: File *iop; 133: } current_fmt; 134: 135: private void 136: putld(d, base) 137: long d; 138: { 139: int length = 1; 140: long tmpd = d; 141: 142: if (current_fmt.width == 0 && current_fmt.precision) { 143: current_fmt.width = current_fmt.precision; 144: current_fmt.padc = '0'; 145: } 146: while (tmpd = (tmpd / base)) 147: length += 1; 148: if (d < 0) 149: length += 1; 150: if (!current_fmt.leftadj) 151: pad(current_fmt.padc, current_fmt.width - length); 152: if (d < 0) { 153: putc('-', current_fmt.iop); 154: d = -d; 155: } 156: outld(d, base); 157: if (current_fmt.leftadj) 158: pad(current_fmt.padc, current_fmt.width - length); 159: } 160: 161: private void 162: outld(d, base) 163: long d; 164: { 165: register long n; 166: static char chars[] = {'0', '1', '2', '3', '4', '5', '6', 167: '7', '8', '9', 'a', 'b', 'c', 'd', 168: 'e', 'f'}; 169: 170: if (n = (d / base)) 171: outld(n, base); 172: putc((int) (chars[(int) (d % base)]), current_fmt.iop); 173: } 174: 175: private void 176: puts(str) 177: char *str; 178: { 179: int length; 180: register char *cp; 181: 182: if (str == 0) 183: #if pyr 184: str = ""; 185: #else 186: str = "(null)"; 187: #endif 188: length = strlen(str); 189: if (current_fmt.precision == 0 || length < current_fmt.precision) 190: current_fmt.precision = length; 191: else 192: length = current_fmt.precision; 193: cp = str; 194: if (!current_fmt.leftadj) 195: pad(' ', current_fmt.width - length); 196: while (--current_fmt.precision >= 0) 197: putc(*cp++, current_fmt.iop); 198: if (current_fmt.leftadj) 199: pad(' ', current_fmt.width - length); 200: } 201: 202: private void 203: pad(c, amount) 204: register int c, 205: amount; 206: { 207: while (--amount >= 0) 208: putc(c, current_fmt.iop); 209: } 210: 211: private void 212: doformat(sp, fmt, ap) 213: register File *sp; 214: register char *fmt; 215: va_list ap; 216: { 217: register char c; 218: struct fmt_state prev_fmt; 219: 220: prev_fmt = current_fmt; 221: current_fmt.iop = sp; 222: 223: while (c = *fmt++) { 224: if (c != '%') { 225: putc(c, current_fmt.iop); 226: continue; 227: } 228: 229: current_fmt.padc = ' '; 230: current_fmt.precision = current_fmt.leftadj = current_fmt.width = 0; 231: c = *fmt++; 232: if (c == '-') { 233: current_fmt.leftadj = YES; 234: c = *fmt++; 235: } 236: if (c == '0') { 237: current_fmt.padc = '0'; 238: c = *fmt++; 239: } 240: while (c >= '0' && c <= '9') { 241: current_fmt.width = current_fmt.width * 10 + (c - '0'); 242: c = *fmt++; 243: } 244: if (c == '*') { 245: current_fmt.width = va_arg(ap, int); 246: c = *fmt++; 247: } 248: if (c == '.') { 249: c = *fmt++; 250: while (c >= '0' && c <= '9') { 251: current_fmt.precision = current_fmt.precision * 10 + (c - '0'); 252: c = *fmt++; 253: } 254: if (c == '*') { 255: current_fmt.precision = va_arg(ap, int); 256: c = *fmt++; 257: } 258: } 259: reswitch: 260: /* At this point, fmt points at one past the format letter. */ 261: switch (c) { 262: case '%': 263: putc('%', current_fmt.iop); 264: break; 265: 266: case 'O': 267: case 'D': 268: case 'X': 269: putld(va_arg(ap, long), (c == 'O') ? 8 : 270: (c == 'D') ? 10 : 16); 271: break; 272: 273: case 'b': 274: { 275: Buffer *b = va_arg(ap, Buffer *); 276: 277: puts(b->b_name); 278: break; 279: } 280: 281: case 'c': 282: putc(va_arg(ap, int), current_fmt.iop); 283: break; 284: 285: case 'o': 286: case 'd': 287: case 'x': 288: putld((long) va_arg(ap, int), (c == 'o') ? 8 : 289: (c == 'd') ? 10 : 16); 290: break; 291: 292: case 'f': /* current command name gets inserted here! */ 293: puts(LastCmd->Name); 294: break; 295: 296: case 'l': 297: c = CharUpcase(*++fmt); 298: goto reswitch; 299: 300: case 'n': 301: if (va_arg(ap, int) != 1) 302: puts("s"); 303: break; 304: 305: case 'p': 306: { 307: char cbuf[20]; 308: 309: PPchar(va_arg(ap, int), cbuf); 310: puts(cbuf); 311: break; 312: } 313: 314: case 's': 315: puts(va_arg(ap, char *)); 316: break; 317: 318: default: 319: complain("Unknown format directive: \"%%%c\"", c); 320: } 321: } 322: current_fmt = prev_fmt; 323: } 324: 325: /* VARARGS1 */ 326: 327: char * 328: sprint(fmt, va_alist) 329: char *fmt; 330: va_dcl 331: { 332: va_list ap; 333: static char line[100]; 334: 335: va_start(ap); 336: format(line, sizeof line, fmt, ap); 337: va_end(ap); 338: return line; 339: } 340: 341: /* VARARGS1 */ 342: 343: void 344: printf(fmt, va_alist) 345: char *fmt; 346: va_dcl 347: { 348: va_list ap; 349: 350: va_start(ap); 351: #ifndef IBMPC 352: doformat(stdout, fmt, ap); 353: #else /* IBMPC */ 354: write_em(sprint(fmt, ap)); 355: /* doformat(stdout, fmt, ap); */ 356: #endif /* IBMPC */ 357: va_end(ap); 358: } 359: 360: /* VARARGS1 */ 361: 362: void 363: fprintf(fp, fmt, va_alist) 364: File *fp; 365: char *fmt; 366: va_dcl 367: { 368: va_list ap; 369: 370: va_start(ap); 371: doformat(fp, fmt, ap); 372: va_end(ap); 373: } 374: 375: /* VARARGS2 */ 376: 377: void 378: sprintf(str, fmt, va_alist) 379: char *str, 380: *fmt; 381: va_dcl 382: { 383: va_list ap; 384: 385: va_start(ap); 386: format(str, 130, fmt, ap); 387: va_end(ap); 388: } 389: 390: /* VARARGS1 */ 391: 392: void 393: s_mess(fmt, va_alist) 394: char *fmt; 395: va_dcl 396: { 397: va_list ap; 398: 399: if (InJoverc) 400: return; 401: va_start(ap); 402: format(mesgbuf, sizeof mesgbuf, fmt, ap); 403: va_end(ap); 404: message(mesgbuf); 405: } 406: 407: /* VARARGS1 */ 408: 409: void 410: f_mess(fmt, va_alist) 411: char *fmt; 412: va_dcl 413: { 414: va_list ap; 415: 416: va_start(ap); 417: format(mesgbuf, sizeof mesgbuf, fmt, ap); 418: va_end(ap); 419: DrawMesg(NO); 420: UpdMesg = YES; /* still needs updating (for convenience) */ 421: } 422: 423: /* VARARGS1 */ 424: 425: void 426: add_mess(fmt, va_alist) 427: char *fmt; 428: va_dcl 429: { 430: int mesg_len = strlen(mesgbuf); 431: va_list ap; 432: 433: if (InJoverc) 434: return; 435: va_start(ap); 436: format(&mesgbuf[mesg_len], (sizeof mesgbuf) - mesg_len, fmt, ap); 437: va_end(ap); 438: message(mesgbuf); 439: }