/*
**	termInit.c
**
**	Program initialization and shutdown routines
**
**	Copyright © 1990-1994 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

#include "termGlobal.h"
#include "termEmulationProcess.h"

	/* Spread a byte across a long word. */

#define SPREAD(i)	((ULONG)(i) << 24 | (ULONG)(i) << 16 | (ULONG)(i) << 8 | (i))

	/* This variable helps us to remember whether the fast!
	 * macro panel was open or not.
	 */

STATIC BYTE HadFastMacros = FALSE;

	/* Remember whether we did pen allocation or not. */

STATIC BYTE AllocatedPens = FALSE;

	/* DeleteInterleavedBitMap():
	 *
	 *	Delete an interleaved bitmap as allocated by
	 *	CreateInterleavedBitMap().
	 */

STATIC VOID __regargs
DeleteInterleavedBitMap(struct BitMap *SomeBitMap)
{
	WaitBlit();

	FreeVec(SomeBitMap -> Planes[0]);

	FreeVecPooled(SomeBitMap);
}

	/* CreateInterleavedBitMap():
	 *
	 *	With special thanks to Leo Schwab, this routine will create an
	 *	interleaved BitMap structure suitable for optimized blitter
	 *	access.
	 */

STATIC struct BitMap * __regargs
CreateInterleavedBitMap(LONG Width,LONG Height,WORD Depth)
{
		/* A single plane BitMap cannot be interleaved. */

	if(Depth > 1)
	{
		struct BitMap *SomeBitMap;

			/* Allocate space for the bitmap structure. */

		if(SomeBitMap = (struct BitMap *)AllocVecPooled(sizeof(struct BitMap),MEMF_ANY))
		{
				/* Initialize with standard values, so we can check
				 * whether the current system will be able to handle
				 * an interleaved bitmap of the expected size.
				 */

			InitBitMap(SomeBitMap,Depth,Width,Height);

				/* Check for old standard blitter limits. */

			if(Height * Depth > 1024 || SomeBitMap -> BytesPerRow * Depth > 126)
			{
					/* The current space requirements will operate
					 * correctly only on a system equipped with a
					 * Fat Agnus (or successor) chip, let's see
					 * if we can find one.
					 */

				if(GfxBase -> ChipRevBits0 & GFXF_BIG_BLITS)
				{
						/* Unlikely, put still not impossible: check for
						 * Fat Agnus size limits...
						 */

					if(Height * Depth > 32768 || SomeBitMap -> BytesPerRow * Depth > 4096)
					{
						FreeVecPooled(SomeBitMap);

						return(NULL);
					}
				}
				else
				{
						/* Looks like a Big or old (A1000)
						 * Agnus chip.
						 */

					FreeVecPooled(SomeBitMap);

					return(NULL);
				}
			}

				/* Initialize to interleaved BitMap values. */

			InitBitMap(SomeBitMap,1,Width,Height * Depth);

				/* Allocate plane data. */

			if(SomeBitMap -> Planes[0] = (PLANEPTR)AllocVec(SomeBitMap -> BytesPerRow * SomeBitMap -> Rows,MEMF_CHIP))
			{
				PLANEPTR	Base;
				WORD		i,
						Size;

					/* Remember previous data. */

				Base = SomeBitMap -> Planes[0];
				Size = SomeBitMap -> BytesPerRow;

					/* Clear the bitmap. */

				BltBitMap(SomeBitMap,0,0,SomeBitMap,0,0,Width,Height,MINTERM_ZERO,~0,NULL);

					/* Reinitialize. */

				InitBitMap(SomeBitMap,Depth,Width,Height);

					/* Modify for interleaved look. */

				SomeBitMap -> BytesPerRow *= Depth;

					/* Initialize the single planes. */

				for(i = 0 ; i < Depth ; i++)
				{
					SomeBitMap -> Planes[i] = Base;

					Base += Size;
				}

					/* Return the ready bitmap. */

				return(SomeBitMap);
			}

				/* Deallocate memory. */

			FreeVecPooled(SomeBitMap);
		}
	}

		/* Return failure. */

	return(NULL);
}

	/* LoadKeyMap(STRPTR Name):
	 *
	 *	Load a keymap file from disk.
	 */

STATIC struct KeyMap * __regargs
LoadKeyMap(STRPTR Name)
{
	struct KeyMapResource	*KeyMapResource;
	struct KeyMap		*Map = NULL;

		/* Try to get access to the list of currently loaded
		 * keymap files.
		 */

	if(KeyMapResource = (struct KeyMapResource *)OpenResource("keymap.resource"))
	{
		struct KeyMapNode *Node;

			/* Try to find the keymap in the list. */

		Forbid();

		if(Node = (struct KeyMapNode *)FindName(&KeyMapResource -> kr_List,FilePart(Config -> TerminalConfig -> KeyMapFileName)))
			Map = &Node -> kn_KeyMap;

		Permit();
	}

		/* Still no keymap available? */

	if(!Map)
	{
		APTR OldPtr = ThisProcess -> pr_WindowPtr;

			/* Disable DOS requesters. */

		ThisProcess -> pr_WindowPtr = (APTR)-1;

			/* Unload the old keymap code. */

		if(KeySegment)
			UnLoadSeg(KeySegment);

			/* Try to load the keymap from the
			 * name the user entered.
			 */

		if(!(KeySegment = LoadSeg(Config -> TerminalConfig -> KeyMapFileName)))
		{
				/* Second try: load it from
 				 * the standard keymaps drawer.
 				 */

			strcpy(SharedBuffer,"KEYMAPS:");

			if(AddPart(SharedBuffer,FilePart(Config -> TerminalConfig -> KeyMapFileName),MAX_FILENAME_LENGTH))
			{
				if(!(KeySegment = LoadSeg(SharedBuffer)))
				{
					strcpy(SharedBuffer,"Devs:Keymaps");

					if(AddPart(SharedBuffer,FilePart(Config -> TerminalConfig -> KeyMapFileName),MAX_FILENAME_LENGTH))
						KeySegment = LoadSeg(SharedBuffer);
				}
			}
		}

			/* Did we get the keymap file? */

		if(KeySegment)
		{
			struct KeyMapNode *Node = (struct KeyMapNode *)&((ULONG *)BADDR(KeySegment))[1];

			Map = &Node -> kn_KeyMap;
		}

			/* Enable DOS requesters again. */

		ThisProcess -> pr_WindowPtr = OldPtr;
	}
	else
	{
		if(KeySegment)
		{
			UnLoadSeg(KeySegment);

			KeySegment = NULL;
		}
	}

	return(Map);
}

	/* DeleteOffsetTables(VOID):
	 *
	 *	Delete the line multiplication tables.
	 */

STATIC VOID
DeleteOffsetTables(VOID)
{
	if(OffsetXTable)
	{
		FreeVecPooled(OffsetXTable);

		OffsetXTable = NULL;
	}

	if(OffsetYTable)
	{
		FreeVecPooled(OffsetYTable);

		OffsetYTable = NULL;
	}
}

	/* CreateOffsetTables(VOID):
	 *
	 *	Allocate the line multiplication tables.
	 */

STATIC BYTE
CreateOffsetTables(VOID)
{
	LONG	Width	= (Window -> WScreen -> Width  + TextFontWidth)  * 2 / TextFontWidth,
		Height	= (Window -> WScreen -> Height + TextFontHeight) * 2 / TextFontHeight;

	DeleteOffsetTables();

	if(OffsetXTable = (LONG *)AllocVecPooled(Width * sizeof(LONG),MEMF_ANY))
	{
		if(OffsetYTable = (LONG *)AllocVecPooled(Height * sizeof(LONG),MEMF_ANY))
		{
			LONG i,j;

			for(i = j = 0 ; i < Width ; i++, j += TextFontWidth)
				OffsetXTable[i] = j;

			for(i = j = 0 ; i < Height ; i++, j += TextFontHeight)
				OffsetYTable[i] = j;

			return(TRUE);
		}
	}

	DeleteOffsetTables();

	return(FALSE);
}

	/* CopyItemFlags(struct MenuItem *Src,struct MenuItem *Dst):
	 *
	 *	Copy single menu item flags from one menu strip
	 *	to another.
	 */

STATIC VOID __regargs
CopyItemFlags(struct MenuItem *Src,struct MenuItem *Dst)
{
	while(Src && Dst)
	{
		if(Src -> SubItem)
			CopyItemFlags(Src -> SubItem,Dst -> SubItem);

		Dst -> Flags = Src -> Flags;

		Src = Src -> NextItem;
		Dst = Dst -> NextItem;
	}
}

	/* CopyMenuFlags(struct Menu *Src,struct Menu *Dst):
	 *
	 *	Copy menu flags from one menu strip to
	 *	another.
	 */

STATIC VOID __regargs
CopyMenuFlags(struct Menu *Src,struct Menu *Dst)
{
	struct MenuItem *SrcItem,*DstItem;

	while(Src && Dst)
	{
		SrcItem = Src -> FirstItem;
		DstItem = Dst -> FirstItem;

		while(SrcItem && DstItem)
		{
			CopyItemFlags(SrcItem,DstItem);

			SrcItem = SrcItem -> NextItem;
			DstItem = DstItem -> NextItem;
		}

		Src = Src -> NextMenu;
		Dst = Dst -> NextMenu;
	}
}

	/* BuildMenu():
	 *
	 *	Create the menu strip, including quick dial menu.
	 */

STRPTR
BuildMenu()
{
	struct NewMenu	*NewMenu;
	struct Menu	*MenuNew;
	LONG		 PhoneCount = 0,
			 Count = 0,
			 i;

	BlockWindows();

		/* Clear the window menu strips. */

	if(Window)
		ClearMenuStrip(Window);

	if(StatusWindow)
		ClearMenuStrip(StatusWindow);

	if(FastWindow)
		ClearMenuStrip(FastWindow);

		/* Count the number of menu entries in
		 * the base menu.
		 */

	while(TermMenu[Count++] . nm_Type != NM_END);

		/* Add the quick dial entries. */

	if(Phonebook)
	{
		for(i = 0 ; PhoneCount < DIAL_MENU_MAX && i < NumPhoneEntries ; i++)
		{
			if(Phonebook[i] -> Header -> QuickMenu)
				PhoneCount++;
		}
	}

		/* Allocate new menu prototypes. */

	if(NewMenu = (struct NewMenu *)AllocVecPooled((Count + PhoneCount) * sizeof(struct NewMenu),MEMF_ANY | MEMF_CLEAR))
	{
		CopyMem(TermMenu,NewMenu,Count * sizeof(struct NewMenu));

		if(PhoneCount)
		{
			Count--;

			PhoneCount = 0;

			FirstDialMenu = -1;

			for(i = 0 ; PhoneCount < DIAL_MENU_MAX && i < NumPhoneEntries ; i++)
			{
				if(Phonebook[i] -> Header -> QuickMenu)
				{
					NewMenu[Count] . nm_Type	= NM_ITEM;
					NewMenu[Count] . nm_Label	= Phonebook[i] -> Header -> Name;
					NewMenu[Count] . nm_Flags	= CHECKIT;
					NewMenu[Count] . nm_UserData	= (APTR)(DIAL_MENU_LIMIT + i);

					PhoneCount++;
					Count++;

					if(FirstDialMenu == -1)
						FirstDialMenu = DIAL_MENU_LIMIT + i;
				}
			}

			NewMenu[Count] . nm_Type = NM_END;
		}
		else
			NewMenu[Count - 2] . nm_Type = NM_END;

			/* Create the menu strip. */

		if(!(MenuNew = CreateMenus(NewMenu,TAG_DONE)))
		{
			FreeVecPooled(NewMenu);

			goto Simple;
		}

			/* Do the menu layout. */

		if(!LayoutMenus(MenuNew,VisualInfo,
			GTMN_NewLookMenus,	TRUE,
			GTMN_TextAttr,		&UserFont,

			AmigaGlyph ? GTMN_AmigaKey :  TAG_IGNORE, AmigaGlyph,
			CheckGlyph ? GTMN_Checkmark : TAG_IGNORE, CheckGlyph,
		TAG_DONE))
		{
			FreeVecPooled(NewMenu);

			FreeMenus(MenuNew);

			goto Simple;
		}

		FreeVecPooled(NewMenu);
	}
	else
	{
			/* Create the menu strip. */

Simple:		if(!(MenuNew = CreateMenus(TermMenu,TAG_DONE)))
		{
			ReleaseWindows();

			return(LocaleString(MSG_TERMINIT_FAILED_TO_CREATE_MENUS_TXT));
		}

			/* Do the menu layout. */

		if(!LayoutMenus(MenuNew,VisualInfo,
			AmigaGlyph ? GTMN_AmigaKey :  TAG_IGNORE, AmigaGlyph,
			CheckGlyph ? GTMN_Checkmark : TAG_IGNORE, CheckGlyph,

			GTMN_NewLookMenus,	TRUE,
			GTMN_TextAttr,		&UserFont,
		TAG_DONE))
		{
			ReleaseWindows();

			FreeMenus(MenuNew);

			return(LocaleString(MSG_TERMINIT_FAILED_TO_LAYOUT_MENUS_TXT));
		}
	}

	if(Menu)
	{
		CopyMenuFlags(Menu,MenuNew);

		FreeMenus(Menu);
	}

	Menu = MenuNew;

	if(Window)
		SetMenuStrip(Window,Menu);

	if(StatusWindow)
		SetMenuStrip(StatusWindow,Menu);

	if(FastWindow)
		SetMenuStrip(FastWindow,Menu);

	ReleaseWindows();

	return(NULL);
}

	/* PaletteSetup():
	 *
	 *	Set up colour palettes.
	 */

VOID __regargs
PaletteSetup(struct Configuration *SomeConfig)
{
	WORD i;

	if(!SomeConfig)
		SomeConfig = Config;

	CopyMem(SomeConfig -> ScreenConfig -> Colours, NormalColours    ,16 * sizeof(UWORD));
	CopyMem(SomeConfig -> ScreenConfig -> Colours,&NormalColours[16],16 * sizeof(UWORD));

	CopyMem(NormalColours,BlinkColours,32 * sizeof(UWORD));

	switch(SomeConfig -> ScreenConfig -> ColourMode)
	{
		case COLOUR_EIGHT:

			if(SomeConfig -> ScreenConfig -> Blinking)
			{
				for(i = 0 ; i < 8 ; i++)
					BlinkColours[8 + i] = BlinkColours[0];

				PaletteSize = 16;
			}
			else
				PaletteSize = 8;

			break;

		case COLOUR_SIXTEEN:

			if(Window -> WScreen -> RastPort . BitMap -> Depth >= 5 && SomeConfig -> ScreenConfig -> Blinking)
			{
				for(i = 0 ; i < 16 ; i++)
					BlinkColours[16 + i] = BlinkColours[0];

				PaletteSize = 32;
			}
			else
				PaletteSize = 16;

			break;

		case COLOUR_AMIGA:

			BlinkColours[3] = BlinkColours[0];

			PaletteSize = 4;

			break;

		case COLOUR_MONO:

			PaletteSize = 2;
			break;
	}
}

	/* ResetCursorKeys(struct CursorKeys *Keys):
	 *
	 *	Reset cursor key assignments to defaults.
	 */

VOID __regargs
ResetCursorKeys(struct CursorKeys *Keys)
{
	STATIC STRPTR Defaults[4] =
	{
		"\\e[A",
		"\\e[B",
		"\\e[C",
		"\\e[D"
	};

	WORD i,j;

	for(i = 0 ; i < 4 ; i++)
	{
		for(j = 0 ; j < 4 ; j++)
			strcpy(Keys -> Keys[j][i],Defaults[i]);
	}
}

	/* ResetMacroKeys(struct MacroKeys *Keys):
	 *
	 *	Reset the macro key assignments to defaults.
	 */

