/********************************************/
/*   ShowFont 2.0 - by Arthur Johnson Jr.   */
/* ======================================== */
/* Usage: ShowFont [font_name] [font_size]  */
/* ======================================== */
/*      Last modifications - 09/07/88       */
/********************************************/

#include "intuition/intuition.h" /* this one includes heaps o' stuff */
#include "exec/memory.h"
#include "libraries/diskfont.h"

#define XAREA        617    /* no characters beyond this pixel */
#define FONTBUFFER  5000    /* works for me */
#define FONTNAMELEN   24    /* 23 characters plus the '\0' */
#define MAXSIZES      20    /* hopefully this is overly generous */

/****************************************************/
/* All screen/window/gadget structures created with */
/*              PowerWindows 2.0,  by:              */
/* Inovatronics, Inc.                               */
/* 11311 Stemmons Freeway                           */
/* Dallas, TX  75229                                */
/* (214) 241-9515                                   */
/****************************************************/

struct PropInfo W_PropSInfo = {
        AUTOKNOB+FREEVERT,      /* PROPINFO flags */
        -1,-1,  /* horizontal and vertical pot values */
        -1,-1,  /* horizontal and vertical body values */
};

struct Image Image1 = {
        0,0,    /* XY origin relative to container TopLeft */
        8,167,  /* Image width and height in pixels */
        0,      /* number of bitplanes in Image */
        NULL,   /* pointer to ImageData */
        0x0000,0x0000,  /* PlanePick and PlaneOnOff */
        NULL    /* next Image structure */
};

struct Gadget W_Prop = {
        NULL,   /* next gadget */
        619,19, /* origin XY of hit box relative to window TopLeft */
        16,171, /* hit box width and height */
        NULL,   /* gadget flags */
        RELVERIFY,      /* activation flags */
        PROPGADGET,     /* gadget type flags */
        (APTR)&Image1,  /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        NULL,   /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        (APTR)&W_PropSInfo,     /* SpecialInfo structure */
        2,      /* user-definable data */
        NULL    /* pointer to user-definable data */
};

USHORT ImageDownData[] = {
        0xFFFF,0x8001,0x8181,0x8181,0x87E1,0x83C1,0x8181,0x8001,
        0xFFFF
};

struct Image ImageDown = {
        0,0,    /* XY origin relative to container TopLeft */
        16,9,   /* Image width and height in pixels */
        2,      /* number of bitplanes in Image */
        ImageDownData,     /* pointer to ImageData */
        0x0001,0x0000,  /* PlanePick and PlaneOnOff */
        NULL    /* next Image structure */
};

struct Gadget W_Down = {
        &W_Prop,        /* next gadget */
        619,190,        /* origin XY of hit box relative to window TopLeft */
        16,9,   /* hit box width and height */
        GADGIMAGE,      /* gadget flags */
        RELVERIFY,      /* activation flags */
        BOOLGADGET,     /* gadget type flags */
        (APTR)&ImageDown,  /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        NULL,   /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        NULL,   /* SpecialInfo structure */
        3,      /* user-definable data */
        NULL    /* pointer to user-definable data */
};

USHORT ImageUpData[] = {
        0xFFFF,0x8001,0x8181,0x83C1,0x87E1,0x8181,0x8181,0x8001,
        0xFFFF
};

struct Image ImageUp = {
        0,0,    /* XY origin relative to container TopLeft */
        16,9,   /* Image width and height in pixels */
        2,      /* number of bitplanes in Image */
        ImageUpData,     /* pointer to ImageData */
        0x0001,0x0000,  /* PlanePick and PlaneOnOff */
        NULL    /* next Image structure */
};

struct Gadget W_Up = {
        &W_Down,        /* next gadget */
        619,10, /* origin XY of hit box relative to window TopLeft */
        16,9,   /* hit box width and height */
        GADGIMAGE,      /* gadget flags */
        RELVERIFY,      /* activation flags */
        BOOLGADGET,     /* gadget type flags */
        (APTR)&ImageUp,  /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        NULL,   /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        NULL,   /* SpecialInfo structure */
        1,      /* user-definable data */
        NULL    /* pointer to user-definable data */
};

#define GadgetList1 W_Up

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

struct MenuItem MenuItem2 = {
        NULL,   /* next MenuItem structure */
        0,9,    /* XY of Item hitbox relative to TopLeft of parent hitbox */
        152,8,  /* hit box width and height */
        ITEMTEXT+COMMSEQ+HIGHCOMP,  /* Item flags */
        0,      /* each bit mutually-excludes a same-level Item */
        (APTR)&IText1,  /* Item render  (IntuiText or Image or NULL) */
        NULL,   /* Select render */
        'F',    /* alternate command-key */
        NULL,   /* SubItem list */
        MENUNULL        /* filled in by Intuition for drag selections */
};

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

struct MenuItem MenuItem1 = {
        &MenuItem2,     /* next MenuItem structure */
        0,0,    /* XY of Item hitbox relative to TopLeft of parent hitbox */
        152,8,  /* hit box width and height */
        ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP,  /* Item flags */
        0,      /* each bit mutually-excludes a same-level Item */
        (APTR)&IText2,  /* Item render  (IntuiText or Image or NULL) */
        NULL,   /* Select render */
        'R',    /* alternate command-key */
        NULL,   /* SubItem list */
        MENUNULL        /* filled in by Intuition for drag selections */
};

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

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

