/*
**	$Id: termPacket.c,v 1.4 92/08/18 16:12:47 olsen Sta Locker: olsen $
**	$Revision: 1.4 $
**	$Date: 92/08/18 16:12:47 $
**
**	Support routines for the `packet window'
**
**	Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
**		All Rights Reserved
*/

#include "termGlobal.h"

	/* A custom message structure. */

struct PacketMessage
{
	struct Message	 VanillaMessage;
	LONG		 Line;
};

	/* Some private data required to handle both the window,
	 * the editing functions and the command history buffer.
	 */

STATIC struct Hook		 PacketHook;
STATIC UBYTE			 PacketWorkBuffer[256];
STATIC struct StringInfo	*PacketInfo;

STATIC struct MsgPort		*PacketPort;

STATIC LONG			 PacketLine;
STATIC LONG			 PacketCount;
STATIC STRPTR			 PacketString = NULL;
STATIC LONG			 PacketX = -1,PacketY = -1,PacketWidth = -1,PacketHeight = -1;

STATIC BYTE			 HasList = FALSE;

	/* Gadget IDs */

enum	{	GAD_STRING, GAD_LIST };

	/* The menu to attach to the packet window. */

enum	{	MEN_LOADHISTORY=1,MEN_SAVEHISTORY,MEN_CLEARHISTORY,MEN_OTHERWINDOW,MEN_QUITPANEL };

STATIC struct NewMenu NewPacketMenu[] =
{
	{ NM_TITLE, NULL,		 0 , 0, 0, (APTR)0},
	{  NM_ITEM, NULL,		 0 , 0, 0, (APTR)MEN_LOADHISTORY},
	{  NM_ITEM, NULL,		 0 , 0, 0, (APTR)MEN_SAVEHISTORY},
	{  NM_ITEM, NM_BARLABEL,	 0 , 0, 0, (APTR)0},
	{  NM_ITEM, NULL,		 0 , 0, 0, (APTR)MEN_CLEARHISTORY},
	{  NM_ITEM, NM_BARLABEL,	 0 , 0, 0, (APTR)0},
	{  NM_ITEM, NULL,		 0 , 0, 0, (APTR)MEN_OTHERWINDOW},
	{  NM_ITEM, NM_BARLABEL,	 0 , 0, 0, (APTR)0},
	{  NM_ITEM, NULL,		 0 , 0, 0, (APTR)MEN_QUITPANEL},
	{ NM_END, 0,			 0 , 0, 0, (APTR)0}
};

	/* SendPacketMsg(LONG Line):
	 *
	 *	Tell the main process to display a certain line.
	 */

STATIC VOID __regargs
SendPacketMsg(LONG Line)
{
	struct PacketMessage *Msg;

	if(Msg = (struct PacketMessage *)AllocVec(sizeof(struct PacketMessage),MEMF_PUBLIC|MEMF_CLEAR))
	{
		Msg -> VanillaMessage . mn_Length	= sizeof(struct PacketMessage);
		Msg -> Line				= Line;

		PutMsg(PacketPort,Msg);
	}
}

	/* ClearPacketHistory():
	 *
	 *	Release the command history.
	 */

VOID
ClearPacketHistory()
{
	struct Node *SomeNode,*NextNode;

	if(HasList)
	{
		GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
			GTLV_Labels,	~0,
		TAG_DONE);
	}

	SomeNode = PacketHistoryList . lh_Head;

	while(SomeNode -> ln_Succ)
	{
		NextNode = SomeNode -> ln_Succ;

		Remove(SomeNode);

		FreeVec(SomeNode);

		SomeNode = NextNode;
	}

	PacketCount = PacketLine = 0;

	if(HasList)
	{
		GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
			GTLV_Labels,	&PacketHistoryList,
		TAG_DONE);
	}

	PacketString = NULL;
}

	/* DeletePacketWindow():
	 *
	 *	Delete the packet window and release the command
	 *	history.
	 */