STATIC VOID __regargs
ResetMacroKeys(struct MacroKeys *Keys)
{
	STATIC STRPTR FunctionKeyCodes[4] =
	{
		"\\eOP",
		"\\eOQ",
		"\\eOR",
		"\\eOS"
	};

	WORD i;

	memset(Keys,0,sizeof(struct MacroKeys));

	for(i = 0 ; i < 4 ; i++)
		strcpy(Keys -> Keys[1][i],FunctionKeyCodes[i]);
}

	/* ScreenSizeStuff():
	 *
	 *	Set up the terminal screen size.
	 */

VOID
ScreenSizeStuff()
{
	ObtainTerminal();

		/* Is this really the built-in emulation? */

	if(Config -> TerminalConfig -> EmulationMode != EMULATION_EXTERNAL)
	{
		LONG	MaxColumns	= WindowWidth / TextFontWidth,
			MaxLines	= WindowHeight / TextFontHeight,
			Columns,
			Lines;

			/* Drop the text area marker. */

		if(Marking)
			DropMarker();

			/* Turn off the cursor. */

		ClearCursor();

			/* Set up the new screen width. */

		if(Config -> TerminalConfig -> NumColumns < 20)
			Columns = MaxColumns;
		else
			Columns = Config -> TerminalConfig -> NumColumns;

			/* Set up the new screen height. */

		if(Config -> TerminalConfig -> NumLines < 20)
			Lines = MaxLines;
		else
			Lines = Config -> TerminalConfig -> NumLines;

			/* More columns than we will be able to display? */

		if(Columns > MaxColumns)
			Columns = MaxColumns;

			/* More lines than we will be able to display? */

		if(Lines > MaxLines)
			Lines = MaxLines;

			/* Set up the central data. */

		LastColumn	= Columns - 1;
		LastLine	= Lines - 1;
		LastPixel	= MUL_X(Columns) - 1;

			/* Are we to clear the margin? */

		if(Columns < MaxColumns || Lines < MaxLines)
		{
				/* Save the rendering attributes. */

			BackupRender();

				/* Set the defaults. */

			SetAPen(RPort,MappedPens[0][0]);

			SetWrMsk(RPort,DepthMask);

				/* Clear remaining columns. */

			if(Columns < MaxColumns)
				ScrollLineRectFill(RPort,MUL_X(LastColumn + 1),0,WindowWidth - 1,WindowHeight - 1);

				/* Clear remaining lines. */

			if(Lines < MaxLines)
				ScrollLineRectFill(RPort,0,MUL_Y(LastLine + 1),WindowWidth - 1,WindowHeight - 1);

				/* Restore rendering attributes. */

			BackupRender();
		}

			/* Truncate illegal cursor position. */

		if(CursorY > LastLine)
			CursorY = LastLine;

		ConFontScaleUpdate();

			/* Truncate illegal cursor position. */

		if(CursorX > LastColumn)
			CursorX = LastColumn;

			/* Reset the cursor position. */

		if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
			CursorX *= 2;
		else
		{
			if(PrivateConfig -> EmulationConfig -> FontScale == SCALE_HALF)
				CursorX /= 2;
		}

			/* Fix scroll region button. */

		if(!RegionSet)
			Bottom = LastLine;

			/* Turn the cursor back on. */

		DrawCursor();
	}

	FixScreenSize = FALSE;

	ReleaseTerminal();
}

	/* PubScreenStuff():
	 *
	 *	This part handles the public screen setup stuff.
	 */

VOID
PubScreenStuff()
{
	if(Screen)
	{
			/* Are we to make our screen public? */

		if(Config -> ScreenConfig -> MakeScreenPublic)
			PubScreenStatus(Screen,NULL);
		else
			PubScreenStatus(Screen,PSNF_PRIVATE);

			/* Are we to `shanghai' Workbench windows? */

		if(Config -> ScreenConfig -> ShanghaiWindows)
		{
			PublicModes |= SHANGHAI;

			SetPubScreenModes(PublicModes);

				/* Make this the default public screen. */

			SetDefaultPubScreen(TermIDString);
		}
		else
		{
			PublicModes &= ~SHANGHAI;

			if(LockPubScreen(DefaultPubScreenName))
			{
				SetDefaultPubScreen(DefaultPubScreenName);

				UnlockPubScreen(DefaultPubScreenName,NULL);
			}
			else
				SetDefaultPubScreen(NULL);

			SetPubScreenModes(PublicModes);
		}
	}

	FixPubScreenMode = FALSE;
}

	/* ConfigSetup():
	 *
	 *	Compare the current configuration with the
	 *	last backup and reset the serial device, terminal,
	 *	etc. if necessary.
	 */

VOID
ConfigSetup()
{
	BYTE RasterWasEnabled = RasterEnabled;

		/* First we will take a look at the configuration
		 * and try to find those parts which have changed
		 * and require the main screen display to be
		 * reopened.
		 */

	if(PrivateConfig -> ScreenConfig -> FontHeight != Config -> ScreenConfig -> FontHeight)
		ResetDisplay = TRUE;

	if(PrivateConfig -> ScreenConfig -> SplitStatus != Config -> ScreenConfig -> SplitStatus)
		ResetDisplay = TRUE;

	if(PrivateConfig -> ScreenConfig -> ShareScreen != Config -> ScreenConfig -> ShareScreen)
		ResetDisplay = TRUE;

	if(PrivateConfig -> ScreenConfig -> Depth != Config -> ScreenConfig -> Depth || PrivateConfig -> ScreenConfig -> OverscanType != Config -> ScreenConfig -> OverscanType)
		ResetDisplay = TRUE;

	if(PrivateConfig -> ScreenConfig -> DisplayWidth != Config -> ScreenConfig -> DisplayWidth || PrivateConfig -> ScreenConfig -> DisplayHeight != Config -> ScreenConfig -> DisplayHeight)
		ResetDisplay = TRUE;

	if(Stricmp(PrivateConfig -> ScreenConfig -> FontName,Config -> ScreenConfig -> FontName))
		ResetDisplay = TRUE;

	if(PrivateConfig -> TerminalConfig -> FontMode != Config -> TerminalConfig -> FontMode)
		ResetDisplay = TRUE;

	if(PrivateConfig -> TerminalConfig -> UseTerminalTask != Config -> TerminalConfig -> UseTerminalTask)
		ResetDisplay = TRUE;

	if(PrivateConfig -> TerminalConfig -> TextFontHeight != Config -> TerminalConfig -> TextFontHeight)
		ResetDisplay = TRUE;

	if(Stricmp(PrivateConfig -> TerminalConfig -> TextFontName,Config -> TerminalConfig -> TextFontName))
		ResetDisplay = TRUE;

	if(PrivateConfig -> ScreenConfig -> DisplayMode != Config -> ScreenConfig -> DisplayMode || PrivateConfig -> ScreenConfig -> ColourMode != Config -> ScreenConfig -> ColourMode)
		ResetDisplay = TRUE;

	if(PrivateConfig -> TerminalConfig -> IBMFontHeight != Config -> TerminalConfig -> IBMFontHeight)
		ResetDisplay = TRUE;

	if(Stricmp(PrivateConfig -> TerminalConfig -> IBMFontName,Config -> TerminalConfig -> IBMFontName))
		ResetDisplay = TRUE;

	if((PrivateConfig -> ScreenConfig -> ColourMode == Config -> ScreenConfig -> ColourMode) && (PrivateConfig -> ScreenConfig -> ColourMode == COLOUR_EIGHT || PrivateConfig -> ScreenConfig -> ColourMode == COLOUR_SIXTEEN))
	{
		if(PrivateConfig -> ScreenConfig -> Blinking != Config -> ScreenConfig -> Blinking)
			ResetDisplay = TRUE;
	}

	if(Kick30)
	{
		if(Config -> ScreenConfig -> UsePens != PrivateConfig -> ScreenConfig -> UsePens || memcmp(Config -> ScreenConfig -> PenArray,PrivateConfig -> ScreenConfig -> PenArray,sizeof(UWORD) * 12))
			ResetDisplay = TRUE;
	}

	if(Config -> ScreenConfig -> Depth != PrivateConfig -> ScreenConfig -> Depth)
		ResetDisplay = TRUE;

	if(PrivateConfig -> ScreenConfig -> FasterLayout != Config -> ScreenConfig -> FasterLayout)
		ResetDisplay = TRUE;

	if(PrivateConfig -> ScreenConfig -> StatusLine != Config -> ScreenConfig -> StatusLine)
		ResetDisplay = TRUE;

	if(PrivateConfig -> ScreenConfig -> TitleBar != Config -> ScreenConfig -> TitleBar)
		ResetDisplay = TRUE;

	if(PrivateConfig -> ScreenConfig -> UseWorkbench != Config -> ScreenConfig -> UseWorkbench)
		ResetDisplay = TRUE;

	if(strcmp(PrivateConfig -> ScreenConfig -> PubScreenName,Config -> ScreenConfig -> PubScreenName) && Config -> ScreenConfig -> UseWorkbench)
		ResetDisplay = TRUE;

		/* Now for the `harmless' actions which do not
		 * require to change the screen or other
		 * rendering data.
		 */

	if(!ResetDisplay)
	{
		if(PrivateConfig -> TerminalConfig -> NumColumns != Config -> TerminalConfig -> NumColumns || PrivateConfig -> TerminalConfig -> NumLines != Config -> TerminalConfig -> NumLines)
		{
			if(Config -> ScreenConfig -> UseWorkbench)
			{
				UWORD	Width,
					Height;

				if(Config -> TerminalConfig -> NumColumns < 20)
					Width = ScreenWidth;
				else
					Width = Window -> BorderLeft + TextFontWidth * Config -> TerminalConfig -> NumColumns + Window -> BorderRight;

				if(Config -> TerminalConfig -> NumLines < 20)
					Height = ScreenHeight;
				else
					Height = Window -> BorderTop + TextFontHeight * Config -> TerminalConfig -> NumLines + Window -> BorderBottom;

				ChangeWindowBox(Window,Window -> LeftEdge,Window -> TopEdge,Width,Height);

				FixScreenSize = TRUE;
			}
			else
				ResetDisplay = TRUE;
		}
	}

	if(PrivateConfig -> ScreenConfig -> MakeScreenPublic != Config -> ScreenConfig -> MakeScreenPublic || PrivateConfig -> ScreenConfig -> ShanghaiWindows != Config -> ScreenConfig -> ShanghaiWindows)
		PubScreenStuff();

	if(PrivateConfig -> ScreenConfig -> ColourMode == Config -> ScreenConfig -> ColourMode && memcmp(PrivateConfig -> ScreenConfig -> Colours,Config -> ScreenConfig -> Colours,sizeof(UWORD) * 16))
	{
		switch(Config -> ScreenConfig -> ColourMode)
		{
			case COLOUR_EIGHT:

				CopyMem(Config -> ScreenConfig -> Colours,ANSIColours,16 * sizeof(UWORD));
				break;

			case COLOUR_SIXTEEN:

				CopyMem(Config -> ScreenConfig -> Colours,EGAColours,16 * sizeof(UWORD));
				break;

			case COLOUR_AMIGA:

				CopyMem(Config -> ScreenConfig -> Colours,DefaultColours,16 * sizeof(UWORD));
				break;

			case COLOUR_MONO:

				CopyMem(Config -> ScreenConfig -> Colours,AtomicColours,16 * sizeof(UWORD));
				break;
		}
	}

		/* Are we to load a new transfer library? */

	if(Config -> TransferConfig -> DefaultLibrary[0] && strcmp(PrivateConfig -> TransferConfig -> DefaultLibrary,Config -> TransferConfig -> DefaultLibrary))
	{
		strcpy(LastXprLibrary,Config -> TransferConfig -> DefaultLibrary);

		ProtocolSetup(FALSE);
	}

		/* No custom keymap this time? */

	if(!Config -> TerminalConfig -> KeyMapFileName[0])
	{
		KeyMap = NULL;

		if(KeySegment)
		{
			UnLoadSeg(KeySegment);

			KeySegment = NULL;
		}
	}
	else
	{
			/* Check whether the keymap name has changed. */

		if(strcmp(PrivateConfig -> TerminalConfig -> KeyMapFileName,Config -> TerminalConfig -> KeyMapFileName))
			KeyMap = LoadKeyMap(Config -> TerminalConfig -> KeyMapFileName);
	}

		/* Are we to load the keyboard macro settings? */

	if(Config -> FileConfig -> MacroFileName[0] && Stricmp(PrivateConfig -> FileConfig -> MacroFileName,Config -> FileConfig -> MacroFileName))
	{
		if(!LoadMacros(Config -> FileConfig -> MacroFileName,MacroKeys))
			ResetMacroKeys(MacroKeys);
		else
			strcpy(LastMacros,Config -> FileConfig -> MacroFileName);
	}

		/* Are we to load the cursor key settings? */

	if(Config -> FileConfig -> CursorFileName[0] && Stricmp(PrivateConfig -> FileConfig -> CursorFileName,Config -> FileConfig -> CursorFileName))
	{
		if(!ReadIFFData(Config -> FileConfig -> CursorFileName,CursorKeys,sizeof(struct CursorKeys),ID_KEYS))
			ResetCursorKeys(CursorKeys);
		else
			strcpy(LastCursorKeys,Config -> FileConfig -> CursorFileName);
	}

		/* Are we to load the translation tables? */

	if(Config -> FileConfig -> TranslationFileName[0] && Stricmp(PrivateConfig -> FileConfig -> TranslationFileName,Config -> FileConfig -> TranslationFileName))
	{
		if(SendTable)
		{
			FreeTranslationTable(SendTable);

			SendTable = NULL;
		}

		if(ReceiveTable)
		{
			FreeTranslationTable(ReceiveTable);

			ReceiveTable = NULL;
		}

		if(SendTable = AllocTranslationTable())
		{
			if(ReceiveTable = AllocTranslationTable())
			{
				if(LoadTranslationTables(Config -> FileConfig -> TranslationFileName,SendTable,ReceiveTable))
				{
					strcpy(LastTranslation,Config -> FileConfig -> TranslationFileName);

					if(IsStandardTable(SendTable) && IsStandardTable(ReceiveTable))
					{
						FreeTranslationTable(SendTable);

						SendTable = NULL;

						FreeTranslationTable(ReceiveTable);

						ReceiveTable = NULL;
					}
				}
				else
				{
					FreeTranslationTable(SendTable);

					SendTable = NULL;

					FreeTranslationTable(ReceiveTable);

					ReceiveTable = NULL;
				}
			}
			else
			{
				FreeTranslationTable(SendTable);

				SendTable = NULL;
			}
		}
	}

		/* Update the text sending functions. */

	SendSetup();

		/* Are we to load the fast macro settings? */

	if(Config -> FileConfig -> FastMacroFileName[0] && Stricmp(PrivateConfig -> FileConfig -> FastMacroFileName,Config -> FileConfig -> FastMacroFileName))
	{
		if(LoadFastMacros(Config -> FileConfig -> FastMacroFileName))
			strcpy(LastFastMacros,Config -> FileConfig -> FastMacroFileName);
	}

		/* Serial configuration needs updating? */

	ReconfigureSerial(Window,NULL);

		/* Are we to open the fast macro panel? */

	if(Config -> MiscConfig -> OpenFastMacroPanel)
		HadFastMacros = TRUE;

		/* Are we to freeze the text buffer? */

	if(!Config -> CaptureConfig -> BufferEnabled)
		BufferFrozen = TRUE;

		/* Now for the actions which require that the
		 * screen stays open.
		 */

	if(!ResetDisplay)
	{
		if(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
		{
			if(PrivateConfig -> TerminalConfig -> EmulationMode != EMULATION_EXTERNAL || (Config -> TerminalConfig -> EmulationFileName[0] && strcmp(PrivateConfig -> TerminalConfig -> EmulationFileName,Config -> TerminalConfig -> EmulationFileName)))
			{
				if(!OpenEmulator(Config -> TerminalConfig -> EmulationFileName))
				{
					Config -> TerminalConfig -> EmulationMode = EMULATION_ANSIVT100;

					ResetDisplay = TRUE;

					RasterEnabled = TRUE;

					MyEasyRequest(Window,LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_EMULATION_LIBRARY_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Config -> TerminalConfig -> EmulationFileName);
				}
				else
					RasterEnabled = FALSE;
			}
		}
		else
		{
			if(XEmulatorBase && PrivateConfig -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
			{
				XEmulatorClearConsole(XEM_IO);

				CloseEmulator();

				RasterEnabled = TRUE;

				ClearCursor();

				Reset();

				DrawCursor();
			}
			else
				RasterEnabled = TRUE;
		}

		if(RasterEnabled != RasterWasEnabled)
			RasterEraseScreen(2);

		if(!Config -> ScreenConfig -> UseWorkbench && !SharedScreen)
		{
			PaletteSetup(Config);

			LoadRGB4(VPort,NormalColours,PaletteSize);
		}

		if(Config -> MiscConfig -> OpenFastMacroPanel && !FastWindow)
			OpenFastWindow();

		PubScreenStuff();

		if(Menu)
		{
			CheckItem(MEN_FREEZE_BUFFER,BufferFrozen);

			if(!XProtocolBase)
				SetTransferMenu(FALSE);
			else
				SetTransferMenu(TRUE);

			SetRasterMenu(RasterEnabled);
		}

		Blocking = FALSE;
	}
	else
	{
			/* Are we no longer to use the external emulator? */

		if(Config -> TerminalConfig -> EmulationMode != EMULATION_EXTERNAL)
		{
			if(XEmulatorBase && PrivateConfig -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
			{
				XEmulatorClearConsole(XEM_IO);

				CloseEmulator();
			}
		}

		RasterEnabled = TRUE;
	}

		/* Change the task priority. */

	SetTaskPri(ThisProcess,(LONG)Config -> MiscConfig -> Priority);

	ConOutputUpdate();

	ConFontScaleUpdate();

	ConProcessUpdate();

		/* Reset the scanner. */

	FlowInit(TRUE);
}

	/* DisplayReset():
	 *
	 *	Reset the entire display if necessary.
	 */

BYTE
DisplayReset()
{
	UBYTE	*Result;
	BYTE	 Success = TRUE;

		/* Delete the display (if possible).
		 * This will go wrong if there
		 * are any visitor windows on our
		 * screen.
		 */

	if(DeleteDisplay())
	{
		if(Result = CreateDisplay(FALSE))
		{
			DeleteDisplay();

			MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Result);

			Success = FALSE;
		}
		else
		{
			BumpWindow(Window);

			PubScreenStuff();

			DisplayReopened = TRUE;
		}
	}
	else
	{
		SaveConfig(PrivateConfig,Config);

		BlockWindows();

		MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LocaleString(MSG_TERMMAIN_CANNOT_CLOSE_SCREEN_YET_TXT));

		ReleaseWindows();

		Success = TRUE;
	}

	ResetDisplay = FALSE;

		/* Prepare for the worst case... */

	if(Success)
		Apocalypse = FALSE;
	else
		MainTerminated = Apocalypse = TRUE;

	return(Success);
}

	/* DeleteDisplay():
	 *
	 *	Free all resources associated with the terminal
	 *	display (tasks, interrupts, screen, window, etc.).
	 */

BYTE
DeleteDisplay()
{
	GuideCleanup();

	if(Screen)
	{
		struct List		*PubScreenList;
		struct PubScreenNode	*ScreenNode;

		PubScreenList = LockPubScreenList();

		for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ)
		{
			if(ScreenNode -> psn_Screen == Screen)
				break;
		}

		if(ScreenNode && ScreenNode -> psn_Node . ln_Succ)
		{
			if(ScreenNode -> psn_VisitorCount)
			{
				UnlockPubScreenList();

				return(FALSE);
			}
			else
			{
				Forbid();

				UnlockPubScreenList();

				PubScreenStatus(Screen,PSNF_PRIVATE);

				Permit();
			}
		}
		else
			UnlockPubScreenList();
	}

	if(SharedScreen)
	{
		struct List		*PubScreenList;
		struct PubScreenNode	*ScreenNode;

		PubScreenList = LockPubScreenList();

		for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ)
		{
			if(ScreenNode -> psn_Screen == SharedScreen)
				break;
		}

		if(ScreenNode && ScreenNode -> psn_Node . ln_Succ)
		{
			if(ScreenNode -> psn_VisitorCount)
			{
				UnlockPubScreenList();

				return(FALSE);
			}
			else
			{
				Forbid();

				UnlockPubScreenList();

				PubScreenStatus(SharedScreen,PSNF_PRIVATE);

				Permit();
			}
		}
		else
			UnlockPubScreenList();
	}

	CloseQueueWindow();

	if(StatusProcess)
	{
		Forbid();

		Signal(StatusProcess,SIG_KILL);

		ClrSignal(SIG_HANDSHAKE);

		Wait(SIG_HANDSHAKE);

		Permit();

		StatusProcess = NULL;
	}

	if(Marking)
		FreeMarker();

	FirstClick	= TRUE;
	HoldClick	= FALSE;

	CloseInfoWindow();

	DeleteReview();

	DeleteEmulationProcess();

	if(Config)
	{
		if(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && XEmulatorBase)
			CloseEmulator();
	}

	DeleteRaster();

	DeleteScale();

	if(TabStops)
	{
		FreeVecPooled(TabStops);

		TabStops = NULL;
	}

	if(ScrollLines)
	{
		FreeVecPooled(ScrollLines);

		ScrollLines = NULL;
	}

	if(Screen)
		ScreenToBack(Screen);

	if(FastWindow)
	{
		HadFastMacros = TRUE;

		CloseFastWindow();
	}
	else
		HadFastMacros = FALSE;

		/* Clean up the menu glyphs. */

	DisposeObject(AmigaGlyph);

	AmigaGlyph = NULL;

	DisposeObject(CheckGlyph);

	CheckGlyph = NULL;

	if(StatusWindow)
	{
		ClearMenuStrip(StatusWindow);
		CloseWindowSafely(StatusWindow);

		StatusWindow = NULL;
	}

	if(DefaultPubScreen)
	{
		UnlockPubScreen(NULL,DefaultPubScreen);

		DefaultPubScreen = NULL;
	}

		/* Remove AppWindow link. */

	if(WorkbenchWindow)
	{
		RemoveAppWindow(WorkbenchWindow);

		WorkbenchWindow = NULL;
	}

		/* Remove AppWindow port and any pending messages. */

	if(WorkbenchPort)
	{
		struct Message *Message;

		while(Message = GetMsg(WorkbenchPort))
			ReplyMsg(Message);

		DeleteMsgPort(WorkbenchPort);

		WorkbenchPort = NULL;
	}

	if(DrawInfo)
	{
			/* Release the rendering pens. */

		FreeScreenDrawInfo(Window -> WScreen,DrawInfo);

		DrawInfo = NULL;
	}

	if(Window)
	{
		if(AllocatedPens && Kick30)
		{
			WORD i;

			ObtainTerminal();

				/* Erase the window contents. We will
				 * want to release any pens we have
				 * allocated and want to avoid nasty
				 * flashing and flickering.
				 */

			SetAPen(RPort,0);

			RectFill(RPort,WindowLeft,WindowTop,WindowLeft + WindowWidth - 1,WindowTop + WindowHeight - 1);

				/* Release any pens we have allocated. */

			for(i = 0 ; i < 16 ; i++)
			{
				if(MappedPens[1][i])
				{
					ReleasePen(VPort -> ColorMap,MappedPens[0][i]);

					MappedPens[0][i] = i;
					MappedPens[1][i] = FALSE;
				}
			}

			AllocatedPens = FALSE;

			ReleaseTerminal();
		}

		if(ClipRegion)
		{
			InstallClipRegion(Window -> WLayer,OldRegion);

			DisposeRegion(ClipRegion);

			ClipRegion = NULL;
		}

		ClearMenuStrip(Window);

		ThisProcess -> pr_WindowPtr = OldWindowPtr;

		PopWindow();

		if(TermPort)
			TermPort -> TopWindow = NULL;

		LT_DeleteWindowLock(Window);

		CloseWindow(Window);

		Window = NULL;

		if(StatusGadget)
			DeleteStatusGadget(StatusGadget);

		StatusGadget = NULL;
	}

	if(Menu)
	{
		FreeMenus(Menu);

		Menu = NULL;
	}

	if(VisualInfo)
	{
		FreeVisualInfo(VisualInfo);

		VisualInfo = NULL;
	}

	DeletePacketWindow(FALSE);

	if(UserTextFont)
	{
		CloseFont(UserTextFont);

		UserTextFont = NULL;
	}

		/* Before we can close screen we will have to
		 * make sure that it is no longer the default
		 * public screen.
		 */

	if(Config)
	{
		if(Config -> ScreenConfig -> ShanghaiWindows)
		{
			if(LockPubScreen(DefaultPubScreenName))
			{
				SetDefaultPubScreen(DefaultPubScreenName);

				UnlockPubScreen(DefaultPubScreenName,NULL);
			}
			else
				SetDefaultPubScreen(NULL);
		}
	}

	if(Screen)
	{
		CloseScreen(Screen);

		Screen = NULL;
	}

	if(SharedScreen)
	{
		CloseScreen(SharedScreen);

		SharedScreen = NULL;
	}

	if(InterleavedBitMap)
	{
		DeleteInterleavedBitMap(InterleavedBitMap);

		InterleavedBitMap = NULL;
	}

	if(GFX)
	{
		CloseFont(GFX);

		GFX = NULL;
	}

	if(TextFont)
	{
		CloseFont(TextFont);

		TextFont = NULL;
	}

	return(TRUE);
}