struct MenuItem MenuItem4 = {
        NULL,   /* next MenuItem structure */
        0,9,    /* XY of Item hitbox relative to TopLeft of parent hitbox */
        80,8,   /* hit box width and height */
        ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP,  /* Item flags */
        0,      /* each bit mutually-excludes a same-level Item */
        (APTR)&IText3,  /* Item render  (IntuiText or Image or NULL) */
        NULL,   /* Select render */
        'Q',    /* alternate command-key */
        NULL,   /* SubItem list */
        MENUNULL        /* filled in by Intuition for drag selections */
};

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

struct MenuItem MenuItem3 = {
        &MenuItem4,     /* next MenuItem structure */
        0,0,    /* XY of Item hitbox relative to TopLeft of parent hitbox */
        80,8,   /* hit box width and height */
        ITEMTEXT+COMMSEQ+ITEMENABLED+HIGHCOMP,  /* Item flags */
        0,      /* each bit mutually-excludes a same-level Item */
        (APTR)&IText4,  /* Item render  (IntuiText or Image or NULL) */
        NULL,   /* Select render */
        'A',    /* alternate command-key */
        NULL,   /* SubItem list */
        MENUNULL        /* filled in by Intuition for drag selections */
};

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

#define MenuList1 Menu1

struct NewWindow newwindow = {
        0,0,    /* window XY origin relative to TopLeft of screen */
        640,200,        /* window width and height */
        0,1,    /* detail and block pens */
        GADGETUP+MENUPICK+CLOSEWINDOW,  /* IDCMP flags */
        WINDOWDEPTH+WINDOWCLOSE+ACTIVATE,       /* other window flags */
        &GadgetList1,  /* first gadget in gadget list */
        NULL,   /* custom CHECKMARK imagery */
        "ShowFont 2.0 by Arthur Johnson Jr.",   /* window title */
        NULL,   /* custom screen pointer */
        NULL,   /* custom bitmap */
        -1,-1,  /* minimum width and height */
        -1,-1,  /* maximum width and height */
        WBENCHSCREEN    /* destination screen type */
};

SHORT BorderVectors2[] = {
        0,0,
        29,0,
        29,58,
        0,58,
        0,0
};
struct Border Border2 = {
        246,8,  /* XY origin relative to container TopLeft */
        1,0,JAM1,       /* front pen, back pen and drawmode */
        5,      /* number of XY vectors */
        BorderVectors2, /* pointer to XY vectors */
        NULL    /* next border in list */
};

SHORT BorderVectors1[] = {
        0,0,
        188,0,
        188,58,
        0,58,
        0,0
};
struct Border Border1 = {
        5,8,    /* XY origin relative to container TopLeft */
        1,0,JAM1,       /* front pen, back pen and drawmode */
        5,      /* number of XY vectors */
        BorderVectors1, /* pointer to XY vectors */
        &Border2        /* next border in list */
};

struct Gadget Gadget12 = {
        NULL,   /* next gadget */
        0,0,    /* origin XY of hit box relative to window TopLeft */
        1,1,    /* hit box width and height */
        GADGHBOX+GADGHIMAGE,    /* gadget flags */
        NULL,   /* activation flags */
        BOOLGADGET+REQGADGET,   /* gadget type flags */
        (APTR)&Border1, /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        NULL,   /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        NULL,   /* SpecialInfo structure */
        NULL,   /* user-definable data */
        NULL    /* pointer to user-definable data */
};

SHORT BorderVectors3[] = {
        0,0,
        60,0,
        60,16,
        0,16,
        0,0
};
struct Border Border3 = {
        -2,-1,  /* XY origin relative to container TopLeft */
        1,0,JAM1,       /* front pen, back pen and drawmode */
        5,      /* number of XY vectors */
        BorderVectors3, /* pointer to XY vectors */
        NULL    /* next border in list */
};

struct IntuiText IText5 = {
        1,0,JAM2,       /* front and back text pens, drawmode and fill byte */
        6,4,    /* XY origin relative to container TopLeft */
        NULL,   /* font pointer or NULL for default */
        "Cancel",       /* pointer to text */
        NULL    /* next IntuiText structure */
};

struct Gadget R_Cancel = {
        &Gadget12,      /* next gadget */
        185,76, /* origin XY of hit box relative to window TopLeft */
        57,15,  /* hit box width and height */
        NULL,   /* gadget flags */
        RELVERIFY+ENDGADGET,    /* activation flags */
        BOOLGADGET+REQGADGET,   /* gadget type flags */
        (APTR)&Border3, /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        &IText5,        /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        NULL,   /* SpecialInfo structure */
        102,    /* user-definable data */
        NULL    /* pointer to user-definable data */
};

SHORT BorderVectors4[] = {
        0,0,
        60,0,
        60,16,
        0,16,
        0,0
};
struct Border Border4 = {
        -2,-1,  /* XY origin relative to container TopLeft */
        1,0,JAM1,       /* front pen, back pen and drawmode */
        5,      /* number of XY vectors */
        BorderVectors4, /* pointer to XY vectors */
        NULL    /* next border in list */
};

