/*
**	CustomRequest.c
**
**	EasyRequest like custom requester
**
**	Copyright © 1990-1995 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

#include "termGlobal.h"

	/* Pack two words into a long. */

#define PACK_ULONG(a,b)	(((ULONG)(a)) << 16 | b)

	/* Gadget extension. */

struct ButtonInfo
{
	struct Image	*ButtonImage;
	UWORD		 LabelLen,
			 LabelLeft,
			 LabelTop;
};

	/* GetScreenInfo():
	 *
	 *	Obtain the currently visible screen area.
	 */

STATIC VOID __regargs
GetScreenInfo(struct Screen *Screen,WORD *Left,WORD *Top,WORD *Width,WORD *Height)
{
	struct ViewPortExtra	*Extra;
	struct TagItem		 Tags[2] = { VTAG_VIEWPORTEXTRA_GET, NULL, TAG_DONE };

	if(!VideoControl(Screen -> ViewPort . ColorMap,Tags))
		Extra = (struct ViewPortExtra *)Tags[0] . ti_Data;
	else
		Extra = NULL;

	if(!Extra)
		Extra = Screen -> ViewPort . ColorMap -> cm_vpe;

	if(!Extra)
		Extra = (struct ViewPortExtra *)GfxLookUp(&Screen -> ViewPort);

	if(Extra)
	{
		struct Rectangle Clip;

		QueryOverscan(GetVPModeID(&Screen -> ViewPort),&Clip,OSCAN_TEXT);

		*Width	= Extra -> DisplayClip . MaxX - Extra -> DisplayClip . MinX + 1;
		*Height	= Extra -> DisplayClip . MaxY - Extra -> DisplayClip . MinY + 1;

		if(*Width < Clip . MaxX - Clip . MinX + 1)
			*Width = Clip . MaxX - Clip . MinX + 1;

		if(*Height < Clip . MaxY - Clip . MinY + 1)
			*Height = Clip . MaxY - Clip . MinY + 1;
	}
	else
	{
		*Width	= Screen -> Width;
		*Height	= Screen -> Height;
	}

	*Left	= ABS(Screen -> LeftEdge);
	*Top	= ABS(Screen -> TopEdge);

	if(*Left > Screen -> Width || *Left < 0)
		*Left = 0;

	if(*Top > Screen -> Height || *Top < 0)
		*Top = 0;
}

	/* CentreWindow():
	 *
	 *	Centre a window within the visible bounds of
	 *	a screen.
	 */

STATIC VOID __regargs
CentreWindow(struct Screen *Screen,WORD Width,WORD Height,WORD *Left,WORD *Top)
{
	WORD ScreenWidth,ScreenHeight,ScreenLeft,ScreenTop;

	GetScreenInfo(Screen,&ScreenLeft,&ScreenTop,&ScreenWidth,&ScreenHeight);

	*Left	= ScreenLeft + (ScreenWidth - Width) / 2;
	*Top	= ScreenTop + (ScreenHeight - Height) / 2;
}

	/* RenderText():
	 *
	 *	Render the button text.
	 */

STATIC VOID __regargs
RenderText(struct RastPort *RPort,struct GadgetInfo *GadgetInfo,struct Gadget *Gadget,struct ButtonInfo *ButtonInfo)
{
	STRPTR	Label = (STRPTR)Gadget -> GadgetText;
	ULONG	State;
	UWORD	Pen;

		/* Which state is the button in? */

	if(Gadget -> Flags & GFLG_SELECTED)
	{
		State	= IDS_SELECTED;
		Pen	= GadgetInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN];
	}
	else
	{
		State	= IDS_NORMAL;
		Pen	= GadgetInfo -> gi_DrInfo -> dri_Pens[TEXTPEN];
	}

		/* Render the frame. */

	DoMethod(Gadget -> GadgetRender,IM_DRAWFRAME,RPort,PACK_ULONG(Gadget -> LeftEdge,Gadget -> TopEdge),State,GadgetInfo -> gi_DrInfo,PACK_ULONG(Gadget -> Width,Gadget -> Height));

		/* Set the rendering pens. */

	if(IntuitionBase -> LibNode . lib_Version >= 39)
		SetABPenDrMd(RPort,Pen,0,JAM1);
	else
	{
		SetDrMd(RPort,JAM1);
		SetAPen(RPort,Pen);
	}

		/* Render the button label. */

	Move(RPort,Gadget -> LeftEdge + ButtonInfo -> LabelLeft,Gadget -> TopEdge + ButtonInfo -> LabelTop);
	Text(RPort,Label,ButtonInfo -> LabelLen);
}

	/* RenderButton():
	 *
	 *	Render the button label.
	 */