STATIC VOID __regargs
StatusSizeSetup(struct Screen *Screen,LONG *StatusWidth,LONG *StatusHeight)
{
	SZ_SizeSetup(Screen,&UserFont);

	if(Config -> ScreenConfig -> StatusLine != STATUSLINE_DISABLED)
	{
		if(Config -> ScreenConfig -> StatusLine == STATUSLINE_COMPRESSED)
		{
			*StatusWidth	= 80 * UserFontWidth;
			*StatusHeight	= UserFontHeight;

			if(Config -> ScreenConfig -> SplitStatus)
			{
				*StatusWidth	+= 2;
				*StatusHeight	+= 2;
			}
		}
		else
		{
			LONG	i,Len,Max;
			UWORD	ColumnLeft[4],
				ColumnWidth[4];

			*StatusWidth	= 0;
			*StatusHeight	= SZ_BoxHeight(2);

			ColumnLeft[0] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_STATUS_TXT,MSG_TERMSTATUSDISPLAY_FONT_TXT,-1);
			ColumnLeft[1] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_PROTOCOL_TXT,MSG_TERMSTATUSDISPLAY_TERMINAL_TXT,-1);
			ColumnLeft[2] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_BAUDRATE_TXT,MSG_TERMSTATUSDISPLAY_PARAMETERS_TXT,-1);
			ColumnLeft[3] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_TIME_TXT,MSG_TERMSTATUSDISPLAY_ONLINE_TXT,-1);

			Max = 0;

			for(i = MSG_TERMAUX_READY_TXT ; i <= MSG_TERMAUX_HANG_UP_TXT ; i++)
			{
				if((Len = SZ_BoxWidth(strlen(LocaleString(i)))) > Max)
					Max = Len;
			}

			for(i = MSG_TERMSTATUSDISPLAY_FROZEN_TXT ; i <= MSG_TERMSTATUSDISPLAY_RECORDING_TXT ; i++)
			{
				if((Len = SZ_BoxWidth(strlen(LocaleString(i)))) > Max)
					Max = Len;
			}

			ColumnWidth[0] = Max;

			Max = SZ_BoxWidth(12);

			for(i = MSG_TERMAUX_ANSI_VT102_TXT ; i <= MSG_TERMAUX_HEX_TXT ; i++)
			{
				if((Len = SZ_BoxWidth(strlen(LocaleString(i)))) > Max)
					Max = Len;
			}

			ColumnWidth[1] = Max;

			Max = SZ_BoxWidth(10);

			for(i = MSG_TERMAUX_NONE_TXT ; i <= MSG_TERMAUX_SPACE_TXT ; i++)
			{
				if((Len = SZ_BoxWidth(4 + strlen(LocaleString(i)))) > Max)
					Max = Len;
			}

			ColumnWidth[2] = Max;

			ColumnWidth[3] = SZ_BoxWidth(8);

			for(i = 0 ; i < 4 ; i++)
				*StatusWidth += ColumnWidth[i] + ColumnLeft[i];

			*StatusWidth += 3 * InterWidth;

			if(!Config -> ScreenConfig -> SplitStatus)
				*StatusHeight += 3;
			else
			{
				*StatusWidth	+= 2;
				*StatusHeight	+= 2;
			}
		}
	}
	else
		*StatusHeight = 0;
}

	/* CreateDisplay(BYTE FirstSetup):
	 *
	 *	Open the display and allocate associated data.
	 */

STRPTR __regargs
CreateDisplay(BYTE FirstSetup)
{
	UWORD			Count = 0,i;
	LONG			ErrorCode,Top,Height;
	ULONG			TagArray[9];
	struct Rectangle	DisplayClip;
	BYTE			OpenFailed = FALSE,
				RealDepth;
	STRPTR			Error;
	ULONG			X_DPI,Y_DPI;
	UWORD			PenArray[16];
	LONG			StatusWidth,
				StatusHeight;

	BlockNestCount = 0;

	WeAreBlocking = FALSE;

	SetQueueDiscard(SpecialQueue,FALSE);

	TagDPI[0] . ti_Tag = TAG_DONE;

		/* Don't permit weird settings. */

	if(!Config -> ScreenConfig -> StatusLine || (!Config -> ScreenConfig -> ShareScreen && !Config -> ScreenConfig -> UseWorkbench))
		Config -> ScreenConfig -> SplitStatus = FALSE;

	if(Config -> ScreenConfig -> UseWorkbench || Config -> ScreenConfig -> ShareScreen)
	{
		STRPTR ScreenName = NULL;

		if(Config -> ScreenConfig -> PubScreenName[0])
		{
			struct Screen *SomeScreen;

			if(SomeScreen = LockPubScreen(Config -> ScreenConfig -> PubScreenName))
			{
				UnlockPubScreen(NULL,SomeScreen);

				ScreenName = Config -> ScreenConfig -> PubScreenName;
			}
		}

		if(!(DefaultPubScreen = LockPubScreen(ScreenName)))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_GET_DEFAULT_PUBLIC_SCREEN_TXT));
		else
		{
			GetDPI(GetVPModeID(&DefaultPubScreen -> ViewPort),&X_DPI,&Y_DPI);

				/* gadtools.library v37 objects don't look too pretty
				 * with a proportional-spaced font.
				 */

/*			if(!(DefaultPubScreen -> Font -> ta_Flags & FPF_PROPORTIONAL) || Kick30)*/

			if(TRUE)
			{
				strcpy(UserFontName,DefaultPubScreen -> Font -> ta_Name);

				UserFont . tta_Name	= UserFontName;
				UserFont . tta_YSize	= DefaultPubScreen -> Font -> ta_YSize;
				UserFont . tta_Style	= DefaultPubScreen -> Font -> ta_Style;
				UserFont . tta_Flags	= DefaultPubScreen -> Font -> ta_Flags;
			}
			else
			{
				UnlockPubScreen(NULL,DefaultPubScreen);

				DefaultPubScreen = NULL;

				Config -> ScreenConfig -> UseWorkbench = FALSE;
			}
		}
	}

	if(!Config -> ScreenConfig -> UseWorkbench)
	{
		GetDPI(Config -> ScreenConfig -> DisplayMode,&X_DPI,&Y_DPI);

		strcpy(UserFontName,Config -> ScreenConfig -> FontName);

		UserFont . tta_Name	= UserFontName;
		UserFont . tta_YSize	= Config -> ScreenConfig -> FontHeight;
		UserFont . tta_Style	= FS_NORMAL | FSF_TAGGED;
		UserFont . tta_Flags	= FPF_DESIGNED;
		UserFont . tta_Tags	= TagDPI;

		TagDPI[0] . ti_Tag	 = TA_DeviceDPI;
		TagDPI[0] . ti_Data	 = (X_DPI << 16) | Y_DPI;
		TagDPI[1] . ti_Tag	 = TAG_DONE;
	}

	if(!(UserTextFont = OpenDiskFont(&UserFont)))
	{
		if(Config -> ScreenConfig -> UseWorkbench)
			return(LocaleString(MSG_TERMINIT_UNABLE_TO_OPEN_FONT_TXT));
		else
		{
			strcpy(Config -> ScreenConfig -> FontName,	"topaz.font");
			strcpy(UserFontName,				"topaz.font");

			Config -> ScreenConfig -> FontHeight = 8;

			UserFont . tta_YSize	= Config -> ScreenConfig -> FontHeight;
			UserFont . tta_Style	= FS_NORMAL;
			UserFont . tta_Flags	= FPF_DESIGNED | FPF_ROMFONT;

			if(!(UserTextFont = OpenFont(&UserFont)))
				return(LocaleString(MSG_TERMINIT_UNABLE_TO_OPEN_FONT_TXT));
		}
	}

