/* 
    Demoprogram showing random objects drawn by the 
    graphics.library or/and my own gfx.library.
    Well, removed gfx.library support again. Is not used
    any more.
    This demo is not really complete. The task control
    is just a bit of exercise for me. It does not support
    semaphores or such (see task termination)...
    but feel free to modify it...
    Also this piece of code is really old, so please
    don't flame me for that not nicely written code...

    name : demo.c
    path : daten:c_src/a2410
    author : jürgen schober
    date : 4.2.94 taken from the dev_con demo files (C= a2410 support code)
    last change : 22.10.94
    changed : 18.11.95 for a release with my EGSA2410Driver Version 2

    Bugs : do not exactly know. But did never try AreaEllipse() in 
           amiga mode. I guess a temp_rast should be allocated.
*/

#include <stdio.h>
#include <stdlib.h>
#include <a2410/typedefs.h>
#include <a2410/devtiga.h>
#include <a2410/ti_function_nums.h> 
#include <exec/types.h>
#include <dos/dos.h>
#include <exec/memory.h>
#include <graphics/gfx.h>
#include <intuition/intuition.h>
#include <math.h>
#include <graphics/gfxmacros.h>

#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/alib_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/intuition_pragmas.h>

#define GSP_GFX   1
#define AMIGA_GFX 2

#define PATTERN_B 1 
#define FILL_B    2
#define PATTERN_F (1<<PATTERN_B)
#define FILL_F    (1<<FILL_B)
#define NOFILL    0
#define NOPATTERN 0

#define LIN (1<<0)
#define BOX (1<<1)
#define STR (1<<2)
#define ELL (1<<3)
#define REC (1<<4)

struct Library *IntuitionBase,*GfxBase=NULL;
struct Library *GraphicsBase,*DiskfontBase;
struct Window *win;
struct Task *BoxTask = NULL, *RectTask = NULL, *TextTask = NULL, *EllipseTask = NULL, *LineTask = NULL;
struct RastPort *RP;
USHORT class;	/* Intu event class */
USHORT code;	/* Intu event code */
struct IntuiMessage *message;
CONFIG	config;
LONG gfx_mode=AMIGA_GFX,demo_mode=0L,fill_mode=NOFILL;
BOOL  out = FALSE, line_busy = FALSE, box_busy = FALSE, txt_busy = FALSE, ell_busy = FALSE, rect_busy = FALSE;


/* =================================================================================== */

int event(void);
void t_Task(void);
void LinesDemo(void);
void BoxDemo(void);
void RectDemo(void);
void TextDemo(void);
void CleanUp(void);
void TestText(void);
void EllipseDemo(void);

void main(int argc,char *argv[])
{
    int i=0;
    ULONG sig,bits;
    POINT pt[]={{100,100},{1000,500},{300,700},{1000,1000},{100,800},{50,500}};
    WORD *area;
    UBYTE strg[]="Hallo, Tiga scrolling Demo,....";

    onbreak(CleanUp);

    if (strncmp(argv[1],"?",1)==0) {
        puts("gfxdemo, (c)94 - js -");
        puts("usage : demo [pat[tern]] [box] [rec[tangle]] [lin[e]] [tex[t]] [ell[ipse]]");
        exit(0);
    }
    
    for (i=1;i<=argc;i++)  {
        if (strncmp(argv[i],"box",3)==0) demo_mode |= BOX;
        if (strncmp(argv[i],"rec",3)==0) demo_mode |= REC;
        if (strncmp(argv[i],"tex",3)==0) demo_mode |= STR;
        if (strncmp(argv[i],"lin",3)==0) demo_mode |= LIN;
        if (strncmp(argv[i],"ell",3)==0) { demo_mode |= ELL; fill_mode = NOFILL; }
        if (strncmp(argv[i],"are",3)==0) { demo_mode |= ELL; fill_mode |= FILL_F; }
        if (strncmp(argv[i],"pat",3)==0) fill_mode |= PATTERN_F;
    }
    if (demo_mode == NULL) demo_mode = LIN;

    if ((DiskfontBase=(struct Library *)OpenLibrary("diskfont.library",0L))==NULL)
    {
        puts("could not open diskfont.library ...");
        return;
    }
    if ((GfxBase=(struct Library *)OpenLibrary("graphics.library",0L))==NULL)
    {
        puts("could not open graphics.library ...");
        return;
    }
    if ((IntuitionBase=(struct Library *)OpenLibrary("intuition.library",0L))==NULL)
    {
         puts("could not open intuition.library ...");
         return;
    }
    win=(struct Window *)OpenWindowTags(NULL,
                        WA_Title,"My GfxDemo",
                        WA_AutoAdjust,TRUE,
                        WA_Left,50,
                        WA_Top,50,
                        WA_Width,640,
                        WA_Height,480,
                        WA_MaxWidth,2000,
                        WA_MaxHeight,2000,
                        WA_MinWidth,10,
                        WA_MinHeight,10,
                        WA_DepthGadget,TRUE,
                        WA_CloseGadget,TRUE,
                        WA_SizeGadget,TRUE,
                        WA_DragBar,TRUE,
                        WA_IDCMP,IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE,
                        WA_GimmeZeroZero,TRUE,
                        TAG_DONE);

    RP=win->RPort;

	chkabort();
    if (demo_mode & BOX)
    {
        BoxTask = CreateTask("DemoBoxTask",0,BoxDemo,20000);
    }
    if (demo_mode & REC)
    {
        RectTask = CreateTask("DemoRectTask",0,RectDemo,20000);
    }
    if (demo_mode & STR)
    {
        TextTask = CreateTask("DemoTextTask",0,TextDemo,20000);
    }
    if (demo_mode & ELL)
    {
        EllipseTask = CreateTask("DemoEllipseTask",0,EllipseDemo,20000);
    }
    if (demo_mode & LIN)
    {
        LineTask = CreateTask("DemoLinesTask",0,LinesDemo,20000);
    }
    sig = (1L<<win->UserPort->mp_SigBit);
    while (!out)
    {
        bits = Wait(sig | SIGBREAKF_CTRL_C);
        chkabort();
		if (bits & sig)
       	{
			if (message = (struct IntuiMessage *)GetMsg(win->UserPort))
   	    	{
    			class = message->Class;
	        	code  = message->Code;
    	    	ReplyMsg((struct Message *)message);
                switch(class)
		    	{
   			    	case CLOSEWINDOW:
                        out = TRUE;
                        break;
		    	    case NEWSIZE:
                        Forbid();
                        config.mode.disp_hres=(win->Width);
                        config.mode.disp_vres=(win->Height);
                        config.mode.palet_size=(2<<(win->RPort->BitMap->Depth));
                        Permit();
                        break;
                   default :
                        break;
               }
       		}
        }
    }
    CleanUp();
}

