Logo Search packages:      
Sourcecode: yabasic version File versions  Download package

io.c

/*  

    YABASIC ---  a simple Basic Interpreter
    written by Marc-Oliver Ihm 1995-2005
    homepage: www.yabasic.de
    
    io.c --- code for screen and file i/o
    
    This file is part of yabasic and  may be copied only 
    under the terms of either the Artistic License or 
    the GNU General Public License (GPL), both of which 
    can be found at www.yabasic.de

*/


/* ------------- defines ---------------- */

#ifdef WINDOWS
#define WM_WANTKEY (WM_APP+7)
#endif

/* ------------- includes ---------------- */

#ifndef YABASIC_INCLUDED
#include "yabasic.h"          /* all prototypes and structures */
#endif


/* ------------- local defines ----------------- */

#define YC_BLACK 0
#define YC_WHITE 1
#define YC_RED 2
#define YC_BLUE 3
#define YC_GREEN 4
#define YC_YELLOW 5
#define YC_CYAN 6
#define YC_MAGENTA 7

#ifndef COLOR_BLACK
#define COLOR_BLACK     0
#define COLOR_RED 1
#define COLOR_GREEN     2
#define COLOR_YELLOW    3
#define COLOR_BLUE      4
#define COLOR_MAGENTA   5
#define COLOR_CYAN      6
#define COLOR_WHITE     7
#endif
#ifndef A_COLOR
#define A_COLOR 0xff00
#endif

/* ------------- external references ---------------- */

extern int yylineno;          /* current line number */
extern int yyparse ();        /* call bison parser */


/* ------------- local functions ---------------- */

static int onechar (void);    /* read one char from currentinstream */
static void backchar (int);   /* put char back into stream */
static void readline (void);  /* read one line from current stream */
static void curinit (void);   /* initialize curses */
static void initcol (void);   /* initialize curses colors */
int checkstream (void);       /* test if currst is still valid */
#ifdef WINDOWS
static DWORD keythread (LPWORD);    /* wait for key input from console */
static int is_valid_key (INPUT_RECORD *); /* check if input rec is valid key */
#endif
int name2yc (char *);         /* convert a color name to an integer */
int yc2oc (int, int);         /* convert a yabasic color to operating system color */
char *yc2short (int);         /* convert yabasic colours to short colour name */
#ifdef UNIX
int oc2yc (int);        /* convert an operating system color to yabasic color */
#endif

/* ------------- global variables ---------------- */

static int prompted;          /* TRUE, if prompt is fresh */
int read_controls;            /* TRUE, if input should read control characters */
FILE *streams[FOPEN_MAX];     /* file streams */
int stream_modes[FOPEN_MAX];  /* modes for streams */
int lprstream = -1;           /* stream associated with lineprinter */
static int currstr = STDIO_STREAM;  /* currently switched stream */
static FILE *cinstr;          /* current stream for input */
static FILE *coutstr;         /* current stream for output */
static char linebuffer[INBUFFLEN];  /* buffer for one line of input */
int curinized = FALSE;        /* true, if curses has been initialized */
static char *currchar;        /* current char to read */
static short stdfc;           /* standard foreground color of window */
static short stdbc;           /* standard background color of window */
#ifdef UNIX
int winpid = -1;        /* pid of process waiting for window keys */
int termpid = -1;       /* pid of process waiting for terminal keys */
FILE *lineprinter = NULL;     /* handle for line printer */
#else
HANDLE wantkey = INVALID_HANDLE_VALUE;    /* mutex to signal key desire */
HANDLE gotkey = INVALID_HANDLE_VALUE;     /* mutex to signal key reception */
HANDLE wthandle = INVALID_HANDLE_VALUE;   /* handle of win thread */
HANDLE kthandle = INVALID_HANDLE_VALUE;   /* handle of inkey thread */
DWORD ktid;             /* id of inkey thread */
int LINES = 0;                /* number of lines on screen */
int COLS = 0;                 /* number of columns on screen */
HANDLE ConsoleInput;          /* handle for console input */
HANDLE ConsoleOutput;         /* handle for console output */
HANDLE lineprinter = INVALID_HANDLE_VALUE;      /* handle for line printer */
#endif


/* ------------- functions ---------------- */

void
create_print (char type)      /* create command 'print' */
{
  struct command *cmd;

  cmd = add_command (cPRINT, NULL);
  cmd->pointer = my_malloc (sizeof (int));
  /* store type of print  */
  cmd->tag = type;
}


void
print (struct command *cmd)   /* print on screen */
{
  int type;
  struct stackentry *p, *q, *r;
  static int last = 'n';
  char *s;
  int x, y;
  long int n;
  double d;
#ifdef WINDOWS
  CONSOLE_SCREEN_BUFFER_INFO csbi;
  SMALL_RECT screen;
  COORD to;
  CHAR_INFO ci;
#endif

  r = NULL;
  type = cmd->tag;
  if (!checkstream ())
    return;
  switch (type)
    {
    case 'n':                 /* print newline */
      if (curinized && coutstr == stdout)
      {
#ifdef WINDOWS
        GetConsoleScreenBufferInfo (ConsoleOutput, &csbi);
        x = csbi.dwCursorPosition.X;
        y = csbi.dwCursorPosition.Y;
        if (y >= LINES - 1)
          {
            screen.Left = 0;
            screen.Right = COLS;
            screen.Top = 1;
            screen.Bottom = LINES;
            to.X = 0;
            to.Y = 0;
            ci.Char.AsciiChar = ' ';
            ci.Attributes =
              FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
            ScrollConsoleScreenBuffer (ConsoleOutput, &screen, NULL, to,
                               &ci);
            to.X = 0;
            to.Y = y;
          }
        else
          {
            to.X = 0;
            to.Y = y + 1;
          }
        SetConsoleCursorPosition (ConsoleOutput, to);
        break;
#else
        getyx (stdscr, y, x);
        if (y >= LINES - 1)
          {
            scrl (1);
            y = y - 1;
          }
        move (y + 1, 0);
        refresh ();
        break;
#endif
      }
      else
      {
        string[0] = '\n';
        if (abs (currstr) == lprstream)
          {
            string[1] = '\r';
            string[2] = '\0';
          }
        else
          {
            string[1] = '\0';
          }
      }
      onestring (string);
      break;
    case 't':                 /* print tab */
      string[0] = '\t';
      string[1] = '\0';
      onestring (string);
      break;
    case 'd':                 /* print double value */
      p = pop (stNUMBER);
      d = p->value;
      n = (int) d;
      if (n == d && d <= LONG_MAX && d >= LONG_MIN)
      sprintf (string, "%s%ld", (last == 'd') ? " " : "", n);
      else
      sprintf (string, "%s%g", (last == 'd') ? " " : "", d);
      onestring (string);
      break;
    case 'U':
      r = pop (stSTRING);
    case 'u':                 /* print using */
      p = pop (stSTRING);
      q = pop (stNUMBER);
      type = 'd';
      s = string;
      if (last == 'd')
      {
        *s = ' ';
        s++;
      }
      if (!myformat (s, q->value, p->pointer, r ? r->pointer : NULL))
      {
        sprintf (string, "'%s' is not a valid format",
               (char *) p->pointer);
        error (ERROR, string);
        break;
      }
      onestring (string);
      break;
    case 's':
      p = pop (stSTRING);
      onestring ((char *) p->pointer);
      break;
    }
  last = type;
}