Reopen:	if(Config -> TerminalConfig -> FontMode != FONT_STANDARD)
	{
		strcpy(TextFontName,Config -> TerminalConfig -> IBMFontName);

		TextAttr . tta_YSize = Config -> TerminalConfig -> IBMFontHeight;
	}
	else
	{
		strcpy(TextFontName,Config -> TerminalConfig -> TextFontName);

		TextAttr . tta_YSize = Config -> TerminalConfig -> TextFontHeight;
	}

	TextAttr . tta_Name	= TextFontName;
	TextAttr . tta_Style	= FS_NORMAL | FSF_TAGGED;
	TextAttr . tta_Flags	= FPF_DESIGNED;
	TextAttr . tta_Tags	= TagDPI;

	if(!(TextFont = OpenDiskFont(&TextAttr)))
	{
		if(Config -> TerminalConfig -> FontMode != FONT_STANDARD)
		{
			Config -> TerminalConfig -> FontMode = FONT_STANDARD;

			goto Reopen;
		}

		strcpy(Config -> TerminalConfig -> TextFontName,	"topaz.font");
		strcpy(TextFontName,					"topaz.font");

		Config -> TerminalConfig -> TextFontHeight = 8;

		TextAttr . tta_YSize	= Config -> TerminalConfig -> TextFontHeight;
		TextAttr . tta_Style	= FS_NORMAL;
		TextAttr . tta_Flags	= FPF_DESIGNED | FPF_ROMFONT;
		TextAttr . tta_Tags	= NULL;

		if(!(TextFont = OpenFont(&TextAttr)))
			return(LocaleString(MSG_TERMINIT_UNABLE_TO_OPEN_TEXT_TXT));
	}

	TextFontHeight	= TextFont -> tf_YSize;
	TextFontWidth	= TextFont -> tf_XSize;
	TextFontBase	= TextFont -> tf_Baseline;

		/* Determine extra font box width for slanted/boldface glyphs. */

	FontRightExtend	= MAX(TextFont -> tf_XSize / 2,TextFont -> tf_BoldSmear);

	CurrentFont = TextFont;

	GFXFont . ta_YSize = Config -> ScreenConfig -> FontHeight;

	if(GFX = (struct TextFont *)OpenDiskFont(&GFXFont))
	{
		if(GFX -> tf_XSize != TextFont -> tf_XSize || GFX -> tf_YSize != TextFont -> tf_YSize)
		{
			CloseFont(GFX);

			GFX = NULL;
		}
	}

	UserFontHeight	= UserTextFont -> tf_YSize;
	UserFontWidth	= UserTextFont -> tf_XSize;
	UserFontBase	= UserTextFont -> tf_Baseline;

	if(Config -> ScreenConfig -> UseWorkbench || Config -> ScreenConfig -> ShareScreen)
	{
		struct TagItem	 SomeTags[7];
		LONG		 FullWidth,
				 Height,Width,
				 Index = 0;
		struct Screen	*LocalScreen = DefaultPubScreen;

		if(Config -> ScreenConfig -> ShareScreen && !Config -> ScreenConfig -> UseWorkbench)
		{
			struct DimensionInfo DimensionInfo;

			if(ModeNotAvailable(Config -> ScreenConfig -> DisplayMode))
				Config -> ScreenConfig -> DisplayMode = GetVPModeID(&DefaultPubScreen -> ViewPort);

			if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Config -> ScreenConfig -> DisplayMode))
			{
				LONG	Depth,ScreenWidth,ScreenHeight;
				UWORD	Pens = (UWORD)~0;

				if(Config -> ScreenConfig -> DisplayWidth && Config -> ScreenConfig -> DisplayHeight)
				{
					ScreenWidth	= Config -> ScreenConfig -> DisplayWidth;
					ScreenHeight	= Config -> ScreenConfig -> DisplayHeight;
				}
				else
				{
					ScreenWidth	= 0;
					ScreenHeight	= 0;
				}

				switch(Config -> ScreenConfig -> ColourMode)
				{
					case COLOUR_EIGHT:

						Depth = 3;
						break;

					case COLOUR_SIXTEEN:

						Depth = 4;
						break;

					case COLOUR_AMIGA:

						Depth = 2;
						break;

					default:

						Depth = 1;
						break;
				}

				if(Depth > DimensionInfo . MaxDepth)
					Depth = DimensionInfo . MaxDepth;

				if(!Kick30 && Depth > 2)
					Depth = 2;

				if(Config -> ScreenConfig -> Depth && Config -> ScreenConfig -> Depth <= DimensionInfo . MaxDepth)
					Depth = Config -> ScreenConfig -> Depth;

#ifdef _M68030
				SPrintf(ScreenTitle,LocaleString(MSG_TERMINIT_SCREENTITLE_TXT),TermName,"'030 ",TermDate,TermIDString);
#else
				SPrintf(ScreenTitle,LocaleString(MSG_TERMINIT_SCREENTITLE_TXT),TermName,"",TermDate,TermIDString);
#endif	/* _M68030 */
				if(SharedScreen = OpenScreenTags(NULL,
					ScreenWidth  ? SA_Width  : TAG_IGNORE,	ScreenWidth,
					ScreenHeight ? SA_Height : TAG_IGNORE,	ScreenHeight,

					SA_Title,	ScreenTitle,
					SA_Depth,	Depth,
					SA_Pens,	&Pens,
					SA_Overscan,	Config -> ScreenConfig -> OverscanType,
					SA_DisplayID,	Config -> ScreenConfig -> DisplayMode,
					SA_Font,	&UserFont,
					SA_AutoScroll,	TRUE,
					SA_ShowTitle,	Config -> ScreenConfig -> TitleBar,
					SA_PubName,	TermIDString,
					SA_Interleaved,	Config -> ScreenConfig -> FasterLayout && Kick30 && Depth > 1,
					SA_SharePens,	TRUE,
				TAG_DONE))
				{
					LocalScreen = SharedScreen;

					if(DefaultPubScreen)
					{
						UnlockPubScreen(NULL,DefaultPubScreen);

						DefaultPubScreen = NULL;
					}

					if(Config -> ScreenConfig -> MakeScreenPublic)
						PubScreenStatus(LocalScreen,NULL);
					else
						PubScreenStatus(LocalScreen,PSNF_PRIVATE);
				}
			}
		}

		if(!SharedScreen)
		{
#ifdef _M68030
			SPrintf(ScreenTitle,"%s '030 (%s)",TermName,TermDate);
#else
			SPrintf(ScreenTitle,"%s (%s)",TermName,TermDate);
#endif	/* _M68030 */

		}

		StatusSizeSetup(LocalScreen,&StatusWidth,&StatusHeight);

		if(LocalScreen -> RastPort . BitMap -> Depth == 1)
			UseMasking = FALSE;
		else
		{
			if(Kick30)
			{
				if(GetBitMapAttr(LocalScreen -> RastPort . BitMap,BMA_FLAGS) & BMF_INTERLEAVED)
					UseMasking = FALSE;
				else
					UseMasking = TRUE;
			}
			else
				UseMasking = TRUE;
		}

		VPort = &LocalScreen -> ViewPort;

			/* Get the current display dimensions. */

		if(VPort -> ColorMap -> cm_vpe)
		{
			struct ViewPortExtra *Extra;

			Extra = VPort -> ColorMap -> cm_vpe;

			ScreenWidth	= Extra -> DisplayClip . MaxX - Extra -> DisplayClip . MinX + 1;
			ScreenHeight	= Extra -> DisplayClip . MaxY - Extra -> DisplayClip . MinY + 1;
		}
		else
		{
			struct ViewPortExtra *Extra;

			if(Extra = (struct ViewPortExtra *)GfxLookUp(VPort))
			{
				ScreenWidth	= Extra -> DisplayClip . MaxX - Extra -> DisplayClip . MinX + 1;
				ScreenHeight	= Extra -> DisplayClip . MaxY - Extra -> DisplayClip . MinY + 1;
			}
			else
			{
				ScreenWidth	= LocalScreen -> Width;
				ScreenHeight	= LocalScreen -> Height;
			}
		}

		DepthMask = (1L << LocalScreen -> RastPort . BitMap -> Depth) - 1;

		switch(Config -> ScreenConfig -> ColourMode)
		{
			case COLOUR_SIXTEEN:

				if(DepthMask < 15)
				{
					if(DepthMask >= 7)
						Config -> ScreenConfig -> ColourMode = COLOUR_EIGHT;
					else
					{
						if(DepthMask >= 3)
							Config -> ScreenConfig -> ColourMode = COLOUR_AMIGA;
						else
							Config -> ScreenConfig -> ColourMode = COLOUR_MONO;
					}
				}

				break;

			case COLOUR_EIGHT:

				if(DepthMask < 7)
				{
					if(DepthMask >= 3)
						Config -> ScreenConfig -> ColourMode = COLOUR_AMIGA;
					else
						Config -> ScreenConfig -> ColourMode = COLOUR_MONO;
				}

				break;

			case COLOUR_AMIGA:

				if(DepthMask < 3)
					Config -> ScreenConfig -> ColourMode = COLOUR_MONO;

				break;
		}

		if(!(DrawInfo = GetScreenDrawInfo(LocalScreen)))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_OBTAIN_SCREEN_DRAWINFO_TXT));

		CreateMenuGlyphs(LocalScreen,DrawInfo,&AmigaGlyph,&CheckGlyph);

		SZ_SizeSetup(LocalScreen,&UserFont);

			/* Obtain visual info (whatever that may be). */

		if(!(VisualInfo = GetVisualInfo(LocalScreen,TAG_DONE)))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_OBTAIN_VISUAL_INFO_TXT));

		if(Config -> ScreenConfig -> StatusLine != STATUSLINE_DISABLED && !Config -> ScreenConfig -> SplitStatus)
		{
			if(!(StatusGadget = (struct Gadget *)CreateStatusGadget(LocalScreen -> Width,42)))
				return(LocaleString(MSG_TERMINIT_FAILED_TO_CREATE_STATUS_GADGET_TXT));
		}

		if(StatusGadget)
			GetAttr(SGA_FullWidth,StatusGadget,(ULONG *)&FullWidth);
		else
			FullWidth = 0;

		if(StatusGadget)
		{
			SomeTags[Index  ] . ti_Tag	= WA_Gadgets;
			SomeTags[Index++] . ti_Data	= (ULONG)StatusGadget;
		}

		if(WindowBox . Left != -1)
		{
			SomeTags[Index  ] . ti_Tag	= WA_Left;
			SomeTags[Index++] . ti_Data	= WindowBox . Left;
			SomeTags[Index  ] . ti_Tag	= WA_Top;
			SomeTags[Index++] . ti_Data	= WindowBox . Top;

			SomeTags[Index  ] . ti_Tag	= WA_Width;
			SomeTags[Index++] . ti_Data	= WindowBox . Width;
			SomeTags[Index  ] . ti_Tag	= WA_Height;
			SomeTags[Index++] . ti_Data	= WindowBox . Height;

			WindowBox . Left = -1;
		}
		else
		{
			if(Config -> TerminalConfig -> NumColumns < 20)
			{
				LONG Width = GetScreenWidth(NULL);

				if(FullWidth && Width < FullWidth)
				{
					SomeTags[Index  ] . ti_Tag	= WA_InnerWidth;
					SomeTags[Index++] . ti_Data	= FullWidth;
				}
				else
				{
					SomeTags[Index  ] . ti_Tag	= WA_Width;
					SomeTags[Index++] . ti_Data	= Width;
				}
			}
			else
			{
				SomeTags[Index  ] . ti_Tag	= WA_InnerWidth;
				SomeTags[Index++] . ti_Data	= Config -> TerminalConfig -> NumColumns * TextFontWidth;
			}

			if(Config -> TerminalConfig -> NumLines < 20)
			{
				SomeTags[Index  ] . ti_Tag	= WA_Height;
				SomeTags[Index++] . ti_Data	= GetScreenHeight(NULL) - (LocalScreen -> BarHeight + 1);
			}
			else
			{
				SomeTags[Index  ] . ti_Tag	= WA_InnerHeight;
				SomeTags[Index++] . ti_Data	= Config -> TerminalConfig -> NumLines * TextFontHeight;
			}

			SomeTags[Index  ] . ti_Tag	= WA_Left;
			SomeTags[Index++] . ti_Data	= GetScreenLeft(NULL);

			SomeTags[Index  ] . ti_Tag	= WA_Top;
			SomeTags[Index++] . ti_Data	= GetScreenTop(NULL) + LocalScreen -> BarHeight + 1;
		}

		SomeTags[Index] . ti_Tag = TAG_DONE;

			/* Open the main window. */

		if(!(Window = OpenWindowTags(NULL,
			WA_MaxHeight,		LocalScreen -> Height,
			WA_MaxWidth,		LocalScreen -> Width,
			WA_SmartRefresh,	TRUE,
			WA_CustomScreen,	LocalScreen,
			WA_NewLookMenus,	TRUE,
			WA_RMBTrap,		TRUE,
			WA_IDCMP,		IDCMP_RAWKEY | IDCMP_INACTIVEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MOUSEMOVE | IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MENUPICK | IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_IDCMPUPDATE,
			WA_DragBar,		TRUE,
			WA_DepthGadget,		TRUE,
			WA_CloseGadget,		TRUE,
			WA_SizeGadget,		TRUE,
			WA_SizeBBottom,		TRUE,
			WA_NoCareRefresh,	TRUE,
			WA_Title,		ScreenTitle,

			AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
			CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,

			TAG_MORE,		SomeTags,
		TAG_DONE)))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_WINDOW_TXT));

			/* Create a user clip region to keep text from
			 * leaking into the window borders.
			 */

		if(!(ClipRegion = NewRegion()))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_WINDOW_TXT));
		else
		{
			struct Rectangle RegionRectangle;

				/* Adjust the region to match the inner window area. */

			RegionRectangle . MinX = Window -> BorderLeft;
			RegionRectangle . MinY = Window -> BorderTop;
			RegionRectangle . MaxX = Window -> Width - (Window -> BorderRight + 1);
			RegionRectangle . MaxY = Window -> Height - (Window -> BorderBottom + 1);

				/* Establish the region. */

			OrRectRegion(ClipRegion,&RegionRectangle);

				/* Install the region. */

			OldRegion = InstallClipRegion(Window -> WLayer,ClipRegion);
		}

		if(FullWidth < 40 * TextFontWidth)
			FullWidth = 40 * TextFontWidth;

		Width	= Window -> BorderLeft + FullWidth + Window -> BorderRight;
		Height	= Window -> BorderTop + 20 * TextFontHeight + Window -> BorderBottom;

		WindowLimits(Window,Width,Height,0,0);

		if(WorkbenchBase)
		{
			if(WorkbenchPort = CreateMsgPort())
			{
				if(!(WorkbenchWindow = AddAppWindow(0,0,Window,WorkbenchPort,TAG_DONE)))
				{
					DeleteMsgPort(WorkbenchPort);

					WorkbenchPort = NULL;
				}
			}
		}
	}
	else
	{
		struct DimensionInfo	DimensionInfo;
		WORD			MaxDepth,
					ScreenDepth;

		if(ModeNotAvailable(Config -> ScreenConfig -> DisplayMode))
		{
			struct Screen *PubScreen;

			if(PubScreen = LockPubScreen(NULL))
			{
				Config -> ScreenConfig -> DisplayMode = GetVPModeID(&PubScreen -> ViewPort);

				UnlockPubScreen(NULL,PubScreen);
			}
		}

		if(!QueryOverscan(Config -> ScreenConfig -> DisplayMode,&DisplayClip,Config -> ScreenConfig -> OverscanType))
		{
			OpenFailed = TRUE;

			ErrorCode = ModeNotAvailable(Config -> ScreenConfig -> DisplayMode);

			goto OpenS;
		}

		if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Config -> ScreenConfig -> DisplayMode))
		{
			UWORD	MaxWidth,
				MaxHeight,
				Width,
				Height;

			MaxWidth	= DisplayClip . MaxX - DisplayClip . MinX + 1;
			MaxHeight	= DisplayClip . MaxY - DisplayClip . MinY + 1;

			if(Config -> ScreenConfig -> DisplayWidth && Config -> ScreenConfig -> DisplayHeight)
			{
				ScreenWidth	= Config -> ScreenConfig -> DisplayWidth;
				ScreenHeight	= Config -> ScreenConfig -> DisplayHeight;
			}
			else
			{
				ScreenWidth	= MaxWidth;
				ScreenHeight	= MaxHeight;
			}

			if(Config -> TerminalConfig -> NumColumns < 20)
				Width = MaxWidth = ScreenWidth;
			else
			{
				Width = TextFontWidth * Config -> TerminalConfig -> NumColumns;

				ScreenWidth = 0;
			}

			if(Config -> TerminalConfig -> NumLines < 20)
				Height = MaxHeight = ScreenHeight;
			else
			{
				Height = TextFontHeight * Config -> TerminalConfig -> NumLines;

				if(Config -> ScreenConfig -> TitleBar)
					Height += UserFontHeight + 3;

				if(Config -> ScreenConfig -> StatusLine != STATUSLINE_DISABLED)
				{
					if(Config -> ScreenConfig -> StatusLine == STATUSLINE_COMPRESSED)
						Height += UserFontHeight;
					else
						Height += 2 + (2 + 2 * UserFontHeight + 2);
				}

				ScreenHeight = 0;
			}

			if(Height > MaxHeight)
				Height = MaxHeight;

			if(Width > MaxWidth)
				Width = MaxWidth;

			if(DimensionInfo . MinRasterWidth <= Width && Width <= DimensionInfo . MaxRasterWidth)
			{
				UWORD Half;

				Width = MaxWidth - Width;

				Half = Width / 2;

				DisplayClip . MinX += Half;
				DisplayClip . MaxX -= Width - Half;
			}

			if(DimensionInfo . MinRasterHeight <= Height && Height <= DimensionInfo . MaxRasterHeight)
				DisplayClip . MaxY = DisplayClip . MinY + Height - 1;

			if(!ScreenWidth)
				ScreenWidth = DisplayClip . MaxX - DisplayClip . MinX + 1;

			if(!ScreenHeight)
				ScreenHeight = DisplayClip . MaxY - DisplayClip . MinY + 1;

			MaxDepth = DimensionInfo . MaxDepth;
		}
		else
		{
			ScreenWidth = ScreenHeight = 0;
			MaxDepth = 4;
		}

			/* We'll configure the screen parameters at
			 * run time, at first we'll set up the screen
			 * depth.
			 */