struct IntuiText IText6 = {
        1,0,JAM2,       /* front and back text pens, drawmode and fill byte */
        20,4,   /* XY origin relative to container TopLeft */
        NULL,   /* font pointer or NULL for default */
        "OK",   /* pointer to text */
        NULL    /* next IntuiText structure */
};

struct Gadget R_OK = {
        &R_Cancel,      /* next gadget */
        70,76,  /* origin XY of hit box relative to window TopLeft */
        57,15,  /* hit box width and height */
        NULL,   /* gadget flags */
        RELVERIFY+ENDGADGET,    /* activation flags */
        BOOLGADGET+REQGADGET,   /* gadget type flags */
        (APTR)&Border4, /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        &IText6,        /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        NULL,   /* SpecialInfo structure */
        101,    /* user-definable data */
        NULL    /* pointer to user-definable data */
};

struct Gadget R_SizeDown = {
        &R_OK,  /* next gadget */
        279,58, /* origin XY of hit box relative to window TopLeft */
        16,9,   /* hit box width and height */
        GADGIMAGE,      /* gadget flags */
        RELVERIFY,      /* activation flags */
        BOOLGADGET+REQGADGET,   /* gadget type flags */
        (APTR)&ImageDown,  /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        NULL,   /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        NULL,   /* SpecialInfo structure */
        23,     /* user-definable data */
        NULL    /* pointer to user-definable data */
};

struct PropInfo R_SizeSInfo = {
        AUTOKNOB+FREEVERT,      /* PROPINFO flags */
        -1,-1,  /* horizontal and vertical pot values */
        -1,-1,  /* horizontal and vertical body values */
};

struct Image Image5 = {
        0,0,    /* XY origin relative to container TopLeft */
        8,37,   /* Image width and height in pixels */
        0,      /* number of bitplanes in Image */
        NULL,   /* pointer to ImageData */
        0x0000,0x0000,  /* PlanePick and PlaneOnOff */
        NULL    /* next Image structure */
};

struct Gadget R_Size = {
        &R_SizeDown,    /* next gadget */
        279,17, /* origin XY of hit box relative to window TopLeft */
        16,41,  /* hit box width and height */
        NULL,   /* gadget flags */
        RELVERIFY,      /* activation flags */
        PROPGADGET+REQGADGET,   /* gadget type flags */
        (APTR)&Image5,  /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        NULL,   /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        (APTR)&R_SizeSInfo,     /* SpecialInfo structure */
        22,     /* user-definable data */
        NULL    /* pointer to user-definable data */
};

struct Gadget R_SizeUp = {
        &R_Size,        /* next gadget */
        279,8,  /* origin XY of hit box relative to window TopLeft */
        16,9,   /* hit box width and height */
        GADGIMAGE,      /* gadget flags */
        RELVERIFY,      /* activation flags */
        BOOLGADGET+REQGADGET,   /* gadget type flags */
        (APTR)&ImageUp,  /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        NULL,   /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        NULL,   /* SpecialInfo structure */
        21,     /* user-definable data */
        NULL    /* pointer to user-definable data */
};

struct PropInfo R_FontSInfo = {
        AUTOKNOB+FREEVERT,      /* PROPINFO flags */
        -1,-1,  /* horizontal and vertical pot values */
        -1,-1,  /* horizontal and vertical body values */
};

struct Image Image7 = {
        0,0,    /* XY origin relative to container TopLeft */
        8,37,   /* Image width and height in pixels */
        0,      /* number of bitplanes in Image */
        NULL,   /* pointer to ImageData */
        0x0000,0x0000,  /* PlanePick and PlaneOnOff */
        NULL    /* next Image structure */
};

struct Gadget R_Font = {
        &R_SizeUp,      /* next gadget */
        197,17, /* origin XY of hit box relative to window TopLeft */
        16,41,  /* hit box width and height */
        NULL,   /* gadget flags */
        RELVERIFY,      /* activation flags */
        PROPGADGET+REQGADGET,   /* gadget type flags */
        (APTR)&Image7,  /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        NULL,   /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        (APTR)&R_FontSInfo,     /* SpecialInfo structure */
        12,     /* user-definable data */
        NULL    /* pointer to user-definable data */
};

struct Gadget R_FontDown = {
        &R_Font,        /* next gadget */
        197,58, /* origin XY of hit box relative to window TopLeft */
        16,9,   /* hit box width and height */
        GADGIMAGE,      /* gadget flags */
        RELVERIFY,      /* activation flags */
        BOOLGADGET+REQGADGET,   /* gadget type flags */
        (APTR)&ImageDown,  /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        NULL,   /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        NULL,   /* SpecialInfo structure */
        13,     /* user-definable data */
        NULL    /* pointer to user-definable data */
};

