
#include <exec/types.h>
#include <intuition/intuition.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/text.h>
#include <graphics/rastport.h>
#include <libraries/dosextens.h>
#include <libraries/diskfont.h>
#include <stdio.h>

extern long code;                   /*code from IntuiMessage*/
extern struct TextAttr TextAttr; /*Text attributes of custom font*/
extern struct TextAttr DefaultAttr; /*Default Text attributes */
extern struct TextFont *FontPtr;   /*custom font pointer*/
extern struct TextFont *DefaultPtr; /*default font pointer*/
extern struct RastPort *rp;       /*RastPort for main window*/
extern struct RastPort *rptext;  /*RastPort for text window*/

static struct MenuItem MenuItemf[20];   /*array of 20 MenuItems*/
static struct MenuItem SubItemf[50];    /*array of 50 SubItems*/
static struct IntuiText ITextf[70];     /*array of 70 IntuiTexts*/

struct AvailFonts *af;           /*avail fonts structure*/
int AvailFonts();                /*routine from diskfont library*/
char fontname[36];               /*name of current font*/
char lastname[36];               /*name of last font*/
char *dotfont=".font";           /*file extension of file header*/
char availbuff[12];               /*buffer*/
char availfontname[20*30];       /*font names*/  
char availfontnumber[50*4];      /*font sizes*/
struct AvailFontsHeader *afh;    /*header structure for available fonts data*/


/* menus and menuitems */



struct IntuiText IText9 = {
   3,1,COMPLEMENT,  /*front and back text pens,drawmode and fill byte */
   CHECKWIDTH,0,    /* XY origin relative to container TopLeft */
   &DefaultAttr,    /* font pointer or NULL for default */
   "Italic",        /* pointer to text */
   NULL             /* next IntuiText structure */ 
};

struct MenuItem MenuItem4 = {
   NULL,   /* next MenuItem structure, or NULL for last one */                        
   0,24,   /* XY of Item hitbox relative to TopLeft of parent hitbox */
   160,8,  /* hitbox width and height */
   ITEMTEXT+CHECKIT+COMMSEQ+ITEMENABLED+HIGHCOMP, /*Item flags */
   7,      /*each bit mutually excludes a sme-level item */
   (APTR)&IText9,  /*Item render (IntuiText or Image or NULL) */
    NULL,  /* Select render */
   'I',    /* alternate command-key */
   NULL,   /* SubItem list */
   MENUNULL       /*filled in by Intuition for drag selections */
};

struct IntuiText IText8 = {
   3,1,COMPLEMENT,
   CHECKWIDTH,0,
   &DefaultAttr,
   "Underlined",
   NULL
};

struct MenuItem MenuItem3 = {
   &MenuItem4,
   0,16,
   160,8,
   ITEMTEXT+CHECKIT+COMMSEQ+ITEMENABLED+HIGHCOMP,
   11,
   (APTR)&IText8,
   NULL,
   'U',
   NULL,
   MENUNULL
};

struct IntuiText IText7 = {
   3,2,COMPLEMENT,
   CHECKWIDTH,0,
   &DefaultAttr,
   "Bold",
   NULL
};

struct MenuItem MenuItem2 = {
   &MenuItem3,
   0,8,
   160,8,
   ITEMTEXT+CHECKIT+COMMSEQ+ITEMENABLED+HIGHCOMP,
   13,
   (APTR)&IText7,
   NULL,
   'B',
   NULL,
   MENUNULL
};

struct IntuiText IText6 = {
   3,2,COMPLEMENT,
   CHECKWIDTH,0,
   &DefaultAttr,
   "Normal",
   NULL
};

struct MenuItem MenuItem1 = {
   &MenuItem2,
   0,0,
   160,8,
   CHECKIT+ITEMTEXT+CHECKED+COMMSEQ+ITEMENABLED+HIGHCOMP,
   14,
   (APTR)&IText6,
   NULL,
   'N',
   NULL,
   MENUNULL
};

