pdirt/data/
pdirt/data/HELP/
pdirt/data/HELP/0/
pdirt/data/HELP/F/
pdirt/data/HELP/G/
pdirt/data/HELP/H/
pdirt/data/HELP/J/
pdirt/data/HELP/K/
pdirt/data/HELP/O/
pdirt/data/HELP/Q/
pdirt/data/HELP/R/
pdirt/data/HELP/U/
pdirt/data/HELP/V/
pdirt/data/HELP/Y/
pdirt/data/HELP/Z/
pdirt/data/MESSAGES/
pdirt/data/POWERINFO/
pdirt/data/WIZ_ZONES/
pdirt/drv/
pdirt/drv/bin/
pdirt/drv/compiler/converter/
pdirt/drv/compiler/libs/
pdirt/drv/compiler/scripts/
pdirt/drv/include/AberChat/
pdirt/drv/include/InterMud/
pdirt/drv/include/machine/
pdirt/drv/src/InterMud/
pdirt/drv/src/Players/
pdirt/drv/utils/UAFPort/
pdirt/drv/utils/dnsresolv/
pdirt/drv/utils/gdbm/
/* 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. */
/* Added some new features to the color parser, like in the iDirt system */
/* Some control codes that can be used.
   If you place a \001 mark somewhere in the format and enter one of these
   codes, the following will happen:
   A : write an ansi-fied message.
   C : clear the screen.
   D : Hold in account you are blind.
   F : Dumps the contents of the file (specified after this char to the user)
       with filtering.
   N : pryou
   P : ppndeaf
   c : pndark
   d : pndeaf
   f : Dumps file to user without filtering.
   n : pryour
   p : prname
   s : pcansee
  */

#define BPRINTF_C

#include "kernel.h"
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef RS6000
#include <strings.h>
#endif
#include "config.h"
#include "sflags.h"
#include "lflags.h"
#include "pflags.h"
#include "sendsys.h"
#include "bprintf.h"
#include "utils.h"
#include "mud.h"
#include "mobile.h"
#include "misc.h"
#include "log.h"
#include "parse.h"
#include "rooms.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;
  static char snoop_prompt[40];

   
  if (new_line && snooplev > 0)
  {
      for (i = 0; i < snooplev; i++)
      {   fix_color(snoop_prompt,"&+wO&+w>&* ");
          fprintf(file,"%s",snoop_prompt);
	  /*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, BUFSIZ, 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);
  }
}

A_COMMAND(snoopcom)
{ 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 ("SNOOP: %s stopped SNOOPing %s", pname (mynum), pname (plr));
#endif

	  send_msg (DEST_ALL, MODE_BRACKET|MODE_QUIET, Max(plev(mynum),LVL_ARCHWIZARD), LVL_MAX, 
		    NOBODY, NOBODY,"%s stopped snooping %s",
		    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));
  }
  else 
     send_msg (DEST_ALL, MODE_BRACKET, LVL_GOD, LVL_MAX, NOBODY, NOBODY,
	  "%s has started to snoop on %s", 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 ("SNOOP: %s started SNOOPing %s.", pname (mynum), pname (plr));
#endif

}

size_t xstrlen(char *str)
{   size_t real_len = strlen(str);
    size_t i=0,len=0;

    while (i < real_len)
    {   if (str[i] == '&')
        {   switch(str[i+1]) {
            case '-':
            case '+': i+=3; break;
            case '*': i+=2; break;
            case '&': i+=2; len++; break;
	    case '=': i+=4; break;
            default:
		len++;
		i++;
            }
            continue;
         }
         i++;
         len++;
    }
    return len;
}

size_t bstrlen(char *str, size_t len)
{  size_t real_len = 0;

   while (str[real_len] != '\0' && len > 0)
   {  if (str[real_len] == '&')
      {  if (str[real_len+1] == '+' || str[real_len+1] == '-' || 
             str[real_len+1] == '=')
         {  real_len += 3;
         }
         else if (str[real_len+1] == '&')
         {  real_len += 2;
            len--;
         }
         else if (str[real_len+1] == '*')
         {  real_len += 2;
         }
         else 
         {  real_len++;
            len--;
         }
      }
      else if (str[real_len] >= '\001' && str[real_len] <= '\005')
      {  real_len++;
      }
      else
      {  real_len++;
         len--;
      }
   }
   return real_len;
}

char *bstrncpy(char *dest, char *src, size_t req_len)
{  size_t real_len = bstrlen(src,req_len);
   size_t i;  
   
   for (i = 0; i < real_len && src[i] != '\0'; i++)
   {   dest[i] = src[i];
   }
   dest[i] = '\0';
   return dest;
}

#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;

          /* Blinking text */
          case 'B':
              if (ststflg(mynum,SFL_COLOR)) 
              {
                 if (ststflg(mynum,SFL_NOBLINK))
                    strcpy((char *)dest,"");
                 else 
                 {   strcpy((char *)dest,"\33[5m");
                     dest += strlen((char *)dest);
                 }
              }
              src += 2;
              continue; 

          /* Beeps */
          case '#':
               if (ststflg(mynum,SFL_NOBEEP)) 
                  strcpy((char *)dest,"");
               else
                  strcpy((char *)dest,"\a");

               dest += strlen((char*)dest);
               src+=2;
               continue;
	  case 'N':
               *dest++ = '\n';
	       src+=2;
	       continue;
	  case 'T':
	      *dest++ = '\t';
	      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;
  }
}