VOID
DeletePacketWindow(BYTE WindowOnly)
{
	struct MenuItem	*Item;

	if(Item = FindThisItem(MEN_PACKET_WINDOW))
		Item -> Flags &= ~CHECKED;

	if(PacketWindow)
	{
		PacketWindow -> Flags |= WFLG_RMBTRAP;

		ClearMenuStrip(PacketWindow);

		if(PacketGadgetList)
			RemoveGList(PacketWindow,PacketGadgetList,(UWORD)-1);

		PacketX		= PacketWindow -> LeftEdge;
		PacketY		= PacketWindow -> TopEdge;

		PacketWidth	= PacketWindow -> Width;
		PacketHeight	= PacketWindow -> Height;

		CloseWindow(PacketWindow);

		PacketWindow = NULL;
	}

	if(PacketGadgetList)
	{
		FreeGadgets(PacketGadgetList);

		PacketGadgetList = NULL;
	}

	if(PacketMenu)
	{
		FreeMenus(PacketMenu);

		PacketMenu = NULL;
	}

	if(PacketPort)
	{
		struct Message *Message;
	
		while(Message = GetMsg(PacketPort))
			FreeVec(Message);

		FreeVec(PacketPort);

		PacketPort = NULL;
	}

	if(!WindowOnly)
	{
		HasList = FALSE;

		ClearPacketHistory();
	}
}

	/* AddPacketHistory(UBYTE *Buffer):
	 *
	 *	Add a line to the packet window command history. This
	 *	works very much the same as the AddLine()-routine.
	 */

VOID
AddPacketHistory(UBYTE *Buffer)
{
	struct Node *SomeNode;

	if(HasList)
	{
		GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
			GTLV_Labels,	~0,
		TAG_DONE);
	}

	if(SomeNode = (struct Node *)AllocVec(sizeof(struct Node) + strlen(Buffer) + 1,MEMF_ANY|MEMF_CLEAR))
	{
		SomeNode -> ln_Name = (UBYTE *)(SomeNode + 1);

		strcpy(SomeNode -> ln_Name,Buffer);

		AddTail(&PacketHistoryList,SomeNode);

		PacketCount = ++PacketLine;
	}

	if(HasList)
	{
		GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
			GTLV_Top,	PacketCount - 1,
			GTLV_Labels,	&PacketHistoryList,
		TAG_DONE);
	}
}

	/* CreateAllGadgets():
	 *
	 *	Create the packet string gadget.
	 */

STATIC struct Gadget *
CreateAllGadgets(LONG Width,struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
{
	struct Gadget		*Gadget;
	struct NewGadget	 NewGadget;

	SZ_SizeSetup(Screen,&UserFont,TRUE);

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

	if(Gadget = CreateContext(GadgetList))
	{
		WORD Rest,StringHeight,ProtoHeight;

		StringHeight	= SZ_Height(STRING_KIND,0,0);
		ProtoHeight	= Screen -> WBorTop + Screen -> Font -> ta_YSize + 1 + 2 + StringHeight + 2;
		Rest		= (PacketHeight - 2 - ProtoHeight - 2) / UserFontHeight;

		NewGadget . ng_Width		= Width - 26;
		NewGadget . ng_Height		= StringHeight;
		NewGadget . ng_GadgetText	= NULL;
		NewGadget . ng_TextAttr		= &UserFont;
		NewGadget . ng_VisualInfo	= VisualInfo;
		NewGadget . ng_GadgetID		= GAD_STRING;
		NewGadget . ng_Flags		= 0;
		NewGadget . ng_LeftEdge		= 6;
		NewGadget . ng_TopEdge		= 1 + TopEdge;

		GadgetArray[GAD_STRING] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
			GTST_MaxChars,	256,
			GTST_EditHook,	&PacketHook,
			GA_TabCycle,	FALSE,
		TAG_DONE);

			/* If the window is large enough to display the
			 * list, create the list view gadget.
			 */

		if(Rest > 0)
		{
			NewGadget . ng_Height		= 2 + Rest * UserFontHeight + 2 + StringHeight;
			NewGadget . ng_GadgetID		= GAD_LIST;

			GadgetArray[GAD_LIST] = Gadget = CreateGadget(LISTVIEW_KIND,Gadget,&NewGadget,
				GTLV_ShowSelected,	GadgetArray[GAD_STRING],
				GTLV_Labels,		&PacketHistoryList,
				GTLV_Selected,		PacketCount,
				GTLV_Top,		PacketCount,
			TAG_DONE);

			if(Gadget)
				HasList = TRUE;
			else
				HasList = FALSE;
		}
		else
			HasList = FALSE;
	}

	return(Gadget);
}

	/* CreatePacketWindow():
	 *
	 *	Open the packet window and allocate the command history
	 *	buffer.
	 */