PenReset:	if(!Config -> ScreenConfig -> UsePens && Kick30)
		{
			for(i = DETAILPEN ; i <= BARTRIMPEN ; i++)
				PenArray[i] = Config -> ScreenConfig -> PenArray[i];

			PenArray[i] = (UWORD)~0;
		}
		else
		{
			UWORD *Data;

			switch(Config -> ScreenConfig -> ColourMode)
			{
				case COLOUR_EIGHT:

					Data = ANSIPens;
					break;

				case COLOUR_SIXTEEN:

					Data = EGAPens;
					break;

				case COLOUR_AMIGA:

					Data = StandardPens;
					break;

				default:

					Data = NULL;
					break;
			}

			if(Data)
			{
				for(i = DETAILPEN ; i <= BARTRIMPEN ; i++)
					PenArray[i] = Data[i];

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

		switch(Config -> ScreenConfig -> ColourMode)
		{
			case COLOUR_EIGHT:

					// Special screen depth requested?

				if(Config -> ScreenConfig -> Depth)
				{
						// The minimum number of colours required

					if(Config -> ScreenConfig -> Blinking)
						ScreenDepth = 4;
					else
						ScreenDepth = 3;

						// This is what the user wanted

					RealDepth = Config -> ScreenConfig -> Depth;

						// Too deep for this display mode?

					if(RealDepth > MaxDepth)
						RealDepth = MaxDepth;

						// Less colours than required?

					if(RealDepth < ScreenDepth && ScreenDepth <= MaxDepth)
						RealDepth = ScreenDepth;

						// Not enough colours to display it?

					if(RealDepth < ScreenDepth)
					{
							// Return to standard mode

						Config -> ScreenConfig -> ColourMode = COLOUR_AMIGA;

						ConfigChanged = TRUE;

						goto PenReset;
					}
				}
				else
				{
						// The minimum number of colours

					if(Config -> ScreenConfig -> Blinking)
						ScreenDepth = 4;
					else
						ScreenDepth = 3;

						// Too many for this mode?

					if(ScreenDepth > MaxDepth)
					{
							// Return to standard mode

						Config -> ScreenConfig -> ColourMode = COLOUR_AMIGA;

						ConfigChanged = TRUE;

						goto PenReset;
					}

					RealDepth = ScreenDepth;
				}

				TagArray[Count++] = SA_Pens;
				TagArray[Count++] = (LONG)PenArray;

				TagArray[Count++] = SA_BlockPen;
				TagArray[Count++] = PenArray[SHADOWPEN];

				TagArray[Count++] = SA_DetailPen;
				TagArray[Count++] = PenArray[BACKGROUNDPEN];

				break;

			case COLOUR_SIXTEEN:

				if(Config -> ScreenConfig -> Depth)
				{
					if(Config -> ScreenConfig -> Blinking && MaxDepth > 4)
						ScreenDepth = 5;
					else
						ScreenDepth = 4;

					RealDepth = Config -> ScreenConfig -> Depth;

					if(RealDepth > MaxDepth)
						RealDepth = MaxDepth;

					if(RealDepth < ScreenDepth && ScreenDepth <= MaxDepth)
						RealDepth = ScreenDepth;

					if(RealDepth < ScreenDepth)
					{
						Config -> ScreenConfig -> ColourMode = COLOUR_AMIGA;

						ConfigChanged = TRUE;

						goto PenReset;
					}
				}
				else
				{
					if(Config -> ScreenConfig -> Blinking && MaxDepth > 4)
						ScreenDepth = 5;
					else
						ScreenDepth = 4;

					if(ScreenDepth > MaxDepth)
					{
						Config -> ScreenConfig -> ColourMode = COLOUR_AMIGA;

						ConfigChanged = TRUE;

						goto PenReset;
					}

					RealDepth = ScreenDepth;
				}

				TagArray[Count++] = SA_Pens;
				TagArray[Count++] = (LONG)PenArray;

				TagArray[Count++] = SA_BlockPen;
				TagArray[Count++] = PenArray[SHADOWPEN];

				TagArray[Count++] = SA_DetailPen;
				TagArray[Count++] = PenArray[BACKGROUNDPEN];

				break;

			case COLOUR_MONO:

				if(Config -> ScreenConfig -> Depth)
					RealDepth = Config -> ScreenConfig -> Depth;
				else
					RealDepth = 1;

				if(RealDepth > MaxDepth)
					RealDepth = MaxDepth;

				break;

			case COLOUR_AMIGA:

				if(Config -> ScreenConfig -> Depth)
					RealDepth = Config -> ScreenConfig -> Depth;
				else
					RealDepth = 2;

				if(RealDepth > MaxDepth)
					RealDepth = MaxDepth;

				TagArray[Count++] = SA_Pens;
				TagArray[Count++] = (LONG)PenArray;

				break;
		}

			/* Add the depth value. */

		TagArray[Count++] = SA_Depth;
		TagArray[Count++] = RealDepth;

			/* Terminate the tag array. */

		TagArray[Count] = TAG_END;

			/* Set the plane mask. */

		DepthMask = (1L << RealDepth) - 1;

			/* Inquire overscan limits and try to create an interleaved
			 * bitmap if possible.
			 */

		if(Config -> ScreenConfig -> FasterLayout && RealDepth > 1 && !Kick30)
			InterleavedBitMap = CreateInterleavedBitMap(DisplayClip . MaxX - DisplayClip . MinX + 1,DisplayClip . MaxY - DisplayClip . MinY + 1,RealDepth);
		else
			InterleavedBitMap = NULL;

#ifdef _M68030
OpenS:		SPrintf(ScreenTitle,LocaleString(MSG_TERMINIT_SCREENTITLE_TXT),TermName,"'030 ",TermDate,TermIDString);
#else
OpenS:		SPrintf(ScreenTitle,LocaleString(MSG_TERMINIT_SCREENTITLE_TXT),TermName,"",TermDate,TermIDString);
#endif	/* _M68030 */

		if(InterleavedBitMap)
		{
			if(Screen = (struct Screen *)OpenScreenTags(NULL,
				ScreenWidth  ? SA_Width  : TAG_IGNORE,	ScreenWidth,
				ScreenHeight ? SA_Height : TAG_IGNORE,	ScreenHeight,

				SA_Title,	ScreenTitle,
				SA_DClip,	&DisplayClip,
				SA_BitMap,	InterleavedBitMap,
				SA_DisplayID,	Config -> ScreenConfig -> DisplayMode,
				SA_Font,	&UserFont,
				SA_Behind,	TRUE,
				SA_AutoScroll,	TRUE,
				SA_ShowTitle,	Config -> ScreenConfig -> TitleBar,
				SA_PubName,	TermIDString,
				SA_ErrorCode,	&ErrorCode,
				SA_BackFill,	&BackfillHook,
				TAG_MORE,	TagArray,
			TAG_END))
				UseMasking = FALSE;
		}
		else
		{
			BYTE Interleaved;

			if(Config -> ScreenConfig -> FasterLayout && Kick30 && RealDepth > 1)
				Interleaved = TRUE;
			else
				Interleaved = FALSE;

			if(Screen = (struct Screen *)OpenScreenTags(NULL,
				ScreenWidth  ? SA_Width  : TAG_IGNORE,	ScreenWidth,
				ScreenHeight ? SA_Height : TAG_IGNORE,	ScreenHeight,

				SA_Title,	ScreenTitle,
				SA_DClip,	&DisplayClip,
				SA_DisplayID,	Config -> ScreenConfig -> DisplayMode,
				SA_Font,	&UserFont,
				SA_Behind,	TRUE,
				SA_AutoScroll,	TRUE,
				SA_ShowTitle,	Config -> ScreenConfig -> TitleBar,
				SA_PubName,	TermIDString,
				SA_ErrorCode,	&ErrorCode,
				SA_Interleaved,	Interleaved,
				SA_BackFill,	&BackfillHook,
				TAG_MORE,	TagArray,
			TAG_END))
			{
				if(Interleaved)
					UseMasking = FALSE;
				else
					UseMasking = TRUE;
			}
		}

			/* We've got an error. */

		if(!Screen)
		{
			if(!OpenFailed)
			{
				struct Screen *PubScreen;

				switch(ErrorCode)
				{
						/* Can't open screen with these display
						 * modes.
						 */

					case OSERR_NOMONITOR:
					case OSERR_NOCHIPS:
					case OSERR_UNKNOWNMODE:
					case OSERR_NOTAVAILABLE:

						if(PubScreen = LockPubScreen(NULL))
						{
							Config -> ScreenConfig -> DisplayMode = GetVPModeID(&PubScreen -> ViewPort);

							UnlockPubScreen(NULL,PubScreen);
						}
						else
							Config -> ScreenConfig -> DisplayMode = HIRES_KEY;

						OpenFailed = TRUE;

						goto OpenS;

					case OSERR_PUBNOTUNIQUE:

						return(LocaleString(MSG_TERMINIT_SCREEN_ID_ALREADY_IN_USE_TXT));
				}
			}

				/* Some different error, probably out of
				 * memory.
				 */

			return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_SCREEN_TXT));
		}

		if(!(DrawInfo = GetScreenDrawInfo(Screen)))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_OBTAIN_SCREEN_DRAWINFO_TXT));

		CreateMenuGlyphs(Screen,DrawInfo,&AmigaGlyph,&CheckGlyph);

		VPort = &Screen -> ViewPort;

		ScreenWidth	= Screen -> Width;
		ScreenHeight	= Screen -> Height;

		StatusSizeSetup(Screen,&StatusWidth,&StatusHeight);

			/* Obtain visual info (whatever that may be). */

		if(!(VisualInfo = GetVisualInfo(Screen,TAG_DONE)))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_OBTAIN_VISUAL_INFO_TXT));

		if(Config -> ScreenConfig -> TitleBar)
		{
			Top = Screen -> BarHeight + 1;

			Height = Screen -> Height - (Screen -> BarHeight + 1 + StatusHeight);
		}
		else
		{
			Top = 0;

			Height = Screen -> Height - StatusHeight;
		}

			/* Open the main window. */

		if(!(Window = OpenWindowTags(NULL,
			WA_Top,		Top,
			WA_Left,	0,
			WA_Width,	Screen -> Width,
			WA_Height,	Height,
			WA_Backdrop,	TRUE,
			WA_Borderless,	TRUE,
			WA_SmartRefresh,TRUE,
			WA_CustomScreen,Screen,
			WA_NewLookMenus,TRUE,
			WA_RMBTrap,	TRUE,
			WA_IDCMP,	IDCMP_RAWKEY | IDCMP_INACTIVEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MOUSEMOVE | IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MENUPICK | IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_SIZEVERIFY | IDCMP_IDCMPUPDATE,

			AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
			CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
		TAG_DONE)))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_WINDOW_TXT));
	}

		/* Fill the `default' colour with current values. */

	if(!Config -> ScreenConfig -> UseWorkbench && Initializing && !SharedScreen)
	{
		for(i = 0 ; i < 16 ; i++)
			DefaultColours[i] = GetRGB4(VPort -> ColorMap,i);

		Initializing = FALSE;
	}

		/* Load the approriate colours. */

	if(LoadColours)
	{
		switch(Config -> ScreenConfig -> ColourMode)
		{
			case COLOUR_EIGHT:

				CopyMem(ANSIColours,Config -> ScreenConfig -> Colours,16 * sizeof(UWORD));
				break;

			case COLOUR_SIXTEEN:

				CopyMem(EGAColours,Config -> ScreenConfig -> Colours,16 * sizeof(UWORD));
				break;

			case COLOUR_AMIGA:

				CopyMem(DefaultColours,Config -> ScreenConfig -> Colours,16 * sizeof(UWORD));
				break;

			case COLOUR_MONO:

				CopyMem(AtomicColours,Config -> ScreenConfig -> Colours,16 * sizeof(UWORD));
				break;
		}

		LoadColours = FALSE;
	}

		/* Reset the current colours and the blinking equivalents. */

	PaletteSetup(Config);

	if(!Config -> ScreenConfig -> UseWorkbench && !SharedScreen)
		LoadRGB4(VPort,NormalColours,PaletteSize);

		/* Get the vanilla rendering pens. */

	RenderPens[0] = DrawInfo -> dri_Pens[BACKGROUNDPEN];
	RenderPens[1] = DrawInfo -> dri_Pens[TEXTPEN];
	RenderPens[2] = DrawInfo -> dri_Pens[SHINEPEN];
	RenderPens[3] = DrawInfo -> dri_Pens[FILLPEN];

		/* Are we to use the Workbench screen for text output? */

	if(Config -> ScreenConfig -> UseWorkbench || (SharedScreen && Kick30))
	{
		if(Kick30 && (Config -> ScreenConfig -> ColourMode == COLOUR_EIGHT || Config -> ScreenConfig -> ColourMode == COLOUR_SIXTEEN))
		{
			ULONG	R,G,B;
			BYTE	GotAll = TRUE;
			WORD	NumPens;

			if(Config -> ScreenConfig -> ColourMode == COLOUR_EIGHT)
				NumPens = 8;
			else
				NumPens = 16;

			for(i = 0 ; i < 16 ; i++)
				MappedPens[1][i] = FALSE;

				/* Allocate the text rendering pens, note that
				 * we will use the currently installed palette
				 * to obtain those pens which match them best.
				 * The user will be unable to change these
				 * colours.
				 */

			for(i = 0 ; i < NumPens ; i++)
			{
					/* Split the 12 bit colour palette entry. */

				R = (NormalColours[i] >> 8) & 0xF;
				G = (NormalColours[i] >> 4) & 0xF;
				B =  NormalColours[i]       & 0xF;

					/* Try to obtain a matching pen. */

				if((MappedPens[0][i] = ObtainBestPen(VPort -> ColorMap,SPREAD((R << 4) | R),SPREAD((G << 4) | G),SPREAD((B << 4) | B),
					OBP_FailIfBad,TRUE,
				TAG_DONE)) == -1)
				{
					MappedPens[1][i] = FALSE;

					GotAll = FALSE;

					break;
				}
				else
					MappedPens[1][i] = TRUE;
			}

				/* Did we get what we wanted? */

			if(!GotAll)
			{
					/* Release all the pens we succeeded
					 * in allocating.
					 */

				for(i = 0 ; i < NumPens ; i++)
				{
					if(MappedPens[1][i])
						ReleasePen(VPort -> ColorMap,MappedPens[0][i]);
				}

					/* Use the default rendering pens. */

				for(i = 0 ; i < 4 ; i++)
				{
					MappedPens[0][i] = RenderPens[i];
					MappedPens[1][i] = FALSE;
				}

					/* Set the remaining pens to defaults. */

				for(i = 4 ; i < NumPens ; i++)
				{
					MappedPens[0][i] = RenderPens[1];
					MappedPens[1][i] = FALSE;
				}
			}
			else
				AllocatedPens = TRUE;
		}
		else
		{
				/* Use the default rendering pens. */

			if(Config -> ScreenConfig -> ColourMode == COLOUR_AMIGA)
			{
				for(i = 0 ; i < 4 ; i++)
				{
					MappedPens[0][i] = RenderPens[i];
					MappedPens[1][i] = FALSE;
				}

					/* Set the remaining pens to defaults. */

				for(i = 4 ; i < 16 ; i++)
				{
					MappedPens[0][i] = RenderPens[1];
					MappedPens[1][i] = FALSE;
				}
			}
			else
			{
				for(i = 0 ; i < 16 ; i++)
				{
					MappedPens[0][i] = RenderPens[i & 1];
					MappedPens[1][i] = FALSE;
				}
			}
		}

		for(i = 0 ; i < 16 ; i++)
		{
			MappedPens[0][i + 16] = MappedPens[0][i];
			MappedPens[1][i + 16] = FALSE;
		}
	}
	else
	{
			/* Reset the colour translation table. */

		for(i = 0 ; i < 32 ; i++)
		{
			MappedPens[0][i] = i;
			MappedPens[1][i] = FALSE;
		}
	}

		/* Determine default text rendering colour. */

	switch(Config -> ScreenConfig -> ColourMode)
	{
		case COLOUR_SIXTEEN:

			SafeTextPen = MappedPens[0][15];
			break;

		case COLOUR_EIGHT:

			SafeTextPen = MappedPens[0][7];
			break;

		case COLOUR_AMIGA:
		case COLOUR_MONO:

			SafeTextPen = MappedPens[0][1];
			break;
	}

		/* Determine window inner dimensions and top/left edge offsets. */

	WindowLeft	= Window -> BorderLeft;
	WindowTop	= Window -> BorderTop;

	WindowWidth	= Window -> Width - (Window -> BorderLeft + Window -> BorderRight);
	WindowHeight	= Window -> Height - (Window -> BorderTop + Window -> BorderBottom);

		/* Set up scaling data (bitmaps & rastports). */

	if(!CreateScale())
		return(LocaleString(MSG_TERMINIT_FAILED_TO_CREATE_FONT_SCALING_INFO_TXT));

	if(!CreateOffsetTables())
		return(LocaleString(MSG_TERMINIT_FAILED_TO_CREATE_OFFSET_TABLES_TXT));

	TabStopMax = Window -> WScreen -> Width / TextFontWidth;

		/* Allocate the tab stop line. */

	if(!(TabStops = (BYTE *)AllocVecPooled(TabStopMax,MEMF_ANY | MEMF_CLEAR)))
		return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));

		/* Push it on the window stack (should become bottommost
		 * entry).
		 */

	PushWindow(Window);

	if(TermPort)
		TermPort -> TopWindow = Window;

	StatusWindow = NULL;

	if(Config -> ScreenConfig -> StatusLine != STATUSLINE_DISABLED)
	{
		if(Config -> ScreenConfig -> SplitStatus)
		{
			if(!(StatusWindow = OpenWindowTags(NULL,
				WA_Top,			Window -> TopEdge + Window -> Height,
				WA_Left,		Window -> LeftEdge,
				WA_InnerWidth,		StatusWidth,
				WA_InnerHeight,		StatusHeight,
				WA_GimmeZeroZero,	TRUE,
				WA_DragBar,		TRUE,
				WA_DepthGadget,		TRUE,
				WA_NewLookMenus,	TRUE,
				WA_Title,		ScreenTitle,
				WA_CustomScreen,	Window -> WScreen,
				WA_RMBTrap,		TRUE,
				WA_CloseGadget,		TRUE,

				AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
				CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
			TAG_DONE)))
				return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_STATUS_WINDOW_TXT));
		}
		else
		{
			if(!Config -> ScreenConfig -> UseWorkbench && !SharedScreen)
			{
				if(!(StatusWindow = OpenWindowTags(NULL,
					WA_Top,		Window -> TopEdge + Window -> Height,
					WA_Left,	0,
					WA_Width,	Screen -> Width,
					WA_Height,	Screen -> Height - (Window -> TopEdge + Window -> Height),
					WA_Backdrop,	TRUE,
					WA_Borderless,	TRUE,
					WA_SmartRefresh,TRUE,
					WA_NewLookMenus,TRUE,
					WA_CustomScreen,Screen,
					WA_RMBTrap,	TRUE,

					AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
					CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
				TAG_DONE)))
					return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_STATUS_WINDOW_TXT));
			}
		}
	}

	if(StatusWindow)
	{
		StatusWindow -> UserPort = Window -> UserPort;

		ModifyIDCMP(StatusWindow,Window -> IDCMPFlags);
	}

	RPort = Window -> RPort;

		/* Default console setup. */

	CursorX = 0;
	CursorY	= 0;

	SetDrMd(RPort,JAM2);

		/* Set the font. */

	SetFont(RPort,CurrentFont);

		/* Redirect AmigaDOS requesters. */

	OldWindowPtr = ThisProcess -> pr_WindowPtr;

	ThisProcess -> pr_WindowPtr = (APTR)Window;

		/* Create the character raster. */

	if(!CreateRaster())
		return(LocaleString(MSG_TERMINIT_UNABLE_TO_CREATE_SCREEN_RASTER_TXT));

	ConOutputUpdate();

	ConFontScaleUpdate();

		/* Set up the scrolling info. */

	ScrollLineCount = Window -> WScreen -> Height / TextFontHeight;

	if(!(ScrollLines = (struct ScrollLineInfo *)AllocVecPooled(sizeof(struct ScrollLineInfo) * ScrollLineCount,MEMF_ANY|MEMF_CLEAR)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_CREATE_SCROLLING_SUPPORT_INFO_TXT));

		/* Create the menu strip. */

	if(Error = BuildMenu())
		return(Error);

		/* Disable the `Execute ARexx Command' menu item if
		 * the rexx server is not available.
		 */

	if(!RexxSysBase)
		OffItem(MEN_EXECUTE_REXX_COMMAND);

	if(Recording)
	{
		OnItem(MEN_RECORD_LINE);

		CheckItem(MEN_RECORD,TRUE);
		CheckItem(MEN_RECORD_LINE,RecordingLine);
	}
	else
	{
		OffItem(MEN_RECORD_LINE);

		CheckItem(MEN_RECORD,FALSE);
		CheckItem(MEN_RECORD_LINE,FALSE);
	}

	CheckItem(MEN_DISABLE_TRAPS,!(WatchTraps && GenericListTable[GLIST_TRAP] -> ListHeader . mlh_Head -> mln_Succ));

	if(StatusWindow)
	{
		SetMenuStrip(StatusWindow,Menu);

		StatusWindow -> Flags &= ~WFLG_RMBTRAP;

		SetDrMd(StatusWindow -> RPort,JAM2);
	}

		/* Add a tick if file capture is active. */

	if(FileCapture)
		CheckItem(MEN_CAPTURE_TO_FILE,TRUE);
	else
		CheckItem(MEN_CAPTURE_TO_FILE,FALSE);

		/* Add a tick if printer capture is active. */

	CheckItem(MEN_CAPTURE_TO_PRINTER,PrinterCapture);

		/* Add a tick if the buffer is frozen. */

	CheckItem(MEN_FREEZE_BUFFER,BufferFrozen);

		/* Disable the dialing functions if online. */

	if(Online)
		SetDialMenu(FALSE);
	else
		SetDialMenu(TRUE);

		/* Update the clipboard menus. */

	SetClipMenu(FALSE);

	if(!XProtocolBase)
		SetTransferMenu(FALSE);

		/* Disable the `Print Screen' and `Save ASCII' functions
		 * if raster is not enabled.
		 */

	SetRasterMenu(RasterEnabled);

		/* Enable the menu. */

	Window -> Flags &= ~WFLG_RMBTRAP;

	strcpy(EmulationName,LocaleString(MSG_TERMXEM_NO_EMULATION_TXT));

		/* Create the status server. */

	Forbid();

	if(StatusProcess = CreateNewProcTags(
		NP_Entry,	StatusServer,
		NP_Name,	"term Status Process",
		NP_WindowPtr,	-1,
		NP_Priority,	5,
	TAG_DONE))
	{
		ClrSignal(SIG_HANDSHAKE);

		Wait(SIG_HANDSHAKE);
	}

	Permit();

		/* Status server has `died'. */

	if(!StatusProcess)
		return(LocaleString(MSG_TERMINIT_UNABLE_TO_CREATE_STATUS_TASK_TXT));

		/* Obtain the default public screen name just in case
		 * we'll need it later.
		 */

	GetDefaultPubScreen(DefaultPubScreenName);

		/* Set up the window size. */

	ScreenSizeStuff();

		/* Select the default console data processing routine. */

	Forbid();

	ConProcessData = ConProcessData8;

	Permit();

		/* Handle the remaining terminal setup. */

	if(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Config -> TerminalConfig -> EmulationFileName[0])
	{
		if(!OpenEmulator(Config -> TerminalConfig -> EmulationFileName))
		{
			Config -> TerminalConfig -> EmulationMode = EMULATION_ANSIVT100;

			ResetDisplay = TRUE;

			RasterEnabled = TRUE;

			MyEasyRequest(Window,LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_EMULATION_LIBRARY_TXT),Config -> TerminalConfig -> EmulationFileName);
		}
		else
		{
			if(RasterEnabled)
				RasterEnabled = FALSE;

			SetRasterMenu(RasterEnabled);
		}
	}

		/* Choose the right console data processing routine. */

	ConProcessUpdate();

		/* Reset terminal emulation. */

	if(Config -> TerminalConfig -> EmulationMode != EMULATION_EXTERNAL)
	{
		ClearCursor();

		Reset();

		DrawCursor();
	}
	else
	{
		if(XEmulatorBase)
			XEmulatorResetConsole(XEM_IO);
	}

		/* Restart the fast! macro panel. */

	if(HadFastMacros || Config -> MiscConfig -> OpenFastMacroPanel)
		OpenFastWindow();

	if(Config -> TerminalConfig -> UseTerminalTask && Config -> TerminalConfig -> EmulationMode != EMULATION_EXTERNAL)
		CreateEmulationProcess();
	else
		DeleteEmulationProcess();

	return(NULL);
}

	/* CloseAll():
	 *
	 *	Free all resources and leave the program.
	 */

