/*
**	termAbout.c
**
**	Support routines for the `About' window.
**
**	Copyright © 1990-1994 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

#include "termGlobal.h"

enum	{	GAD_FRAME=1,GAD_BUTTON };

	/* LocalDeleteBitMap(struct BitMap *BitMap,UWORD Width,UWORD Height):
	 *
	 *	Delete yet another screen bitmap.
	 */

STATIC VOID __regargs
LocalDeleteBitMap(struct BitMap *BitMap,UWORD Width,UWORD Height)
{
	if(BitMap)
	{
		WORD i;

		WaitBlit();

		for(i = 0 ; i < BitMap -> Depth ; i++)
		{
			if(BitMap -> Planes[i])
				FreeRaster(BitMap -> Planes[i],Width,Height);
		}

		FreeVecPooled(BitMap);
	}
}

	/* LocalCreateBitMap(UWORD Depth,UWORD Width,UWORD Height):
	 *
	 *	Create yet another screen bitmap.
	 */

STATIC struct BitMap * __regargs
LocalCreateBitMap(UWORD Depth,UWORD Width,UWORD Height)
{
	struct BitMap *BitMap;

	if(BitMap = (struct BitMap *)AllocVecPooled(sizeof(struct BitMap),MEMF_ANY))
	{
		BYTE	Success = TRUE;
		WORD	i;

		InitBitMap(BitMap,Depth,Width,Height);

		for(i = 0 ; Success && i < Depth ; i++)
		{
			if(!(BitMap -> Planes[i] = AllocRaster(Width,Height)))
				Success = FALSE;
		}

		if(Success)
			return(BitMap);

		LocalDeleteBitMap(BitMap,Width,Height);
	}

	return(NULL);
}

	/* CreateBitMapFromImage(struct Image *Image,struct BitMap *BitMap):
	 *
	 *	Turn an Intuition Image into a Gfx BitMap.
	 */

STATIC VOID __regargs
CreateBitMapFromImage(struct Image *Image,struct BitMap *BitMap)
{
	PLANEPTR	Data	= (PLANEPTR)Image -> ImageData;
	ULONG		Modulo	= ((((ULONG)Image -> Width) + 15) >> 3) & ~1;
	WORD		i;

	InitBitMap(BitMap,Image -> Depth,Image -> Width,Image -> Height);

	for(i = 0 ; i < Image -> Depth ; i++, Data += Modulo * Image -> Height)
		BitMap -> Planes[i] = Data;
}

	/* RecolourBitMap():
	 *
	 *	Remap a BitMap to use a different colour selection.
	 */