/*fonts menu structure*/
struct Menu Menu2 = {
   NULL,            /*always last menu on bar*/ 
   88,0,            /*XY origin follows on from last menu*/
   79,0,            
   MENUENABLED,
   "LOAD FONT",    /*text of name*/
   NULL            /*dummy first item*/
};

struct Menu Menu1 = {
   &Menu2,         /* next Menu structure */
   0,0,          /* XY origin of Menu hit box relative to screen TopLeft */
   87,0,         /* Menu hit box width and height */
   MENUENABLED,  /* Menu flags */
   "TEXT STYLE", /* text of Menu name */ 
   &MenuItem1    /* MenuItem linked list pointer */
};

/*gadgets and their border vectors */


 SHORT BorderVectors1[] = {
	0,0,
	48,0,
	48,71,
	0,71,
	0,0
};
 struct Border Border1 = {
	-1,-1,	
	3,0,JAM1,
	5,	
	BorderVectors1,	
	NULL	
};

 struct IntuiText IText1 = {
	3,0,JAM2,
	8,40,	
	&DefaultAttr,	
	"Quit",	
	NULL	
};

 struct Gadget Gadget1 = {
	NULL,
	66,131,	
	47,70,	
	NULL,	
    RELVERIFY,	
	BOOLGADGET,	
	(APTR)&Border1,	
	NULL,	
	&IText1,	
	NULL,	
	NULL,	
	NULL,	
	NULL	
};


/*handles gadgetand menu events*/

void HandleEvent(object)
APTR object;
    {
     if (object==(APTR)&Gadget1) 
        {quit();return;}            /*sets the quit flag */ 
     if (object == (APTR)&MenuItem1) 
        { normal(); return; }       /*sets normal style  */
     if (object == (APTR)&MenuItem2) 
        { bold();return; }          /*sets bold style */
     if (object == (APTR)&MenuItem3) 
        { underlined(); return; }   /*sets underlined style */
     if (object == (APTR)&MenuItem4) 
        { italic(); return; }       /*sets italic style */
     findfont(object);              /*font item or sub item*/ 
     return;
     }

/*handles menu events*/
/*finds the item address of the selected menu item*/
/*handles this event */
/*proceeds to the next menu event*/

void HandleMenuEvent()
     {
      struct MenuItem  *object;
     while(code!=MENUNULL)
       {
        object=(struct MenuItem *)ItemAddress(&Menu1,code);
        HandleEvent(object); 
        code=object->NextSelect;
       }
     }