void
mymove ()               /* move to specific position on screen */
{
  int x, y;
#ifdef WINDOWS
  COORD coord;
#endif

  y = (int) pop (stNUMBER)->value;
  if (y < 0)
    y = 0;
  if (y > LINES - 1)
    y = LINES - 1;
  x = (int) pop (stNUMBER)->value;
  if (x < 0)
    x = 0;
  if (x > COLS - 1)
    x = COLS - 1;
  if (!curinized)
    {
      error (ERROR, "need to call 'clear screen' first");
      return;
    }
#ifdef UNIX
  move (y, x);
  refresh ();
#else
  coord.X = x;
  coord.Y = y;
  SetConsoleCursorPosition (ConsoleOutput, coord);
#endif
}


void
clearscreen ()                /* clear entire screen */
{
#ifdef WINDOWS
  DWORD written;        /* number of chars actually written */
  COORD coord;                /* coordinates to start writing */
#endif

  if (!curinized)
    curinit ();
#ifdef UNIX
  clear ();
  refresh ();
#else
  coord.X = 0;
  coord.Y = 0;
  FillConsoleOutputCharacter (ConsoleOutput, ' ', LINES * COLS, coord,
                        &written);
  FillConsoleOutputAttribute (ConsoleOutput,
                        FOREGROUND_RED | FOREGROUND_GREEN |
                        FOREGROUND_BLUE, LINES * COLS, coord,
                        &written);
  SetConsoleCursorPosition (ConsoleOutput, coord);
#endif
}


static void
curinit (void)                /* initialize curses */
{
#ifdef WINDOWS
  CONSOLE_SCREEN_BUFFER_INFO coninfo;     /* receives console size */
#endif

#ifdef UNIX
  initscr ();
  initcol ();
  setscrreg (0, LINES);
  scrollok (stdscr, TRUE);
  leaveok (stdscr, TRUE);
  keypad (stdscr, TRUE);
  intrflush (stdscr, FALSE);
  curs_set (0);
  def_prog_mode ();
#else
  GetConsoleScreenBufferInfo (ConsoleOutput, &coninfo);
  COLS = coninfo.srWindow.Right + 1;
  LINES = coninfo.srWindow.Bottom + 1;
  initcol ();
#endif
  curinized = TRUE;
}


char *
inkey (double maxtime)        /* get char from keyboard */
{
  char *skey;
#ifdef WINDOWS
  int ms;               /* number of milliseconds to wait */
  DWORD oflags;               /* saves normal state of console input buffer */
  DWORD flags;                /* new input mode for console input buffer */
  static char conkeybuff[100], winkeybuff[100];
#else
  fd_set readfds;
  struct timeval tv;
  int maxfd;
  int winfd[2], termfd[2];
  char retkey[100];
  int status, ret;
#endif


  if (maxtime >= 0.0 && maxtime < 0.01)
    maxtime = 0.01;
  if (!curinized)
    {
      error (ERROR, "need to call 'clear screen' first");
      return my_strdup ("");
    }
#ifdef UNIX
  retkey[0] = '\0';
  winfd[0] = winfd[1] = termfd[0] = termfd[1] = -1;
  winpid = termpid = -1;
  if (pipe (winfd) || pipe (termfd))
    {
      error (ERROR, "Couldn't open pipes");
      goto sane_state;
    }

  winpid = fork ();
  if (winpid == 0)
    {
      /* this is the child */
      signal (SIGINT, SIG_DFL);
      signal (SIGFPE, SIG_DFL);
      signal (SIGSEGV, SIG_DFL);
      retkey[0] = '\0';
      if (winopened)
      getwinkey (retkey);
      if (*retkey)
      write (winfd[1], retkey, strlen (retkey));
      wait (&status);
      exit (0);
    }
  else if (winpid == -1)
    {
      error (ERROR, "couldn't fork child");
      goto sane_state;
    }

  termpid = fork ();
  if (termpid == 0)
    {
      /* this is the child */
      signal (SIGINT, SIG_DFL);
      signal (SIGFPE, SIG_DFL);
      signal (SIGSEGV, SIG_DFL);
      retkey[0] = '\0';
      noecho ();
      cbreak ();
      timeout (-1);
      gettermkey (retkey);
      if (*retkey)
      write (termfd[1], retkey, strlen (retkey));
      wait (&status);
      exit (0);
    }
  else if (termpid == -1)
    {
      error (ERROR, "Couldn't fork child");
      goto sane_state;
    }

  FD_ZERO (&readfds);
  FD_SET (termfd[0], &readfds);
  FD_SET (winfd[0], &readfds);
  fflush (stdout);
  maxfd = (termfd[0] > winfd[0]) ? termfd[0] : winfd[0];
  if (maxtime >= 0)
    {
      tv.tv_sec = (int) maxtime;
      tv.tv_usec = (maxtime - (int) maxtime) * 1000000.;
      ret = select (maxfd + 1, &readfds, NULL, NULL, &tv);
    }
  else
    {
      ret = select (maxfd + 1, &readfds, NULL, NULL, NULL);
    }
  if (ret == -1)
    {
      error (ERROR, "select failed");
      goto sane_state;
    }

  if (FD_ISSET (termfd[0], &readfds))
    {
      ret = read (termfd[0], retkey, 100);
    }
  else if (FD_ISSET (winfd[0], &readfds))
    {
      ret = read (winfd[0], retkey, 100);
      if (!strncmp ("MB", retkey, 2))
      getmousexybm (retkey, &mousex, &mousey, &mouseb, &mousemod);
    }
  else
    ret = 0;
  retkey[ret] = '\0';
sane_state:
  skey = retkey;
  if (winfd[0] > 0)
    close (winfd[0]);
  if (winfd[1] > 0)
    close (winfd[1]);
  if (termfd[0] > 0)
    close (termfd[0]);
  if (termfd[1] > 0)
    close (termfd[1]);
  if (termpid > 0)
    {
      kill (termpid, SIGTERM);
      waitpid (termpid, &status, 0);
      termpid = -1;
    }
  if (winpid > 0)
    {
      kill (winpid, SIGTERM);
      waitpid (winpid, &status, 0);
      winpid = -1;
    }
  reset_prog_mode ();         /* prepare for input afterwards */

#elif WINDOWS
  /* create event to signal key */
  if (gotkey == INVALID_HANDLE_VALUE)
    gotkey = CreateEvent (NULL, FALSE, FALSE, NULL);
  if (wantkey == INVALID_HANDLE_VALUE)
    wantkey = CreateEvent (NULL, TRUE, FALSE, NULL);

  conkeybuff[0] = winkeybuff[0] = '\0';

  GetConsoleMode (ConsoleInput, &oflags);
  flags = oflags & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
  SetConsoleMode (ConsoleInput, flags);

  /* create thread to observe console */
  if (kthandle == INVALID_HANDLE_VALUE)
    {
      kthandle = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) keythread,
                         (LPVOID) conkeybuff, 0, (LPDWORD) & ktid);
    }
  /* signal, that we want a key */
  if (winopened)
    {
      SendMessage (window, WM_WANTKEY, 0, (LPARAM) winkeybuff);
    }
  SetEvent (wantkey);
  ms = (int) (1000 * maxtime);
  if (ms < 0)
    WaitForSingleObject (gotkey, INFINITE);
  else
    WaitForSingleObject (gotkey, ms);

  ResetEvent (wantkey);
  SetConsoleMode (ConsoleInput, oflags);
  if (*winkeybuff)
    skey = winkeybuff;
  else
    skey = conkeybuff;