struct Gadget R_FontUp = {
        &R_FontDown,    /* next gadget */
        197,8,  /* origin XY of hit box relative to window TopLeft */
        16,9,   /* hit box width and height */
        GADGIMAGE,      /* gadget flags */
        RELVERIFY,      /* activation flags */
        BOOLGADGET+REQGADGET,   /* gadget type flags */
        (APTR)&ImageUp,  /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        NULL,   /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        NULL,   /* SpecialInfo structure */
        11,     /* user-definable data */
        NULL    /* pointer to user-definable data */
};

#define GadgetList2 R_FontUp

SHORT BorderVectors6[] = {
        0,0,
        299,0,
        299,99,
        0,99,
        0,0
};
struct Border Border6 = {
        0, 0,  /* XY origin relative to container TopLeft */
        1,0,JAM1,       /* front pen, back pen and drawmode */
        5,      /* number of XY vectors */
        BorderVectors6, /* pointer to XY vectors */
        NULL    /* next border in list */
};

struct Requester requester1 = {
        NULL,   /* previous requester (filled in by Intuition) */
        170,50, /* requester XY origin relative to TopLeft of window */
        300,100,        /* requester width and height */
        0,0,    /* relative to these mouse offsets if POINTREL is set */
        &GadgetList2,   /* gadget list */
        &Border6,   /* box's border */
        NULL,   /* requester text */
        NULL,   /* requester flags */
        0,      /* back-plane fill pen */
        NULL,   /* leave these alone */
        NULL,   /* custom bitmap if PREDRAWN is set */
        NULL    /* leave this alone */
};

SHORT BorderVectors5[] = {
        0,0,
        99,0,
        99,25,
        0,25,
        0,0
};
struct Border Border5 = {
        -2,-1,  /* XY origin relative to container TopLeft */
        1,0,JAM1,       /* front pen, back pen and drawmode */
        5,      /* number of XY vectors */
        BorderVectors5, /* pointer to XY vectors */
        NULL    /* next border in list */
};

struct IntuiText IText7 = {
        1,0,JAM2,       /* front and back text pens, drawmode and fill byte */
        36,8,   /* XY origin relative to container TopLeft */
        NULL,   /* font pointer or NULL for default */
        "DUH",  /* pointer to text */
        NULL    /* next IntuiText structure */
};

struct Gadget Gadget5 = {
        NULL,   /* next gadget */
        56,65,  /* origin XY of hit box relative to window TopLeft */
        96,24,  /* hit box width and height */
        NULL,   /* gadget flags */
        RELVERIFY+ENDGADGET,    /* activation flags */
        BOOLGADGET+REQGADGET,   /* gadget type flags */
        (APTR)&Border5, /* gadget border or image to be rendered */
        NULL,   /* alternate imagery for selection */
        &IText7,        /* first IntuiText structure */
        NULL,   /* gadget mutual-exclude long word */
        NULL,   /* SpecialInfo structure */
        NULL,   /* user-definable data */
        NULL    /* pointer to user-definable data */
};

#define GadgetList3 Gadget5

struct IntuiText IText12 = {
        1,0,JAM2,       /* front and back text pens, drawmode and fill byte */
        80,43,  /* XY origin relative to container TopLeft */
        NULL,   /* font pointer or NULL for default */
        "fonts.",       /* pointer to text */
        NULL    /* next IntuiText structure */
};

struct IntuiText IText11 = {
        1,0,JAM2,       /* front and back text pens, drawmode and fill byte */
        20,34,  /* XY origin relative to container TopLeft */
        NULL,   /* font pointer or NULL for default */
        "This program displays",        /* pointer to text */
        &IText12        /* next IntuiText structure */
};

struct IntuiText IText10 = {
        1,0,JAM2,       /* front and back text pens, drawmode and fill byte */
        8,19,   /* XY origin relative to container TopLeft */
        NULL,   /* font pointer or NULL for default */
        "Last revision - 09/07/88",     /* pointer to text */
        &IText11        /* next IntuiText structure */
};

struct IntuiText IText9 = {
        3,0,JAM2,       /* front and back text pens, drawmode and fill byte */
        20,10,  /* XY origin relative to container TopLeft */
        NULL,   /* font pointer or NULL for default */
        "by Arthur Johnson Jr.",        /* pointer to text */
        &IText10        /* next IntuiText structure */
};

struct IntuiText IText8 = {
        3,0,JAM2,       /* front and back text pens, drawmode and fill byte */
        56,2,   /* XY origin relative to container TopLeft */
        NULL,   /* font pointer or NULL for default */
        "ShowFont 2.0", /* pointer to text */
        &IText9 /* next IntuiText structure */
};

#define IntuiTextList3 IText8

SHORT BorderVectors7[] = {
        0,0,
        207,0,
        207,99,
        0,99,
        0,0
};
struct Border Border7 = {
        0, 0,  /* XY origin relative to container TopLeft */
        1,0,JAM1,       /* front pen, back pen and drawmode */
        5,      /* number of XY vectors */
        BorderVectors7, /* pointer to XY vectors */
        NULL    /* next border in list */
};

