/*  GadTools layout toolkit
**
**  Copyright © 1993-1994 by Olaf `Olsen' Barthel
**  Freely distributable.
*/

#include "gtlayout_global.h"

#ifdef DO_CLONING
VOID __regargs
LTP_CloneScreen(struct LayoutHandle *Handle,LONG Width,LONG Height)
{
	struct ColorSpec	*ColourSpec	= NULL;
	struct ColourRecord	*ColourRecord	= NULL;
	struct CloneExtra	*Extra = Handle -> CloneExtra;
	LONG			 AllocationSize;
	UWORD			 i,j,*Pens = Handle -> CloneExtra -> ScreenPens,NumColours;
	struct Screen		*Screen;
	ULONG			 DisplayID = GetVPModeID(&Handle -> Screen -> ViewPort);
	UWORD			 EndPen = (UWORD)~0;

	if(Handle -> ExactClone)
		NumColours = Handle -> Screen -> ViewPort . ColorMap -> Count;
	else
	{
		NumColours = Extra -> TotalPens;

		DisplayID &= ~(HAM | EXTRA_HALFBRITE);
	}

	Height += Handle -> Screen -> BarHeight + 1;

	if(Width < Extra -> MinWidth)
		Width = Extra -> MinWidth;

	if(Height < Extra -> MinHeight)
		Height = Extra -> MinHeight;

	if(Handle -> SimpleClone)
		Pens = &EndPen;
	else
	{
		if(V39)
		{
			if(!(ColourRecord = (struct ColourRecord *)AsmAllocPooled(Handle -> Pool,AllocationSize = sizeof(struct ColourRecord) + sizeof(struct ColourTriplet) * NumColours,SysBase)))
			{
				Handle -> Failed = TRUE;

				return;
			}
			else
			{
				memset(ColourRecord,0,AllocationSize);

				ColourRecord -> NumColours = NumColours;

				if(Handle -> ExactClone)
					GetRGB32(Handle -> Screen -> ViewPort . ColorMap,0,NumColours,(ULONG *)ColourRecord -> Triplets);
				else
				{
					for(i = 0 ; i < NumColours ; i++)
						GetRGB32(Handle -> Screen -> ViewPort . ColorMap,Extra -> Pens[i],1,(ULONG *)&ColourRecord -> Triplets[i]);
				}
			}
		}
		else
		{
			if(!(ColourSpec = (struct ColorSpec *)AsmAllocPooled(Handle -> Pool,AllocationSize = sizeof(struct ColorSpec) * (NumColours + 1),SysBase)))
			{
				Handle -> Failed = TRUE;

				return;
			}
			else
			{
				UWORD RGB;

				if(Handle -> ExactClone)
				{
					for(i = 0 ; i < NumColours ; i++)
					{
						RGB = GetRGB4(Handle -> Screen -> ViewPort . ColorMap,i);

						ColourSpec[i] . ColorIndex	= i;
						ColourSpec[i] . Red		= (RGB >> 8) & 0xF;
						ColourSpec[i] . Green		= (RGB >> 4) & 0xF;
						ColourSpec[i] . Blue		= (RGB	   ) & 0xF;
					}
				}
				else
				{
					for(i = 0 ; i < NumColours ; i++)
					{
						RGB = GetRGB4(Handle -> Screen -> ViewPort . ColorMap,Extra -> Pens[i]);

						ColourSpec[i] . ColorIndex	= i;
						ColourSpec[i] . Red		= (RGB >> 8) & 0xF;
						ColourSpec[i] . Green		= (RGB >> 4) & 0xF;
						ColourSpec[i] . Blue		= (RGB	   ) & 0xF;
					}
				}

				ColourSpec[i] . ColorIndex = -1;
			}
		}

		if(Handle -> ExactClone)
		{
			for(i = 0 ; i < Handle -> DrawInfo -> dri_NumPens ; i++)
				Pens[i] = Extra -> Pens[i];
		}
		else
		{
			for(i = 0 ; i < Handle -> DrawInfo -> dri_NumPens ; i++)
			{
				for(j = 0 ; j < NumColours ; j++)
				{
					if(Extra -> Pens[j] == Handle -> DrawInfo -> dri_Pens[i])
					{
						Pens[i] = j;

						break;
					}
				}
			}
		}

		Pens[i] = (UWORD)~0;
	}

	if(Screen = OpenScreenTags(NULL,
		SA_Width,	Width,
		SA_Height,	Height,
		SA_Overscan,	OSCAN_TEXT,
		SA_AutoScroll,	TRUE,
		SA_DisplayID,	DisplayID,
		SA_Behind,	TRUE,
		SA_Depth,	Handle -> SimpleClone ? 2 : Extra -> Depth,
		SA_Colors,	ColourSpec,
		SA_Colors32,	ColourRecord,
		SA_Pens,	Pens,
		SA_Font,	Handle -> TextAttr,
		SA_Title,	Handle -> Screen -> DefaultTitle,

		Handle -> SimpleClone ? TAG_IGNORE : SA_BackFill,	&Handle -> BackfillHook,
		Handle -> SimpleClone ? TAG_IGNORE : SA_BlockPen,	Pens[SHADOWPEN],
		Handle -> SimpleClone ? TAG_IGNORE : SA_DetailPen,	Pens[BACKGROUNDPEN],
	TAG_DONE))
	{
		struct DrawInfo *DrawInfo;

		if(DrawInfo = GetScreenDrawInfo(Screen))
		{
			APTR VisualInfo;

			if(VisualInfo = GetVisualInfoA(Screen,NULL))
			{
				UnlockPubScreen(NULL,Handle -> PubScreen);

				FreeScreenDrawInfo(Handle -> Screen,Handle -> DrawInfo);

				FreeVisualInfo(Handle -> VisualInfo);

				Handle -> PubScreen	= NULL;
				Handle -> Screen	= Screen;
				Handle -> DrawInfo	= DrawInfo;
				Handle -> VisualInfo	= VisualInfo;
				Handle -> TextPen	= Handle -> DrawInfo -> dri_Pens[TEXTPEN];
				Handle -> BackgroundPen = Handle -> DrawInfo -> dri_Pens[BACKGROUNDPEN];
				Handle -> ShinePen	= Handle -> DrawInfo -> dri_Pens[SHINEPEN];
				Handle -> ShadowPen	= Handle -> DrawInfo -> dri_Pens[SHADOWPEN];
				Handle -> AspectX	= Handle -> DrawInfo -> dri_Resolution . X;
				Handle -> AspectY	= Handle -> DrawInfo -> dri_Resolution . Y;

				if(Handle -> SimpleClone)
					Handle -> MaxPen = 0;
				else
					Handle -> MaxPen = Extra -> TotalPens - 1;

				Extra -> Screen = Screen;

				if(ColourRecord)
					AsmFreePooled(Handle -> Pool,ColourRecord,AllocationSize,SysBase);

				if(ColourSpec)
					AsmFreePooled(Handle -> Pool,ColourSpec,AllocationSize,SysBase);

				return;
			}

			FreeScreenDrawInfo(Screen,DrawInfo);
		}

		CloseScreen(Screen);
	}

	if(ColourRecord)
		AsmFreePooled(Handle -> Pool,ColourRecord,AllocationSize,SysBase);

	if(ColourSpec)
		AsmFreePooled(Handle -> Pool,ColourSpec,AllocationSize,SysBase);

	Handle -> Failed = TRUE;
}

