dyrt/
dyrt/bin/
dyrt/data/MAIL/
dyrt/data/WIZ_ZONES/
dyrt/include/machine/
dyrt/src/misc/cpp/
/* This module handles all the Input/Output of the system */

/* The file has been changed accordingly to handle a color parser written by
 * ErIC (ic@ludd.luth.se) for Northern Lights. Colorcode at end of file. */

#include "kernel.h"
#include "stdinc.h"

/* included to make send_msg's possible in snoop -Vitastjern */
#include "sendsys.h"

#include "utils.h"
#include "mud.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 *);
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, buff[32768], buff2[65536];
  
  if (strchr (s, '&') != NULL && strlen (s) <= 32768)
    {
      strcpy (buff, s);
      fix_color ((unsigned char *) buff2, (unsigned char *) buff);
    }
  else
    strcpy (buff2, s);
  
  s = buff2;
  
  start_line (file);
  while ((t = (char *) strchr (s, '\n')) != NULL)
    {
      *t = '\0';
      fputs (s, file);
      if (ststflg (mynum, SFL_COLOR))
	fputs ("\033[40m\033[0m", file);
      fputs ("\r\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, 2 * 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 = (char *) index (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 = (FILE *) bopen (args[0].str)) == NULL)
    fprintf (stderr, "ERROR: Cannot find file ->%s\n", args[0].str);
  else
    {
      while (fgets (x, sizeof (x), a))
	kiputs (x, file);
      bclose (a);
    }
}


static void
pndeaf (struct arg *args, FILE * file)
{
  if (!ststflg (mynum, SFL_DEAF))
    prnt (args[0], file);
}

#define CLS "\033[2J\033[H\014"
void
pcls (struct arg *args, FILE * file)
{
  bprintf (CLS);
}


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)
{
  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 ((plr = cur_player->snooptarget) >= 0)
    {
      bprintf ("Stopped snooping on %s.\n", pname (plr));

      --(players[plr].snooped);	/* One less to snoop him */
      cur_player->snooptarget = -1;

      /* Message to the snooped person. */
      if (plev (mynum) < LVL_ARCHWIZARD)
	{
	  send_msg (plr, 0, LVL_MIN, LVL_MAX, NOBODY, NOBODY,
		    "%s has stopped snooping on you.\n", pname (mynum));

#ifdef LOG_SNOOP
  mudlog ("%s stopped SNOOPing %s", pname (mynum), pname (plr));
#endif

	  send_msg (DEST_ALL, MODE_COLOR|MODE_QUIET, LVL_GOD, LVL_MAX, 
		    NOBODY, NOBODY,"[%s stopped snooping %s]\n",
		    pname(mynum),pname(plr));
	}

    }
  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) ||
       ltstflg (ploc (plr), LFL_NO_SNOOP)) &&
      plev (mynum) < LVL_ARCHWIZARD)
    {
      bprintf ("I'm sorry, %s, but that room is ",
	       psex (mynum) ? "Madam" : "Sir");
      if (ltstflg (ploc (plr), LFL_PRIVATE))
	bprintf ("private.\n");
      else
	bprintf ("hidden for snoops.\n");

      return;
    }

  /* Message to the snooped person. */
  if (plev (mynum) < LVL_ARCHWIZARD)
    {
      send_msg (plr, 0, LVL_MIN, LVL_MAX, NOBODY, NOBODY,
		"%s has started to snoop on you.\n", pname (mynum));
    }
  send_msg (DEST_ALL, MODE_COLOR, LVL_GOD, LVL_MAX, NOBODY, NOBODY,
	  "[%s has started to snoop on %s.]\n", pname (mynum), pname (plr));

  cur_player->snooptarget = plr;
  ++(players[plr].snooped);	/* One more to snoop him */

  bprintf ("Started to snoop on %s.\n", pname (plr));


#ifdef LOG_SNOOP
  mudlog ("%s started SNOOPing %s.", pname (mynum), pname (plr));
#endif

}

#ifdef VARGS

void
bprintf (char *format,...)
{
  va_list pvar;
  register int len;

  if (!sysbuf)
    makebfr ();

  if (cur_player == NULL)
    {
      return;
/* code AFTER return? why?
 * 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





/* Color parser written by ErIC (ic@ludd.luth.se) for Northern Lights, 1993
 * You may change, add and use to this code as long as this text is still in
 * the file. If you find any bugs that is traceable to the original code,
 * please contact Northern Lights so that we can fix it there as well. ;) */

#define colorcode(x) ( (x>=64 && x<=127) ? color_table[x-64] : 0 )

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,
};

void
fix_color (unsigned char *dest, unsigned char *src)
{
  while (*src != 0)
    {
      if (*src == '\a' && ststflg(mynum, SFL_NOBEEP)) src++;
      else if (*src != '&')
	{
	  *dest++ = *src++;
	}
      else
	{
	  switch (*(src + 1))
	    {

	    case '&':
	      src += 2;
	      *dest++ = '&';
	      continue;

	    case '+':
	      if (colorcode (*(src + 2)))
		{
		  if (ststflg (mynum, SFL_COLOR))
		    {
		      strcpy ((char *) dest, "\033[1;30m");
		      dest[5] = colorcode (*(src + 2));
		      if (*(src + 2) >= 96)
			dest[2] = '0';
		      dest += 7;
		    }
		  src += 3;
		  continue;
		}
	      else
		{
		  *dest++ = *src++;
		  continue;
		}

	    case '-':
	      if (colorcode (*(src + 2)))
		{
		  if (ststflg (mynum, SFL_COLOR))
		    {
		      strcpy ((char *) dest, "\033[1;40m");
		      dest[5] = colorcode (*(src + 2));
		      if (*(src + 2) >= 96)
			dest[2] = '0';
		      dest += 7;
		    }
		  src += 3;
		  continue;
		}
	      else
		{
		  *dest++ = *src++;
		  continue;
		}

	    case '=':
	      if (colorcode (*(src + 2)) && colorcode (*(src + 3)))
		{
		  if (ststflg (mynum, SFL_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;
		    }
		  src += 4;
		  continue;
		}
	      else
		{
		  *dest++ = *src++;
		  continue;
		}

	    case '*':
	      if (ststflg (mynum, SFL_COLOR))
		{
		  strcpy ((char *) dest, "\033[40m\033[0m");
		  dest += strlen ((char *) dest);
		}
	      src += 2;
	      continue;

	    default:
	      *dest++ = *src++;
	      continue;
	    }
	}
    }
  *dest = 0;
}

/**/

/* 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;
    }
}