cdirt/ascii/
cdirt/data/BULL/
cdirt/data/ZONES/PENDING/
cdirt/pending/
cdirt/src/utils/
cdirt/utils/
#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;
  }
}