/***************************************************************************
 ** File paging system
 ***************************************************************************/

void read_file (char *file, char *stopper, Boolean brief, char *pattern)
{ FILE *fp;
  struct stat s;
  int fdx;
  
  strcpy (cur_player->pager.old_prompt, cur_player->prompt);
  
  fp = (FILE *) bopen (file);
  if (!fp)
  {
      bprintf ("Cannot read that file.\n");
#ifdef LOG_PAGEERROR
      mudlog ("ERROR: read_file failed for %s.", file);
#endif
      return;
  }
  
  fdx = fileno (fp);
  
  if (fstat (fdx, &s) == -1)
  {
      bprintf ("Cannot read that file.\n");
#ifdef LOG_PAGEERROR
      mudlog ("ERROR: stat failed for %s.", file);
#endif
      return;
  }
  
  
  cur_player->pager.oldhandler = (INP_HANDLER *) cur_player->inp_handler->inp_handler;
/*  if (S_ISFIFO (s.st_mode))
    cur_player->pager.brief = 0;
  else
    cur_player->pager.brief = 1 - brief;*/
  cur_player->pager.file = fp;
  cur_player->pager.read = 0; 
  strncpy (cur_player->pager.stopper, stopper ? stopper : "--NONE--", 19);
  cur_player->pager.pattern = pattern;
  
  cur_player->pager.size = s.st_size;
  replace_input_handler (file_pager);
  file_pager (" ");
  return;
}

/* Smart file pager. ALso handles embedded codes.
 * Available codes are:
 * %CLEAR	- send a cls.
 * %BREAK	- force a page break
 * %EXIT	- force exit
 * %<MARKER>	- stop at <MARKER>, common used markers are the wizlevels. 
 * Also shows percentage shown. - Marty
 */
void file_pager (char *input)
{ char f[256];
  int linecount = 0;
  float percent;
  char perstr[20];
  Boolean printed = True;
  int pagelen = ppager(mynum);
  
  if (input[0] == 'q' || input[0] == 'Q')
  {				/* got a quit */
    pg_exit:

    replace_input_handler ((void *) cur_player->pager.oldhandler);
    bclose (cur_player->pager.file);
      
    strcpy (cur_player->prompt, cur_player->pager.old_prompt);

    cur_player->pager.read = 0;     /* CLear fields to make sure */
    cur_player->pager.size = 0; 
    /*bprintf ("%s", cur_player->prompt);*/
    bprintf ("%s", build_prompt(real_mynum));
    return;
  }
  
  for (linecount = 0; linecount != pagelen; linecount++)
  {
      f[0] = '\0';
      if (feof (cur_player->pager.file))
	goto pg_exit;
	
      fgets (f, 256, cur_player->pager.file);
      
      /* does it match the pattern? (if any) */
      printed = check_match (f,
			     cur_player->pager.pattern
			     ? cur_player->pager.pattern : "*",
			     True);
      
      
      cur_player->pager.read += strlen (f);
      
#ifndef CLS
#define CLS "\033[2J\033[H\014"
#endif
      
      /* embedded codes, must start at the beginning of a line. */
      if (f[0] == '%')
      {
	  if (cur_player->pager.stopper[0] != '\0')
	    if (!strncasecmp (cur_player->pager.stopper, &f[1],
			      strlen (cur_player->pager.stopper)))
	      goto pg_exit;

	    else if (!strncasecmp (&f[1], "CLEAR", 5))
	    {			/* clear screen */
		bprintf (CLS);
	    }
	    else if (!strncasecmp (&f[1], "EXIT", 4))
	    {			/* abort text file read */
		goto pg_exit;
	    }
	    else if (!strncasecmp (&f[1], "BREAK", 5))
	    {			/* force page break */
		goto pg_break;
	    }
      }
      else
      {
	  if (printed)
	    bprintf ("%s", f);
	  else
          {
	      linecount--;
	      continue;
          }
	  
      }
  }

pg_break: 
  perstr[0] = '\0';
  if (!cur_player->pager.brief)
  {
      percent = (100 * cur_player->pager.read) / cur_player->pager.size;
      sprintf (perstr, "(%d percent displayed) ", (int) percent);
  }
  
  sprintf (cur_player->prompt,
	   "%spress 'q' to abort or return to continue",
	   cur_player->pager.brief ? "" : perstr);

  /*bprintf (cur_player->prompt);*/
  bprintf ("\r%s",build_prompt(real_mynum));
  return;
}