/*
**	PhonePanel.c
**
**	The phonebook and support routines
**
**	Copyright © 1990-1996 by Olaf `Olsen' Barthel
**		All Rights Reserved
**
**	:ts=4
*/

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

	// The gadget IDs are in there

#include "PhonePanel.h"

	/* What action is to follow clicking into the listview. */

enum	{	CLICK_NONE,CLICK_SELECT,CLICK_TOGGLE,CLICK_DIAL };

STATIC VOID
HighlightEntry(LayoutHandle *Manager,LayoutHandle *Editor,struct List *PhoneList,struct PhoneNode *Node,ULONG Count,ULONG Grouper,BOOL Activate,BOOL Hide,BOOL NewList)
{
	BOOL IsFirst,IsLast,Disabled;

	if(Node && PhoneList)
	{
		IsFirst		= (Node == (struct PhoneNode *)PhoneList -> lh_Head);
		IsLast		= (Node == (struct PhoneNode *)PhoneList -> lh_TailPred);
		Disabled	= FALSE;
	}
	else
	{
		IsFirst		= TRUE;
		IsLast		= TRUE;
		Disabled	= TRUE;
	}

	if(PhoneList)
	{
		LT_SetAttributes(Manager,GAD_NAMELIST,
			NewList ? GTLV_Labels : TAG_IGNORE,	PhoneList,
			Node ? TAG_IGNORE : GTLV_Selected,	~0,
		TAG_DONE);
	}
	else
	{
		LT_SetAttributes(Manager,GAD_NAMELIST,
			GTLV_Labels,						NULL,
			Node ? TAG_IGNORE : GTLV_Selected, ~0,
			Kick30 ? GA_Disabled : TAG_IGNORE,	TRUE,
		TAG_DONE);
	}

	LT_SetAttributes(Manager,GAD_COMMENTLINE,
		LABX_Text,	Node ? Node -> Entry -> Header -> Comment : (STRPTR)"",
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_MOVE_FIRST,
		GA_Disabled,	IsFirst || Disabled,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_MOVE_UP,
		GA_Disabled,	IsFirst || Disabled,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_MOVE_DOWN,
		GA_Disabled,	IsLast || Disabled,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_MOVE_LAST,
		GA_Disabled,	IsLast || Disabled,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_EDIT,
		GA_Disabled,	!Node || Disabled,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_COPY,
		GA_Disabled,	!Node || Disabled,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_DELETE,
		GA_Disabled,	!Node || Disabled || Node -> Entry == ChosenEntry,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_USE,
		GA_Disabled,	!Node || Disabled,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_MAKE_GROUP,
		GA_Disabled,	!Node && !Count,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_SPLIT_GROUP,
		GA_Disabled,	Grouper == 0,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_SELECT,
		GA_Disabled,	Disabled || (Node && Node -> Entry -> Count != -1),
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_CLEAR,
		GA_Disabled,	Disabled || (Node && Node -> Entry -> Count == -1),
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_TOGGLE_ALL,
		GA_Disabled,	Disabled,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_SELECT_ALL,
		GA_Disabled,	!NumPhoneEntries || Count == NumPhoneEntries || !PhoneList,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_CLEAR_ALL,
		GA_Disabled,	!Count,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_PATTERN,
		GA_Disabled,	!NumPhoneEntries || !PhoneList,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_DIAL,
		GA_Disabled,	!Node || (Online && !Config -> MiscConfig -> ProtectiveMode),
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_LOAD,
		GA_Disabled,	ChosenEntry != NULL,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_MERGE,
		GA_Disabled,	!NumPhoneEntries || !PhoneList,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_SAVE,
		GA_Disabled,	!NumPhoneEntries || !PhoneList,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_PRINT,
		GA_Disabled,	!NumPhoneEntries || !PhoneList,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_SORT,
		GA_Disabled,	!NumPhoneEntries || !PhoneList,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_COPY_CONFIG,
		GA_Disabled,	!NumPhoneEntries || !PhoneList,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_SORT_ORDER,
		GA_Disabled,	!NumPhoneEntries || !PhoneList,
	TAG_DONE);

	LT_SetAttributes(Manager,GAD_GROUPID,
		GTCY_Active,	Grouper,
	TAG_DONE);

	if(Editor)
	{
		BOOL					 IsFirst,IsLast,Disabled,RatesValid;
		struct Configuration	*LocalConfig;

		if(Node)
		{
			IsFirst			= (Node -> Entry -> Count == -1) || (Node -> Entry -> Count == 0);
			IsLast			= (Node -> Entry -> Count == -1) || (Node -> Entry -> Count == Count - 1);
			Disabled		= FALSE;
			LocalConfig		= Node -> Entry -> Config;
			RatesValid		= (Node -> Entry -> TimeDateList . mlh_Head -> mln_Succ != NULL && !Node -> Entry -> Header -> NoRates);
		}
		else
		{
			IsFirst			= TRUE;
			IsLast			= TRUE;
			Disabled		= TRUE;
			LocalConfig		= NULL;
			RatesValid		= FALSE;
		}

		LT_SetAttributes(Editor,GAD_SYSTEM_NAME,
			GTST_String,	Node ? Node -> Entry -> Header -> Name : (STRPTR)"",
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_COMMENT,
			GTST_String,	Node ? Node -> Entry -> Header -> Comment : (STRPTR)"",
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_NUMBERS,
			GTST_String,	Node ? Node -> Entry -> Header -> Number : (STRPTR)"",
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_QUICK_MENU,
			GTCB_Checked,	Node ? Node -> Entry -> Header -> QuickMenu : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_AUTODIAL,
			GTCB_Checked,	Node ? Node -> Entry -> Header -> AutoDial : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_USER_NAME,
			GTST_String,	(Node && !Hide) ? Node -> Entry -> Header -> UserName : (STRPTR)"",
			GA_Disabled,	Hide || Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_USER_PASSWORD,
			GTST_String,	(Node && !Hide) ? Node -> Entry -> Header -> Password : (STRPTR)"",
			GA_Disabled,	Hide || Disabled,
		TAG_DONE);


		LT_SetAttributes(Editor,GAD_SERIAL_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> SerialConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_SERIAL_EDIT,
#ifndef ADAM_SZYMCZAK
				GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> SerialConfig),
#else
				GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_MODEM_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> ModemConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_MODEM_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> ModemConfig),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_SCREEN_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> ScreenConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_SCREEN_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> ScreenConfig),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_TERMINAL_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> TerminalConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_TERMINAL_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> TerminalConfig),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_EMULATION_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> EmulationConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_EMULATION_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> EmulationConfig),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_CLIPBOARD_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> ClipConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_CLIPBOARD_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> ClipConfig),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_CAPTURE_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> CaptureConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_CAPTURE_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> CaptureConfig),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_COMMAND_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> CommandConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_COMMAND_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> CommandConfig),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_MISC_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> MiscConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_MISC_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> MiscConfig),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_PATH_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> PathConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_PATH_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> PathConfig),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_TRANSFER_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> TransferConfig != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_TRANSFER_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> TransferConfig),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_TRANSLATION_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> TranslationFileName != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_TRANSLATION_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> TranslationFileName),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_MACRO_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> MacroFileName != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_MACRO_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> MacroFileName),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_CURSOR_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> CursorFileName != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_CURSOR_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> CursorFileName),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_FASTMACRO_STATE,
			GTCB_Checked,	LocalConfig ? (LocalConfig -> FastMacroFileName != NULL) : FALSE,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_FASTMACRO_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> FastMacroFileName),
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_RATE_STATE,
			GTCB_Checked,	RatesValid,
			GA_Disabled,	Disabled,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_RATE_EDIT,
#ifndef ADAM_SZYMCZAK
			GA_Disabled,	Disabled || !RatesValid,
#else
			GA_Disabled,	Disabled,
#endif
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_FIRST_ENTRY,
			GA_Disabled,	Disabled || IsFirst,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_PREVIOUS_ENTRY,
			GA_Disabled,	Disabled || IsFirst,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_NEXT_ENTRY,
			GA_Disabled,	Disabled || IsLast,
		TAG_DONE);

		LT_SetAttributes(Editor,GAD_LAST_ENTRY,
			GA_Disabled,	Disabled || IsLast,
		TAG_DONE);

		if(Activate)
		{
			LT_ShowWindow(Editor,TRUE);

			LT_Activate(Editor,GAD_SYSTEM_NAME);
		}
	}
}

STATIC VOID
UpdateWindowTitle(struct Window *Window,STRPTR Title,LONG Count)
{
	if(Count)
		SPrintf(Title,LocaleString(MSG_PHONEPANEL_SELECTED_OUT_OF_TXT),LocaleString(MSG_PHONEPANEL_PHONEBOOK_TXT),Count,NumPhoneEntries);
	else
		Title = LocaleString(MSG_PHONEPANEL_PHONEBOOK_TXT);

	SetWindowTitles(Window,Title,(STRPTR)~0);
}

STATIC VOID
UpdateEditorData(LayoutHandle *Editor,struct PhoneNode *Node,BOOL Hide)
{
	if(Editor && Node)
	{
		strcpy(Node -> Entry -> Header -> Name,LT_GetString(Editor,GAD_SYSTEM_NAME));
		strcpy(Node -> Entry -> Header -> Comment,LT_GetString(Editor,GAD_COMMENT));
		strcpy(Node -> Entry -> Header -> Number,LT_GetString(Editor,GAD_NUMBERS));

		if(!Hide)
		{
			strcpy(Node -> Entry -> Header -> UserName,LT_GetString(Editor,GAD_USER_NAME));
			strcpy(Node -> Entry -> Header -> Password,LT_GetString(Editor,GAD_USER_PASSWORD));
		}
	}
}

