#include <intuition/intuitionbase.h>
#include <graphics/gfxbase.h>
#include <datatypes/pictureclass.h>
#include <exec/memory.h>
#include <dos/dos.h>

#include <clib/datatypes_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/macros.h>

#include <stdio.h>

struct IntuitionBase	*IntuitionBase;
struct GfxBase			*GfxBase;
struct Library			*DataTypesBase;

VOID					CloseAll(VOID);
BOOL					OpenAll(VOID);
VOID					SavePicture(Object *Picture,STRPTR FileName);
Object *				GetPicture(VOID);

int
main(int argc,char **argv)
{
	int Result = RETURN_FAIL;

	if(OpenAll())
	{
		Object	*Picture;
		STRPTR	 Name;

		Result = RETURN_OK;

		if(argc < 2)
			Name = "Testbild";
		else
			Name = (STRPTR)argv[1];

		if(Picture = GetPicture())
		{
			printf("Aktives Fenster wird unter \"%s\" gespeichert.\n",Name);

			SavePicture(Picture,Name);
		}
	}

	CloseAll();

	return(Result);
}

VOID
CloseAll()
{
	CloseLibrary((struct Library *)IntuitionBase);
	CloseLibrary((struct Library *)GfxBase);
	CloseLibrary(DataTypesBase);
}

BOOL
OpenAll()
{
	if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",
		39)))
	{
		printf("Kann intuition.library v39 nicht öffnen\n");
		return(FALSE);
	}

	if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",39)))
	{
		printf("Kann graphics.library v39 nicht öffnen\n");
		return(FALSE);
	}

	if(!(DataTypesBase = OpenLibrary("datatypes.library",39)))
	{
		printf("Kann datatypes.library v39 nicht öffnen\n");
		return(FALSE);
	}

	return(TRUE);
}

VOID
SavePicture(Object *Picture,STRPTR FileName)
{
	BPTR FileHandle;

	if(FileHandle = Open(FileName,MODE_NEWFILE))
	{
		if(DoMethod(Picture,DTM_WRITE,NULL,FileHandle,DTWM_IFF,NULL))
			Close(FileHandle);
		else
		{
			Close(FileHandle);

			DeleteFile(FileName);
		}
	}

	DisposeDTObject(Picture);
}

Object *
GetPicture()
{
	struct RastPort *RPort;

	if(RPort = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY))
	{
		struct BitMap	*BitMap;
		ULONG			 IntuiLock;
		struct Window	*Window;
		LONG			 Left,Top,
						 Width,Height,
						 PageWidth,PageHeight,
						 Depth;
		BOOL			 Locked = TRUE;

		InitRastPort(RPort);

		IntuiLock = LockIBase(NULL);

		Window = IntuitionBase -> ActiveWindow;

		Left		= Window -> LeftEdge;
		Top			= Window -> TopEdge;
		Width		= Window -> Width;
		Height		= Window -> Height;
		PageWidth	= Window -> WScreen -> Width;
		PageHeight	= Window -> WScreen -> Height;
		Depth		= GetBitMapAttr(Window -> RPort -> BitMap,BMA_DEPTH);

		if(BitMap = AllocBitMap(Width,Height,Depth,BMF_CLEAR,
			Window -> RPort -> BitMap))
		{
			ULONG	*ColourTable,
					 ModeID;
			LONG	 NumColours;

			NumColours = Window -> WScreen -> ViewPort . ColorMap -> Count;

			ModeID = GetVPModeID(&Window -> WScreen -> ViewPort);

			RPort -> BitMap = BitMap;

			ClipBlit(Window -> RPort,0,0,RPort,0,0,Width,Height,0xC0);

			WaitBlit();

			if(ColourTable = (ULONG *)AllocVec(sizeof(ULONG) * 3 * NumColours,
				MEMF_ANY))
			{
				Object *Picture;

				GetRGB32(Window -> WScreen -> ViewPort . ColorMap,0,NumColours,
					ColourTable);

				UnlockIBase(IntuiLock);

				Locked = FALSE;

				if(Picture = NewDTObject("ActiveWindow",
					DTA_SourceType,	DTST_RAM,
					DTA_GroupID,	GID_PICTURE,
					PDTA_NumColors,	NumColours,
					PDTA_BitMap,	BitMap,
					PDTA_ModeID,	ModeID,
				TAG_DONE))
				{
					struct ColorRegister	*ColourMap;
					struct BitMapHeader		*BitMapHeader;
					ULONG					*Colours;
		
					if(GetDTAttrs(Picture,
						PDTA_BitMapHeader,	&BitMapHeader,
						PDTA_ColorRegisters,&ColourMap,
						PDTA_CRegs,			&Colours,
					TAG_DONE) == 3)
					{
						BitMapHeader -> bmh_Left		= Left;
						BitMapHeader -> bmh_Top			= Top;
						BitMapHeader -> bmh_Width		= Width;
						BitMapHeader -> bmh_Height		= Height;
						BitMapHeader -> bmh_Depth		= Depth;
						BitMapHeader -> bmh_PageWidth	= PageWidth;
						BitMapHeader -> bmh_PageHeight	= PageHeight;

						CopyMem(ColourTable,Colours,
							3 * sizeof(ULONG) * NumColours);
		
						while(NumColours--)
						{
							ColourMap -> red	= (UBYTE)((*Colours++) >> 24);
							ColourMap -> green	= (UBYTE)((*Colours++) >> 24);
							ColourMap -> blue	= (UBYTE)((*Colours++) >> 24);

							ColourMap++;
						}

						FreeVec(ColourTable);

						FreeVec(RPort);

						return(Picture);
					}

					DisposeDTObject(Picture);

					BitMap = NULL;
				}

				FreeVec(ColourTable);
			}

			FreeBitMap(BitMap);
		}

		if(Locked)
			UnlockIBase(IntuiLock);

		FreeVec(RPort);
	}

	return(NULL);
}
