/*
**	termUploadQueue.c
**
**	Upload queue user interface.
**
**	Copyright © 1990-1995 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

#include "termGlobal.h"

enum	{	GAD_LIST=1000,GAD_NAME,
		GAD_ADD,GAD_REMOVE,GAD_CLEAR,GAD_HIDE,
		GAD_ADD_FILES
	};

enum	{	APP_ICON=1,APP_WINDOW=2 };

enum	{	TRANSFERMSG_GET_LIST=1,TRANSFERMSG_CHECK_LIST,
		TRANSFERMSG_UPLOAD,TRANSFERMSG_TOGGLE_ICON
	};

STATIC struct List	*TransferList;
STATIC struct Node	*TransferNode;
STATIC LONG		 TransferOffset,
			 TransferCount,
			 TransferSignal;
STATIC struct Process	*TransferProcess;
STATIC struct MsgQueue	*TransferQueue;

	/* QueuePanel(struct Window *Window):
	 *
	 *	Create the user interface for the queue panel.
	 */

STATIC LayoutHandle *
QueuePanel(struct Window *Window)
{
	LayoutHandle *Handle;

	TransferNode	= NULL;
	TransferOffset	= -1;
	TransferCount	= GetListSize(TransferList);

	if(Handle = LT_CreateHandleTags(Window ? Window -> WScreen : NULL,
		LH_LocaleHook,	&LocaleHook,
	TAG_DONE))
	{
		LT_New(Handle,
			LA_Type,	VERTICAL_KIND,
		TAG_DONE);
		{
			LT_New(Handle,
				LA_Type,	VERTICAL_KIND,
			TAG_DONE);
			{
				LT_New(Handle,
					LA_Type,	LISTVIEW_KIND,
					LA_LabelID,	MSG_UPLOADQUEUE_FILES_TO_UPLOAD_TXT,
					LA_LabelPlace,	PLACE_ABOVE,
					LA_Chars,	30,
					LA_Lines,	10,
					LA_ID,		GAD_LIST,
					LALV_CursorKey,	TRUE,
					LALV_MaxGrowY,	20,
					LALV_MaxGrowX,	50,
					LALV_ResizeX,	TRUE,
					LALV_ResizeY,	TRUE,
					GTLV_Labels,	TransferList,

					Kick30 ? LALV_Link : TAG_IGNORE,NIL_LINK,
				TAG_DONE);

				LT_New(Handle,
					LA_Type,	STRING_KIND,
					LA_ID,		GAD_NAME,
					GTST_MaxChars,	255,
					LAST_Picker,	TRUE,
				TAG_DONE);

				LT_EndGroup(Handle);
			}

			LT_New(Handle,
				LA_Type,	HORIZONTAL_KIND,
				LA_LabelID,	MSG_V36_0043,
				LA_SameSize,	TRUE,
			TAG_DONE);
			{
				LT_New(Handle,
					LA_Type,	BUTTON_KIND,
					LA_LabelID,	MSG_ADD_SEVERAL_FILES_TXT,
					LA_ID,		GAD_ADD_FILES,
				TAG_DONE);

				LT_New(Handle,
					LA_Type,	BUTTON_KIND,
					LA_LabelID,	MSG_UPLOADQUEUE_ADD_TXT,
					LA_ID,		GAD_ADD,
				TAG_DONE);

				LT_New(Handle,
					LA_Type,	BUTTON_KIND,
					LA_LabelID,	MSG_UPLOADQUEUE_REMOVE_TXT,
					LA_ID,		GAD_REMOVE,
					GA_Disabled,	TRUE,
				TAG_DONE);

				LT_New(Handle,
					LA_Type,	BUTTON_KIND,
					LA_LabelID,	MSG_UPLOADQUEUE_CLEAR_TXT,
					LA_ID,		GAD_CLEAR,
					GA_Disabled,	!TransferCount,
				TAG_DONE);

				LT_EndGroup(Handle);
			}

			LT_New(Handle,
				LA_Type,	VERTICAL_KIND,
			TAG_DONE);
			{
				LT_New(Handle,LA_Type,XBAR_KIND,LAXB_FullSize,TRUE,TAG_DONE);

				LT_EndGroup(Handle);
			}

			LT_New(Handle,LA_Type,HORIZONTAL_KIND,
				LAGR_SameSize,	TRUE,
			TAG_DONE);
			{
				LT_New(Handle,
					LA_Type,	BUTTON_KIND,
					LA_LabelID,	MSG_UPLOADQUEUE_BINARY_UPLOAD_TXT,
					LA_ID,		UPLOAD_BINARY,
					LABT_ExtraFat,	TRUE,
					LABT_ReturnKey,	TRUE,
					GA_Disabled,	!TransferCount,
				TAG_DONE);

				LT_New(Handle,
					LA_Type,	BUTTON_KIND,
					LA_LabelID,	MSG_UPLOADQUEUE_TEXT_UPLOAD_TXT,
					LA_ID,		UPLOAD_TEXT,
					GA_Disabled,	!TransferCount,
				TAG_DONE);

				LT_New(Handle,
					LA_Type,	BUTTON_KIND,
					LA_LabelID,	MSG_UPLOADQUEUE_HIDE_TXT,
					LA_ID,		GAD_HIDE,
					LABT_EscKey,	TRUE,
				TAG_DONE);

				LT_EndGroup(Handle);
			}

			LT_EndGroup(Handle);
		}

		if(LT_Layout(Handle,LocaleString(MSG_UPLOADQUEUE_FILE_UPLOAD_LIST_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
			WA_DepthGadget,		TRUE,
			WA_CloseGadget,		TRUE,
			WA_DragBar,		TRUE,
			WA_RMBTrap,		TRUE,
			WA_Activate,		TRUE,
			LAWN_BelowMouse,	TRUE,
		TAG_DONE))
		{
			GuideContext(CONTEXT_UPLOAD_QUEUE);

			return(Handle);
		}

		LT_DeleteHandle(Handle);
	}

	return(NULL);
}

	/* HandleQueueWindow(LayoutHandle *Handle):
	 *
	 *	Process queue panel messages.
	 */

STATIC LONG __regargs
HandleQueueWindow(LayoutHandle *Handle)
{
	struct IntuiMessage	*Message;
	ULONG			 MsgClass,
				 MsgQualifier;
	UWORD			 MsgCode;
	struct Gadget		*MsgGadget;

	struct Node		*Node;

	struct Window		*Window = Handle -> Window;
	LONG			 Result = 0;

	UBYTE		 	 DummyBuffer[MAX_FILENAME_LENGTH],
				*DummyChar;
	struct FileRequester	*FileRequest;
	struct TagItem		 DimensionTags[5];

	while(Message = (struct IntuiMessage *)LT_GetIMsg(Handle))
	{
		MsgClass	= Message -> Class;
		MsgQualifier	= Message -> Qualifier;
		MsgCode		= Message -> Code;
		MsgGadget	= (struct Gadget *)Message -> IAddress;

		LT_ReplyIMsg(Message);

		if(MsgClass == IDCMP_CLOSEWINDOW)
			Result = GAD_HIDE;

		if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadget -> GadgetID == GAD_NAME)
		{
			LT_LockWindow(Window);

			SplitFileName(LT_GetString(Handle,GAD_NAME),&DummyChar,DummyBuffer);

			if(FileRequest = GetFile(Window,LocaleString(MSG_UPLOADQUEUE_SELECT_FILE_TXT),DummyBuffer,DummyChar,DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT),FALSE))
			{
				LT_SetAttributes(Handle,GAD_NAME,
					GTST_String,	DummyBuffer,
				TAG_DONE);
			}

			LT_UnlockWindow(Window);

			LT_Activate(Handle,GAD_NAME);
		}

		if(MsgClass == IDCMP_GADGETUP)
		{
			switch(MsgGadget -> GadgetID)
			{
				case GAD_ADD_FILES:

					LT_LockWindow(Window);

					if(!GetCurrentDirName(DummyBuffer,MAX_FILENAME_LENGTH))
						DummyBuffer[0] = 0;

					if(FileRequest = AllocAslRequestTags(ASL_FileRequest,
						ASL_Window,	Window,
						ASL_Hail,	LocaleString(MSG_ADD_FILES_TITLE_TXT),
						ASL_FuncFlags,	FILF_MULTISELECT,
						ASL_OKText,	LocaleString(MSG_ADD_GAD),
						ASL_CancelText,	LocaleString(MSG_DONE_GAD),
						ASL_Dir,	DummyBuffer,
						ASLFR_TextAttr,	&UserFont,
					TAG_MORE,GetDimensionTags(Window,DimensionTags)))
					{
						LONG i;

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

						while(AslRequestTags(FileRequest,TAG_DONE))
						{
							for(i = 0 ; i < FileRequest -> rf_NumArgs ; i++)
							{
								if(FileRequest -> fr_ArgList[i] . wa_Lock)
								{
									if(!NameFromLock(FileRequest -> fr_ArgList[i] . wa_Lock,DummyBuffer,MAX_FILENAME_LENGTH))
										DummyBuffer[0] = 0;
								}
								else
									strcpy(DummyBuffer,FileRequest -> fr_Drawer);

								if(FileRequest -> fr_ArgList[i] . wa_Name)
								{
									if(!AddPart(DummyBuffer,FileRequest -> fr_ArgList[i] . wa_Name,MAX_FILENAME_LENGTH))
										DummyBuffer[0] = 0;
								}

								if(DummyBuffer[0])
								{
									if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + 256,MEMF_ANY))
									{
										Node -> ln_Name = (STRPTR)(Node + 1);

										strcpy(Node -> ln_Name,DummyBuffer);

										AddTail(TransferList,Node);

										TransferNode = Node;
										TransferOffset = TransferCount++;
									}
								}
							}

							LT_SetAttributes(Handle,GAD_LIST,
								GTLV_Labels,	TransferList,
								GTLV_Selected,	TransferOffset,
							TAG_DONE);
						}

						LT_SetAttributes(Handle,GAD_LIST,
							GTLV_Labels,	TransferList,
							GTLV_Selected,	TransferOffset,
						TAG_DONE);

						if(TransferCount)
						{
							LT_SetAttributes(Handle,GAD_NAME,
								GTST_String,	"",
							TAG_DONE);

							LT_SetAttributes(Handle,GAD_REMOVE,
								GA_Disabled,	FALSE,
							TAG_DONE);

							LT_SetAttributes(Handle,UPLOAD_BINARY,
								GA_Disabled,	FALSE,
							TAG_DONE);

							LT_SetAttributes(Handle,UPLOAD_TEXT,
								GA_Disabled,	FALSE,
							TAG_DONE);

							LT_SetAttributes(Handle,GAD_CLEAR,
								GA_Disabled,	FALSE,
							TAG_DONE);
						}

						PutDimensionTags(Window,FileRequest -> rf_LeftEdge,FileRequest -> rf_TopEdge,FileRequest -> rf_Width,FileRequest -> rf_Height);

						FreeAslRequest(FileRequest);
					}

					LT_UnlockWindow(Window);
					break;

				case GAD_ADD:

					if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + 256,MEMF_ANY))
					{
						Node -> ln_Name = (STRPTR)(Node + 1);

						Node -> ln_Name[0] = 0;

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

						AddTail(TransferList,Node);

						LT_SetAttributes(Handle,GAD_LIST,
							GTLV_Labels,	TransferList,
							GTLV_Selected,	TransferOffset = TransferCount++,
						TAG_DONE);

						LT_SetAttributes(Handle,GAD_NAME,
							GTST_String,	"",
						TAG_DONE);

						LT_SetAttributes(Handle,GAD_REMOVE,
							GA_Disabled,	FALSE,
						TAG_DONE);

						LT_SetAttributes(Handle,UPLOAD_BINARY,
							GA_Disabled,	FALSE,
						TAG_DONE);

						LT_SetAttributes(Handle,UPLOAD_TEXT,
							GA_Disabled,	FALSE,
						TAG_DONE);

						LT_SetAttributes(Handle,GAD_CLEAR,
							GA_Disabled,	FALSE,
						TAG_DONE);

						TransferNode = Node;

						LT_Activate(Handle,GAD_NAME);
					}
					else
						DisplayBeep(Window -> WScreen);

					break;

				case GAD_REMOVE:

					if(TransferNode)
					{
						LT_SetAttributes(Handle,GAD_LIST,
							GTLV_Labels,	~0,
						TAG_DONE);

						if(--TransferCount)
						{
							if(TransferNode -> ln_Succ -> ln_Succ)
								Node = TransferNode -> ln_Succ;
							else
							{
								if(TransferNode -> ln_Pred -> ln_Pred)
								{
									Node = TransferNode -> ln_Pred;

									TransferOffset--;
								}
								else
								{
									TransferOffset = -1;

									Node = NULL;
								}
							}
						}
						else
						{
							TransferOffset = -1;

							Node = NULL;
						}

						Remove(TransferNode);

						FreeVecPooled(TransferNode);

						TransferNode = Node;

						LT_SetAttributes(Handle,GAD_LIST,
							GTLV_Labels,	TransferList,
							GTLV_Selected,	TransferOffset,
						TAG_DONE);

						if(!TransferCount)
						{
							LT_SetAttributes(Handle,GAD_REMOVE,
								GA_Disabled,	TRUE,
							TAG_DONE);

							LT_SetAttributes(Handle,GAD_NAME,
								GTST_String,	"",
							TAG_DONE);

							LT_SetAttributes(Handle,GAD_CLEAR,
								GA_Disabled,	TRUE,
							TAG_DONE);

							LT_SetAttributes(Handle,UPLOAD_BINARY,
								GA_Disabled,	TRUE,
							TAG_DONE);

							LT_SetAttributes(Handle,UPLOAD_TEXT,
								GA_Disabled,	TRUE,
							TAG_DONE);
						}
						else
						{
							LT_SetAttributes(Handle,GAD_NAME,
								GTST_String,	TransferNode -> ln_Name,
							TAG_DONE);
						}
					}

					break;

				case GAD_LIST:

					if(TransferNode = (struct Node *)GetListNode(MsgCode,TransferList))
					{
						TransferOffset = MsgCode;

						LT_SetAttributes(Handle,GAD_NAME,
							GTST_String,	TransferNode -> ln_Name,
						TAG_DONE);

						LT_SetAttributes(Handle,GAD_REMOVE,
							GA_Disabled,	FALSE,
						TAG_DONE);
					}

					break;

				case GAD_NAME:

					if(TransferNode)
					{
						LT_SetAttributes(Handle,GAD_LIST,
							GTLV_Labels,	~0,
						TAG_DONE);

						strcpy(TransferNode -> ln_Name,LT_GetString(Handle,GAD_NAME));

						LT_SetAttributes(Handle,GAD_LIST,
							GTLV_Labels,	TransferList,
							GTLV_Selected,	~0,
						TAG_DONE);
					}
					else
					{
						if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + 256,MEMF_ANY))
						{
							Node -> ln_Name = (STRPTR)(Node + 1);

							strcpy(Node -> ln_Name,LT_GetString(Handle,GAD_NAME));

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

							AddTail(TransferList,Node);

							TransferCount++;

							LT_SetAttributes(Handle,UPLOAD_BINARY,
								GA_Disabled,	FALSE,
							TAG_DONE);

							LT_SetAttributes(Handle,UPLOAD_TEXT,
								GA_Disabled,	FALSE,
							TAG_DONE);

							LT_SetAttributes(Handle,GAD_CLEAR,
								GA_Disabled,	FALSE,
							TAG_DONE);

							LT_SetAttributes(Handle,GAD_LIST,
								GTLV_Labels,		TransferList,
								GTLV_Selected,		~0,
								GTLV_MakeVisible,	TransferCount - 1,
							TAG_DONE);
						}
					}

					LT_SetAttributes(Handle,GAD_REMOVE,
						GA_Disabled,	TRUE,
					TAG_DONE);

					LT_SetAttributes(Handle,GAD_NAME,
						GTST_String,	"",
					TAG_DONE);

					TransferNode	= NULL;
					TransferOffset	= -1;

					break;

				case GAD_CLEAR:

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

					TransferCount	= 0;
					TransferOffset	= -1;
					TransferNode	= NULL;

					FreeList(TransferList);

					LT_SetAttributes(Handle,GAD_REMOVE,
						GA_Disabled,	TRUE,
					TAG_DONE);

					LT_SetAttributes(Handle,GAD_NAME,
						GTST_String,	"",
					TAG_DONE);

					LT_SetAttributes(Handle,GAD_CLEAR,
						GA_Disabled,	TRUE,
					TAG_DONE);

					LT_SetAttributes(Handle,UPLOAD_BINARY,
						GA_Disabled,	TRUE,
					TAG_DONE);

					LT_SetAttributes(Handle,UPLOAD_TEXT,
						GA_Disabled,	TRUE,
					TAG_DONE);

					LT_SetAttributes(Handle,GAD_LIST,
						GTLV_Labels,	TransferList,
						GTLV_Selected,	~0,
					TAG_DONE);

					break;

				case UPLOAD_BINARY:
				case UPLOAD_TEXT:
				case GAD_HIDE:

					Result = MsgGadget -> GadgetID;
					break;
			}
		}
	}

	return(Result);
}

	/* QueueClientDestructor(struct DataMsg *Item):
	 *
	 *	Local msgitem destructor.
	 */