STATIC ULONG __regargs
RenderButton(struct IClass *class,Object *object,struct gpRender *RenderInfo)
{
	RenderText(RenderInfo -> gpr_RPort,RenderInfo -> gpr_GInfo,(struct Gadget *)object,INST_DATA(class,object));

	return(TRUE);
}

	/* FreeButton():
	 *
	 *	Free a button gadget object.
	 */

STATIC ULONG __regargs
FreeButton(struct IClass *class,Object *object,Msg msg)
{
	struct ButtonInfo *ButtonInfo = INST_DATA(class,object);

	if(ButtonInfo -> ButtonImage)
		DisposeObject(ButtonInfo -> ButtonImage);

	return(DoSuperMethodA(class,object,msg));
}

	/* NewButton():
	 *
	 *	Create a new button object.
	 */

STATIC ULONG __regargs
NewButton(struct IClass *class,Object *object,struct opSet *SetMethod)
{
	struct TagItem	*Tag,*TagList;
	struct Gadget	*NewGadget	= NULL;
	struct DrawInfo	*DrawInfo	= NULL;
	STRPTR		 Label		= NULL;

	TagList = SetMethod -> ops_AttrList;

	while(Tag = NextTagItem(&TagList))
	{
		switch(Tag -> ti_Tag)
		{
			case GA_Text:

				Label = (STRPTR)Tag -> ti_Data;
				break;

			case GA_DrawInfo:

				DrawInfo = (struct DrawInfo *)Tag -> ti_Data;
				break;
		}
	}

	if(Label && DrawInfo)
	{
		struct RastPort __aligned RastPort;

		UWORD Width,Height,LabelWidth,LabelHeight,LabelLen;

		LabelLen = strlen(Label);

		InitRastPort(&RastPort);

		SetFont(&RastPort,DrawInfo -> dri_Font);

		LabelWidth	= TextLength(&RastPort,Label,LabelLen);
		LabelHeight	= RastPort . TxHeight;

		Width		= 2 + LabelWidth + (6 * RastPort . TxWidth) / 2;
		Height		= 2 + LabelHeight + RastPort . TxHeight / 2;

		if(Width && Height)
		{
			struct Image *ButtonImage;

				/* Create a button frame. */

			if(ButtonImage = NewObject(NULL,"frameiclass",
				IA_Width,	Width,
				IA_Height,	Height,
			TAG_DONE))
			{
				struct TagItem	*OldTags = SetMethod -> ops_AttrList,
						 NewTags[4];

					/* Add new tag values. */

				NewTags[0] . ti_Tag	= GA_Image;
				NewTags[0] . ti_Data	= (ULONG)ButtonImage;
				NewTags[1] . ti_Tag	= GA_Width;
				NewTags[1] . ti_Data	= (ULONG)Width;
				NewTags[2] . ti_Tag	= GA_Height;
				NewTags[2] . ti_Data	= (ULONG)Height;
				NewTags[3] . ti_Tag	= TAG_MORE;
				NewTags[3] . ti_Data	= (ULONG)OldTags;

				SetMethod -> ops_AttrList = NewTags;

					/* Create new object. */

				if(NewGadget = (struct Gadget *)DoSuperMethodA(class,object,(Msg)SetMethod))
				{
					struct ButtonInfo *ButtonInfo = INST_DATA(class,NewGadget);

					ButtonInfo -> LabelLen	= LabelLen;
					ButtonInfo -> LabelLeft	= (Width - LabelWidth) / 2;
					ButtonInfo -> LabelTop	= RastPort . TxBaseline + (Height - LabelHeight) / 2;

						/* Remember the frame image. */

					ButtonInfo -> ButtonImage = ButtonImage;

						/* Restore the tags. */

					SetMethod -> ops_AttrList = OldTags;
				}
				else
					DisposeObject(ButtonImage);
			}
		}
	}

	return((ULONG)NewGadget);
}

	/* HandleButton():
	 *
	 *	Handle button input.
	 */

