/* This module handles all the Input/Output of the system */ #include "kernel.h" #include "sflags.h" #include "pflags.h" #include "lflags.h" #include "bprintf.h" #include "mud.h" #include "mobile.h" #ifdef VARGS #include <stdarg.h> #endif static void kiputs (char *string, FILE *file); static void dcprnt (char *ct, FILE *file); /* ** Output Functions ** */ #define SYSBUFSIZE 4096 #define MAX_ARGS 2 #define prnt(x, f) if ((x).nest) dcprnt((x).str, f); else kiputs((x).str, f); static char *bufptr, *sysbuf; static int buflen; static int snooplev = 0; static Boolean new_line = True; /* True when next char is first in a line */ struct arg { char *str; int nest; }; static void pansi (struct arg [], FILE *); static void pcls (struct arg [], FILE *); static void ppnblind (struct arg [], FILE *); static void pfilter (struct arg [], FILE *); static void pryou (struct arg [], FILE *); static void pryour (struct arg [], FILE *); static void ppndeaf (struct arg [], FILE *); static void pndark (struct arg [], FILE *); static void pndeaf (struct arg [], FILE *); static void pfile (struct arg [], FILE *); static void prname (struct arg [], FILE *); static void pcansee (struct arg [], FILE *); struct _code { char name; int args; void (*func)(struct arg [], FILE *); }; static struct _code codes[] = {{'A', 1, pansi }, {'C', 0, pcls }, {'D', 1, ppnblind}, {'F', 1, pfilter }, {'N', 1, pryou }, {'P', 1, ppndeaf }, {'c', 1, pndark }, {'d', 1, pndeaf }, {'f', 1, pfile }, {'n', 1, pryour }, {'p', 1, prname }, {'s', 2, pcansee }}; #define NUM_CODES (sizeof codes / sizeof(struct _code)) static void start_line(FILE *file) { int i; if (new_line && snooplev > 0) { for (i = 0; i < snooplev; i++) { putc('|',file); } } } static void kiputs(char *s,FILE *file) { char *t; start_line(file); while ((t = strchr(s, '\n')) != NULL) { *t = '\0'; fputs(s,file); putc('\n', file); *t = '\n'; new_line = True; start_line(file); s = t + 1; } if (*s != '\0') { fputs(s,file); new_line = False; } } static void makebfr() { if ((bufptr = sysbuf = NEW(char, SYSBUFSIZE+BUFSIZ)) == NULL) { mudlog("ERROR: Out of Memory!"); _exit(1); } sysbuf[0] = 0; buflen = 0; } static int _code_cmp (const void *c, const void *code) { return (*((const char *)c) - ((const struct _code *)code)->name); } static int tocontinue(char **ct) { register char *s = *ct; register int n = 1; register int nest = 0; struct _code *code; for (; n; s++) { switch (*s) { case '\002': case '\003': --n; break; case '\001': if (*++s != '\001') { code = (struct _code *) bsearch(s, (char *)codes, NUM_CODES, sizeof(struct _code), _code_cmp); if (code == NULL) { mudlog("ERROR: tocontinue(): Unknown control code %3o", 0377 & *s); _exit(2); } n += code->args; nest = 1; } break; case '\0': mudlog("ERROR: tocontinue(): Buffer overrun\n"); mudlog("txt:%s", *ct); _exit(2); break; } } *ct = s; return(nest); } static void dcprnt (char *ct, FILE *file) { char *str; char bk[100]; struct arg args[MAX_ARGS+1]; struct _code *code; int n; while (*(str = ct)) { if ((ct = strchr(str, '\001')) == NULL) { kiputs(str, file); break; } *ct = '\0'; kiputs(str, file); *ct++ = '\001'; if (*ct == '\001') { kiputs("\001", file); ct++; } else { code = (struct _code *)bsearch((char *)ct, (char *)codes, NUM_CODES, sizeof(struct _code), _code_cmp); if (code == NULL) { mudlog("ERROR: dcprnt(): Unknown control code %c (%3o) \n", *ct, 0377 & *ct); mudlog("ct[0..19] = \"%s\".", mk_string(bk,ct,20,-1)); _exit(2); } else { args[0].str = ++ct; for (n = 1; n <= code->args; n++) { args[n-1].nest = tocontinue(&ct); ct[-1] = '\0'; args[n].str = ct; } code->func(args, file); for (n = 1; n <= code->args; n++) args[n].str[-1] = '\003'; } } } } static void pfilter(struct arg *args, FILE *file) { FILE *a; char x[BUFSIZ]; if ((a = popen(args[0].str, "r")) == NULL) fprintf(stderr, "[Cannot find filter ->%s]\n", args[0].str); else { while (fgets(x, sizeof x, a)) kiputs(x, file); pclose(a); } } static void pfile(struct arg *args, FILE *file) { FILE *a; char x[BUFSIZ]; if ((a = fopen(args[0].str, "r")) == NULL) fprintf(stderr, "[Cannot find file ->%s]\n", args[0].str); else { while (fgets(x, sizeof(x), a)) kiputs(x, file); fclose(a); } } static void pndeaf(struct arg *args, FILE *file) { if (!ststflg(mynum, SFL_DEAF)) prnt(args[0], file); } static void pcls(struct arg *args, FILE *file) { #if 0 if (ststflg(mynum, SFL_CLS)) prnt("\033[2J", file); /* Ansi clear screen sequence */ #endif } static void pcansee(struct arg *args, FILE *file) { int a; a = fpbns(args[0].str); if (seeplayer(a) && (a != -1)) prnt(args[1], file); } static void prname(struct arg *args, FILE *file) { kiputs(seeplayer(fpbns(args[0].str)) ? args[0].str : "Someone", file); } static void pryou (struct arg *args, FILE *file) { kiputs((fpbns(args[0].str) == mynum) ? "you" : args[0].str, file); } /* Prints "your" if player is the receiver, otherwise prints the possessive form of the receiver's name */ static void pryour (struct arg *args, FILE *file) { if (fpbns(args[0].str) == mynum) kiputs("your", file); else { kiputs(args[0].str, file); kiputs("'s", file); } } static void pndark(struct arg *args, FILE *file) { if ((!isdark()) && (!ststflg(mynum, SFL_BLIND))) prnt(args[0], file); } static void pansi(struct arg *args, FILE *file) { if (cur_player->iamon && ststflg(mynum, SFL_COLOR)) prnt(args[0], file); } static void ppndeaf(struct arg *args, FILE *file) { if (!ststflg(mynum, SFL_DEAF)) prname(args,file); } static void ppnblind(struct arg *args, FILE *file) { if (!ststflg(mynum, SFL_BLIND)) prname(args,file); } void print_buf(char *b,Boolean notself) { int plr; int ct = 0; int me = real_mynum; Boolean n1, n2; if (cur_player->in_pbfr) return; cur_player->in_pbfr = True; n1 = new_line; if (!notself) dcprnt(b, cur_player->stream); n2 = new_line; if (cur_player->iamon && ploc(mynum) < 0 && !EMPTY(pname(mynum)) && cur_player->snooped > 0) { ++snooplev; for (plr = 0; plr < max_players; plr++) { if (!is_in_game(plr)) continue; if (players[plr].snooptarget == me) { ++ct; xsetup_globals(plr); new_line = n1; print_buf(b, False); fflush(cur_player->stream); } } xsetup_globals(me); new_line = n2; --snooplev; if (ct != cur_player->snooped) { mudlog("ERROR: Internal error, snooped = %d, ct = %d, check print_buf", cur_player->snooped, ct); } } cur_player->in_pbfr = False; } void pbfr(void) { FILE *fln; if (sysbuf == NULL) { makebfr(); } if (buflen > 0 && cur_player != NULL && cur_player->stream != NULL) { print_buf(sysbuf, False); sysbuf[0] = 0; /* clear buffer */ bufptr = sysbuf; buflen = 0; new_line = True; } } void bflush(void) { if (cur_player != NULL && cur_player->stream != NULL) { pbfr(); fflush(cur_player->stream); } } void snoopcom(void) { int plr; if (!ptstflg(mynum, PFL_SNOOP)) { erreval(); return; } if (cur_player->snooptarget >= 0) { bprintf("Stopped snooping on %s.\n", pname(cur_player->snooptarget)); snoop_off(mynum); #if 0 --(players[plr].snooped); /* One less to snoop him */ cur_player->snooptarget = -1; #endif } if ((plr = pl1) < 0) { return; } else if (plr >= max_players) { bprintf("You can't snoop %s!\n", pname(plr)); return; } else if (plr == mynum) { bprintf("You can't snoop yourself!\n" ); return; } if (! do_okay( mynum, plr, PFL_NOSNOOP)) { bprintf("Your magical vision is obscured.\n"); return; } /* Is this a PRIVATE room? If so don't let them snoop. */ if (ltstflg(ploc(plr), LFL_PRIVATE) && plev(mynum) < LVL_ARCHWIZARD) { bprintf("I'm sorry, %s, but the room is private.\n", psex(mynum) ? "Madam" : "Sir"); return; } cur_player->snooptarget = plr; ++(players[plr].snooped); /* One more to snoop him */ bprintf("Started to snoop on %s.\n", pname(plr)); } /* Make player no longer snoop his target */ void snoop_off(int plr) { int target; if ((target = players[plr].snooptarget) >= 0) { players[plr].snooptarget = -1; /* One less to snoop him: */ if (--players[target].snooped < 0) players[target].snooped = 0; } } #ifdef VARGS void bprintf(char *format, ...) { va_list pvar; register int len; if(!sysbuf) makebfr(); if (cur_player == NULL) { return; va_start(pvar,format); vprintf(format, pvar); va_end(pvar); } else if (cur_player->stream == NULL) { return; } else { va_start(pvar,format); vsprintf(bufptr, format, pvar); len = strlen(bufptr); buflen += len; va_end(pvar); if (buflen >= SYSBUFSIZE) pbfr(); else bufptr += len; } } #else void bprintf(char *format, char *a1, char *a2, char *a3, char *a4, char *a5, char *a6, char *a7, char *a8, char *a9) { register int len; if (!sysbuf) makebfr(); if (cur_player == NULL) { printf( format, a1, a2, a3, a4, a5, a6, a7, a8, a9); } else { sprintf(bufptr, format, a1, a2, a3, a4, a5, a6, a7, a8, a9); len = strlen(bufptr); buflen += len; if (buflen >= SYSBUFSIZE) pbfr(); else bufptr += len; } } #endif