// MPImage - Amiga Image Conversion
// Copyright (C) © 1996 Mark John Paddock
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

// mark@topic.demon.co.uk
// mpaddock@cix.compulink.co.uk

#include "mpimage.h"

extern struct Library *DCTVBase = NULL;

#ifdef CYBER
extern struct Library *CyberGfxBase = NULL;
#endif

extern struct Library *EGSBase = NULL;

extern char ErrorMessage[256] = "";

extern long __oslibversion=39;

const char Version[]="$VER: MPImage.library"
#ifdef _M68040
	"_040"
#else
#ifdef _M68881
	"_881"
#else
#ifdef _M68020
	"_020"
#else
	"_000"
#endif
#endif
#endif
	" 5.1 (9.10.96)";

static far int OpenCount = 0;
static far struct SignalSemaphore sema = {0};

extern void
SetMax(int max) {
	if (ProgressWnd) {
		GT_SetGadgetAttrs(ProgressGadgets[GDX_Progress],ProgressWnd,NULL,
							GTSL_Max,max-1,
							GTSL_Level,0,
							TAG_END);
	}
}
extern void
SetCur(int cur) {
	if (ProgressWnd) {
		GT_SetGadgetAttrs(ProgressGadgets[GDX_Progress],ProgressWnd,NULL,
							GTSL_Level,cur,
							TAG_END);
	}
}

int top = 0;
// add a message to the progress list
void
AddMessage(UBYTE *message) {
	struct Node *node;
	if (ProgressWnd) {
		if ((node = (struct Node *)malloc(sizeof(struct Node))) &&
			 (node->ln_Name = malloc(strlen(message)+1))) {
			strcpy(node->ln_Name,message);
			GT_SetGadgetAttrs(ProgressGadgets[GDX_Info],ProgressWnd,NULL,
   	 						 GTLV_Labels, ~0,
   							 TAG_END);
			AddTail(&InfoList,node);
			GT_SetGadgetAttrs(ProgressGadgets[GDX_Info],ProgressWnd,NULL,
    							 GTLV_Labels, &InfoList,
	    						 GTLV_MakeVisible, top,
   							 TAG_END);
  			top++;
  		}
  		HandleProgressIDCMP();
	}
}

int __stdargs
_STI_CreateSema(void) {
#ifdef CYBER
	char buffer[3];
#endif
	Forbid();
	if (!OpenCount) {
		memset(&sema,0,sizeof(sema));
		InitSemaphore(&sema);
		NewList(&InfoList);
	}
	++OpenCount;
	Permit();
	DCTVBase = OpenLibrary("dctv.library",3);
#ifdef CYBER
	if (GetVar("mpimage/cybergraphics",buffer,1,0) != -1) {							
		CyberGfxBase = OpenLibrary("cybergraphics.library",40);
	}
#endif
	return 0;
}

void __stdargs
_STD_DeleteSema(void) {
	--OpenCount;
	if (DCTVBase) {
		CloseLibrary(DCTVBase);
		DCTVBase = NULL;
	}
#ifdef CYBER
	if (CyberGfxBase) {
		CloseLibrary(CyberGfxBase);
		CyberGfxBase = NULL;
	}
#endif
	return;
}

extern void LockSema(void) {
	ObtainSemaphore(&sema);
}
extern void UnlockSema(void) {
	ReleaseSemaphore(&sema);
}

extern void
PlanarToChunky(struct p2cStruct *p2c) {
	AddMessage("Planar to Chunky");
	ObtainSemaphore(&sema);
	PlanarToChunkyAsm(p2c);
	ReleaseSemaphore(&sema);
}

extern void
ChunkyToPlanar(struct c2pStruct *c2p) {
	AddMessage("Chunky to Planar");
	ObtainSemaphore(&sema);
	ChunkyToPlanarAsm(c2p);
	ReleaseSemaphore(&sema);
}

struct MyBitMap *
MyAllocBitMap(UWORD wide,UWORD high, UWORD deep, UBYTE *filename) {
	struct MyBitMap *bitmap;
	int k;
	BOOL error = 0;

	if (!filename || !*filename) {
		return (struct MyBitMap *)AllocBitMap(wide,high,deep,BMF_CLEAR|BMF_DISPLAYABLE,NULL);
	}
	if (bitmap = AllocMem(sizeof(struct MyBitMap),MEMF_CLEAR)) {
		InitBitMap((struct BitMap *)bitmap,deep,wide,high);
		for (k=0; k<deep && (!error); k++) {
			if (!(bitmap->BitMap.Planes[k] = AllocVec(RASSIZE(wide,high),MEMF_CLEAR))) {
				error = 1;
			}
		}
		if(error) {
			MyFreeBitMap(bitmap,filename);
			bitmap = NULL;
		}
	}
	return bitmap;
}

void
MyFreeBitMap(struct MyBitMap *bitmap,UBYTE *filename) {
	int k;
	if (!filename || !*filename) {
		FreeBitMap(bitmap);
		return;
	}
	for(k=0; k< bitmap->BitMap.Depth; k++) {
		if (bitmap->BitMap.Planes[k]) {
			FreeVec(bitmap->BitMap.Planes[k]);
		}
	}
	FreeMem(bitmap,sizeof(struct MyBitMap));
}