#endif
  return my_strdup (skey);
}


#ifdef WINDOWS
static DWORD
keythread (LPWORD lparam)     /* wait for key input from console */
{
  INPUT_RECORD inrec;         /* for reading key-event */
  int key, skey;
  int num;
  char *keybuff;
  HANDLE evn[2];

  keybuff = (char *) lparam;
  keybuff[0] = '\0';
  evn[0] = wantkey;
  evn[1] = ConsoleInput;
  do
    {
      do
      {
        do
          {
            WaitForMultipleObjects (2, evn, TRUE, INFINITE);
            ReadConsoleInput (ConsoleInput, &inrec, 1, &num);
          }
        while (!is_valid_key (&inrec));
        if (isprint (inrec.Event.KeyEvent.uChar.AsciiChar))
          {
            keybuff[0] = inrec.Event.KeyEvent.uChar.AsciiChar;
            keybuff[1] = '\0';
          }
        else
          {
            key = inrec.Event.KeyEvent.wVirtualKeyCode;
            skey = -1;
            switch (key)
            {
            case 0x1b:
              skey = kESC;
              break;
            case 0x0d:
              skey = kENTER;
              break;
            case 0x09:
              skey = kTAB;
              break;
            case 0x21:
              skey = kSCRNUP;
              break;
            case 0x22:
              skey = kSCRNDOWN;
              break;
            case 0x70:
              skey = kF1;
              break;
            case 0x71:
              skey = kF2;
              break;
            case 0x72:
              skey = kF3;
              break;
            case 0x73:
              skey = kF4;
              break;
            case 0x74:
              skey = kF5;
              break;
            case 0x75:
              skey = kF6;
              break;
            case 0x76:
              skey = kF7;
              break;
            case 0x77:
              skey = kF8;
              break;
            case 0x78:
              skey = kF9;
              break;
            case 0x79:
              skey = kF10;
              break;
            case 0x7a:
              skey = kF11;
              break;
            case 0x7b:
              skey = kF12;
              break;
            case 0x24:
              skey = kHOME;
              break;
            case 0x23:
              skey = kEND;
              break;
            case 0x2d:
              skey = kINS;
              break;
            case 0x2e:
              skey = kDEL;
              break;
            case 0x08:
              skey = kBACKSPACE;
              break;
            case 0x27:
              skey = kRIGHT;
              break;
            case 0x25:
              skey = kLEFT;
              break;
            case 0x28:
              skey = kDOWN;
              break;
            case 0x26:
              skey = kUP;
              break;
            default:
              sprintf (keybuff, "key%x", key);
            }
            if (skey > 0)
            strcpy (keybuff, ykey[skey]);
          }
        if (!keybuff[0])
          printf ("Loop !\n");
      }
      while (!keybuff[0]);
      ResetEvent (wantkey);
      SetEvent (gotkey);
    }
  while (TRUE);

  return 0;
}


static int
is_valid_key (INPUT_RECORD * rec)   /* check if input rec contains valid key */
{
  if (rec->EventType != KEY_EVENT ||
      !rec->Event.KeyEvent.bKeyDown ||
      rec->Event.KeyEvent.wVirtualKeyCode == VK_SHIFT ||
      rec->Event.KeyEvent.wVirtualKeyCode == VK_CONTROL)
    {
      return FALSE;
    }
  return TRUE;
}
#endif


char *
replace (char *string)        /* replace \n,\a, etc. */
{
  char *from, *to;
  char *p;
  int val;
  static char *hexdigits = "0123456789abcdef";

  from = to = string;
  while (*from)
    {
      if (*from == '\\')
      {
        from++;
        switch (*from)
          {
          case 'n':
            *to = '\n';
            break;
          case 't':
            *to = '\t';
            break;
          case 'v':
            *to = '\v';
            break;
          case 'b':
            *to = '\b';
            break;
          case 'r':
            *to = '\r';
            break;
          case 'f':
            *to = '\f';
            break;
          case 'a':
            *to = '\a';
            break;
          case '\\':
            *to = '\\';
            break;
          case '\?':
            *to = '\?';
            break;
          case '\'':
            *to = '\'';
            break;
          case '\"':
            *to = '\"';
            break;
          case 'x':
            val = 0;
            if ((p = strchr (hexdigits, tolower (*(from + 1))))
              && p - hexdigits < 16)
            {
              from++;
              val = p - hexdigits;
              if ((p = strchr (hexdigits, tolower (*(from + 1))))
                  && p - hexdigits < 16)
                {
                  from++;
                  val *= 16;
                  val += p - hexdigits;
                }
            }
            *to = (char) val;
            break;
          default:
            *to = '\\';
            to++;
            *to = *from;
          }
      }
      else
      *to = *from;
      from++;
      to++;
    }
  *to = '\0';
  return string;
}


