
/******************************************************************\
 This file contains the library functions for ACS Harlequin. 
 In this example alpha channel properties of Harlequin are used, but
 no multiple screens are supported. Therefore, the handle argument
 and the internal 'hscreen' pointer have the same value, and hence
 most functions ignore the 'hnd' argument and use 'hscreen' instead.
 I hope this is not confusing.
   
 Custom saving is not implemented.

 It is quite easy to modify the functions to fit the properties of 
 another similar device. To recompile the modified file, use the command

    'lc -y -v -O hrcode' (SAS C)
    
\*******************************************************************/


#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/harlequin.h>
#include "dspdrvbase.h"
#include <proto/all.h>
#include <proto/harlequin.h>

struct ExecBase *SysBase;
struct R3DDspDrvBase *R3DDspDrvBase;
struct IntuitionBase *IntuitionBase;


/* Harlequin related data items: */

struct Library *HarlequinBase;

struct HNewScreen myscreen = 
    {0,0,740,576,HINTERLACE|HPAL|HBORDERLESS|HNEAREST,-1,0,0};
struct HImageBlock hbl = {0,1,IB_RED|IB_GREEN|IB_BLUE|IB_ALPHA,};

struct HScreen *hscreen;


/* Library functions: */

R3DInitDspDrv()
{   if(hscreen) return(NULL); /* Exclusive access through this library !!*/
    SysBase = R3DDspDrvBase->SysLib;
    if(!(HarlequinBase = OpenLibrary("harlequin.library",0L))) return(FALSE);
    
    if(hscreen = HOpenScreen(&myscreen))
        HScreenFunction(hscreen,SCREEN_ON|SCREEN_FRONT);
    else goto error;

    return(hscreen);
error:
    CloseLibrary(HarlequinBase); HarlequinBase = NULL;
    return(FALSE);
}

void
R3DFreeDspDrv(int hnd) 
{   if(hscreen) HCloseScreen(hscreen); 
    hscreen = NULL;
    if(HarlequinBase) CloseLibrary(HarlequinBase);
    HarlequinBase = NULL;
}

void
R3DWriteLine(hnd,buf,pixnum,x,y) /* writes rgba of pixnum pixels */
int hnd;
int *buf;
int pixnum,x,y;
{   if(!hscreen) return;
    hbl.Data = buf; hbl.Width = pixnum;
    HClipBlockScreen(&hbl,0,0,hscreen,x,y,pixnum,1);        
}

void 
R3DReadLine(hnd,buf,pixnum,x,y) /* returns rgba of pixnum pixels */
int hnd, *buf;
int pixnum,x,y; /*The length and the position of the line to be read */
{   
    if(!hscreen) return;
    hbl.Data = buf; hbl.Width = pixnum;
    HClipScreenBlock(hscreen,x,y,&hbl,0,0,pixnum,1);
}

void 
R3DClsScr(int hnd, int color)
{   if(!hscreen) return;
    hscreen->FgPen = color; HClearScreen(hscreen);   
}

void
R3DGetSize(int hnd, int *x, int *y)
{   *x = hscreen->Width; *y = hscreen->Height;
}
        
void 
R3DSetMode(int hnd)
{   struct IntuiMessage *message;
    struct Window *aw;
    ULONG class,gadgetid;
    APTR iaddress;

    static WORD gsquare[6] = {0,10, 0, 0,79,0}; 
    static WORD gsquare2[6] = {0,10,79,10,79,0}; 

    static struct Border gborder2 = {0,0,2,3,JAM2,3,(WORD *)&gsquare2,NULL,};
    static struct Border gborder = {0,0,1,3,JAM2,3,(WORD *)&gsquare,&gborder2,};
    
    static struct IntuiText _headertext = 
        {1,1,JAM1,9, 4,NULL,"Select frame buffer modes",NULL,};
    static struct IntuiText headertext =
        {2,2,JAM1,11,5,NULL,"Select frame buffer modes",&_headertext,};

    static struct IntuiText lace_text = {1,5,JAM1,4,2,NULL,"INTERLACE",NULL,};
    static struct IntuiText hires_text = {1,5,JAM1,20,2,NULL,"HIRES",NULL,};
    static struct IntuiText otext = { 1,1,JAM1,30,2,NULL,"OK",0,};
    static struct IntuiText ctext = {1,1,JAM1,14,2,NULL,"CANCEL",NULL,};  

    static struct Gadget lace_gadget =
    {	NULL,130,25,80,11,GADGHCOMP,TOGGLESELECT,BOOLGADGET|REQGADGET,
        (APTR)&gborder,NULL,&lace_text,NULL,NULL,0,NULL,
    };

    static struct Gadget hires_gadget =
    {	&lace_gadget,10,25,80,11,GADGHCOMP,TOGGLESELECT,BOOLGADGET|REQGADGET,
        (APTR)&gborder,NULL,&hires_text,NULL,NULL,0,NULL,
    };
    
    static struct Gadget cancel_gadget =
    {	&hires_gadget,130,45,80,11,GADGHCOMP,ENDGADGET | RELVERIFY,
	BOOLGADGET|REQGADGET,(APTR)&gborder,NULL,&ctext,NULL,NULL,2,NULL,
    };

    static struct Gadget ok_gadget=
    {	&cancel_gadget,10,45,80,11,GADGHCOMP,ENDGADGET | RELVERIFY,
        BOOLGADGET|REQGADGET,(APTR)&gborder,NULL,&otext,NULL,NULL,1,NULL,
    };

    static WORD req_square[6] = {0,59,0,0,219,0};
    static WORD req_square2[6] = {0,59,219,59,219,0};

    static struct Border req_border2 =
        { 0,0,2,2,JAM1,3,(WORD *)&req_square2,NULL,};
    static struct Border req_border =
        { 0,0,1,1,JAM1,3,(WORD *)&req_square,&req_border2,};

    static struct Requester mode_req =
    {  	NULL,100,50,220,60,0,0,&ok_gadget,&req_border,&headertext,
	NULL,0,NULL,{NULL},{NULL},NULL,{NULL},
    };
    
    if(!hscreen) return;
    
    if(!(IntuitionBase=(struct IntuitionBase *)
    	OpenLibrary("intuition.library",0))) return;

    if(hscreen->Type & HINTERLACE) lace_gadget.Flags |= SELECTED;
    else lace_gadget.Flags &= ~SELECTED;
    if(hscreen->Width  == 910) hires_gadget.Flags |= SELECTED; 
    else hires_gadget.Flags &= ~SELECTED;

    aw = IntuitionBase->ActiveWindow;
    if(!Request(&mode_req,aw)) goto cleanexit;
    
    for(;;)
    {   while(!(message=(struct IntuiMessage *)GetMsg(aw->UserPort)))
            Wait(1<<aw->UserPort->mp_SigBit);
        if(message)
        {   class = message->Class;
            iaddress = message->IAddress;
            ReplyMsg(message);
            if(class == GADGETUP) break;
        }	    
    }
    gadgetid=((struct Gadget *)iaddress)->GadgetID;
    if(gadgetid == 1)
    {   if(lace_gadget.Flags & SELECTED) myscreen.Type |= HINTERLACE;
	else myscreen.Type &=~HINTERLACE;
	if(hires_gadget.Flags & SELECTED) myscreen.Width = 910;
	else myscreen.Width = 740;
        HConvertScreen(hscreen,&myscreen,0);
    }
  cleanexit:  CloseLibrary(IntuitionBase);
}

void
R3DCustomSave(int hnd, char *name, int x, int y, int w, int h)
{   
}

