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

#ifndef _GLOBAL_H
#include "Global.h"
#endif

	// The default public screen, if it is locked

STATIC struct Screen *DefaultPubScreen;

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

STATIC BOOLEAN HadFastMacros = FALSE;

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

STATIC BOOLEAN AllocatedPens = FALSE;

	/* Initialized at setup time, determines if the speech
	 * synthesizer is available.
	 */

STATIC BOOLEAN SpeechAvailable = FALSE;

	/* SafeOpenLibrary(STRPTR Name,LONG Version):
	 *
	 *	Try to open a library, but if there already is
	 *	a version in memory that's older than the release
	 *	we want flush it out first.
	 */

struct Library *
SafeOpenLibrary(STRPTR Name,LONG Version)
{
	struct Library *Base;

	Forbid();

		/* Is this library already in memory? */

	if(Base = (struct Library *)FindName(&SysBase -> LibList,FilePart(Name)))
	{
			/* An old release? */

		if(Base -> lib_Version < Version)
		{
				/* Flush it out. */

			RemLibrary(Base);
		}
	}

	Permit();

		/* Now reopen the library. */

	return(OpenLibrary(Name,Version));
}

	/* TTYResize():
	 *
	 *	Signal AmigaUW that the window size has changed.
	 */

VOID
TTYResize()
{
	if(Window)
	{
		LONG	Lines,Columns;
		BOOL	GotIt = TRUE;

		if(XEmulatorBase && XEM_IO)
		{
			if(XEmulatorBase -> lib_Version >= 4)
			{
				ULONG Result = XEmulatorInfo(XEM_IO,XEMI_CONSOLE_DIMENSIONS);

				Columns	= XEMI_EXTRACT_COLUMNS(Result);
				Lines	= XEMI_EXTRACT_LINES(Result);
			}
			else
				GotIt = FALSE;
		}
		else
		{
			Columns	= LastColumn + 1;
			Lines	= LastLine + 1;
		}

		if(GotIt && WriteRequest)
		{
			WriteRequest -> IOSer . io_Command	= UWCMD_TTYRESIZE;
			WriteRequest -> IOSer . io_Data		= (APTR)((Columns << 16) | (Lines));
			WriteRequest -> IOSer . io_Length	= (WindowWidth << 16) | (WindowHeight);

			DoIO(WriteRequest);
		}
	}
}

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

STATIC struct KeyMap *
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)
{
	FreeVecPooled(OffsetXTable);
	OffsetXTable = NULL;

	FreeVecPooled(OffsetYTable);
	OffsetYTable = NULL;
}

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

STATIC BOOL
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
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
CopyMenuFlags(struct Menu *Src,struct Menu *Dst)
{
	struct MenuItem *SrcItem,*DstItem;

	while(Src && Dst)
	{
			// Don't touch the quick dial menu. If CopyMenuFlags()
			// is called its contents are likely to have changed

		if((ULONG)GTMENU_USERDATA(Src) == DIAL_MENU_LIMIT)
			break;

		SrcItem = Src -> FirstItem;
		DstItem = Dst -> FirstItem;

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

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

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

	/* AttachMenu():
	 *
	 *	Rebuild the main menu (if necessary) and attach it to the other windows.
	 */

BOOL
AttachMenu(struct Menu *ThisMenu)
{
	if(!ThisMenu)
		ThisMenu = BuildMenu();

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

			if(Window)
				ClearMenuStrip(Window);

			if(StatusWindow)
				ClearMenuStrip(StatusWindow);

			if(FastWindow)
				ClearMenuStrip(FastWindow);

			LT_DisposeMenu(Menu);
		}

		Menu = ThisMenu;

		if(Window)
			SetMenuStrip(Window,Menu);

		if(StatusWindow)
			SetMenuStrip(StatusWindow,Menu);

		if(FastWindow)
			SetMenuStrip(FastWindow,Menu);

		return(TRUE);
	}
	else
		return(FALSE);
}

	/* DisconnectDialMenu():
	 *
	 *	Disconnect the quick dial menu as its contents will
	 *	be invalid. This may happen if `term' fails to rebuild
	 *	the main menu due to memory shortage. Please note that
	 *	disconnecting the menu this way is legal only for menus
	 *	created by gtlayout.library.
	 */

VOID
DisconnectDialMenu()
{
	if(Menu)
	{
		struct Menu *ThisMenu,*LastMenu = NULL;

		if(Window)
			ClearMenuStrip(Window);

		if(StatusWindow)
			ClearMenuStrip(StatusWindow);

		if(FastWindow)
			ClearMenuStrip(FastWindow);

		for(ThisMenu = Menu ; ThisMenu ; LastMenu = ThisMenu, ThisMenu = ThisMenu -> NextMenu)
		{
			if(!ThisMenu -> NextMenu && (ULONG)GTMENU_USERDATA(ThisMenu) == DIAL_MENU_LIMIT)
			{
				LastMenu -> NextMenu = NULL;
				break;
			}
		}

		if(Window)
			SetMenuStrip(Window,Menu);

		if(StatusWindow)
			SetMenuStrip(StatusWindow,Menu);

		if(FastWindow)
			SetMenuStrip(FastWindow,Menu);
	}
}

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