VOID __regargs
CloseAll(BYTE CloseDOS)
{
	WORD i;

	Forbid();

	if(RendezvousSemaphore . rs_Semaphore . ss_Link . ln_Name)
		RemSemaphore(&RendezvousSemaphore);

	Permit();

#ifdef DATAFEED
	{
		extern BPTR DataFeed;

		if(DataFeed)
		{
			Close(DataFeed);

			DataFeed = NULL;
		}
	}
#endif	/* DATAFEED */

	Forbid();

	if(DialMsg)
	{
		DialMsg -> rm_Result1 = RC_WARN;
		DialMsg -> rm_Result2 = 0;

		ReplyMsg(DialMsg);

		DialMsg = NULL;
	}

	Permit();

	DeleteRecord();

	DeleteQueueProcess();

	SoundExit();

	SZ_SizeCleanup();

	FreeDialList(TRUE);

	if(SpecialQueue)
	{
		DeleteMsgQueue(SpecialQueue);

		SpecialQueue = NULL;
	}

	if(SpecialTable)
	{
		FreeVecPooled(SpecialTable);

		SpecialTable = NULL;
	}

	if(AbortTable)
	{
		FreeVecPooled(AbortTable);

		AbortTable = NULL;
	}

	if(BackupConfig)
	{
		DeleteConfiguration(BackupConfig);

		BackupConfig = NULL;
	}

	if(IntuitionBase && Window)
		BlockWindows();

	/* ALWAYS */
	{
		extern struct MsgPort *RexxPort;

		if(RexxPort)
			RemPort(RexxPort);
	}

	if(EditList)
	{
		DeleteList(EditList);

		EditList = NULL;
	}

	if(EditLabels)
	{
		FreeVecPooled(EditLabels);

		EditLabels = NULL;
	}

	if(TermRexxPort)
	{
		if(RexxSysBase)
		{
			struct Message *Msg;

			while(Msg = GetMsg(TermRexxPort))
				ReplyMsg(Msg);
		}

		DeleteMsgPort(TermRexxPort);

		TermRexxPort = NULL;
	}

	if(RexxProcess)
	{
		Forbid();

		Signal(RexxProcess,SIG_KILL);

		ClrSignal(SIG_HANDSHAKE);

		Wait(SIG_HANDSHAKE);

		Permit();

		RexxProcess = NULL;
	}

	if(RexxSysBase)
	{
		CloseLibrary(RexxSysBase);

		RexxSysBase = NULL;
	}

	if(XprIO && XProtocolBase)
		XProtocolCleanup(XprIO);

	if(XProtocolBase)
	{
		CloseLibrary(XProtocolBase);

		XProtocolBase = NULL;
	}

	if(XprIO)
	{
		FreeVec(XprIO);

		XprIO = NULL;
	}

	if(CursorKeys)
	{
		FreeVecPooled(CursorKeys);

		CursorKeys = NULL;
	}

	if(MacroKeys)
	{
		FreeVecPooled(MacroKeys);

		MacroKeys = NULL;
	}

	TerminateBuffer();

	DeleteSpeech();

	Forbid();

	BufferClosed = TRUE;

	DeleteBuffer();

	Permit();

	if(AttentionBuffers[0])
	{
		FreeVecPooled(AttentionBuffers[0]);

		AttentionBuffers[0] = NULL;
	}

	if(SendTable)
	{
		FreeTranslationTable(SendTable);

		SendTable = NULL;
	}

	if(ReceiveTable)
	{
		FreeTranslationTable(ReceiveTable);

		ReceiveTable = NULL;
	}

	FreeDialList(TRUE);

	DeleteOffsetTables();

	FreeList(&FastMacroList);
	FreeList((struct List *)&ReviewBufferHistory);
	FreeList((struct List *)&TextBufferHistory);

	for(i = GLIST_UPLOAD ; i < GLIST_COUNT ; i++)
	{
		if(GenericListTable[i])
		{
			DeleteGenericList(GenericListTable[i]);

			GenericListTable[i] = NULL;
		}
	}

	if(FileCapture)
	{
		BufferClose(FileCapture);

		if(!GetFileSize(CaptureName))
			DeleteFile(CaptureName);
		else
		{
			AddProtection(CaptureName,FIBF_EXECUTE);

			if(Config -> MiscConfig -> CreateIcons)
				AddIcon(CaptureName,FILETYPE_TEXT,FALSE);
		}

		FileCapture = NULL;
	}

	if(PrinterCapture)
	{
		Close(PrinterCapture);

		PrinterCapture = NULL;
	}

		/* Close the external emulator. */

	if(XEmulatorBase)
	{
		if(XEM_IO)
		{
			XEmulatorMacroKeyFilter(XEM_IO,NULL);
			XEmulatorCloseConsole(XEM_IO);
			XEmulatorCleanup(XEM_IO);

			FreeVec(XEM_IO);

			XEM_IO = NULL;
		}

		CloseLibrary(XEmulatorBase);

		XEmulatorBase = NULL;
	}

	if(XEM_MacroKeys)
	{
		FreeVecPooled(XEM_MacroKeys);

		XEM_MacroKeys = NULL;
	}

	DeleteDisplay();

	if(KeySegment)
	{
		UnLoadSeg(KeySegment);

		KeySegment = NULL;
	}

	StopCall(TRUE);

	if(CheckBit != -1)
	{
		FreeSignal(CheckBit);

		CheckBit = -1;
	}

	ClearSerial();

	DeleteSerial();

	if(TimeRequest)
	{
		if(TimeRequest -> tr_node . io_Device)
			CloseDevice(TimeRequest);

		DeleteIORequest(TimeRequest);

		TimeRequest = NULL;
	}

	if(TimePort)
	{
		DeleteMsgPort(TimePort);

		TimePort = NULL;
	}

	ShutdownCx();

	if(TermPort)
	{
		if(TermID != -1)
		{
			ObtainSemaphore(&TermPort -> OpenSemaphore);

			TermPort -> OpenCount--;

			if(TermPort -> OpenCount <= 0 && !TermPort -> HoldIt)
			{
				RemPort(&TermPort -> ExecNode);

				ReleaseSemaphore(&TermPort -> OpenSemaphore);

				FreeVec(TermPort);
			}
			else
				ReleaseSemaphore(&TermPort -> OpenSemaphore);

			TermID = -1;
		}

		TermPort = NULL;
	}

	CloseClip();

	if(GTLayoutBase)
	{
		CloseLibrary(GTLayoutBase);

		GTLayoutBase = NULL;
	}

	if(Config)
	{
		DeleteConfiguration(Config);

		Config = NULL;
	}

	if(PrivateConfig)
	{
		DeleteConfiguration(PrivateConfig);

		PrivateConfig = NULL;
	}

	if(FakeInputEvent)
	{
		FreeVecPooled(FakeInputEvent);

		FakeInputEvent = NULL;
	}

	if(ConsoleDevice)
	{
		CloseDevice(ConsoleRequest);

		ConsoleDevice = NULL;
	}

	if(ConsoleRequest)
	{
		FreeVecPooled(ConsoleRequest);

		ConsoleRequest = NULL;
	}

	if(IconBase)
	{
		CloseLibrary(IconBase);

		IconBase = NULL;
	}

	if(DataTypesBase)
	{
		CloseLibrary(DataTypesBase);

		DataTypesBase = NULL;
	}

	if(WorkbenchBase)
	{
		CloseLibrary(WorkbenchBase);

		WorkbenchBase = NULL;
	}

	if(OwnDevUnitBase)
	{
		CloseLibrary(OwnDevUnitBase);

		OwnDevUnitBase = NULL;
	}

	if(CxBase)
	{
		CloseLibrary(CxBase);

		CxBase = NULL;
	}

	if(IFFParseBase)
	{
		CloseLibrary(IFFParseBase);

		IFFParseBase = NULL;
	}

	if(AslBase)
	{
		CloseLibrary(AslBase);

		AslBase = NULL;
	}

	if(DiskfontBase)
	{
		CloseLibrary(DiskfontBase);

		DiskfontBase = NULL;
	}

	if(GadToolsBase)
	{
		CloseLibrary(GadToolsBase);

		GadToolsBase = NULL;
	}

	if(LayersBase)
	{
		CloseLibrary(LayersBase);

		LayersBase = NULL;
	}

	if(GfxBase)
	{
		CloseLibrary(GfxBase);

		GfxBase = NULL;
	}

	if(IntuitionBase)
	{
		CloseLibrary(IntuitionBase);

		IntuitionBase = NULL;
	}

	LocaleClose();

	if(UtilityBase)
	{
		CloseLibrary(UtilityBase);

		UtilityBase = NULL;
	}

#ifdef DEBUG
	DebugExit();
#endif	/* DEBUG */

#ifdef BETA
	StopBetaTask();
#endif	/* BETA */

	MemoryCleanup();

	if(WBenchMsg)
	{
		CurrentDir(WBenchLock);

		if(DOSBase)
		{
			CloseLibrary(DOSBase);

			DOSBase = NULL;
		}

		Forbid();

		ReplyMsg((struct Message *)WBenchMsg);

		WBenchMsg = NULL;
	}
	else
	{
		if(CloseDOS && DOSBase)
		{
			CloseLibrary(DOSBase);

			DOSBase = NULL;
		}
	}
}

	/* OpenAll():
	 *
	 *	Open all required resources or return an error message
	 *	if anything went wrong.
	 */

