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

#include "termGlobal.h"

	// 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 __regargs
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,
		GTTX_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,
				GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> SerialConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> ModemConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> ScreenConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> TerminalConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> EmulationConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> ClipConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> CaptureConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> CommandConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> MiscConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> PathConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> TransferConfig),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> TranslationFileName),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> MacroFileName),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> CursorFileName),
		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,
			GA_Disabled,	Disabled || (LocalConfig && !LocalConfig -> FastMacroFileName),
		TAG_DONE);

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

		LT_SetAttributes(Editor,GAD_RATE_EDIT,
			GA_Disabled,	Disabled || !RatesValid,
		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 __regargs
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);
}

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

	STATIC WORD		Sorter;
	STATIC BOOL		ReverseOrder;

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

	UBYTE				 WindowTitle[80];

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

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

		// 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;
		BOOLEAN					 Done = FALSE;
		ULONG					 MsgClass,
								 MsgQualifier,
								 CompleteQualifier;
		UWORD					 MsgCode;
		UWORD					 KeyCode;
		struct Gadget			*MsgGadget;
		struct Window			*MsgWindow;

		BYTE					 ClickAction;

		UBYTE					 DummyBuffer[MAX_FILENAME_LENGTH],
								*DummyChar;

		LONG					 Selected = ~0,
								 MsgGadgetID;

		struct PhoneNode		*SelectedNode = NULL;

		struct FileRequester	*FileRequest;
		WORD					 Vanilla;

		struct Window			*PhoneWindow	= Manager -> Window;
		struct Window			*EditWindow		= NULL;
		struct Window			*PatternWindow	= NULL;
		struct Window			*GroupWindow	= NULL;
		struct Window			*SortWindow		= 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;

					// 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,
								GTLV_Selected,		Selected,
							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 == 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)
								{
									TempNode -> Entry -> Count = LocalCount++;

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

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

							Count = LocalCount;

							UpdateWindowTitle(PhoneWindow,WindowTitle,Count);

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

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

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

							break;

							// Tag the current entry

						case GAD_SELECT:

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

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

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

							UpdateWindowTitle(PhoneWindow,WindowTitle,Count);

							break;

							// Untag the current entry

						case GAD_CLEAR:

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

							RemoveDialEntry(SelectedNode);

							Count--;

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

							UpdateWindowTitle(PhoneWindow,WindowTitle,Count);

							break;

							// Picked a list entry

						case GAD_NAMELIST:

							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,
									GTLV_Selected,		Selected,
								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(EditWindow);
							LT_LockWindow(PatternWindow);
							LT_LockWindow(GroupWindow);
							LT_LockWindow(SortWindow);

							PrintPanel(PhoneWindow,CurrentList,Count);

							LT_UnlockWindow(PhoneWindow);
							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:

							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:

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

							if(PhoneList)
							{
								DeletePhoneList(PhoneList);

								PhoneList = NULL;
							}

								// Create the new entry

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

								if(PhoneList = CreatePhoneList())
								{
										// New entries always end up at the end of the list

									SelectedNode = (struct PhoneNode *)PhoneList -> lh_TailPred;

										// 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,
									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;
									}
									else
										HighlightEntry(Manager,Editor,CurrentList,SelectedNode,Count,PhonebookDefaultGroup,TRUE,Hide,TRUE);

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

							break;

							// Edit the current entry

						case GAD_EDIT:

							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:

							Hide = MsgCode;

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

							break;

							// Make a copy of the current entry

						case GAD_COPY:

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

								if(PhoneList)
								{
									DeletePhoneList(PhoneList);

									PhoneList = NULL;
								}

								if(NewPhoneEntry())
								{
									struct PhoneEntry *SelectedEntry = SelectedNode -> Entry;

									if(PhoneList = CreatePhoneList())
									{
										struct PhoneNode *Tmp = SelectedEntry -> Node;
										LONG i;
										ULONG ID;

										SelectedNode = (struct PhoneNode *)PhoneList -> lh_TailPred;

										if(PhonebookDefaultGroup)
										{
											PhoneGroupNode *Group;

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

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

												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 = PhoneList;
												ListMax = NumPhoneEntries;
											}
										}
										else
										{
											CurrentList = PhoneList;
											ListMax++;
											Selected = ListMax - 1;
										}

										ID = SelectedNode -> Entry -> Header -> ID;

										CopyMem(Tmp -> Entry -> Header,SelectedNode -> Entry -> Header,sizeof(struct PhoneHeader));

										SelectedNode -> Entry -> Header -> QuickMenu	= FALSE;
										SelectedNode -> Entry -> Header -> ID			= ID;

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

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

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

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

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

											/* Allocate space for the config data. */

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

											/* Copy the data. */

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

										RebuildMenu = PhonebookChanged = TRUE;

										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);
									}
									else
										goto ClearList;
								}
								else
									goto ClearList;
							}

							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)
									MyEasyRequest(PhoneWindow,LocaleString(MSG_PHONEPANEL_PHONE_ENTRY_IN_USE_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
								else
								{
									struct PhoneNode	*Next;
									struct PhoneEntry	*Entry;

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

										// Disconnect the list

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

										// Get rid of it

									if(PhoneList)
									{
										DeletePhoneList(PhoneList);

										PhoneList = NULL;
									}

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

										// 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
											goto ClearList;
									}
									else
									{
ClearList:								LT_SetAttributes(Handle,GAD_NAMELIST,
											GTLV_Labels,	NULL,
											GTLV_Selected,	~0,
										TAG_DONE);

										Selected = ~0;
										SelectedNode = NULL;

										Count = 0;
										ListMax = 0;

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

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

										PhonebookChanged = FALSE;

										RebuildMenu = TRUE;
									}

									if(!(PhoneList = CreatePhoneList()))
									{
										LT_SetAttributes(Handle,GAD_NAMELIST,
											GTLV_Labels,	NULL,
											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())
									{
										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,
											GA_Disabled,	FALSE,
										TAG_DONE);

										FreeDialList(TRUE);
									}

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

									UpdateWindowTitle(PhoneWindow,WindowTitle,Count);
								}
							}

							LT_UnlockWindow(PhoneWindow);
							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:

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

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

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

								memcpy(BookHandle . PhonePassword,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))
										{
											strcpy(LastPhone,DummyBuffer);

											PhonebookChanged = RebuildMenu = TRUE;
										}
										else
											DeletePhonebook(BookHandle . Phonebook,BookHandle . PhoneSize,TRUE);
									}

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

										FreeDialList(TRUE);
									}
									else
									{
										LT_SetAttributes(Handle,GAD_NAMELIST,
											GTLV_Labels,	NULL,
											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())
									{
										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(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(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;
									}
								}

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

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

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

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

									if(RenameGroup && !NotGrouped && WhichGroup)
									{
										LONG Tagged = 0;

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

											// Did all the group members get tagged?

										if(Tagged != Count)
											RenameGroup = FALSE;
									}
									else
										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;

										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(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())
							{
								FreeVecPooled(Labels);

								Labels = OtherLabels;
							}

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

							LT_SetAttributes(Manager,GAD_GROUPID,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:

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

								LT_LockWindow(PhoneWindow);
								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(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:

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

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

										PhonebookChanged = FALSE;
									}

									FreeAslRequest(FileRequest);
								}

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

							break;

							// Copy cofiguration data around

						case GAD_COPY_CONFIG:
						{
							BOOLEAN Changes;

							LT_LockWindow(PhoneWindow);
							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(EditWindow);
							LT_UnlockWindow(PatternWindow);
							LT_UnlockWindow(GroupWindow);
							LT_UnlockWindow(SortWindow);

							LT_ShowWindow(Handle,TRUE);

							break;
						}

							// Change or clear the password

						case GAD_PASSWORD:
						{
							UBYTE SomeBuffer[30];

							memset(SomeBuffer,0,21);

							PhonePasswordUsed = FALSE;

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

							if(GetString(FALSE,TRUE,21,LocaleString(MSG_PHONEPANEL_PLEASE_ENTER_PASSWORD_TXT),SomeBuffer))
							{
								SomeBuffer[20] = 0;

								PhonebookChanged = TRUE;

								if(SomeBuffer[0])
								{
									UBYTE OtherBuffer[30];

									memset(OtherBuffer,0,21);

									if(GetString(FALSE,TRUE,21,LocaleString(MSG_PHONEPANEL_PLEASE_REPEAT_PASSWORD_TXT),OtherBuffer))
									{
										OtherBuffer[20] = 0;

										if(!memcmp(OtherBuffer,SomeBuffer,20))
										{
											Encrypt(OtherBuffer,20,PhonePassword,OtherBuffer,strlen(OtherBuffer));

											PhonePasswordUsed = TRUE;
										}
										else
											MyEasyRequest(PhoneWindow,LocaleString(MSG_PHONEPANEL_ERROR_ENTERING_PASSWORD_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
									}
									else
										MyEasyRequest(PhoneWindow,LocaleString(MSG_PHONEPANEL_ERROR_ENTERING_PASSWORD_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
								}
							}

							LT_ShowWindow(Handle,TRUE);

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

							break;
						}

							// Close the editor window

						case GAD_CLOSE:

							LT_DeleteHandle(Editor);

							Editor = NULL;
							EditWindow = NULL;

							LT_ShowWindow(Manager,TRUE);
							break;

							// Move to the first tagged entry

						case GAD_FIRST_ENTRY:

							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:

							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:

							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:

							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)
							{
								BOOLEAN Result = FALSE;

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

								if(MsgGadgetID == GAD_RATE_EDIT)
								{
									if(SelectedNode -> Entry == ChosenEntry)
										MyEasyRequest(PhoneWindow,LocaleString(MSG_PHONEPANEL_PHONE_ENTRY_IN_USE_EDIT_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),DummyBuffer);
									else
										Result = RatePanel(PhoneWindow,PhoneList,SelectedNode -> Entry,NULL);
								}
								else
									Result = EditConfig(SelectedNode -> Entry -> Config,MsgGadgetID,MsgQualifier,PhoneWindow);

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

									PhonebookChanged = TRUE;
								}

								LT_UnlockWindow(PhoneWindow);
								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:

							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:

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

					// Double-clicked on an entry?

				if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadgetID == GAD_NAMELIST)
				{
					if(!(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) && !Online && Phonebook[MsgCode] -> Header -> Number[0])
					{
						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(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);
}