STATIC VOID __stdargs
QueueClientDestructor(struct DataMsg *Item)
{
	Signal(TransferProcess,1L << TransferSignal);
}

	/* QueueEntry(VOID):
	 *
	 *	The entry point for the queue process.
	 */

STATIC VOID __saveds
QueueEntry(VOID)
{
	if(TransferList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
	{
		if(TransferQueue = CreateMsgQueue(NULL,0))
		{
			struct MsgPort		*AppPort;
			struct AppIcon		*AppIcon;
			struct AppWindow	*AppWindow;
			APTR			 OldPtr;

			NewList(TransferList);

			TransferNode	= NULL;
			TransferOffset	= -1;

			if(AppPort = CreateMsgPort())
			{
				if((TransferSignal = AllocSignal(-1)) != -1)
				{
					ULONG			 Signals;
					BOOLEAN			 Done = FALSE;
					LayoutHandle		*Handle;
					struct Window		*LocalWindow;
					ULONG			 WindowMask,
								 TransferMask,
								 ClientMask;
					struct AppMessage	*AppMessage;
					struct DiskObject	*LoadedIcon = NULL;

					if(WorkbenchBase && !Config -> TransferConfig -> HideUploadIcon)
					{
						if(IconBase)
						{
							UBYTE LocalBuffer[MAX_FILENAME_LENGTH];

							strcpy(LocalBuffer,Config -> PathConfig -> DefaultStorage);

							if(AddPart(LocalBuffer,"term_DropIcon",MAX_FILENAME_LENGTH))
								LoadedIcon = GetDiskObject(LocalBuffer);

							if(!LoadedIcon)
								LoadedIcon = GetDiskObject("PROGDIR:term_DropIcon");
						}

						AppIcon = AddAppIconA(APP_ICON,NULL,LocaleString(MSG_UPLOADQUEUE_TERM_UPLOAD_LIST_TXT),AppPort,NULL,LoadedIcon ? LoadedIcon : &DropIcon,NULL);
					}
					else
						AppIcon = NULL;

					AppWindow	= NULL;
					WindowMask	= NULL;
					Handle		= NULL;
					LocalWindow	= NULL;
					TransferMask	= TransferQueue -> SigMask;
					ClientMask	= (1L << TransferSignal);

					TransferProcess = (struct Process *)FindTask(NULL);

					OldPtr = TransferProcess -> pr_WindowPtr;

					Signal(ThisProcess,SIG_HANDSHAKE);

					do
					{
						Signals = Wait(SIG_KILL | SIG_SHOW | SIG_HIDE | SIG_GOAWAY | WindowMask | TransferMask | PORTMASK(AppPort));

						if(Signals & TransferMask)
						{
							struct DataMsg *Item;

							while(Item = GetMsgItem(TransferQueue))
							{
								switch(Item -> Type)
								{
									case TRANSFERMSG_GET_LIST:

										Item -> Data = NULL;

										if(TransferList -> lh_Head -> ln_Succ)
										{
											struct List *List;

											if(Handle)
											{
												LT_SetAttributes(Handle,GAD_LIST,
													GTLV_Labels,	~0,
												TAG_DONE);
											}

											if(List = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
											{
												struct Node *Node,*Next;

												NewList(List);

												for(Node = TransferList -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
												{
													Remove(Node);

													AddTail(List,Node);
												}

												Item -> Data = (UBYTE *)List;
											}

											if(Handle)
											{
												TransferCount = GetListSize(TransferList);

												TransferOffset	= -1;
												TransferNode	= NULL;

												LT_SetAttributes(Handle,GAD_REMOVE,
													GA_Disabled,	TRUE,
												TAG_DONE);

												LT_SetAttributes(Handle,GAD_NAME,
													GTST_String,	"",
												TAG_DONE);

												LT_SetAttributes(Handle,GAD_CLEAR,
													GA_Disabled,	!TransferCount,
												TAG_DONE);

												LT_SetAttributes(Handle,UPLOAD_BINARY,
													GA_Disabled,	!TransferCount,
												TAG_DONE);

												LT_SetAttributes(Handle,UPLOAD_TEXT,
													GA_Disabled,	!TransferCount,
												TAG_DONE);

												LT_SetAttributes(Handle,GAD_LIST,
													GTLV_Labels,	TransferList,
												TAG_DONE);
											}
										}

										break;

										// Check to see if there is anything in the list?

									case TRANSFERMSG_CHECK_LIST:

										if(TransferList -> lh_Head -> ln_Succ)
											Item -> Size = TRUE;
										else
											Item -> Size = FALSE;

										break;

										// Start a file tansfer?

									case TRANSFERMSG_UPLOAD:
									{
										UBYTE		Type = Item -> Size;
										struct DataMsg	Msg;

										DeleteMsgItem(Item);

										Item = NULL;

										InitMsgItem(&Msg,QueueClientDestructor);

										Msg . Type = DATAMSGTYPE_UPLOAD;
										Msg . Data = (UBYTE *)TransferList;
										Msg . Size = Type;

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

											LT_LockWindow(LocalWindow);
										}

										Forbid();

										ClrSignal(ClientMask);

										PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);

										Wait(ClientMask);

										Permit();

										if(Handle)
										{
											TransferCount = GetListSize(TransferList);

											TransferOffset	= -1;
											TransferNode	= NULL;

											LT_SetAttributes(Handle,GAD_REMOVE,
												GA_Disabled,	TRUE,
											TAG_DONE);

											LT_SetAttributes(Handle,GAD_NAME,
												GTST_String,	"",
											TAG_DONE);

											LT_SetAttributes(Handle,GAD_CLEAR,
												GA_Disabled,	!TransferCount,
											TAG_DONE);

											LT_SetAttributes(Handle,UPLOAD_BINARY,
												GA_Disabled,	!TransferCount,
											TAG_DONE);

											LT_SetAttributes(Handle,UPLOAD_TEXT,
												GA_Disabled,	!TransferCount,
											TAG_DONE);

											LT_SetAttributes(Handle,GAD_LIST,
												GTLV_Labels,	TransferList,
											TAG_DONE);

											LT_UnlockWindow(LocalWindow);
										}

										break;
									}

										// Show or hide the icon?

									case TRANSFERMSG_TOGGLE_ICON:

											// Hide the icon

										if(Item -> Size)
										{
											if(AppIcon)
											{
												RemoveAppIcon(AppIcon);

												AppIcon = NULL;
											}

											if(LoadedIcon)
											{
												FreeDiskObject(LoadedIcon);

												LoadedIcon = NULL;
											}
										}
										else
										{
											if(!AppIcon)
											{
												if(WorkbenchBase)
												{
													if(IconBase)
													{
														UBYTE LocalBuffer[MAX_FILENAME_LENGTH];

														strcpy(LocalBuffer,Config -> PathConfig -> DefaultStorage);

														if(AddPart(LocalBuffer,"term_DropIcon",MAX_FILENAME_LENGTH))
															LoadedIcon = GetDiskObject(LocalBuffer);

														if(!LoadedIcon)
															LoadedIcon = GetDiskObject("PROGDIR:term_DropIcon");
													}

													AppIcon = AddAppIconA(APP_ICON,NULL,LocaleString(MSG_UPLOADQUEUE_TERM_UPLOAD_LIST_TXT),AppPort,NULL,LoadedIcon ? LoadedIcon : &DropIcon,NULL);
												}
												else
													AppIcon = NULL;
											}
										}

										break;
								}

								DeleteMsgItem(Item);
							}
						}

						if(Signals & SIG_HIDE)
						{
							if(AppWindow)
							{
								RemoveAppWindow(AppWindow);

								AppWindow = NULL;
							}

							if(Handle)
							{
								LT_DeleteHandle(Handle);

								Handle = NULL;
							}

							WindowMask	= NULL;
							LocalWindow	= NULL;

							TransferProcess -> pr_WindowPtr = OldPtr;

							Signal(ThisProcess,SIG_HANDSHAKE);
						}

						if(Signals & SIG_GOAWAY)
						{
							if(Handle)
							{
								if(LocalWindow -> WScreen == Screen)
								{
									if(AppWindow)
									{
										RemoveAppWindow(AppWindow);

										AppWindow = NULL;
									}

									LT_DeleteHandle(Handle);

									Handle		= NULL;
									WindowMask	= NULL;
									LocalWindow	= NULL;

									TransferProcess -> pr_WindowPtr = OldPtr;
								}
							}

							Signal(ThisProcess,SIG_HANDSHAKE);
						}

						if(Signals & SIG_KILL)
							break;

						if(Signals & SIG_SHOW)
						{
							if(!Handle)
							{
								Forbid();

								if(Handle = QueuePanel(Window))
								{
									Permit();

									if(WorkbenchBase)
										AppWindow = AddAppWindowA(APP_WINDOW,NULL,Handle -> Window,AppPort,NULL);
									else
										AppWindow = NULL;

									LocalWindow	= Handle -> Window;
									WindowMask	= PORTMASK(LocalWindow -> UserPort);

									TransferProcess -> pr_WindowPtr = LocalWindow;
								}
								else
									Permit();
							}

							if(Handle)
								LT_ShowWindow(Handle,TRUE);
						}

						if(Signals & WindowMask)
						{
							struct DataMsg	Msg;
							LONG		Type;

							switch(Type = HandleQueueWindow(Handle))
							{
								case GAD_HIDE:

									if(AppWindow)
									{
										RemoveAppWindow(AppWindow);

										AppWindow = NULL;
									}

									if(Handle)
									{
										LT_DeleteHandle(Handle);

										Handle = NULL;
									}

									TransferProcess -> pr_WindowPtr = OldPtr;

									WindowMask	= NULL;
									LocalWindow	= NULL;

									break;

								case UPLOAD_BINARY:
								case UPLOAD_TEXT:

									InitMsgItem(&Msg,QueueClientDestructor);

									Msg . Type = DATAMSGTYPE_UPLOAD;
									Msg . Data = (UBYTE *)TransferList;
									Msg . Size = Type;

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

										LT_LockWindow(LocalWindow);
									}

									Forbid();

									ClrSignal(ClientMask);

									PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);

									Wait(ClientMask);

									Permit();

									if(Handle)
									{
										TransferCount = GetListSize(TransferList);

										TransferOffset	= -1;
										TransferNode	= NULL;

										LT_SetAttributes(Handle,GAD_REMOVE,
											GA_Disabled,	TRUE,
										TAG_DONE);

										LT_SetAttributes(Handle,GAD_NAME,
											GTST_String,	"",
										TAG_DONE);

										LT_SetAttributes(Handle,GAD_CLEAR,
											GA_Disabled,	!TransferCount,
										TAG_DONE);

										LT_SetAttributes(Handle,UPLOAD_BINARY,
											GA_Disabled,	!TransferCount,
										TAG_DONE);

										LT_SetAttributes(Handle,UPLOAD_TEXT,
											GA_Disabled,	!TransferCount,
										TAG_DONE);

										LT_SetAttributes(Handle,GAD_LIST,
											GTLV_Labels,	TransferList,
										TAG_DONE);

										LT_UnlockWindow(LocalWindow);
									}

									break;
							}
						}

						if(Signals & PORTMASK(AppPort))
						{
							while(AppMessage = (struct AppMessage *)GetMsg(AppPort))
							{
								if(AppMessage -> am_Type == AMTYPE_APPWINDOW && Handle)
								{
									UBYTE	DummyBuffer[MAX_FILENAME_LENGTH];
									BPTR	OldDir,FileLock;
									LONG	i;

									TransferProcess -> pr_WindowPtr = (APTR)-1;

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

									for(i = 0 ; i < AppMessage -> am_NumArgs ; i++)
									{
										if(AppMessage -> am_ArgList[i] . wa_Name)
										{
											OldDir = CurrentDir(AppMessage -> am_ArgList[i] . wa_Lock);

											if(GetFileSize(AppMessage -> am_ArgList[i] . wa_Name))
											{
												if(FileLock = Lock(AppMessage -> am_ArgList[i] . wa_Name,ACCESS_READ))
												{
													if(NameFromLock(FileLock,DummyBuffer,MAX_FILENAME_LENGTH))
													{
														struct Node *Node;

														if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + 256,MEMF_ANY))
														{
															Node -> ln_Name = (STRPTR)(Node + 1);

															strcpy(Node -> ln_Name,DummyBuffer);

															AddTail(TransferList,Node);

															TransferCount++;
														}
													}

													UnLock(FileLock);
												}
											}

											CurrentDir(OldDir);
										}
									}

									TransferProcess -> pr_WindowPtr = LocalWindow;

									LT_SetAttributes(Handle,GAD_LIST,
										GTLV_Labels,	TransferList,
									TAG_DONE);

									LT_SetAttributes(Handle,GAD_CLEAR,
										GA_Disabled,	!TransferCount,
									TAG_DONE);

									LT_SetAttributes(Handle,UPLOAD_BINARY,
										GA_Disabled,	!TransferCount,
									TAG_DONE);

									LT_SetAttributes(Handle,UPLOAD_TEXT,
										GA_Disabled,	!TransferCount,
									TAG_DONE);
								}

								if(AppMessage -> am_Type == AMTYPE_APPICON)
								{
									if(AppMessage -> am_NumArgs)
									{
										UBYTE	DummyBuffer[MAX_FILENAME_LENGTH];
										BPTR	OldDir,FileLock;
										LONG	i;

										TransferProcess -> pr_WindowPtr = (APTR)-1;

										if(Handle)
										{
											LT_SetAttributes(Handle,GAD_LIST,
												GTLV_Labels,	~0,
											TAG_DONE);
										}

										for(i = 0 ; i < AppMessage -> am_NumArgs ; i++)
										{
											if(AppMessage -> am_ArgList[i] . wa_Name)
											{
												OldDir = CurrentDir(AppMessage -> am_ArgList[i] . wa_Lock);

												if(GetFileSize(AppMessage -> am_ArgList[i] . wa_Name))
												{
													if(FileLock = Lock(AppMessage -> am_ArgList[i] . wa_Name,ACCESS_READ))
													{
														if(NameFromLock(FileLock,DummyBuffer,MAX_FILENAME_LENGTH))
														{
															struct Node *Node;

															if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + 256,MEMF_ANY))
															{
																Node -> ln_Name = (STRPTR)(Node + 1);

																strcpy(Node -> ln_Name,DummyBuffer);

																AddTail(TransferList,Node);

																TransferCount++;
															}
														}

														UnLock(FileLock);
													}
												}

												CurrentDir(OldDir);
											}
										}

										if(Handle)
										{
											TransferProcess -> pr_WindowPtr = LocalWindow;

											LT_SetAttributes(Handle,GAD_LIST,
												GTLV_Labels,	TransferList,
											TAG_DONE);

											LT_SetAttributes(Handle,GAD_CLEAR,
												GA_Disabled,	!TransferCount,
											TAG_DONE);

											LT_SetAttributes(Handle,UPLOAD_BINARY,
												GA_Disabled,	!TransferCount,
											TAG_DONE);

											LT_SetAttributes(Handle,UPLOAD_TEXT,
												GA_Disabled,	!TransferCount,
											TAG_DONE);
										}
										else
											TransferProcess -> pr_WindowPtr = OldPtr;
									}
									else
									{
										if(!Handle)
										{
											if(Handle = QueuePanel(NULL))
											{
												AppWindow = AddAppWindowA(APP_WINDOW,NULL,Handle -> Window,AppPort,NULL);

												LocalWindow = Handle -> Window;

												WindowMask = PORTMASK(LocalWindow -> UserPort);

												TransferProcess -> pr_WindowPtr = LocalWindow;
											}
										}
									}
								}

								ReplyMsg(AppMessage);
							}
						}
					}
					while(!Done);

					if(AppIcon)
						RemoveAppIcon(AppIcon);

					if(AppWindow)
						RemoveAppWindow(AppWindow);

					if(LoadedIcon)
						FreeDiskObject(LoadedIcon);

					if(Handle)
						LT_DeleteHandle(Handle);

					while(AppMessage = (struct AppMessage *)GetMsg(AppPort))
						ReplyMsg(AppMessage);

					FreeSignal(TransferSignal);
				}
			}

			DeleteMsgQueue(TransferQueue);
		}

		DeleteList(TransferList);

		TransferList = NULL;
	}

	Forbid();

	TransferProcess = NULL;

	Signal(ThisProcess,SIG_HANDSHAKE);
}

	/* CloseQueueWindow():
	 *
	 *	Close the queue window, wherever it may be.
	 */