BYTE
CreatePacketWindow()
{
	LocalizeMenu(NewPacketMenu,MSG_PACKET_PROJECT_MEN);

	if(PacketPort = (struct MsgPort *)AllocVec(sizeof(struct MsgPort),MEMF_PUBLIC | MEMF_CLEAR))
	{
		if(PacketMenu = CreateMenus(NewPacketMenu,TAG_DONE))
		{
			if(LayoutMenus(PacketMenu,VisualInfo,
				GTMN_TextAttr,		&UserFont,
				GTMN_NewLookMenus,	TRUE,
			TAG_DONE))
			{
				LONG ProtoHeight;

				SZ_SizeSetup(Screen,&UserFont,TRUE);

				ProtoHeight = Screen -> WBorTop + Screen -> Font -> ta_YSize + 1 + 2 + SZ_Height(STRING_KIND,0,0) + 2;

				if(PacketWidth == -1)
					PacketWidth = Screen -> Width;

				if(PacketHeight < ProtoHeight)
					PacketHeight = ProtoHeight;

				if(PacketX == -1 || (PacketX + PacketWidth > Screen -> Width))
				{
					PacketX = 0;

					if(PacketX + PacketWidth > Screen -> Width)
						PacketWidth = Screen -> Width;
				}

				if(PacketY == -1 || (PacketY + PacketHeight > Screen -> Height))
				{
					PacketY = Window -> TopEdge + Window -> Height;

					if(PacketY + PacketHeight > Screen -> Height)
						PacketHeight = ProtoHeight;
				}

				if(CreateAllGadgets(PacketWidth,&PacketGadgetArray[0],&PacketGadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1))
				{
					if(PacketWindow = OpenWindowTags(NULL,
						WA_Width,		PacketWidth,
						WA_Height,		PacketHeight,

						WA_Left,		PacketX,
						WA_Top,			PacketY,

						WA_Activate,		TRUE,
						WA_DragBar,		TRUE,
						WA_DepthGadget,		TRUE,
						WA_CloseGadget,		TRUE,
						WA_RMBTrap,		TRUE,
						WA_SizeGadget,		TRUE,
						WA_MinWidth,		80,
						WA_MinHeight,		ProtoHeight,
						WA_MaxWidth,		Screen -> Width,
						WA_MaxHeight,		Screen -> Height,
						WA_CustomScreen,	Screen,
						WA_NoCareRefresh,	TRUE,
						WA_NewLookMenus,	TRUE,

						WA_IDCMP,		STRINGIDCMP | LISTVIEWIDCMP | IDCMP_NEWSIZE | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_ACTIVEWINDOW | IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS,

						WA_Title,		LocaleString(MSG_GLOBAL_PACKET_WINDOW_TXT),
					TAG_DONE))
					{
						struct MenuItem	*Item;

						if(Item = FindThisItem(MEN_PACKET_WINDOW))
							Item -> Flags |= CHECKED;

						PacketPort -> mp_Flags		= PA_SIGNAL;
						PacketPort -> mp_SigBit		= PacketWindow -> UserPort -> mp_SigBit;
						PacketPort -> mp_SigTask	= PacketWindow -> UserPort -> mp_SigTask;

						NewList(&PacketPort -> mp_MsgList);

						PacketHook . h_Entry		= (APTR)PacketKey;
						PacketHook . h_SubEntry		= NULL;
						PacketHook . h_Data		= NULL;

						PacketInfo = (struct StringInfo *)PacketGadgetArray[GAD_STRING] -> SpecialInfo;

						AddGList(PacketWindow,PacketGadgetList,(UWORD)-1,(UWORD)-1,NULL);
						RefreshGList(PacketGadgetList,PacketWindow,NULL,(UWORD)-1);
						GT_RefreshWindow(PacketWindow,NULL);

						SetMenuStrip(PacketWindow,PacketMenu);

						PacketWindow -> Flags &= ~WFLG_RMBTRAP;

						ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);

						return(TRUE);
					}
				}
			}
		}
	}

	DeletePacketWindow(FALSE);

	return(FALSE);
}

	/* PacketKey(struct Hook *Hook,struct SGWork *Work,ULONG *Msg):
	 *
	 *	This is a string gadget editing call back routine
	 *	(a so-called `hook') which is to perform all the
	 *	line editing and command history actions supported
	 *	by the packet window.
	 */