struct Requester requester2 = {
        NULL,   /* previous requester (filled in by Intuition) */
        216,50, /* requester XY origin relative to TopLeft of window */
        208,100,        /* requester width and height */
        0,0,    /* relative to these mouse offsets if POINTREL is set */
        &GadgetList3,   /* gadget list */
        &Border7,   /* box's border */
        &IntuiTextList3,        /* requester text */
        NULL,   /* requester flags */
        0,      /* back-plane fill pen */
        NULL,   /* leave these alone */
        NULL,   /* custom bitmap if PREDRAWN is set */
        NULL    /* leave this alone */
};

struct Window *window;
struct RastPort *rp;
struct Gadget *whichgad;

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct DiskfontBase *DiskfontBase;

char  fontname[FONTNAMELEN + 5]; /* include space for '.font' */
UWORD fontsize;

int numfonts; /* I'm tired of passing this around */

struct TextAttr myfont = { /* necessary structure for fonts */
    fontname,
    0,
    0,
    0 };
struct TextFont *font;

UBYTE textline[256];
struct IntuiText text = {
    1, 0,
    JAM2,
    0, 0,
    &myfont,
    textline,
    NULL };

struct fontinfo {
    struct fontinfo *next;
    char name[FONTNAMELEN];
    int  sizes;
    int  size[MAXSIZES];
    int  whichsel;
} *fonts;

struct Gadget thegads[14];
struct IntuiText theitext[14];
UBYTE  thetext1[7][FONTNAMELEN],
       thetext2[7][4];

void cleanup(text)
char *text;
{

    struct fontinfo *nextfont;

    if (fonts)
        while (fonts) {
            nextfont = fonts->next;
            FreeMem(fonts, sizeof(struct fontinfo));
            fonts = nextfont;
        }
    if (font)
        CloseFont(font);
    if (window) {
        ClearMenuStrip(window);
        CloseWindow(window);
    }
    if (DiskfontBase)
        CloseLibrary(DiskfontBase);
    if (IntuitionBase)
        CloseLibrary(IntuitionBase);
    if (GfxBase)
        CloseLibrary(GfxBase);

    if (text)
        puts(text);

    exit();

}

void *fontaddress(which)
int which;
{

    struct fontinfo *duh;

    duh = fonts;

    while (which-- != 0)
        duh = duh->next;

    return((void *)duh);

}

void *addfont(next, name, size)
struct fontinfo *next;
char *name;
int size;
{

    struct fontinfo *font;

    font = (struct fontinfo *)AllocMem(sizeof(struct fontinfo), MEMF_CLEAR);
    if (font == NULL)
        cleanup("ShowFont: couldn't allocate enough memory!");
    font->next = next;
    stccpy(font->name, name, (strlen(name) - 4));
    font->sizes = 1;
    font->size[0] = size;
    font->whichsel = 0;

    return((void *)font);

}

void readfonts()
{

    struct AvailFontsHeader *afh;
    struct AvailFonts *af;

    struct fontinfo *font, *prev;

    int mem = FONTBUFFER,
        moremem,
        goya,
        foundit;

    register i, j;

    numfonts = 0;
    fonts = NULL;

    do {
        afh = (struct AvailFontsHeader *)AllocMem(mem, MEMF_CLEAR);
        if (afh == NULL)
            cleanup("ShowFont: couldn't allocate enough memory!");
        moremem = AvailFonts(afh, mem, 0xFF);
        if (moremem != 0) {
            FreeMem(afh, mem);
            mem += moremem;
            printf("ShowFont: allocating %d bytes of memory for the FONTS: info.\n", mem);
        }
    } while (moremem != 0);

    if (afh->afh_NumEntries == 0) {
        FreeMem(afh, mem);
        cleanup("ShowFont: couldn't find any fonts! (Is FONTS: set correctly?)");
    }

    af = (struct AvailFonts *)&afh[1];
    for (i = 0; i < afh->afh_NumEntries; i++) {
        if (!((af->af_Attr.ta_Flags & FPF_REMOVED) ||
            (af->af_Attr.ta_Flags & FPF_REVPATH) ||
            ((af->af_Type & AFF_MEMORY) &&
             (af->af_Attr.ta_Flags & FPF_DISKFONT)))) {
            prev = NULL;
            font = fonts;
            foundit = FALSE;
            while ((font != NULL) && (foundit == FALSE)) {
                goya = strnicmp(af->af_Attr.ta_Name, font->name, (strlen(af->af_Attr.ta_Name) - 5));
                if (goya == 0) {
                    j = font->sizes - 1;
                    while ((j >= 0) && (font->size[j] > af->af_Attr.ta_YSize)) {
                        font->size[j + 1] = font->size[j];
                        --j;
                    }
                    font->size[j + 1] = af->af_Attr.ta_YSize;
                    ++font->sizes;
                    foundit = TRUE;
                }
                else if (goya < 0) {
                        if (prev == NULL)
                            fonts = (struct fontinfo *)addfont(font, af->af_Attr.ta_Name, af->af_Attr.ta_YSize);
                        else
                            prev->next = (struct fontinfo *)addfont(font, af->af_Attr.ta_Name, af->af_Attr.ta_YSize);
                        ++numfonts;
                        foundit = TRUE;
                    }
                    else {
                        prev = font;
                        font = font->next;
                    }
            }
            if (foundit == FALSE) {
                if (prev == NULL)
                    fonts = (struct fontinfo *)addfont(NULL, af->af_Attr.ta_Name, af->af_Attr.ta_YSize);
                else
                    prev->next = (struct fontinfo *)addfont(NULL, af->af_Attr.ta_Name, af->af_Attr.ta_YSize);
                ++numfonts;
            }
        }
        af++;
    }

    FreeMem(afh, mem);

    if (MenuItem2.Flags == ITEMTEXT+COMMSEQ+HIGHCOMP) {
        OnMenu(window, SHIFTMENU(1) | SHIFTITEM(1));
        MenuItem2.Flags |= ITEMENABLED;
    }

}