void
create_myopen (int num)       /* create command 'myopen' */
{
  struct command *cmd;

  cmd = add_command (cOPEN, NULL);
  cmd->tag = num;
}


void
myopen (struct command *cmd)  /* open specified file for given name */
{
#ifdef WINDOWS
  char PrinterName[200];      /* Name of default Printer */
  char *n;              /* points into PrinterName */
  DOC_INFO_1 di;
#endif
  FILE *handle = NULL;
  int stream, i;
  char *name = NULL;
  char *mode = NULL;
  char **pmode;
  static char *valid_modes[] = { "r", "w", "a", "rb", "wb", "ab", "" };
  static int smodes[] =
      { smREAD, smWRITE, smWRITE, smREAD, smWRITE, smWRITE };
  int smode;
  struct stackentry *p;
  int has_mode, has_stream, printer;

  /* decode cmd->tag */
  has_stream = cmd->tag & OPEN_HAS_STREAM;
  has_mode = cmd->tag & OPEN_HAS_MODE;
  printer = cmd->tag & OPEN_PRINTER;

  if (has_mode)
    mode = my_strdup (pop (stSTRING)->pointer);
  else
    mode = printer ? my_strdup ("w") : my_strdup ("r");
  if (printer)
    name = my_strdup ("/usr/bin/lpr");
  else
    name = my_strdup (pop (stSTRING)->pointer);

  if (has_stream)
    {
      stream = (int) pop (stNUMBER)->value;
    }
  else
    {
      stream = 0;
      for (i = 1; i < FOPEN_MAX - 4; i++)
      {
        if (stream_modes[i] == smCLOSED)
          {
            stream = i;
            break;
          }
      }
      if (!stream)
      {
        sprintf (errorstring, "reached maximum number of open files");
        errorcode = 5;
        goto open_done;
      }
    }

  p = push ();
  p->value = 0.;
  p->type = stNUMBER;

  if (printer && print_to_file)
    {
      sprintf (errorstring,
             "cannot open printer: already printing grafics");
      errorcode = 6;
      goto open_done;
    }

  if (badstream (stream, 1))
    {
      sprintf (errorstring, "invalid stream number %d", stream);
      errorcode = 9;
      goto open_done;
    }
  if (stream_modes[stream] != smCLOSED)
    {
      sprintf (errorstring, "stream already in use");
      errorcode = 2;
      goto open_done;
    }

  smode = 0;
  for (pmode = valid_modes; **pmode; pmode++)
    {
      if (!strcmp (*pmode, mode))
      break;
      smode++;
    }
  if (!**pmode)
    {
      sprintf (errorstring, "\'%s\' is not a valid filemode", mode);
      errorcode = 3;
      goto open_done;
    }

  if (printer)
    {
#ifdef UNIX
      lineprinter = popen (name, "w");
      if (!lineprinter)
      {
        sprintf (errorstring, "could not open line printer");
        errorcode = 7;
        goto open_done;
      }
#else
      /* query win.ini for default printer */
      GetProfileString ("windows", "device", ",,,", PrinterName, 200);

      /* truncate printer name */
      n = PrinterName;
      while (*n && *n != ',')
      n++;
      *n = '\0';

      OpenPrinter (PrinterName, &lineprinter, NULL);
      di.pDocName = "yabasic text";
      di.pOutputFile = (LPTSTR) NULL;
      di.pDatatype = "RAW";
      if (!StartDocPrinter (lineprinter, 1, (LPBYTE) & di))
      {
        sprintf (errorstring, "could not open line printer");
        errorcode = 7;
        goto open_done;
      }
      StartPagePrinter (lineprinter);
#endif
      lprstream = stream;
    }
  else
    {
      handle = fopen (name, mode);
      if (handle == NULL)
      {
        sprintf (errorstring, "could not open '%s': %s", name,
               my_strerror (errno));
        errorcode = 4;
        goto open_done;
      }
      streams[stream] = handle;
    }
  stream_modes[stream] = smodes[smode];
  errorcode = 0;
  p->value = stream;
open_done:
  if (name)
    my_free (name);
  if (mode)
    my_free (mode);
}


void
checkopen (void)        /* check, if open has been sucessfull */
{
  double result;

  result = pop (stNUMBER)->value;
  if (result <= 0)
    {
      error (ERROR, errorstring);
    }
}


void
myclose (void)                /* close the specified stream */
{
  int s;
#ifdef WINDOWS
  DWORD written;
#endif

  s = (int) pop (stNUMBER)->value;
  if (abs (s) == STDIO_STREAM || badstream (s, 0))
    return;
  if (stream_modes[s] == smCLOSED)
    {
      sprintf (string, "stream %d already closed", s);
      error (WARNING, string);
      return;
    }
  if (s == lprstream)
    {
#ifdef UNIX
      pclose (lineprinter);
#else
      WritePrinter (lineprinter, "\f", 2, &written);
      EndPagePrinter (lineprinter);
      EndDocPrinter (lineprinter);
      ClosePrinter (lineprinter);
      lineprinter = INVALID_HANDLE_VALUE;
#endif
      lprstream = -1;
    }
  else
    {
      fclose (streams[s]);
    }
  streams[s] = NULL;
  stream_modes[s] = smCLOSED;
}