/*checking for available fonts*/
int availfonts()
{
  struct MenuItem *firstsubitem;
  char *pointer;
  short k=0; 
  long i=0;
  char *lastpointer[30];
  short mitems,sitems,offset;
  UBYTE name;
  afh=(struct AvailFontsHeader *)AllocMem(2000,65537);
  AvailFonts(afh,2000,AFF_DISK);        /*avail fonts data*/
  af=(struct AvailFonts *)&afh[1];      /*in buffer*/
  k=afh->afh_NumEntries;                /*allow 20 names*/
  if (k ==0 )                           /*return if no fonts in */
     {                                  /*directory */
      freeavail();
      return(1);
     }
                                      /*allow 50 subitems*/
  if (k>50) k=50;
  mitems=0;
  sitems=0;
  offset=-1;
  for (i=0;i<k;i++)
     {
      /* put the font number into the array*/
      pointer=&availbuff[0];
      itoa(af->af_Attr.ta_YSize,pointer);
      strncpy(&availfontnumber[4*i],pointer,3);
      name=mitems;
      availfontnumber[4*i+3]=name;  /*sub item for each font size*/
      setupitext(&ITextf[i],&availfontnumber[4*i],19);
      setupsubitem(&SubItemf[i],&ITextf[i],&SubItemf[i+1],offset,sitems);
      offset=offset+8;
      sitems=sitems+1;
      pointer=af->af_Attr.ta_Name;
      if (strcmp(&lastpointer[0],pointer)!=0)
           {                   /*menu item for each new font name*/
             strncpy(&availfontname[30*mitems],pointer,strlen(pointer)-5);
             availfontname[30*mitems+29]=0;/*fontname into array*/
             setupitext(&ITextf[k+mitems],&availfontname[30*mitems],0);
             setupmenuitem(&MenuItemf[mitems],&ITextf[k+mitems],&MenuItemf[mitems+1],&SubItemf[i],8*mitems,mitems);
             if (mitems>0) setupsubitem(&SubItemf[i-1],&ITextf[i-1],0,offset-16,i-1);
             setupsubitem(&SubItemf[i],&ITextf[i],&SubItemf[i+1],-1,0);
             firstsubitem=&SubItemf[i];
             offset=7;
             mitems=mitems+1;
             if (mitems>20) {mitems=20;i=k;}
             sitems=1;
             name=mitems;
             availfontnumber[4*i+3]=name;/*font size into array*/
           }
      /*remember the name of thelast font*/
      strncpy(&lastpointer[0],pointer,strlen(pointer)+1);
      af++;
     }     /*put next item pointers to null at end of list*/
  setupsubitem(&SubItemf[k-1],&ITextf[k-1],0,offset-8,sitems-1);
  setupmenuitem(&MenuItemf[mitems-1],&ITextf[k+mitems-1],0,firstsubitem,8*mitems-8,mitems-1);
  Menu2.FirstItem=&MenuItemf[0];/*attach to other menu items*/
  zerofil(&lastname,20);
  strncpy(&lastname[0],"topaz.font",6);
  freeavail();
  return(0);
}

setupmenuitem(menuitem,itext,nextitem,subitem,topedge,mitems)
struct MenuItem *menuitem;
struct IntuiText *itext;
struct MenuItem *nextitem;
struct MenuItem *subitem;
long  topedge;
short mitems;
{
  menuitem->NextItem=0;
  if (nextitem>0) menuitem->NextItem=nextitem;
  menuitem->TopEdge=topedge;
  menuitem->LeftEdge=0;
  menuitem->Width=72;
  menuitem->Height=8;
  menuitem->Flags=CHECKIT+ITEMTEXT+ITEMENABLED+HIGHCOMP;
  menuitem->MutualExclude=0xffff-power(2,mitems);
  menuitem->ItemFill=(APTR)itext;
  menuitem->Command=0;
  menuitem->SubItem=subitem;
  menuitem->NextSelect=0;
  return(menuitem);
}

setupsubitem(menuitem,itext,nextitem,topedge,sitems)
struct MenuItem *menuitem;
struct IntuiText *itext;
struct MenuItem *nextitem;
long  topedge;
short sitems;
{
   menuitem->NextItem=0;
   if (nextitem>0) menuitem->NextItem=nextitem;
   menuitem->TopEdge=topedge;
   menuitem->LeftEdge=57;
   menuitem->Width=35;
   menuitem->Height=8;
   menuitem->Flags=CHECKIT+ITEMTEXT+ITEMENABLED+HIGHCOMP;
   menuitem->MutualExclude=0xffff-power(2,sitems);
   menuitem->ItemFill=(APTR)itext;
   menuitem->Command=0;
   menuitem->SubItem=0;
   menuitem->NextSelect=0;
   return(menuitem);
}

setupitext(itext,pointer,leftedge)
struct IntuiText *itext;
char *pointer;
long leftedge;
{
  itext->FrontPen=3;
  itext->BackPen=2;
  itext->DrawMode=COMPLEMENT;
  itext->TopEdge=0;
  itext->LeftEdge=CHECKWIDTH+leftedge;
  itext->IText=pointer;
  return(itext);
}

freeavail()
{
  FreeMem(afh,2000);
  return(0);
}

/*lose all the check marks */
losecheck(menuitem)
struct MenuItem *menuitem;
{
  short flags;
  flags=menuitem->Flags;
  menuitem->Flags=flags&(0xffff-CHECKED);
  return(menuitem);
}
/*set a check mark*/
putcheck(menuitem)
struct MenuItem *menuitem;
{
  short flags;
  flags=menuitem->Flags;
  menuitem->Flags=flags|CHECKED;
  return(menuitem);
}

