#include <intuition/intuitionbase.h>
#include <graphics/gfxbase.h>
#include <datatypes/pictureclass.h>
#include <exec/memory.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/macros.h>

#include <stdio.h>

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

VOID					CloseAll(VOID);
BOOL					OpenAll(VOID);
VOID					PrintPicture(Object *Picture);
Object *				GetPicture(VOID);

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

	if(OpenAll())
	{
		Object *Picture;

		Result = RETURN_OK;

		if(Picture = GetPicture())
		{
			printf("Vorderster Bildschirm wird gedruckt.\n");

			PrintPicture(Picture);
		}
	}

	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
PrintPicture(Object *Picture)
{
	struct MsgPort *PrinterPort;

	if(PrinterPort = CreateMsgPort())
	{
		union printerIO *PrinterIO;

		if(PrinterIO = (union printerIO *)CreateIORequest(PrinterPort,
			sizeof(union printerIO)))
		{
			if(!OpenDevice("printer.device",0,(struct IORequest *)PrinterIO,
				NULL))
			{
				DoMethod(Picture,DTM_PRINT,NULL,PrinterIO,NULL);

				CloseDevice((struct IORequest *)PrinterIO);
			}

			DeleteIORequest((struct IORequest *)PrinterIO);
		}

		DeleteMsgPort(PrinterPort);
	}

	DisposeDTObject(Picture);
}

Object *
GetPicture()
{
	struct BitMap	*BitMap;
	ULONG			 IntuiLock;
	struct RastPort	*RPort;
	struct Screen	*Screen;
	LONG			 PageWidth,PageHeight,
					 Depth;
	BOOL			 Locked = TRUE;

	IntuiLock	= LockIBase(NULL);

	Screen		= IntuitionBase -> FirstScreen;
	RPort		= &Screen -> RastPort;

	PageWidth	= Screen -> Width;
	PageHeight	= Screen -> Height;
	Depth		= GetBitMapAttr(RPort -> BitMap,BMA_DEPTH);

	if(BitMap = AllocBitMap(PageWidth,PageHeight,Depth,BMF_CLEAR,
		RPort -> BitMap))
	{
		ULONG	*ColourTable,
				 ModeID;
		LONG	 NumColours = Screen -> ViewPort . ColorMap -> Count;

		ModeID = GetVPModeID(&Screen -> ViewPort);

		BltBitMap(RPort -> BitMap,0,0,BitMap,0,0,PageWidth,PageHeight,0xC0,
			0xFF,NULL);

		WaitBlit();

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

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

			UnlockIBase(IntuiLock);

			Locked = FALSE;

			if(Picture = NewDTObject("FirstScreen",
				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		= 0;
					BitMapHeader -> bmh_Top			= 0;
					BitMapHeader -> bmh_Width		= PageWidth;
					BitMapHeader -> bmh_Height		= PageHeight;
					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);

					return(Picture);
				}

				DisposeDTObject(Picture);

				BitMap = NULL;
			}

			FreeVec(ColourTable);
		}

		FreeBitMap(BitMap);
	}

	if(Locked)
		UnlockIBase(IntuiLock);

	return(NULL);
}