void
myseek (struct command *cmd)  /* reposition file pointer */
{
  int s, p, m, i;
  struct stackentry *pp;
  char *mode;

  if (cmd->type == cSEEK2)
    mode = (char *) my_strdup (pop (stSTRING)->pointer);
  else
    mode = my_strdup ("begin");
  p = (int) pop (stNUMBER)->value;
  s = (int) pop (stNUMBER)->value;
  pp = push ();
  pp->value = 0.;
  pp->type = stNUMBER;
  for (i = 0; mode[i]; i++)
    mode[i] = tolower (mode[i]);
  if (!strcmp (mode, "begin"))
    {
      m = SEEK_SET;
    }
  else if (!strcmp (mode, "end"))
    {
      m = SEEK_END;
    }
  else if (!strcmp (mode, "here"))
    {
      m = SEEK_CUR;
    }
  else
    {
      sprintf (errorstring, "seek mode '%s' is none of begin,end,here",
             mode);
      errorcode = 12;
      my_free (mode);
      return;
    }
  my_free (mode);
  if (abs (s) == STDIO_STREAM || badstream (s, 0))
    return;
  if (!(stream_modes[s] & (smREAD | smWRITE)))
    {
      sprintf (errorstring, "stream %d not open", s);
      errorcode = 11;
      return;
    }
  if (fseek (streams[s], (long) p, m))
    {
      sprintf (errorstring, "could not position stream %d to byte %d", s,
             p);
      errorcode = 10;
      return;
    }
  pp->value = 1.0;
}


void
create_pps (int type, int input)    /* create command pushswitch or popswitch */
{
  struct command *cmd;

  cmd = add_command (type, NULL);
  cmd->args = input;
}


void
push_switch (struct command *cmd)   /* push current stream on stack and switch to new one */
{
  static int oldstream = STDIO_STREAM;
  struct stackentry *s;
  int stream;

  stream = (int) pop (stNUMBER)->value;
  if (badstream (stream, 0))
    return;
  if (!cmd->args)
    stream = -stream;

  s = push ();
  s->type = stNUMBER;
  s->value = oldstream;
  if (infolevel >= DEBUG)
    {
      sprintf (string, "pushing %d on stack, switching to %d", oldstream,
             stream);
      error (DEBUG, string);
    }
  oldstream = stream;
  myswitch (stream);
}


void
pop_switch (void)       /* pop current stream from stack and switch to it */
{
  int stream;

  stream = (int) pop (stNUMBER)->value;
  if (infolevel >= DEBUG)
    {
      sprintf (string, "popping %d from stack, switching to it", stream);
      error (DEBUG, string);
    }
  myswitch (stream);
}


void
myswitch (int stream)         /* switch to specified stream */
{
  int stdio, input;

  stdio = (abs (stream) == STDIO_STREAM);
  input = (stream > 0);
  currstr = stream;
  if (stream < 0)
    stream = -stream;
  if (badstream (stream, 0))
    return;

  if (stdio)
    {
      cinstr = stdin;
      coutstr = stdout;
    }
  else
    {
      cinstr = coutstr = NULL;
      if (input)
      cinstr = streams[stream];
      else
      coutstr = streams[stream];
    }
}


int
checkstream (void)            /* test if currst is still valid */
{
  int stdio, input;

  stdio = (abs (currstr) == STDIO_STREAM);
  input = (currstr > 0);

  if (!stdio)
    {
      if (input && !(stream_modes[abs (currstr)] & smREAD))
      {
        sprintf (string, "stream %d not open for reading",
               abs (currstr));
        error (ERROR, string);
        return FALSE;
      }
      if (!input && !(stream_modes[abs (currstr)] & (smWRITE | smPRINT)))
      {
        sprintf (string, "stream %d not open for writing or printing",
               abs (currstr));
        error (ERROR, string);
        return FALSE;
      }
    }
  return TRUE;
}


void
testeof (struct command *cmd) /* close the specified stream */
{
  int s, c;
  struct stackentry *result;

  s = (int) pop (stNUMBER)->value;
  if (s != STDIO_STREAM && badstream (s, 0))
    return;
  result = push ();
  result->type = stNUMBER;
  if (s && !(stream_modes[s] & smREAD))
    {
      result->value = 1.;
      return;
    }
  if (!s)
    {
      result->value = 0.;
      return;
    }
  c = getc (streams[s]);
  if (c == EOF)
    {
      result->value = 1.;
      return;
    }

  result->value = 0.;
  ungetc (c, streams[s]);
  return;
}


int
badstream (int stream, int errcode) /* test for valid stream id */
{
  if (stream != STDIO_STREAM && (stream > FOPEN_MAX - 4 || stream <= 0))
    {
      sprintf (errcode ? errorstring : string,
             "invalid stream: %d (can handle only streams from 1 to %d)",
             stream, FOPEN_MAX - 4);
      if (errcode)
      errorcode = errcode;
      else
      error (ERROR, string);
      return TRUE;
    }
  return FALSE;
}


void
create_myread (char type, int tileol)     /* create command 'read' */
{
  struct command *cmd;

  cmd = add_command (cREAD, NULL);
  cmd->args = tileol;         /* true, if read should go til eol */
  cmd->tag = type;            /* can be 'd' or 's' */
}


void
myread (struct command *cmd)  /* read string or double */
{
  double d;
  static char buffer[INBUFFLEN];    /* buffer with current input */
  int numread;                /* number of bytes read */
  int tileol;                 /* true, if read should go til end of line */
  struct stackentry *s;
  int currch;                 /* current character */

  numread = 0;                /* no chars read'til now */
  buffer[0] = '\0';
  tileol = cmd->args;

  /* skip leading whitespace */
  if (!tileol)
    {
      do
      {
        currch = onechar ();
      }
      while (currch == ' ' || currch == '\t');
      /* put back last char */
      if (currch != EOF && currch != '\0')
      backchar (currch);
      if (currch == '\0' || currch == EOF)
      goto done;
    }

  /* read chars */
  do
    {
      currch = onechar ();
      buffer[numread] = currch;
      numread++;
    }
  while (((tileol && currch != '\0') ||
        (!tileol && currch != ' ' &&
         currch != '\t' && currch != '\0')) &&
       currch != EOF && numread < INBUFFLEN);

  /* put back last char */
  if (currch != EOF && currch != '\0')
    backchar (currch);
  /* and remove it from buff */
  if (currch != EOF)
    numread--;
  buffer[numread] = '\0';
  if (currch == '\0' || currch == EOF)
    goto done;

  /* skip trailing whitespace */
  if (!tileol)
    {
      do
      {
        currch = onechar ();
      }
      while (currch == ' ' || currch == '\t');
      if (currch != EOF && currch != '\0')
      backchar (currch);
    }

done:
  if (cmd->tag == 's')
    {                   /* read string */
      s = push ();
      s->type = stSTRING;
      s->pointer = my_strdup (buffer);
    }
  else
    {                   /* read double */
      s = push ();
      s->type = stNUMBER;
      s->value = 0.0;
      if (buffer[0] && (sscanf (buffer, "%lf", &d) == 1))
      s->value = d;
    }
}


