/*
 * browser - Rummage around on disks.
 *
 *      copyright (c) 1986, Mike Meyer
 *
 * Permission is hereby granted to distribute this program, so long as this
 * source file is distributed with it, and this copyright notice is not
 * removed from the file.
 *
 * Hacked up to be used as file displayer within MandelVroom.  By Kevin
 * Clague
 */

#include "mandp.h"

#define INTUITION_REV           1L
#define GRAPHICS_REV            1L

#define LONGEST_NAME            80      /* Longest file name we can deal with */
#define LONGEST_LINE            256     /* Longest line we will deal with */
#define AVG_LINE_LENGTH         40      /* A guess, tune it if you need to */

#define UP_GADGET               ((unsigned short) 0)
#define DOWN_GADGET             ((unsigned short) 1)
#define SCROLL_GADGET           ((unsigned short) 2)
#define GWIDTH                  16      /* Width of my two gadgets */
#define GHEIGHT                 9       /* and their heights */

#define FIRST 18L

/*
 * Pictures for the up and down arrows
 */
USHORT arrows[2][GHEIGHT] = {
        {0xFE7F,
         0xFC3F,
         0xF81F,
         0xF00F,        /* Up */
         0xFE7F,
         0xFE7F,
         0xFE7F,
         0xFE7F,
         0xFE7F
        },{
         0xFE7F,
         0xFE7F,
         0xFE7F,
         0xFE7F,        /* Down */
         0xFE7F,
         0xF00F,
         0xF81F,
         0xFC3F,
         0xFE7F}
        } ;

/*
 * Now, the Image structures that use the arrows
 */
struct Image Arrow_Image[2] = {
        {0, 0, GWIDTH, GHEIGHT, 1, NULL, 1, 0, NULL}, /* Up */
        {0, 0, GWIDTH, GHEIGHT, 1, NULL, 1, 0, NULL} /* Down */
        };
/*
 * Now, my Gadget structures
 */
static struct PropInfo prop;
static struct Image prop_img;

static struct Gadget Scroll_Gadget = {
        /*(struct Gadget *)*/ NULL,          /* End of Gadgets */
        0,10+GHEIGHT,                        /* Left, Top */
        GWIDTH, -((GHEIGHT*2)+11),
        GRELHEIGHT | GADGHCOMP,
        GADGIMMEDIATE|FOLLOWMOUSE|RELVERIFY, /* Messages when released */
        PROPGADGET,
        (APTR) &prop_img,
        (APTR) NULL,                        /* No rendering image, using HCOMP */
        /*(struct IntuiText *)*/ NULL,
        0L,                                 /* No mutex */
        (APTR) &prop,
        HELPSCROLL,                         /* Yes, this is the scroll gadget */
        (APTR) NULL                         /* And nothing of mine */
};

static struct Gadget Up_Gadget = {
        &Scroll_Gadget,                     /* next gadget is scroll */
        0,10,                               /* Left, Top */
        GWIDTH, GHEIGHT,
        GADGIMAGE | GADGHCOMP,
        GADGIMMEDIATE,                      /* Messages when released */
        BOOLGADGET,                         /* These be boolean gadgets */
        (APTR) &(Arrow_Image[UP_GADGET]),
        (APTR) NULL,                        /* No rendering image, using HCOMP */
        /*(struct IntuiText *)*/ NULL,
        0L,                                 /* No mutex */
        (APTR) NULL,                        /* Nothing special */
        HELPUP,                             /* Yes, this is the up gadget */
        (APTR) NULL                         /* And nothing of mine */
};

static struct Gadget Down_Gadget = {
        &Up_Gadget,                         /* Next gadget is Up_Gadget */
        0,  -GHEIGHT,                       /* Left, Top */
        GWIDTH, GHEIGHT,
        GRELBOTTOM | GADGIMAGE |            /* Standard bottom border gadget */
        GADGHCOMP,
        GADGIMMEDIATE | BOTTOMBORDER,       /* Messages when released */
        BOOLGADGET,                         /* These be boolean gadgets */
        (APTR) &(Arrow_Image[DOWN_GADGET]),
        (APTR) NULL,                        /* No rendering image, using HCOMP */
        /*(struct IntuiText *)*/ NULL,
        0L,                                 /* No mutex */
        (APTR) NULL,                        /* Nothing special */
        HELPDOWN,                           /* Yes, this is the up gadget */
        (APTR) NULL                         /* And nothing of mine */
        };