STATIC ULONG __regargs
HandleButton(struct IClass *class,Object *object,struct gpInput *InputInfo)
{
	ULONG			 Result		= GMR_MEACTIVE;
	BOOL			 Redraw		= FALSE,
				 Final		= FALSE;
	struct ButtonInfo	*ButtonInfo	= INST_DATA(class,object);
	struct Gadget		*Button		= (struct Gadget *)object;

		/* Only mouse events trigger actions. */

	if(InputInfo -> gpi_IEvent -> ie_Class == IECLASS_RAWMOUSE)
	{
			/* Selection cancelled or no command available? */

		if(InputInfo -> gpi_IEvent -> ie_Code == MENUDOWN)
		{
			if(Button -> Flags & GFLG_SELECTED)
			{
				Button -> Flags &= ~GFLG_SELECTED;

				Redraw = TRUE;
			}

			Result = GMR_NOREUSE;

				/* No further actions, please. */

			Final = TRUE;
		}
		else
		{
				/* Select button released? */

			if(InputInfo -> gpi_IEvent -> ie_Code == SELECTUP)
			{
				if(DoMethod((Object *)ButtonInfo -> ButtonImage,IM_HITFRAME,PACK_ULONG(InputInfo -> gpi_Mouse . X,InputInfo -> gpi_Mouse . Y),PACK_ULONG(Button -> Width,Button -> Height)))
				{
					if(Button -> Flags & GFLG_SELECTED)
					{
						*InputInfo -> gpi_Termination = 0;

						Button -> Flags &= ~GFLG_SELECTED;

						Redraw = TRUE;
					}
					else
						*InputInfo -> gpi_Termination = 1;

					Result = GMR_REUSE | GMR_VERIFY;
				}
				else
					Result = GMR_NOREUSE;

					/* No further actions, please. */

				Final = TRUE;
			}
		}
	}
		/* Change highlighting mode? */

	if(!Final)
	{
			/* Hit inside the boundaries? */

		if(DoMethod((Object *)ButtonInfo -> ButtonImage,IM_HITFRAME,PACK_ULONG(InputInfo -> gpi_Mouse . X,InputInfo -> gpi_Mouse . Y),PACK_ULONG(Button -> Width,Button -> Height)))
		{
			if(!(Button -> Flags & GFLG_SELECTED))
			{
				Button -> Flags |= GFLG_SELECTED;

				Redraw = TRUE;
			}
		}
		else
		{
			if(Button -> Flags & GFLG_SELECTED)
			{
				Button -> Flags &= ~GFLG_SELECTED;

				Redraw = TRUE;
			}
		}
	}

		/* Redraw the object? */

	if(Redraw)
	{
		struct RastPort *RPort;

		if(RPort = ObtainGIRPort(InputInfo -> gpi_GInfo))
		{
			RenderText(RPort,InputInfo -> gpi_GInfo,Button,ButtonInfo);

			ReleaseGIRPort(RPort);
		}
	}

	return(Result);
}

	/* ButtonDispatch():
	 *
	 *	The button gadget class dispatcher.
	 */

STATIC ULONG __saveds __asm
ButtonDispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg)
{
		/* Select the message method. */

	switch(msg -> MethodID)
	{
		case OM_NEW:

			return(NewButton(class,object,(struct opSet *)msg));

		case OM_DISPOSE:

			return(FreeButton(class,object,msg));

		case GM_RENDER:

			return(RenderButton(class,object,(struct gpRender *)msg));

		case GM_HITTEST:

			return(GMR_GADGETHIT);

		case GM_GOINACTIVE:

			return(0);

		case GM_GOACTIVE:

			return(GMR_MEACTIVE);

		case GM_HANDLEINPUT:

			return(HandleButton(class,object,(struct gpInput *)msg));

		default:

			return(DoSuperMethodA(class,object,msg));
	}
}

	/* DeleteButtonClass(VOID):
	 *
	 *	Free private button gadget class.
	 */

STATIC VOID __regargs
DeleteButtonClass(Class *ButtonClass)
{
	if(ButtonClass)
		FreeClass(ButtonClass);
}

	/* CreateButtonClass(VOID):
	 *
	 *	Create private button gadget class.
	 */