BOOL
PhonePanel(ULONG MsgQualifier)
{
	STATIC UBYTE	NamePattern[64]		= "#?",
					NumberPattern[64]	= "#?",
					CommentPattern[64]	= "#?";
	STATIC BYTE		Mode = 1;

	STATIC WORD		Sorter;
	STATIC BOOLEAN		ReverseOrder;

	UBYTE				 ParsedNamePattern[130],
						 ParsedNumberPattern[130],
						 ParsedCommentPattern[130];

	UBYTE				 WindowTitle[80];

	struct MsgPort		*UserPort;
	LayoutHandle		*Manager,
						*Editor,
						*Selector,
						*Grouping,
						*Sorting,
						*PasswordHandle;
	struct PhoneNode	*TempNode;
	struct List			*PhoneList;
	struct List			*CurrentList;
	LONG				 Count;
	STRPTR				*Labels,
						*OtherLabels;
	STRPTR				 Name;
	LONG				 i,ListMax;
	BOOL				 Hide = TRUE;
	BOOL				 DialTheList = FALSE;

		// Create the group labels

	if(!(Labels = BuildLabels()))
	{
		DisplayBeep(Window -> WScreen);
		return(FALSE);
	}

		// Count the number of labels

	for(i = 0 ; Labels[i] ; i++);

		// If the group index is larger than the group label table
		// permits, truncate it.

	if(PhonebookDefaultGroup >= i)
		PhonebookDefaultGroup = i - 1;

		// All the control panels we will open will live on this msgport

	if(!(UserPort = CreateMsgPort()))
	{
		FreeVecPooled(Labels);
		DisplayBeep(Window -> WScreen);
		return(FALSE);
	}

		// Start with a clean slate

	Manager		= NULL;
	Editor		= NULL;
	Selector	= NULL;
	Grouping	= NULL;
	Sorting		= NULL;
	PasswordHandle	= NULL;

		// Does the phonebook hold any entries?

	if(Phonebook && NumPhoneEntries)
	{
		LONG i;

			// Create the phonebook labels

		if(!(PhoneList = CreatePhoneList()))
		{
			DisplayBeep(Window -> WScreen);

			FreeVecPooled(Labels);
			DeleteMsgPort(UserPort);

			return(FALSE);
		}

			// Get rid of the old dialing list

		FreeDialList(TRUE);

			// Now walk through the phonebook, counting the tagged entries

		for(i = 0, Count = -1 ; i < NumPhoneEntries ; i++)
		{
			if(Phonebook[i] -> Count > Count)
				Count = Phonebook[i] -> Count;
		}

		Count++;
	}
	else
	{
		PhoneList	= NULL;
		Count		= 0;
	}

		// Are we to display a group?

	if(PhonebookDefaultGroup)
	{
		PhoneGroupNode	*Group;
		struct Node		*Node;

			// Get the group list header

		Group = (PhoneGroupNode *)(((ULONG)Labels[PhonebookDefaultGroup]) - offsetof(PhoneGroupNode,LocalName));

		CurrentList = (struct List *)&Group -> GroupList;

			// Count the number of entries in the list

		for(ListMax = 0, Node = CurrentList -> lh_Head ; Node -> ln_Succ ; Node = Node -> ln_Succ)
			ListMax++;
	}
	else
	{
			// We'll use the main list

		CurrentList	= PhoneList;
		ListMax		= NumPhoneEntries;
	}

		// Update the window title

	if(Count)
		SPrintf(WindowTitle,LocaleString(MSG_PHONEPANEL_SELECTED_OUT_OF_TXT),LocaleString(MSG_PHONEPANEL_PHONEBOOK_TXT),Count,NumPhoneEntries);
	else
		strcpy(WindowTitle,LocaleString(MSG_PHONEPANEL_PHONEBOOK_TXT));

		// If the user holds down any shift key, the editor window will open in
		// addition to the manager window

	if(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
	{
		if(Editor = CreateEditorHandle(Window,CurrentList,Count,NULL,FALSE,UserPort))
			Manager = CreateManagerHandle(Editor -> Window,CurrentList,Count,&PhonebookDefaultGroup,Labels,UserPort,WindowTitle);
	}
	else
		Manager = CreateManagerHandle(Window,CurrentList,Count,&PhonebookDefaultGroup,Labels,UserPort,WindowTitle);

		// Don't go any further if the manager window is not open

	if(Manager)
	{
		struct IntuiMessage		*Message;
		BOOL					 Done = FALSE;
		BOOL					 ClearList = FALSE;
		ULONG					 MsgClass,
								 MsgQualifier,
								 CompleteQualifier;
		UWORD					 MsgCode;
		LONG					 KeyCode;
		struct Gadget			*MsgGadget;
		struct Window			*MsgWindow;

		LONG					 ClickAction;

		UBYTE					 DummyBuffer[MAX_FILENAME_LENGTH],
								*DummyChar;

		LONG					 Selected = ~0,
								 MsgGadgetID;

		struct PhoneNode		*SelectedNode = NULL;
		struct PhoneEntry		*Entry;

		struct FileRequester	*FileRequest;
		LONG					 Vanilla;

		struct Window			*PhoneWindow	= Manager -> Window;
		struct Window			*EditWindow		= NULL;
		struct Window			*PatternWindow	= NULL;
		struct Window			*GroupWindow	= NULL;
		struct Window			*SortWindow		= NULL;
		struct Window			*PasswordWindow	= NULL;
		LayoutHandle			*Handle;

			// Save this one for later

		if(Editor)
			EditWindow = Editor -> Window;

		GuideContext(CONTEXT_PHONEBOOK);

		PushWindow(PhoneWindow);

		do
		{
			if(Wait(PORTMASK(PhoneWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
			{
				FreeDialList(TRUE);

				break;
			}

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

				GT_ReplyIMsg(Message);

					// Jump to the handle the message originated from

				if(MsgWindow == PhoneWindow)
					Handle = Manager;

				if(MsgWindow == EditWindow)
					Handle = Editor;

				if(MsgWindow == PatternWindow)
					Handle = Selector;

				if(MsgWindow == GroupWindow)
					Handle = Grouping;

				if(MsgWindow == SortWindow)
					Handle = Sorting;

				if(MsgWindow == PasswordWindow)
					Handle = PasswordHandle;

					// Save the original event qualifier

				CompleteQualifier = MsgQualifier;

					// Now, this is not nice, but needs to be done in order
					// to avoid having keyboard movements mess up the list of
					// tagged entries.

				if(MsgClass == IDCMP_RAWKEY && (MsgCode >= CURSORUP && MsgCode <= CURSORDOWN))
					MsgQualifier &= ~(IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT);

					// We'll save the key code for the editing window

				if(MsgClass == IDCMP_RAWKEY)
					KeyCode = MsgCode;
				else
					KeyCode = 0;

					// Let gtlayout take its share

				LT_HandleInput(Handle,CompleteQualifier,&MsgClass,&MsgCode,&MsgGadget);

					// Extract the gadget ID

				if(MsgClass == IDCMP_GADGETUP || MsgClass == IDCMP_IDCMPUPDATE)
					MsgGadgetID = MsgGadget -> GadgetID;
				else
					MsgGadgetID = -1;

					// Now convert the raw key code for special commands

				Vanilla = LT_GetCode(CompleteQualifier,MsgClass,MsgCode,MsgGadget);

				switch(Vanilla)
				{
						// Toggle the current entry

					case ' ':

						if(SelectedNode)
						{
							LT_SetAttributes(Handle,GAD_NAMELIST,
								GTLV_Labels,	~0,
							TAG_DONE);

							if(SelectedNode -> Entry -> Count == -1)
							{
								SelectedNode -> Entry -> Count = Count++;

								SPrintf(SelectedNode -> LocalName,"%3ld - %s",Count,SelectedNode -> Entry -> Header -> Name);

								if(SelectedNode -> Entry -> NodeGroup)
									strcpy(SelectedNode -> Entry -> NodeGroup -> LocalName,SelectedNode -> LocalName);

								UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
							}
							else
							{
								RemoveDialEntry(SelectedNode);

								Count--;

								UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
							}

							LT_SetAttributes(Handle,GAD_NAMELIST,
								GTLV_Labels,		CurrentList,
							TAG_DONE);

							HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);
						}

						break;

						// Untag this or all entries

					case 127:

						if(CompleteQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
						{
							if(Count > 0)
							{
								MsgClass	= IDCMP_GADGETUP;
								MsgGadgetID	= GAD_CLEAR_ALL;

								LT_PressButton(Handle,MsgGadgetID);
							}
						}
						else
						{
							if(Selected != -1 && SelectedNode -> Entry -> Count != -1)
							{
								MsgClass	= IDCMP_GADGETUP;
								MsgGadgetID	= GAD_CLEAR;

								LT_PressButton(Handle,MsgGadgetID);
							}
						}

						break;
				}

					// Moving around through the editing window

				if(MsgWindow == EditWindow && KeyCode)
				{
					switch(KeyCode)
					{
						case CURSORLEFT:

							MsgGadgetID = -1;

							if(SelectedNode && SelectedNode -> Entry -> Count > 0)
							{
								MsgClass = IDCMP_GADGETUP;

								if(CompleteQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
									MsgGadgetID	= GAD_FIRST_ENTRY;
								else
									MsgGadgetID	= GAD_PREVIOUS_ENTRY;

								LT_PressButton(Handle,MsgGadgetID);
							}

							break;

						case CURSORRIGHT:

							MsgGadgetID = -1;

							if(SelectedNode && SelectedNode -> Entry -> Count < Count - 1)
							{
								MsgClass = IDCMP_GADGETUP;

								if(CompleteQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
									MsgGadgetID	= GAD_LAST_ENTRY;
								else
									MsgGadgetID	= GAD_NEXT_ENTRY;

								LT_PressButton(Handle,MsgGadgetID);
							}

							break;
					}
				}

					// Close a window

				if(MsgClass == IDCMP_CLOSEWINDOW)
				{
					if(MsgWindow == PhoneWindow)
					{
						FreeDialList(TRUE);

						Done = TRUE;
					}

					if(MsgWindow == EditWindow)
					{
						LT_DeleteHandle(Editor);

						Editor = NULL;
						EditWindow = NULL;

						LT_ShowWindow(Manager,TRUE);
					}

					if(MsgWindow == PasswordWindow)
					{
						LT_DeleteHandle(PasswordHandle);

						PasswordHandle = NULL;
						PasswordWindow = NULL;

						LT_ShowWindow(Manager,TRUE);
					}

					if(MsgWindow == PatternWindow)
					{
						LT_DeleteHandle(Selector);
						Selector = NULL;
						PatternWindow = NULL;

						LT_ShowWindow(Manager,TRUE);
					}

					if(MsgWindow == GroupWindow)
					{
						LT_DeleteHandle(Grouping);
						Grouping = NULL;
						GroupWindow = NULL;

						LT_ShowWindow(Manager,TRUE);
					}

					if(MsgWindow == SortWindow)
					{
						LT_DeleteHandle(Sorting);
						Sorting = NULL;
						SortWindow = NULL;

						LT_ShowWindow(Manager,TRUE);
					}
				}

					// Hit a gadget

				if(MsgClass == IDCMP_GADGETUP)
				{
					switch(MsgGadgetID)
					{
							// Toggle all entries

						case GAD_TOGGLE_ALL:
						{
							LONG LocalCount = 0;

							LT_SetAttributes(Handle,GAD_NAMELIST,
								GTLV_Labels,	~0,
							TAG_DONE);

							for(TempNode = (struct PhoneNode *)CurrentList -> lh_Head ; TempNode -> VanillaNode . ln_Succ ; TempNode = (struct PhoneNode *)TempNode -> VanillaNode . ln_Succ)
							{
								if(TempNode -> Entry -> Count == -1)
								{
									if(!SelectedNode)
									{
										SelectedNode	= TempNode;
										Selected		= GetNodeOffset((struct Node *)SelectedNode,CurrentList);
									}

									TempNode -> Entry -> Count = LocalCount++;

									SPrintf(TempNode -> LocalName,"%3ld - %s",LocalCount,TempNode -> Entry -> Header -> Name);
								}
								else
								{
									TempNode -> Entry -> Count = -1;

									SPrintf(TempNode -> LocalName,"      %s",TempNode -> Entry -> Header -> Name);
								}

								if(TempNode -> Entry -> NodeGroup)
									strcpy(TempNode -> Entry -> NodeGroup -> LocalName,TempNode -> LocalName);
							}

							Count = LocalCount;

							UpdateWindowTitle(PhoneWindow,WindowTitle,Count);

							LT_SetAttributes(Manager,GAD_NAMELIST,
								GTLV_Labels,	CurrentList,
								GTLV_Selected,	SelectedNode ? Selected : ~0,
							TAG_DONE);

							HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

							break;
						}

							// Select all entries

						case GAD_SELECT_ALL:

							LT_SetAttributes(Handle,GAD_NAMELIST,
								GTLV_Labels,	~0,
							TAG_DONE);

							for(TempNode = (struct PhoneNode *)CurrentList -> lh_Head ; TempNode -> VanillaNode . ln_Succ ; TempNode = (struct PhoneNode *)TempNode -> VanillaNode . ln_Succ)
							{
								if(TempNode -> Entry -> Count == -1)
								{
									if(!SelectedNode)
									{
										SelectedNode	= TempNode;
										Selected		= GetNodeOffset((struct Node *)SelectedNode,CurrentList);
									}

									TempNode -> Entry -> Count = Count++;

									SPrintf(TempNode -> LocalName,"%3ld - %s",Count,TempNode -> Entry -> Header -> Name);

									if(TempNode -> Entry -> NodeGroup)
										strcpy(TempNode -> Entry -> NodeGroup -> LocalName,TempNode -> LocalName);
								}
							}

							UpdateWindowTitle(PhoneWindow,WindowTitle,Count);

							LT_SetAttributes(Manager,GAD_NAMELIST,
								GTLV_Labels,	CurrentList,
								GTLV_Selected,	SelectedNode ? Selected : ~0,
							TAG_DONE);

							HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

							break;

							// Picked a list entry

						case GAD_NAMELIST:

							UpdateEditorData(Editor,SelectedNode,Hide);

							Selected = MsgCode;

								// Get the selected node entry from the right list

							if(PhonebookDefaultGroup)
								SelectedNode = (struct PhoneNode *)GetListNode(Selected,CurrentList);
							else
								SelectedNode = Phonebook[Selected] -> Node;

								// Now check if the entry needs to be tagged or toggled

							if(SelectedNode -> Entry -> Header -> Number[0] && SelectedNode -> Entry -> Header -> Name[0])
							{
								if(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
									ClickAction = CLICK_TOGGLE;
								else
									ClickAction = CLICK_SELECT;
							}
							else
								ClickAction = CLICK_SELECT;

								// Toggle the tag

							if(ClickAction == CLICK_TOGGLE)
							{
								LT_SetAttributes(Handle,GAD_NAMELIST,
									GTLV_Labels,	~0,
								TAG_DONE);

								if(SelectedNode -> Entry -> Count == -1)
								{
									SelectedNode -> Entry -> Count = Count++;

									SPrintf(SelectedNode -> LocalName,"%3ld - %s",Count,SelectedNode -> Entry -> Header -> Name);

									if(SelectedNode -> Entry -> NodeGroup)
										strcpy(SelectedNode -> Entry -> NodeGroup -> LocalName,SelectedNode -> LocalName);
								}
								else
								{
									RemoveDialEntry(SelectedNode);

									Count--;
								}

								LT_SetAttributes(Handle,GAD_NAMELIST,
									GTLV_Labels,		CurrentList,
								TAG_DONE);
							}

							UpdateWindowTitle(PhoneWindow,WindowTitle,Count);

							HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

							break;

							// Clear all selections in this group

						case GAD_CLEAR_ALL:

							LT_SetAttributes(Handle,GAD_NAMELIST,
								GTLV_Labels,	~0,
							TAG_DONE);

							for(TempNode = (struct PhoneNode *)CurrentList -> lh_Head ; TempNode -> VanillaNode . ln_Succ ; TempNode = (struct PhoneNode *)TempNode -> VanillaNode . ln_Succ)
							{
								if(TempNode -> Entry -> Count != -1)
								{
									SPrintf(TempNode -> LocalName,"      %s",TempNode -> Entry -> Header -> Name);

									TempNode -> Entry -> Count = -1;

									Count--;

									if(TempNode -> Entry -> NodeGroup)
										strcpy(TempNode -> Entry -> NodeGroup -> LocalName,TempNode -> LocalName);
								}
							}

							UpdateWindowTitle(PhoneWindow,WindowTitle,Count);

							HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

							break;

							// Print the current group

						case GAD_PRINT:

							LT_LockWindow(PhoneWindow);
							LT_LockWindow(PasswordWindow);
							LT_LockWindow(EditWindow);
							LT_LockWindow(PatternWindow);
							LT_LockWindow(GroupWindow);
							LT_LockWindow(SortWindow);

							PrintPanel(PhoneWindow,CurrentList,Count);

							LT_UnlockWindow(PhoneWindow);
							LT_UnlockWindow(PasswordWindow);
							LT_UnlockWindow(EditWindow);
							LT_UnlockWindow(PatternWindow);
							LT_UnlockWindow(GroupWindow);
							LT_UnlockWindow(SortWindow);

							LT_ShowWindow(Handle,TRUE);

							break;

							// Copy the setting stored with the current entry
							// into the global settings

						case GAD_USE:

							UpdateEditorData(Editor,SelectedNode,Hide);

							if(SelectedNode)
							{
								SaveConfig(Config,PrivateConfig);

								SaveConfig(SelectedNode -> Entry -> Config,Config);

								strcpy(Password,SelectedNode -> Entry -> Header -> Password);
								strcpy(UserName,SelectedNode -> Entry -> Header -> UserName);

								ConfigSetup();

								Done = TRUE;

								ConfigChanged = FALSE;
							}

							break;

							// Add a new phonebook entry to the group

						case GAD_ADD:

							UpdateEditorData(Editor,SelectedNode,Hide);

							LT_SetAttributes(Handle,GAD_NAMELIST,
								GTLV_Labels,	~0,
							TAG_DONE);

							if(PhoneList)
							{
								DeletePhoneList(PhoneList);

								PhoneList = NULL;
							}

								// Create the new entry

							if(Entry = NewPhoneEntry())
							{
									// Then fiddle with the list to display

								if(PhoneList = CreatePhoneList())
								{
										// Grab the new node

									SelectedNode = Entry->Node;

										// Are we displaying a group?

									if(PhonebookDefaultGroup)
									{
										PhoneGroupNode *Group;

											// Link this entry into the group

										Group = (PhoneGroupNode *)(((ULONG)Labels[PhonebookDefaultGroup]) - offsetof(PhoneGroupNode,LocalName));

										if(AddGroupEntry(Group,SelectedNode))
											ListMax++;
										else
										{
												// If this went wrong, move up to the
												// main list

											DisplayBeep(PhoneWindow -> WScreen);

											PhonebookDefaultGroup = 0;

											LT_SetAttributes(Manager,GAD_GROUPID,
												GTCY_Active,0,
											TAG_DONE);

											CurrentList = PhoneList;
											ListMax = NumPhoneEntries;
										}
									}
									else
									{
											// This needs to be updated

										CurrentList = PhoneList;
										ListMax++;
									}

									Selected = ListMax - 1;

									LT_SetAttributes(Handle,GAD_NAMELIST,
										GTLV_Labels,		CurrentList,
										GTLV_Selected,		Selected,
										GA_Disabled,		FALSE,
									TAG_DONE);

										// Open the editor window so the user can edit the new entry

									if(!Editor)
									{
										if(Editor = CreateEditorHandle(Manager -> Window,CurrentList,Count,SelectedNode,TRUE,PhoneWindow -> UserPort))
											EditWindow = Editor -> Window;
									}

									HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

									RebuildMenu = PhonebookChanged = TRUE;
									UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
								}
								else
									ClearList = TRUE;
							}
							else
								ClearList = TRUE;

							break;

							// Edit the current entry

						case GAD_EDIT:

							UpdateEditorData(Editor,SelectedNode,Hide);

							if(SelectedNode)
							{
								if(!Editor)
								{
									if(Editor = CreateEditorHandle(Manager -> Window,CurrentList,Count,SelectedNode,TRUE,PhoneWindow -> UserPort))
										EditWindow = Editor -> Window;
								}
								else
									HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,TRUE,Hide,FALSE);
							}

							break;

							// Hide user name and password?

						case GAD_HIDE_USERNAME_PASSWORD:

							if(SelectedNode)
							{
								if(!Hide)
								{
									strcpy(SelectedNode -> Entry -> Header -> UserName,LT_GetString(Editor,GAD_USER_NAME));
									strcpy(SelectedNode -> Entry -> Header -> Password,LT_GetString(Editor,GAD_USER_PASSWORD));
								}

								HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,TRUE,MsgCode,FALSE);
							}

							Hide = MsgCode;

							break;

							// Make a copy of the current entry

						case GAD_COPY:

							UpdateEditorData(Editor,SelectedNode,Hide);

							if(SelectedNode)
							{
								struct PhoneEntry *New;

								LT_SetAttributes(Handle,GAD_NAMELIST,
									GTLV_Labels,	~0,
								TAG_DONE);

									// Create a blank entry

								if(New = NewPhoneEntry())
								{
									struct List *LocalPhoneList;

										// Create a new display list, we just
										// discarded the other one...

									if(LocalPhoneList = CreatePhoneList())
									{
										struct PhoneNode *Source;
										LONG i,Len1,Len2;
										LONG Copies;
										UBYTE TempName[80];
										STRPTR BaseName;
										STRPTR Trailer;

											// Remember where the old node pointed to

										Source = SelectedNode;

											// This is the one we just added

										SelectedNode = New->Node;

											// Is a group currently being displayed?

										if(PhonebookDefaultGroup)
										{
											PhoneGroupNode *Group;

												// Move back to the group header

											Group = (PhoneGroupNode *)(((ULONG)Labels[PhonebookDefaultGroup]) - offsetof(PhoneGroupNode,LocalName));

												// Add the new entry to the group

											if(AddGroupEntry(Group,SelectedNode))
											{
												struct PhoneNode *Node;

													// Now find out which list index this
													// group entry maps to

												SelectedNode = SelectedNode -> Entry -> NodeGroup;

												for(Selected = 0, Node = (struct PhoneNode *)Group -> GroupList . mlh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ)
												{
													if(Node == SelectedNode)
														break;
													else
														Selected++;
												}

												ListMax++;
											}
											else
											{
												DisplayBeep(PhoneWindow -> WScreen);

												PhonebookDefaultGroup = 0;

												LT_SetAttributes(Manager,GAD_GROUPID,
													GTCY_Active,0,
												TAG_DONE);

												CurrentList = LocalPhoneList;
												ListMax = NumPhoneEntries;
											}
										}
										else
										{
											CurrentList = LocalPhoneList;
											ListMax++;
											Selected = ListMax - 1;
										}

										CopyPhoneHeader(Source -> Entry -> Header,SelectedNode -> Entry -> Header);

										FreeTimeDateList((struct List *)&SelectedNode -> Entry -> TimeDateList);

										CopyTimeDateList((struct List *)&Source -> Entry -> TimeDateList,(struct List *)&SelectedNode -> Entry -> TimeDateList,FALSE);

											/* Allocate space for the config data. */

										for(i = PREF_SERIAL ; i <= PREF_FASTMACROFILENAME ; i++)
										{
											if(GetConfigEntry(Source -> Entry -> Config,i))
												CreateConfigEntry(SelectedNode -> Entry -> Config,i);
										}

											/* Copy the data. */

										SaveConfig(Source -> Entry -> Config,SelectedNode -> Entry -> Config);

										RebuildMenu = PhonebookChanged = TRUE;

											// Build the "Copy <filler>of" template

										SPrintf(TempName,LocaleString(MSG_COPY_OF_TXT)," <filler>");

											// Now look where the "<filler>" ended up

										for(i = 0 ; i < strlen(TempName) ; i++)
										{
											if(!Strnicmp(&TempName[i],"<filler>",strlen("<filler>")))
											{
													// Chop off everything after the "Copy " string

												TempName[i] = 0;
												Trailer = &TempName[i + strlen("<filler>")];
												break;
											}
										}

											// Does this entry have a leading "Copy " string?

										if(!Strnicmp(TempName,SelectedNode -> Entry -> Header -> Name,strlen(TempName)))
										{
											BaseName = &SelectedNode -> Entry -> Header -> Name[strlen(TempName)];

												// Skip the numbers

											while(*BaseName >= '0' && *BaseName <= '9')
												BaseName++;

												// Skip the spaces

											while(*BaseName == ' ')
												BaseName++;

												// If there is the trailing "of", skip it

											if(!Strnicmp(BaseName,Trailer,strlen(Trailer)))
												BaseName += strlen(Trailer);

												// Skip the spaces

											while(*BaseName == ' ')
												BaseName++;
										}
										else
											BaseName = SelectedNode -> Entry -> Header -> Name;

										Len1 = strlen(BaseName);

										Copies = 0;

										for(i = 0 ; i < NumPhoneEntries ; i++)
										{
											if(Phonebook[i] != SelectedNode -> Entry)
											{
												Len2 = strlen(Phonebook[i] -> Header -> Name);

												if(Len2 >= Len1)
												{
													if(!Stricmp(&Phonebook[i] -> Header -> Name[Len2 - Len1],BaseName))
														Copies++;
												}
											}
										}

										if(Copies)
										{
											UBYTE Counter[10];

											if(Copies > 1)
												SPrintf(Counter," %ld ",Copies);
											else
												strcpy(Counter," ");

											SPrintf(TempName,LocaleString(MSG_COPY_OF_TXT),Counter);
											strcat(TempName," ");

											if(strlen(TempName) + strlen(BaseName) < 40)
											{
												strcat(TempName,BaseName);

												strcpy(SelectedNode -> Entry -> Header -> Name,TempName);
											}
										}

										SPrintf(SelectedNode -> LocalName,"      %s",SelectedNode -> Entry -> Header -> Name);

										if(SelectedNode -> Entry -> NodeGroup)
											strcpy(SelectedNode -> Entry -> NodeGroup -> LocalName,SelectedNode -> LocalName);

										LT_SetAttributes(Handle,GAD_NAMELIST,
											GTLV_Labels,	CurrentList,
											GTLV_Selected,	Selected,
										TAG_DONE);

										if(!Editor)
										{
											if(Editor = CreateEditorHandle(Manager -> Window,CurrentList,Count,SelectedNode,TRUE,PhoneWindow -> UserPort))
												EditWindow = Editor -> Window;
										}
										else
											HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,TRUE,Hide,TRUE);

										if(PhoneList)
											DeletePhoneList(PhoneList);

										PhoneList = LocalPhoneList;

										break;
									}
								}

									// So that didn't work...

								DisplayBeep(Window -> WScreen);

								LT_SetAttributes(Handle,GAD_NAMELIST,
									GTLV_Labels,		CurrentList,
									GTLV_Selected,		Selected,
								TAG_DONE);
							}

							break;

							// Delete the current entry

						case GAD_DELETE:

							if(SelectedNode)
							{
									// We canot delete entries that are still in use by
									// the status server.

								if(SelectedNode -> Entry == ChosenEntry)
									ShowRequest(PhoneWindow,LocaleString(MSG_PHONEPANEL_PHONE_ENTRY_IN_USE_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
								else
								{
									struct PhoneNode	*Next;
									struct PhoneEntry	*Entry;

										// Disconnect the list

									LT_SetAttributes(Handle,GAD_NAMELIST,
										GTLV_Labels,~0,
									TAG_DONE);

										// Pick the node that will show up as the next
										// selected node.

									if(SelectedNode -> VanillaNode . ln_Succ -> ln_Succ)
										Next = (struct PhoneNode *)SelectedNode -> VanillaNode . ln_Succ;
									else
									{
										if(SelectedNode -> VanillaNode . ln_Pred -> ln_Pred)
											Next = (struct PhoneNode *)SelectedNode -> VanillaNode . ln_Pred;
										else
											Next = NULL;
									}

									if(Next)
										Entry = Next -> Entry;
									else
										Entry = NULL;

										// This is definitely a change

									RebuildMenu = PhonebookChanged = TRUE;

										// If this particular entry is tagged,
										// untag it first

									if(SelectedNode -> Entry -> Count != -1)
									{
										RemoveDialEntry(SelectedNode);

										Count--;

										UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
									}

										// Get rid of the entry

									if(PhonebookDefaultGroup)
										RemPhoneEntry(SelectedNode,0);
									else
										RemPhoneEntry(NULL,Selected);

										// One less in the group...

									ListMax--;

										// Discard the list

									if(PhoneList)
									{
										DeletePhoneList(PhoneList);

										PhoneList = NULL;
									}

										// Are there still entries left?

									if(NumPhoneEntries > 0)
									{
											// Form a new list

										if(PhoneList = CreatePhoneList())
										{
												// Move to the next selected entry

											if(PhonebookDefaultGroup)
												SelectedNode = Next;
											else
											{
												CurrentList = PhoneList;

												SelectedNode = Entry -> Node;
											}

												// Adapt the index

											if(Selected == ListMax)
												Selected--;

											LT_SetAttributes(Handle,GAD_NAMELIST,
												GTLV_Labels,	CurrentList,
												GTLV_Selected,	Selected,
											TAG_DONE);

											HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);
											UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
										}
										else
											ClearList = TRUE;
									}
									else
										ClearList = TRUE;
								}
							}

							if(!Count)
							{
								LT_DeleteHandle(Grouping);

								Grouping = NULL;
								GroupWindow = NULL;
							}

							break;

							// Change the system name; this is what shows up in the list

						case GAD_SYSTEM_NAME:

							if(SelectedNode)
							{
								LT_SetAttributes(Manager,GAD_NAMELIST,
									GTLV_Labels,~0,
								TAG_DONE);

								strcpy(SelectedNode -> Entry -> Header -> Name,(STRPTR)LT_GetAttributes(Editor,GAD_SYSTEM_NAME,TAG_DONE));

								UpdatePhoneList(PhoneList);

								if(!SelectedNode -> Entry -> Header -> Name[0])
								{
									LT_SetAttributes(Manager,GAD_NAMELIST,
										GTLV_Labels,	~0,
									TAG_DONE);

									if(SelectedNode -> Entry -> Count != -1)
									{
										RemoveDialEntry(SelectedNode);

										Count--;

										UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
									}
								}

								HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

								RebuildMenu = PhonebookChanged = TRUE;

								if(MsgCode == '\r')
									LT_Activate(Editor,GAD_COMMENT);
							}

							break;

							// Change the comment; this is what shows up directly below the list

						case GAD_COMMENT:

							if(SelectedNode)
							{
								strcpy(SelectedNode -> Entry -> Header -> Comment,(STRPTR)LT_GetAttributes(Editor,GAD_COMMENT,TAG_DONE));

								PhonebookChanged = TRUE;

								if(MsgCode == '\r')
									LT_Activate(Handle,GAD_NUMBERS);

								LT_SetAttributes(Manager,GAD_COMMENTLINE,
									GTTX_Text,	SelectedNode -> Entry -> Header -> Comment,
								TAG_DONE);
							}

							break;

							// Put this entry into the quick dial menu or don't

						case GAD_QUICK_MENU:

							if(SelectedNode)
							{
								if(SelectedNode -> Entry -> Header -> QuickMenu != MsgCode)
								{
									SelectedNode -> Entry -> Header -> QuickMenu = MsgCode;

									RebuildMenu = PhonebookChanged = TRUE;
								}
							}

							break;

							// Do the same for the autodial feature

						case GAD_AUTODIAL:

							if(SelectedNode)
								SelectedNode -> Entry -> Header -> AutoDial = MsgCode;

							break;

							// Change the phone numbers for this entry

						case GAD_NUMBERS:

							if(SelectedNode)
							{
								strcpy(SelectedNode -> Entry -> Header -> Number,(STRPTR)LT_GetAttributes(Editor,GAD_NUMBERS,TAG_DONE));

								PhonebookChanged = TRUE;

								if(!SelectedNode -> Entry -> Header -> Number[0])
								{
									LT_SetAttributes(Manager,GAD_NAMELIST,
										GTLV_Labels,	~0,
									TAG_DONE);

									if(SelectedNode -> Entry -> Count != -1)
									{
										RemoveDialEntry(SelectedNode);

										Count--;
										UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
									}
								}

								HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);
							}

							break;

							// Change the user name

						case GAD_USER_NAME:

							if(SelectedNode)
							{
								strcpy(SelectedNode -> Entry -> Header -> UserName,(STRPTR)LT_GetAttributes(Editor,GAD_USER_NAME,TAG_DONE));

								PhonebookChanged = TRUE;
							}

							break;

							// Change the login password

						case GAD_USER_PASSWORD:

							if(SelectedNode)
							{
								strcpy(SelectedNode -> Entry -> Header -> Password,(STRPTR)LT_GetAttributes(Editor,GAD_USER_PASSWORD,TAG_DONE));

								PhonebookChanged = TRUE;
							}

							break;

							// Load a new phonebook

						case GAD_LOAD:

							LT_LockWindow(PhoneWindow);
							LT_LockWindow(PasswordWindow);
							LT_LockWindow(EditWindow);
							LT_LockWindow(PatternWindow);
							LT_LockWindow(GroupWindow);
							LT_LockWindow(SortWindow);

								// If an entry is still in use, don't let the user replace
								// the phonebook

							if(ChosenEntry)
								ShowRequest(PhoneWindow,LocaleString(MSG_PHONEPANEL_PHONE_ENTRY_IN_USE_LOAD_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
							else
							{
								SplitFileName(LastPhone,&DummyChar,DummyBuffer);

								if(FileRequest = GetFile(PhoneWindow,LocaleString(MSG_PHONEPANEL_LOAD_PHONEBOOK_TXT),DummyBuffer,DummyChar,DummyBuffer,"#?.prefs",FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_LOAD_TXT),TRUE))
								{
									STRPTR *OtherLabels;

									LT_SetAttributes(Handle,GAD_NAMELIST,
										GTLV_Labels,	~0,
									TAG_DONE);

									if(PhoneList)
										DeletePhoneList(PhoneList);

									LT_DeleteHandle(Grouping);

									Grouping = NULL;
									GroupWindow = NULL;

									if(!LoadPhonebook(DummyBuffer,NULL))
										ShowError(PhoneWindow,ERR_LOAD_ERROR,IoErr(),DummyBuffer);
									else
									{
										strcpy(LastPhone,DummyBuffer);
										strcpy(Config->PhonebookFileName,LastPhone);

										PhonebookChanged = FALSE;

										RebuildMenu = TRUE;
									}

									if(!(PhoneList = CreatePhoneList()))
									{
										LT_SetAttributes(Handle,GAD_NAMELIST,
											GTLV_Labels,	NULL,
											GTLV_Selected,	~0,
											GA_Disabled,	TRUE,
										TAG_DONE);
									}

									CurrentList = PhoneList;
									ListMax = NumPhoneEntries;

									Selected = ~0;
									SelectedNode = NULL;

									Count = 0;

									FreeAslRequest(FileRequest);

										// The group labels need to be rebuilt. If we run
										// out of memory, access to groups other than the
										// main group will be blocked

									if(OtherLabels = BuildLabels())
									{
										LT_SetAttributes(Manager,GAD_GROUPID,
											GTCY_Labels,OtherLabels,
										TAG_DONE);

										FreeVecPooled(Labels);

										Labels = OtherLabels;
									}
									else
									{
										Labels[1] = NULL;

										PhonebookDefaultGroup = 0;
									}

									if(PhonebookDefaultGroup)
									{
										PhoneGroupNode	*Group;
										struct Node		*Node;

											// Grab the list we wanted

										Group = (PhoneGroupNode *)(((ULONG)Labels[PhonebookDefaultGroup]) - offsetof(PhoneGroupNode,LocalName));

										LT_SetAttributes(Manager,GAD_SPLIT_GROUP,
											GA_Disabled,FALSE,
										TAG_DONE);

										CurrentList = (struct List *)&Group -> GroupList;

										for(ListMax = 0, Node = CurrentList -> lh_Head ; Node -> ln_Succ ; Node = Node -> ln_Succ)
											ListMax++;
									}

									if(GroupWindow)
										LT_SetAttributes(Grouping,GAD_GROUP_LIST,GTCY_Labels,Labels,TAG_DONE);

									LT_SetAttributes(Manager,GAD_GROUPID,
										GTCY_Labels,	Labels,
										GTCY_Active,	PhonebookDefaultGroup,
									TAG_DONE);

									LT_SetAttributes(Manager,GAD_MAIN_AUTODIAL,
										GTCB_Checked,	PhonebookAutoDial,
									TAG_DONE);

									LT_SetAttributes(Manager,GAD_MAIN_EXIT_WHEN_FINISHED,
										GA_Disabled,	!PhonebookAutoDial,
										GTCB_Checked,	PhonebookAutoExit,
									TAG_DONE);

									if(CurrentList)
									{
										LT_SetAttributes(Handle,GAD_NAMELIST,
											GTLV_Labels,	CurrentList,
											GTLV_Selected,	~0,
											GA_Disabled,	!ListMax,
										TAG_DONE);

										FreeDialList(TRUE);
									}

									HighlightEntry(Manager,Editor,CurrentList,NULL,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

									UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
								}
							}

							LT_UnlockWindow(PhoneWindow);
							LT_UnlockWindow(PasswordWindow);
							LT_UnlockWindow(EditWindow);
							LT_UnlockWindow(PatternWindow);
							LT_UnlockWindow(GroupWindow);
							LT_UnlockWindow(SortWindow);

							break;

							// Merge existing phonebook with a new phonebook loaded from disk

						case GAD_MERGE:

							UpdateEditorData(Editor,SelectedNode,Hide);

							LT_LockWindow(PhoneWindow);
							LT_LockWindow(PasswordWindow);
							LT_LockWindow(EditWindow);
							LT_LockWindow(PatternWindow);
							LT_LockWindow(GroupWindow);
							LT_LockWindow(SortWindow);

							if(ChosenEntry)
								ShowRequest(PhoneWindow,LocaleString(MSG_PHONEPANEL_PHONE_ENTRY_IN_USE_LOAD_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
							else
							{
								PhonebookHandle BookHandle;

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

								CopyMem(PhonePassword,BookHandle . PhonePassword,256);
								BookHandle . PhonePasswordUsed = PhonePasswordUsed;

								SplitFileName(LastPhone,&DummyChar,DummyBuffer);

								if(FileRequest = GetFile(PhoneWindow,LocaleString(MSG_PHONEPANEL_LOAD_PHONEBOOK_TXT),DummyBuffer,DummyChar,DummyBuffer,"#?.prefs",FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_LOAD_TXT),TRUE))
								{
									STRPTR *OtherLabels;

									LT_SetAttributes(Handle,GAD_NAMELIST,
										GTLV_Labels,	~0,
									TAG_DONE);

									if(PhoneList)
										DeletePhoneList(PhoneList);

									if(!LoadPhonebook(DummyBuffer,&BookHandle))
										ShowError(PhoneWindow,ERR_LOAD_ERROR,IoErr(),DummyBuffer);
									else
									{
										if(MergePhonebook(&BookHandle))
											PhonebookChanged = RebuildMenu = TRUE;
										else
											DeletePhonebook(BookHandle . Phonebook,BookHandle . PhoneSize,TRUE);
									}

									if(PhoneList = CreatePhoneList())
									{
										LT_SetAttributes(Handle,GAD_NAMELIST,
											GTLV_Labels,	PhoneList,
											GTLV_Selected,	~0,
											GA_Disabled,	FALSE,
										TAG_DONE);

										FreeDialList(TRUE);
									}
									else
									{
										LT_SetAttributes(Handle,GAD_NAMELIST,
											GTLV_Labels,	NULL,
											GTLV_Selected,	~0,
											GA_Disabled,	TRUE,
										TAG_DONE);
									}

									CurrentList = PhoneList;
									ListMax = NumPhoneEntries;

									Selected = ~0;
									SelectedNode = NULL;

									Count = 0;

									HighlightEntry(Manager,Editor,CurrentList,NULL,Count,PhonebookDefaultGroup = 0,FALSE,Hide,TRUE);

									FreeAslRequest(FileRequest);

									if(OtherLabels = BuildLabels())
									{
										LT_SetAttributes(Manager,GAD_GROUPID,
											GTCY_Labels,OtherLabels,
										TAG_DONE);

										FreeVecPooled(Labels);

										Labels = OtherLabels;
									}
									else
									{
										Labels[1] = NULL;

										PhonebookDefaultGroup = 0;
									}

									if(GroupWindow)
										LT_SetAttributes(Grouping,GAD_GROUP_LIST,GTCY_Labels,Labels,TAG_DONE);

									LT_SetAttributes(Manager,GAD_GROUPID,
										GTCY_Labels,	Labels,
										GTCY_Active,	0,
									TAG_DONE);

									UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
								}
							}

							LT_UnlockWindow(PhoneWindow);
							LT_UnlockWindow(PasswordWindow);
							LT_UnlockWindow(EditWindow);
							LT_UnlockWindow(PatternWindow);
							LT_UnlockWindow(GroupWindow);
							LT_UnlockWindow(SortWindow);

							break;

							// Join the currently tagged entries in a new group

						case GAD_MAKE_GROUP:

							if(GroupWindow)
							{
								LT_ShowWindow(Grouping,TRUE);
								LT_Activate(Grouping,GAD_GROUP_NAME);
							}
							else
							{
								if(Grouping = CreateGroupHandle(PhoneWindow,Labels,PhonebookDefaultGroup))
									GroupWindow = Grouping -> Window;
							}

							break;

							// Copy the selected group name into the text entry field

						case GAD_GROUP_LIST:

							LT_SetAttributes(Grouping,GAD_GROUP_NAME,
								GTST_String,	Labels[MsgCode],
							TAG_DONE);

							break;

							// Do something to the selected entries.

						case GAD_GROUP_OK:

							LT_LockWindow(PhoneWindow);
							LT_LockWindow(PasswordWindow);
							LT_LockWindow(EditWindow);
							LT_LockWindow(PatternWindow);
							LT_LockWindow(GroupWindow);
							LT_LockWindow(SortWindow);

							LT_SetAttributes(Manager,GAD_NAMELIST,
								GTLV_Labels,	~0,
							TAG_DONE);

								// Which group should the tagged entries go into?

							Name = (STRPTR)LT_GetAttributes(Grouping,GAD_GROUP_NAME,TAG_DONE);

								// If it's "All", then the entries will be removed from the
								// subgroups and end up in the main group

							if(!Stricmp(Name,Labels[0]))
							{
								struct PhoneNode *Next;

								for(TempNode = (struct PhoneNode *)CurrentList -> lh_Head ; Next = (struct PhoneNode *)TempNode -> VanillaNode . ln_Succ ; TempNode = Next)
								{
									if(TempNode -> Entry -> ThisGroup && TempNode -> Entry -> Count != -1)
									{
										Remove(TempNode -> Entry -> NodeGroup);

										FreeVecPooled(TempNode -> Entry -> NodeGroup);

										TempNode -> Entry -> ThisGroup = NULL;
										TempNode -> Entry -> NodeGroup = NULL;
									}
								}
							}
							else
							{
								PhoneGroupNode	*GroupNode;
								PhoneGroupNode	*WhichGroup		= NULL;
								BOOL			 RenameGroup	= TRUE,
												 Success		= TRUE;

									// Check if the requested group already exists. In this
									// case, the user wants to move entries from one group
									// to another.

								for(GroupNode = (PhoneGroupNode *)PhoneGroupList . mlh_Head ; GroupNode -> Node . ln_Succ ; GroupNode = (PhoneGroupNode *)GroupNode -> Node . ln_Succ)
								{
									if(!Stricmp(GroupNode -> Node . ln_Name,Name))
									{
										RenameGroup = FALSE;
										break;
									}
								}

									// Are we displaying a group list at all?

								if(CurrentList && CurrentList != PhoneList)
								{
									struct PhoneNode *SomeNode;

									for(SomeNode = (struct PhoneNode *)CurrentList -> lh_Head ; SomeNode -> VanillaNode . ln_Succ ; SomeNode = (struct PhoneNode *)SomeNode -> VanillaNode . ln_Succ)
									{
										if(SomeNode -> Entry -> Count != -1)
										{
											WhichGroup = SomeNode -> Entry -> ThisGroup;
											break;
										}
									}

										// If there is no group to play with, don't rename it

									if(!WhichGroup)
										RenameGroup = FALSE;
								}
								else
									RenameGroup = FALSE;

									// Check if the marked entries are already
									// members of the same group

								if(RenameGroup)
								{
									LONG i,NotGrouped = 0,InGroup = 0;

									for(i = 0 ; RenameGroup && i < NumPhoneEntries ; i++)
									{
										if(Phonebook[i] -> Count != -1)
										{
											if(Phonebook[i] -> ThisGroup)
											{
												if(NotGrouped)
													RenameGroup = FALSE;
												else
												{
													if(Phonebook[i] -> ThisGroup == WhichGroup)
														InGroup++;
													else
														RenameGroup = FALSE;
												}
											}
											else
											{
												if(WhichGroup)
													RenameGroup = FALSE;
												else
													NotGrouped++;
											}
										}
										else
										{
											if(Phonebook[i] -> ThisGroup == WhichGroup)
												InGroup++;
										}
									}

										// If we should continue, check if there are
										// any group members at all and if all members
										// of the group are selected.

									if(NotGrouped || InGroup != Count)
										RenameGroup = FALSE;
								}

								if(RenameGroup)
								{
									strcpy(WhichGroup -> LocalName,Name);

									GroupNode = WhichGroup;
								}
								else
								{
										// Either find an existing group of the given name
										// or make a new group.

									if(GroupNode = CreatePhoneGroup(Name,&PhoneGroupList))
									{
										struct PhoneNode	*Next;
										LONG				 Total = 0;

											// Add the tagged entries to the group

										for(TempNode = (struct PhoneNode *)CurrentList -> lh_Head ; Next = (struct PhoneNode *)TempNode -> VanillaNode . ln_Succ ; TempNode = Next)
										{
											if(TempNode -> Entry -> Count != -1)
											{
												AddGroupEntry(GroupNode,TempNode);
												Total++;
											}
										}

										if(!Total && SelectedNode)
											AddGroupEntry(GroupNode,SelectedNode);
									}
									else
										Success = FALSE;
								}

								if(Success)
								{
									STRPTR *OtherLabels;

										// Now update the labels

									if(OtherLabels = BuildLabels())
									{
										PhoneGroupNode *This;

										LT_SetAttributes(Manager,GAD_GROUPID,
											GTCY_Labels,OtherLabels,
										TAG_DONE);

										FreeVecPooled(Labels);

										Labels = OtherLabels;

										CurrentList = (struct List *)&GroupNode -> GroupList;

										for(PhonebookDefaultGroup = 1, This = (PhoneGroupNode *)PhoneGroupList . mlh_Head ; This -> Node . ln_Succ ; This = (PhoneGroupNode *)This -> Node . ln_Succ)
										{
											if(This == GroupNode)
												break;
											else
												PhonebookDefaultGroup++;
										}
									}
									else
									{
										Labels[1] = NULL;

										PhonebookDefaultGroup = 0;

										CurrentList = PhoneList;
										ListMax = NumPhoneEntries;
									}

									if(GroupWindow)
									{
										LT_SetAttributes(Grouping,GAD_GROUP_LIST,
											GTCY_Labels,	Labels,
											GTCY_Active,	PhonebookDefaultGroup,
										TAG_DONE);
									}

									LT_SetAttributes(Manager,GAD_GROUPID,
										GTCY_Labels,	Labels,
										GTCY_Active,	PhonebookDefaultGroup,
									TAG_DONE);

									RebuildMenu = PhonebookChanged = TRUE;
								}
								else
									DisplayBeep(PhoneWindow -> WScreen);
							}

							Selected = ~0;
							SelectedNode = NULL;

							HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

							LT_UnlockWindow(PhoneWindow);
							LT_UnlockWindow(PasswordWindow);
							LT_UnlockWindow(EditWindow);
							LT_UnlockWindow(PatternWindow);
							LT_UnlockWindow(GroupWindow);
							LT_UnlockWindow(SortWindow);

							// Close the grouping window without doing anything

						case GAD_GROUP_CANCEL:

							LT_DeleteHandle(Grouping);

							Grouping = NULL;
							GroupWindow = NULL;

							LT_ShowWindow(Manager,TRUE);

							break;

							// Display a different group

						case GAD_GROUPID:

							Selected = ~0;
							SelectedNode = NULL;

							LT_SetAttributes(Manager,GAD_NAMELIST,
								GTLV_Selected,	~0,
							TAG_DONE);

								// Special group?

							if(MsgCode)
							{
								PhoneGroupNode	*Group;
								struct Node		*Node;

									// Grab the list we wanted

								Group = (PhoneGroupNode *)(((ULONG)Labels[MsgCode]) - offsetof(PhoneGroupNode,LocalName));

								LT_SetAttributes(Manager,GAD_SPLIT_GROUP,
									GA_Disabled,FALSE,
								TAG_DONE);

								CurrentList = (struct List *)&Group -> GroupList;

								for(ListMax = 0, Node = CurrentList -> lh_Head ; Node -> ln_Succ ; Node = Node -> ln_Succ)
									ListMax++;
							}
							else
							{
								LT_SetAttributes(Manager,GAD_SPLIT_GROUP,
									GA_Disabled,TRUE,
								TAG_DONE);

								CurrentList	= PhoneList;
								ListMax		= NumPhoneEntries;
							}

							LT_SetAttributes(Manager,GAD_NAMELIST,
								GTLV_Labels,CurrentList,
							TAG_DONE);

							HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

							break;

							// Get rid of this group

						case GAD_SPLIT_GROUP:

							LT_SetAttributes(Manager,GAD_NAMELIST,
								GTLV_Labels,~0,
							TAG_DONE);

							LT_DeleteHandle(Grouping);

							Grouping = NULL;
							GroupWindow = NULL;

							Remove((struct Node *)(((ULONG)Labels[PhonebookDefaultGroup]) - offsetof(PhoneGroupNode,LocalName)));

							DeletePhoneGroupNode((PhoneGroupNode *)(((ULONG)Labels[PhonebookDefaultGroup]) - offsetof(PhoneGroupNode,LocalName)));

							CurrentList = PhoneList;
							ListMax = NumPhoneEntries;
							Selected = ~0;
							SelectedNode = NULL;
							PhonebookDefaultGroup = 0;

								// Now update the labels

							if(OtherLabels = BuildLabels())
							{
								LT_SetAttributes(Manager,GAD_GROUPID,
									GTCY_Labels,OtherLabels,
								TAG_DONE);

								FreeVecPooled(Labels);

								Labels = OtherLabels;
							}

							if(GroupWindow)
								LT_SetAttributes(Grouping,GAD_GROUP_LIST,GTCY_Labels,Labels,TAG_DONE);

							HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

							PhonebookChanged = TRUE;

							break;

							// Open the sort window

						case GAD_SORT:

							if(Sorting)
								LT_ShowWindow(Sorting,TRUE);
							else
							{
								if(Sorting = CreateSortHandle(PhoneWindow,&Sorter,&ReverseOrder))
									SortWindow = Sorting -> Window;
								else
									DisplayBeep(SortWindow -> WScreen);
							}

							break;

							// Sort the phonelist

						case GAD_SORT_AND_CLOSE:
						case GAD_SORT_IT:

							UpdateEditorData(Editor,SelectedNode,Hide);

							if(ListMax > 1)
							{
								RebuildMenu = PhonebookChanged = TRUE;

								LT_LockWindow(PhoneWindow);
								LT_LockWindow(PasswordWindow);
								LT_LockWindow(EditWindow);
								LT_LockWindow(PatternWindow);
								LT_LockWindow(GroupWindow);
								LT_LockWindow(SortWindow);

								LT_SetAttributes(Manager,GAD_NAMELIST,
									GTLV_Labels,	~0,
								TAG_DONE);

								SortPhoneEntries(PhonebookDefaultGroup ? CurrentList : NULL,Sorter,ReverseOrder);

								if(!PhonebookDefaultGroup)
									UpdatePhoneList(PhoneList);

								Selected = ~0;
								SelectedNode = NULL;

								HighlightEntry(Manager,Editor,CurrentList,NULL,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

								LT_UnlockWindow(PhoneWindow);
								LT_UnlockWindow(PasswordWindow);
								LT_UnlockWindow(EditWindow);
								LT_UnlockWindow(PatternWindow);
								LT_UnlockWindow(GroupWindow);
								LT_UnlockWindow(SortWindow);
							}

							if(MsgGadgetID == GAD_SORT_IT)
								break;

							// Falls through to...

						case GAD_SORT_JUST_CLOSE:

							LT_DeleteHandle(Sorting);
							Sorting = NULL;
							SortWindow = NULL;

							LT_ShowWindow(Manager,TRUE);
							break;

							// Save the phonebook to disk

						case GAD_SAVE:

							UpdateEditorData(Editor,SelectedNode,Hide);

							if(NumPhoneEntries)
							{
								SplitFileName(LastPhone,&DummyChar,DummyBuffer);

								LT_LockWindow(PhoneWindow);
								LT_LockWindow(PasswordWindow);
								LT_LockWindow(EditWindow);
								LT_LockWindow(PatternWindow);
								LT_LockWindow(GroupWindow);
								LT_LockWindow(SortWindow);

								if(FileRequest = GetFile(PhoneWindow,LocaleString(MSG_PHONEPANEL_SAVE_PHONEBOOK_TXT),DummyBuffer,DummyChar,DummyBuffer,"#?.prefs",TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_TXT),TRUE))
								{
									if(!SavePhonebook(DummyBuffer))
										ShowError(PhoneWindow,ERR_SAVE_ERROR,IoErr(),DummyBuffer);
									else
									{
										strcpy(LastPhone,DummyBuffer);
										strcpy(Config->PhonebookFileName,LastPhone);

										PhonebookChanged = FALSE;
									}

									FreeAslRequest(FileRequest);
								}

								LT_UnlockWindow(PhoneWindow);
								LT_UnlockWindow(PasswordWindow);
								LT_UnlockWindow(EditWindow);
								LT_UnlockWindow(PatternWindow);
								LT_UnlockWindow(GroupWindow);
								LT_UnlockWindow(SortWindow);
							}

							break;

							// Copy cofiguration data around

						case GAD_COPY_CONFIG:
						{
							BOOL Changes;

							LT_LockWindow(PhoneWindow);
							LT_LockWindow(PasswordWindow);
							LT_LockWindow(EditWindow);
							LT_LockWindow(PatternWindow);
							LT_LockWindow(GroupWindow);
							LT_LockWindow(SortWindow);

							if(!SelectedNode)
								Changes = CopyPanel(PhoneWindow,NULL,Count > 0);
							else
								Changes = CopyPanel(PhoneWindow,SelectedNode -> Entry -> Config,Count > 0);

							if(Changes)
							{
								HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

								PhonebookChanged = TRUE;
							}

							LT_UnlockWindow(PhoneWindow);
							LT_UnlockWindow(PasswordWindow);
							LT_UnlockWindow(EditWindow);
							LT_UnlockWindow(PatternWindow);
							LT_UnlockWindow(GroupWindow);
							LT_UnlockWindow(SortWindow);

							LT_ShowWindow(Handle,TRUE);

							break;
						}

							// Change or clear the password

						case GAD_PASSWORD:

							if(PasswordWindow)
								LT_ShowWindow(PasswordHandle,TRUE);
							else
							{
								if(PasswordHandle = CreatePasswordHandle(PhoneWindow,PhonePasswordUsed))
									PasswordWindow = PasswordHandle->Window;
							}

							break;

							// Changed the new password

						case GAD_NEW_PASSWORD:
						case GAD_REPEAT_PASSWORD:

							UpdatePasswordWindow(PasswordHandle);
							break;

						case GAD_CLEAR_PASSWORD:

							PhonePasswordUsed = FALSE;
							PhonebookChanged = TRUE;

							// FALLS THROUGH TO...

						case GAD_CANCEL_PASSWORD:

							LT_DeleteHandle(PasswordHandle);
							PasswordHandle = NULL;
							PasswordWindow = NULL;
							break;

						case GAD_USE_NEW_PASSWORD:
						{
							UBYTE NewPassword[30];

							memset(NewPassword,0,sizeof(NewPassword));

							if(GetWindowPassword(Handle,NewPassword))
							{
								PhonebookChanged = TRUE;
								PhonePasswordUsed = TRUE;

								Encrypt(NewPassword,20,PhonePassword,NewPassword,strlen(NewPassword));

								LT_DeleteHandle(PasswordHandle);

								PasswordHandle = NULL;
								PasswordWindow = NULL;
							}

							break;
						}

							// Close the editor window

						case GAD_CLOSE:

							UpdateEditorData(Editor,SelectedNode,Hide);

							LT_DeleteHandle(Editor);

							Editor = NULL;
							EditWindow = NULL;

							LT_ShowWindow(Manager,TRUE);
							break;

							// Move to the first tagged entry

						case GAD_FIRST_ENTRY:

							UpdateEditorData(Editor,SelectedNode,Hide);

							if(SelectedNode)
							{
								if(SelectedNode -> Entry -> Count > 0)
								{
									LONG i;

									for(i = 0 ; i < NumPhoneEntries ; i++)
									{
										if(!Phonebook[i] -> Node -> Entry -> Count)
										{
											Selected = i;
											SelectedNode = Phonebook[Selected] -> Node;

											if(SelectedNode -> Entry -> NodeGroup)
												SelectedNode = SelectedNode -> Entry -> NodeGroup;

											FindGroup(&CurrentList,&Selected,&PhonebookDefaultGroup,PhoneList,&PhoneGroupList,SelectedNode);

											LT_SetAttributes(Manager,GAD_NAMELIST,
												GTLV_Labels,	CurrentList,
												GTLV_Selected,	Selected,
											TAG_DONE);

											HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

											break;
										}
									}
								}
							}

							break;

							// Move to the previous tagged entry

						case GAD_PREVIOUS_ENTRY:

							UpdateEditorData(Editor,SelectedNode,Hide);

							if(SelectedNode)
							{
								if(SelectedNode -> Entry -> Count > 0)
								{
									LONG i,Index = SelectedNode -> Entry -> Count - 1;

									for(i = 0 ; i < NumPhoneEntries ; i++)
									{
										if(Phonebook[i] -> Node -> Entry -> Count == Index)
										{
											Selected = i;
											SelectedNode = Phonebook[Selected] -> Node;

											if(SelectedNode -> Entry -> NodeGroup)
												SelectedNode = SelectedNode -> Entry -> NodeGroup;

											FindGroup(&CurrentList,&Selected,&PhonebookDefaultGroup,PhoneList,&PhoneGroupList,SelectedNode);

											LT_SetAttributes(Manager,GAD_NAMELIST,
												GTLV_Labels,	CurrentList,
												GTLV_Selected,	Selected,
											TAG_DONE);

											HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

											break;
										}
									}
								}
							}

							break;

							// Move to the next tagged entry

						case GAD_NEXT_ENTRY:

							UpdateEditorData(Editor,SelectedNode,Hide);

							if(SelectedNode)
							{
								if(SelectedNode -> Entry -> Count < Count - 1)
								{
									LONG i,Index = SelectedNode -> Entry -> Count + 1;

									for(i = 0 ; i < NumPhoneEntries ; i++)
									{
										if(Phonebook[i] -> Node -> Entry -> Count == Index)
										{
											Selected = i;
											SelectedNode = Phonebook[Selected] -> Node;

											if(SelectedNode -> Entry -> NodeGroup)
												SelectedNode = SelectedNode -> Entry -> NodeGroup;

											FindGroup(&CurrentList,&Selected,&PhonebookDefaultGroup,PhoneList,&PhoneGroupList,SelectedNode);

											LT_SetAttributes(Manager,GAD_NAMELIST,
												GTLV_Labels,	CurrentList,
												GTLV_Selected,	Selected,
											TAG_DONE);

											HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

											break;
										}
									}
								}
							}

							break;

							// Move to the next tagged entry

						case GAD_LAST_ENTRY:

							UpdateEditorData(Editor,SelectedNode,Hide);

							if(SelectedNode)
							{
								if(SelectedNode -> Entry -> Count < Count - 1)
								{
									LONG i;

									for(i = 0 ; i < NumPhoneEntries ; i++)
									{
										if(Phonebook[i] -> Node -> Entry -> Count == Count - 1)
										{
											Selected = i;
											SelectedNode = Phonebook[Selected] -> Node;

											if(SelectedNode -> Entry -> NodeGroup)
												SelectedNode = SelectedNode -> Entry -> NodeGroup;

											FindGroup(&CurrentList,&Selected,&PhonebookDefaultGroup,PhoneList,&PhoneGroupList,SelectedNode);

											LT_SetAttributes(Manager,GAD_NAMELIST,
												GTLV_Labels,	CurrentList,
												GTLV_Selected,	Selected,
											TAG_DONE);

											HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

											break;
										}
									}
								}
							}

							break;

							// Move entry to beginning of list

						case GAD_MOVE_FIRST:

							if(Selected != ~0 && Selected > 0)
							{
								LT_SetAttributes(Manager,GAD_NAMELIST,
									GTLV_Labels,~0,
								TAG_DONE);

								if(PhonebookDefaultGroup)
								{
									Remove((struct Node *)SelectedNode);
									AddHead(CurrentList,(struct Node *)SelectedNode);

									Selected = 0;
								}
								else
								{
									struct PhoneEntry	*This;
									LONG				 i;

									This = Phonebook[Selected];

									for(i = Selected ; i > 0 ; i--)
										Phonebook[i] = Phonebook[i - 1];

									Phonebook[0] = This;

									UpdatePhoneList(PhoneList);

									Selected = 0;
									SelectedNode = Phonebook[Selected] -> Node;
								}

								HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

								LT_SetAttributes(Manager,GAD_NAMELIST,
									GTLV_Labels,		CurrentList,
									GTLV_Selected,		Selected,
								TAG_DONE);
							}

							break;

							// Move entry up in the list

						case GAD_MOVE_UP:

							if(Selected != ~0 && Selected > 0)
							{
								LT_SetAttributes(Manager,GAD_NAMELIST,
									GTLV_Labels,~0,
								TAG_DONE);

								if(PhonebookDefaultGroup)
								{
									struct Node *Other;

									Other = SelectedNode -> VanillaNode . ln_Pred -> ln_Pred;

									Remove((struct Node *)SelectedNode);
									Insert(CurrentList,(struct Node *)SelectedNode,Other);

									Selected--;
								}
								else
								{
									struct PhoneEntry *This;

									This					= Phonebook[Selected];
									Phonebook[Selected]		= Phonebook[Selected - 1];
									Phonebook[Selected - 1]	= This;

									UpdatePhoneList(PhoneList);

									Selected--;
									SelectedNode = Phonebook[Selected] -> Node;
								}

								HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

								LT_SetAttributes(Manager,GAD_NAMELIST,
									GTLV_Labels,		CurrentList,
									GTLV_Selected,		Selected,
								TAG_DONE);
							}

							break;

							// Move entry down in the list

						case GAD_MOVE_DOWN:

							if(Selected != ~0 && Selected < ListMax - 1)
							{
								LT_SetAttributes(Manager,GAD_NAMELIST,
									GTLV_Labels,~0,
								TAG_DONE);

								if(PhonebookDefaultGroup)
								{
									struct Node *Other;

									Other = SelectedNode -> VanillaNode . ln_Succ;

									Remove((struct Node *)SelectedNode);
									Insert(CurrentList,(struct Node *)SelectedNode,Other);

									Selected++;
								}
								else
								{
									struct PhoneEntry *This;

									This					= Phonebook[Selected];
									Phonebook[Selected]		= Phonebook[Selected + 1];
									Phonebook[Selected + 1]	= This;

									UpdatePhoneList(PhoneList);

									Selected++;
									SelectedNode = Phonebook[Selected] -> Node;
								}

								HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

								LT_SetAttributes(Manager,GAD_NAMELIST,
									GTLV_Labels,		CurrentList,
									GTLV_Selected,		Selected,
								TAG_DONE);
							}

							break;

							// Move entry to end of list

						case GAD_MOVE_LAST:

							if(Selected != ~0 && Selected < ListMax - 1)
							{
								LT_SetAttributes(Manager,GAD_NAMELIST,
									GTLV_Labels,~0,
								TAG_DONE);

								if(PhonebookDefaultGroup)
								{
									Remove((struct Node *)SelectedNode);
									AddTail(CurrentList,(struct Node *)SelectedNode);

									Selected = ListMax - 1;
								}
								else
								{
									struct PhoneEntry	*This;
									LONG				 i;

									This = Phonebook[Selected];

									for(i = Selected ; i < NumPhoneEntries - 1 ; i++)
										Phonebook[i] = Phonebook[i + 1];

									Phonebook[NumPhoneEntries - 1] = This;

									UpdatePhoneList(PhoneList);

									Selected = ListMax - 1;
									SelectedNode = Phonebook[Selected] -> Node;
								}

								HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);

								LT_SetAttributes(Manager,GAD_NAMELIST,
									GTLV_Labels,		CurrentList,
									GTLV_Selected,		Selected,
								TAG_DONE);
							}

							break;

							// Fiddle with the editor checkboxes

						case GAD_SERIAL_STATE:
						case GAD_MODEM_STATE:
						case GAD_SCREEN_STATE:
						case GAD_TERMINAL_STATE:
						case GAD_EMULATION_STATE:
						case GAD_CLIPBOARD_STATE:
						case GAD_CAPTURE_STATE:
						case GAD_COMMAND_STATE:
						case GAD_MISC_STATE:
						case GAD_PATH_STATE:
						case GAD_TRANSFER_STATE:
						case GAD_TRANSLATION_STATE:
						case GAD_MACRO_STATE:
						case GAD_CURSOR_STATE:
						case GAD_FASTMACRO_STATE:
						case GAD_RATE_STATE:

							if(Selected != ~0)
							{
								if(ChangeState(MsgGadgetID,MsgCode,SelectedNode))
								{
									HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

									PhonebookChanged = TRUE;
								}
							}

							break;

							// Edit the settings of the current entry

						case GAD_SERIAL_EDIT:
						case GAD_MODEM_EDIT:
						case GAD_SCREEN_EDIT:
						case GAD_TERMINAL_EDIT:
						case GAD_EMULATION_EDIT:
						case GAD_CLIPBOARD_EDIT:
						case GAD_CAPTURE_EDIT:
						case GAD_COMMAND_EDIT:
						case GAD_MISC_EDIT:
						case GAD_PATH_EDIT:
						case GAD_TRANSFER_EDIT:
						case GAD_TRANSLATION_EDIT:
						case GAD_MACRO_EDIT:
						case GAD_CURSOR_EDIT:
						case GAD_FASTMACRO_EDIT:
						case GAD_RATE_EDIT:

							if(Selected != ~0)
							{
								BOOL Result = FALSE;

								LT_LockWindow(PhoneWindow);
								LT_LockWindow(PasswordWindow);
								LT_LockWindow(EditWindow);
								LT_LockWindow(PatternWindow);
								LT_LockWindow(GroupWindow);
								LT_LockWindow(SortWindow);

								if(MsgGadgetID == GAD_RATE_EDIT)
								{
									if(SelectedNode -> Entry == ChosenEntry)
										ShowRequest(PhoneWindow,LocaleString(MSG_PHONEPANEL_PHONE_ENTRY_IN_USE_EDIT_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),DummyBuffer);
									else
									{
										BOOL HadToFill = FALSE;

										if(!SelectedNode -> Entry -> TimeDateList . mlh_Head -> mln_Succ)
										{
											struct TimeDateNode *TimeDateNode;

												// Provide defaults

											if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
											{
												AddTail((struct List *)&SelectedNode -> Entry -> TimeDateList,&TimeDateNode -> VanillaNode);

												HadToFill = TRUE;

												SelectedNode -> Entry -> Header -> NoRates = FALSE;
											}
											else
												SelectedNode -> Entry -> Header -> NoRates = TRUE;	// Sorry, guv'nor
										}

										if(SelectedNode -> Entry -> TimeDateList . mlh_Head -> mln_Succ)
											Result = RatePanel(EditWindow,PhoneList,SelectedNode -> Entry,NULL);
										else
											Result = FALSE;

										if(!Result && HadToFill)
										{
												// Discard the time/date list

											FreeTimeDateList((struct List *)&SelectedNode -> Entry -> TimeDateList);

												// No rates here

											SelectedNode -> Entry -> Header -> NoRates = TRUE;
										}
									}
								}
								else
									Result = EditConfig(SelectedNode -> Entry -> Config,MsgGadgetID,MsgQualifier,EditWindow);

								if(Result)
								{
									HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,FALSE);

									PhonebookChanged = TRUE;
								}

								LT_UnlockWindow(PhoneWindow);
								LT_UnlockWindow(PasswordWindow);
								LT_UnlockWindow(EditWindow);
								LT_UnlockWindow(PatternWindow);
								LT_UnlockWindow(GroupWindow);
								LT_UnlockWindow(SortWindow);

								LT_ShowWindow(Editor,TRUE);
							}

							break;

							// Open the pattern selection window

						case GAD_PATTERN:

							if(PatternWindow)
							{
								LT_ShowWindow(Selector,TRUE);
								LT_Activate(Selector,GAD_SELECT_NAME);
							}
							else
							{
								if(Selector = CreateSelectorHandle(PhoneWindow,NamePattern,NumberPattern,CommentPattern,&Mode))
									PatternWindow = Selector -> Window;
								else
									DisplayBeep(PhoneWindow -> WScreen);
							}

							break;

							// Apply the selection pattern to the phonebook

						case GAD_SELECT_APPLY:
						case GAD_SELECT_APPLY_AND_CLOSE:

							UpdateEditorData(Editor,SelectedNode,Hide);

							ParsePatternNoCase(NamePattern,		ParsedNamePattern,		130);
							ParsePatternNoCase(NumberPattern,	ParsedNumberPattern,	130);
							ParsePatternNoCase(CommentPattern,	ParsedCommentPattern,	130);

							LT_SetAttributes(Handle,GAD_NAMELIST,
								GTLV_Labels,	~0,
							TAG_DONE);

							if(Mode)
							{
								for(TempNode = (struct PhoneNode *)CurrentList -> lh_Head ; TempNode -> VanillaNode . ln_Succ ; TempNode = (struct PhoneNode *)TempNode -> VanillaNode . ln_Succ)
								{
									if(TempNode -> Entry -> Count == -1)
									{
										BOOL Result;

										Result = MatchPatternNoCase(ParsedNamePattern,TempNode -> Entry -> Header -> Name) & MatchPatternNoCase(ParsedNumberPattern,TempNode -> Entry -> Header -> Number) & MatchPatternNoCase(ParsedCommentPattern,TempNode -> Entry -> Header -> Comment);

										if(Result)
										{
											TempNode -> Entry -> Count = Count++;

											SPrintf(TempNode -> LocalName,"%3ld - %s",Count,TempNode -> Entry -> Header -> Name);

											if(TempNode -> Entry -> NodeGroup)
												strcpy(TempNode -> Entry -> NodeGroup -> LocalName,TempNode -> LocalName);
										}
									}
								}
							}
							else
							{
								for(TempNode = (struct PhoneNode *)CurrentList -> lh_Head ; TempNode -> VanillaNode . ln_Succ ; TempNode = (struct PhoneNode *)TempNode -> VanillaNode . ln_Succ)
								{
									if(TempNode -> Entry -> Count != -1)
									{
										BOOL Result;

										Result = MatchPatternNoCase(ParsedNamePattern,TempNode -> Entry -> Header -> Name) & MatchPatternNoCase(ParsedNumberPattern,TempNode -> Entry -> Header -> Number) & MatchPatternNoCase(ParsedCommentPattern,TempNode -> Entry -> Header -> Comment);

										if(Result)
										{
											RemoveDialEntry(TempNode);

											Count--;
										}
									}
								}
							}

							HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);
							UpdateWindowTitle(PhoneWindow,WindowTitle,Count);

							if(Count > 0)
							{
								LT_SetAttributes(Manager,GAD_MAKE_GROUP,
									GA_Disabled,FALSE,
								TAG_DONE);
							}

							if(MsgGadgetID == GAD_SELECT_APPLY)
								break;

							// Close the pattern window

						case GAD_SELECT_CLOSE:

							LT_DeleteHandle(Selector);
							Selector = NULL;
							PatternWindow = NULL;

							LT_ShowWindow(Manager,TRUE);
							break;

							// Dial the selected list

						case GAD_DIAL:

							UpdateEditorData(Editor,SelectedNode,Hide);

							if(!Count && Selected != ~0)
							{
								LT_SetAttributes(Handle,GAD_NAMELIST,
									GTLV_Labels,	~0,
								TAG_DONE);

								SPrintf(SelectedNode -> LocalName,"      %s",SelectedNode -> Entry -> Header -> Name);

								if(SelectedNode -> Entry -> NodeGroup)
									strcpy(SelectedNode -> Entry -> NodeGroup -> LocalName,SelectedNode -> Entry -> Header -> Name);

								SelectedNode -> Entry -> Count = Count++;

								LT_SetAttributes(Handle,GAD_NAMELIST,
									GTLV_Labels,	CurrentList,
								TAG_DONE);

								UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
							}

								/* If the modem is still online, provide help. */

							if(Count > 0 && AskDial(PhoneWindow))
							{
								DialTheList	= TRUE;
								Done		= TRUE;
							}

							break;

							// Hit the autodial button

						case GAD_MAIN_AUTODIAL:

							LT_SetAttributes(Manager,GAD_MAIN_EXIT_WHEN_FINISHED,
								GA_Disabled,	!PhonebookAutoDial,
							TAG_DONE);

							break;
					}
				}

					// Does the displayed list need clearing?

				if(ClearList)
				{
					ClearList = FALSE;

					LT_SetAttributes(Handle,GAD_NAMELIST,
						GTLV_Labels,	NULL,
						GTLV_Selected,	~0,
					TAG_DONE);

					DeletePhoneGroupList(&PhoneGroupList);

					if(OtherLabels = BuildLabels())
					{
						LT_SetAttributes(Manager,GAD_GROUPID,
							GTCY_Labels,OtherLabels,
						TAG_DONE);

						FreeVecPooled(Labels);

						Labels = OtherLabels;
					}
					else
						Labels[1] = NULL;

					PhonebookDefaultGroup = 0;

					if(GroupWindow)
					{
						LT_SetAttributes(Grouping,GAD_GROUP_LIST,
							GTCY_Labels,	Labels,
							GTCY_Active,	PhonebookDefaultGroup,
						TAG_DONE);
					}

					LT_SetAttributes(Manager,GAD_GROUPID,
						GTCY_Labels,	Labels,
						GTCY_Active,	PhonebookDefaultGroup,
					TAG_DONE);

					Selected = ~0;
					SelectedNode = NULL;

					if(PhoneList)
					{
						DeletePhoneList(PhoneList);

						PhoneList = NULL;
					}

					CurrentList = NULL;

					Count = 0;
					ListMax = 0;

					HighlightEntry(Manager,Editor,CurrentList,NULL,Count,PhonebookDefaultGroup,FALSE,Hide,TRUE);
					UpdateWindowTitle(PhoneWindow,WindowTitle,Count);

					LT_DeleteHandle(Grouping);

					Grouping = NULL;
					GroupWindow = NULL;
				}

					// Double-clicked on an entry?

				if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadgetID == GAD_NAMELIST)
				{
					if(!(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) && !Online && Phonebook[MsgCode] -> Header -> Number[0])
					{
						UpdateEditorData(Editor,SelectedNode,Hide);

						Selected = MsgCode;

						if(PhonebookDefaultGroup)
							SelectedNode = (struct PhoneNode *)GetListNode(Selected,CurrentList);
						else
							SelectedNode = Phonebook[Selected] -> Node;

						LT_SetAttributes(Handle,GAD_NAMELIST,
							GTLV_Labels,	~0,
						TAG_DONE);

						Count = 1;

						for(TempNode = (struct PhoneNode *)CurrentList -> lh_Head ; TempNode -> VanillaNode . ln_Succ ; TempNode = (struct PhoneNode *)TempNode -> VanillaNode . ln_Succ)
						{
							if(TempNode != SelectedNode)
							{
								SPrintf(TempNode -> LocalName,"      %s",TempNode -> Entry -> Header -> Name);

								TempNode -> Entry -> Count = -1;
							}
							else
							{
								SPrintf(TempNode -> LocalName,"  1 - %s",TempNode -> Entry -> Header -> Name);

								TempNode -> Entry -> Count = 0;
							}

							if(TempNode -> Entry -> NodeGroup)
								strcpy(TempNode -> Entry -> NodeGroup -> LocalName,TempNode -> LocalName);
						}

						DialTheList	= TRUE;
						Done		= TRUE;

						LT_PressButton(Handle,GAD_DIAL);
						UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
					}
				}
			}
		}
		while(!Done);

		PopWindow();
	}

	LT_DeleteHandle(PasswordHandle);
	LT_DeleteHandle(Grouping);
	LT_DeleteHandle(Selector);
	LT_DeleteHandle(Manager);
	LT_DeleteHandle(Editor);
	LT_DeleteHandle(Sorting);

	if(PhonebookChanged)
		RebuildMenu = TRUE;

	FreeDialList(TRUE);

	if(PhoneList)
	{
		if(Count > 0)
		{
			for(TempNode = (struct PhoneNode *)CurrentList -> lh_Head ; TempNode -> VanillaNode . ln_Succ ; TempNode = (struct PhoneNode *)TempNode -> VanillaNode . ln_Succ)
			{
				if(TempNode -> Entry -> Count != -1 && TempNode -> Entry -> Header -> Number[0])
					SortToList(TempNode,NULL);
			}

			if(!DialList)
				DialTheList = FALSE;
		}

		DeletePhoneList(PhoneList);
	}

	if(RebuildMenu)
		DisconnectDialMenu();

	FreeVecPooled(Labels);
	DeleteMsgPort(UserPort);

	return(DialTheList);
}