/*
 * Now, the window for it all
 */
static struct NewWindow New_Window = {
#ifdef DEBUG
        0, 0, 320, 150,                 /* smaller window to left printf's show up */
#else
        0, 1, 320, 199,                 /* Full screen */
#endif
        -1L, -1L,                               /* Default pens */
        NULL,                           /* Window closes and gadgets */
        ACTIVATE                        /* Standard window */
        | SMART_REFRESH | NOCAREREFRESH | SIZEBBOTTOM
        | WINDOWSIZING | WINDOWDEPTH | WINDOWCLOSE | WINDOWDRAG,
        &Down_Gadget,                   /* Add my gadgets */
        /*(struct Image *)*/ NULL,
        (UBYTE *) "MandelVroom Help Window",  /* Title */
        /*(struct Screen *)*/NULL,
        /*(struct BitMap *)*/NULL,
        100, 40,                        /* Minimum sizes */
        -1, -1,                         /* Maximum sizes */
        CUSTOMSCREEN
        } ;

/*
 * My very own variables (mostly for done)
 */
       struct Window    *HelpWind = NULL ;
static FILE             *infile = NULL ;        /* Current input file */
static void             Page_File();
       char             HelpOpen;

/*
 * Finally, declare the string twiddling functions as voids
 */
void    strcat(), strcpy(), strncat();

AllocArrows()
{
  extern USHORT *MakeChipSprite();

  Arrow_Image[0].ImageData = MakeChipSprite( arrows[0], GHEIGHT );
  Arrow_Image[1].ImageData = MakeChipSprite( arrows[1], GHEIGHT );
}

FreeArrows()
{
  USHORT *Temp;

  Temp = Arrow_Image[0].ImageData;

  if (Temp)
    FreeMem( (char *) Temp, (long) sizeof(arrows[0]));
  Arrow_Image[0].ImageData = NULL;

  Temp = Arrow_Image[1].ImageData;

  if (Temp)
    FreeMem( (char *) Temp, (long) sizeof(arrows[0]));
  Arrow_Image[1].ImageData = NULL;
}

/*
 * Display_File - given a directory path and file name, put the first page of
 *      the file in the window.
 */

long aprox_lines, file_size;
long Page_Length = 22L;

static int old_off, new_off;

static
Display_File(dir, name)
char *dir, *name;
{
  static char     File_Name[LONGEST_NAME];
  FILE *fopen();
  long ftell();
  long i;

  if (HelpWind == NULL)
    return;

  old_off = -1;

  /* Get the file name */
  strcpy(File_Name, dir);
  strcat(File_Name, name);

  if (infile != NULL)
    fclose(infile);

  if ((infile = fopen(File_Name, "r")) == NULL) {
    CloseHelpWind(20, "can't open file") ;
    return;
  }

  /* set up the prop gadget for scrolling */
  fseek(infile, 0L, 2);
  file_size = ftell(infile);
  aprox_lines = file_size / AVG_LINE_LENGTH;
  prop.Flags = FREEVERT | AUTOKNOB;
  if (Page_Length >= aprox_lines)
    i = 0xAAAA; /* guess 66% for small files */
  else
    i = (Page_Length * 0x10000) / aprox_lines; /* FFFF=100% - 0000=0% */

  prop.VertBody = i;
  prop.VertPot = 0;       /* always start at begin of file */
  fseek(infile, 0L, 0);

  Page_File(HELPUP);         /* Down from page 0 */
}

/*
 * Page_File - move the file up or down one "page"
 */