STATIC Class *
CreateButtonClass(VOID)
{
	Class *ButtonClass;

	if(ButtonClass = MakeClass(NULL,GADGETCLASS,NULL,sizeof(struct ButtonInfo),0))
	{
		ButtonClass -> cl_Dispatcher . h_Entry = (HOOKFUNC)ButtonDispatch;

		return(ButtonClass);
	}
	else
		return(NULL);
}

	/* DrawDent():
	 *
	 *	Draw a recessed box.
	 */

STATIC VOID __regargs
DrawDent(struct RastPort *RPort,struct DrawInfo *DrawInfo,LONG Left,LONG Top,LONG Width,LONG Height)
{
	SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
	RectFill(RPort,Left + 2,Top + 1,Left + Width - 3,Top + Height - 2);

	SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);
	Move(RPort,Left + 1,Top + 1);
	Draw(RPort,Left + 1,Top + Height - 1);
	Draw(RPort,Left,Top + Height - 1);
	Draw(RPort,Left,Top);
	Draw(RPort,Left + Width - 2,Top);

	SetAPen(RPort,DrawInfo -> dri_Pens[SHINEPEN]);
	Move(RPort,Left + 1,Top + Height - 1);
	Draw(RPort,Left + Width - 1,Top + Height - 1);
	Draw(RPort,Left + Width - 1,Top);
	Draw(RPort,Left + Width - 2,Top + 1);
	Draw(RPort,Left + Width - 2,Top + Height - 2);
}

STATIC VOID
StuffChar(VOID)
{
	__emit(0x16C0);	/* MOVE D0,(A3)+ */
}

STATIC VOID __asm
CountChar(register __a3 LONG *Count,register __d0 UBYTE Char)
{
	if(Char == '\n' || Char == '\0')
		Count[1]++;

	Count[0]++;
}

	/* ShowInfo():
	 *
	 *	Display an EasyRequest like information requester.
	 */