struct Menu *
BuildMenu()
{
	LONG PhoneCount,Grouped,NotGrouped,Groups,Separator,i,j;

	PhoneCount = 0;

		// Add the quick dial entries. This is not your basic
		// O(N) algorithm :-/

	if(Phonebook)
	{
		Grouped = NotGrouped = Groups = 0;

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

					// Check if this entry is in a group

				if(Phonebook[i] -> ThisGroup)
				{
					BOOL Unique = TRUE;

					Grouped++;

						// Are there other entries in this group?

					for(j = 0 ; j < i ; j++)
					{
						if(Phonebook[j] -> ThisGroup && Phonebook[j] -> ThisGroup == Phonebook[i] -> ThisGroup)
						{
							Unique = FALSE;

							break;
						}
					}

						// Is this the only one?

					if(Unique)
						Groups++;
				}
				else
					NotGrouped++;
			}
		}

			// Will we need to mix grouped and ungrouped entries?

		if(Grouped && NotGrouped)
			Separator = 1;
		else
			Separator = 0;
	}

		// Don't do the work if no quick dial menu needs to be built

	if(PhoneCount)
	{
		struct NewMenu *NewMenu;

			// Allocate new menu prototypes

		if(NewMenu = (struct NewMenu *)AllocVecPooled((NumMenuEntries + PhoneCount + Groups + Separator) * sizeof(struct NewMenu),MEMF_ANY | MEMF_CLEAR))
		{
			struct Menu	*ThisMenu;
			LONG		 Count;

				// Reset the menu type

			TermMenu[NumMenuEntries - 2] . nm_Type		= NM_TITLE;
			TermMenu[NumMenuEntries - 2] . nm_UserData	= (APTR)DIAL_MENU_LIMIT;

			CopyMem(TermMenu,NewMenu,NumMenuEntries * sizeof(struct NewMenu));

			FirstDialMenu = -1;

			Count = NumMenuEntries - 1;

				// Are we to pull entries just from one single group?

			if(Grouped == 1 && !NotGrouped)
			{
				for(i = 0 ; 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);
						NewMenu[Count] . nm_CommKey	= NULL;

						Count++;

						if(FirstDialMenu == -1)
							FirstDialMenu = DIAL_MENU_LIMIT + i;
					}
				}
			}
			else
			{
					// First step: collect the entries that don't belong into groups

				for(i = 0 ; i < NumPhoneEntries ; i++)
				{
					if(Phonebook[i] -> Header -> QuickMenu && !Phonebook[i] -> ThisGroup)
					{
						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);
						NewMenu[Count] . nm_CommKey	= NULL;

						Count++;

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

					// If there needs to be a separator, add it

				if(Separator)
				{
					NewMenu[Count] . nm_Type	= NM_ITEM;
					NewMenu[Count] . nm_Label	= NM_BARLABEL;
					NewMenu[Count] . nm_Flags	= NULL;
					NewMenu[Count] . nm_UserData	= NULL;
					NewMenu[Count] . nm_CommKey	= NULL;

					Count++;
				}

					// Second step: collect the remaining entries that belong into groups

				for(i = 0 ; i < NumPhoneEntries ; i++)
				{
					if(Phonebook[i] -> Header -> QuickMenu && Phonebook[i] -> ThisGroup)
					{
						BOOL Unique = TRUE;

						for(j = 0 ; j < i ; j++)
						{
							if(Phonebook[j] -> Header -> QuickMenu && Phonebook[j] -> ThisGroup && Phonebook[j] -> ThisGroup == Phonebook[i] -> ThisGroup)
							{
								Unique = FALSE;
								break;
							}
						}

						if(Unique)
						{
							LONG k;

							NewMenu[Count] . nm_Type	= NM_ITEM;
							NewMenu[Count] . nm_Label	= Phonebook[i] -> ThisGroup -> LocalName;
							NewMenu[Count] . nm_Flags	= NULL;
							NewMenu[Count] . nm_UserData	= NULL;
							NewMenu[Count] . nm_CommKey	= NULL;

							Count++;

							for(k = i ; k < NumPhoneEntries ; k++)
							{
								if(Phonebook[k] -> Header -> QuickMenu && Phonebook[k] -> ThisGroup == Phonebook[i] -> ThisGroup)
								{
									NewMenu[Count] . nm_Type	= NM_SUB;
									NewMenu[Count] . nm_Label	= Phonebook[k] -> Header -> Name;
									NewMenu[Count] . nm_Flags	= CHECKIT;
									NewMenu[Count] . nm_UserData	= (APTR)(DIAL_MENU_LIMIT + k);
									NewMenu[Count] . nm_CommKey	= NULL;

									Count++;

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

			}

			NewMenu[Count] . nm_Type = NM_END;

				// If the speech synthesizer is not available, disconnect
				// the speech settings menu item

			for(i = Count - 1 ; i >= 0 ; i--)
			{
				if(TermMenu[i].nm_UserData == (APTR)MEN_SPEECH)
				{
					if(SpeechAvailable)
						TermMenu[i].nm_Type = NM_ITEM;
					else
						TermMenu[i].nm_Type = NM_IGNORE;
				}

				if(TermMenu[i].nm_UserData == (APTR)MEN_EXECUTE_REXX_COMMAND)
				{
					if(!RexxSysBase)
						TermMenu[i].nm_Type = NM_IGNORE;

					break;
				}
			}

				// Now layout the menu

			ThisMenu = LT_NewMenuTemplate(Window -> WScreen,NULL,AmigaGlyph,CheckGlyph,NULL,NewMenu);

				// We don't need this any more

			FreeVecPooled(NewMenu);

				// Successful?

			if(ThisMenu)
				return(ThisMenu);
		}
	}

		// If the speech synthesizer is not available, disconnect
		// the speech settings menu item

	for(i = NumMenuEntries - 1 ; i >= 0 ; i--)
	{
		if(TermMenu[i].nm_UserData == (APTR)MEN_SPEECH)
		{
			if(SpeechAvailable)
				TermMenu[i].nm_Type = NM_ITEM;
			else
				TermMenu[i].nm_Type = NM_IGNORE;

			break;
		}
	}

		// Disconnect the quick dial menu

	TermMenu[NumMenuEntries - 2] . nm_Type = NM_END;

		// Create the default menu strip

	return(LT_NewMenuTemplate(Window -> WScreen,NULL,AmigaGlyph,CheckGlyph,NULL,TermMenu));
}

	/* UpdateTerminalLimits():
	 *
	 *	Check the current window size and extract the
	 *	size and position of the usable window rectangle.
	 */

VOID
UpdateTerminalLimits()
{
	WindowLeft	= Window -> BorderLeft;
	WindowTop	= Window -> BorderTop;

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

	if(StatusWindow)
	{
		StatusDisplayLeft	= StatusWindow -> BorderLeft;
		StatusDisplayTop	= StatusWindow -> BorderTop;
		StatusDisplayWidth	= StatusWindow -> Width - (StatusWindow -> BorderLeft + StatusWindow -> BorderRight);
		StatusDisplayHeight	= StatusWindow -> Height - (StatusWindow -> BorderTop + StatusWindow -> BorderBottom);
	}
	else
	{
		if(Config -> ScreenConfig -> StatusLine != STATUSLINE_DISABLED && !(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Config -> TerminalConfig -> EmulationFileName[0]))
		{
			StatusDisplayLeft	= WindowLeft;
			StatusDisplayTop	= Window -> Height - (Window -> BorderBottom + StatusDisplayHeight);
			StatusDisplayWidth	= WindowWidth;

			WindowHeight -= StatusDisplayHeight;
		}
	}

	if(ChatMode && !(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Config -> TerminalConfig -> EmulationFileName[0]))
	{
		if(CreateChatGadget())
		{
			UpdateChatGadget();

			WindowHeight -= (UserFontHeight + 2);

			ActivateChat(FALSE);
		}
	}
}

	/* Current2DefaultPalette(struct Configuration *SomeConfig):
	 *
	 *	Copy the current colour palette into the
	 *	default tables.
	 */

VOID
Current2DefaultPalette(struct Configuration *SomeConfig)
{
	ColourTable	*Table = NULL;
	UWORD		*Colour12;

	if(!SomeConfig)
		SomeConfig = Config;

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

			if(Kick30)
			{
				if(!ANSIColourTable)
					ANSIColourTable = CreateColourTable(8,ANSIColours,NULL);

				Table = ANSIColourTable;
			}

			Colour12 = ANSIColours;

			break;

		case COLOUR_SIXTEEN:

			if(Kick30)
			{
				if(!EGAColourTable)
					EGAColourTable = CreateColourTable(16,EGAColours,NULL);

				Table = EGAColourTable;
			}

			Colour12 = EGAColours;

			break;

		case COLOUR_AMIGA:

			if(Kick30)
			{
				if(!DefaultColourTable)
					DefaultColourTable = CreateColourTable(16,DefaultColours,NULL);

				Table = DefaultColourTable;
			}

			Colour12 = DefaultColours;

			break;

		case COLOUR_MONO:

			if(Kick30)
			{
				if(!MonoColourTable)
					MonoColourTable = CreateColourTable(2,AtomicColours,NULL);

				Table = MonoColourTable;
			}

			Colour12 = AtomicColours;
			break;
	}

	if(Table)
	{
		if(SomeConfig -> ScreenConfig -> UseColours96)
			Colour96xColourTable(SomeConfig -> ScreenConfig -> Colours96,Table,Table -> NumColours);
		else
		{
			Colour12xColourTable(SomeConfig -> ScreenConfig -> Colours,Table,Table -> NumColours);

			Colour12x96(SomeConfig -> ScreenConfig -> Colours,SomeConfig -> ScreenConfig -> Colours96,16);

			SomeConfig -> ScreenConfig -> UseColours96 = TRUE;
		}
	}

	CopyMem(SomeConfig -> ScreenConfig -> Colours,Colour12,16 * sizeof(UWORD));
}

	/* Default2CurrentPalette(struct Configuration *SomeConfig):
	 *
	 *	Copy the default palette to the current palette.
	 */

VOID
Default2CurrentPalette(struct Configuration *SomeConfig)
{
	ColourTable	*Table = NULL;
	UWORD		*Colour12;

	if(!SomeConfig)
		SomeConfig = Config;

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

			Table		= ANSIColourTable;
			Colour12	= ANSIColours;

			break;

		case COLOUR_SIXTEEN:

			Table		= EGAColourTable;
			Colour12	= EGAColours;

			break;

		case COLOUR_AMIGA:

			Table		= DefaultColourTable;
			Colour12	= DefaultColours;

			break;

		case COLOUR_MONO:

			Table		= MonoColourTable;
			Colour12	= AtomicColours;

			break;
	}

	CopyMem(Colour12,SomeConfig -> ScreenConfig -> Colours,16 * sizeof(UWORD));

	if(Table)
	{
		ColourTablex96(Table,SomeConfig -> ScreenConfig -> Colours96);

		SomeConfig -> ScreenConfig -> UseColours96 = TRUE;
	}
	else
		SomeConfig -> ScreenConfig -> UseColours96 = FALSE;
}

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

VOID
PaletteSetup(struct Configuration *SomeConfig)
{
	LONG i;

	if(!SomeConfig)
		SomeConfig = Config;

	if(SomeConfig -> ScreenConfig -> UseColours96)
	{
		Colour96x12(SomeConfig -> ScreenConfig -> Colours96,NormalColours,16);
		Colour96x12(SomeConfig -> ScreenConfig -> Colours96,SomeConfig -> ScreenConfig -> Colours,16);
	}
	else
	{
		CopyMem(SomeConfig -> ScreenConfig -> Colours,NormalColours,16 * sizeof(UWORD));

		Colour12x96(NormalColours,SomeConfig -> ScreenConfig -> Colours96,16);

		SomeConfig -> ScreenConfig -> UseColours96 = TRUE;
	}

	CopyMem(NormalColours,&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(GetBitMapDepth(Window -> WScreen -> RastPort . BitMap) >= 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;
	}

	if(Kick30)
	{
		if(NormalColourTable)
			DeleteColourTable(NormalColourTable);

		if(BlinkColourTable)
			DeleteColourTable(BlinkColourTable);

		if(NormalColourTable = CreateColourTable(PaletteSize,NULL,SomeConfig -> ScreenConfig -> Colours96))
		{
			if(PaletteSize == 2 || !SomeConfig -> ScreenConfig -> Blinking)
				BlinkColourTable = NULL;
			else
			{
				if(BlinkColourTable = CreateColourTable(PaletteSize,NULL,NULL))
				{
					switch(SomeConfig -> ScreenConfig -> ColourMode)
					{
						case COLOUR_EIGHT:

							for(i = 0 ; i < 8 ; i++)
							{
								CopyColourEntry(NormalColourTable,NormalColourTable,i,8 + i);
								CopyColourEntry(NormalColourTable,BlinkColourTable,i,i);
								CopyColourEntry(NormalColourTable,BlinkColourTable,0,8 + i);
							}

							break;

						case COLOUR_SIXTEEN:

							if(GetBitMapDepth(Window -> WScreen -> RastPort . BitMap) >= 5)
							{
								for(i = 0 ; i < 16 ; i++)
								{
									CopyColourEntry(NormalColourTable,NormalColourTable,i,16 + i);
									CopyColourEntry(NormalColourTable,BlinkColourTable,i,i);
									CopyColourEntry(NormalColourTable,BlinkColourTable,0,16 + i);
								}
							}
							else
							{
								DeleteColourTable(BlinkColourTable);

								BlinkColourTable = NULL;
							}

							break;

						case COLOUR_AMIGA:

							for(i = 0 ; i < 4 ; i++)
								CopyColourEntry(NormalColourTable,BlinkColourTable,i,i);

							CopyColourEntry(BlinkColourTable,BlinkColourTable,0,3);

							break;
					}
				}
				else
				{
					DeleteColourTable(NormalColourTable);

					NormalColourTable = NULL;
				}
			}
		}
	}
}

	/* ResetHotkeys(struct Hotkeys *Hotkeys):
	 *
	 *	Reset hotkey assignments to defaults.
	 */

STATIC VOID
ResetHotkeys(struct Hotkeys *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;
}

	/* ResetSpeechConfig(struct SpeechConfig *SpeechConfig):
	 *
	 *	Reset speech configuration to defaults.
	 */

STATIC VOID
ResetSpeechConfig(struct SpeechConfig *SpeechConfig)
{
	SpeechConfig->Rate	= DEFRATE;
	SpeechConfig->Pitch	= DEFPITCH;
	SpeechConfig->Frequency	= DEFFREQ;
	SpeechConfig->Volume	= DEFVOL;
	SpeechConfig->Sex	= DEFSEX;
	SpeechConfig->Enabled	= FALSE;
}

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

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

	LONG i,j;

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

	/* ResetSound(struct SoundConfig *SoundConfig):
	 *
	 *	Reset the sound settings to defaults.
	 */

STATIC VOID
ResetSound(struct SoundConfig *SoundConfig)
{
	memset(SoundConfig,0,sizeof(struct SoundConfig));

	SoundConfig -> Volume = 100;

	strcpy(SoundConfig -> BellFile,Config -> TerminalConfig -> BeepFileName);
}

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

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

	LONG i;

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

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

	/* LoadDefaultTranslationTables(STRPTR FileName):
	 *
	 *	Load the default character translation file.
	 */

STATIC BOOL
LoadDefaultTranslationTables(STRPTR FileName)
{
	BOOL Success = FALSE;

	if(SendTable = AllocTranslationTable())
	{
		if(ReceiveTable = AllocTranslationTable())
		{
			BOOL ReleaseIt;

			if(LoadTranslationTables(FileName,SendTable,ReceiveTable))
			{
				ReleaseIt = (BOOL)(IsStandardTable(SendTable) && IsStandardTable(ReceiveTable));

				Success = TRUE;
			}
			else
				ReleaseIt = TRUE;

			if(ReleaseIt)
			{
				FreeTranslationTable(SendTable);
				SendTable = NULL;

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

	return(Success);
}

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

VOID
ScreenSizeStuff()
{
	ObtainSemaphore(&TerminalSemaphore);

		/* 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,BgPen = MappedPens[0][PenTable[0]]);

			SetMask(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 > LastPrintableColumn)
			CursorX = LastPrintableColumn;

			/* Fix scroll region button. */

		if(!RegionSet)
			Bottom = LastLine;

			/* Turn the cursor back on. */

		DrawCursor();
	}

	FixScreenSize = FALSE;

	ReleaseSemaphore(&TerminalSemaphore);
}

	/* 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
		{
			struct Screen *PubScreen;

			PublicModes &= ~SHANGHAI;

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

				UnlockPubScreen(NULL,PubScreen);
			}
			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()
{
	BOOL RasterWasEnabled,WindowSizeUpdate,WantCustomScreen;

	RasterWasEnabled = RasterEnabled;
	WindowSizeUpdate = FALSE;

		// See if we want a custom screen

	if(Config -> ScreenConfig -> UseWorkbench || Config -> ScreenConfig -> ShareScreen)
		WantCustomScreen = FALSE;
	else
		WantCustomScreen = TRUE;

		/* Hide or show the upload queue icon. */

	ToggleUploadQueueIcon(Config -> TransferConfig -> HideUploadIcon);

		/* Take care of the end-of-line translation. */

	Update_CR_LF_Translation();

		/* 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 -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Config -> TerminalConfig -> EmulationMode != EMULATION_EXTERNAL) || (PrivateConfig -> TerminalConfig -> EmulationMode != EMULATION_EXTERNAL && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL))
		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 -> AutoSize != Config -> TerminalConfig -> AutoSize && !WantCustomScreen)
	{
		if(Config -> TerminalConfig -> AutoSize)
			FixScreenSize = TRUE;
		else
			WindowSizeUpdate = 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;

	if(PrivateConfig -> EmulationConfig -> UseStandardPens != Config -> EmulationConfig -> UseStandardPens)
		ResetDisplay = TRUE;

	if(!Config -> EmulationConfig -> UseStandardPens && (memcmp(Config -> EmulationConfig -> Pens,PrivateConfig -> EmulationConfig -> Pens,sizeof(Config -> EmulationConfig -> Pens)) || memcmp(Config -> EmulationConfig -> Attributes,PrivateConfig -> EmulationConfig -> Attributes,sizeof(Config -> EmulationConfig -> Attributes))))
		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(!WantCustomScreen)
				WindowSizeUpdate = TRUE;
			else
				ResetDisplay = TRUE;
		}
	}

	if(!ResetDisplay && WindowSizeUpdate)
	{
		LONG	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;

			// Add the status line size if necessary

		if(!StatusWindow && Config -> ScreenConfig -> StatusLine != STATUSLINE_DISABLED && !(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Config -> TerminalConfig -> EmulationFileName[0]))
			Height += StatusDisplayHeight;

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

		FixScreenSize = 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) || memcmp(PrivateConfig -> ScreenConfig -> Colours96,Config -> ScreenConfig -> Colours96,sizeof(ColourEntry) * 16)))
		Current2DefaultPalette(Config);

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

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

				ProtocolSetup(FALSE);
			}
		}
		else
			CloseXPR();
	}
	else
	{
		CloseXPR();

		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 -> MacroFileName[0] && Stricmp(PrivateConfig -> MacroFileName,Config -> MacroFileName))
	{
		if(!LoadMacros(Config -> MacroFileName,MacroKeys))
			ResetMacroKeys(MacroKeys);
		else
			strcpy(LastMacros,Config -> MacroFileName);
	}

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

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

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

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

			SendTable = NULL;
		}

		if(ReceiveTable)
		{
			FreeTranslationTable(ReceiveTable);

			ReceiveTable = NULL;
		}

		if(SendTable = AllocTranslationTable())
		{
			if(ReceiveTable = AllocTranslationTable())
			{
				if(LoadTranslationTables(Config -> TranslationFileName,SendTable,ReceiveTable))
				{
					strcpy(LastTranslation,Config -> 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 -> FastMacroFileName[0] && Stricmp(PrivateConfig -> FastMacroFileName,Config -> FastMacroFileName))
	{
		if(FastWindow)
			LT_LockWindow(FastWindow);

		FreeList(&FastMacroList);

		if(LoadFastMacros(Config -> FastMacroFileName,&FastMacroList))
		{
			strcpy(LastFastMacros,Config -> FastMacroFileName);
			FastMacroCount = GetListSize(&FastMacroList);
		}

		if(FastWindow)
		{
			RefreshFastWindow(TRUE);

			LT_UnlockWindow(FastWindow);
		}
	}

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

					ShowRequest(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(FALSE);
			}
			else
				RasterEnabled = TRUE;
		}

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

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

			LoadColourTable(VPort,NormalColourTable,NormalColours,PaletteSize);
		}

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

		PubScreenStuff();

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

			if(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Config -> TerminalConfig -> EmulationFileName[0])
				OffItem(MEN_CHAT_LINE);
			else
				CheckItem(MEN_CHAT_LINE,ChatMode);

			SetTransferMenu(TRUE);

			SetRasterMenu(RasterEnabled);

			if(MatrixWindow)
				CheckItem(MEN_MATRIX_WINDOW,TRUE);

			if(InfoWindow)
				CheckItem(MEN_STATUS_WINDOW,TRUE);

			if(PacketWindow)
				CheckItem(MEN_PACKET_WINDOW,TRUE);

			if(ChatMode)
				CheckItem(MEN_CHAT_LINE,TRUE);

			if(FastWindow)
				CheckItem(MEN_FAST_MACROS_WINDOW,TRUE);

				/* Disable the dialing functions if online. */

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

		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(FALSE);
			}
		}

		RasterEnabled = TRUE;
		FixScreenSize = FALSE;
	}

		/* 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.
	 */

BOOL
DisplayReset()
{
	UBYTE	*Result;
	BOOL	 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();

			ShowRequest(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();

		ShowRequest(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.).
	 */

BOOL
DeleteDisplay()
{
	struct Screen *WhichScreen;

	if(SharedScreen)
		WhichScreen = SharedScreen;
	else
		WhichScreen = Screen;

	if(WhichScreen)
	{
		if(!(PubScreenStatus(WhichScreen,PSNF_PRIVATE) & PSNF_PRIVATE))
			return(FALSE);
	}

	GuideCleanup();

	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();

	CloseEmulator(FALSE);

	DeleteRaster();

	DeleteScale();

	FreeVecPooled(TabStops);
	TabStops = NULL;

	FreeVecPooled(ScrollLines);
	ScrollLines = NULL;

	if(Screen)
		ScreenToBack(Screen);

	if(FastWindow)
	{
		HadFastMacros = TRUE;

		CloseFastWindow();
	}
	else
		HadFastMacros = FALSE;

	if(MatrixWindow)
		CloseMatrixWindow();

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

		StatusWindow = 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;
	}

	HideChatGadget();

	DeletePacketWindow(FALSE);

	if(Window)
	{
		if(!Screen)
			PutWindowInfo(WINDOW_MAIN,Window -> LeftEdge,Window -> TopEdge,Window -> Width,Window -> Height);

		if(AllocatedPens && Kick30)
		{
			LONG i;

			ObtainSemaphore(&TerminalSemaphore);

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

			FillBox(RPort,WindowLeft,WindowTop,WindowWidth,WindowHeight);

				/* Release any pens we have allocated. */

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

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

			AllocatedPens = FALSE;

			ReleaseSemaphore(&TerminalSemaphore);
		}

		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(Menu)
	{
		LT_DisposeMenu(Menu);
		Menu = NULL;
	}

	FreeVisualInfo(VisualInfo);
	VisualInfo = 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)
		{
			struct Screen *PubScreen;

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

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

		/* Clean up the menu glyphs. */

	DisposeObject(AmigaGlyph);

	AmigaGlyph = NULL;

	DisposeObject(CheckGlyph);

	CheckGlyph = NULL;

	if(Screen)
	{
		CloseScreen(Screen);

		Screen = NULL;
	}

	if(SharedScreen)
	{
		CloseScreen(SharedScreen);

		SharedScreen = NULL;
	}

	UnlockPubScreen(NULL,DefaultPubScreen);
	DefaultPubScreen = NULL;

	if(GFX)
	{
		CloseFont(GFX);

		GFX = NULL;
	}

	if(TextFont)
	{
		CloseFont(TextFont);

		TextFont = NULL;
	}

	if(UserTextFont)
	{
		CloseFont(UserTextFont);

		UserTextFont = NULL;
	}

	return(TRUE);
}

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

	if(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Config -> TerminalConfig -> EmulationFileName[0] && Config -> ScreenConfig -> StatusLine != STATUSLINE_DISABLED && !Config -> ScreenConfig -> SplitStatus)
	{
		*StatusHeight = 0;

		return;
	}

	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;
			LONG	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 += 4 + 3 * InterWidth;

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

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

STRPTR
CreateDisplay(BOOL FirstSetup)
{
	LONG			Count = 0,i;
	LONG			ErrorCode,Top,Height;
	ULONG			TagArray[9];
	struct Rectangle	DisplayClip;
	BOOL			OpenFailed = FALSE;
	LONG			RealDepth;
	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);

			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;
		}
	}

	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)
		{
			UnlockPubScreen(NULL,DefaultPubScreen);
			DefaultPubScreen = NULL;

			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)))
			{
				UnlockPubScreen(NULL,DefaultPubScreen);
				DefaultPubScreen = NULL;

				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)))
		{
			UnlockPubScreen(NULL,DefaultPubScreen);
			DefaultPubScreen = NULL;

			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 = TextFontHeight;

	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;

		// We will need this one later

	OpenWindowTag = WA_CustomScreen;

	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	Width	= DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,
						Height	= DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1;

					if(Width != Config -> ScreenConfig -> DisplayWidth && Config -> ScreenConfig -> DisplayWidth)
						Config -> ScreenConfig -> DisplayWidth = Width;

					if(Height != Config -> ScreenConfig -> DisplayHeight && Config -> ScreenConfig -> DisplayHeight)
						Config -> ScreenConfig -> DisplayHeight = Height;
				}
			}

			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 && AslBase -> lib_Version >= 38)
				{
					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;

#if defined(_M68030)
				SPrintf(ScreenTitle,LocaleString(MSG_TERMINIT_SCREENTITLE_TXT),TermName,"'030 ",TermDate,TermIDString);
#endif

#if defined(_M68040)
				SPrintf(ScreenTitle,LocaleString(MSG_TERMINIT_SCREENTITLE_TXT),TermName,"'040 ",TermDate,TermIDString);
#endif

#if !defined(_M68030) && !defined(_M68040)
				SPrintf(ScreenTitle,LocaleString(MSG_TERMINIT_SCREENTITLE_TXT),TermName,"",TermDate,TermIDString);
#endif	/* _M68030 */

				StatusSizeSetup(NULL,&StatusWidth,&StatusHeight);

				if(StatusHeight && StatusWidth > ScreenWidth)
					ScreenWidth = StatusWidth;

				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,	AslBase -> lib_Version >= 38 ? Config -> ScreenConfig -> OverscanType : OSCAN_TEXT,
					SA_DisplayID,	Config -> ScreenConfig -> DisplayMode,
					SA_Font,	&UserFont,
					SA_AutoScroll,	TRUE,
					SA_ShowTitle,	Config -> ScreenConfig -> TitleBar,
					SA_PubName,	TermIDString,
					SA_Interleaved,	Config -> ScreenConfig -> FasterLayout,
					SA_SharePens,	TRUE,
				TAG_DONE))
				{
					LocalScreen = SharedScreen;

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

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

#if defined(_M68040)
			SPrintf(ScreenTitle,"%s '040 (%s)",TermName,TermDate);
#endif

#if !defined(_M68030) && !defined(_M68040)
			SPrintf(ScreenTitle,"%s (%s)",TermName,TermDate);
#endif
		}

		StatusSizeSetup(LocalScreen,&StatusWidth,&StatusHeight);

		if(GetBitMapDepth(LocalScreen -> RastPort . BitMap) == 1 || Config -> ScreenConfig -> FasterLayout)
			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 << GetBitMapDepth(LocalScreen -> RastPort . BitMap)) - 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)))
		{
			UnlockPubScreen(NULL,DefaultPubScreen);
			DefaultPubScreen = NULL;

			return(LocaleString(MSG_TERMINIT_FAILED_TO_OBTAIN_SCREEN_DRAWINFO_TXT));
		}
		else
			Pens = DrawInfo->dri_Pens;

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

		SZ_SizeSetup(LocalScreen,&UserFont);

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

		if(!(VisualInfo = GetVisualInfo(LocalScreen,TAG_DONE)))
		{
				/* Delete the DrawInfo now, or it won't
				 * get freed during shutdown.
				 */

			FreeScreenDrawInfo(LocalScreen,DrawInfo);
			DrawInfo = NULL;

			UnlockPubScreen(NULL,DefaultPubScreen);
			DefaultPubScreen = NULL;

			return(LocaleString(MSG_TERMINIT_FAILED_TO_OBTAIN_VISUAL_INFO_TXT));
		}

		if(Config -> ScreenConfig -> StatusLine != STATUSLINE_DISABLED && !Config -> ScreenConfig -> SplitStatus)
			FullWidth = StatusWidth;
		else
			FullWidth = 0;

		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
		{
			LONG WindowLeft = -1,WindowTop = -1,DummyWidth,DummyHeight;

			GetWindowInfo(WINDOW_MAIN,&WindowLeft,&WindowTop,&DummyWidth,&DummyHeight,0,0);

			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 + StatusHeight;
			}

			if(WindowLeft != -1)
			{
				SomeTags[Index  ] . ti_Tag	= WA_Left;
				SomeTags[Index++] . ti_Data	= WindowLeft;
			}
			else
			{
				SomeTags[Index  ] . ti_Tag	= WA_Left;
				SomeTags[Index++] . ti_Data	= GetScreenLeft(NULL);
			}

			if(WindowTop != -1)
			{
				SomeTags[Index  ] . ti_Tag	= WA_Top;
				SomeTags[Index++] . ti_Data	= WindowTop;
			}
		}

		SomeTags[Index] . ti_Tag = TAG_DONE;

			// If we're using a public screen, take care of it.

		if(!SharedScreen)
			OpenWindowTag = WA_PubScreen;

			/* Open the main window. */

		if(!(Window = OpenWindowTags(NULL,
			WA_MaxHeight,		LocalScreen -> Height,
			WA_MaxWidth,		LocalScreen -> Width,
			WA_SmartRefresh,	TRUE,
			WA_NewLookMenus,	TRUE,
			WA_RMBTrap,		TRUE,
			WA_IDCMP,		DEFAULT_IDCMP | IDCMP_SIZEVERIFY,
			WA_DragBar,		TRUE,
			WA_DepthGadget,		TRUE,
			WA_CloseGadget,		TRUE,
			WA_SizeGadget,		TRUE,
			WA_SizeBBottom,		Config -> ScreenConfig -> StatusLine == STATUSLINE_DISABLED || Config -> ScreenConfig -> SplitStatus,
			WA_NoCareRefresh,	TRUE,
			WA_Title,		WindowTitle[0] ? WindowTitle : ScreenTitle,
			WA_MenuHelp,		TRUE,
			OpenWindowTag,		LocalScreen,

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

		TAG_MORE,SomeTags)))
		{
				/* Delete the DrawInfo now, or it won't
				 * get freed during shutdown.
				 */

			FreeScreenDrawInfo(LocalScreen,DrawInfo);
			DrawInfo = NULL;

			UnlockPubScreen(NULL,DefaultPubScreen);
			DefaultPubScreen = NULL;

			return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_WINDOW_TXT));
		}

		if(WindowTitle[0])
			SetWindowTitles(Window,(STRPTR)-1,ScreenTitle);

		if(StatusHeight)
		{
			StatusDisplayHeight = StatusHeight;

			CopyMem(Window -> RPort,StatusRPort = &StatusRastPort,sizeof(struct RastPort));
		}
		else
			StatusRPort = NULL;

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

		if(!(ClipRegion = NewRegion()))
		{
			UnlockPubScreen(NULL,DefaultPubScreen);
			DefaultPubScreen = NULL;

			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 + StatusHeight;

		if(ChatMode && !(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Config -> TerminalConfig -> EmulationFileName[0]))
			Height += UserFontHeight + 2;

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

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

					WorkbenchPort = NULL;
				}
			}
		}

		UnlockPubScreen(NULL,DefaultPubScreen);
		DefaultPubScreen = NULL;
	}
	else
	{
		struct DimensionInfo	DimensionInfo;
		LONG			MaxDepth,
					ScreenDepth;

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

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

				if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Config -> ScreenConfig -> DisplayMode))
				{
					LONG	Width	= DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,
						Height	= DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1;

					if(Width != Config -> ScreenConfig -> DisplayWidth && Config -> ScreenConfig -> DisplayWidth)
						Config -> ScreenConfig -> DisplayWidth = Width;

					if(Height != Config -> ScreenConfig -> DisplayHeight && Config -> ScreenConfig -> DisplayHeight)
						Config -> ScreenConfig -> DisplayHeight = Height;
				}

				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))
		{
			LONG	MaxWidth,
				MaxHeight,
				Width,
				Height;

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

			if(Config -> ScreenConfig -> DisplayWidth && Config -> ScreenConfig -> DisplayHeight && AslBase -> lib_Version >= 38)
			{
				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 += 4 + (2 + 2 * UserFontHeight + 2);
				}

				ScreenHeight = 0;
			}

			if(Height > MaxHeight)
				Height = MaxHeight;

			if(Width > MaxWidth)
				Width = MaxWidth;

			if(DimensionInfo . MinRasterWidth <= Width && Width <= DimensionInfo . MaxRasterWidth && Width < MaxWidth)
			{
				LONG 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:

					if(IntuitionBase -> LibNode . lib_Version >= 39)
						Data = NewEGAPens;
					else
						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;

#if defined(_M68030)
OpenS:		SPrintf(ScreenTitle,LocaleString(MSG_TERMINIT_SCREENTITLE_TXT),TermName,"'030 ",TermDate,TermIDString);
#endif

#if defined(_M68040)
OpenS:		SPrintf(ScreenTitle,LocaleString(MSG_TERMINIT_SCREENTITLE_TXT),TermName,"'040 ",TermDate,TermIDString);
#endif

#if !defined(_M68030) && !defined(_M68040)
OpenS:		SPrintf(ScreenTitle,LocaleString(MSG_TERMINIT_SCREENTITLE_TXT),TermName,"",TermDate,TermIDString);
#endif

		/* ALWAYS */
		{
			BOOL Interleaved;

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

			StatusSizeSetup(NULL,&StatusWidth,&StatusHeight);

			if(StatusHeight && StatusWidth > ScreenWidth)
				ScreenWidth = StatusWidth;

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

				SA_Title,	ScreenTitle,
				SA_Left,	DisplayClip . MinX,
				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(RealDepth > 1 && !Config -> ScreenConfig -> FasterLayout)
				{
					UseMasking = TRUE;

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

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

							Config -> ScreenConfig -> DisplayMode = GetVPModeID(&PubScreen -> ViewPort);

							if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Config -> ScreenConfig -> DisplayMode))
							{
								LONG	Width	= DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,
									Height	= DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1;

								if(Width != Config -> ScreenConfig -> DisplayWidth && Config -> ScreenConfig -> DisplayWidth)
									Config -> ScreenConfig -> DisplayWidth = Width;

								if(Height != Config -> ScreenConfig -> DisplayHeight && Config -> ScreenConfig -> DisplayHeight)
									Config -> ScreenConfig -> DisplayHeight = Height;
							}

							UnlockPubScreen(NULL,PubScreen);
						}
						else
							Config -> ScreenConfig -> DisplayMode = DEFAULT_MONITOR_ID | HIRESLACE_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));
		else
			Pens = DrawInfo->dri_Pens;

		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)))
		{
				/* Delete the DrawInfo now, or it won't
				 * get freed during shutdown.
				 */

			FreeScreenDrawInfo(Screen,DrawInfo);

			DrawInfo = NULL;

			return(LocaleString(MSG_TERMINIT_FAILED_TO_OBTAIN_VISUAL_INFO_TXT));
		}

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

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

			Height = Screen -> Height;
		}

			/* 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_CustomScreen,	Screen,
			WA_NewLookMenus,	TRUE,
			WA_RMBTrap,		TRUE,
			WA_IDCMP,		DEFAULT_IDCMP & ~IDCMP_CLOSEWINDOW,
			WA_MenuHelp,		TRUE,
			WA_NoCareRefresh,	TRUE,

			AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
			CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
		TAG_DONE)))
		{
				/* Delete the DrawInfo now, or it won't
				 * get freed during shutdown.
				 */

			FreeScreenDrawInfo(Screen,DrawInfo);

			DrawInfo = NULL;

			return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_WINDOW_TXT));
		}

		if(StatusHeight)
		{
			StatusDisplayHeight = StatusHeight;

			CopyMem(Window -> RPort,StatusRPort = &StatusRastPort,sizeof(struct RastPort));
		}
		else
			StatusRPort = NULL;
	}

		// Now check if a nonzero background colour should be used.

	if(Pens[BACKGROUNDPEN])
		BackfillTag = WA_BackFill;
	else
		BackfillTag = TAG_IGNORE;

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

	if(!Config -> ScreenConfig -> UseWorkbench && Initializing && !SharedScreen)
	{
		if(Kick30)
		{
			ULONG RGB[3 * 16];

			GetRGB32(VPort -> ColorMap,0,16,RGB);

			ANSIColourTable		= CreateColourTable(8,	ANSIColours,	NULL);
			EGAColourTable		= CreateColourTable(16,	EGAColours,	NULL);
			DefaultColourTable	= CreateColourTable(16,	NULL,		RGB);
			MonoColourTable		= CreateColourTable(2,	AtomicColours,	NULL);
		}

		for(i = 0 ; i < 16 ; i++)
			DefaultColours[i] = GetRGB4(VPort -> ColorMap,i);

		Initializing = FALSE;
	}

		/* Load the approriate colours. */

	if(LoadColours)
	{
		Default2CurrentPalette(Config);

		LoadColours = FALSE;
	}

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

	PaletteSetup(Config);

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

		/* Get the vanilla rendering pens. */

	RenderPens[0] = Pens[BACKGROUNDPEN];
	RenderPens[1] = Pens[TEXTPEN];
	RenderPens[2] = Pens[SHINEPEN];
	RenderPens[3] = 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;
			BOOL	GotAll = TRUE;
			LONG	NumPens;

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

			for(i = 0 ; i < 32 ; 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.
				 */

			if(NormalColourTable)
			{
				for(i = 0 ; i < NumPens ; i++)
				{
						/* Try to obtain a matching pen. */

					if((MappedPens[0][i] = ObtainBestPen(VPort -> ColorMap,NormalColourTable -> Entry[i] . Red,NormalColourTable -> Entry[i] . Green,NormalColourTable -> Entry[i] . Blue,
						OBP_FailIfBad,TRUE,
					TAG_DONE)) == -1)
					{
						MappedPens[1][i] = FALSE;

						GotAll = FALSE;

						break;
					}
					else
						MappedPens[1][i] = TRUE;
				}
			}
			else
			{
				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;
				}

					/* Can't do anything else. */

				Config -> ScreenConfig -> ColourMode = COLOUR_AMIGA;
			}
			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][7];
			break;

		case COLOUR_EIGHT:

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

		case COLOUR_AMIGA:
		case COLOUR_MONO:

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

		/* Take care of pen and attribute mapping. */

	if(Config -> EmulationConfig -> UseStandardPens)
	{
		for(i = 0 ; i < 16 ; i++)
		{
			PenTable[i]		= i;
			TextAttributeTable[i]	= i;
		}
	}
	else
	{
		UBYTE Value;

		CopyMem(Config -> EmulationConfig -> Pens,PenTable,sizeof(Config -> EmulationConfig -> Pens));

		for(i = 0 ; i < 16 ; i++)
		{
			Value = 0;

			if(i & ATTR_UNDERLINE)
			{
				switch(Config -> EmulationConfig -> Attributes[TEXTATTR_UNDERLINE])
				{
					case TEXTATTR_UNDERLINE:

						Value |= ATTR_UNDERLINE;
						break;

					case TEXTATTR_HIGHLIGHT:

						Value |= ATTR_HIGHLIGHT;
						break;

					case TEXTATTR_BLINK:

						Value |= ATTR_BLINK;
						break;

					case TEXTATTR_INVERSE:

						Value |= ATTR_INVERSE;
						break;
				}
			}

			if(i & ATTR_HIGHLIGHT)
			{
				switch(Config -> EmulationConfig -> Attributes[TEXTATTR_HIGHLIGHT])
				{
					case TEXTATTR_UNDERLINE:

						Value |= ATTR_UNDERLINE;
						break;

					case TEXTATTR_HIGHLIGHT:

						Value |= ATTR_HIGHLIGHT;
						break;

					case TEXTATTR_BLINK:

						Value |= ATTR_BLINK;
						break;

					case TEXTATTR_INVERSE:

						Value |= ATTR_INVERSE;
						break;
				}
			}

			if(i & ATTR_BLINK)
			{
				switch(Config -> EmulationConfig -> Attributes[TEXTATTR_BLINK])
				{
					case TEXTATTR_UNDERLINE:

						Value |= ATTR_UNDERLINE;
						break;

					case TEXTATTR_HIGHLIGHT:

						Value |= ATTR_HIGHLIGHT;
						break;

					case TEXTATTR_BLINK:

						Value |= ATTR_BLINK;
						break;

					case TEXTATTR_INVERSE:

						Value |= ATTR_INVERSE;
						break;
				}
			}

			if(i & ATTR_INVERSE)
			{
				switch(Config -> EmulationConfig -> Attributes[TEXTATTR_INVERSE])
				{
					case TEXTATTR_UNDERLINE:

						Value |= ATTR_UNDERLINE;
						break;

					case TEXTATTR_HIGHLIGHT:

						Value |= ATTR_HIGHLIGHT;
						break;

					case TEXTATTR_BLINK:

						Value |= ATTR_BLINK;
						break;

					case TEXTATTR_INVERSE:

						Value |= ATTR_INVERSE;
						break;
				}
			}

			TextAttributeTable[i] = Value;
		}
	}

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

	UpdateTerminalLimits();

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

	if(!CreateScale(Window))
		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;

	if(Config -> ScreenConfig -> StatusLine != STATUSLINE_DISABLED && Config -> ScreenConfig -> SplitStatus)
	{
		if(!(StatusWindow = OpenWindowTags(NULL,
			WA_Top,			Window -> TopEdge + Window -> Height,
			WA_Left,		Window -> LeftEdge,
			WA_InnerWidth,		StatusWidth,
			WA_InnerHeight,		StatusHeight,
			WA_DragBar,		TRUE,
			WA_DepthGadget,		TRUE,
			WA_NewLookMenus,	TRUE,
			WA_Title,		ScreenTitle,
			OpenWindowTag,		Window -> WScreen,
			WA_RMBTrap,		TRUE,
			WA_CloseGadget,		TRUE,
			WA_MenuHelp,		TRUE,
			WA_NoCareRefresh,	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
		StatusWindow = NULL;

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

		if(!ModifyIDCMP(StatusWindow,DEFAULT_IDCMP))
		{
			StatusWindow -> UserPort = NULL;

			CloseWindow(StatusWindow);
			StatusWindow = NULL;

			return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_STATUS_WINDOW_TXT));
		}
	}

	UpdateTerminalLimits();

	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(!AttachMenu(NULL))
		return(LocaleString(MSG_TERMINIT_FAILED_TO_CREATE_MENUS_TXT));

		/* 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(RawCapture)
	{
		if(FileCapture)
			CheckItem(MEN_CAPTURE_TO_RAW_FILE,TRUE);
		else
			CheckItem(MEN_CAPTURE_TO_RAW_FILE,FALSE);

		CheckItem(MEN_CAPTURE_TO_FILE,FALSE);
	}
	else
	{
		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 != NULL);

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

		/* Take care of the chat line. */

	if(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Config -> TerminalConfig -> EmulationFileName[0])
		OffItem(MEN_CHAT_LINE);
	else
		CheckItem(MEN_CHAT_LINE,ChatMode);

		/* Update the clipboard menus. */

	SetClipMenu(FALSE);

	SetTransferMenu(TRUE);

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

	SetRasterMenu(RasterEnabled);

		// Take care of the remaining windows

	if(MatrixWindow)
		CheckItem(MEN_MATRIX_WINDOW,TRUE);

	if(InfoWindow)
		CheckItem(MEN_STATUS_WINDOW,TRUE);

	if(PacketWindow)
		CheckItem(MEN_PACKET_WINDOW,TRUE);

	if(ChatMode)
		CheckItem(MEN_CHAT_LINE,TRUE);

	if(FastWindow)
		CheckItem(MEN_FAST_MACROS_WINDOW,TRUE);

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

			ShowRequest(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();

		ForegroundPen = GetPenIndex(SafeTextPen);
		BackgroundPen = 0;

		UpdatePens();

		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();

	TTYResize();

	return(NULL);
}

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

VOID
CloseAll(BOOL CloseDOS)
{
	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);
	}

	Permit();

	DeleteRecord();

	DeleteQueueProcess();

	SoundExit();

	SZ_SizeCleanup();

	FreeDialList(TRUE);

	if(IntuitionBase && Window)
		BlockWindows();

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

		if(RexxPort)
			RemPort(RexxPort);
	}

	DeleteChatGadget();

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

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

		DeleteMsgPort(TermRexxPort);
	}

	if(RexxProcess)
	{
		Forbid();

		Signal(RexxProcess,SIG_KILL);

		ClrSignal(SIG_HANDSHAKE);

		Wait(SIG_HANDSHAKE);

		Permit();
	}

	CloseLibrary(RexxSysBase);

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

	CloseLibrary(XProtocolBase);

	FreeVec(XprIO);

	TerminateBuffer();

	DeleteSpeech();

	Forbid();

	BufferClosed = TRUE;

	DeleteBuffer();

	Permit();

	if(FileCapture)
	{
		BufferClose(FileCapture);

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

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

	if(PrinterCapture)
		Close(PrinterCapture);

		/* Close the external emulator. */

	CloseEmulator(TRUE);

	if(IntuitionBase && GfxBase)
		DeleteDisplay();

	CaptureParserExit();

	UnLoadSeg(KeySegment);

	StopCall(TRUE);

	DeleteAccountant();

	FreeSignal(CheckBit);

	ClearSerial();

	DeleteSerial();

	StopTime();

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

		DeleteIORequest(TimeRequest);
	}

	DeleteMsgPort(TimePort);

	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);
		}
	}

	CloseClip();

	LocaleClose();

	DeleteMsgQueue(SpecialQueue);

	if(ConsoleDevice)
		CloseDevice(ConsoleRequest);

	CloseLibrary(GTLayoutBase);

	CloseLibrary(IconBase);

	CloseLibrary(DataTypesBase);

	CloseLibrary(WorkbenchBase);

	CloseLibrary(OwnDevUnitBase);

	CloseLibrary(CxBase);

	CloseLibrary(IFFParseBase);

	CloseLibrary(AslBase);

	CloseLibrary(DiskfontBase);

	CloseLibrary(GadToolsBase);

	CloseLibrary(LayersBase);

	CloseLibrary(GfxBase);

	CloseLibrary(IntuitionBase);

	CloseLibrary(UtilityBase);

	MemoryCleanup();

	if(WBenchMsg)
	{
		CurrentDir(WBenchLock);

		CloseLibrary(DOSBase);

		Forbid();

		ReplyMsg((struct Message *)WBenchMsg);
	}
	else
	{
		if(CloseDOS)
			CloseLibrary(DOSBase);
	}
}

	/* AddExtraAssignment(STRPTR LocalDir,STRPTR Assign):
	 *
	 *	Add assignments for local directories.
	 */