static void
readline (void)               /* read one line from current stream */
{
#ifdef UNIX
  char *nl;             /* position of newline */
  int x, y;
#else
  int read;
#endif

  if (!checkstream ())
    return;
  linebuffer[0] = '\0';
#ifdef UNIX
  if (curinized && cinstr == stdin)
    {
      getyx (stdscr, y, x);
#ifdef HAVE_GETNSTR
      getnstr (linebuffer, INBUFFLEN);
#else
      getstr (linebuffer);
#endif
      if ((nl = strchr (linebuffer, '\0')))
      {
        *nl = '\n';
        *(nl + 1) = '\0';
      }
      if (y >= LINES - 1)
      scrl (1);
      refresh ();
    }
#else
  if (curinized && cinstr == stdin)
    {
      FlushConsoleInputBuffer (ConsoleInput);
      ReadConsole (ConsoleInput, linebuffer, INBUFFLEN, &read, NULL);
      if (read >= 2)
      {
        linebuffer[read - 2] = '\n';
        linebuffer[read - 1] = '\0';
      }
    }
#endif
  else
    {
      fgets (linebuffer, INBUFFLEN, cinstr);
    }
  currchar = linebuffer;
  prompted = FALSE;
}


static int
onechar ()              /* read one char from cinstr */
{
  int ch;

  if (!checkstream ())
    return '\0';
  if (cinstr == stdin)
    {
      if (!currchar || !*currchar)
      {
        readline ();
      }
      do
      {
        ch = *currchar;
        currchar++;
      }
      while (!
           (!iscntrl (ch) || strchr (" \t\n", ch) || read_controls
            || ch == '\0'));
    }
  else
    {
      do
      {
        ch = fgetc (cinstr);
      }
      while (!
           (!iscntrl (ch) || strchr (" \t\n", ch) || read_controls
            || ch == '\0' || ch == EOF));
    }

  if (ch == '\n' || ch == EOF)
    return '\0';
  else
    return ch;
}


static void
backchar (int ch)       /* put char back into stream */
{
  if (!checkstream ())
    return;
  if (cinstr == stdin)
    {
      if (currchar > linebuffer)
      currchar--;
    }
  else
    {
      ungetc (ch, cinstr);
    }
}


void
chkprompt ()                  /* print an intermediate prompt if necessary */
{
  if (cinstr == stdin && (!currchar || !*currchar) && !prompted)
    onestring ("?");
}


void
create_onestring (char *str)  /* create command 'onestring' */
{
  struct command *cmd;

  cmd = add_command (cONESTRING, NULL);
  cmd->pointer = my_strdup (str);
}


void
onestring (char *s)           /* write string to file */
{
#ifdef WINDOWS
  DWORD len, written;
#endif

  if (!checkstream ())
    return;
  if (curinized && abs (currstr) == STDIO_STREAM)
    {
#ifdef UNIX
      addstr (s);
      refresh ();
#else
      len = strlen (s);
      WriteConsole (ConsoleOutput, s, len, &written, NULL);
#endif
    }
  else if (abs (currstr) == lprstream)
    {
#ifdef UNIX
      fprintf (lineprinter, "%s", s);
      fflush (lineprinter);
#else
      len = strlen (s);
      WritePrinter (lineprinter, s, len, &written);
#endif
    }
  else
    {
      fprintf (coutstr, "%s", s);
      fflush (coutstr);
    }
  prompted = TRUE;
}


void
create_colour (int flag)      /* create command 'colour' */
{
  struct command *c;

  c = add_command (cCOLOUR, NULL);
  c->args = flag;
}


void
colour (struct command *cmd)  /* switch on colour */
{
  char *fore = NULL, *back = NULL, *p;
  int fc, bc;

  if (cmd->args && !curinized)
    {
      error (ERROR, "need to call 'clear screen' first");
      return;
    }
  if (cmd->args == 0)
    {
      if (!curinized)
      return;
#ifdef UNIX
      if (has_colors ())
      attrset (A_NORMAL | COLOR_PAIR (stdfc * 8 + stdbc));
      else
      attrset (A_NORMAL);
      return;
#else
      SetConsoleTextAttribute (ConsoleOutput, (WORD) (stdfc | stdbc));
      return;
#endif
    }
  else if (cmd->args == 1)
    {
#ifdef UNIX
      if (has_colors ())
      attrset (A_NORMAL | COLOR_PAIR (stdbc * 8 + stdfc));
      else
      {
        attrset (A_REVERSE);
        return;
      }
#else
      SetConsoleTextAttribute (ConsoleOutput,
                         (WORD) (yc2oc (oc2yc (stdfc), 0) |
                               yc2oc (oc2yc (stdbc), 1)));
      return;
#endif
    }
  else
    {                   /* decode colours */
#ifdef UNIX
      if (!has_colors ())
      {
        pop (stSTRING);
        if (cmd->args == 3)
          pop (stSTRING);
        attrset (A_REVERSE);
        return;
      }
#endif
      if (cmd->args == 2)
      {
        back = NULL;
        fore = pop (stSTRING)->pointer;
        for (p = fore; *p; p++)
          *p = tolower (*p);
      }
      else
      {
        back = pop (stSTRING)->pointer;
        for (p = back; *p; p++)
          *p = tolower (*p);
        fore = pop (stSTRING)->pointer;
        for (p = fore; *p; p++)
          *p = tolower (*p);
      }
      fc = name2yc (fore);
      if (fc < 0)
      {
        sprintf (string, "unknown foreground colour: '%s'", fore);
        error (ERROR, string);
      }
      bc = stdbc;
      if (back)
      {
        bc = name2yc (back);
        if (fc < 0)
          {
            sprintf (string, "unknown background colour: '%s'", back);
            error (ERROR, string);
          }
      }
#ifdef UNIX
      attrset (COLOR_PAIR (fc * 8 + bc));
#else
      SetConsoleTextAttribute (ConsoleOutput,
                         (WORD) (yc2oc (fc, TRUE) |
                               yc2oc (bc, FALSE)));
#endif
    }
}