VOID __saveds __asm
PacketKey(register __a0 struct Hook *Hook,register __a1 ULONG *Msg,register __a2 struct SGWork *Work)
{
		/* Someone activated the string gadget and
		 * hit a key.
		 */

	if(Msg[0] == SGH_KEY)
	{
		if(Work -> IEvent -> ie_Qualifier & IEQUALIFIER_RCOMMAND)
		{
			if(Work -> Code == 'c')
			{
				Work -> Actions &= ~SGA_USE;
				Work -> Actions |= SGA_BEEP;

				if(Work -> PrevBuffer[0])
				{
					struct MsgPort *ReplyPort;

					if(ReplyPort = CreateMsgPort())
					{
						struct Message ClipMessage;

						ClipMessage . mn_Node . ln_Name	= Work -> PrevBuffer;
						ClipMessage . mn_ReplyPort	= ReplyPort;
						ClipMessage . mn_Length		= sizeof(struct Message);

						PutMsg(ClipPort,&ClipMessage);

						WaitPort(ReplyPort);

						GetMsg(ReplyPort);

						DeleteMsgPort(ReplyPort);

						Work -> Actions &= ~SGA_BEEP;
					}
				}

				return;
			}

			if(Work -> Code == 'v')
			{
				Work -> Actions &= ~SGA_USE;
				Work -> Actions |= SGA_BEEP;

				if(!(Work -> Gadget -> Activation & GACT_LONGINT))
				{
					struct MsgPort *ReplyPort;

					if(ReplyPort = CreateMsgPort())
					{
						STATIC UBYTE	Buffer[2048];
						struct Message	ClipMessage;

						Buffer[0] = 0;

						ClipMessage . mn_Node . ln_Name	= &Buffer[0];
						ClipMessage . mn_ReplyPort	= ReplyPort;
						ClipMessage . mn_Length		= sizeof(struct Message);

						PutMsg(ClipPort,&ClipMessage);

						WaitPort(ReplyPort);

						GetMsg(ReplyPort);

						DeleteMsgPort(ReplyPort);

						if(Buffer[0])
						{
							WORD Len = strlen(Buffer);

							while(Len > 0 && Work -> NumChars + Len > Work -> StringInfo -> MaxChars)
								Len--;

							if(Len > 0)
							{
								STATIC UBYTE OtherBuffer[2048];

								Buffer[Len] = 0;

								if(Work -> StringInfo -> UndoBuffer)
									strcpy(Work -> StringInfo -> UndoBuffer,Work -> PrevBuffer);

								Work -> StringInfo -> UndoPos = --Work -> BufferPos;

								if(Work -> BufferPos)
									CopyMem(Work -> PrevBuffer,OtherBuffer,Work -> BufferPos);

								OtherBuffer[Work -> BufferPos] = 0;

								strcat(OtherBuffer,Buffer);

								strcat(OtherBuffer,&Work -> PrevBuffer[Work -> BufferPos]);

								strcpy(Work -> WorkBuffer,OtherBuffer);

								Work -> BufferPos += Len;
								Work -> NumChars	+= Len;

								Work -> Actions	|= SGA_USE;
								Work -> EditOp	 = EO_BIGCHANGE;

								Work -> Actions &= ~SGA_BEEP;
							}
						}
						else
							Work -> Actions &= ~SGA_BEEP;
					}
				}

				return;
			}
		}

			/* Right-Amiga-key was pressed, release the
			 * string gadget so user may select a menu
			 * item.
			 */

		if((Work -> IEvent -> ie_Qualifier & AMIGARIGHT) && Work -> IEvent -> ie_Code < 96)
		{
			if(!(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) && (Work -> IEvent -> ie_Code == KEYCODE_X || Work -> IEvent -> ie_Code == KEYCODE_Q))
				return;
			else
			{
				Work -> Actions |= (SGA_END|SGA_REUSE);
				Work -> Actions &= ~(SGA_USE|SGA_BEEP);

				CommandWindow = Work -> GadgetInfo -> gi_Window;
				CommandGadget = Work -> Gadget;
			}
		}

			/* The user pressed the cursor-right key to
			 * move the cursor to the next word in the buffer.
			 */

		if(Work -> IEvent -> ie_Code == CURSORRIGHT && (Work -> IEvent -> ie_Qualifier & IEQUALIFIER_CONTROL))
		{
			if(Work -> BufferPos != Work -> NumChars)
			{
				WORD i,Position = -1;

				for(i = Work -> BufferPos ; i < Work -> NumChars ; i++)
				{
					if(Work -> WorkBuffer[i] == ' ')
					{
						for( ; i < Work -> NumChars ; i++)
						{
							if(Work -> WorkBuffer[i] != ' ')
							{
								Position = i;
								break;
							}
						}

						break;
					}
				}

				if(Position != -1)
					Work -> BufferPos = Position;
				else
					Work -> BufferPos = Work -> NumChars;

				Work -> EditOp = EO_MOVECURSOR;
			}
		}

			/* The user pressed the cursor-right key to
			 * move the cursor to the previous word in the buffer.
			 */

		if(Work -> IEvent -> ie_Code == CURSORLEFT && (Work -> IEvent -> ie_Qualifier & IEQUALIFIER_CONTROL))
		{
			if(Work -> BufferPos)
			{
				WORD i,Position = -1;

				for(i = Work -> BufferPos ; i >= 0 ; i--)
				{
					if(Work -> WorkBuffer[i] != ' ')
					{
						Position = i;
						break;
					}
				}

				if(Position == -1)
					Position = 0;

				if(Position)
				{
					i = Position;

					Position = -1;

					for( ; i >= 0 ; i--)
					{
						if(Work -> WorkBuffer[i] == ' ')
						{
							Position = i + 1;
							break;
						}
					}
				}

				if(Position != -1)
					Work -> BufferPos = Position;
				else
					Work -> BufferPos = 0;

				Work -> EditOp = EO_MOVECURSOR;
			}
		}

			/* The user pressed the cursor-up key to
			 * scroll through the command history.
			 */

		if(Work -> IEvent -> ie_Code == CURSORUP)
		{
				/* Shift key: jump to first command
				 * history entry.
				 */

			if(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
			{
				if(PacketLine)
					SendPacketMsg(0);
			}
			else
			{
				if(PacketLine && PacketCount > 0)
					SendPacketMsg(PacketCount - 1);
			}
		}

			/* The user pressed the cursor-down key to
			 * scroll through the command history.
			 */

		if(Work -> IEvent -> ie_Code == CURSORDOWN)
		{
				/* Shift key: jump to last command
				 * history entry.
				 */

			if(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
			{
				if(PacketLine > 0)
					SendPacketMsg(PacketLine);
			}
			else
			{
				if(PacketCount < PacketLine)
					SendPacketMsg(PacketCount + 1);
			}
		}
	}
}

	/* HandlePacket():
	 *
	 *	Process the input coming through the packet window.
	 */

BYTE
HandlePacket()
{
	struct IntuiMessage	*Massage;
	struct PacketMessage	*PacketMsg;
	ULONG			 Class,Code;
	struct Gadget		*Gadget;
	struct FileRequest	*FileRequest;
	UBYTE			 DummyBuffer[256];
	BYTE			 SwapWindow = FALSE;

		/* Are we already shut down? */

	if(PacketWindow)
	{
		BYTE Result = FALSE;

		if(Massage = (struct IntuiMessage *)GT_GetIMsg(PacketWindow -> UserPort))
		{
			Class	= Massage -> Class;
			Code	= Massage -> Code;
			Gadget	= (struct Gadget *)Massage -> IAddress;

			GT_ReplyIMsg(Massage);

				/* Re-enable the string gadget if necessary. */

			if(Class == IDCMP_RAWKEY)
				if(Code == IECODE_UP_PREFIX|103 && CommandWindow == PacketWindow)
					ActivateGadget(CommandGadget,PacketWindow,NULL);

				/* Handle the menu. */

			if(Class == IDCMP_MENUPICK)
			{
				struct MenuItem *MenuItem;

				while(Code != MENUNULL)
				{
					MenuItem = ItemAddress(PacketMenu,Code);

					switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
					{
						case MEN_QUITPANEL:	Class = IDCMP_CLOSEWINDOW;
									break;

						case MEN_LOADHISTORY:	BlockWindows();

									if(FileRequest = GetFile(LocaleString(MSG_PACKET_LOAD_HISTORY_TXT),"","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_LOAD_TXT)))
									{
										if(GetFileSize(DummyBuffer))
										{
											BPTR SomeFile;

											if(SomeFile = Open(DummyBuffer,MODE_OLDFILE))
											{
												if(PacketLine)
												{
													switch(MyEasyRequest(Window,LocaleString(MSG_PACKET_PACKET_WINDOW_STILL_HOLDS_LINES_TXT),LocaleString(MSG_PACKET_DISCARD_APPEND_CANCEL_TXT),PacketLine))
													{
														case 1:	ClearPacketHistory();
															break;

														case 2:	break;

														case 0:	Close(SomeFile);
															SomeFile = NULL;
															break;
													}
												}

												if(SomeFile)
												{
													WORD Len;

													LineRead(NULL,NULL,NULL);

													while(Len = LineRead(SomeFile,DummyBuffer,255))
													{
														DummyBuffer[Len - 1] = 0;

														AddPacketHistory(DummyBuffer);
													}

													Close(SomeFile);
												}
											}
										}
									}

									ReleaseWindows();
									break;

						case MEN_SAVEHISTORY:	BlockWindows();

									if(!PacketLine)
										MyEasyRequest(Window,LocaleString(MSG_PACKET_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
									else
									{
										if(FileRequest = GetFile(LocaleString(MSG_PACKET_SAVE_HISTORY_TXT),"","",DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_TXT)))
										{
											BPTR SomeFile = NULL;

												/* If the file we are about
												 * to create already exists,
												 * ask the user whether we are
												 * to create, append or skip
												 * the file.
												 */

											if(GetFileSize(DummyBuffer))
											{
												switch(MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_TXT),LocaleString(MSG_GLOBAL_CREATE_APPEND_CANCEL_TXT),DummyBuffer))
												{
													case 1:	SomeFile = Open(DummyBuffer,MODE_NEWFILE);
														break;

													case 2:	if(SomeFile = Open(DummyBuffer,MODE_READWRITE))
														{
															if(Seek(SomeFile,0,OFFSET_END) == -1)
															{
																Close(SomeFile);

																SomeFile = NULL;
															}
														}
														break;
												}
											}
											else
												SomeFile = Open(DummyBuffer,MODE_NEWFILE);

											if(!SomeFile)
												MyEasyRequest(Window,LocaleString(MSG_GLOBAL_ERROR_OPENING_FILE_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),DummyBuffer);
											else
											{
												struct Node *SomeNode;

												SomeNode = PacketHistoryList . lh_Head;

												while(SomeNode -> ln_Succ)
												{
													FPrintf(SomeFile,"%s\n",SomeNode -> ln_Name);

													SomeNode = SomeNode -> ln_Succ;
												}

												Close(SomeFile);
											}

											FreeAslRequest(FileRequest);
										}
									}

									ReleaseWindows();

									break;

						case MEN_CLEARHISTORY:  BlockWindows();

									ClearPacketHistory();

									ReleaseWindows();
									break;

						case MEN_OTHERWINDOW:	SwapWindow = TRUE;
									break;

						default:		break;
					}

					Code = MenuItem -> NextSelect;
				}

				ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
			}

				/* Shut down. */

			if(Class == IDCMP_CLOSEWINDOW)
			{
				DeletePacketWindow(FALSE);

				return(FALSE);
			}

				/* Activate the string gadget as well. */

			if(Class == IDCMP_ACTIVEWINDOW)
				ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);

			if(Class == IDCMP_NEWSIZE)
			{
				PacketWindow -> Flags |= WFLG_RMBTRAP;

				strcpy(DummyBuffer,PacketInfo -> Buffer);

				RemoveGList(PacketWindow,PacketGadgetList,(UWORD)-1);

				FreeGadgets(PacketGadgetList);

				PacketGadgetList = NULL;

				SetAPen(PacketWindow -> RPort,0);
				RectFill(PacketWindow -> RPort,PacketWindow -> BorderLeft,PacketWindow -> BorderTop,PacketWindow -> Width - PacketWindow -> BorderRight,PacketWindow -> Height - PacketWindow -> BorderBottom);
				RefreshWindowFrame(PacketWindow);

				PacketHeight	= PacketWindow -> Height;
				PacketWidth	= PacketWindow -> Width;

				if(CreateAllGadgets(PacketWindow -> Width,&PacketGadgetArray[0],&PacketGadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1))
				{
					PacketInfo = (struct StringInfo *)PacketGadgetArray[GAD_STRING] -> SpecialInfo;

					strcpy(PacketInfo -> Buffer,DummyBuffer);

					AddGList(PacketWindow,PacketGadgetList,(UWORD)-1,(UWORD)-1,NULL);
					RefreshGList(PacketGadgetList,PacketWindow,NULL,(UWORD)-1);
					GT_RefreshWindow(PacketWindow,NULL);

					PacketWindow -> Flags &= ~WFLG_RMBTRAP;

					ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
				}
				else
				{
					DeletePacketWindow(FALSE);

					return(FALSE);
				}
			}

			if(Class == IDCMP_MOUSEBUTTONS)
				ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);

				/* User has entered a string. */

			if(Class == IDCMP_GADGETUP)
			{
				switch(Gadget -> GadgetID)
				{
					case GAD_STRING:		/* Just pressed Right-Amiga? */

									/* Is there anything in the buffer at all? */

								if(PacketInfo -> Buffer[0])
								{
									strcpy(DummyBuffer,PacketInfo -> Buffer);

									if(PacketString)
									{
										if(strcmp(PacketString,DummyBuffer))
											AddPacketHistory(DummyBuffer);

										PacketString = NULL;
									}
									else
										AddPacketHistory(DummyBuffer);

										/* Convert alien IBM characters. */

									if(Config . Font == FONT_IBM)
									{
										WORD i;
										UBYTE Char;

										for(i = 0 ; i < strlen(DummyBuffer) ; i++)
										{
											if(Char = IBMConversion[DummyBuffer[i]])
												DummyBuffer[i] = Char;
										}
									}

										/* Execute the command. */

									SerialCommand(DummyBuffer);
								}

									/* Clear the packet window string
									 * gadget.
									 */

								GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
									GTST_String,	"",
								TAG_DONE);

									/* Send a terminating `CR'. */

								switch(Config . SendCR)
								{
									case CR_IGNORE:	break;

									case CR_ASCR:	SerWrite("\r",1);
											break;

									case CR_ASCRLF:	SerWrite("\r\n",2);
											break;
								}

									/* Re-activate the string gadget. */

								ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);

								break;

					case GAD_LIST:		ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
								break;
				}
			}

			if(SwapWindow)
				BumpWindow(Window);

			Result = TRUE;
		}

		if(PacketMsg = (struct PacketMessage *)GetMsg(PacketPort))
		{
			struct Node *Node;

			Result = TRUE;

			if(Node = GetListNode(PacketMsg -> Line,&PacketHistoryList))
			{
				PacketString = Node -> ln_Name;

				if(HasList)
				{
					GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
						GTLV_Selected,	PacketMsg -> Line,
						GTLV_Top,	PacketMsg -> Line,
					TAG_DONE);
				}
				else
				{
					GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
						GTST_String,	Node -> ln_Name,
					TAG_DONE);
				}
			}
			else
			{
				PacketString = NULL;

				GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
					GTST_String,	"",
				TAG_DONE);
			}

			PacketCount = PacketMsg -> Line;

			FreeVec(PacketMsg);

			ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
		}

		return(Result);
	}

	return(FALSE);
}