VOID
CloseQueueWindow()
{
	if(TransferProcess)
	{
		Forbid();

		ClrSignal(SIG_HANDSHAKE);

		Signal(TransferProcess,SIG_GOAWAY);

		Wait(SIG_HANDSHAKE);

		Permit();
	}
}

	/* DeleteQueueProcess():
	 *
	 *	Terminate the queue handler process.
	 */

VOID
DeleteQueueProcess()
{
	if(TransferProcess)
	{
		Forbid();

		ClrSignal(SIG_HANDSHAKE);

		Signal(TransferProcess,SIG_KILL);

		Wait(SIG_HANDSHAKE);

		Permit();
	}
}

	/* CreateQueueProcess():
	 *
	 *	Create the queue handler process, if it's still around
	 *	bring it to the front.
	 */

BOOLEAN
CreateQueueProcess()
{
	if(!TransferProcess)
	{
		Forbid();

		if(CreateNewProcTags(
			NP_Entry,	QueueEntry,
			NP_Name,	"term Upload process",
			NP_Priority,	SysBase -> ThisTask -> tc_Node . ln_Pri,
			NP_StackSize,	6144,
			NP_WindowPtr,	NULL,
		TAG_DONE))
		{
			ClrSignal(SIG_HANDSHAKE);

			Wait(SIG_HANDSHAKE);
		}

		Permit();
	}
	else
		Signal(TransferProcess,SIG_SHOW);

	return((BOOLEAN)(TransferProcess != NULL));
}