void setupfont()
{

    char windowtitle[80];

    if (font)
        CloseFont(font);

    myfont.ta_YSize = fontsize;
    if ((font = (struct TextFont *)OpenDiskFont(&myfont)) == NULL)
        cleanup("ShowFont: couldn't find the font.");
    fontsize = font->tf_YSize;

    stccpy(windowtitle, fontname, (strlen(fontname) - 4));
    sprintf(windowtitle + strlen(windowtitle), " - %d (ShowFont 2.0 by Arthur Johnson Jr.)", fontsize);
    SetWindowTitles(window, windowtitle, -1);

}

int findfont()
{

    struct fontinfo *search;

    int foundit,
        which,
        i;

    which = 0;
    search = fonts;
    foundit = FALSE;
    while ((search != NULL) && (!foundit)) {
        if (!(strnicmp(fontname, search->name, (strlen(fontname) - 5))))
            foundit = TRUE;
        else {
            search = search->next;
            which++;
        }
    }
    if (foundit == FALSE)
        return(0);     /* if for some reason I can't find the font, use */
                       /* the first font available. */
    i = 0;
    while ((i < search->sizes) && (search->size[i] != fontsize))
        i++;
    if (i != search->sizes)
        search->whichsel = i;
    else
        search->whichsel = 0;

    return(which);

}

void mygadssetup()
{

    register loop;

    Gadget12.NextGadget = &thegads[0];

    for (loop = 0; loop < 14; loop++) {
        if (loop != 13)
            thegads[loop].NextGadget = &thegads[loop + 1];
        else
            thegads[loop].NextGadget = NULL;
        if (loop < 7)
            thegads[loop].LeftEdge = 8;
        else
            thegads[loop].LeftEdge = 250;
        if (loop < 7)
            thegads[loop].TopEdge = (loop * 8) + 10;
        else
            thegads[loop].TopEdge = ((loop - 7) * 8) + 10;
        if (loop < 7)
            thegads[loop].Width = 184;
        else
            thegads[loop].Width = 24;
        thegads[loop].Height = 8;
        if (loop == 3)
            thegads[loop].Flags = GADGHCOMP | SELECTED;
        else
            thegads[loop].Flags = GADGHCOMP;
        thegads[loop].Activation = RELVERIFY;
        thegads[loop].GadgetType = BOOLGADGET | REQGADGET;
        thegads[loop].GadgetRender = NULL;
        thegads[loop].SelectRender = NULL;
        thegads[loop].GadgetText = &theitext[loop];
        thegads[loop].MutualExclude = NULL;
        thegads[loop].SpecialInfo = NULL;
        thegads[loop].GadgetID = 1000 + loop;
        thegads[loop].UserData = NULL;

        theitext[loop].FrontPen = 1;
        theitext[loop].BackPen = 0;
        theitext[loop].DrawMode = JAM2;
        theitext[loop].LeftEdge = 0;
        theitext[loop].TopEdge = 0;
        theitext[loop].ITextFont = NULL;
        if (loop < 7)
            theitext[loop].IText = (UBYTE *)&thetext1[loop];
        else
            theitext[loop].IText = (UBYTE *)&thetext2[loop - 7];
        theitext[loop].NextText = NULL;
    }

}

USHORT proppos(line, maxline)
int line;
int maxline;
{

    ULONG duh;

    if (maxline == 1)
        duh = MAXBODY;
    else
        duh = (MAXBODY * (line - 1)) / (maxline - 1);

    return ((USHORT)duh);

}

USHORT propsize(display, maxdisplay)
int display;
int maxdisplay;
{

    ULONG duh;

    if (display >= maxdisplay)
        duh = MAXPOT;
    else
        duh = (MAXPOT * display) / maxdisplay;

    return((USHORT)duh);

}

int propline(proppos, maxline)
USHORT proppos;
int maxline;
{

    int duh;

    duh = (proppos * maxline) / MAXPOT;

    return(duh);

}