void
Page_File(direction)
int direction;
{
  register long where;
  static char     buffer[LONGEST_LINE];
  static char edited[84]; /* allow room for a tab at end */
  int end_flag = 0;
  long tabs, size, Line_Length;
  int i,j;
  long new_pos;
  char *p;

  register struct Window *Window;

  Window = HelpWind;

  if (infile == NULL) return ;

  Page_Length = (Window -> Height - 20) / 8 ;
  Line_Length = (Window -> Width - (3+FIRST)) / 8;

  switch (direction) {

   case HELPUP:         /* Seek back one page */
        if (ftell(infile) < AVG_LINE_LENGTH * (Page_Length + 2))
          fseek(infile, 0L, 0);
        else {
          fseek(infile, (long) -Page_Length * AVG_LINE_LENGTH, 1) ;
          fgets(buffer, LONGEST_LINE, infile) ;
        }
        break;

   case HELPDOWN:
        break;

   case HELPSCROLL:
        /* compute new position based on the users scroll bar pot */
        new_pos = (file_size * prop.VertPot) / 0x10000;

        /* if at end of file, back up 1/2 page */
        if (new_pos >= file_size)
          new_pos = file_size - ((Page_Length / 2) * AVG_LINE_LENGTH);
          fseek(infile, new_pos, 0);

          /* discard a partial line */
          if (new_pos)
            fgets(buffer, LONGEST_LINE, infile);
        new_off = ftell(infile);

        if (new_off == old_off)
          return;

        old_off = new_off;
        break;

   default:
        CloseHelpWind(20, "Illegal argument to Page_File");
        return;
  }

  SetAPen(Window->RPort, NORMALPEN);
  SetDrMd(Window->RPort, JAM1);
  RectFill(Window->RPort, GWIDTH, 10,
                          Window->Width-2, Window->Height-10);
  RectFill(Window->RPort, GWIDTH, Window->Height-10,
                          Window->Width-12-(YScale*4),
                          Window->Height);
  BorderWindow( Window );

  /* now put out one page's worth of the file's data */
  for (where = 17, j = Page_Length; j--; where += 8) {

    /* blank the buffer first */
    for (i = 0; i < 80; i++)
      edited[i] = ' ';

    if (!end_flag) {

      if (fgets(buffer, LONGEST_LINE, infile) == NULL)
        end_flag = TRUE;
      else {
        size = strlen(buffer);

        /* remove the newline */
        buffer[size-1] = '\0';
        size--;

        p = buffer;
        size = 0;

        /* edit the buffer for tabs and non-printables */
        while(*p) {

          if (*p == '\t') {
            do {
              edited[size++] = ' ';
            } while(size&3);
          } else

          if (*p < ' ') {
            edited[size++] = '^';
            edited[size++] = *p + '@';

          } else
            edited[size++] = *p;

          p++;

          /* mark the line as longer than the window */
          if (size >= Line_Length) {
            edited[size-1] = '>';
            break;
          }
        }
      }
    }

    SetAPen(Window->RPort, SHADOWPEN);
    Move(Window -> RPort, FIRST+1, where+1) ;
    Text(Window -> RPort, edited, Line_Length);

    SetAPen(Window->RPort, HIGHLIGHTPEN);
    Move(Window -> RPort, FIRST, where) ;
    Text(Window -> RPort, edited, Line_Length);

  } /* for 1 to size of window */
}

ShowHelp( DirName, FileName )
  char *DirName, *FileName;
{
  register struct IntuiMessage    *message;
  register unsigned short         class, code ;

  if (HelpWind == NULL) {

    /* set up the scroll bar */
    prop.Flags = FREEVERT | AUTOKNOB;
    prop.VertBody = 0x1000;

    New_Window.Screen = screen;

    HelpWind = OpenMyWind(&New_Window,screen, NULL, 320, 200);

    if (HelpWind == NULL){
      CloseHelpWind(20, "can't open the window") ;
      return;
    }

    if (HelpWind == NULL) return;

    AddGList( HelpWind, &Down_Gadget, -1, -1);

    RefreshGadgets( &Down_Gadget, HelpWind, NULL );
  }

  SetAPen(HelpWind->RPort, NORMALPEN);
  SetDrMd(HelpWind->RPort, JAM1);
  RectFill(HelpWind->RPort, GWIDTH, 10,
                          HelpWind->Width-2, HelpWind->Height-10);
  RectFill(HelpWind->RPort, GWIDTH, HelpWind->Height-10,
                          HelpWind->Width-12-(YScale*4),
                          HelpWind->Height);
  BorderWindow( HelpWind );

  Display_File(DirName, FileName) ;
}

/*
 * done - just close everything that's open, and exit.
 */
CloseHelpWind(how, why)
int how;
char *why;
{
  if (HelpWind) {
    CloseMyWind(HelpWind, NULL) ;
    HelpWind = NULL;

    if (infile) {
      fclose(infile) ;
      infile = NULL;
    }
    if (why)
      DispErrMsg(why,0);
  }
}