STATIC struct BitMap * __regargs
RecolourBitMap (struct BitMap *Src, UBYTE * Mapping, UBYTE DestDepth, UWORD Width, UWORD Height)
{
	struct BitMap *Dst;

		/* Create the bitmap to hold the remapped data. */

	if(Dst = LocalCreateBitMap(DestDepth,Width,Height))
	{
		struct BitMap *SingleMap;

			/* Create a single bitplane bitmap. */

		if(SingleMap = LocalCreateBitMap(1,Width,Height))
		{
			struct BitMap *FullMap;

				/* Create a dummy bitmap. */

			if(FullMap = (struct BitMap *)AllocVecPooled(sizeof(struct BitMap),MEMF_ANY))
			{
				WORD i,Mask = (1L << Src -> Depth) - 1;

					/* Make the dummy bitmap use the
					 * single bitmap in all planes.
					 */

				InitBitMap(FullMap,DestDepth,Width,Height);

				for(i = 0 ; i < DestDepth ; i++)
					FullMap -> Planes[i] = SingleMap -> Planes[0];

					/* Clear the destination bitmap. */

				BltBitMap(Dst,0,0,Dst,0,0,Width,Height,MINTERM_ZERO,0xFF,NULL);

					/* Is colour zero to be mapped to a non-zero colour? */

				if(Mapping[0])
				{
						/* Clear the single plane bitmap. */

					BltBitMap(SingleMap,0,0,SingleMap,0,0,Width,Height,MINTERM_ZERO,1,NULL);

						/* Merge all source bitplane data. */

					BltBitMap(Src,0,0,FullMap,0,0,Width,Height,MINTERM_B_OR_C,Mask,NULL);

						/* Invert the single plane bitmap, to give us
						 * the zero colour bitmap we can work with.
						 */

					BltBitMap(SingleMap,0,0,SingleMap,0,0,Width,Height,MINTERM_NOT_C,1,NULL);

						/* Now set all the bits for colour zero. */

					BltBitMap(FullMap,0,0,Dst,0,0,Width,Height,MINTERM_B_OR_C,Mapping[0],NULL);
				}

					/* Run down the colours. */

				for(i = 1 ; i <= Mask ; i++)
				{
						/* Set the single plane bitmap to all 1's. */

					BltBitMap(SingleMap,0,0,SingleMap,0,0,Width,Height,MINTERM_ONE,1,NULL);

						/* Isolate the pixels to match the colour
						 * specified in `i'.
						 */

					BltBitMap(Src,0,0,FullMap,0,0,Width,Height,MINTERM_B_AND_C,i,NULL);

					if(Mask ^ i)
						BltBitMap(Src,0,0,FullMap,0,0,Width,Height,MINTERM_NOT_B_AND_C,Mask ^ i,NULL);

						/* Set the pixels in the destination bitmap,
						 * use the designated colour.
						 */

					BltBitMap(FullMap,0,0,Dst,0,0,Width,Height,MINTERM_B_OR_C,Mapping[i],NULL);
				}

					/* Free the temporary bitmap. */

				FreeVecPooled(FullMap);

					/* Free the single plane bitmap. */

				LocalDeleteBitMap(SingleMap,Width,Height);

					/* Return the result. */

				return(Dst);
			}

			LocalDeleteBitMap(SingleMap,Width,Height);
		}

		LocalDeleteBitMap(Dst,Width,Height);
	}

	return(NULL);
}

	/* ShowAbout():
	 *
	 *	Open a window, draw the `term' logo, show some text
	 *	and wait for user reaction.
	 */