void selectfont()
{

    struct IntuiMessage *message;

    struct fontinfo *thefont, *duh;

    int cont = TRUE,
        refresh = TRUE,
        nameline, sizeline,
        which,
        rfontlastline, rsizelastline;

    register loop;

    ULONG  class;

    USHORT fontpropsize, fontproppos, sizepropsize, sizeproppos;

    which = findfont();
    thefont = (struct fontinfo *)fontaddress(which);

    Request(&requester1, window);

    nameline = which;
    sizeline = 0;

    rfontlastline = numfonts;

    fontpropsize = propsize(7, numfonts);

    while (cont) {

        if (refresh) {

            rsizelastline = (thefont->sizes - 7) + 1;
            if (rsizelastline < 1)
                rsizelastline = 1;

            sizepropsize = propsize(7, thefont->sizes);
            fontproppos = proppos((nameline + 1), rfontlastline);
            sizeproppos = proppos((sizeline + 1), rsizelastline);

            NewModifyProp(&R_Font, window, &requester1, AUTOKNOB | FREEVERT, -1, fontproppos, -1, fontpropsize, 0);
            NewModifyProp(&R_Size, window, &requester1, AUTOKNOB | FREEVERT, -1, sizeproppos, -1, sizepropsize, 0);

            for (loop = -3; loop < 4; loop++)
                if (((loop + nameline) < 0) || ((loop + nameline) >= numfonts))
                    strcpy(thetext1[loop + 3], "                       ");
                else {
                    duh = (struct fontinfo *)fontaddress(nameline + loop);
                    sprintf(thetext1[loop + 3], "%-23s", duh->name);
                }
            for (loop = 0; loop < 7; loop++)
                if ((loop + sizeline) < thefont->sizes) {
                    sprintf(thetext2[loop], "%3d", thefont->size[loop + sizeline]);
                    if ((loop + sizeline) == thefont->whichsel)
                        thegads[loop + 7].Flags = GADGHCOMP | SELECTED;
                    else
                        thegads[loop + 7].Flags = GADGHCOMP;
                }
                else {
                    strcpy(thetext2[loop], "   ");
                    thegads[loop + 7].Flags = GADGHCOMP;
                }
            RefreshGadgets(&thegads[0], window, &requester1);
            refresh = FALSE;
        }

        Wait(1 << window->UserPort->mp_SigBit);

        while (message = (struct IntuiMessage *)GetMsg(window->UserPort)) {
            class = message->Class;
            whichgad = (struct Gadget *)message->IAddress;
            ReplyMsg(message);

            if (class == GADGETUP) {
                if (whichgad->GadgetID == 11) /* FontUp */
                    if (nameline > 0) {
                        refresh = TRUE;
                        --nameline;
                        thefont = (struct fontinfo *)fontaddress(nameline);
                    }
                if (whichgad->GadgetID == 12) { /* Font */
                    refresh = TRUE;
                    fontproppos = R_FontSInfo.VertPot;
                    nameline = propline(fontproppos, rfontlastline);
                    if ((nameline + 1) >= rfontlastline)
                        nameline = rfontlastline - 1;
                    thefont = (struct fontinfo *)fontaddress(nameline);
                }
                if (whichgad->GadgetID == 13) /* FontDown */
                    if ((nameline + 1) < rfontlastline) {
                        refresh = TRUE;
                        ++nameline;
                        thefont = (struct fontinfo *)fontaddress(nameline);
                    }
                if (whichgad->GadgetID == 21) /* SizeUp */
                    if (sizeline > 0) {
                        refresh = TRUE;
                        --sizeline;
                    }
                if (whichgad->GadgetID == 22) { /* Size */
                    refresh = TRUE;
                    sizeproppos = R_SizeSInfo.VertPot;
                    sizeline = propline(sizeproppos, rsizelastline);
                    if ((sizeline + 1) >= rsizelastline)
                        sizeline = rsizelastline - 1;
                }
                if (whichgad->GadgetID == 23) /* SizeDown */
                    if ((sizeline + 1) < rsizelastline) {
                        refresh = TRUE;
                        ++sizeline;
                    }
                if (whichgad->GadgetID == 101) { /* OK */
                    cont = FALSE;
                    strcpy(fontname, thefont->name);
                    strcat(fontname, ".font");
                    fontsize = thefont->size[thefont->whichsel];
                }
                if (whichgad->GadgetID == 102) /* Cancel */
                    cont = FALSE;
                if ((whichgad->GadgetID > 999) &&
                    (whichgad->GadgetID < 1007)) {
                    refresh = TRUE;
                    nameline += (whichgad->GadgetID - 1003);
                    if (nameline < 0)
                        nameline = 0;
                    if ((nameline + 1) > rfontlastline)
                        nameline = rfontlastline - 1;
                    thefont = (struct fontinfo *)fontaddress(nameline);
                }
                if ((whichgad->GadgetID > 1006) &&
                    (whichgad->GadgetID < 1014)) {
                    refresh = TRUE;
                    thefont->whichsel = (whichgad->GadgetID - 1007) + sizeline;
                    if (thefont->whichsel >= thefont->sizes)
                        thefont->whichsel = thefont->sizes - 1;
                }
            }
        }
    }

}

void mycat(s, c)
char *s;
char c;
{

    while (*s++ != '\0') {}
    *(s - 1) = c;
    *s = '\0';

}