STRPTR __regargs
OpenAll(STRPTR ConfigPath)
{
	extern	ULONG HookEntry(struct Hook *,APTR,APTR);

	UBYTE		 PathBuffer[MAX_FILENAME_LENGTH];
	STRPTR		 Result,Error,ConfigFileName = NULL;
	WORD		 i;
	struct Node	*Node;

		/* Pretty cheap ;-) */

	Kick30 = (SysBase -> LibNode . lib_Version >= 39);

	if(!MemorySetup())
		return("Cannot create memory pool");

#ifdef DEBUG
	DebugInit();
#endif	/* DEBUG */

		/* Don't let it hit the ground! */

	ConTransfer = ConProcess;

		/* Remember the start of this session. */

	DateStamp(&SessionStart);

		/* Reset some flags. */

	BinaryTransfer	= TRUE;

	Status		= STATUS_READY;
	Online		= FALSE;

	InSequence	= FALSE;
	Quiet		= FALSE;

	TagDPI[0] . ti_Tag = TAG_DONE;

		/* Double buffered file locking. */

	NewList(&DoubleBufferList);

	InitSemaphore(&DoubleBufferSemaphore);

		/* Terminal emulation data. */

	InitSemaphore(&TerminalSemaphore);

		/* Text buffer task access semaphore. */

	InitSemaphore(&BufferTaskSemaphore);

		/* Set up all the lists. */

	NewList(&PacketHistoryList);
	NewList(&EmptyList);
	NewList(&FastMacroList);
	NewList(&TransferInfoList);

	NewList((struct List *)&ReviewBufferHistory);
	NewList((struct List *)&TextBufferHistory);

		/* Rendezvous setup. */

	InitSemaphore(&RendezvousSemaphore);

	RendezvousSemaphore . rs_Login		= RendezvousLogin;
	RendezvousSemaphore . rs_Logoff		= RendezvousLogoff;
	RendezvousSemaphore . rs_NewNode	= RendezvousNewNode;

		/* Open the translation tables. */

	LocaleOpen("term.catalog","english",20);

		/* Fill in the menu configuration. */

	LocalizeMenu(TermMenu,MSG_TERMDATA_PROJECT_MEN);

		/* Open intuition.library, any version. */

	if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_INTUITION_LIBRARY_TXT));

	Forbid();

		/* Query the current public screen modes. */

	PublicModes = SetPubScreenModes(NULL);

		/* Set them back. */

	SetPubScreenModes(PublicModes);

	Permit();

		/* Open some more libraries. */

	if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_GRAPHICS_LIBRARY_TXT));

	if(!(LayersBase = OpenLibrary("layers.library",0)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_LAYERS_LIBRARY_TXT));

		/* Install the correct routines to query
		 * the rendering colours and drawing mode.
		 */

	if(!Kick30)
	{
		ReadAPen = OldGetAPen;
		ReadBPen = OldGetBPen;
		ReadDrMd = OldGetDrMd;
		SetWrMsk = OldSetWrMsk;
	}
	else
	{
		ReadAPen = NewGetAPen;
		ReadBPen = NewGetBPen;
		ReadDrMd = NewGetDrMd;
		SetWrMsk = NewSetWrMsk;
	}

	if(!(UtilityBase = OpenLibrary("utility.library",0)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_UTILITY_LIBRARY_TXT));

		/* Check if locale.library has already installed the operating system
		 * patches required for localization.
		 */

	LanguageCheck();

		/* Open the remaining libraries. */

	if(!(GadToolsBase = OpenLibrary("gadtools.library",0)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_GADTOOLS_LIBRARY_TXT));

	if(!(AslBase = OpenLibrary("asl.library",0)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_ASL_LIBRARY_TXT));

	if(!(IFFParseBase = OpenLibrary("iffparse.library",0)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_IFFPARSE_LIBRARY_TXT));

	if(!(CxBase = OpenLibrary("commodities.library",0)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_COMMODITIES_LIBRARY_TXT));

	if(!(DiskfontBase = (struct Library *)OpenLibrary("diskfont.library",0)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_DISKFONT_LIBRARY_TXT));

		/* User interface. */

	if(!(GTLayoutBase = OpenLibrary("PROGDIR:gtlayout.library",0)))
	{
		if(!(GTLayoutBase = OpenLibrary("gtlayout.library",0)))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_GTLAYOUT_LIBRARY_TXT));
	}

		/* Open OwnDevUnit.library, don't complain if it fails. */

	OwnDevUnitBase = OpenLibrary(ODU_NAME,0);

		/* Open workbench.library, don't complain if it fails. */

	WorkbenchBase = OpenLibrary("workbench.library",0);

		/* Open icon.library as well, don't complain if it fails either. */

	IconBase = OpenLibrary("icon.library",0);

		/* Try to open datatypes.library, just for the fun of it. */

	DataTypesBase = OpenLibrary("datatypes.library",39);

	if(!(ConsoleRequest = (struct IOStdReq *)AllocVecPooled(sizeof(struct IOStdReq),MEMF_ANY|MEMF_CLEAR)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_ALLOCATE_CONSOLE_REQUEST_TXT));

	if(OpenDevice("console.device",CONU_LIBRARY,ConsoleRequest,0))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_CONSOLE_DEVICE_TXT));

	ConsoleDevice = &ConsoleRequest -> io_Device -> dd_Library;

	if(!(FakeInputEvent = (struct InputEvent *)AllocVecPooled(sizeof(struct InputEvent),MEMF_ANY|MEMF_CLEAR)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_ALLOCATE_INPUTEVENT_TXT));

	FakeInputEvent -> ie_Class = IECLASS_RAWKEY;

	if(!(MacroKeys = (struct MacroKeys *)AllocVecPooled(sizeof(struct MacroKeys),MEMF_ANY|MEMF_CLEAR)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_ALLOCATE_MACROKEYS_TXT));

	if(!(CursorKeys = (struct CursorKeys *)AllocVecPooled(sizeof(struct CursorKeys),MEMF_ANY|MEMF_CLEAR)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_ALLOCATE_CURSORKEYS_TXT));

	ResetCursorKeys(CursorKeys);

		/* Set up the attention buffers. */

	if(!(AttentionBuffers[0] = (STRPTR)AllocVecPooled(SCAN_COUNT * 260,MEMF_ANY|MEMF_CLEAR)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_CREATE_SEQUENCE_ATTENTION_INFO_TXT));

	for(i = 1 ; i < SCAN_COUNT ; i++)
		AttentionBuffers[i] = &AttentionBuffers[i - 1][260];

		/* Obtain the default environment storage
		 * path.
		 */

	if(!ConfigPath)
	{
		ConfigPath = PathBuffer;

		if(!GetEnvDOS("TERMCONFIGPATH",PathBuffer))
		{
			if(!GetEnvDOS("TERMPATH",PathBuffer))
			{
				APTR LastPtr = ThisProcess -> pr_WindowPtr;
				BPTR FileLock;

				strcpy(PathBuffer,"TERM:config");

				ThisProcess -> pr_WindowPtr = (APTR)-1;

				if(FileLock = Lock("TERM:",ACCESS_READ))
					UnLock(FileLock);
				else
				{
					FileLock = DupLock(ThisProcess-> pr_HomeDir);

						/* Create TERM: assignment referring to
						 * the directory `term' was loaded from.
						 */

					if(!AssignLock("TERM",FileLock))
						UnLock(FileLock);
				}

				if(!(FileLock = Lock(PathBuffer,ACCESS_READ)))
					FileLock = CreateDir(PathBuffer);

				if(FileLock)
					UnLock(FileLock);

				ThisProcess -> pr_WindowPtr = LastPtr;
			}
		}
	}
	else
	{
		if(GetFileSize(ConfigPath))
		{
			STRPTR Index;

			strcpy(PathBuffer,ConfigPath);

			Index = PathPart(PathBuffer);

			*Index = 0;

			ConfigFileName = ConfigPath;

			ConfigPath = PathBuffer;
		}
	}

		/* Check for proper assignment path if necessary. */

        if(!Strnicmp(ConfigPath,"TERM:",5))
        {
        	APTR OldPtr = ThisProcess -> pr_WindowPtr;
        	BPTR DirLock;

			/* Block dos requesters. */

        	ThisProcess -> pr_WindowPtr = (APTR)-1;

			/* Try to get a lock on `TERM:' assignment. */

		if(DirLock = Lock("TERM:",ACCESS_READ))
			UnLock(DirLock);
		else
		{
				/* Clone current directory lock. */

			DirLock = DupLock(ThisProcess-> pr_CurrentDir);

				/* Create TERM: assignment referring to
				 * current directory.
				 */

			if(!AssignLock("TERM",DirLock))
				UnLock(DirLock);
		}

		ThisProcess -> pr_WindowPtr = OldPtr;
        }

		/* Create proper path names. */

	if(ConfigFileName)
	{
		if(!GetFileSize(ConfigFileName))
			ConfigFileName = NULL;
	}

	if(!ConfigFileName)
	{
		strcpy(LastConfig,ConfigPath);

		AddPart(LastConfig,"term_preferences.iff",MAX_FILENAME_LENGTH);

		if(!GetFileSize(LastConfig))
		{
			strcpy(LastConfig,ConfigPath);

			AddPart(LastConfig,"term.prefs",MAX_FILENAME_LENGTH);
		}
	}
	else
		strcpy(LastConfig,ConfigFileName);

	strcpy(DefaultPubScreenName,"Workbench");

		/* Create both configuration buffers. */

	if(!(Config = CreateConfiguration(TRUE)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_ALLOCATE_PRIMARY_CONFIG_TXT));

	if(!(PrivateConfig = CreateConfiguration(TRUE)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_ALLOCATE_SECONDARY_CONFIG_TXT));

	ResetConfig(Config,ConfigPath);

		/* Read some more environment variables. */

	if(!WindowName[0])
	{
		if(!GetEnvDOS("TERMWINDOW",WindowName))
			strcpy(WindowName,"CON:0/11//100/term Output Window/CLOSE/SCREEN %s");
	}

	GetEnvDOS("EDITOR",Config -> PathConfig -> Editor);

		/* Look for the default configuration file. */

	if(!ReadConfig(LastConfig,Config))
	{
		ResetConfig(Config,ConfigPath);

		Initializing = TRUE;

		LoadColours = TRUE;
	}
	else
	{
		switch(Config -> ScreenConfig -> ColourMode)
		{
			case COLOUR_EIGHT:

				CopyMem(Config -> ScreenConfig -> Colours,ANSIColours,16 * sizeof(UWORD));
				break;

			case COLOUR_SIXTEEN:

				CopyMem(Config -> ScreenConfig -> Colours,EGAColours,16 * sizeof(UWORD));
				break;

			case COLOUR_AMIGA:

				CopyMem(Config -> ScreenConfig -> Colours,DefaultColours,16 * sizeof(UWORD));
				break;

			case COLOUR_MONO:

				CopyMem(Config -> ScreenConfig -> Colours,AtomicColours,16 * sizeof(UWORD));
				break;
		}

		if(Config -> ScreenConfig -> ColourMode == COLOUR_AMIGA)
			Initializing = FALSE;
		else
			Initializing = TRUE;
	}

	if(UseNewDevice)
		strcpy(Config -> SerialConfig -> SerialDevice,NewDevice);

	if(UseNewUnit)
		Config -> SerialConfig -> UnitNumber = NewUnit;

	if(Config -> MiscConfig -> OpenFastMacroPanel)
		HadFastMacros = TRUE;

	strcpy(LastPhone,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastPhone,	"term_phonebook.iff",MAX_FILENAME_LENGTH);

	if(!GetFileSize(LastPhone))
	{
		strcpy(LastPhone,	Config -> PathConfig -> DefaultStorage);
		AddPart(LastPhone,	"phonebook.prefs",MAX_FILENAME_LENGTH);
	}

	strcpy(LastKeys,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastKeys,	"term_hotkeys.iff",MAX_FILENAME_LENGTH);

	if(!GetFileSize(LastKeys))
	{
		strcpy(LastKeys,	Config -> PathConfig -> DefaultStorage);
		AddPart(LastKeys,	"hotkeys.prefs",MAX_FILENAME_LENGTH);
	}

	strcpy(LastSpeech,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastSpeech,	"term_speech.iff",MAX_FILENAME_LENGTH);

	if(!GetFileSize(LastSpeech))
	{
		strcpy(LastSpeech,	Config -> PathConfig -> DefaultStorage);
		AddPart(LastSpeech,	"speech.prefs",MAX_FILENAME_LENGTH);
	}

	strcpy(LastFastMacros,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastFastMacros,	"term_fastmacros.iff",MAX_FILENAME_LENGTH);

	if(!GetFileSize(LastFastMacros))
	{
		strcpy(LastFastMacros,	Config -> PathConfig -> DefaultStorage);
		AddPart(LastFastMacros,	"fastmacros.prefs",MAX_FILENAME_LENGTH);
	}

	if(Config -> FileConfig -> MacroFileName[0])
		strcpy(LastMacros,Config -> FileConfig -> MacroFileName);
	else
	{
		strcpy(LastMacros,	Config -> PathConfig -> DefaultStorage);
		AddPart(LastMacros,	"term_macros.iff",MAX_FILENAME_LENGTH);

		if(!GetFileSize(LastMacros))
		{
			strcpy(LastMacros,	Config -> PathConfig -> DefaultStorage);
			AddPart(LastMacros,	"macros.prefs",MAX_FILENAME_LENGTH);

			if(!GetFileSize(LastMacros))
			{
				strcpy(LastMacros,	Config -> PathConfig -> DefaultStorage);
				AddPart(LastMacros,	"functionkeys.prefs",MAX_FILENAME_LENGTH);
			}
		}
	}

	strcpy(LastSound,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastSound,	"sound.prefs",MAX_FILENAME_LENGTH);

		/* Load the keyboard macros. */

	if(!LoadMacros(LastMacros,MacroKeys))
		ResetMacroKeys(MacroKeys);

	if(Config -> FileConfig -> CursorFileName[0])
		strcpy(LastCursorKeys,Config -> FileConfig -> CursorFileName);
	else
	{
		strcpy(LastCursorKeys,	Config -> PathConfig -> DefaultStorage);
		AddPart(LastCursorKeys,	"cursorkeys.prefs",MAX_FILENAME_LENGTH);
	}

		/* Load the cursor keys. */

	if(!ReadIFFData(LastCursorKeys,CursorKeys,sizeof(struct CursorKeys),ID_KEYS))
		ResetCursorKeys(CursorKeys);

		/* Load the sound settings. */

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

	SoundConfig . Volume = 100;

	if(!ReadIFFData(LastSound,&SoundConfig,sizeof(struct SoundConfig),ID_SOUN))
		strcpy(SoundConfig . BellFile,Config -> TerminalConfig -> BeepFileName);

		/* Initialize the sound support routines. */

	SoundInit();

		/* Are we to load the translation tables? */

	strcpy(LastTranslation,Config -> FileConfig -> TranslationFileName);

	if(Config -> FileConfig -> TranslationFileName[0])
	{
		if(SendTable = AllocTranslationTable())
		{
			if(ReceiveTable = AllocTranslationTable())
			{
				if(!LoadTranslationTables(Config -> FileConfig -> TranslationFileName,SendTable,ReceiveTable))
				{
					FreeTranslationTable(SendTable);

					SendTable = NULL;

					FreeTranslationTable(ReceiveTable);

					ReceiveTable = NULL;
				}
				else
				{
					if(IsStandardTable(SendTable) && IsStandardTable(ReceiveTable))
					{
						FreeTranslationTable(SendTable);

						SendTable = NULL;

						FreeTranslationTable(ReceiveTable);

						ReceiveTable = NULL;
					}
				}
			}
			else
			{
				FreeTranslationTable(SendTable);

				SendTable = NULL;
			}
		}
	}

	SendSetup();

	ConOutputUpdate();

		/* Load the fast! macro settings. */

	LoadFastMacros(LastFastMacros);

		/* Load the speech settings. */

	if(!ReadIFFData(LastSpeech,&SpeechConfig,sizeof(struct SpeechConfig),ID_SPEK))
	{
		SpeechConfig . Rate		= DEFRATE;
		SpeechConfig . Pitch		= DEFPITCH;
		SpeechConfig . Frequency	= DEFFREQ;
		SpeechConfig . Volume		= DEFVOL;
		SpeechConfig . Sex		= DEFSEX;
		SpeechConfig . Enabled		= FALSE;
	}

		/* Load the hotkey settings. */

	if(!LoadHotkeys(LastKeys,&Hotkeys))
	{
		strcpy(Hotkeys . termScreenToFront,	"lshift rshift return");
		strcpy(Hotkeys . BufferScreenToFront,	"control rshift return");
		strcpy(Hotkeys . SkipDialEntry,		"control lshift rshift return");
		strcpy(Hotkeys . AbortARexx,		"lshift rshift escape");

		Hotkeys . CommodityPriority	= 0;
		Hotkeys . HotkeysEnabled	= TRUE;
	}

		/* Initialize the data flow parser. */

	FlowInit(TRUE);

		/* Set up the edit list labels for the phonebook. */

	if(!(EditList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY)))
		return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));

	NewList(EditList);

	if(!(EditLabels = (STRPTR *)AllocVecPooled(sizeof(STRPTR) * (MSG_PHONEPANEL_RATES_TXT - MSG_PHONEPANEL_SERIAL_TXT + 1),MEMF_ANY | MEMF_CLEAR)))
		return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));

	for(i = MSG_PHONEPANEL_SERIAL_TXT ; i <= MSG_PHONEPANEL_RATES_TXT ; i++)
	{
		if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(LocaleString(i)) + 2,MEMF_ANY))
		{
			EditLabels[i - MSG_PHONEPANEL_SERIAL_TXT] = Node -> ln_Name = (STRPTR)(Node + 1);

			Node -> ln_Name[0] = ' ';

			strcpy(&Node -> ln_Name[1],LocaleString(i));

			AddTail(EditList,Node);
		}
		else
			return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));
	}

		/* Set up parsing jump tables. */

	if(!(SpecialTable = (JUMP *)AllocVecPooled(256 * sizeof(JUMP),MEMF_CLEAR | MEMF_ANY)))
		return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));

	for(i = 0 ; i < sizeof(SpecialKeys) / sizeof(struct SpecialKey) ; i++)
		SpecialTable[SpecialKeys[i] . Key] = (JUMP)SpecialKeys[i] . Routine;

	if(!(AbortTable = (JUMP *)AllocVecPooled(256 * sizeof(JUMP),MEMF_ANY)))
		return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));

	for(i = 0 ; i < 256 ; i++)
	{
		switch(AbortMap[i])
		{
			case 0:	AbortTable[i] = (JUMP)ParseCode;
				break;

			case 1:	AbortTable[i] = (JUMP)DoCancel;
				break;

			case 2:	AbortTable[i] = (JUMP)DoNewEsc;
				break;

			case 3:	AbortTable[i] = (JUMP)DoNewCsi;
				break;
		}
	}

		/* Create all generic lists. */

	for(i = GLIST_UPLOAD ; i < GLIST_COUNT ; i++)
	{
		if(!(GenericListTable[i] = CreateGenericList()))
			return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));
	}

		/* Load the trap settings. */

	strcpy(LastTraps,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastTraps,	"trap.prefs",MAX_FILENAME_LENGTH);

	WatchTraps = TRUE;

	LoadTraps(LastTraps,GenericListTable[GLIST_TRAP]);

		/* Create the special event queue. */

	if(!(SpecialQueue = CreateMsgQueue(NULL,0)))
		return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));

		/* Set up the serial driver. */

	if(Error = CreateSerial())
	{
		MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Error);

		DeleteSerial();
	}
	else
	{
		if(SerialMessage)
		{
			MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SerialMessage);

			SerialMessage = NULL;
		}
	}

		/* Get a signal bit. */

	if((CheckBit = AllocSignal(-1)) == -1)
		return(LocaleString(MSG_TERMINIT_FAILED_TO_GET_CHECK_SIGNAL_TXT));

	if(!(TimePort = (struct MsgPort *)CreateMsgPort()))
		return(LocaleString(MSG_GLOBAL_FAILED_TO_CREATE_MSGPORT_TXT));

	if(!(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest))))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_CREATE_IOREQUEST_TXT));

	if(OpenDevice("timer.device",UNIT_VBLANK,TimeRequest,0))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_TIMER_DEVICE_TXT));

	TimerBase = &TimeRequest -> tr_node . io_Device -> dd_Library;

		/* Add the global term port. */

	if(!TermPort)
	{
		if(!(TermPort = (struct TermPort *)AllocVec(sizeof(struct TermPort) + 11,MEMF_PUBLIC|MEMF_CLEAR)))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_CREATE_GLOBAL_PORT_TXT));
		else
		{
			NewList(&TermPort -> ExecNode . mp_MsgList);

			InitSemaphore(&TermPort -> OpenSemaphore);

			TermPort -> ExecNode . mp_Flags			= PA_IGNORE;
			TermPort -> ExecNode . mp_Node . ln_Name	= (char *)(TermPort + 1);

			strcpy(TermPort -> ExecNode . mp_Node . ln_Name,"term Port");

			AddPort(&TermPort -> ExecNode);
		}
	}

		/* Keep another term task from removing the port. */

	TermPort -> HoldIt = TRUE;

		/* Install a new term process. */

	ObtainSemaphore(&TermPort -> OpenSemaphore);

	TermPort -> OpenCount++;

	TermPort -> HoldIt = FALSE;

	TermID = TermPort -> ID++;

	ReleaseSemaphore(&TermPort -> OpenSemaphore);

		/* Set up the ID string. */

	if(TermID)
		SPrintf(TermIDString,"TERM.%ld",TermID);
	else
		strcpy(TermIDString,"TERM");

	if(RexxPortName[0])
	{
		WORD i;

		for(i = 0 ; i < strlen(RexxPortName) ; i++)
			RexxPortName[i] = ToUpper(RexxPortName[i]);

		if(FindPort(RexxPortName))
			RexxPortName[0] = 0;
	}

	if(!RexxPortName[0])
		strcpy(RexxPortName,TermIDString);

		/* Install the hotkey handler. */

	SetupCx();

		/* Allocate the first few lines for the display buffer. */

	if(!CreateBuffer())
		return(LocaleString(MSG_TERMINIT_FAILED_TO_ALLOCATE_VIEW_BUFFER_TXT));

	if(!(XprIO = (struct XPR_IO *)AllocVec(sizeof(struct XPR_IO),MEMF_ANY|MEMF_CLEAR)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_CREATE_PROTOCOL_BUFFER_TXT));

		/* Set up the external emulation macro data. */

	if(!(XEM_MacroKeys = (struct XEmulatorMacroKey *)AllocVecPooled((2 + 10 * 4) * sizeof(struct XEmulatorMacroKey),MEMF_ANY|MEMF_CLEAR)))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_ALLOCATE_MACRO_KEY_DATA_TXT));

	strcpy(LastXprLibrary,Config -> TransferConfig -> DefaultLibrary);

	ProtocolSetup(FALSE);

		/* Load a keymap file if required. */

	if(Config -> TerminalConfig -> KeyMapFileName[0])
		KeyMap = LoadKeyMap(Config -> TerminalConfig -> KeyMapFileName);

	if(!(TermRexxPort = (struct MsgPort *)CreateMsgPort()))
		return(LocaleString(MSG_GLOBAL_FAILED_TO_CREATE_MSGPORT_TXT));

		/* If rexxsyslib.library opens cleanly it's time for
		 * us to create the background term Rexx server.
		 */

	if(RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME,0))
	{
			/* Create a background process handling the
			 * rexx messages asynchronously.
			 */

		Forbid();

		if(RexxProcess = (struct Process *)CreateNewProcTags(
			NP_Entry,	RexxServer,
			NP_Name,	"term Rexx Process",
			NP_Priority,	5,
			NP_StackSize,	8192,
			NP_WindowPtr,	-1,
		TAG_END))
		{
			ClrSignal(SIG_HANDSHAKE);

			Wait(SIG_HANDSHAKE);
		}

		Permit();

		if(!RexxProcess)
			return(LocaleString(MSG_TERMINIT_UNABLE_TO_CREATE_AREXX_PROCESS_TXT));
	}

		/* Install the public screen name, assumes that the user
		 * wants the window to be opened on the screen, rather than
		 * opening a custom screen.
		 */

	if(SomePubScreenName[0])
	{
		strcpy(Config -> ScreenConfig -> PubScreenName,SomePubScreenName);

		Config -> ScreenConfig -> Blinking	= FALSE;
		Config -> ScreenConfig -> FasterLayout	= FALSE;
		Config -> ScreenConfig -> UseWorkbench	= TRUE;

		SomePubScreenName[0] = 0;
	}

	CreateQueueProcess();

	Forbid();

	RendezvousSemaphore . rs_Semaphore . ss_Link . ln_Name = RexxPortName;
	RendezvousSemaphore . rs_Semaphore . ss_Link . ln_Pri  = -127;

	AddSemaphore(&RendezvousSemaphore);

	Permit();

	if(DoIconify)
		return(NULL);
	else
	{
			/* Create the whole display. */

		if(Result = CreateDisplay(TRUE))
			return(Result);
		else
		{
			PubScreenStuff();

			return(NULL);
		}
	}
}
