/* TP(L) V0.9 - asciifile displayer
   Demo for UGA newsletter
   (c)1989 by Trihedral systems for the Amiga
   Author: Jeroen K Sparla
   Language: Manx Aztec C V3.6a
   Compiler notes: Use option +L for automatic long ints.
*/

/* place here your includes (outside the comment...)
   I'm using the Aztec +i option for pre-compiled include files.
   you need at least the following headerfiles :
   #include <stdio.h>
   #include <intuition/intuitionbase.h>
   #include <exec/types.h>
   #include <exec/execbase.h>
   #include <exec/exec.h>
   #include <graphics/gfxbase.h>
   #include <graphics/gfx.h>
   #include <graphics/text.h>
*/

#define GTX 560  /* Emulated Gadget coordinates topleft & bottomright */
#define GTY 0
#define GBX 579
#define GBY 9

extern struct Screen *OpenScreen();           /* prototyping for Aztec */

LONG IntuitionBase=0L;                        /* pointer to intuition.library */
LONG GfxBase=0L;                              /* pointer to graphics.library */

/* our own screen definitions */
struct NewScreen ns= { 0,0,                   /* top x,y */
                       640,200,1,             /* lower x,y and number of bitplanes */
                       0,1,                   /* detail and block pen */
                       HIRES,                 /* we want a hires screen */
                       CUSTOMSCREEN,          /* not the workbench but our own */
                       NULL,                  /* default font */
                       /* the title */
                       (UBYTE *)"TP(L) V0.9 (c)1989 by Trihedral Systems  -=[YEP]=-",
                       NULL                   /* always null, no screengadgets */
                     };

struct RastPort *rp=NULL;                     /* pointer to rasterport */
struct Screen *screen=NULL;                   /* pointer to screen */
FILE  *infile=NULL;                           /* pointer to our ascii textfile */
int error=0;                                  /* errornumber during init */
int new=FALSE;                                /* user want to start again ? */
int scndscr=FALSE;                            /* are we past the first screen ? */
int BottomLine;                               /* lowest scanline we want to reach */

/*------------------ Initialize the system --------------------------*/

void Init()
{ /* try to open the graphics library */
  GfxBase=OpenLibrary("graphics.library",0);
  if(GfxBase==NULL)
  { puts("Can't open graphics.library");
    error=10;
  }
  /* try to open the intuition library */
  IntuitionBase=OpenLibrary("intuition.library",0);
  if(IntuitionBase==NULL)
  { puts("Can't open intuition.library");
    error=20;
  }
  /* try to open the new screen */
  screen=OpenScreen(&ns);
  if(screen==NULL)
  { puts("Can't open screen");
    error=30;
  }
  /* place screen in front (should be done automaticly.. just in case */
  ScreenToFront(screen);
  /* initialise pointer to the rasterport from the screen */
  rp = &screen->RastPort;
  /* set the drawing pen to the second color (0,1,2...) of the palette */
  SetAPen(rp,1);
  ShowTitle(screen,FALSE);        /* disable screen title */
}

/*------------------- Check if left mousebutton is pressed --------------*/
 
int LeftMouseButton()
{ APTR address=0xbfe000;          /* CIAA, bit 6, 1:released, 0:pressed */ 
                                  /* this should be address 0xbfe001, but */
                                  /* we work on word (2byte) boundaries */
  unsigned short Mouse;  
  Mouse=(unsigned short)(*address);        /* fetch data CIAA */
  if((Mouse & 64)==64)                     /* bit 6 set ? */
    return(FALSE);                         /* yes, button not pressed */
  else
    return(TRUE);                          /* no, button is pressed */
}

/*------------ Draw an emulated -non intuition- gadget in screentitle ---*/

void DrawGadget()
{ SetAPen(rp,0);                           /* set drawpen to backgroundcolor */
  RectFill(rp,GTX,GTY,GBX,GBY);            /* draw filled box */
  SetAPen(rp,1);                           /* set drawpen to cursorcolor */
  Move(rp,GTX+4,GTY+2);                    /* move to topleftedge */
  Draw(rp,GBX-4,GTY+2);                    /* draw interior box */
  Draw(rp,GBX-4,GBY-2);
  Draw(rp,GTX+4,GBY-2);
  Draw(rp,GTX+4,GTY+2);
}

/*--------------------------- Clear the screen (without titlebar) -------*/

CLS()
{ SetAPen(rp,0);                           /* background color */
  /* fill until scanline 200 if NTSC, in PAL until line 256 */
  RectFill(rp,0,10,639,BottomLine==201 ? 199 : 255);
  SetAPen(rp,1);                           /* back to cursor color */
  DrawGadget();                            /* place the gadget, just in case... */
}

