/* Datatype BitMap Handling code */
/* Linkable library */

/* (C) 1997 by Ben Matthew, All Rights Reserved */

#include <stdio.h>
#include <proto/datatypes.h>
#include <datatypes/datatypes.h>
#include <datatypes/pictureclass.h>
#include <datatypes/pictureclassext.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <intuition/intuition.h>

struct Library *DataTypesBase;

/* The ones which we rely on others providing (eek!) */

#include <proto/dos.h>
#include <proto/exec.h>

#include "dtbitmap.h"

/* Error messages */

char *dterr_msgs[] = {
	"Loaded OK!",
	"Couldn't open file",
	"Not enough free memory",
	"Problems when remapping image",
	"Internal datatypes error - possibly incorrect media type",
	"Could not open a needed library"
	
};

struct Window *OpenWindowBitMap(UBYTE *image, ULONG flags, ULONG idcmp, struct Screen *scr, BOOL keepbitmap, USHORT *err) {

	struct DTImage *img;
	struct Window *win=0;
	struct Library *IntuitionBase;
	struct Library *GfxBase;

	if(!(img=LoadDTBitMap(image,scr,err)))
		return(NULL);


	if(!(IntuitionBase=OpenLibrary("intuition.library",0))) {
		UnLoadDTBitMap(img);
		return(NULL);
	}
	
	if(!(GfxBase=OpenLibrary("graphics.library",0))) {
		UnLoadDTBitMap(img);
		CloseLibrary(IntuitionBase);
		return(NULL);
	}

	if(!(win=OpenWindowTags(NULL,WA_Left,0,WA_Top,0,WA_InnerWidth,img->Width,WA_InnerHeight,img->Height,WA_Flags,flags,(scr->Flags&PUBLICSCREEN) ? WA_PubScreen : WA_CustomScreen, scr, WA_IDCMP, idcmp, TAG_DONE))) {
		UnLoadDTBitMap(img);
		CloseLibrary(IntuitionBase);
		CloseLibrary(GfxBase);
		return(NULL);
	}

	BltBitMapRastPort(img->BitMap,0,0,win->RPort,(ULONG)win->BorderLeft,(ULONG)win->BorderTop,(ULONG)win->GZZWidth,(ULONG)win->GZZHeight,0xc0);
	win->UserData=NULL;
	if(keepbitmap)
		 win->UserData=(BYTE *)img; 
	else 
		UnLoadDTBitMap(img);
		
		
	CloseLibrary(IntuitionBase);
	CloseLibrary(GfxBase);
		
	return(win);

}

void CloseWindowBitMap(struct Window *win) {
	struct Library *IntuitionBase;

	if(IntuitionBase=OpenLibrary("intuition.library",0)) {
		if(win) {
			if(win->UserData) UnLoadDTBitMap((struct DTImage *)win->UserData);
			CloseWindow(win);
		}
		CloseLibrary(IntuitionBase);
	}
}

struct DTImage *LoadDTBitMap(UBYTE *filename, struct Screen *scr, USHORT *err) {

	struct DTImage *img;
	struct BitMap *tmp=0;
	struct BitMapHeader *head=0;
	ULONG *flags=0;
	Object *obj=0;
	struct Window *win=0;
	BPTR ptr=0;
	struct Library *IntuitionBase=0;
	struct Library *GfxBase=0;
	struct Gadget *gad=0;
	BOOL truecolour=FALSE;
	

	/* First check pointers */

	if(!err)
		return(0);

	if(!scr) {
		*err=DTERR_SCR;
		return(0);
	}

	if(!filename) {
		*err=DTERR_FILE;
		return(0);
	}


	/* Check to see if file exists */

	if(!(ptr=Open(filename,MODE_OLDFILE))) {
		*err=DTERR_FILE;
		return(0);
	}

	Close(ptr);


	/* Open lib and start the ball rolling */
	
	if(IntuitionBase=OpenLibrary("intuition.library",0)) {
		if(GfxBase=OpenLibrary("graphics.library",0)) {
			if(DataTypesBase=OpenLibrary("datatypes.library",0)) {
			
				if(GetBitMapAttr(scr->RastPort.BitMap,BMA_DEPTH)>8) truecolour=TRUE;
	
				/* Open remapping window on the given screen */
		
				if(win=OpenWindowTags(NULL,WA_Left,0,WA_Top,0,WA_Width,1,WA_Height,1,(scr->Flags&PUBLICSCREEN) ? WA_PubScreen : WA_CustomScreen,scr,TAG_DONE)) {
		
					/* Fire up a new DTObj */
			
					if(obj=NewDTObject(filename,DTA_SourceType,DTST_FILE,
									DTA_GroupID,GID_PICTURE,
									PDTA_DestMode,MODE_V43,
									PDTA_Screen,scr,
									PDTA_Remap, truecolour ? FALSE:TRUE,
								TAG_DONE)) {
				
						/* add it to window and refresh */
				
						AddDTObject(win,0,obj,-1);
				
						gad=(struct Gadget *)obj;
						flags=(UBYTE *)(gad->SpecialInfo)+46;

						while(*flags&1) {
							flags=(UBYTE *)(gad->SpecialInfo)+46;
							Delay(5);
						}

						RefreshDTObjectA(obj,win,0,0);

						/* Grab some info about the decoded dobrey */
				
						if(GetDTAttrs(obj,PDTA_DestBitMap,&tmp,PDTA_BitMapHeader,&head,TAG_DONE)) {
							/* Allocate the necessary bitmap */
							
							if(img=AllocVec(sizeof(struct DTImage),0)) {
							
								img->Width=head->bmh_Width;
								img->Height=head->bmh_Height;
								img->Depth=head->bmh_Depth;
						
								if(img->BitMap=AllocBitMap((ULONG)head->bmh_Width,(ULONG)head->bmh_Height,(ULONG)GetBitMapAttr(tmp,BMA_DEPTH),BMF_MINPLANES,tmp)) {
					
									BltBitMap(tmp,0,0,img->BitMap,0,0,(ULONG)head->bmh_Width,(ULONG)head->bmh_Height,0xc0,0xff,0);
									*err=DTERR_OK;
		
								} else {
									FreeVec(img);
									img=0;
									*err=DTERR_MEM;
								}
							} else
								*err=DTERR_MEM;
						} else
							*err=DTERR_INT;
						
						RemoveDTObject(win,obj);
						DisposeDTObject(obj);
					} else
						*err=DTERR_INT;
		
					CloseWindow(win);
				} else
					*err=DTERR_SCR;
	
				CloseLibrary(DataTypesBase);
			} else
				*err=DTERR_LIB;
			CloseLibrary(GfxBase);
		} else
			*err=DTERR_LIB;
		CloseLibrary(IntuitionBase);
	} else
		*err=DTERR_LIB;
	

	if(*err) return(0);
	return(img);
}

void UnLoadDTBitMap(struct DTImage *img) {
	struct Library *GfxBase;

	if(img) {

		if(GfxBase=OpenLibrary("graphics.library",0)) {
			if(img->BitMap) FreeBitMap(img->BitMap);
			CloseLibrary(GfxBase);
		}
		
		FreeVec(img);
	}
}