void __saveds CleanUp(void)
{
    out = TRUE;             // make sure tasks are Waiting on a CTRL-C
    while ((line_busy) || (box_busy) || (txt_busy) || (ell_busy) || (rect_busy)) ;

    Forbid();

    if (BoxTask)     DeleteTask(BoxTask);
    if (RectTask)    DeleteTask(RectTask);
    if (TextTask)    DeleteTask(TextTask);
    if (EllipseTask) DeleteTask(EllipseTask);
    if (LineTask)    DeleteTask(LineTask);

    Permit();

    SetDrPt(RP,0xFFFF);
    RP->Flags|=(AREAOUTLINE);  // Outline löschen

    if (win)           CloseWindow(win);
    if (GfxBase)       CloseLibrary(GfxBase);
    if (GraphicsBase)  CloseLibrary(GraphicsBase);
    if (IntuitionBase) CloseLibrary(IntuitionBase);
    if (DiskfontBase)  CloseLibrary(DiskfontBase);

    exit(0);
}

void __saveds LinesDemo()
{
	int x1,y1,x2,y2;
	int x1v,y1v,x2v,y2v;
	int i,c;
    struct RastPort *my_rport;
	
    my_rport=win->RPort;
    config.mode.disp_hres=(win->Width);
    config.mode.disp_vres=(win->Height);
    config.mode.palet_size=(2<<(win->RPort->BitMap->Depth));

	c = 0;
	x1v = y1v = x2v = y2v = 0;
	x1 = x2 = config.mode.disp_hres/2;
	y1 = y2 = config.mode.disp_vres/2;

    if (fill_mode & PATTERN_F) 
        SetDrPt(my_rport,0xf0f0);

    line_busy = TRUE;
	do
	{

		c = ((c)%(config.mode.palet_size-1))+1;
	
        SetAPen(my_rport,c);

		x1v = x1v/2 + (rand() & 15) - 7;
		y1v = y1v/2 + (rand() & 15) - 7;
		x2v = x2v/2 + (rand() & 15) - 7;
		y2v = y2v/2 + (rand() & 15) - 7;

		i = 100;

		while(i--)
		{
			x1 += x1v;
			y1 += y1v;
			x2 += x2v;
			y2 += y2v;

			if (x1 < 0)
				{
				x1 = - x1;
				x1v = - x1v;
				y1v += (rand() % 5) - 2;
				}

			if (y1 < 0)
				{
				y1 = - y1;
				y1v = - y1v;
				x1v += (rand() % 5) - 2;
				}

			if (x1 >= config.mode.disp_hres)
				{
				x1 = 2*config.mode.disp_hres - x1 - 2;
				x1v = - x1v;
				y1v += (rand() % 5) - 2;
				}

			if (y1 >= config.mode.disp_vres)
				{
				y1 = 2*config.mode.disp_vres - y1 - 2;
				y1v = -y1v;
				x1v += (rand() % 5) - 2;
				}

			if (x2 < 0)
				{
				x2 = - x2;
				x2v = - x2v;
				y2v += (rand() % 5) - 2;
				}

			if (y2 < 0)
				{
				y2 = - y2;
				y2v = - y2v;
				x2v += (rand() % 5) - 2;
				}

			if (x2 >= config.mode.disp_hres)
				{
				x2 = 2*config.mode.disp_hres - x2 - 2;
				x2v = - x2v;
				y2v += (rand() % 5) - 2;
				}

			if (y2 >= config.mode.disp_vres)
				{
				y2 = 2*config.mode.disp_vres - y2 - 2;
				y2v = - y2v;
				x2v += (rand() % 5) - 2;
				}

            Move(my_rport,x1,y1);
            Draw(my_rport,x2,y2);
		}
	}while(!out);
    line_busy = FALSE;
    Wait(0L);
}
/* --------------------------------------------------------------------------------- */