void __asm __saveds FreeMPImage(register __a0 struct MPImage *MPi);

char * __asm __saveds MPImageErrorMessage(void);

/****** MPImage.library/MPPlanarToChunky ******************************
*
*   NAME   
*  MPPlanarToChunky -- Convert a bitmap to a chunky buffer (V5)
*
*   SYNOPSIS
*  MPPlanarToChunky( bitmap, chunky, width, height )
*                    A0      A1      D0     D1
*
*  void MPPlanarToChunky( struct BitMap *, UBYTE *, UWORD, UWORD);
*
*   FUNCTION
*  Converts a BitMap to a chunky buffer.
*
*   INPUTS
*  bitmap - Pointer to a standard bitmap.
*  chunky - Pointer to a chunky buffer of sufficient size.
*  width  - Width of bitmap.
*  height - Height of bitmap.
*
*   RESULT
*  None.
*
*   EXAMPLE
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*
*****************************************************************************
*
*/
void __asm __saveds
MPPlanarToChunky(register __a0 struct BitMap *bitmap,register __a1 UBYTE *chunky,
						register __d0 UWORD width, register __d1 UWORD height) {
	struct p2cStruct p2c;
	p2c.bmap = bitmap;
	p2c.startX = 0;
	p2c.startY = 0;
	p2c.width = width;
	p2c.height = height;
	p2c.chunkybuffer = chunky;
	ObtainSemaphore(&sema);
	PlanarToChunkyAsm(&p2c);
	ReleaseSemaphore(&sema);
}


/****** MPImage.library/FreeMPImage ***********************************
*
*   NAME   
*  FreeMPImage -- Free an image loaded using LoadMPImage() (V3)
*
*   SYNOPSIS
*  FreeMPImage( MPi )
*               A0
*
*  void FreeMPImage( struct MPImage * );
*
*   FUNCTION
*  Frees all data associated loaded with an image using LoadMPImage().
*
*   INPUTS
*  MPi - structure returned by LoadMPImage().
*
*   RESULT
*  None.
*
*   EXAMPLE
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  LoadMPImage()
*
*****************************************************************************
*
*/
void __asm __saveds
FreeMPImage(register __a0 struct MPImage *MPi) {
	if (MPi) {
		if (MPi->Red) {
			FreeVec(MPi->Red);
		}
		if (!MPi->GreyScale) {
			if (MPi->Blue) {
				FreeVec(MPi->Blue);
			}
			if (MPi->Green) {
				FreeVec(MPi->Green);
			}
		}
		if (MPi->Object) {	// Dispose object (frees bit map as well...)
			DisposeDTObject(MPi->Object);
		}
		else {
			if (MPi->BitMap) {
				FreeBitMap(MPi->BitMap);
			}
			if (MPi->EGS_BitMap) {
				if (EGSBase = OpenLibrary((char *)"egs.library",0)) {
					E_DisposeBitMap(MPi->EGS_BitMap);
					CloseLibrary(EGSBase);
				}
			}
		}
		FreeMem(MPi,sizeof(struct MPImage));
	}
}

/****** MPImage.library/MPImageErrorMessage *********************************
*
*   NAME   
*  MPImageErrorMessage -- Return the last error set by MPImage.library. (V3)
*
*   SYNOPSIS
*  msg = MPImageErrorMessage()
*  D0
*
*  char *MPImageErrorMessage( void );
*
*   FUNCTION
*  Returns the last error message set by this opener of MPImage.library.
*
*   INPUTS
*  None.
*
*   RESULT
*  Formatted Error Message.
*
*   EXAMPLE
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*
*****************************************************************************
*
*/
char * __asm __saveds
MPImageErrorMessage(void) {
	return ErrorMessage;
}

extern BOOL ShowProgress;

/****** MPImage.library/SetMPImageScreen ************************************
*
*   NAME   
*  SetMPImageScreen -- Sets the Screen name for progress requesters (V3)
*
*   SYNOPSIS
*  SetMPImageScreen(ScreenName,Flags)
*                   A0         D0
*
*  void SetMPImageScreen(char *, ULONG);
*
*   FUNCTION
*  Sets the Screen Name for progress requesters for this opener.
*
*   INPUTS
*  ScreenName - Name of Public Screen, NULL for default
*  Flags      - 0 - Do not show progress requesters (default)
*             - MPIF_PROGRESS - Do show progress requesters
*                               (except for non remapped bitmaps).
*
*   RESULT
*  None.
*
*   EXAMPLE
*
*   NOTES
*  ScreenName must remain valid while MPImage.library is open.
*
*   BUGS
*
*   SEE ALSO
*
*****************************************************************************
*
*/
void __asm __saveds
SetMPImageScreen(register __a0 char *ScreenName, register __d0 ULONG Flags) {
	PubScreenName = ScreenName;
	if (Flags & MPIF_PROGRESS) {
		ShowProgress = TRUE;
	}
	else {
		ShowProgress = FALSE;
	}
}
