/* V1.1 24 Nov 91

 *  Added key-hit to quit
 *  Changed colors and line-types
 */
/* Amiga GnuPlot interface v1.0 29 Sep 90 */
/* Michael D. Black, 1380 Croftwood Dr. Melbourne, FL 32935 */

#include <stdio.h>
#include <functions.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/display.h>

static struct IntuitionBase *IntuitionBase=0;
static struct GfxBase *GfxBase=0;
struct Library *DiskfontBase;
static struct TextAttr AMIGA_Font = {
  "topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT
};

#define INTUITION_REV 0
#define GRAPHICS_REV 0

#define AMIGA_XMAX 640
#define AMIGA_YMAX 400
#define AMIGA_VCHAR 8
#define AMIGA_HCHAR 8
#define AMIGA_VTIC 4
#define AMIGA_HTIC 5
/* The origin is in the upper left hand corner, so we have to translate */
/* and flip the coordinates: */
#define AMIGA_VTF(y) (AMIGA_ymax-1-(y))

static struct NewScreen NewScreen = {
    0L,0L,AMIGA_XMAX,AMIGA_YMAX,3L,
    0L,0L,
    HIRES|INTERLACE,CUSTOMSCREEN,
    &AMIGA_Font,
    (UBYTE*)"GNUPlot",
    NULL,NULL};

static struct Screen *Screen;
static struct Window *Window;
static struct NewWindow NewWindow = {
    0L, 0L, 640L, 400L, -1L, -1L, MOUSEBUTTONS | VANILLAKEY,
/*    SMART_REFRESH | ACTIVATE | GIMMEZEROZERO*/
    SMART_REFRESH | ACTIVATE
    | NOCAREREFRESH | BORDERLESS | RMBTRAP,
    NULL, NULL, (UBYTE*)"GNUPlot", NULL, NULL,
    0L, 0L, 0L, 0L, CUSTOMSCREEN
};

static struct RastPort *rp;
static long AMIGA_xmax=AMIGA_XMAX,AMIGA_ymax=AMIGA_YMAX;
static struct TextFont *AMIGA_TextFont;
static enum JUSTIFY AMIGA_justify = LEFT;
static WORD AMIGA_cwd,AMIGA_cht,AMIGA_bsl,AMIGA_vadj;

AMIGA_init()
{
    char *s;

    if (s=getenv("GNUXMAX")) {
        AMIGA_xmax = atol(s);
        NewScreen.Width = AMIGA_xmax;
        NewWindow.Width = AMIGA_xmax;
        term_tbl[term].xmax = AMIGA_xmax;
    }
    if (s=getenv("GNUYMAX")) {
        AMIGA_ymax = atol(s);
        NewScreen.Height = AMIGA_ymax;
        NewWindow.Height = AMIGA_ymax;
        term_tbl[term].ymax = AMIGA_ymax;
    }

    return 0;
}

AMIGA_reset()
{
    return 0;
}

/* scale() not provided */