/* ------------------------------------------------------------------------------- */

void __saveds RectDemo(void)
{
	int x,y,w,h,col;
    struct RastPort *rp;

    rp=win->RPort;
    config.mode.disp_hres=(win->Width);
    config.mode.disp_vres=(win->Height);
    config.mode.palet_size=(2<<(win->RPort->BitMap->Depth));
    if (fill_mode&PATTERN_F) 
        SetDrPt(rp,0xf0f0);

    rect_busy = TRUE;
    do
	{
		w = rand() % (config.mode.disp_hres-1)+1;
		h = rand() % (config.mode.disp_vres-1)+1;
		x = rand() % (config.mode.disp_hres-w);
		y = rand() % (config.mode.disp_vres-h);
		col = rand() % config.mode.palet_size;

        SetAPen(rp,col);
        Move(rp,x,y);
        Draw(rp,x+w,y);
        Draw(rp,x+w,y+h);
        Draw(rp,x,y+h);
        Draw(rp,x,y);

	}while(!out);
    rect_busy = FALSE; // OK, left core function, can be terminated
    Wait(0L); // set task idle to terminate
}

/* ------------------------------------------------------------------------------- */

void __saveds BoxDemo(void)
{
	int x,y,w,h,col;
    struct RastPort *rp;
    USHORT areaptrn[] = { 0xf0f0, /*0*/ 0x0f0f, /*1*/ 0xf0f0, 0xf0f0, /*2*/ 0x0f0f, 0x0f0f, 0xf0f0, 0xf0f0,/*3*/
                          0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF /*4*/ };

    rp=win->RPort;
    config.mode.disp_hres=(win->Width);
    config.mode.disp_vres=(win->Height);
    config.mode.palet_size=(2<<(win->RPort->BitMap->Depth));

    SetDrPt(rp,0xF0F0);

    if (fill_mode&PATTERN_F) 
        {SetAfPt(rp,areaptrn,1);}
    else 
        SetAfPt(rp,NULL,1);

    rp->Flags&=(~AREAOUTLINE);  // Outline löschen
    box_busy = TRUE;
    do
	{
		w = rand() % (config.mode.disp_hres-1)+1;
		h = rand() % (config.mode.disp_vres-1)+1;
		x = rand() % (config.mode.disp_hres-w);
		y = rand() % (config.mode.disp_vres-h);
		col = rand() % config.mode.palet_size;

        SetAPen(rp,col);
        RectFill(rp,x,y,x+w,y+h);

	}while(!out);
    box_busy = FALSE;
    Wait(0L);
}
/* ------------------------------------------------------------------------------- */

void __saveds TextDemo(void)
{
	int x,y,col;
    struct RastPort *rp;

    rp=win->RPort;
    config.mode.disp_hres=(win->Width);
    config.mode.disp_vres=(win->Height);
    config.mode.palet_size=(2<<(win->RPort->BitMap->Depth));

    txt_busy = TRUE;
    do
    {
		x = rand() % (config.mode.disp_hres);
		y = rand() % (config.mode.disp_vres);
		col = rand() % config.mode.palet_size;

        SetAPen(rp,col);

        Move(rp,x,y);
        Text(rp,"Text Demo",9);

	}while(!out);
    txt_busy = FALSE;
    Wait(0L);
}

/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */

void __saveds EllipseDemo(void)
{
	int x,y,w,h,col;
    struct RastPort *rp;
    USHORT areaptrn[] = { 0xf0f0, /*0*/ 0x0f0f, /*1*/ 0xf0f0, 0xf0f0, /*2*/ 0x0f0f, 0x0f0f, 0xf0f0, 0xf0f0,/*3*/
                          0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF /*4*/ };

    rp=win->RPort;
    config.mode.disp_hres=(win->Width);
    config.mode.disp_vres=(win->Height);
    config.mode.palet_size=(2<<(win->RPort->BitMap->Depth));

    SetDrPt(rp,0xF0F0);

    if (fill_mode&PATTERN_F) 
        {SetAfPt(rp,areaptrn,1);}
    else 
        SetAfPt(rp,NULL,1);

    rp->Flags&=(~AREAOUTLINE);  // Outline löschen
    ell_busy = FALSE;
    do
	{
		w = rand() % (config.mode.disp_hres/2);
		h = rand() % (config.mode.disp_vres/2);
		x = rand() % (config.mode.disp_hres);
		y = rand() % (config.mode.disp_vres);
		col = rand() % config.mode.palet_size;

        SetAPen(rp,col);
        DrawEllipse(rp,x,y,w,h);

	}while(!out);
    ell_busy = FALSE;
    Wait(0L);
}

/* ------------------------------------------------------------------------------- */
