/************************************************************
  Vmore.c  By: Stephen Vermeulen

  Copyright (C) 1987 By Stephen Vermeulen

  Syntax:
           Vmore filename [filename [filename [...]]]

  Yet another text display routine.
************************************************************/

#include <intuition/intuition.h>
#include <workbench/startup.h>
#include <exec/memory.h>
#include <stdio.h>
#include <functions.h>

#define NO_INTUITION   1
#define NO_GRAPHICS    2

extern struct WBStartup *WBenchMsg;

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

extern char *malloc();

/************************************************************
  The following routine just opens the libraries
************************************************************/

short OpenLibs()
{
  short flags; /* any libraries that do not open get recorded here */

  flags = 0;
  IntuitionBase = (struct IntuitionBase *)
                  OpenLibrary("intuition.library", 0L);
  GfxBase =       (struct GfxBase *)
                  OpenLibrary("graphics.library", 0L);
  if (!IntuitionBase) flags |= NO_INTUITION;
  if (!GfxBase) flags |= NO_GRAPHICS;
  return(flags);
}

void CloseLibs(flags)
short flags;
{
  if (!(flags & NO_INTUITION)) CloseLibrary(IntuitionBase);
  if (!(flags & NO_GRAPHICS))  CloseLibrary(GfxBase);
}

struct NewWindow nw =
{
  0, 1, 640, 199,
  -1, -1, RAWKEY,
  ACTIVATE | WINDOWDEPTH | SMART_REFRESH,
  NULL, NULL,
  (UBYTE *) "Vmore  Copyright (C) 1987 By Stephen Vermeulen",
  NULL,
  NULL,
  -1, -1, -1, -1,
  WBENCHSCREEN
};

/********************************************
  The following structure is used to keep a
  record of the positions to seek() to when
  the page backward key is pressed.
*********************************************/

struct PageStart
{
  struct PageStart *prev;   /* previous page */
  long pos;                 /* position      */
};

char s[90];

void main(argc, argv)
short argc;
char *argv[];
{
  short lib_flags, init_flags, pause;
  short left, top, maxx, maxy, c, code;
  FILE *in;
  struct RastPort *rp;
  struct Window *w;
  struct IntuiMessage *mess;
  struct PageStart *ps, *ps2;
  struct WBArg *arg;
  short nargs, CLI_flag, files_left;
  char *name;
  struct FileLock *start_dir;

  CLI_flag = argc;       /* true if run from CLI, false from WB */
  lib_flags  = OpenLibs();
  if (!lib_flags)
  {
    w = (struct Window *) OpenWindow(&nw);
    if (w)
    {
      rp = w->RPort;
      SetAPen(rp, 1L);
      SetDrMd(rp, JAM1);
      left = w->BorderLeft + 1;
      top = w->BorderTop + rp->TxHeight;
      maxx = w->Width  - w->BorderRight - 1;
      maxy = w->Height - w->BorderBottom - 1;
      if (CLI_flag)
      {
        --argc;
        files_left = argc;
        name = argv[argc];
      }
      else
      {
        nargs = WBenchMsg->sm_NumArgs;
        arg = WBenchMsg->sm_ArgList;
        start_dir = (struct FileLock *) CurrentDir(arg->wa_Lock);
        /****** skip tool name *******/
        ++arg;
        files_left = --nargs;
        (void) CurrentDir(arg->wa_Lock);
        name = arg->wa_Name;
      }
      while(files_left)
      {
        in = fopen(name, "r");
        if (in)
        {
          /**********************************
            Allocate the root page start node
          ***********************************/

          ps = (struct PageStart *) malloc(sizeof(struct PageStart));
          ps->prev = NULL;
          ps->pos = 0L;
          SetAPen(rp, 0L);
          RectFill(rp, (long) left, (long) w->BorderTop + 1L,
                       (long) maxx, (long) maxy);
          SetAPen(rp, 1L);
          Move(rp, (long) left, (long) top);
new_line:
          while (fgets(s, 79, in))
          {
            /***************************************
              remove the newline marker, if it is
              present
            ****************************************/

            s[79] = 0;
            c = strlen(s);
            if (s[c - 1] == 10)
            {
              --c;
              s[c] = 0;
            }

            /*****************************
              Now check to see if too far
              down the window.
            ******************************/

            if (rp->cp_y >= maxy)
            {
              pause = TRUE;
              while(pause)
              {
                Wait(1L << w->UserPort->mp_SigBit);
                while(mess = (struct IntuiMessage *) GetMsg(w->UserPort))
                {
                  code = mess->Code;
                  ReplyMsg(mess);
                  switch (code)
                  {
                    case 0x0c5: /* ESC key released */
                      goto free_up;

                    case 192:   /* space bar released */
                    case 0x0cd: /* down arrow key up  */
                      pause = FALSE;
                      SetAPen(rp, 0L);
                      RectFill(rp, (long) left, (long) w->BorderTop + 1L,
                                   (long) maxx, (long) maxy);
                      SetAPen(rp, 1L);
                      Move(rp, (long) left, (long) top);

                      /********************************
                        Now allocate and link in a new
                        page start structure.
                      *********************************/

                      ps2 = (struct PageStart *)
                            malloc(sizeof(struct PageStart));
                      ps2->prev = ps;
                      ps2->pos = ftell(in);
                      ps = ps2;
                      break;

                    case 0x0cc: /* up arrow key up */

                      SetAPen(rp, 0L);
                      RectFill(rp, (long) left, (long) w->BorderTop + 1L,
                                   (long) maxx, (long) maxy);
                      SetAPen(rp, 1L);
                      Move(rp, (long) left, (long) top);

                      /**********************************
                        Deallocate the current pagestart
                        node and move backwards in the
                        file.
                      ***********************************/

                      ps2 = ps->prev;
                      if (ps2)
                      {
                        free(ps);
                        ps = ps2;
                        fseek(in, ps->pos, 0);
                      }
                      else
                      {
                        fseek(in, 0L, 0);
                      }
                      goto new_line;
                  }
                }
              }
            }
            Text(rp, s, (long) c);
            Move(rp, (long) left, (long) (rp->cp_y + rp->TxHeight + 1) );
          }
          Wait(1L << w->UserPort->mp_SigBit);
free_up:
          while(mess = (struct IntuiMessage *) GetMsg(w->UserPort))
            ReplyMsg(mess);
        }

        /************************************
          free up the page start list
        *************************************/

        do
        {
          ps2 = ps->prev;
          free(ps);
          ps = ps2;
        } while (ps);
        fclose(in);
        --files_left;
        if (CLI_flag)
          name = argv[files_left];
        else
        {
          ++arg;
          (void) CurrentDir(arg->wa_Lock);
          name = arg->wa_Name;
        }
      }
      CloseWindow(w);
    }
    if (!CLI_flag) (void) CurrentDir(start_dir);
    CloseLibs(lib_flags);
  }
}