AMIGA_graphics()
{
    char *colors,fontname[80],*gnufont,*search;
    static int fsize;
    static char *test_str =
    " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
    static WORD test_len,test_pxl;

    IntuitionBase = (struct IntuitionBase *)
        OpenLibrary("intuition.library",INTUITION_REV);
    if(IntuitionBase == NULL) {
        puts("Can't open intution.library");
        goto cleanup1;
    }

    GfxBase =(struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV);
    if (GfxBase == NULL) {
        puts("Can't open graphics.library");
        goto cleanup2;
    }

    DiskfontBase = OpenLibrary("diskfont.library",0);
    if (DiskfontBase == NULL) {
        puts("Can't open diskfont.library");
        goto cleanup2a;
    }
    if((Screen = (struct Screen *) OpenScreen(&NewScreen)) == NULL) {
        puts("Screen error");
        goto cleanup3;
    }
    NewWindow.Screen = Screen;
    if (( Window = (struct Window *) OpenWindow(&NewWindow)) == NULL) {
        puts("Window error");
        goto cleanup4;
    }
    rp = Window->RPort;

    if (colors=getenv("GNUCOLORS")) {
        long color=0,r,g,b;
        char *s;
        while (s=strtok(colors,", ")) {
            colors=0;
            if (sscanf (s,"%1x%1x%1x",&r,&g,&b)==3)
                SetRGB4(&Screen->ViewPort,color++,r,g,b);
            else {
                printf("Error in GNUCOLORS at '%s'\n",s);
            }
        }
    }
    else {
        long r[8] = { 0x08,0x00,0x00,0x0b,0x00,0x0f,0x0f,0x0f };
        long g[8] = { 0x08,0x00,0x00,0x00,0x0b,0x09,0x0f,0x00 };
        long b[8] = { 0x08,0x00,0x0b,0x00,0x00,0x00,0x0f,0x0f };
        long i;
        for(i=0;i<8;i++)
            SetRGB4(&Screen->ViewPort,i,r[i],g[i],b[i]);
    }

    gnufont = getenv("GNUFONT");
    if (gnufont != NULL ) {
        search = strchr(gnufont,'/');
        if (search != NULL) {
            *search++ = '\0';
            strncpy(fontname,gnufont,74);
            strcat(fontname,".font");
            sscanf(search,"%d",&fsize);
            if ((strcmp("topaz.font",fontname) == 0) &&
                ((fsize == TOPAZ_EIGHTY) || (fsize == TOPAZ_SIXTY))) {
                AMIGA_Font.ta_Name = fontname;
                AMIGA_Font.ta_YSize = fsize;
                AMIGA_Font.ta_Style = FS_NORMAL;
                AMIGA_Font.ta_Flags = FPF_ROMFONT;
                AMIGA_TextFont = OpenFont(&AMIGA_Font);
                if (AMIGA_TextFont != NULL)
                    SetFont(rp,AMIGA_TextFont);
            }
            else {
                if (DiskfontBase != NULL) {
                    AMIGA_Font.ta_Name = fontname;
                    AMIGA_Font.ta_YSize = fsize;
                    AMIGA_Font.ta_Style = FS_NORMAL;
                    AMIGA_Font.ta_Flags = FPF_ROMFONT|FPF_DISKFONT;
                    AMIGA_TextFont = OpenDiskFont(&AMIGA_Font);
                    if (AMIGA_TextFont != NULL)
                        SetFont(rp,AMIGA_TextFont);
                }
            }
        }
    }
    /* Width of characters: This works better for proportional fonts than */
    /* AMIGA_Screen->RastPort.TxWidth + AMIGA_Screen->RastPort.TxSpacing */
    test_len = strlen(test_str);
    test_pxl = TextLength(rp,test_str,test_len);
    AMIGA_cwd = test_pxl / test_len;
    AMIGA_cht = rp->TxHeight; /* Height of characters */
    AMIGA_bsl = rp->TxBaseline; /* Reference line */
    /* Amount by which characters have to be shifted upwards to be */
    /* vertically justified: */
    AMIGA_vadj = AMIGA_bsl / 2;
    term_tbl[term].v_char = AMIGA_cht + 4; /* So lines won't be too close */
    term_tbl[term].h_char = AMIGA_cwd;

    goto ok;

    CloseWindow(Window);
    cleanup4:
        CloseScreen(Screen);
    cleanup3:
        CloseLibrary(DiskfontBase);
    cleanup2a:
        CloseLibrary(GfxBase);
    cleanup2:
        CloseLibrary(IntuitionBase);
    cleanup1:;
        exit(5);
    ok:;
    return 0;
}

AMIGA_text()
{
    Wait(1L<<Window->UserPort->mp_SigBit);
    CloseWindow(Window);
    CloseScreen(Screen);
    CloseLibrary(DiskfontBase);
    CloseLibrary(GfxBase);
    CloseLibrary(IntuitionBase);
    return 0;
}

AMIGA_move(x,y)
int x,y;
{
    if ((x<AMIGA_xmax) && (y<AMIGA_ymax))
        Move(rp,(long)x,AMIGA_ymax-1-(long)y);
    return 0;
}

AMIGA_vector(x,y)
int x,y;
{
    if ((x<AMIGA_xmax) && (y<AMIGA_ymax))
        Draw(rp,(long)x,AMIGA_ymax-1-(long)y);
    return 0;
}

AMIGA_linetype(linetype)
int linetype;
{
    static long pattern[] = {0xffff, 0x8888, /* these 2 are the border & axis */
                             0xffff, 0xffff, 0xffff, 0xffff,
                             0xffff, 0xffff, 0xffff, 0xf0f0,
                             0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
                             0x8888, 0x8888, 0x8888, 0x8888,
                             0x8888, 0x8888, 0x8888 };
    static long colors[] = {  1, 1,
                              1, 2, 3, 4,
                              5, 6, 7, 1,
                              2, 3, 4, 5,
                              1, 2, 3, 4,
                              5, 6, 7 };

    linetype = linetype % 19;
    SetDrPt(rp,pattern[linetype+2]);
    SetAPen(rp,colors[linetype+2]);
    return 0;
}

AMIGA_put_text(x,y,str)
int x,y;
char *str;
{
    long len,tx_len;
    int xmin,xmax,ymin,ymax;

    len = strlen(str);
    tx_len = TextLength(rp,str,len);
    SetDrMd(rp,JAM1);
    switch (AMIGA_justify) {
        case LEFT:
            xmin = x;
            xmax = x + tx_len;
            break;
        case CENTRE:
            xmin = x - tx_len / 2;
            xmax = x + tx_len - tx_len / 2; /* aviod roundoff errors ! */
            break;
        case RIGHT:
            xmin = x - tx_len;
            xmax = x;
            break;
    }
    ymin = AMIGA_VTF(y) - AMIGA_vadj;
    ymax = ymin + AMIGA_cht;
    /* Check if character-string lies completely within the screen: */
    if ((xmax < AMIGA_xmax) && (ymin >=0) && (ymax < AMIGA_ymax)) {
        Move(rp,xmin,ymin+AMIGA_bsl);
        Text(rp,str,(long)strlen(str));
    }
    return 0;
}

AMIGA_text_angle(mode)
enum JUSTIFY mode;
{
    AMIGA_justify = mode;
    return TRUE; /* we can't rotate text */
}

AMIGA_justify_text(ang)
int ang;
{
    return 0; /* we can't justify text either */
}
