/*
**    GrabKEY
**
**        © 1996 by Timo C. Nentwig
**        All Rights Reserved !
**
**        Tcn@techbase.in-berlin.de
**
**
*/

/// #include

#include "gk_GST.h"
#include "gk_Protos.h"

///
/// proto

static BOOL    GetCoords    (const ULONG What, struct Window *Window, struct Screen *Screen);
proto  BOOL    GetImage     (Object **Image, const ULONG What);

///

static struct
{

	LONG    Left;
	LONG    Top;
	LONG    Width;
	LONG    Height;

} GrabCoords;

/// GetImage ()

	/*
	 *    FUNCTION    Create a DT Object * referencing
	 *                to a window or screen.
	 *
	 *    NOTE        Values fur <What> in gk_GST.h.
	 *
	 *    EXAMPLE     GetImage (&Image, WINDOW);
	 *
	 */


BOOL
GetImage (Object **Image, const ULONG What)
{

	BOOL               Result = FALSE;
	ULONG              ILock  = LockIBase (NULL);

	struct   Window   *Window = IntuitionBase -> ActiveWindow;
	struct   Screen   *Screen = IntuitionBase -> ActiveScreen;

	if (Window && Screen)
	{

			// Get coordinates to grab

		if (GetCoords (What, Window, Screen))
		{

			struct    BitMap   *BitMap;
			LONG                Depth;

			Depth = GetBitMapAttr (Screen -> RastPort . BitMap, BMA_DEPTH);

				// Alloc BitMap for our image

			if (BitMap = AllocBitMap (GrabCoords . Width, GrabCoords . Height, Depth, NULL, Screen -> RastPort . BitMap))
			{

				struct    RastPort __aligned    RPort;

				InitRastPort (&RPort);

				RPort . BitMap = BitMap;

				if (What == WINDOW)
				{

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

				}
				else // if (What == SCREEN || What == RANGE)
				{

					ClipBlit (&Screen -> RastPort, 0, 0, &RPort, 0, 0, GrabCoords . Width, GrabCoords . Height, 0xC0);

				}

					// Wait till blitted

				WaitBlit();

				{

					LONG    NumColors = Screen -> ViewPort . ColorMap -> Count;
					LONG    ModeID    = BestModeID (BIDTAG_NominalWidth,     GrabCoords . Width,
													BIDTAG_NominalHeight,    GrabCoords . Height,
													BIDTAG_Depth,            Depth,
													TAG_END);

					if (*Image = NewDTObject ("GrabImage", DTA_SourceType,    DTST_RAM,
														   DTA_GroupID,       GID_PICTURE,
														   PDTA_NumColors,    NumColors,
														   PDTA_BitMap,       BitMap,
														   PDTA_ModeID,       ModeID,
														   TAG_END))
														   {

															   struct    ColorRegister    *ColorMap;
															   struct    BitMapHeader     *BitMapHeader;
															   ULONG                      *Colors;

															   if (GetDTAttrs (*Image, PDTA_BitMapHeader,     &BitMapHeader,
																					   PDTA_ColorRegisters,   &ColorMap,
																					   PDTA_CRegs,            &Colors,
																					   TAG_END) == 3)
																					   {

																						   LONG    i;

																						   BitMapHeader -> bmh_Left       = GrabCoords . Left;
																						   BitMapHeader -> bmh_Top        = GrabCoords . Top;
																						   BitMapHeader -> bmh_Width      = GrabCoords . Width;
																						   BitMapHeader -> bmh_Height     = GrabCoords . Height;
																						   BitMapHeader -> bmh_PageWidth  = GrabCoords . Width;
																						   BitMapHeader -> bmh_PageHeight = GrabCoords . Height;
																						   BitMapHeader -> bmh_Depth      = Depth;

																						   GetRGB32 (Screen -> ViewPort . ColorMap, 0, NumColors, Colors);

																						   for (i = 0; i < NumColors; i++)
																						   {

																							   ColorMap[i] . red   = (UBYTE) (Colors [i * 3 + 0] >> 24);
																							   ColorMap[i] . green = (UBYTE) (Colors [i * 3 + 1] >> 24);
																							   ColorMap[i] . blue  = (UBYTE) (Colors [i * 3 + 2] >> 24);

																						   }

																						   Result = TRUE;

																					   }
																					   else
																					   {

																						   DisposeDTObject(*Image);

																						   *Image = NULL;

																					   }

														   }
														   else // "else" is VERY important !!
														   {

																   // Failed, free our BitMap

															   FreeBitMap (BitMap);

														   }

				}

			}

		}

	}

		// Unlock IntuitionBase

	UnlockIBase (ILock);

		// Success ?

	return (Result);

}

///
/// GetCoords ()

	/*
	 *    FUNCTION    Get coordinates to grab
	 *                and write them to GrabCoords.
	 *
	 *    NOTE        MUST be called in state of LockIBase() !
	 *
	 *    EXAMPLE     GetCoords (RANGE);
	 *
	 */

static BOOL
GetCoords (const ULONG What, struct Window *Window, struct Screen *Screen)
{

	BOOL    Result = FALSE;

	if (What == WINDOW)
	{

			// Get coordinates

		GrabCoords . Left   = Window -> LeftEdge;
		GrabCoords . Top    = Window -> TopEdge;
		GrabCoords . Width  = Window -> Width;
		GrabCoords . Height = Window -> Height;

		if (Window -> Flags & WFLG_SIMPLE_REFRESH)
		{

			struct    Rectangle    Visible;

			GetRPAttrs (Window -> RPort, RPTAG_DrawBounds,   &Visible,
										 TAG_END);

			if (Visible . MaxX < Visible . MinX)
			{

				return (FALSE);

			}
			else
			{

				GrabCoords . Width  = Visible . MaxX - Visible . MinX + 1;
				GrabCoords . Height = Visible . MaxY - Visible . MinY + 1;

				if (GrabCoords . Width < Window -> Width || GrabCoords . Height < Window -> Height)
				{

					return (FALSE);

				}

			}

		}

		Result = TRUE;

	}
	else // if (What == SCREEN)
	{

			// Get coordinates

		GrabCoords . Left   = Screen -> LeftEdge;
		GrabCoords . Top    = Screen -> TopEdge;
		GrabCoords . Width  = Screen -> Width;
		GrabCoords . Height = Screen -> Height;

		Result = TRUE;

	}

	return (Result);

}

///