void main(argc,argv)
int argc;
char *argv[];
{

    struct IntuiMessage *message;

    int cont = TRUE,
        brandnewfont = TRUE,
        refresh = TRUE;

    ULONG   class;
    USHORT  code;

    char c;
    int line, maxline,
        yoffset,
        yarea,
        startchar,
        len,
        whichmenu, whichitem,
        wproplastline;

    USHORT range[256][2], numy, pos, size;

    register loop, i;

    if ((argc == 2) && (*argv[1] == '?'))
        cleanup("Usage: ShowFont [font_name] [font_size]");

    if ((IntuitionBase = (struct IntuitionBase *)
            OpenLibrary("intuition.library", 0)) == NULL)
        cleanup("ShowFont: couldn't open 'intuition.library'.");

    if ((GfxBase = (struct GfxBase *)
            OpenLibrary("graphics.library", 0)) == NULL)
        cleanup("ShowFont: couldn't open 'graphics.library'.");

    if ((DiskfontBase = (struct DiskfontBase *)
            OpenLibrary("diskfont.library", 0)) == NULL)
        cleanup("ShowFont: couldn't open 'diskfont.library'.");

    if ((window = (struct Window *)OpenWindow(&newwindow)) == NULL)
        cleanup("ShowFont: couldn't open the window.");
    rp = window->RPort;

    SetMenuStrip(window, &MenuList1);

    mygadssetup();

    if (argc == 1)
        strcpy(fontname, "Topaz.font");
    else
        sprintf(fontname, "%s.font", argv[1]);
    if (argc < 3) {
        readfonts();
        fontsize = 0;
        selectfont();
        setupfont();
    }
    else {
        fontsize = atoi(argv[2]);
        setupfont();
    }

    while (cont) {

        if (brandnewfont) {

            startchar = font->tf_LoChar;
            if (startchar == 0)
                startchar = 1;
            line = 0;
            textline[0] = '\0';

            for (loop = font->tf_LoChar; loop <= font->tf_HiChar; ++loop) {
                c = loop;
                mycat(textline, c);
                len = window->BorderLeft + IntuiTextLength(&text) + font->tf_XSize;
                if (len > XAREA) {
                    range[line][0] = startchar;
                    range[line][1] = loop - 1;
                    startchar = loop;
                    line++;
                    textline[0] = '\0';
                }
                else
                    if (loop == font->tf_HiChar) {
                        range[line][0] = startchar;
                        range[line][1] = font->tf_HiChar;
                    }
            }

            maxline = line;
            line = 0;
            yarea = 200 - (window->BorderTop + window->BorderBottom);
            numy = yarea / font->tf_YSize;

            wproplastline = (maxline - numy) + 1;
            if (wproplastline < 1)
                wproplastline = 1;

            size = propsize(numy, maxline);
            pos = 0;

            brandnewfont = FALSE;
            refresh = TRUE;
        }

        if (refresh) { /* display the characters, update gadgets */

            pos = proppos((line + 1), wproplastline);

            ModifyProp(&W_Prop, window, NULL, AUTOKNOB | FREEVERT, -1, pos, -1, size);

            SetAPen(rp, 0); /* clear the screen */
            RectFill(rp, window->BorderLeft, window->BorderTop, XAREA, 200 - window->BorderBottom);
            SetAPen(rp, 1);

            yoffset = window->BorderTop;

            for (loop = line; (((loop - line) < numy) && (loop <= maxline)); ++loop) {
                textline[0] = '\0';
                for (i = range[loop][0]; i <= range[loop][1]; i++) {
                    c = i;
                    mycat(textline, c);
                }
                PrintIText(rp, &text, window->BorderLeft, yoffset);
                yoffset += font->tf_YSize;
            }
            refresh = FALSE;
        }

        Wait(1 << window->UserPort->mp_SigBit);

        while (message = (struct IntuiMessage *)GetMsg(window->UserPort)) {
            class = message->Class;
            code  = message->Code;
            whichgad = (struct Gadget *)message->IAddress;
            ReplyMsg(message);

            if (class == CLOSEWINDOW)
                cont = FALSE;
            if (class == GADGETUP) {
                if (whichgad->GadgetID == 1) /* - */
                    if (line > 0) {
                        refresh = TRUE;
                        --line;
                    }
                if (whichgad->GadgetID == 2) { /* slider */
                    refresh = TRUE;
                    pos = W_PropSInfo.VertPot;
                    line = propline(pos, wproplastline);
                    if ((line + 1) > wproplastline)
                        line = wproplastline - 1;
                }
                if (whichgad->GadgetID == 3) /* + */
                    if ((line + 1) < wproplastline) {
                        refresh = TRUE;
                        ++line;
                    }
            }
            if (class == MENUPICK) {
                if (code != MENUNULL) {
                    whichmenu = MENUNUM(code);
                    whichitem = ITEMNUM(code);
                    switch (whichmenu) {
                        case 0 : switch (whichitem) {
                                    case 0: Request(&requester2, window); /* about */
                                            break;
                                    case 1: cont = FALSE; /* quit */
                                            break;
                                 }
                                 break;
                        case 1 : refresh = TRUE;
                                 switch (whichitem) {
                                    case 0: readfonts(); /* read FONTS: */
                                            selectfont();
                                            setupfont();
                                            brandnewfont = TRUE;
                                            break;
                                    case 1: selectfont();
                                            setupfont();
                                            brandnewfont = TRUE;
                                            break; /* font selection */
                                 }
                                 break;
                    }
                }
            }
        }
    }

    cleanup(NULL);

}