STATIC VOID __stdargs
LocalMsgDestructor(struct DataMsg *Item)
{
	Signal(Item -> Client,Item -> Mask);
}

	/* GetUploadList():
	 *
	 *	Copy the current upload list and return it.
	 */

struct List *
GetUploadList()
{
	if(TransferProcess)
	{
		BYTE SigBit;

		if((SigBit = AllocSignal(-1)) != -1)
		{
			struct DataMsg Msg;

			InitMsgItem(&Msg,LocalMsgDestructor);

			Msg . Type	= TRANSFERMSG_GET_LIST;
			Msg . Client	= SysBase -> ThisTask;
			Msg . Mask	= 1L << SigBit;

			ClrSignal(Msg . Mask);

			PutMsgItem(TransferQueue,(struct MsgItem *)&Msg);

			Wait(Msg . Mask);

			FreeSignal(SigBit);

			return((struct List *)Msg . Data);
		}
	}

	return(NULL);
}

	/* CheckUpload():
	 *
	 *	Check if there is anything in the upload list.
	 */

BOOLEAN
CheckUpload()
{
	if(TransferProcess)
	{
		BYTE SigBit;

		if((SigBit = AllocSignal(-1)) != -1)
		{
			struct DataMsg Msg;

			InitMsgItem(&Msg,LocalMsgDestructor);

			Msg . Type	= TRANSFERMSG_CHECK_LIST;
			Msg . Client	= SysBase -> ThisTask;
			Msg . Mask	= 1L << SigBit;

			ClrSignal(Msg . Mask);

			PutMsgItem(TransferQueue,(struct MsgItem *)&Msg);

			Wait(Msg . Mask);

			FreeSignal(SigBit);

			return((BOOLEAN)Msg . Size);
		}
	}

	return(FALSE);
}

	/* StartUpload(UBYTE Type):
	 *
	 *	Start an upload the standard way.
	 */