STATIC VOID
AddExtraAssignment(STRPTR LocalDir,STRPTR Assign)
{
	UBYTE	LocalBuffer[40];
	BPTR	FileLock;

		// Add the colon, we'll need it later

	SPrintf(LocalBuffer,"%s:",Assign);

		// Is the local directory present?

	if(FileLock = Lock(LocalDir,ACCESS_READ))
	{
			// Is the assignment present?

		if(IsAssign(LocalBuffer))
		{
				// Check to see if the local directory
				// is already on the assignment list

			if(LockInAssign(FileLock,LocalBuffer))
			{
				UnLock(FileLock);

				FileLock = NULL;
			}
		}
	}

		// Can we attach the lock to the assignment list?

	if(FileLock)
	{
		Forbid();

			// If the assignment is already present, add the
			// new directory, else create a new assignment.

		if(IsAssign(LocalBuffer))
			AssignAdd(Assign,FileLock);
		else
			AssignLock(Assign,FileLock);

		Permit();
	}
}

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

STRPTR
OpenAll(STRPTR ConfigPath)
{
	UBYTE	PathBuffer[MAX_FILENAME_LENGTH];
	STRPTR	Result,Error,ConfigFileName = NULL;
	LONG	i;
	LONG	ErrorCode;
	BOOL	ZapPhonebook;

		/* Pretty cheap ;-) */

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

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

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

	TagDPI[0] . ti_Tag = TAG_DONE;

		/* Double buffered file locking. */

	NewList(&DoubleBufferList);

	InitSemaphore(&DoubleBufferSemaphore);

		/* ARexx command queue. */

	InitSemaphore(&ARexxQueueSemaphore);

	NewList(&ARexxQueue);

		/* Terminal emulation data. */

	InitSemaphore(&TerminalSemaphore);

		/* Phone number patterns and rates. */

	InitSemaphore(&PatternSemaphore);

		/* Online status. */

	InitSemaphore(&OnlineSemaphore);

		/* Text buffer task access semaphore. */

	InitSemaphore(&BufferTaskSemaphore);
	InitSemaphore(&ReviewTaskSemaphore);

		/* Set up all the lists. */

	NewList(&PacketHistoryList);
	NewList(&EmptyList);
	NewList(&FastMacroList);
	NewList(&TransferInfoList);
	NewList((struct List *)&PhoneGroupList);

	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. */

	LocalizeMenuTable(TermMenu,MenuLabels);

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

		/* Check if we should use the old style sliders. */

	if(GetVar("termoldsliders",PathBuffer,256,NULL) >= 0)
		SliderType = SLIDER_KIND;
	else
		SliderType = LEVEL_KIND;

		/* 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;
		SetMask = OldSetWrMsk;
	}
	else
	{
		ReadAPen = NewGetAPen;
		ReadBPen = NewGetBPen;
		ReadDrMd = NewGetDrMd;
		SetMask = NewSetWrMsk;
	}

		/* 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 = SafeOpenLibrary("PROGDIR:gtlayout.library",26)))
	{
		if(!(GTLayoutBase = SafeOpenLibrary("gtlayout.library",26)))
			return(LocaleString(MSG_TERMINIT_FAILED_TO_OPEN_GTLAYOUT_LIBRARY_TXT));
	}

	if(GetVar("termoldcycle",PathBuffer,256,NULL) >= 0 || GetVar("RussLeBar",PathBuffer,256,NULL) >= 0)
	{
		LONG Value;

		CycleType = CYCLE_KIND;

		if(StrToLong(PathBuffer,&Value) > 0)
		{
			if(!Value && GTLayoutBase -> lib_Version >= 22)
				CycleType = POPUP_KIND;
		}
	}
	else
	{
		if(GTLayoutBase -> lib_Version >= 22)
			CycleType = POPUP_KIND;
		else
			CycleType = CYCLE_KIND;
	}

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

		// Now check if the speech synthesizer is available.

	if(TranslatorBase = OpenLibrary("translator.library",0))
	{
		struct narrator_rb __aligned NarratorRequest;

		memset(&NarratorRequest,0,sizeof(NarratorRequest));

		if(!OpenDevice("narrator.device",0,&NarratorRequest,NULL))
		{
			SpeechAvailable = TRUE;

			CloseDevice(&NarratorRequest);
		}

		CloseLibrary(TranslatorBase);
		TranslatorBase = NULL;
	}

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

		/* Create all generic lists. */

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

		/* Add extra assignments. */

	AddExtraAssignment("PROGDIR:Fonts","Fonts");
	AddExtraAssignment("Fonts","Fonts");
	AddExtraAssignment("PROGDIR:Libs","Libs");
	AddExtraAssignment("Libs","Libs");

		/* 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.prefs",MAX_FILENAME_LENGTH);
	}
	else
		strcpy(LastConfig,ConfigFileName);

	strcpy(DefaultPubScreenName,"Workbench");

		// Special measure

	if(!LastPhone[0])
		ZapPhonebook = TRUE;
	else
		ZapPhonebook = FALSE;

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

	if(ZapPhonebook)
		LastPhone[0] = 0;

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

			// Now we can safely assume that this is the
			// first invocation of this program on the
			// current setup

		FirstInvocation = TRUE;
	}
	else
	{
		Current2DefaultPalette(Config);

		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;

		// Set up the phonebook file name

	if(!LastPhone[0])
	{
		if(Config->PhonebookFileName[0])
			strcpy(LastPhone,Config->PhonebookFileName);
		else
		{
			strcpy(LastPhone,	Config -> PathConfig -> DefaultStorage);
			AddPart(LastPhone,	"phonebook.prefs",MAX_FILENAME_LENGTH);
		}
	}

		/* Load the keyboard macros. */

	strcpy(LastMacros,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastMacros,	"functionkeys.prefs",MAX_FILENAME_LENGTH);

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

		/* Load the cursor keys. */

	strcpy(LastCursorKeys,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastCursorKeys,	"cursorkeys.prefs",MAX_FILENAME_LENGTH);

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

		/* Load the sound settings. */

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

	if(Config->SoundFileName[0])
	{
		if(ReadIFFData(Config->SoundFileName,&SoundConfig,sizeof(struct SoundConfig),ID_SOUN))
			strcpy(LastSound,Config->SoundFileName);
		else
		{
			if(!ReadIFFData(LastSound,&SoundConfig,sizeof(struct SoundConfig),ID_SOUN))
				ResetSound(&SoundConfig);
		}
	}
	else
	{
		if(!ReadIFFData(LastSound,&SoundConfig,sizeof(struct SoundConfig),ID_SOUN))
			ResetSound(&SoundConfig);
	}

		/* Initialize the sound support routines. */

	SoundInit();

		/* Load the phone number pattern / rates settings. */

	strcpy(LastPattern,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastPattern,	"rates.prefs",MAX_FILENAME_LENGTH);

	if(Config->AreaCodeFileName[0])
	{
		if(PatternList = LoadTimeDateList(Config->AreaCodeFileName,&ErrorCode))
			strcpy(LastPattern,Config->AreaCodeFileName);
		else
			PatternList = LoadTimeDateList(LastPattern,&ErrorCode);
	}
	else
		PatternList = LoadTimeDateList(LastPattern,&ErrorCode);

	if(!PatternList)
	{
		if(!(PatternList = CreateList()))
			return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));
	}

		/* Load the translation tables. */

	strcpy(LastTranslation,		Config -> PathConfig -> DefaultStorage);
	AddPart(LastTranslation,	"translation.prefs",MAX_FILENAME_LENGTH);

	if(Config -> TranslationFileName[0])
	{
		if(LoadDefaultTranslationTables(Config -> TranslationFileName))
			strcpy(LastTranslation,Config -> TranslationFileName);
		else
			LoadDefaultTranslationTables(LastTranslation);
	}
	else
		LoadDefaultTranslationTables(LastTranslation);

		/* Load the fast! macro settings. */

	strcpy(LastFastMacros,		Config -> PathConfig -> DefaultStorage);
	AddPart(LastFastMacros,		"fastmacros.prefs",MAX_FILENAME_LENGTH);

	if(Config->FastMacroFileName[0])
	{
		if(LoadFastMacros(Config->FastMacroFileName,&FastMacroList))
			strcpy(LastFastMacros,Config->FastMacroFileName);
		else
			LoadFastMacros(LastFastMacros,&FastMacroList);
	}
	else
		LoadFastMacros(LastFastMacros,&FastMacroList);

	FastMacroCount = GetListSize(&FastMacroList);

		/* Load the speech settings. */

	strcpy(LastSpeech,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastSpeech,	"speech.prefs",MAX_FILENAME_LENGTH);

	if(Config->SpeechFileName[0])
	{
		if(ReadIFFData(Config->SpeechFileName,&SpeechConfig,sizeof(struct SpeechConfig),ID_SPEK))
			strcpy(LastSpeech,Config->SpeechFileName);
		else
		{
			if(!ReadIFFData(LastSpeech,&SpeechConfig,sizeof(struct SpeechConfig),ID_SPEK))
				ResetSpeechConfig(&SpeechConfig);
		}
	}
	else
	{
		if(!ReadIFFData(LastSpeech,&SpeechConfig,sizeof(struct SpeechConfig),ID_SPEK))
			ResetSpeechConfig(&SpeechConfig);
	}

		/* Load the hotkey settings. */

	strcpy(LastKeys,	Config -> PathConfig -> DefaultStorage);
	AddPart(LastKeys,	"hotkeys.prefs",MAX_FILENAME_LENGTH);

	if(Config->HotkeyFileName[0])
	{
		if(LoadHotkeys(Config->HotkeyFileName,&Hotkeys))
			strcpy(LastKeys,Config->HotkeyFileName);
		else
		{
			if(!LoadHotkeys(LastKeys,&Hotkeys))
				ResetHotkeys(&Hotkeys);
		}
	}
	else
	{
		if(!LoadHotkeys(LastKeys,&Hotkeys))
			ResetHotkeys(&Hotkeys);
	}

		/* Load the trap settings. */

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

	WatchTraps = TRUE;

	if(Config->TrapFileName[0])
	{
		if(LoadTraps(Config->TrapFileName,GenericListTable[GLIST_TRAP]))
			strcpy(LastTraps,Config->TrapFileName);
		else
		{
			if(!LoadTraps(LastTraps,GenericListTable[GLIST_TRAP]))
				WatchTraps = FALSE;
		}
	}
	else
	{
		if(!LoadTraps(LastTraps,GenericListTable[GLIST_TRAP]))
			WatchTraps = FALSE;
	}

		/* Set up the text pacing controls. */

	SendSetup();

		/* Set up the capture parser. */

	if(!(ParserStuff = CreateParseContext()))
		return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));

	if(!CaptureParserInit())
		return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));

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

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

	ConOutputUpdate();

		/* Initialize the data flow parser. */

	FlowInit(TRUE);

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

	if(!(TrapStuff = CreateParseContext()))
		return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));

		/* 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())
	{
		ShowRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Error);

		DeleteSerial();
	}
	else
	{
		if(SerialMessage)
		{
			ShowRequest(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])
	{
		LONG 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));

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

	NewList((struct List *)&Update_MsgList);

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

		// Start the rates accounting

	if(!CreateAccountant())
		return(LocaleString(MSG_GLOBAL_NO_AUX_BUFFERS_TXT));

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

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

			return(NULL);
		}
	}
}
