/*
**	termInfo.c
**
**	Support routines for the `About' window.
**
**	Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
**		All Rights Reserved
*/

#include "termGlobal.h"

	/* The number of text strings to display. */

#define NUM_STRINGS	16

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

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

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

		FreeVec(BitMap);
	}
}

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

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

	if(BitMap = (struct BitMap *)AllocVec(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);

		DeleteBitMap(BitMap,Width,Height);
	}

	return(NULL);
}

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

VOID __regargs
CreateBitMapFromImage(struct Image *Image,struct BitMap *BitMap)
{
	PLANEPTR	Data	= (PLANEPTR)Image -> ImageData;
	UWORD		Modulo	= (((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.
	 */

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 = CreateBitMap(DestDepth,Width,Height))
	{
		struct BitMap *SingleMap;

			/* Create a single bitplane bitmap. */

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

				/* Create a dummy bitmap. */

			if(FullMap = (struct BitMap *)AllocVec(sizeof(struct BitMap),MEMF_ANY))
			{
				WORD i;

					/* 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);

					/* Run down the colours. */

				for(i = 0 ; i < (1 << Src -> Depth) - 1 ; 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);
					BltBitMap(Src,0,0,FullMap,0,0,Width,Height,MINTERM_NOT_B_AND_C,0xFF ^ 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. */

				FreeVec(FullMap);

					/* Free the single plane bitmap. */

				DeleteBitMap(SingleMap,Width,Height);

					/* Return the result. */

				return(Dst);
			}

			DeleteBitMap(SingleMap,Width,Height);
		}

		DeleteBitMap(Dst,Width,Height);
	}

	return(NULL);
}

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

BYTE
ShowInfo(BYTE Ticks)
{
	struct Window		*InfoWindow;
	LONG			 i,Length,MaxWidth,Offset;
	BYTE			 GotRexxMessage = FALSE;
	struct DiskObject	*Icon;
	LONG			 Height,
				 Width;
	struct Image		*Image;
	struct BitMap		 ImageBitMap,
				*RenderBitMap,
				*TempBitMap = NULL;

	SZ_SizeSetup(Window -> WScreen,&UserFont,TRUE);

	if(IconBase)
		Icon = GetProgramIcon();
	else
		Icon = NULL;

	Offset = Window -> WScreen -> WBorTop + INTERHEIGHT;

	Height = Window -> WScreen -> WBorTop + INTERHEIGHT + NUM_STRINGS * (UserFontHeight + 1) + INTERHEIGHT + Window -> WScreen -> WBorBottom;

	if(!Ticks)
		Height += SZ_Height(BUTTON_KIND,0,0) + INTERHEIGHT;

		/* Find the longest string. */

	for(i = MaxWidth = 0 ; i < NUM_STRINGS ; i++)
	{
		if((Length = SZ_TextWidth(LocaleString(MSG_TERMINFO_INFOTEXT1_TXT + i))) > MaxWidth)
			MaxWidth = Length;
	}

	if(Icon)
	{
		Image = Icon -> do_Gadget . GadgetRender;

		if(Image -> Height + INTERHEIGHT + Height > Window -> WScreen -> Height || Image -> Depth > Window -> WScreen -> RastPort . BitMap -> Depth)
		{
			FreeDiskObject(Icon);

			Icon = NULL;
		}
		else
		{
			CreateBitMapFromImage(Image,&ImageBitMap);

			if(Image -> Depth == Window -> WScreen -> RastPort . BitMap -> Depth)
				RenderBitMap = &ImageBitMap;
			else
			{
				UBYTE Mapping[4];

				Mapping[0] = DrawInfo -> dri_Pens[BACKGROUNDPEN];
				Mapping[1] = DrawInfo -> dri_Pens[SHADOWPEN];
				Mapping[2] = DrawInfo -> dri_Pens[SHINEPEN];
				Mapping[3] = DrawInfo -> dri_Pens[FILLPEN];

				if(TempBitMap = RecolourBitMap(&ImageBitMap,Mapping,Window -> WScreen -> RastPort . BitMap -> Depth,Image -> Width,Image -> Height))
					RenderBitMap = TempBitMap;
				else
					RenderBitMap = NULL;
			}

			if(RenderBitMap)
			{
				if(Image -> Width > MaxWidth)
					MaxWidth = Image -> Width;

				Offset += Image -> Height + INTERHEIGHT;

				Height += Image -> Height + INTERHEIGHT;
			}
			else
			{
				FreeDiskObject(Icon);

				Icon = NULL;
			}
		}
	}

	Width = Window -> WScreen -> WBorLeft + INTERWIDTH + MaxWidth + INTERWIDTH + Window -> WScreen -> WBorRight;

		/* Open the window. */

	if(InfoWindow = OpenWindowTags(NULL,
		WA_Left,		GetScreenLeft(Window) + ((Width < GetScreenWidth(Window)) ? (GetScreenWidth(Window) - Width) / 2 : 0),
		WA_Top,			GetScreenTop(Window) + ((Height < GetScreenHeight(Window)) ? (GetScreenHeight(Window) - Height) / 2 : 0),
		WA_Width,		Width,
		WA_Height,		Height,
		WA_IDCMP,		IDCMP_RAWKEY | IDCMP_VANILLAKEY | IDCMP_RAWKEY | IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_INTUITICKS | IDCMP_INACTIVEWINDOW | BUTTONIDCMP,
		WA_ReportMouse,		TRUE,
		WA_Activate,		TRUE,
		WA_RMBTrap,		TRUE,
		WA_SmartRefresh,	TRUE,
		WA_GimmeZeroZero,	TRUE,
		WA_CustomScreen,	Window -> WScreen,
	TAG_DONE))
	{
		struct Gadget		*GadgetList	= NULL,
					*Gadget		= NULL;

		if(!Ticks)
		{
			if(Gadget = CreateContext(&GadgetList))
			{
				struct NewGadget NewGadget;

				memset(&NewGadget,0,sizeof(struct NewGadget));

				NewGadget . ng_Width		= SZ_Width(BUTTON_KIND,LocaleString(MSG_TERMINFO_CONTINUE_TXT),0,NULL);
				NewGadget . ng_Height		= SZ_Height(BUTTON_KIND,0,0);
				NewGadget . ng_GadgetText	= LocaleString(MSG_TERMINFO_CONTINUE_TXT);
				NewGadget . ng_TextAttr		= &UserFont;
				NewGadget . ng_VisualInfo	= VisualInfo;
				NewGadget . ng_GadgetID		= 0;
				NewGadget . ng_Flags		= NULL;
				NewGadget . ng_LeftEdge		= (InfoWindow -> Width - NewGadget . ng_Width) / 2;
				NewGadget . ng_TopEdge		= InfoWindow -> Height - (Window -> WScreen -> WBorBottom + INTERHEIGHT + NewGadget . ng_Height);

				if(Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
					GT_Underscore,	'_',
				TAG_DONE))
				{
					AddGList(InfoWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
					RefreshGList(GadgetList,InfoWindow,NULL,(UWORD)-1);
					GT_RefreshWindow(InfoWindow,NULL);
				}
			}
		}

		if(Gadget || Ticks)
		{
			struct RastPort		*IPort;
			LONG			 Left,Top;

			struct IntuiMessage	*Massage;
			BYTE			 Terminated = FALSE;

			BYTE			 FgPen,BgPen;
			LONG			 TickCount = 0;
			ULONG			 SignalSet;

			UBYTE			 TheKey,
						*Button;
			WORD			 Len;

			SetFont(InfoWindow -> RPort,UserTextFont);

			Button = LocaleString(MSG_TERMINFO_CONTINUE_TXT);

			while(*Button)
			{
				if(*Button++ == '_')
				{
					TheKey = ToUpper(*Button);

					break;
				}
			}

				/* Adapt the rendering pens accordingly. */

			FgPen = DrawInfo -> dri_Pens[SHINEPEN];
			BgPen = DrawInfo -> dri_Pens[SHADOWPEN];

			if(UseMasking)
			{
				if(FgPen == BgPen)
					BgPen = DrawInfo -> dri_Pens[BACKGROUNDPEN];
			}

				/* Just a shortcut. */

			IPort = InfoWindow -> RPort;

				/* Set up rendering modes. */

			SetDrMd(IPort,JAM1);

				/* Draw the icon if any. */

			if(Icon)
				BltBitMapRastPort(RenderBitMap,0,0,IPort,(InfoWindow -> Width - Image -> Width) / 2 - Image -> LeftEdge,Window -> WScreen -> WBorTop + INTERHEIGHT - Image -> TopEdge,Image -> Width,Image -> Height,MINTERM_COPY);

				/* Determine first line. */

			Top = Offset + UserFontBase;

				/* Walk down the text list. */

			for(i = 0 ; i < NUM_STRINGS ; i++)
			{
					/* Can we print this line? */

				if(Len = strlen(LocaleString(MSG_TERMINFO_INFOTEXT1_TXT + i)))
				{
					Length = SZ_TextWidth(LocaleString(MSG_TERMINFO_INFOTEXT1_TXT + i));

						/* Centre it. */

					Left = (InfoWindow -> GZZWidth - Length) / 2;

						/* Draw the shadow. */

					if(FgPen != BgPen)
					{
						SetAPen(IPort,BgPen);
						Move(IPort,Left + 1,Top + 1);
						Text(IPort,LocaleString(MSG_TERMINFO_INFOTEXT1_TXT + i),Len);
					}

						/* Draw the bright part. */

					SetAPen(IPort,FgPen);
					Move(IPort,Left,Top);
					Text(IPort,LocaleString(MSG_TERMINFO_INFOTEXT1_TXT + i),Len);
				}

					/* Jump to next line. */

				Top += UserFontHeight + 1;
			}

				/* Ignore any previously received input. */

			while(Massage = (struct IntuiMessage *)GetMsg(InfoWindow -> UserPort))
				ReplyMsg(Massage);

			if(Ticks)
				Say(LocaleString(MSG_TERMINFO_WELCOME_TO_TERM_TXT));

			ActivateWindow(InfoWindow);

			ClrSignal(SIG_BREAK);

				/* Wait for mouse/key event. */

			while(!Terminated)
			{
				SignalSet = Wait(SIG_REXX | PORTMASK(InfoWindow -> UserPort) | SIG_BREAK);

				if(SignalSet & SIG_BREAK)
					break;

				if(Ticks)
				{
					if(SignalSet & SIG_REXX)
					{
						GotRexxMessage	= TRUE;
						Terminated	= TRUE;
					}
				}

				while(Massage = (struct IntuiMessage *)GetMsg(InfoWindow -> UserPort))
				{
					if(Ticks)
					{
						if(Massage -> Class == IDCMP_INTUITICKS)
						{
							if(TickCount++ == 50)
								Terminated = TRUE;
						}
						else
							Terminated = TRUE;
					}
					else
					{
						if((Massage -> Class == IDCMP_VANILLAKEY && ToUpper(Massage -> Code) == TheKey) || Massage -> Class == IDCMP_GADGETUP)
							Terminated = TRUE;

						if(Massage -> Class == IDCMP_RAWKEY && Massage -> Code == HELP_CODE)
							GuideDisplay(CONTEXT_MAIN);
					}

					ReplyMsg(Massage);
				}
			}

			if(Gadget)
				RemoveGList(InfoWindow,GadgetList,(UWORD)-1);
		}

		FreeGadgets(GadgetList);

			/* Close the window and exit. */

		CloseWindow(InfoWindow);
	}

	if(TempBitMap)
		DeleteBitMap(TempBitMap,Image -> Width,Image -> Height);

	if(Icon)
		FreeDiskObject(Icon);

	return(GotRexxMessage);
}