BYTE __regargs
ShowAbout(BYTE Ticks)
{
	struct BitMap		*ImageBitMap = NULL;
	LONG			 ImageWidth,
				 ImageHeight;
	BYTE			 GotRexxMessage = FALSE;
	struct LayoutHandle	*Handle;

	if(IconBase)
	{
		struct DiskObject *Icon;

		if(Icon = GetProgramIcon())
		{
			STATIC UWORD DefaultColours[4] =
			{
				0xAAA,
				0x000,
				0xFFF,
				0x68B
			};

			UBYTE	Mapping[4];
			UWORD	Colour1,Colour2;
			WORD	ChannelDistance;
			LONG	Distance,BestDistance,BestIndex,Depth,Count,i,j;
			BOOLEAN	Duplicates = FALSE;

			if(Kick30)
				Depth = GetBitMapAttr(Window -> RPort -> BitMap,BMA_DEPTH);
			else
				Depth = Window -> RPort -> BitMap -> Depth;

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

			if(Count > (1L << Depth))
				Count = 1L << Depth;

			if(Count >= 4)
			{
				for(i = 0 ; i < 4 ; i++)
				{
					Colour2 = DefaultColours[i];

					BestDistance	= 3 * 15 * 15;
					BestIndex	= 0;

					for(j = 0 ; j < Count ; j++)
					{
						Colour1 = GetRGB4(Window -> WScreen -> ViewPort . ColorMap,j);

						ChannelDistance = ((WORD)((Colour1 >> 8) & 0xF)) - ((WORD)((Colour2 >> 8) & 0xF));

						Distance = ChannelDistance * ChannelDistance;

						ChannelDistance = ((WORD)((Colour1 >> 4) & 0xF)) - ((WORD)((Colour2 >> 4) & 0xF));

						Distance += ChannelDistance * ChannelDistance;

						ChannelDistance = ((WORD)(Colour1 & 0xF)) - ((WORD)(Colour2 & 0xF));

						Distance += ChannelDistance * ChannelDistance;

						if(Distance < BestDistance)
						{
							BestDistance	= Distance;
							BestIndex	= j;
						}
					}

					Mapping[i] = BestIndex;
				}

				for(i = 0 ; !Duplicates && i < 4 ; i++)
				{
					for(j = i + 1 ; !Duplicates && j < 4 ; j++)
						Duplicates = (Mapping[i] == Mapping[j]);
				}

				if(!Duplicates)
				{
					struct BitMap	 LocalBitMap;
					struct Image	*Image;

					Image = Icon -> do_Gadget . GadgetRender;

					if(Image -> Depth == 2)
					{
						CreateBitMapFromImage(Image,&LocalBitMap);

						if(ImageBitMap = RecolourBitMap(&LocalBitMap,Mapping,Depth,Image -> Width,Image -> Height))
						{
							ImageWidth	= Image -> Width;
							ImageHeight	= Image -> Height;
						}
					}
				}
			}

			FreeDiskObject(Icon);
		}
	}

	if(Handle = LT_CreateHandleTags(Window -> WScreen,
		LH_LocaleHook,	&LocaleHook,
		LH_ExactClone,	TRUE,
	TAG_DONE))
	{
		STRPTR		 AboutLines[3],
				 RequestLines[4],
				 StandardMail[4],
				 ElectronicMail[2];
		struct Window	*Window;
		WORD		 i;

		for(i = 0 ; i < 2 ; i++)
			AboutLines[i] = LocaleString(MSG_TERMINFO_INFOTEXT1_TXT + i);

		AboutLines[i] = NULL;

		for(i = 0 ; i < 3 ; i++)
			RequestLines[i] = LocaleString(MSG_TERMINFO_INFOTEXT4_TXT + i);

		RequestLines[i] = NULL;

		for(i = 0 ; i < 3 ; i++)
			StandardMail[i] = LocaleString(MSG_TERMINFO_INFOTEXT10_TXT + i);

		StandardMail[i] = NULL;

		for(i = 0 ; i < 1 ; i++)
			ElectronicMail[i] = LocaleString(MSG_TERMINFO_INFOTEXT16_TXT + i);

		ElectronicMail[i] = NULL;

		LT_New(Handle,
			LA_Type,	VERTICAL_KIND,
		TAG_DONE);
		{
			LT_New(Handle,
				LA_Type,	VERTICAL_KIND,
				LA_LabelText,	TermName,
			TAG_DONE);
			{
				if(ImageBitMap)
				{
					LT_New(Handle,
						LA_Type,	VERTICAL_KIND,
					TAG_DONE);
					{
						LT_New(Handle,
							LA_Type,		FRAME_KIND,
							LAFR_InnerWidth,	ImageWidth,
							LAFR_InnerHeight,	ImageHeight,
							LA_DrawBox,		FALSE,
							LA_ID,			GAD_FRAME,
						TAG_DONE);

						LT_EndGroup(Handle);
					}
				}

				LT_New(Handle,
					LA_Type,	VERTICAL_KIND,
				TAG_DONE);
				{
					LT_New(Handle,
						LA_Type,	BOX_KIND,
						LA_Chars,	56,
						LABX_Lines,	AboutLines,
						LABX_AlignText,	ALIGNTEXT_CENTERED,
						LABX_DrawBox,	FALSE,
					TAG_DONE);

					LT_EndGroup(Handle);
				}

				LT_EndGroup(Handle);
			}

			LT_New(Handle,
				LA_Type,	VERTICAL_KIND,
				LA_LabelID,	MSG_V36_1030,
			TAG_DONE);
			{
				LT_New(Handle,
					LA_Type,	VERTICAL_KIND,
				TAG_DONE);
				{
					LT_New(Handle,
						LA_Type,	BOX_KIND,
						LA_Chars,	56,
						LABX_Lines,	RequestLines,
						LABX_AlignText,	ALIGNTEXT_CENTERED,
						LABX_DrawBox,	FALSE,
					TAG_DONE);

					LT_EndGroup(Handle);
				}

				LT_New(Handle,
					LA_Type,	VERTICAL_KIND,
					LA_LabelID,	MSG_V36_1031,
				TAG_DONE);
				{
					LT_New(Handle,
						LA_Type,	BOX_KIND,
						LA_Chars,	56,
						LABX_Lines,	StandardMail,
						LABX_AlignText,	ALIGNTEXT_CENTERED,
						LABX_DrawBox,	FALSE,
					TAG_DONE);

					LT_EndGroup(Handle);
				}

				LT_New(Handle,
					LA_Type,	VERTICAL_KIND,
					LA_LabelID,	MSG_V36_1032,
				TAG_DONE);
				{
					LT_New(Handle,
						LA_Type,	BOX_KIND,
						LA_Chars,	56,
						LABX_Lines,	ElectronicMail,
						LABX_AlignText,	ALIGNTEXT_CENTERED,
						LABX_DrawBox,	FALSE,
					TAG_DONE);

					LT_EndGroup(Handle);
				}

				LT_EndGroup(Handle);
			}

			if(!Ticks)
			{
				LT_New(Handle,
					LA_Type,VERTICAL_KIND,
				TAG_DONE);
				{
					LT_New(Handle,LA_Type,XBAR_KIND,LAXB_FullSize,TRUE,TAG_DONE);

					LT_New(Handle,
						LA_Type,	BUTTON_KIND,
						LA_LabelID,	MSG_V36_1033,
						LA_ID,		GAD_BUTTON,
						LABT_ReturnKey,	TRUE,
						LABT_ExtraFat,	TRUE,
					TAG_DONE);

					LT_EndGroup(Handle);
				}
			}

			LT_EndGroup(Handle);
		}

		if(!Ticks)
		{
			Window = LT_Layout(Handle,LocaleString(MSG_V36_1034),NULL,0,0,IDCMP_CLOSEWINDOW,0,
				LAWN_HelpHook,		&GuideHook,
				LAWN_MaxPen,		0,
				WA_DepthGadget,		TRUE,
				WA_CloseGadget,		TRUE,
				WA_DragBar,		TRUE,
				WA_RMBTrap,		TRUE,
				WA_Activate,		TRUE,
			TAG_DONE);
		}
		else
		{
			Window = LT_Layout(Handle,NULL,NULL,0,0,IDCMP_RAWKEY | IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_INTUITICKS,0,
				LAWN_HelpHook,		&GuideHook,
				WA_RMBTrap,		TRUE,
				WA_Activate,		TRUE,
				WA_ReportMouse,		TRUE,
				WA_GimmeZeroZero,	TRUE,
			TAG_DONE);
		}

		if(Window)
		{
			struct IntuiMessage	*Message;
			BOOLEAN			 Done = FALSE;
			ULONG			 MsgClass,
						 MsgQualifier;
			UWORD			 MsgCode;
			struct Gadget		*MsgGadget;
			ULONG			 Signals;
			LONG			 TickCount = 0;

			if(ImageBitMap)
			{
				LONG Left,Top;

				LT_GetAttributes(Handle,GAD_FRAME,
					LA_Left,	&Left,
					LA_Top,		&Top,
				TAG_DONE);

				BltBitMapRastPort(ImageBitMap,0,0,Window -> RPort,Left,Top,ImageWidth,ImageHeight,MINTERM_COPY);
			}

			while(Message = GT_GetIMsg(Window -> UserPort))
				GT_ReplyIMsg(Message);

			if(!Ticks)
			{
				GuideContext(CONTEXT_COMMAND);

				PushWindow(Window);
			}
			else
				Say(LocaleString(MSG_TERMINFO_WELCOME_TO_TERM_TXT));

			do
			{
				Signals = Wait(PORTMASK(Window -> UserPort) | SIG_BREAK | SIG_REXX);

				if(Signals & SIG_BREAK)
					break;

				if(Ticks)
				{
					if(Signals & SIG_REXX)
					{
						GotRexxMessage = TRUE;

						break;
					}
				}

				while(Message = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
				{
					MsgClass	= Message -> Class;
					MsgQualifier	= Message -> Qualifier;
					MsgCode		= Message -> Code;
					MsgGadget	= (struct Gadget *)Message -> IAddress;

					GT_ReplyIMsg(Message);

					if(Ticks)
					{
						if(MsgClass == IDCMP_INTUITICKS && TickCount++ >= 50)
							Done = TRUE;

						if((MsgClass == IDCMP_RAWKEY || MsgClass == IDCMP_MOUSEBUTTONS) && !(MsgCode & IECODE_UP_PREFIX))
							Done = TRUE;

						if(MsgClass == IDCMP_MOUSEMOVE)
							Done = TRUE;
					}
					else
					{
						LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);

						if(MsgClass == IDCMP_CLOSEWINDOW || MsgClass == IDCMP_GADGETUP)
							Done = TRUE;
					}
				}
			}
			while(!Done);

			if(!Ticks)
				PopWindow();
		}

		LT_DeleteHandle(Handle);
	}

	if(ImageBitMap)
		LocalDeleteBitMap(ImageBitMap,ImageWidth,ImageHeight);

	return(GotRexxMessage);
}