VOID __stdargs
ShowInfo(struct Window *Parent,STRPTR Title,STRPTR Continue,STRPTR FormatString,...)
{
	struct Screen	*Screen,
			*OldFrontScreen;
	ULONG		 IntuiLock;

	if(Parent)
		Screen = Parent -> WScreen;
	else
		Screen = LockPubScreen(NULL);

	IntuiLock = LockIBase(NULL);

	if((OldFrontScreen = IntuitionBase -> FirstScreen) == Screen)
		OldFrontScreen = NULL;

	UnlockIBase(IntuiLock);

	if(Screen)
	{
		struct DrawInfo *DrawInfo;

		if(OldFrontScreen)
			ScreenToFront(Screen);

		if(DrawInfo = GetScreenDrawInfo(Screen))
		{
			Class *ButtonClass;

			if(ButtonClass = CreateButtonClass())
			{
				struct Gadget *Button;

				if(Button = NewObject(ButtonClass,NULL,
					GA_Text,	Continue,
					GA_DrawInfo,	DrawInfo,
					GA_RelVerify,	TRUE,
				TAG_DONE))
				{
					va_list	VarArgs;
					LONG	Information[2];
					STRPTR	Data;

					Information[0] = Information[1] = 0;

					va_start(VarArgs,FormatString);
					RawDoFmt(FormatString,VarArgs,(VOID (*)())CountChar,Information);
					va_end(VarArgs);

					if(Data = (STRPTR)AllocVec(Information[0],MEMF_ANY))
					{
						LONG			i,Lines = Information[1],Start,Len;
						WORD			Width = 0,Height,Left,Top;
						struct IntuiText	IText;
						struct Window		*Window;
						struct TextFont		*Font = DrawInfo -> dri_Font;

						WORD			WindowLeft,WindowTop,
									WindowWidth,WindowHeight,
									ScreenWidth,ScreenHeight,
									ScreenLeft,ScreenTop;

						va_start(VarArgs,FormatString);
						RawDoFmt(FormatString,VarArgs,(VOID (*)())StuffChar,Data);
						va_end(VarArgs);

						memset(&IText,0,sizeof(struct IntuiText));

						IText . ITextFont = Screen -> Font;

						for(i = Start = 0 ; i < Information[0] ; i++)
						{
							if(!Data[i])
							{
								IText . IText = &Data[Start];

								if((Len = IntuiTextLength(&IText)) > Width)
									Width = Len;

								Start = i + 1;
							}
							else
							{
								if(Data[i] == '\n')
								{
									if(Start != i)
									{
										Data[i] = 0;

										IText . IText = &Data[Start];

										Len = IntuiTextLength(&IText);

										Data[i] = '\n';

										if(Len > Width)
											Width = Len;
									}

									Start = i + 1;
								}
							}
						}

						Len = Button -> Width + 2 * Font -> tf_XSize;

						if(Width < Len)
							Width = Len;

						Width	= Screen -> WBorLeft + 4 + 3 * Font -> tf_XSize + Width + Screen -> WBorRight;
						Height	= Screen -> WBorTop + Screen -> Font -> ta_YSize + 1 + Font -> tf_YSize / 2 + (2 + Lines) * Font -> tf_YSize + Button -> Height + Screen -> WBorBottom;

						if(Parent)
						{
							WindowLeft	= Parent -> LeftEdge + Parent -> BorderLeft;
							WindowTop	= Parent -> TopEdge + Parent -> BorderTop;
							WindowWidth	= Parent -> Width - (Parent -> BorderLeft + Parent -> BorderRight);
							WindowHeight	= Parent -> Height - (Parent ->BorderTop + Parent -> BorderBottom);

							if((Left = WindowLeft + (WindowWidth - Width) / 2) < 0)
								Left = 0;

							if((Top = WindowTop + (WindowHeight - Height) / 2) < 0)
								Top = 0;

							GetScreenInfo(Screen,&ScreenLeft,&ScreenTop,&ScreenWidth,&ScreenHeight);

							if(Left < ScreenLeft || Left + Width > ScreenLeft + ScreenWidth)
								Left = -1;

							if(Top < ScreenTop || Top + Height > ScreenTop + ScreenHeight)
								Top = -1;

							if(Top == -1 || Left == -1)
								CentreWindow(Screen,Width,Height,&Left,&Top);
						}
						else
							CentreWindow(Screen,Width,Height,&Left,&Top);

						if(Window = OpenWindowTags(NULL,
							WA_Left,		Left,
							WA_Top,			Top,
							WA_Width,		Width,
							WA_Height,		Height,
							WA_Title,		Title,
							WA_DragBar,		TRUE,
							WA_DepthGadget,		TRUE,
							WA_RMBTrap,		TRUE,
							WA_IDCMP,		IDCMP_GADGETUP | IDCMP_VANILLAKEY | IDCMP_RAWKEY,
							WA_Activate,		TRUE,
							WA_CustomScreen,	Screen,
							WA_NoCareRefresh,	TRUE,
						TAG_DONE))
						{
							struct IntuiMessage	*Message;
							struct RastPort		*RPort = Window -> RPort;
							BOOL			 Terminated	= FALSE,
										 KeyHit		= FALSE;

							if(GfxBase -> LibNode . lib_Version >= 39)
							{
								LONG MaxPen = 0;

								for(i = 0 ; i < DrawInfo -> dri_NumPens ; i++)
								{
									if(DrawInfo -> dri_Pens[i] > MaxPen)
										MaxPen = DrawInfo -> dri_Pens[i];
								}

								SetMaxPen(Window -> RPort,MaxPen);
							}

							SetFont(RPort,Font);

							if(GfxBase -> LibNode . lib_Version >= 39)
								SetABPenDrMd(RPort,DrawInfo -> dri_Pens[SHINEPEN],DrawInfo -> dri_Pens[BACKGROUNDPEN],JAM2);
							else
							{
								SetAPen(RPort,DrawInfo -> dri_Pens[SHINEPEN]);
								SetBPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
								SetDrMd(RPort,JAM2);
							}

							LockLayerRom(Window -> RPort -> Layer);

							SetAfPt(RPort,(UWORD *)&Crosshatch,1);
							RectFill(RPort,Window -> BorderLeft,Window -> BorderTop,Window -> Width - (Window -> BorderRight + 1),Window -> Height - (Window -> BorderBottom + 1));
							SetAfPt(RPort,NULL,0);

							Left	= Window -> BorderLeft + RPort -> Font -> tf_XSize;
							Top	= Window -> BorderTop + RPort -> Font -> tf_YSize / 2;
							Width	= Window -> Width - (Window -> BorderRight + 2 * RPort -> Font -> tf_XSize + Window -> BorderLeft);
							Height	= (1 + Lines) * RPort -> Font -> tf_YSize;

							SetDrMd(RPort,JAM1);

							DrawDent(RPort,DrawInfo,Left,Top,Width,Height);

							SetAttrs(Button,
								GA_Left,	(Window -> Width - Button -> Width) / 2,
								GA_Top,		Window -> BorderTop + Font -> tf_YSize / 2 + (1 + Lines) * Font -> tf_YSize + (Window -> Height - (Window -> BorderTop + Font -> tf_YSize / 2 + (1 + Lines) * Font -> tf_YSize + Window -> BorderBottom) - Button -> Height) / 2,
							TAG_DONE);

							UnlockLayerRom(Window -> RPort -> Layer);

							AddGadget(Window,Button,(UWORD)~0);
							RefreshGList(Button,Window,NULL,1);

							LockLayerRom(Window -> RPort -> Layer);

							SetAPen(RPort,DrawInfo -> dri_Pens[TEXTPEN]);

							Top = Window -> BorderTop + Font -> tf_YSize + Font -> tf_Baseline;

							for(i = Start = 0 ; i < Information[0] ; i++)
							{
								if(!Data[i])
								{
									Move(RPort,(Window -> Width - TextLength(RPort,&Data[Start],strlen(&Data[Start]))) / 2,Top);
									Text(RPort,&Data[Start],strlen(&Data[Start]));

									Top += Font -> tf_YSize;
								}
								else
								{
									if(Data[i] == '\n')
									{
										if(Start != i)
										{
											Data[i] = 0;

											Move(RPort,(Window -> Width - TextLength(RPort,&Data[Start],strlen(&Data[Start]))) / 2,Top);
											Text(RPort,&Data[Start],strlen(&Data[Start]));
										}

										Top += Font -> tf_YSize;

										Start = i + 1;
									}
								}
							}

							UnlockLayerRom(Window -> RPort -> Layer);

							do
							{
								WaitPort(Window -> UserPort);

								while(Message = (struct IntuiMessage *)GetMsg(Window -> UserPort))
								{
									if(Message -> Class == IDCMP_GADGETUP)
										Terminated = TRUE;

									if(Message -> Class == IDCMP_VANILLAKEY)
									{
										if(Message -> Code == '\33' || Message -> Code == '\r')
											KeyHit = Terminated = TRUE;
									}

									if(Message -> Class == IDCMP_RAWKEY)
									{
										UWORD Code = Message -> Code;

										ReplyMsg((struct Message *)Message);

										if(Code == HELP_CODE)
											GuideDisplay(CONTEXT_MAIN);
									}
									else
										ReplyMsg((struct Message *)Message);
								}
							}
							while(!Terminated);

							if(KeyHit)
							{
								SetAttrs(Button,GA_Selected,TRUE,TAG_DONE);
								RefreshGList(Button,Window,NULL,1);

								WaitTime(0,80000);

								SetAttrs(Button,GA_Selected,FALSE,TAG_DONE);
								RefreshGList(Button,Window,NULL,1);
							}

							CloseWindow(Window);
						}

						FreeVec(Data);
					}

					DisposeObject(Button);
				}

				DeleteButtonClass(ButtonClass);
			}

			FreeScreenDrawInfo(Screen,DrawInfo);
		}

		if(!Parent)
			UnlockPubScreen(NULL,Screen);
	}

	if(OldFrontScreen)
	{
		struct Screen *NewFrontScreen = NULL,*Screen;

		Forbid();

		IntuiLock = LockIBase(NULL);

		Screen = IntuitionBase -> FirstScreen;

		while(Screen)
		{
			if(Screen == OldFrontScreen)
			{
				NewFrontScreen = Screen;

				break;
			}
			else
				Screen = Screen -> NextScreen;
		}

		UnlockIBase(IntuiLock);

		if(NewFrontScreen)
			ScreenToFront(NewFrontScreen);

		Permit();
	}
}