/*----------------- Display the next screen ----------------------------*/

NextScreen()
{ int x,y,hit=FALSE;                /* mouse x,y position and mouseleftbutton */
  new=FALSE;                        /* does the user want to restart */
  while((!hit) && (!new))           /* user didn't take any action */
  { hit=LeftMouseButton();          /* left mousebutton ? */
    x=screen->MouseX;               /* fetch mouse coordinates */
    y=screen->MouseY;
    /* if the pointer is in our gadget and we are at least at the secondscreen */
    if(x>GTX && x<GBX && y>GTY && y<GBY && scndscr)
      new=TRUE;                     /* the user wants to restart */
  }
  CLS();                            /* always clear the screen */
  if(hit && new)                    /* user in gadget and mousebutton pressed */
    error=(90);                     /* user wants to quit */
  if(hit)                           /* mousebutton pressed ? */
    scndscr=TRUE;                   /* this means we are reading the next screen */
}

/*---------- Cleanup the mess we made ------------------------------*/

CleanUp()
{
  if(infile) fclose(infile);                     /* close the textfile */
  if(screen) CloseScreen(screen);                /* give screen back.. */
  if(IntuitionBase) CloseLibrary(IntuitionBase); /* don't need this libs anymore */
  if(GfxBase) CloseLibrary(GfxBase);
}

/*------- ^C-pressed routine --------------------------------------*/

_abort()
{ puts("-=INTERRUPTED=- user abort request");
  /* user wants to quit by pressing [ctrl]C on keyboard */
  CleanUp();        /* cleanup the system before */
  exit(100);        /* exit with errornumber */
}

/*---------------- main entry routine -----------------------------*/

main(argc,argv)
int argc;                        /* urgument count (1..n) */
char *argv[];                    /* the values (0..n-1) */
{ int xpos,ypos,len;             /* current x,y cursor position & length */        
  char str[81];                  /* from the string stored int str */
  char ch;                       /* dummy character */

  if(argc!=2)                    /* more or less than 1 argument ? */ 
  { puts("USAGE : TP(L) <ascii-file>");        /* display help */
    CleanUp();                   /* cleanup and exit with error */
    error=40;
    goto Quit;
  }
  infile=fopen(argv[1],"r");     /* try to open the specified file */
  if(infile==NULL)               /* nop, not found... */
  { puts("Can't open specified file");
    CleanUp();
    error=50;
    goto Quit;
  }
  /* this is kinda tricky:
  since we have NTSC (200 scanlines) and PAL (256 scanlines) version Amy's
  the name of the command defines the version you want to use. 
  if you name the program :
  TP  you are requesting the NTSC version.
  TPL you are requesting the PAL version.
  */
  BottomLine=201;                /* standard NTSC */
  if(toupper(argv[0][2])=='L')   /* if command's 3th character is an L */
  { BottomLine=257;              /* we want the large screen */
    ns.Height=256;               /* redefine screen height */
  }
  Init();                        /* initialise the system */
  if(error)                      /* error returned ? */
    goto Quit;                        
  CLS();                         /* clear the screen */
  xpos=0; ypos=17;               /* cursor position */
  Move(rp,xpos,ypos);            /* go set the cursor */

  while((ch=getc(infile)) != EOF)        /* read one char ahead to detect EOF */
  { ungetc(ch,infile);                   /* put character back in buffer */
    fgets(str,81,infile);                /* get a string of maximal 80+\0 chars */
    len=strlen(str);                     /* calculate it's length */
    if(len==80)                          /* buffer was full without reading a \0 */
      len++;
    Move(rp,xpos,ypos);                  /* move to cursor position */
    Text(rp,str,--len);                  /* output the textline */
    ypos+=8;                             /* 'linefeed' */
    if(ypos==BottomLine)                 /* did we reach the bootom */
    { NextScreen();                      /* yes, do the next screen */
      ypos=17;                           /* cursor back to top */
      if(error==90)                      /* did user want to quit ? */
      { CleanUp();                       /* cleanup and quit */
        goto Quit;
      }
      if(new)                            /* user wants to restart */
      { new=FALSE;                       /* reset flags */
        scndscr=FALSE;
        if(fseek(infile,0L,0L))          /* goto start of file */
          puts("Something wrong with seek");   /* how could this happen ? */
      }
    }
  }
  NextScreen();                          /* clear the last screen */
  CleanUp();                             /* cleanup the theatre */
Quit:
  exit(error);
}