VOID __regargs
StartUpload(UBYTE Type)
{
	if(TransferProcess)
	{
		BYTE SigBit;

		if((SigBit = AllocSignal(-1)) != -1)
		{
			struct DataMsg Msg;

			SetQueueDiscard(SpecialQueue,FALSE);

			InitMsgItem(&Msg,LocalMsgDestructor);

			Msg . Type	= TRANSFERMSG_UPLOAD;
			Msg . Size	= Type;
			Msg . Client	= SysBase -> ThisTask;
			Msg . Mask	= 1L << SigBit;

			ClrSignal(Msg . Mask);

			PutMsgItem(TransferQueue,(struct MsgItem *)&Msg);

			Wait(Msg . Mask);

			FreeSignal(SigBit);
		}
	}
}

	/* ToggleUploadQueueIcon():
	 *
	 *	Turn the upload queue appicon on or off.
	 */

VOID __regargs
ToggleUploadQueueIcon(BOOL Mode)
{
	if(TransferProcess)
	{
		BYTE SigBit;

		if((SigBit = AllocSignal(-1)) != -1)
		{
			struct DataMsg Msg;

			InitMsgItem(&Msg,LocalMsgDestructor);

			Msg . Type	= TRANSFERMSG_TOGGLE_ICON;
			Msg . Size	= Mode;
			Msg . Client	= SysBase -> ThisTask;
			Msg . Mask	= 1L << SigBit;

			ClrSignal(Msg . Mask);

			PutMsgItem(TransferQueue,(struct MsgItem *)&Msg);

			Wait(Msg . Mask);

			FreeSignal(SigBit);
		}
	}
}