findfont(object)
APTR object;
{
  long subitemnumber;
  long fontnumber;
  char *name;
  UBYTE menuitemnumber;
  short i;
  /*find subitemnuber and fontsize*/
  subitemnumber=(long) checkforsubitem(object);
  if (subitemnumber==255) return(0);
  fontnumber=atol(&availfontnumber[subitemnumber*4]);
  /*find item number and font name*/
  menuitemnumber=availfontnumber[subitemnumber*4+3];
  name=&availfontname[menuitemnumber*30-30];
  /*put name into fontnamebuffer and add .font*/
  strncpy(&fontname[0],name,strlen(name)+1);
  strncpy(fontname +strlen(name),dotfont,6);
  changefont(fontnumber,&fontname[0]);
  /*font loaded. tidy up checkmarks*/
  zerofil(&lastname[0],20);
  strncpy(&lastname[0],name,strlen(name)+1);
  for (i=0;i<50;i++) losecheck(&SubItemf[i]);
  putcheck(&SubItemf[subitemnumber]);
  for (i=0;i<20;i++) losecheck(&MenuItemf[i]);
  putcheck(&MenuItemf[menuitemnumber-1]);
  return(0);
}

/*find place in array from subitem number*/
long  checkforsubitem(object)
struct MenuItem *object;
{
   long i;
   long flag=255;
   for(i=0;i<50;i++)
   if (object==&SubItemf[i]) return(i);
   return(flag);
}

firstfont()
{
   DefaultAttr.ta_Flags = FPF_ROMFONT;     /*diskfont*/
   DefaultAttr.ta_Style = FS_NORMAL;        /*reset style to normal*/ 
   DefaultAttr.ta_YSize= 8;                 /*font height*/
   DefaultAttr.ta_Name="topaz.font";                /*font name*/  
   DefaultPtr=(struct TextFont *)OpenDiskFont(&DefaultAttr); /*find font pointer*/
   if (DefaultPtr==0)                       /*message if font not available*/
     {
       printf("no font");
       return(1);
     }
   SetFont(rp,DefaultPtr);                  /*set the font*/
   writetext();                          /*write the text in the new font*/
   return(0);
}


changefont(size,name)
long size;
char *name;
{
   TextAttr.ta_Flags = FPF_DISKFONT;     /*diskfont*/
   TextAttr.ta_Style = FS_NORMAL;        /*reset style to normal*/ 
   TextAttr.ta_YSize= size;                 /*font height*/
   TextAttr.ta_Name=name;                /*font name*/  
   FontPtr=(struct TextFont *)OpenDiskFont(&TextAttr); /*find font pointer*/
   if (FontPtr==0)                       /*message if font not available*/
     {
       printf("no font");
       return(1);
     }
   SetFont(rptext,FontPtr);                  /*set the font*/
   writetext();                          /*write the text in the new font*/
   return(0);
}

/*fill from s with n zeros*/
zerofil(s,n)
char *s;
long n;
{
  int i;
  for (i=0;i<n;i++)
  *s=0;
  return(0);
}

/*raise x to power n*/
power(x,n)
long x,n;
{
   long i,p;
   p=1;
   if(n==0) return(1);
   for (i=1;i<=n;++i)
   p=p*x;
   return(p);
} 

/*integer to ascii*/
itoa(n,s)
char s[];
int n;
{
   int i=0;
   do 
      {
        s[i++]=n%10+'0';
      } 
   while ((n/=10)>0);
   s[i]='\0';
   reverse(s);
   return(0);
}

reverse(s)
char s[];
{
  int c,i,j;
  for (i=0,j=strlen(s)-1;i<j;i++,j--)
     {
        c=s[i];
        s[i]=s[j];
        s[j]=c;
     }
  return(0);
}
