/* Another weird program from another weird programmer ? YES.
   Still playing the never-ending adventure of 'How To Program An Amiga..'
   I'm still 'writing' useless little programs in order to find out
   about Amiga specific 'nuggles'. (What are nuggles? Don't ask me..) */

#include <graphics/gfx.h> /* probably don't need them all ?? */
#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <graphics/text.h>
#include <libraries/diskfont.h>
#include <stdio.h>
#include <exec/interrupts.h>
#include <hardware/custom.h>
#include <hardware/intbits.h>

struct Interrupt *VertBIntr;
struct { long count;           /* number of requests */
         long speed;           /* every 50/speed requests */
         long flag;            /* which color ? */
         APTR grafbase;        /* where's my GfxBase */
         APTR vport;           /* Need my Vieport too */
       } VertBData={0L,10L,0L,0L,0L};


struct GfxBase *GfxBase;               
struct IntuitionBase *IntuitionBase;
struct DiskfontBase *DiskfontBase;
struct Screen *screen=NULL;
struct NewScreen ns=
{0,0,640,256,3,0,0,HIRES,CUSTOMSCREEN,NULL,NULL,NULL,NULL};
struct Window *window=NULL;
struct NewWindow nw=
{0,0,640,256,0,1,NULL,BORDERLESS|BACKDROP,NULL,NULL,NULL,
 NULL,NULL,0,0,640,200,CUSTOMSCREEN};
struct RastPort *rp;
struct ViewPort vp;
struct TextAttr f;
struct TextFont *font;

long r1=2,r2=7,g1=9,g2=3,b1=13,b2=15; /* color values RGB */
int ysize=10,delta=20,space=2;        /* textspacings */

VertBServer() /* this one does the flashing stuff */
{ 
#asm
        movem.l d0-d7/a0-a6,-(SP)	; save regs /* just to be sure! */
	addq.l	#1,(a1)			; increment count
	move.l	(a1),d0			; count -> d0
	cmp.l	4(a1),d0		; count == speed ?
	bne.s	EndIntr			; no, endintr
	clr.l   (a1)			; yes, clear count
	move.l	12(a1),a6		; get gfxbase
	cmpi.l	#0,8(a1)		; reset color ?
	beq.s	Set			; no, set it

	move.l	#7,d0			; yes, set up registers
        move.l	_r1,d1
        move.l	_g1,d2
        move.l	_b1,d3
	move.l	16(a1),a0		; get viewport
	jsr	-288(a6)		; go reset the color /* SetRGB4 */
        movem.l	(SP)+,d0-d7/a0-a6	; get old regs

	clr.l	8(a1)			; clear flag
	bra.s	EndIntr			; go endintr

Set     move.l	#7,d0			; set up regs 
        move.l	_r2,d1
        move.l	_g2,d2
        move.l	_b2,d3
	move.l	16(a1),a0		; get viewport
	jsr	-288(a6)		; go set the color
        movem.l	(SP)+,d0-d7/a0-a6	; get old regs

	move.l	#$ffffffff,8(a1)	; set flag /* rather big one huh? */
EndIntr
	move.l	#0,d0			; so far, so good....
#endasm
}

InstallFlash() /* hook in the server... */
{ 

  VertBIntr=(struct Interrupt *)AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC);
  if(VertBIntr==NULL) return(FALSE);

  VertBIntr->is_Node.ln_Type=NT_INTERRUPT;
  VertBIntr->is_Node.ln_Pri=-16;
  VertBIntr->is_Node.ln_Name="VertBflash";
  VertBIntr->is_Data=(APTR)&VertBData;
  VertBIntr->is_Code=VertBServer;

  AddIntServer(INTB_VERTB,VertBIntr);
  return(NULL);
}

NextLine(rp,xpos,ypos)  /* goto next 'text line' */
struct RastPort *rp;
int *xpos, *ypos;
{ int cnt;
  (*xpos)=0;
  if(256-(*ypos) < ysize+space)
    ScrollRaster(rp,0,ysize+space,0,0,640,256);
  else
  { (*ypos) +=(ysize+space);
  }
}