static void
initcol (void)                /* initialize curses colors */
{
  static int first = TRUE;
#ifdef UNIX
  int i, j, col;
  short f, b;
#else
  CONSOLE_SCREEN_BUFFER_INFO csbi;
#endif

  if (!first)
    return;
  first = FALSE;
#ifdef UNIX
  if (!has_colors ())
    return;
  start_color ();

  for (i = 0; i < 8; i++)
    {
      for (j = 0; j < 8; j++)
      {
        if (!i && !j)
          continue;
        init_pair (i * 8 + j, yc2oc (i, TRUE), yc2oc (j, FALSE));
      }
    }
  init_color (COLOR_YELLOW, 1000, 1000, 0);

  col = inch () & A_COLOR;
  pair_content (col, &f, &b);
  stdfc = oc2yc (f);
  stdbc = oc2yc (b);
  bkgdset (COLOR_PAIR (stdfc * 8 + stdbc));
#else
  GetConsoleScreenBufferInfo (ConsoleOutput, &csbi);
  stdfc =
      csbi.
      wAttributes & (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
  stdbc =
      csbi.
      wAttributes & (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED);
  
#endif
}


int
name2yc (char *name)          /* convert a color name to an integer */
{
  char *c;

  for (c = name; *c; c++)
    *c = tolower (*c);
  if (!strcmp (name, "black") || !strcmp (name, "bla"))
    return YC_BLACK;
  if (!strcmp (name, "white") || !strcmp (name, "whi"))
    return YC_WHITE;
  if (!strcmp (name, "red") || !strcmp (name, "red"))
    return YC_RED;
  if (!strcmp (name, "blue") || !strcmp (name, "blu"))
    return YC_BLUE;
  if (!strcmp (name, "green") || !strcmp (name, "gre"))
    return YC_GREEN;
  if (!strcmp (name, "yellow") || !strcmp (name, "yel"))
    return YC_YELLOW;
  if (!strcmp (name, "cyan") || !strcmp (name, "cya"))
    return YC_CYAN;
  if (!strcmp (name, "magenta") || !strcmp (name, "mag"))
    return YC_MAGENTA;
  return -1;
}


int
yc2oc (int yc, int fore)      /* convert a yabasic color to operating system color */
{
#ifdef UNIX
  fore = 0;             /* stop gcc from complaining */
  if (yc == YC_BLACK)
    return COLOR_BLACK;
  if (yc == YC_WHITE)
    return COLOR_WHITE;
  if (yc == YC_RED)
    return COLOR_RED;
  if (yc == YC_BLUE)
    return COLOR_BLUE;
  if (yc == YC_GREEN)
    return COLOR_GREEN;
  if (yc == YC_YELLOW)
    return COLOR_YELLOW;
  if (yc == YC_CYAN)
    return COLOR_CYAN;
  if (yc == YC_MAGENTA)
    return COLOR_MAGENTA;
#else
  if (fore)
    {
      if (yc == YC_BLACK)
      return 0;
      if (yc == YC_WHITE)
      return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
      if (yc == YC_RED)
      return FOREGROUND_RED;
      if (yc == YC_BLUE)
      return FOREGROUND_BLUE;
      if (yc == YC_GREEN)
      return FOREGROUND_GREEN;
      if (yc == YC_YELLOW)
      return FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
      if (yc == YC_CYAN)
      return FOREGROUND_GREEN | FOREGROUND_BLUE;
      if (yc == YC_MAGENTA)
      return FOREGROUND_BLUE | FOREGROUND_RED;
    }
  else
    {
      if (yc == YC_BLACK)
      return 0;
      if (yc == YC_WHITE)
      return BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
      if (yc == YC_RED)
      return BACKGROUND_RED;
      if (yc == YC_BLUE)
      return BACKGROUND_BLUE;
      if (yc == YC_GREEN)
      return BACKGROUND_GREEN;
      if (yc == YC_YELLOW)
      return BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY;
      if (yc == YC_CYAN)
      return BACKGROUND_GREEN | BACKGROUND_BLUE;
      if (yc == YC_MAGENTA)
      return BACKGROUND_BLUE | BACKGROUND_RED;
    }
#endif
  return -1;
}


int
oc2yc (int oc)                /* convert an operating system color to yabasic color */
{
#ifdef UNIX
  if (oc == COLOR_BLACK)
    return YC_BLACK;
  if (oc == COLOR_WHITE)
    return YC_WHITE;
  if (oc == COLOR_RED)
    return YC_RED;
  if (oc == COLOR_BLUE)
    return YC_BLUE;
  if (oc == COLOR_GREEN)
    return YC_GREEN;
  if (oc == COLOR_YELLOW)
    return YC_YELLOW;
  if (oc == COLOR_CYAN)
    return YC_CYAN;
  if (oc == COLOR_MAGENTA)
    return YC_MAGENTA;
#else
  if (oc == 0)
    return YC_BLACK;
  if (oc == (FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN) ||
      oc == (BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN))
    return YC_WHITE;
  if (oc == (FOREGROUND_RED) || oc == (BACKGROUND_RED))
    return YC_RED;
  if (oc == (FOREGROUND_BLUE) || oc == (BACKGROUND_BLUE))
    return YC_BLUE;
  if (oc == (FOREGROUND_GREEN) || oc == (BACKGROUND_GREEN))
    return YC_GREEN;
  if (oc == (FOREGROUND_RED | FOREGROUND_GREEN) ||
      oc == (BACKGROUND_RED | BACKGROUND_GREEN) ||
      oc == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY) ||
      oc == (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY))
    return YC_YELLOW;
  if (oc == (FOREGROUND_BLUE | FOREGROUND_GREEN) ||
      oc == (BACKGROUND_BLUE | BACKGROUND_GREEN))
    return YC_CYAN;
  if (oc == (FOREGROUND_RED | FOREGROUND_BLUE) ||
      oc == (BACKGROUND_RED | BACKGROUND_BLUE))
    return YC_MAGENTA;
#endif
  return -1;
}


