#include <stdarg.h>
#include <sys/file.h>
#include <stdlib.h>
#include "kernel.h"
#include "sflags.h"
#include "mobile.h"
#include "mud.h"
#include "rooms.h"
#include "bprintf.h"
char color_table[] =
{ /* Not beautiful, but efficient :) */
0, 0, '4', '6',
0, 0, 0, '2',
0, 0, 0, 0,
'0', '5', 0, 0,
0, 0, '1', 0,
0, 0, 0, '7',
0, '3', 0, 0,
0, 0, 0, 0,
0, 0, '4', '6',
0, 0, 0, '2',
0, 0, 0, 0,
'0', '5', 0, 0,
0, 0, '1', 0,
0, 0, 0, '7',
0, '3', 0, 0,
0, 0, 0, 0,
};
#define colorcode(x) ((x >= 64 && x <= 127) ? color_table[x-64]: 0)
unsigned char *dest;
void strip_color (char *dests, char *srcs) {
unsigned char *out = dests;
unsigned char *src = srcs;
while (*src != 0) {
if (*src != '&') {
*out++ = *src++;
}
else {
switch (*(src + 1)) {
case '&':
src += 2; *out++ = '&';
continue;
case '+': case '-':
if (colorcode (*(src + 2)))
src += 3;
else
*out++ = *src++;
continue;
case '=':
if (colorcode (*(src + 2)) && colorcode (*(src + 3)))
src += 4;
else
*out++ = *src++;
continue;
case '*': case 'B': case 'N': case 'n': case '#':
src += 2;
continue;
default:
*out++ = *src++;
continue;
}
}
}
*out = 0;
}
int count_colors(char *inp) {
int nchars = 0;
unsigned char *src = inp;
while (*src != 0) {
if (*src != '&')
src++;
else {
switch (*(src + 1)) {
case '+': case '-':
if (colorcode (*(src + 2)))
nchars += 3;
src++;
continue;
case '=':
if (colorcode (*(src + 2)) && colorcode (*(src + 3)))
nchars += 4;
src ++;
continue;
case '*': case 'B': case 'N': case '#': case '&': case 'n':
nchars += 2;
src++;
continue;
default:
src++;
continue;
}
}
}
return nchars;
}
void snoop_txt(int me, char *buffer) {
Boolean has_color;
char snoopbuff[50];
int plx;
for (plx = 0 ; plx < max_players ; plx++)
if (snooptarget(plx) == me && is_in_game(plx)) {
setup_globals(plx);
has_color = ststflg(real_mynum, SFL_COLOR);
dest = NULL;
if (out_write(real_mynum) == out_buffer(real_mynum)) {
sprintf(snoopbuff, "&+r[&+WSnoop: &+M%s&+r]&N ",
pname(snooptarget(real_mynum)));
ADD_LINE(snoopbuff);
}
ADD_LINE(buffer);
output(real_mynum) = True;
out_write(real_mynum) = dest;
}
setup_globals(me);
}
/* main output function, maximum length of all args passed is M_BUFFLEN */
void bprintf (char *format, ...) {
va_list pvar;
static char buffer[M_BUFFLEN];
int me = real_mynum;
Boolean has_color;
if (me < 0 || me >= max_players || cur_player == NULL || !is_conn(me))
return;
has_color = ststflg(me, SFL_COLOR);
va_start(pvar, format);
vsprintf(buffer, format, pvar);
va_end(pvar);
dest = NULL;
ADD_LINE(buffer);
output(me) = True;
out_write(me) = dest;
if (islogged(me))
write_plr_log(buffer);
if (snooped(me))
snoop_txt(me, buffer);
}
/* colorsel: pick a color for a string based on a percentage */
void colorsel(int cur, int max, char *str) {
char mod[4] = "&+";
float percent;
char newstr[500];
percent = ((float) cur / (float) max) * 100;
if (percent < 11) mod[2] = 'r';
else if (percent < 22) mod[2] = 'R';
else if (percent < 33) mod[2] = 'Y';
else if (percent < 44) mod[2] = 'b';
else if (percent < 55) mod[2] = 'B';
else if (percent < 66) mod[2] = 'c';
else if (percent < 77) mod[2] = 'C';
else if (percent < 88) mod[2] = 'g';
else mod[2] = 'G';
mod[3] = '\0';
strcpy(newstr, mod);
strcat(newstr, str);
strcat(newstr, "&+w");
strcpy(str, newstr);
}
void init_memory(void) {
int readlen = out_read(real_mynum) - out_buffer(real_mynum);
int writelen;
if (!dest) {
writelen = out_write(real_mynum) - out_buffer(real_mynum);
dest = out_write(real_mynum);
}
else writelen = dest - out_buffer(real_mynum);
if (out_size(real_mynum) - writelen < HIGH_MARK) {
out_buffer(real_mynum) = (unsigned char *)
resize_array(out_buffer(real_mynum), sizeof(char),
out_size(real_mynum), M_BUFFLEN + out_size(real_mynum));
out_write(real_mynum) = dest = out_buffer(real_mynum) + writelen;
out_read(real_mynum) = out_buffer(real_mynum) + readlen;
out_size(real_mynum) += M_BUFFLEN;
}
}
/* strformat: add/format a string (with color) onto dest */
void strformat (char *srcs, Boolean has_color) {
register unsigned char *src = srcs;
Boolean is_color = False;
init_memory();
while (*src != 0) {
if (*src != '&' && !(iscntrl(*src))) /* normal case */
*dest++ = *src++;
else if (*src == '\n') { /* newline needs LF */
*dest++ = *src++; *dest++ = '\r';
if (is_color) {
strcpy ((char *) dest, CRESET);
is_color = False;
dest += 9;
}
}
else if (*src == '&') /* Color code */
src = do_colorcode(src, &is_color, has_color);
else
src = do_specialcode(src, has_color); /* \001[X][Arg] */
}
if (is_color) { /* reset text after line */
strcpy ((char *) dest, CRESET);
is_color = False;
dest += 9;
}
*dest = 0;
}
char * do_colorcode(char *srcs, Boolean *is_color, Boolean has_color)
{
static unsigned char *src;
src = srcs;
switch (*(src + 1)) {
case '&':
src += 2; *dest++ = '&';
break;
case '+':
if (colorcode (*(src + 2))) {
if (has_color) {
strcpy ((char *) dest, "\033[1;30m");
dest[5] = colorcode (*(src + 2));
if (*(src + 2) >= 96) dest[2] = '0';
dest += 7;
*is_color = True;
}
src += 3;
} else
*dest++ = *src++;
break;
case '-':
if (colorcode (*(src + 2))) {
if (has_color) {
strcpy ((char *) dest, "\033[1;40m");
dest[5] = colorcode (*(src + 2));
if (*(src + 2) >= 96) dest[2] = '0';
dest += 7;
*is_color = True;
}
src += 3;
}
else *dest++ = *src++;
break;
case '=':
if (colorcode (*(src + 2)) && colorcode (*(src + 3))) {
if (has_color) {
strcpy ((char *) dest, "\033[1;40;30m");
dest[5] = colorcode (*(src + 3));
dest[8] = colorcode (*(src + 2));
if (*(src + 2) >= 96)
dest[2] = '0';
dest += 10;
*is_color = True;
}
src += 4;
}
else *dest++ = *src++;
break;
case '*': case 'N': case 'n':
if (has_color) {
strcpy ((char *) dest, CRESET);
dest += 9;
*is_color = False;
}
src += 2;
break;
case 'B':
if (has_color && !ststflg (real_mynum, SFL_NOBLINK)) {
strcpy ((char *) dest, "\033[5m");
dest += 4;
*is_color = True;
}
src += 2;
break;
/* Carriage return */
case '/':
strcpy ((char *) dest, "\r\n");
dest += 2; src += 2;
break;
case '#':
if (!ststflg (real_mynum, SFL_NOBEEP)) {
strcpy ((char *) dest, "\a");
dest++;
}
src += 2;
break;
default:
*dest++ = *src++;
break;
}
return src;
}
char *do_specialcode(char *srcs, Boolean has_color) {
char *delim, *src;
static char arg[256];
int i;
src = srcs;
if (*src == 001) { /* special code */
delim = ++src;
for (src++, i = 0; *src && *src != 003 ; src++, i++)
arg[i] = *src;
arg[i] = 0; src++;
switch(*delim) {
case 'A':
if (is_conn(real_mynum) && has_color)
ADD_LINE(arg);
break;
case 'C':
ADD_LINE("\033[2J\033[H");
break;
case 'D':
if (!ststflg(mynum, SFL_BLIND))
SHOWNAME(arg);
break;
case 'E': /* IAC Echo */
strcpy(dest, "\377\374\001");
dest += 4;
break;
case 'F':
pfilter(arg, has_color);
break;
case 'N':
ADD_LINE((fmbn (arg) == mynum) ? "you" : arg);
break;
case 'P':
if (!ststflg(mynum, SFL_DEAF))
SHOWNAME(arg);
break;
case 'R': /* IAC NO Echo */
strcpy(dest, "\377\373\001");
dest += 4;
break;
case 'V':
ADD_LINE (VERSION);
break;
case '@':
ADD_LINE (EMAIL);
break;
case '$':
ADD_LINE (MUD_NAME);
break;
case 'U':
ADD_LINE (MASTERUSER);
break;
case '#':
sprintf(dest, "%d", PORT);
dest += 4;
break;
case 'T':
ADD_LINE (LASTBUILD);
break;
case 'H':
ADD_LINE (_HOSTNAME_);
break;
case 'O':
ADD_LINE (_OS_);
break;
case '~':
ADD_LINE (_ARCH_);
break;
case 'c':
if ((!isdark ()) && (!ststflg (mynum, SFL_BLIND)))
ADD_LINE (arg);
break;
case 'd':
if (!ststflg(mynum, SFL_DEAF))
ADD_LINE(arg);
break;
case 'f':
file_pager(arg, has_color);
break;
case 'n':
if (fmbn (arg) == mynum)
ADD_LINE ("your");
else {
ADD_LINE (arg);
ADD_LINE ("'s");
}
break;
case 'p':
SHOWNAME(arg);
break;
}
}
else
*dest++ = *src++; /* something unknown */
return src;
}
void file_pager (char filename[512], Boolean has_color) {
FILE *file;
if (!ppager (mynum)) {
pfile (filename, has_color);
return;
}
if ((file = FOPEN(filename, "r")) == NULL) {
mudlog ("ERROR: Cannot read file: %s", filename);
return;
}
cur_player->pager.old_handler = (INP_HANDLER *) phandler(real_mynum);
strcpy(cur_player->pager.prompt, cur_player->cprompt); /* store old prompt */
strcpy(cur_player->cprompt, qwait);
cur_player->inpager = True;
cur_player->pager.file = file;
replace_input_handler (pager);
pager (NULL);
}
void quit_pager (void) {
cur_player->inpager = False;
replace_input_handler ((void *) cur_player->pager.old_handler);
FCLOSE(cur_player->pager.file);
strcpy(cur_player->cprompt, cur_player->pager.prompt);
}
void apply_filecodes(char *inputstr) {
char *b, *p, *buff;
buff = COPY(inputstr);
for (p = buff, b = inputstr ; *p ; p++) {
if (*p != '&')
*b++ = *p;
else {
switch (*(p+1)) {
case 'V':
strcpy(b, VERSION);
break;
case '@':
strcpy(b, EMAIL);
break;
case '$':
strcpy(b, MUD_NAME);
break;
case 'U':
strcpy(b, MASTERUSER);
break;
case '?':
strcpy(b, HOMEPAGE);
break;
case '#':
sprintf(b, "%d", PORT);
break;
case 'T':
strcpy(b, LASTBUILD);
break;
case 'H':
strcpy(b, _HOSTNAME_);
break;
case 'O':
strcpy(b, _OS_);
break;
case '~':
strcpy(b, _ARCH_);
break;
default:
*b++ = *p;
continue;
}
b += strlen(b);
p++;
}
}
*b = 0;
FREE(buff);
}
void pager (char *c) {
Boolean has_color = ststflg(real_mynum, SFL_COLOR);
char ch[256];
int ct;
if (c == NULL || tolower(*c) != 'q') {
for (ct = 1 ; ct < ppager(real_mynum) ; ct++) {
fgets(ch, 255, cur_player->pager.file);
if (!feof(cur_player->pager.file)) {
if (c == NULL) {
apply_filecodes(ch);
ADD_LINE(ch);
}
else
bprintf("%s", ch);
}
else {
quit_pager();
return;
}
}
}
else
quit_pager();
}
void pfile (char *filename, Boolean has_color) {
FILE *a;
char x[BUFSIZ];
if ((a = FOPEN(filename, "r")) == NULL)
mudlog ("ERROR: Cannot read file: %s", filename);
else {
while (fgets (x, sizeof (x), a)) {
if (!feof(a)) {
apply_filecodes(x);
ADD_LINE (x);
}
else break;
}
FCLOSE(a);
}
}
void pfilter (char *arg, Boolean has_color) {
FILE *a;
char x[BUFSIZ];
if ((a = popen (arg, "r")) == NULL)
fprintf (stderr, "[Cannot find filter ->%s]\n", arg);
else {
while (fgets (x, sizeof x, a))
ADD_LINE (x);
pclose (a);
*dest = 0;
}
}