main(argc,argv)
int argc;
char *argv[];
{ FILE *InFile;           /* handle to textfile */
  int xpos=0, ypos;       /* my coordinates */
  int oldx=0, oldy;       /* the old ones for B option */
  char ch;                /* just to hold a character */
  char *str="\0\0";       /* the escape parms */
  char hulpstr[20];       /* dummy dummy dummy... */
  int col=1;              /* current color */
  char Code;              /* which escape code ? */
  char SubFunc;           /* and it's subfunction */
  long r,g,b;             /* RGB values */
  int x1=0,y1=0,x2=0,y2=0,xo=0,yo=0; /* coordinates for linedrawing */

  if(argc!=4) /* need 3 parms */
  { puts("USAGE: SHOW <textfile> <font.font> <fontsize>");
    puts("Program by SynSys, J Sparla 1988 no version, no rights\n");
    exit(0);
  }

  DiskfontBase=(struct Library *)OpenLibrary("diskfont.library",0);
  if(DiskfontBase==NULL) goto CleanUp;
  GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0);
  if(GfxBase==NULL) goto CleanUp;
  VertBData.grafbase=GfxBase;
  IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0);
  if(IntuitionBase==NULL) goto CleanUp;
  screen=(struct Screen *)OpenScreen(&ns);
  if(screen==NULL) goto CleanUp;
  ShowTitle(screen,FALSE);
  nw.Screen=screen;
  vp=screen->ViewPort;
  VertBData.vport= &vp;
  window=(struct Window *)OpenWindow(&nw);
  if(window==NULL) goto CleanUp;
  rp=window->RPort;
  sscanf(argv[3],"%d",&ysize); /* get the requested font size as integer */
  f.ta_Name=argv[2];
  f.ta_YSize=ysize;
  f.ta_Style=0;
  f.ta_Flags=0;
  font=OpenDiskFont(&f);       /* try to get the requested font */
  if(font==NULL) goto CleanUp;
  ysize=f.ta_YSize;            /* modify ysize of the font */
  delta=ysize;                 /* xsize equates ysize for so long... */
  ypos=ysize; oldy=ysize;

  SetAPen(rp,0);               /* clear the screen */
  RectFill(rp,0,0,640,256);
  SetAPen(rp,1);
     
  SetFont(rp,font);            /* use font */
  if(InstallFlash()!=NULL) goto CleanUp; /* flashflash! */

  InFile=fopen(argv[1],"r");   /* open requested textfile */
  if(InFile==NULL) goto CleanUp;

  while(!feof(InFile))         /* as long as there are characters... */
  { if((ch=fgetc(InFile))=='') /* escape detected ? */
    { Code=fgetc(InFile);       /* get it's code and subfunction */
      SubFunc=fgetc(InFile)-'0';
      switch(toupper(Code))     /* find out what's to be done */
      { case 'C' : SetAPen(rp,(col=SubFunc));  /* change color */
                   break;
        case 'W' : if(SubFunc!=0)              /* wait time */
                     Delay(5*SubFunc+1);
                   else getchar();             /* wait return */
                   break;
        case 'S' : SetAPen(rp,SubFunc);        /* clear screen */
                   SetBPen(rp,SubFunc);
                   RectFill(rp,0,0,640,256);
                   SetAPen(rp,col);
                   xpos=0; ypos=ysize;
                   break;
        case 'X' : ungetc(SubFunc+'0',InFile); /* move to xcoordinate */
                   oldx=xpos;
                   fgets(hulpstr,4,InFile);
                   sscanf(hulpstr,"%d",&xpos);
                   break;
        case 'Y' : ungetc(SubFunc+'0',InFile); /* move to ycoordinate */
                   oldy=ypos;
                   fgets(hulpstr,4,InFile);
                   sscanf(hulpstr,"%d",&ypos);
                   break;
        case 'B' : ypos=oldy;                  /* back to previous position */
                   xpos=oldx;
                   break;
        case 'F' : if(SubFunc!=0)              /* set flash speed */
                   { VertBData.speed=(long)(SubFunc*2);
                     VertBData.count=(long)(SubFunc*2-1);
                   }
                   else
                     SetAPen(rp,col); 
                   break;
        case 'M' : r=(ch=fgetc(InFile)-'0') > 9 ? ch-7 : ch; /* modify colors*/
                   g=(ch=fgetc(InFile)-'0') > 9 ? ch-7 : ch;
                   b=(ch=fgetc(InFile)-'0') > 9 ? ch-7 : ch;
                   if(SubFunc<=7) SetRGB4(&vp,SubFunc,r,g,b);
                   if(SubFunc==7) /* first color for flas */
                   { r1=r; g1=g; b1=b;
                   }
                   if(SubFunc==8) /* second color for flash.. */
                   { r2=r; g2=g; b2=b; 
                   }
                   break;
        case 'L' : fgets(hulpstr,4,InFile);      /* draw line */
                   sscanf(hulpstr,"%d",&x1);
                   fgets(hulpstr,4,InFile);
                   sscanf(hulpstr,"%d",&y1);
                   fgets(hulpstr,4,InFile);
                   sscanf(hulpstr,"%d",&x2);
                   fgets(hulpstr,4,InFile);
                   sscanf(hulpstr,"%d",&y2);
                   xo=rp->cp_x; yo=rp->cp_y;
                   SetAPen(rp,SubFunc);
                   Move(rp,x1,y1);
                   Draw(rp,x2,y2);
                   Move(rp,xo,yo);
                   SetAPen(rp,col);
                   break;
        case 'I' : space=SubFunc;               /* interline spacing.. */
      }
    }
    else if(ch=='\n')                  /* goto next textline */
    { NextLine(rp,&xpos,&ypos);
    }
    else if(ch=='\\')                  /* skip linefeed after '\' */
    { if((ch=fgetc(InFile))!='\n')
        ungetc(ch,InFile);
    }
    else                               /* display character */
    { *str=ch;
      Move(rp,xpos,ypos);
      Text(rp,str,1);
      xpos=rp->cp_x;
      if(640-(rp->cp_x) <= delta)
      { NextLine(rp,&xpos,&ypos);
      }
    }
  }

CleanUp: /* close en cleanup theatre */

  if(InFile)        fclose(InFile);
  else puts("Couldn't find inputfile\n");
  if(IntuitionBase) CloseLibrary(IntuitionBase);
  else puts("Couldn't find Intuition\n");
  if(GfxBase)       CloseLibrary(GfxBase); 
  else puts("Couldn't find Graphix\n");
  if(DiskfontBase)  CloseLibrary(DiskfontBase);
  else puts("Couldn't find Diskfontlib\n");
  if(window)        CloseWindow(window);
  else puts("Couldn't open window\n");
  if(screen)        CloseScreen(screen);
  else puts("Couldn't open screen\n");
  if(VertBIntr)     { RemIntServer(INTB_VERTB,VertBIntr);
                      FreeMem(VertBIntr,sizeof(struct Interrupt));
                    }
  else puts("Couldn't add interruptserver\n");
  if(font)          RemFont(font); 
  else puts("Couldn't open font...\n");
  exit(0);
}