void
putchars (void)               /* put rect onto screen */
{
  char *ch, text, fore[4], back[4];
  int n, sx, sy, x, y, f, b;
  int tox, toy;
  int oldx, oldy;
#ifdef WINDOWS
  CONSOLE_SCREEN_BUFFER_INFO csbi;
  COORD cp;
  WORD attributes;
  char buff[2];
  int written;
#endif

  toy = (int) (pop (stNUMBER)->value);
  tox = (int) (pop (stNUMBER)->value);
  ch = pop (stSTRING)->pointer;
#ifdef UNIX
  getyx (stdscr, oldy, oldx);
#else
  GetConsoleScreenBufferInfo (ConsoleOutput, &csbi);
  attributes = csbi.wAttributes;
  oldx = csbi.dwCursorPosition.X;
  oldy = csbi.dwCursorPosition.Y;
#endif
  if (sscanf (ch, "%d,%d:%n", &sx, &sy, &n) != 2)
    {
      error (ERROR, "illegal screen string");
      return;
    }
  ch += n;
  for (x = tox; x < tox + sx; x++)
    {
      if (x < 0 || x >= COLS)
      continue;
      for (y = toy; y < toy + sy; y++)
      {
        if (x < 0 || x >= COLS || y < 0 || y >= LINES)
          {
            for (n = 0; n < 10; n++)
            if (*ch)
              ch++;
            continue;
          }
        if (!*ch)
          {
            text = ' ';
            f = YC_BLACK;
            b = YC_BLACK;
          }
        else
          {
            text = *ch;
            strncpy (fore, ch + 2, 3);
            fore[3] = '\0';
            strncpy (back, ch + 6, 3);
            back[3] = '\0';
            for (n = 0; n < 10; n++)
            if (*ch)
              ch++;
            f = name2yc (fore);
            if (f < 0)
            f = YC_WHITE;
            b = name2yc (back);
            if (b < 0)
            b = YC_WHITE;
          }
#ifdef UNIX
        if (has_colors ())
          attrset (COLOR_PAIR (f * 8 + b));
        mvaddch (y, x, text);
#else
        cp.X = x;
        cp.Y = y;
        SetConsoleCursorPosition (ConsoleOutput, cp);
        SetConsoleTextAttribute (ConsoleOutput,
                           (WORD) (yc2oc (f, TRUE) |
                                 yc2oc (b, FALSE)));
        buff[0] = text;
        buff[1] = '\0';
        WriteConsole (ConsoleOutput, buff, 1, &written, NULL);
#endif
      }
    }
#ifdef UNIX
  if (has_colors ())
    attrset (A_NORMAL | COLOR_PAIR (stdfc * 8 + stdbc));
  else
    attrset (A_NORMAL);
  move (y, x);
  refresh ();
#else
  cp.X = oldx;
  cp.Y = oldy;
  SetConsoleCursorPosition (ConsoleOutput, cp);
  SetConsoleTextAttribute (ConsoleOutput, attributes);
#endif

  return;
}


char *
getchars (int xf, int yf, int xt, int yt) /* get rect from screen */
{
  int x, y;
#ifdef UNIX
  int c, ct, cc;
#endif
  int cf, cb;
  int oldx, oldy;
  char *res;
  char cols[20];
#ifdef WINDOWS
  CONSOLE_SCREEN_BUFFER_INFO csbi;
  COORD cp;
  char charbuff[2];
  WORD attrbuff[2];
  int read;
#endif

  if (xf > xt)
    {
      x = xf;
      xf = xt;
      xt = x;
    }
  if (yf > yt)
    {
      y = yf;
      yf = yt;
      yt = y;
    }

  res = my_malloc (12 + (xt - xf + 1) * (yt - yf + 1) * 12);
  sprintf (res, "%d,%d:", xt - xf + 1, yt - yf + 1);
#ifdef UNIX
  getyx (stdscr, oldy, oldx);
#else
  GetConsoleScreenBufferInfo (ConsoleOutput, &csbi);
  oldx = csbi.dwCursorPosition.X;
  oldy = csbi.dwCursorPosition.Y;
#endif

  for (x = xf; x <= xt; x++)
    {
      for (y = yf; y <= yt; y++)
      {
        if (y < 0 || y >= LINES || x < 0 || x >= COLS)
          {
            strcat (res, " blbl");
          }
        else
          {
#ifdef UNIX
            c = mvinch (y, x);
            ct = c & A_CHARTEXT;
            if (!isprint (ct))
            ct = ' ';
            cc = PAIR_NUMBER (c & A_COLOR);
            cb = cc & 7;
            cf = (cc - cb) / 8;
            if (has_colors ())
            {
              sprintf (cols, "%c:%s:%s,", ct, yc2short (cf),
                     yc2short (cb));
            }
            else
            {
              sprintf (cols, "%c:???:???,", ct);
            }
#else
            cp.X = x;
            cp.Y = y;
            ReadConsoleOutputCharacter (ConsoleOutput, charbuff, 1, cp,
                                &read);
            charbuff[1] = '\0';
            ReadConsoleOutputAttribute (ConsoleOutput, attrbuff, 1, cp,
                                &read);
            cf = oc2yc (attrbuff[0] &
                    (FOREGROUND_RED | FOREGROUND_GREEN |
                     FOREGROUND_BLUE));
            cb = oc2yc (attrbuff[0] &
                    (BACKGROUND_RED | BACKGROUND_GREEN |
                     BACKGROUND_BLUE));
            sprintf (cols, "%c:%s:%s,", charbuff[0], yc2short (cf),
                   yc2short (cb));
#endif
            strcat (res, cols);
          }
      }
    }
#ifdef UNIX
  move (oldy, oldx);
#endif
  res[strlen (res) - 1] = '\0';
  return res;
}


char *
yc2short (int col)            /* convert yabasic colours to short colour name */
{
  static char r1[4], r2[4];
  static char *pr = r1;

  if (pr == r1)
    pr = r2;
  else
    pr = r1;

  strcpy (pr, "***");
  if (col == YC_BLACK)
    strcpy (pr, "Bla");
  if (col == YC_WHITE)
    strcpy (pr, "Whi");
  if (col == YC_RED)
    strcpy (pr, "Red");
  if (col == YC_BLUE)
    strcpy (pr, "Blu");
  if (col == YC_GREEN)
    strcpy (pr, "Gre");
  if (col == YC_YELLOW)
    strcpy (pr, "Yel");
  if (col == YC_CYAN)
    strcpy (pr, "Cya");
  if (col == YC_MAGENTA)
    strcpy (pr, "Mag");

  return pr;
}

Generated by  Doxygen 1.6.0   Back to index