BOOLEAN __regargs
LTP_PrepareCloning(struct LayoutHandle *Handle)
{
	if(Handle -> CloneExtra)
		return(TRUE);
	else
	{
		struct DimensionInfo DimensionInfo;

		if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,GetVPModeID(&Handle -> Screen -> ViewPort)))
		{
			if(Handle -> CloneExtra = (struct CloneExtra *)AsmAllocPooled(Handle -> Pool,sizeof(struct CloneExtra) + (sizeof(LONG) + sizeof(UWORD)) * Handle -> DrawInfo -> dri_NumPens + sizeof(UWORD),SysBase))
			{
				UWORD	 i,j,TotalPens = 0;
				LONG	*Pens;
				BOOLEAN  NotFound;

				Handle -> CloneExtra -> Pens		= (LONG *)(Handle -> CloneExtra + 1);
				Handle -> CloneExtra -> ScreenPens	= (UWORD *)(&Handle -> CloneExtra -> Pens[Handle -> DrawInfo -> dri_NumPens]);
				Handle -> CloneExtra -> MinWidth	= DimensionInfo . MinRasterWidth;
				Handle -> CloneExtra -> MinHeight	= DimensionInfo . MinRasterHeight;
				Handle -> CloneExtra -> MaxWidth	= DimensionInfo . MaxRasterWidth;
				Handle -> CloneExtra -> MaxHeight	= DimensionInfo . MaxRasterHeight;

				Handle -> CloneExtra -> Bounds . Left	= 0;
				Handle -> CloneExtra -> Bounds . Top	= 0;
				Handle -> CloneExtra -> Bounds . Width	= DimensionInfo . MaxRasterWidth;
				Handle -> CloneExtra -> Bounds . Height = DimensionInfo . MaxRasterHeight;

				Pens = Handle -> CloneExtra -> Pens;

				if(Handle -> ExactClone)
				{
					for(i = 0 ; i < Handle -> DrawInfo -> dri_NumPens ; i++)
						Pens[i] = Handle -> DrawInfo -> dri_Pens[i];

					TotalPens = Handle -> DrawInfo -> dri_NumPens;

					Handle -> CloneExtra -> Depth = Handle -> DrawInfo -> dri_Depth;
				}
				else
				{
					for(i = 0 ; i < Handle -> DrawInfo -> dri_NumPens ; i++)
					{
						for(j = 0,NotFound = TRUE ; NotFound && j < TotalPens ; j++)
						{
							if(Pens[j] == Handle -> DrawInfo -> dri_Pens[i])
								NotFound = FALSE;
						}

						if(NotFound)
							Pens[TotalPens++] = Handle -> DrawInfo -> dri_Pens[i];
					}

					for(i = 0 ; i < DimensionInfo . MaxDepth ; i++)
					{
						if(TotalPens <= (1L << i))
						{
							Handle -> CloneExtra -> Depth = i;

							break;
						}
					}
				}

				if((Handle -> CloneExtra -> TotalPens = TotalPens) && Handle -> CloneExtra -> Depth)
				{
					if(LTP_GlyphSetup(Handle,Handle -> InitialTextAttr))
					{
						Handle -> Failed = Handle -> Rescaled = FALSE;

						LTP_ResetGroups(Handle -> TopGroup);

						if(!V39 && (Handle -> RPort . TxFlags & FPF_PROPORTIONAL))
						{
							LTP_Rescale(Handle,FALSE,FALSE);

							Handle -> Rescaled = FALSE;
						}

						return(TRUE);
					}
				}
				else
				{
					AsmFreePooled(Handle -> Pool,Handle -> CloneExtra,sizeof(struct CloneExtra) + sizeof(LONG) * Handle -> DrawInfo -> dri_NumPens,SysBase);

					Handle -> CloneExtra = NULL;
				}
			}
		}
	}

	return(FALSE);
}
#endif
