#ifndef TSICON_H
#include "TSIcon.h.c" 
#endif

char *Version = "$VER: TSIcon 1.00 (9.6.93)\n";

/* Arexx commands */
 struct CommandEntry CommandEntry[] = {
	{"quit"},
	{"add"},
	{"show"},
	{"enable"},
	{"disable"},
	{"hide"},
	{"remove"},
	{"wshow"},
	{"list"}
};
#define RX_QUIT		0
#define RX_ADD			1
#define RX_SHOW		2
#define RX_ENABLE		3
#define RX_DISABLE	4
#define RX_HIDE		5
#define RX_REMOVE		6
#define RX_WSHOW		7
#define RX_LIST		8
#define COMMAND_END	9

struct Gadget *Gad_R_Disable,*Gad_R_Hide,*Gad_R_List,*Gad_R_Quit,*Gad_R_Enable,
				*Gad_R_Delete,*Gad_R_Add,*Gad_R_About,*EGList,*Egadlist[8];

struct Window		*EWin = NULL;
struct VisualInfo	*VisInfo=NULL;

/* Menu stuff */
struct Menu* MyMenu = NULL;
#define MM_OPEN			1
#define MM_CLOSE			2
#define MM_ABOUT			3
#define MM_HIDE			4
#define MM_QUIT			5
#define MM_ENABLED		6
#define MM_ENABLED_NUM	11
#define MM_CLOSE_NUM	 	3
#define FULL_CLOSE FULLMENUNUM(0,2,NOSUB)
#define FULL_ENABLED FULLMENUNUM(1,0,NOSUB)
struct NewMenu MyNewMenu[13] = {
	{NM_TITLE,"Project",NULL,0,0,NULL},
		{NM_ITEM,"Open...","O",0,0,(APTR)MM_OPEN},
		{NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
		{NM_ITEM,"Close",NULL,0,0,(APTR)MM_CLOSE},
		{NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
		{NM_ITEM,"About...",NULL,0,0,(APTR)MM_ABOUT},
		{NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
		{NM_ITEM,"Hide",NULL,0,0,(APTR)MM_HIDE},
		{NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
		{NM_ITEM,"Quit","Q",0,0,(APTR)MM_QUIT},
	{NM_TITLE,"Settings",NULL,0,0,NULL},
		{NM_ITEM,"Enabled?",NULL,CHECKIT|MENUTOGGLE,0,(APTR)MM_ENABLED},
	{NM_END,NULL,NULL,0,0,NULL}
};

struct NewGadget NGAry[8] = {
{
	GLEF_0,GTOP_0,GWID_0,GHEI_0,
	"Di_sable",
	NULL,
	GAD_R_Disable,
	PLACETEXT_IN,
},
{
	GLEF_1,GTOP_1,GWID_1,GHEI_1,
	"_Hide",
	NULL,
	GAD_R_Hide,
	PLACETEXT_IN,
},
{
	GLEF_2,GTOP_2,GWID_2,GHEI_2,
	"Available _Icons",
	NULL,
	GAD_R_List,
	PLACETEXT_ABOVE|NG_HIGHLABEL,
},
{
	GLEF_3,GTOP_3,GWID_3,GHEI_3,
	"_Quit",
	NULL,
	GAD_R_Quit,
	PLACETEXT_IN,
},
{
	GLEF_4,GTOP_4,GWID_4,GHEI_4,
	"_Enable",
	NULL,
	GAD_R_Enable,
	PLACETEXT_IN,
},
{
	GLEF_5,GTOP_5,GWID_5,GHEI_5,
	"_Delete",
	NULL,
	GAD_R_Delete,
	PLACETEXT_IN,
},
{
	GLEF_6,GTOP_6,GWID_6,GHEI_6,
	"_Add...",
	NULL,
	GAD_R_Add,
	PLACETEXT_IN,
},
{
	GLEF_7,GTOP_7,GWID_7,GHEI_7,
	"A_bout...",
	NULL,
	GAD_R_About,
	PLACETEXT_IN,
}
};

WORD WA_Zoom_TAG[4] = {0,0,WWID,0};

extern struct Library *IconBase = NULL,*WorkbenchBase = NULL,*CxBase = NULL,*GadToolsBase = NULL,*AslBase = NULL,*UtilityBase = NULL;

extern struct IntuitionBase *IntuitionBase = NULL;
extern struct GfxBase *GfxBase = NULL;
extern struct RxsLib *RexxSysBase = NULL;

struct MsgPort *RexxPort = NULL,*MsgPortp = NULL,*ControlPort = NULL,*CxPort = NULL,*timerport = NULL,*UserPort = NULL,*WindowPort = NULL;

struct timerequest *timerequest = NULL;
CxObj *CxObjp = NULL;
struct FileRequester *filereq = NULL;
struct AppMenuItem *AppMenu = NULL;
struct AppWindow *AppWindowp = NULL;
struct Screen *Scr = NULL;
struct Gadget *gadgets = NULL;
struct RDArgs *RDArg = NULL;

struct List IList;

ULONG ListCount = 0;

short Animated = 0, notDone = 1;
ULONG CurrentList=0;
BOOL Active = TRUE, CliFg;
WORD W_Left,W_Top;

extern struct WBStartup *WBenchMsg;
extern int _fmode,_iomode;
extern struct UFB _ufbs[];

 USHORT __chip BusyPointerData[] = {
	0x0000,0x0000,
	0x0400,0x07C0,0x0000,0x07C0,0x0100,0x0380,0x0000,0x07E0,
	0x07C0,0x1FF8,0x1FF0,0x3FEC,0x3FF8,0x7FDE,0x3FF8,0x7FBE,
	0x7FFC,0xFF7F,0x7EFC,0xFFFF,0x7FFC,0xFFFF,0x3FF8,0x7FFE,
	0x3FF8,0x7FFE,0x1FF0,0x3FFC,0x07C0,0x1FF8,0x0000,0x07E0,
	0x0000,0x0000,
};

LONG RD_Array[8] = {
	0,0,0,0,0,0,0,0
};

void
mymain(char *line) {
	char dirname[257];
	BOOL GoFlag = TRUE;
	short cnt;
	struct AppMessage *AppMessage;
	struct WBStartup *argmsg;
	struct WBArg *wb_arg;
	struct IN *IN;
	short i;
	struct IconMessage IconMessage;
	struct IconMessage *IconMessagep;
	ULONG WaitSig,signals;
	struct MsgPort *ControlPortSend;
	struct MsgPort *ReplyPort;
	CxMsg *CxMsgp;
	LONG id;
	struct NewBroker NewBroker = {
		NB_VERSION,
		"TSIcon",
		"mpaddock@cix.compulink.co.uk",
		"Generic AppIcon/Window controller",
		NBU_UNIQUE,
		COF_SHOW_HIDE,
		0,
		NULL,
		0
	};
	struct IntuiMessage *im;
	struct Message *msg;
	char *ToolType;
	char **ToolTypeArray;
	struct DiskObject *Dobj;
	BOOL PopUp;
	char **Args;
	int x;
	USHORT Selection;
	struct ANode *ANode;
	struct RexxMsg *rexxmsg;
	char *arg1;

	W_Left = WLEF;
	W_Top = WTOP;

	if (*line) {
		CliFg = TRUE;
		while (*line && (*line != ' ')) {
			++line;
		}
		while (*line == ' ') {
			++line;
		}
		_ufbs[0].ufbfh = Input();
		_ufbs[1].ufbfh = Output();
		_ufbs[2].ufbfh = Open("*", MODE_OLDFILE);
		_ufbs[0].ufbflg |= UFB_RA | O_RAW | UFB_NC;
		_ufbs[1].ufbflg |= UFB_WA | O_RAW | UFB_NC;
		_ufbs[2].ufbflg |= UFB_RA | UFB_WA | O_RAW;

		x = (_fmode) ? 0 : _IOXLAT;
		stdin->_file = 0;
		stdin->_flag = _IOREAD | x;	
		stdout->_file = 1;
		stdout->_flag = _IOWRT | x;
		stderr->_file = 2;
		stderr->_flag = _IORW | x;
	}
	else {
		CliFg = FALSE;
	}

	Forbid();
	ControlPortSend = FindPort(CPORTNAME);
	Permit();

	if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",37))) {
		exit(20); /* We can't even print error message */
	}

	if (ControlPortSend) {
		if (!(ReplyPort = CreateMsgPort())) {
			SError("Open Reply Port\n");
		}
		GoFlag = FALSE;
		if (CliFg) {
			if (!(*line) || (*line == '?') || (*line == '\n')) {
				printf("Usage: TSIcon %s\n",Template);
				SError(NULL);
			}
			if (!(RDArg = AllocDosObject(DOS_RDARGS,NULL))) {
				SError("Alloc RDArgs structure\n");
			}
			RDArg->RDA_Source.CS_Buffer = line;
			RDArg->RDA_Source.CS_Length = strlen(line);
			RDArg->RDA_Flags = RDAF_NOPROMPT;
			RDArg = ReadArgs(Template,RD_Array,RDArg);
			if (RD_Array[RD_Show] & RD_Array[RD_Hide]) {
				FreeArgs(RDArg);
				FreeDosObject(DOS_RDARGS,RDArg);
				SError("Cannot specify Show and Hide\n");
			}
			if (RD_Array[RD_Enable] & RD_Array[RD_Disable]) {
				FreeArgs(RDArg);
				FreeDosObject(DOS_RDARGS,RDArg);
				SError("Cannot specify Enable and Disable\n");
			}
			Args = (char **) RD_Array[RD_Files];
			if (RD_Array[RD_Add] & !RD_Array[RD_Remove]) {
				IconMessage.IM_Type = IMT_Add_Add;
			}
			else {
				if (RD_Array[RD_Remove] & !RD_Array[RD_Add]) {
					IconMessage.IM_Type = IMT_Remove;
				}
				else {
					IconMessage.IM_Type = IMT_Add;
				}
			}
			while (*Args) {
				IconMessage.IM_Name = *Args;
				SafePutToPort(&IconMessage,CPORTNAME,ReplyPort);
				++Args;
			}
			if (RD_Array[RD_Show]) {
				IconMessage.IM_Type = IMT_Show;
				SafePutToPort(&IconMessage,CPORTNAME,ReplyPort);
			}
			if (RD_Array[RD_Hide]) {
				IconMessage.IM_Type = IMT_Hide;
				SafePutToPort(&IconMessage,CPORTNAME,ReplyPort);
			}
			if (RD_Array[RD_Enable]) {
				IconMessage.IM_Type = IMT_Enable;
				SafePutToPort(&IconMessage,CPORTNAME,ReplyPort);
			}
			if (RD_Array[RD_Disable]) {
				IconMessage.IM_Type = IMT_Disable;
				SafePutToPort(&IconMessage,CPORTNAME,ReplyPort);
			}
			if (RD_Array[RD_Quit]) {
				IconMessage.IM_Type = IMT_Quit;
				SafePutToPort(&IconMessage,CPORTNAME,ReplyPort);
			}
			FreeArgs(RDArg);
			FreeDosObject(DOS_RDARGS,RDArg);
		}
		else {
			argmsg = WBenchMsg;
			if (argmsg->sm_NumArgs == 1) {
				IconMessage.IM_Type = IMT_Show;
				SafePutToPort(&IconMessage,CPORTNAME,ReplyPort);
			}
			else {
				wb_arg = argmsg->sm_ArgList;
				for (i = 1; (i < argmsg->sm_NumArgs); i++) {
					wb_arg++;
					dirname[0] = 0;
					if (wb_arg->wa_Lock) {
							NameFromLock(wb_arg->wa_Lock,dirname,len);
					}
					if (AddPart(dirname,wb_arg->wa_Name,len)) {
						IconMessage.IM_Type = IMT_Add;
						IconMessage.IM_Name = dirname;
						SafePutToPort(&IconMessage,CPORTNAME,ReplyPort);
					}
				}
			}
		}
		DeleteMsgPort(ReplyPort);
	}
	else {
		if (CliFg) {
			if (*line == '?') {
				printf("Usage: AnimIcon %s\n",Template1);
				SError(NULL);
			}
		}
		NewList(&IList);

		if (!(timerport = CreateMsgPort())) {
			SError("Create Timer Port\n");
		}
		if (!(timerequest = (struct timerequest *)
								  CreateIORequest(timerport,sizeof(struct timerequest)))) {
			SError("Create Time Request\n");
		}
		if (OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)timerequest,0L)) {
			SError("Open Timer Device\n");
		}

		if (!(UserPort = CreateMsgPort())) {
			SError("Create UserPort\n");
		}
		if (!(WindowPort = CreateMsgPort())) {
			SError("Create WindowPort\n");
		}

		if (!(AslBase = OpenLibrary(AslName,37))) {
			SError("Open asl.library (37)\n");
		}
		if (!(filereq = (struct FileRequest *)AllocFileRequest())) {
			SError("Can't Get FileRequest\n");
		}
		if (!(IconBase = OpenLibrary(ICONNAME,37))) {
			SError("Open icon.library (37)\n");
		}

		if (!(WorkbenchBase = OpenLibrary(WORKBENCH_NAME,37))) {
			SError("Open workbench.library (37)\n");
		}

		if (!(CxBase = OpenLibrary("commodities.library",37))) {
			SError("Open commodities.library (37)\n");
		}

		if (!(GadToolsBase = OpenLibrary("gadtools.library",37))) {
			SError("Open gadtools.library (37)\n");
		}

		if (!(GfxBase = (struct GfxBase *)OpenLibrary(GRAPHICSNAME,37))) {
			 SError("Open graphics.library (37)\n");
		}

		if (!(UtilityBase = OpenLibrary("utility.library",37))) {
			SError("Open utility.library (37)\n");
		}

		if (!(RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME,0))) {
			 SError("Open rexxsyslib.library\n");
		}

		if (!(MsgPortp = CreateMsgPort())) {
			SError("Open Message Port\n");
		}

		if (!(AppMenu = AddAppMenuItem(0,0,"Add TSIcon",MsgPortp,TAG_END))) {
			SError("Add App Menu\n");
		}

		if (!(ControlPort = CreateMsgPort())) {
			SError("Open Control Port\n");
		}

		ControlPort->mp_Node.ln_Pri = 0;
		ControlPort->mp_Node.ln_Name = CPORTNAME;

		AddPort(ControlPort);

		if (!(RexxPort = CreateMsgPort())) {
			SError("Open Rexx Port\n");
		}

		RexxPort->mp_Node.ln_Pri = 0;
		RexxPort->mp_Node.ln_Name = RPORTNAME;

		AddPort(RexxPort);

		if (!(CxPort = CreateMsgPort())) {
			SError("Open Cx Port\n");
		}

		NewBroker.nb_Port = CxPort;
		if (!(CxObjp = CxBroker(&NewBroker,NULL))) {
			SError("Create CxBroker\n");
		}

		if (CliFg) {
			if (!(RDArg = AllocDosObject(DOS_RDARGS,NULL))) {
				SError("Alloc RDArgs structure\n");
			}
			RDArg->RDA_Source.CS_Buffer = line;
			RDArg->RDA_Source.CS_Length = strlen(line);
			RDArg->RDA_Flags = RDAF_NOPROMPT;
			RDArg = ReadArgs(Template1,RD_Array,RDArg);
			Args = (char **) RD_Array[RD_Files1];
			while (*Args) {
				AddObject(*Args,FALSE);
				++Args;
			}
			if (RD_Array[RD_Show1]) {
				Show(TRUE);
			}
			if (RD_Array[RD_Disable1]) {
				IDisable();
			}
			FreeArgs(RDArg);
			FreeDosObject(DOS_RDARGS,RDArg);
		}
		else {
			argmsg = WBenchMsg;
			wb_arg = argmsg->sm_ArgList;
			for (i = 1; (i < argmsg->sm_NumArgs); i++) {
				wb_arg++;
				dirname[0] = 0;
				if (wb_arg->wa_Lock) {
					NameFromLock(wb_arg->wa_Lock,dirname,len);
				}
				if (AddPart(dirname,wb_arg->wa_Name,len)) {
					AddObject(dirname,FALSE);
				}
			}
			wb_arg = argmsg->sm_ArgList;
			PopUp = TRUE;
			if (Dobj = GetDiskObject(wb_arg->wa_Name)) {
				if (ToolType = FindToolType(Dobj->do_ToolTypes,"CX_POPUP")) {
					if (MatchToolValue(ToolType,"NO")) {
						PopUp = FALSE;
					}
				}
				ToolTypeArray = Dobj->do_ToolTypes;
				SetCxObjPri(CxObjp,ArgInt(ToolTypeArray,"CX_PRIORITY",0));
				AttachCxObj(CxObjp,HotKey(ArgString(ToolTypeArray,"CX_WPOPKEY","RALT a"),
								CxPort,CX_MESSAGE_WPOPUP));
				AttachCxObj(CxObjp,HotKey(ArgString(ToolTypeArray,"CX_POPKEY","LALT a"),
								CxPort,CX_MESSAGE_POPUP));
				while (ToolType = FindToolType(ToolTypeArray,"FILE")) {
					AddObject(ToolType,FALSE);
					while (*ToolTypeArray && (ToolType != (*ToolTypeArray + 5))) {
						++ToolTypeArray;
					}
					++ToolTypeArray;
				}
				FreeDiskObject(Dobj);
			}
			if (PopUp) {
				Show(TRUE);
			}
		}
		ActivateCxObj(CxObjp,TRUE);
	}
	if (GoFlag) {
	  timerequest->tr_node.io_Command = TR_ADDREQUEST;
	  timerequest->tr_time.tv_secs = 0;
	  timerequest->tr_time.tv_micro = 100000;
	  SendIO((struct IORequest *)timerequest);
	  while (GoFlag) {
		WaitSig = (1L << MsgPortp->mp_SigBit) | 
					 (1L << ControlPort->mp_SigBit) | 
					 (1L << CxPort->mp_SigBit) |
					 (1L << timerport->mp_SigBit) |
					 (1L << UserPort->mp_SigBit) |
					 (1L << WindowPort->mp_SigBit) |
					 (1L << RexxPort->mp_SigBit);
		if (EWin) {
			WaitSig |= (1L << EWin->UserPort->mp_SigBit);
		}
		signals = Wait(WaitSig);
		if (signals & (1L << timerport->mp_SigBit)) {
			if (msg = GetMsg(timerport)) {
				if (Active && Animated) {
					for (IN = (struct IN *)IList.lh_Head;
						  IN->IN_Node.ln_Succ;
						  IN = (struct IN *)IN->IN_Node.ln_Succ) {
						if (ANode=IN->IN_CurrANode) {
							if (!((++ANode->AN_CurrentTime)<ANode->AN_WaitTime)) {
								ANode = (struct ANode *)ANode->AN_Node.ln_Succ;
								if (!(ANode->AN_Node.ln_Succ)) {
									ANode = (struct ANode *)IN->IN_AnimList.lh_Head;
								}
								ANode->AN_CurrentTime=0;
								DrawImage(IN->IN_W->RPort,
											 (struct Image *)
											 ANode->AN_DiskObject->do_Gadget.GadgetRender,
											 IN->IN_W->WScreen->WBorLeft,
											 IN->IN_YPos);
								IN->IN_CurrANode = ANode;
							}
						}
					}
					timerequest->tr_time.tv_secs = 0;
				}
				else {
					timerequest->tr_time.tv_secs = 1;
				}
				timerequest->tr_time.tv_micro = 100000;
				SendIO((struct IORequest *)timerequest);
			}
		}
		if (signals & (1L << RexxPort->mp_SigBit)) {
			while (rexxmsg = (struct RexxMsg *)GetMsg(RexxPort)) {
				if (IsRexxMsg(rexxmsg)) {
					rexxmsg->rm_Result1 = RC_OK;
					arg1 = rexxmsg->rm_Args[0];
					while (*arg1 &&(*arg1 != ' ')) {
						++arg1;
					}
					if (*arg1) {
						*arg1 = 0;
						++arg1;
					}
					else {
						arg1 = NULL;
					}
					switch(FindCommand(rexxmsg->rm_Args[0])) {
					case RX_QUIT:
						GoFlag = FALSE;
						break;
					case RX_ADD:
						if (!arg1 || !SafeAddObject(arg1,TRUE)) {
							rexxmsg->rm_Result1 = RC_ERROR;
						}
						break;
					case RX_SHOW:
						Show(TRUE);
						break;
					case RX_ENABLE:
						IEnable();
						break;
					case RX_DISABLE:
						IDisable();
						break;
					case RX_HIDE:
						Hide();
						break;
					case RX_REMOVE:
						if (!arg1 || !DeleteObject(arg1)) {
							rexxmsg->rm_Result1 = RC_ERROR;
						}
						break;
					case RX_WSHOW:
						Show(FALSE);
						break;
					case RX_LIST:
						if (!arg1 || !ListObjects(arg1)) {
							rexxmsg->rm_Result1 = RC_ERROR;
						}
						break;
					case -1:
						if (arg1) {
							--arg1;
							*arg1 = ' ';
							arg1 = NULL;
						}
						if (!SafeAddObject(rexxmsg->rm_Args[0],FALSE)) {
							rexxmsg->rm_Result1 = RC_ERROR;
						}
						break;
					default:
						rexxmsg->rm_Result1 = RC_ERROR;
						break;
					}
					if (arg1) {
						--arg1;
						*arg1 = ' ';
					}
				}
				ReplyMsg((struct Message *)rexxmsg);
			}
		}
		if (signals & (1L << WindowPort->mp_SigBit)) {
			while (AppMessage = (struct AppMessage *)GetMsg(WindowPort)) {
				switch (AppMessage->am_Type) {
				case MTYPE_APPWINDOW:
					DoMessage(AppMessage);
					break;
				}
				ReplyMsg((struct Message *)AppMessage);
			}
		}
		if (signals & (1L << MsgPortp->mp_SigBit)) {
			while (AppMessage = (struct AppMessage *)GetMsg(MsgPortp)) {
				switch (AppMessage->am_Type) {
				case MTYPE_APPICON:
					DoMessage(AppMessage);
					break;
				case MTYPE_APPWINDOW:
				case MTYPE_APPMENUITEM:
					for (cnt = 0; cnt != AppMessage->am_NumArgs; cnt++) {
						dirname[0] = 0;
						if (AppMessage->am_ArgList[cnt].wa_Lock) {
							NameFromLock(AppMessage->am_ArgList[cnt].wa_Lock,dirname,len);
						}
						if (AppMessage->am_ArgList[cnt].wa_Name) {
							AddPart(dirname,AppMessage->am_ArgList[cnt].wa_Name,len);
						}
						SafeAddObject(dirname,FALSE);
					}
					if (EWin) {
						ActivateWindow(EWin);
					}
					break;				
				}
				ReplyMsg((struct Message *)AppMessage);
			}
		}
		if (signals & (1L << ControlPort->mp_SigBit)) {
			while (IconMessagep = (struct IconMessage *)GetMsg(ControlPort)) {
				switch(IconMessagep->IM_Type) {
				case IMT_Quit:
					GoFlag = FALSE;
					break;
				case IMT_Add:
					SafeAddObject(IconMessagep->IM_Name,FALSE);
					break;
				case IMT_Show:
					Show(TRUE);
					break;
				case IMT_Enable:
					IEnable();
					break;
				case IMT_Disable:
					IDisable();
					break;
				case IMT_Hide:
					Hide();
					break;
				case IMT_Add_Add:
					SafeAddObject(IconMessagep->IM_Name,TRUE);
					break;
				case IMT_Remove:
					DeleteObject(IconMessagep->IM_Name);
				}
				ReplyMsg((struct Message *)IconMessagep);
			}
		}
		if (signals & (1L << CxPort->mp_SigBit)) {
			while (CxMsgp = (CxMsg *)GetMsg(CxPort)) {
				id = CxMsgID(CxMsgp);
				switch (CxMsgType(CxMsgp)) {
				case CXM_COMMAND:
					switch (id) {
					case CXCMD_DISABLE:
						IDisable();
						break;
					case CXCMD_ENABLE:
						IEnable();
						break;
					case CXCMD_KILL:
						GoFlag = FALSE;
						break;
					case CXCMD_APPEAR:
						Show(TRUE);
						break;
					case CXCMD_DISAPPEAR:
						Hide();
						break;
					}
					break;
				case CXM_IEVENT:
					switch (id) {
					case CX_MESSAGE_POPUP:
						Show(TRUE);
						break;
					case CX_MESSAGE_WPOPUP:
						Show(FALSE);
						break;
					}
					break;
				}
				ReplyMsg((struct Message *)CxMsgp);
			}
		}
		if (signals & (1L << UserPort->mp_SigBit)) {
			while (im = (struct IntuiMessage *)GetMsg(UserPort)) {
				switch (im->Class) {
				case IDCMP_GADGETDOWN:
					if (DoubleClick(((struct IN *)
										  (((struct Gadget *)
											 (im->IAddress)
											)->UserData
										  )
										 )->IN_LastSeconds,
										 ((struct IN *)
										  (((struct Gadget *)
											 (im->IAddress)
											)->UserData
										  )
										 )->IN_LastMicros,
										 im->Seconds,im->Micros)) {
						ReplyMsg((struct Message *)im);
						DeleteObject(((struct IN *)
										  (((struct Gadget *)
											 (im->IAddress)
											)->UserData
										  )
										 )->IN_Node.ln_Name);
					}
					else {
						((struct IN *)
						 (((struct Gadget *)
							(im->IAddress)
						  )->UserData
						 )
						)->IN_LastSeconds=im->Seconds;
						((struct IN *)
						 (((struct Gadget *)
							(im->IAddress)
						  )->UserData
						 )
						)->IN_LastMicros=im->Micros;
						ReplyMsg((struct Message *)im);
					 }
					break;
				case IDCMP_REFRESHWINDOW:
					BeginRefresh(((struct IN *)(((struct Gadget *)
									 (im->IAddress))->UserData))->IN_W);
					EndRefresh(((struct IN *)(((struct Gadget *)
								  (im->IAddress))->UserData))->IN_W,
								  TRUE);
					ReplyMsg((struct Message *)im);
					break;
				default:
					ReplyMsg((struct Message *)im);
					break;
				}
			}
		}
		if (EWin) {
			while (im = GT_GetIMsg(EWin->UserPort)) {
				switch (im->Class) {
				struct Gadget *Gp;
				case IDCMP_CLOSEWINDOW:
					notDone = 0;
					break;
				case IDCMP_REFRESHWINDOW:
					GT_BeginRefresh(EWin);
					drawborders();
					GT_EndRefresh(EWin,TRUE);
					break;
				case IDCMP_GADGETUP:
					Gp = (struct Gadget *)(im->IAddress);
					switch (Gp->GadgetID) {
					case GAD_R_Disable:
						IDisable();
						break;
					case GAD_R_Hide:
						notDone = 0;
						break;
					case GAD_R_List:
						GT_SetGadgetAttrs(Egadlist[GAD_R_Delete],EWin,NULL,
							GA_Disabled, FALSE, TAG_END);
						OnMenu(EWin,FULL_CLOSE);
						CurrentList = im->Code+1;
						break;
					case GAD_R_Quit:
						GoFlag = FALSE;
						break;
					case GAD_R_Enable:
						IEnable();
						break;
					case GAD_R_Delete:
						Delete();
						break;
					case GAD_R_Add:
						Add();
						break;
					case GAD_R_About:
						About();
						break;
					}
					break;
				case IDCMP_VANILLAKEY:
					switch (im->Code) {
					case 'S':
					case 's':
						IDisable();
						break;
					case 'H':
					case 'h':
					case 0x1B:  /* Escape */
						notDone = 0;
						break;
					case 'i':
						Down();
						break;
					case 'I':
						Up();
						break;
					case 'Q':
					case 'q':
					GoFlag = FALSE;
						break;
					case 'E':
					case 'e':
						IEnable();
						break;
					case 'D':
					case 'd':
						Delete();
						break;
					case 'A':
					case 'a':
						Add();
						break;
					case 'B':
					case 'b':
						About();
						break; 
					}
					break;
					case IDCMP_RAWKEY:
					switch (im->Code) {
					case 0x5F:  /* Help */
						About();
						break;
					case CURSORUP:
						Up();
						break;
					case CURSORDOWN:
						Down();
						break;
					}
					break;
				case IDCMP_MENUPICK:
					Selection = im->Code;
					while (Selection != MENUNULL) {
						switch((ULONG) GTMENUITEM_USERDATA(
											ItemAddress(MyMenu,(LONG)Selection))) {
						case MM_OPEN:
							Add();
							break;
						case MM_CLOSE:
							Delete();
							break;
						case MM_ABOUT:
							About();
							break;
						case MM_HIDE:
							notDone = 0;
							break;
						case MM_QUIT:
							GoFlag = FALSE;
							break;
						case MM_ENABLED:
							if (Active) {
								IDisable();
							}
							else {
								IEnable();
							}
							break;
						}
						Selection = ((struct MenuItem *)ItemAddress(
													MyMenu,(LONG)Selection))->NextSelect;
					}
					break;
				}
				GT_ReplyIMsg(im);
			}
			if (!notDone) {
				Hide();
			}
		}
	  }
	  WaitPort(timerport);
	  GetMsg(timerport);
	  Hide();
	}
	SError(NULL);
}

void
DoMessage (struct AppMessage *AppMessage) {
	struct IN *IN;
	char buffer[257];
	short cnt;

	if (Active) {
		for (IN = (struct IN *)IList.lh_Head;
			  IN->IN_Node.ln_Succ && 
			  (IN != (struct IN *)AppMessage->am_UserData);
			  IN = (struct IN *)IN->IN_Node.ln_Succ) {
		}
		if (IN->IN_Node.ln_Succ) {
			if (AppMessage->am_NumArgs == 0) {
				DeleteObject(IN->IN_Node.ln_Name);
			}
			else {
				WinDisable();
				for (cnt = 0; cnt != AppMessage->am_NumArgs; cnt++) {
					if (AppMessage->am_ArgList[cnt].wa_Lock) {
						if (NameFromLock(AppMessage->am_ArgList[cnt].wa_Lock,buffer,len)) {
							DoIt(IN,buffer,AppMessage->am_ArgList[cnt].wa_Name);
						}
					}
					else {
						DoIt(IN,NULL,AppMessage->am_ArgList[cnt].wa_Name);
					}
				}
				WinEnable();
			}
		}
	}
}

BOOL
SafeAddObject(STRPTR ObjectName,BOOL JustAdd) {
	BOOL Succ;
	if (EWin) {
		GT_SetGadgetAttrs(Egadlist[GAD_R_List],EWin,NULL,
			GTLV_Labels, (Tag) ~0, TAG_END);
	}
	Succ=AddObject(ObjectName,JustAdd);
	if (EWin) {
		if (CurrentList) {
			GT_SetGadgetAttrs(Egadlist[GAD_R_Delete],EWin,NULL,
				GA_Disabled, FALSE, TAG_END);
			OnMenu(EWin,FULL_CLOSE);
			GT_SetGadgetAttrs(Egadlist[GAD_R_List],EWin,NULL,
				GTLV_Labels, (Tag) &IList,
				GTLV_Top, CurrentList-1,
				GTLV_Selected, CurrentList-1,
				TAG_END);
		}
		else {
			GT_SetGadgetAttrs(Egadlist[GAD_R_Delete],EWin,NULL,
				GA_Disabled, TRUE, TAG_END);
			OffMenu(EWin,FULL_CLOSE);
			GT_SetGadgetAttrs(Egadlist[GAD_R_List],EWin,NULL,
				GTLV_Labels, (Tag) &IList,
				GTLV_Selected, ~0,
				TAG_END);
		}
	}
	return(Succ);
}

BOOL
AddObject(STRPTR ObjectName,BOOL JustAdd) {
	struct IN *IN,*OldIN;
	char *filepart;
	char tfilepart[32];
	short cnt;
	ULONG ListNo;

	filepart = FilePart(ObjectName);
	if (!(*filepart)) {
		--filepart;
		--filepart;
		while ((filepart != ObjectName) && (*filepart != '/') && (*filepart != ':')) {
			--filepart;
		}
		if (filepart != ObjectName) {
			++filepart;
		}
		cnt = 0;
		while ((*filepart) && (*filepart != '/') && (*filepart != ':') && (cnt < 31)) {
			tfilepart[cnt] = *filepart;
			++cnt;
			++filepart;
		}
		tfilepart[cnt]=0;
		filepart = tfilepart;
	}
	for (OldIN = (struct IN *)IList.lh_Head,ListNo=1;
		  OldIN->IN_Node.ln_Succ &&
		  (Stricmp(OldIN->IN_Node.ln_Name,filepart)<0);
		  OldIN = (struct IN *)OldIN->IN_Node.ln_Succ,++ListNo) {
	}
	if (OldIN->IN_Node.ln_Succ && 
		 !Stricmp(OldIN->IN_Node.ln_Name,filepart)) {
		if (JustAdd) {
			return(FALSE);
		}
		else {
			return(DeleteObject(filepart));
		}
	}
	OldIN = (struct IN *)OldIN->IN_Node.ln_Pred;
	if (IN = AllocMem(sizeof(struct IN),MEMF_PUBLIC | MEMF_CLEAR)) {
		NewList(&(IN->IN_AnimList));
		if (IN->IN_Node.ln_Name = AllocMem(strlen(filepart) + 1,
															  MEMF_PUBLIC | MEMF_CLEAR)) {
			strcpy(IN->IN_Node.ln_Name,filepart);
			if (IN->IN_FName = AllocMem(strlen(ObjectName) + 1,
															 MEMF_PUBLIC | MEMF_CLEAR)) {
				strcpy(IN->IN_FName,ObjectName);
				if (IN->IN_DiskObject = GetDiskObjectNew(ObjectName)) {
					if (IN->IN_DiskObject->do_Type == WBDRAWER) {
						if (AddIcons(IN)) {
							Insert(&IList,(struct Node *)IN,
									 (struct Node *)OldIN);
							++ListCount;
							CurrentList = ListNo;
							return(TRUE);
						}
					}
					else {
						if (IN->IN_AppIcon = AddAppIcon(0,(ULONG) IN,filepart,
												MsgPortp,NULL,IN->IN_DiskObject,TAG_END)) {
							Insert(&IList,(struct Node *)IN,
									 (struct Node *)OldIN);
							++ListCount;
							CurrentList = ListNo;
							return(TRUE);
						}
					}
					FreeDiskObject(IN->IN_DiskObject);
				}
				FreeMem(IN->IN_FName,strlen(IN->IN_FName)+1);
			}
			FreeMem(IN->IN_Node.ln_Name,strlen(IN->IN_Node.ln_Name)+1);
		}
		FreeMem(IN,sizeof(struct IN));
	}
	return(FALSE);
}

BOOL
AddIcons(struct IN *IN) {
	struct Screen *WScr;
	struct DiskObject *Dobj;
	char IName[8] = "Icon.01";
	struct ANode *ANode;
	BOOL OkFlag = FALSE;
	BPTR OldLock,NewLock;

	OldLock = CurrentDir(NewLock = Lock(IN->IN_FName,ACCESS_READ));

	while (Dobj = GetDiskObjectNew(IName)) {
		OkFlag = TRUE;
		if (!(ANode = AllocMem(sizeof(struct ANode),MEMF_PUBLIC | MEMF_CLEAR))) {
			FreeDiskObject(Dobj);
			RemoveIcons(IN);
			CurrentDir(OldLock);
			UnLock(NewLock);
			SError("Allocate IN\n");
		}
		ANode->AN_DiskObject = Dobj;
		ANode->AN_WaitTime = ArgInt(Dobj->do_ToolTypes,"WAIT",1);
		AddTail(&IN->IN_AnimList,(struct Node *)ANode);
		if (IName[6] == '9') {
			++IName[5];
			IName[6] = '0';
		}
		else {
			++IName[6];
		}
	}
	CurrentDir(OldLock);
	UnLock(NewLock);
	if (!OkFlag) {
		return(FALSE);
	}
	if (WScr = (struct Screen *)LockPubScreen("Workbench")) {
		if (IN->IN_G = AllocMem(sizeof(struct Gadget),
													  MEMF_PUBLIC | MEMF_CLEAR)) {
			IN->IN_G->LeftEdge = WScr->WBorLeft;
			IN->IN_G->TopEdge = WScr->Font->ta_YSize+WScr->WBorTop+1;
			IN->IN_G->Width = ((struct ANode *)
												  IN->IN_AnimList.lh_Head)->
												  AN_DiskObject->do_Gadget.Width;
			IN->IN_G->Height = ((struct ANode *)
													IN->IN_AnimList.lh_Head)->
													AN_DiskObject->do_Gadget.Height;
			IN->IN_G->Flags = GFLG_GADGHNONE;
			IN->IN_G->Activation = GACT_IMMEDIATE;
			IN->IN_G->GadgetType = GTYP_BOOLGADGET;
			IN->IN_G->UserData = (APTR)IN;
			if (IN->IN_W = (struct Window *)OpenWindowTags(NULL,
				WA_Gadgets, IN->IN_G,
				WA_Flags,	WFLG_DRAGBAR|
								WFLG_SMART_REFRESH,
				WA_IDCMP,	0,
				WA_Left,	 ArgInt(((struct ANode *)IN->IN_AnimList.lh_Head)->
										  AN_DiskObject->do_ToolTypes,"LEFT",0),
				WA_Top,	  ArgInt(((struct ANode *)IN->IN_AnimList.lh_Head)->
										  AN_DiskObject->do_ToolTypes,"TOP",0),
				WA_Width,	  ((struct ANode *)IN->IN_AnimList.lh_Head)->
								  AN_DiskObject->do_Gadget.Width+
								  WScr->WBorLeft+WScr->WBorRight,
				WA_Height,	 ((struct ANode *)IN->IN_AnimList.lh_Head)->
								  AN_DiskObject->do_Gadget.Height+
								  WScr->Font->ta_YSize+WScr->WBorTop+1+WScr->WBorBottom,
				WA_Title,	  IN->IN_Node.ln_Name,
				WA_AutoAdjust, 1,
				WA_PubScreenName, "Workbench",
				WA_PubScreenFallBack, 1,
				TAG_END )) {
				IN->IN_W->UserPort = UserPort;
				ModifyIDCMP(IN->IN_W,IDCMP_GADGETDOWN|IDCMP_REFRESHWINDOW);
				IN->IN_AppWindow = AddAppWindow(0,(ULONG)IN,
															IN->IN_W,WindowPort,TAG_END);
				DrawImage(IN->IN_W->RPort,
							 (struct Image *)((struct ANode *)
							 IN->IN_AnimList.lh_Head)->
							 AN_DiskObject->do_Gadget.GadgetRender,
							 WScr->WBorLeft,WScr->Font->ta_YSize+WScr->WBorTop+1);
				IN->IN_YPos = WScr->Font->ta_YSize+WScr->WBorTop+1;
				IN->IN_CurrANode=(struct ANode *)
												  IN->IN_AnimList.lh_Head;
				UnlockPubScreen(NULL,WScr);
				++Animated;
				return(TRUE);
			}
			FreeMem(IN->IN_G,sizeof(struct Gadget));
		}
		UnlockPubScreen(NULL,WScr);
	}
	RemoveIcons(IN);
	return(FALSE);
}

void
RemoveIcons(struct IN *IN) {
	struct ANode *ANode;
	if (IN->IN_AppWindow) {
		RemoveAppWindow(IN->IN_AppWindow);
		IN->IN_AppWindow = NULL;
	}
	if (IN->IN_G) {
		if (IN->IN_W) {
			RemoveGadget(IN->IN_W,IN->IN_G);
		}
		FreeMem(IN->IN_G,sizeof(struct Gadget));
		IN->IN_G = NULL;
	}
	if (IN->IN_W) {
		CloseWindowSafely(IN->IN_W);
		--Animated;
		IN->IN_W = NULL;
	}
	while (IN->IN_AnimList.lh_Head->ln_Succ) {
		ANode = (struct ANode *)IN->IN_AnimList.lh_Head;
		FreeDiskObject(ANode->AN_DiskObject);
		Remove((struct Node *)ANode);
		FreeMem(ANode,sizeof(struct ANode));
	}
	IN->IN_CurrANode=NULL;
}

BOOL
DeleteObject(STRPTR filepart) {
	struct IN *IN;
	BOOL Succ;
	if (EWin) {
		GT_SetGadgetAttrs(Egadlist[GAD_R_List],EWin,NULL,
			GTLV_Labels, (Tag) ~0, TAG_END);
	}
	if (IN = (struct IN *)FindName(&IList,filepart)) {
		if (IN->IN_DiskObject->do_Type == WBDRAWER) {
			RemoveIcons(IN);
		}
		else {
			RemoveAppIcon(IN->IN_AppIcon);
		}
		FreeDiskObject(IN->IN_DiskObject);
		FreeMem(IN->IN_FName,strlen(IN->IN_FName)+1);
		FreeMem(IN->IN_Node.ln_Name,strlen(IN->IN_Node.ln_Name)+1);
		Remove((struct Node *)IN);
		FreeMem(IN,sizeof(struct IN));
		--ListCount;
		Succ=TRUE;
	}
	else {
		Succ=FALSE;
	}
	if (EWin) {
		CurrentList = 0;
		GT_SetGadgetAttrs(Egadlist[GAD_R_Delete],EWin,NULL,
			GA_Disabled, TRUE, TAG_END);
		OffMenu(EWin,FULL_CLOSE);
		GT_SetGadgetAttrs(Egadlist[GAD_R_List],EWin,NULL,
			GTLV_Labels, (Tag) &IList, 
			GTLV_Selected, ~0,
			TAG_END);
	}
	return(Succ);
}

BOOL
DoIt(struct IN *IN,char *DirName,char *FileName) {
	char FName[257];
	char Ebuffer[1001];
	short i;
	char **ToolTypeArray;
	char *ToolType;
	struct EasyStruct EasyStruct = {
		sizeof(struct EasyStruct),
		0,
		"TSIcon",
		"Error Executing Command",
		"OK",
	};
	strcpy(FName,DirName);
	if (!AddPart(FName,FileName,len)) {
		return (FALSE);
	}
	switch (IN->IN_DiskObject->do_Type) {
	case WBTOOL:
		strcpy(Ebuffer,"Run >NIL: <NIL: ");
		strcat(Ebuffer,IN->IN_FName);
		strcat(Ebuffer," \"");
		strcat(Ebuffer,FName);
		strcat(Ebuffer,"\"");
		if (!(Execute(Ebuffer,NULL,NULL))) {
			EasyRequest(NULL,&EasyStruct,NULL,NULL);
			return (FALSE);
		}
		break;
	case WBPROJECT:
	case WBDRAWER:
		if (IN->IN_DiskObject->do_Type == WBPROJECT) {
			ToolTypeArray = IN->IN_DiskObject->do_ToolTypes;
		}
		else {
			ToolTypeArray = ((struct ANode *)IN->IN_AnimList.lh_Head)->
								 AN_DiskObject->do_ToolTypes;
		}
		while (ToolType = FindToolType(ToolTypeArray,"COMMANDS")) {
			i = 0;
			while (i<1000 && *ToolType) {
				if (*ToolType == '$') {
					++ToolType;
					Ebuffer[i] = 0;
					switch (*ToolType) {
					case 'F':
					case 'f':
						if ((i += strlen(FileName))<1000) {
							strcat(Ebuffer,FileName);
						}
						break;
					case 'D':
					case 'd':
						if ((i += strlen(DirName))<1000) {
							strcat(Ebuffer,DirName);
						}
						break;
					case 'H':
					case 'h':
						if ((i += strlen(FName))<1000) {
							strcat(Ebuffer,FName);
						}
						break;
					default:
						Ebuffer[i++] = *ToolType;
					}
				}
				else {
					Ebuffer[i++] = *ToolType;
				}
				++ToolType;
			}
			if (!(i<1000 && !(Ebuffer[i]=0) && Execute(Ebuffer,NULL,NULL))) {
				EasyRequest(NULL,&EasyStruct,NULL,NULL);
				return (FALSE);
			}
			while (*ToolTypeArray && (ToolType != (*ToolTypeArray + 
																strlen("COMMANDS=")))) {
				++ToolTypeArray;
			}
			++ToolTypeArray;
		}
		break;
	}
	return (TRUE);
}

void
SError(STRPTR ErrorMessage) {
	struct Message *Message;
	struct EasyStruct EasyStruct = {
		sizeof(struct EasyStruct),
		0,
		"TSIcon Error",
		NULL,
		"OK",
	};
	struct IN *IN;
	while (IList.lh_Head->ln_Succ) {
		IN = (struct IN *)IList.lh_Head;
		DeleteObject(IN->IN_Node.ln_Name);
	}
	if (CxObjp) {
		ActivateCxObj(CxObjp,FALSE);
		DeleteCxObjAll(CxObjp);
	}
	if (CxPort) {
		Forbid();
		while (Message = GetMsg(CxPort)) {
			ReplyMsg(Message);
		}
		DeleteMsgPort(CxPort);
		Permit();
	}
	if (ControlPort) {
		Forbid();
		if (FindPort(CPORTNAME)) {
			RemPort(ControlPort);
		}
		while (Message = GetMsg(ControlPort)) {
			ReplyMsg(Message);
		}
		DeleteMsgPort(ControlPort);
		Permit();
	}
	if (RexxPort) {
		Forbid();
		if (FindPort(RPORTNAME)) {
			RemPort(RexxPort);
		}
		while (Message = GetMsg(RexxPort)) {
			ReplyMsg(Message);
		}
		DeleteMsgPort(RexxPort);
		Permit();
	}
	if (AppMenu) {
		RemoveAppMenuItem(AppMenu);
	}
	if (MsgPortp) {
		Forbid();
		while (Message = GetMsg(MsgPortp)) {
			ReplyMsg(Message);
		}
		DeleteMsgPort(MsgPortp);
		Permit();
	}
	if (RexxSysBase) {
		CloseLibrary((struct Library *)RexxSysBase);
	}
	if (UtilityBase) {
		CloseLibrary(UtilityBase);
	}
	if (GfxBase) {
		CloseLibrary((struct Library *)GfxBase);
	}
	if (GadToolsBase) {
		CloseLibrary(GadToolsBase);
	}
	if (CxBase) {
		CloseLibrary(CxBase);
	}
	if (WorkbenchBase) {
		CloseLibrary(WorkbenchBase);
	}
	if (IconBase) {
		CloseLibrary(IconBase);
	}
	if (filereq) {
		FreeFileRequest(filereq);
	}
	if (AslBase) {
		CloseLibrary(AslBase);
	}
	if (WindowPort) {
		DeleteMsgPort(WindowPort);
	}
	if (UserPort) {
		DeleteMsgPort(UserPort);
	}
	if (timerequest) {
		timerequest->tr_node.io_Message.mn_ReplyPort = NULL;
		CloseDevice((struct IORequest *)timerequest);
		DeleteIORequest((struct IORequest *)timerequest);
	}
	if(timerport) {
		DeleteMsgPort(timerport);
	}
	if (ErrorMessage) {
		if (CliFg) {
			printf(ErrorMessage);
		}
		else {
			if (IntuitionBase) {
				EasyStruct.es_TextFormat = ErrorMessage;
				EasyRequest(NULL,&EasyStruct,NULL,NULL);
			}
		}
		if (IntuitionBase) {
			CloseLibrary((struct Library *)IntuitionBase);
		}
		exit(20);
	}
	else {
		if (IntuitionBase) {
			CloseLibrary((struct Library *)IntuitionBase);
		}
		exit(0);
	}
}

BOOL
SafePutToPort(struct IconMessage *message, STRPTR portname,
				struct MsgPort *ReplyPort) {

	struct MsgPort *port;
	message->IM_Message.mn_Node.ln_Type = NT_MESSAGE;
	message->IM_Message.mn_Length = sizeof(struct IconMessage);
	message->IM_Message.mn_ReplyPort = ReplyPort;
	Forbid();
	port = FindPort(portname);
	if (port) {
		PutMsg(port,(struct Message *)message);
	}
	Permit();
	if (port) {
		while (!GetMsg(ReplyPort)) {
		WaitPort(ReplyPort);
		}
		while (GetMsg(ReplyPort)) {
		} 
	}
	return((BOOL)port);
}

struct Gadget *
InitGads(struct Screen *Scr) {
	struct Gadget *gad;
	short i;
	struct NewGadget *ng;

	EGList = NULL;

	if (!(VisInfo = GetVisualInfo(Scr, TAG_END))) {
		return(NULL);
	}

	for (i = 0, ng = NGAry;
			i < sizeof(NGAry)/sizeof(NGAry[0]);
			++i, ++ng)
	{
		ng->ng_VisualInfo = VisInfo;
		ng->ng_TextAttr	= Scr->Font;
	}
	if (!(gad = CreateContext(&EGList))) {
		return(NULL);
	}

	(NG_R_Disable)->ng_TopEdge=GTOP_0+Scr->Font->ta_YSize-8;
	if (!(Gad_R_Disable = gad = Egadlist[GAD_R_Disable] =
			CreateGadget(BUTTON_KIND, gad, NG_R_Disable,
							 GT_Underscore, '_',
							 TAG_END))) {
		return(NULL);
	}
	gad->UserData = (APTR) BUTTON_KIND;

	(NG_R_Hide)->ng_TopEdge=GTOP_1+Scr->Font->ta_YSize-8;
	if (!(Gad_R_Hide = gad = Egadlist[GAD_R_Hide] =
			CreateGadget(BUTTON_KIND, gad, NG_R_Hide,
							 GT_Underscore, '_',
			TAG_END))) {
		return(NULL);
	}
	gad->UserData = (APTR) BUTTON_KIND;

	(NG_R_List)->ng_TopEdge=GTOP_2+((Scr->Font->ta_YSize)<<1)-16;
	if (!(Gad_R_List = gad = Egadlist[GAD_R_List] =
			CreateGadget(LISTVIEW_KIND, gad, NG_R_List,
							 GTLV_Labels, &IList,
							 GTLV_Selected, ~0,
							 GTLV_ShowSelected, NULL,
							 LAYOUTA_Spacing, 2,
							 GT_Underscore, '_',
							 TAG_END))) {
		return(NULL);
	}
	gad->UserData = (APTR) LISTVIEW_KIND;

	(NG_R_Quit)->ng_TopEdge=GTOP_3+Scr->Font->ta_YSize-8;
	if (!(Gad_R_Quit = gad = Egadlist[GAD_R_Quit] =
		CreateGadget(BUTTON_KIND, gad, NG_R_Quit,
						 GT_Underscore, '_',
						 TAG_END))) {
		return(NULL);
	}
	gad->UserData = (APTR) BUTTON_KIND;

	(NG_R_Enable)->ng_TopEdge=GTOP_4+Scr->Font->ta_YSize-8;
	if (!(Gad_R_Enable = gad = Egadlist[GAD_R_Enable] =
			CreateGadget(BUTTON_KIND, gad, NG_R_Enable,
							 GT_Underscore, '_',
							 TAG_END))) {
		return(NULL);
	}
	gad->UserData = (APTR) BUTTON_KIND;

	(NG_R_Delete)->ng_TopEdge=GTOP_5+(Scr->Font->ta_YSize<<1)-16;
	if (!(Gad_R_Delete = gad = Egadlist[GAD_R_Delete] =
			CreateGadget(BUTTON_KIND, gad, NG_R_Delete,
			GT_Underscore, '_',
			TAG_END))) {
		return(NULL);
	}
	gad->UserData = (APTR) BUTTON_KIND;

	(NG_R_Add)->ng_TopEdge=GTOP_6+(Scr->Font->ta_YSize<<1)-16;
	if (!(Gad_R_Add = gad = Egadlist[GAD_R_Add] =
			CreateGadget(BUTTON_KIND, gad, NG_R_Add,
							 GT_Underscore, '_',
							 TAG_END))) {
		return(NULL);
	}
	gad->UserData = (APTR)	BUTTON_KIND;

	(NG_R_About)->ng_TopEdge=GTOP_7+(Scr->Font->ta_YSize<<1)-16;
	if (!(Gad_R_About = gad = Egadlist[GAD_R_About] =
			CreateGadget(BUTTON_KIND, gad, NG_R_About,
			GT_Underscore, '_',
			TAG_END))) {
		return(NULL);
	}
	gad->UserData = (APTR) BUTTON_KIND;

	return(EGList);
}

void
drawborders(void) {
	DrawBevelBox(EWin->RPort, BLEF_0, BTOP_0+Scr->Font->ta_YSize-8, BWID_0, BHEI_0,
				GT_VisualInfo, VisInfo,
				TAG_END);
}

void
FreeGads(void) {
	if (EGList) {
		FreeGadgets(EGList);
		EGList = NULL;
	}
	if (VisInfo) {
		FreeVisualInfo(VisInfo);
		VisInfo = NULL;
	}
}

void
About(void) {
	struct EasyStruct EasyStruct = {
		sizeof(struct EasyStruct),
		0,
		"TSIcon Info",
		"TSIcon\nGeneric AppIcon/Window Controller\nmpaddock@cix.compulink.co.uk\nV1.00 9/6/93",
		"OK",
	};
	WinDisable();
	EasyRequest(NULL,&EasyStruct,NULL,NULL);
	WinEnable();
}

void
DeleteNum(ULONG Num) {
	ULONG i;
	struct IN *IN = (struct IN *) IList.lh_Head;
	for (i = 1; i != Num; i++) {
		IN = (struct IN *) (IN->IN_Node.ln_Succ);
	}
	DeleteObject(IN->IN_Node.ln_Name);
}

void
Show(BOOL defaultscreen) {
	if (EWin) {
		ScreenToFront(Scr);
		WindowToFront(EWin);
		ActivateWindow(EWin);
		if (EWin->Height == Scr->Font->ta_YSize+Scr->WBorTop+1) {
			ZipWindow(EWin);
		}
		return;
	}
	if (defaultscreen) {
		Scr = LockPubScreen(NULL);
	}
	else {
		Scr = LockPubScreen("Workbench");
	}
	if (Scr) {
		if (gadgets = InitGads(Scr)) {
			WA_Zoom_TAG[3] = Scr->Font->ta_YSize+Scr->WBorTop+1;
			if (EWin = OpenWindowTags(NULL,
				WA_Flags,	WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_REPORTMOUSE|WFLG_ACTIVATE,
				WA_IDCMP,	LISTVIEWIDCMP|BUTTONIDCMP|IDCMP_VANILLAKEY|IDCMP_RAWKEY|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW|IDCMP_MENUPICK,
				WA_Left,		W_Left,
				WA_Top,		W_Top,
				WA_Width,	WWID,
				WA_Height,	WHEI+(Scr->Font->ta_YSize<<1)-16,
				WA_Title,	"TSIcon",
				WA_MinWidth,WWID,
				WA_MinHeight,Scr->Font->ta_YSize+Scr->WBorTop+1,
				WA_MaxWidth,WWID,
				WA_MaxHeight,WHEI,
				WA_AutoAdjust,1,
				WA_PubScreen,Scr,
				WA_Gadgets,	gadgets,
				WA_Zoom,		WA_Zoom_TAG,
				TAG_END )) {
				drawborders();
				GT_RefreshWindow(EWin,NULL);
				GT_SetGadgetAttrs(Egadlist[GAD_R_Enable],EWin,NULL,
					GA_Disabled, Active, TAG_END);
				GT_SetGadgetAttrs(Egadlist[GAD_R_Disable],EWin,NULL,
					GA_Disabled, !Active, TAG_END);
				AppWindowp = AddAppWindow(0,0,EWin,MsgPortp,TAG_END);
				CurrentList = 0;
				GT_SetGadgetAttrs(Egadlist[GAD_R_Delete],EWin,NULL,
					GA_Disabled, TRUE, TAG_END);
				MyNewMenu[MM_CLOSE_NUM].nm_Flags = NM_ITEMDISABLED;
				if (Active) {
					MyNewMenu[MM_ENABLED_NUM].nm_Flags |= CHECKED;
				}
				else {
					MyNewMenu[MM_ENABLED_NUM].nm_Flags &= ~CHECKED;
				}
				if (MyMenu = CreateMenus(MyNewMenu,GTMN_FullMenu,TRUE,TAG_END)) {
					if (LayoutMenus(MyMenu,VisInfo,TAG_END)) {
						if (SetMenuStrip(EWin,MyMenu)) {
							notDone = 1;
							return;
						}
					}
				}
			}
		}
	}
	Hide();
}

void
Hide(void) {
	if (EWin) {
		W_Left = EWin->LeftEdge;
		W_Top = EWin->TopEdge;
		if (MyMenu) {
			ClearMenuStrip(EWin);
			FreeMenus(MyMenu);
			MyMenu = NULL;
		}
		if (AppWindowp) {
			RemoveAppWindow(AppWindowp);
			AppWindowp=NULL;
		}
		CloseWindow(EWin);
		EWin=NULL;
	}
	FreeGads();
	if (Scr) {
		UnlockPubScreen(NULL,Scr);
		Scr=NULL;
	}
	notDone = 0;
}

void
Down(void) {
	++CurrentList;
	if (CurrentList > ListCount) {
		CurrentList = ListCount;
	}
	GT_SetGadgetAttrs(Egadlist[GAD_R_Delete],EWin,NULL,
		GA_Disabled, FALSE, TAG_END);
	OnMenu(EWin,FULL_CLOSE);
	GT_SetGadgetAttrs(Egadlist[GAD_R_List],EWin,NULL,
		GTLV_Labels, (Tag) ~0, TAG_END);
	GT_SetGadgetAttrs(Egadlist[GAD_R_List],EWin,NULL,
		GTLV_Labels, (Tag) &IList,
		GTLV_Top, CurrentList-1,
		GTLV_Selected, CurrentList-1, TAG_END);
}

void
Up(void) {
	if (CurrentList) {
		--CurrentList;
	}
	if (CurrentList == 0) {
		CurrentList = 1;
	}
	GT_SetGadgetAttrs(Egadlist[GAD_R_Delete],EWin,NULL,
		GA_Disabled, FALSE, TAG_END);
	OnMenu(EWin,FULL_CLOSE);
	GT_SetGadgetAttrs(Egadlist[GAD_R_List],EWin,NULL,
		GTLV_Labels, (Tag) ~0, TAG_END);
	GT_SetGadgetAttrs(Egadlist[GAD_R_List],EWin,NULL,
		GTLV_Labels, (Tag) &IList, 
		GTLV_Top, CurrentList-1,
		GTLV_Selected, CurrentList-1, TAG_END);
}

void
Add(void) {
	char dirname[257];
	WinDisable();
	if (AslRequestTags((APTR) filereq,ASL_Hail,(Tag) "Add TSIcon",TAG_DONE)) {
		strncpy(dirname,filereq->rf_Dir,len);
		if (AddPart(dirname,filereq->rf_File,len)) {
			SafeAddObject(dirname,FALSE);
		}
	}
	WinEnable();
}

void
Delete(void) {
	if (CurrentList) {
		DeleteNum(CurrentList);
	}
}

void
IEnable(void) {
	struct MenuItem *MI;
	ActivateCxObj(CxObjp,TRUE);
	Active = TRUE;
	if (EWin) {
		GT_SetGadgetAttrs(Egadlist[GAD_R_Enable],EWin,NULL,
			GA_Disabled, Active, TAG_END);
		GT_SetGadgetAttrs(Egadlist[GAD_R_Disable],EWin,NULL,
			GA_Disabled, !Active, TAG_END);
		ClearMenuStrip(EWin);
		MI = (struct MenuItem *)ItemAddress(MyMenu,FULL_ENABLED);
		MI->Flags |= CHECKED;
		ResetMenuStrip(EWin,MyMenu);
	}
}

void
IDisable(void) {
	struct MenuItem *MI;
	ActivateCxObj(CxObjp,FALSE);
	Active = FALSE;
	if (EWin) {
		GT_SetGadgetAttrs(Egadlist[GAD_R_Enable],EWin,NULL,
			GA_Disabled, Active, TAG_END);
		GT_SetGadgetAttrs(Egadlist[GAD_R_Disable],EWin,NULL,
			GA_Disabled, !Active, TAG_END);
		MI = (struct MenuItem *)ItemAddress(MyMenu,FULL_ENABLED);
		MI->Flags &= ~CHECKED;
		ResetMenuStrip(EWin,MyMenu);
	}
}

void
CloseWindowSafely(struct Window *win) {
	Forbid();
	StripIntuiMessages(win->UserPort,win);
	win->UserPort = NULL;
	ModifyIDCMP(win,0);
	Permit();
	CloseWindow(win);
}

void
StripIntuiMessages(struct MsgPort *mp,struct Window *win) {
	struct IntuiMessage *msg, *succ;
	msg = (struct IntuiMessage *)mp->mp_MsgList.lh_Head;
	while(succ = (struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ) {
		if(msg->IDCMPWindow == win) {
			Remove((struct Node *)msg);
			ReplyMsg((struct Message *)msg);
		}
		msg = succ;
	}
}

ULONG OldIDCMP;

void
WinDisable(void) {
	short cnt;
	if (EWin) {
		OldIDCMP = EWin->IDCMPFlags;
		ModifyIDCMP(EWin,IDCMP_REFRESHWINDOW);
		OffMenu(EWin,FULLMENUNUM(0,NOITEM,NOSUB));
		OffMenu(EWin,FULLMENUNUM(1,NOITEM,NOSUB));
		SetPointer(EWin, BusyPointerData, 16, 16, -6, 0);
		for (cnt = 0; cnt < ALLGADS; cnt++) {
			if (cnt != GAD_R_List) {
				GT_SetGadgetAttrs(Egadlist[cnt],EWin,NULL,
					GA_Disabled, TRUE,
					TAG_END);
			}
		}
	}
}

void
WinEnable(void) {
	short cnt;
	if (EWin) {
		OnMenu(EWin,FULLMENUNUM(0,NOITEM,NOSUB));
		OnMenu(EWin,FULLMENUNUM(1,NOITEM,NOSUB));
		ClearPointer(EWin);
		for (cnt = 0; cnt < ALLGADS; cnt++) {
			if ((cnt != GAD_R_Enable) && (cnt != GAD_R_List)) {
				GT_SetGadgetAttrs(Egadlist[cnt],EWin,NULL,
					GA_Disabled, FALSE,
					TAG_END);
			}
		}
		ModifyIDCMP(EWin,OldIDCMP);
		GT_SetGadgetAttrs(Egadlist[GAD_R_Enable],EWin,NULL,
			GA_Disabled, Active, TAG_END);
		GT_SetGadgetAttrs(Egadlist[GAD_R_Disable],EWin,NULL,
			GA_Disabled, !Active, TAG_END);
		if (!ListCount) {
			GT_SetGadgetAttrs(Egadlist[GAD_R_Delete],EWin,NULL,
				GA_Disabled, TRUE, TAG_END);
			OffMenu(EWin,FULL_CLOSE);
		}
	}
}

int
FindCommand(char *command) {
	int i;
	for(i = 0; i != COMMAND_END; i++) {
		if (!Stricmp(command,CommandEntry[i].CommandName)) {
			return(i);
		}
	}
	return(-1);
}

BOOL
ListObjects(char *FileName) {
	BPTR file;
	struct IN *IN;
	if (file = Open(FileName,MODE_NEWFILE)) {
		for (IN = (struct IN *)IList.lh_Head;
			IN->IN_Node.ln_Succ;
			IN = (struct IN *)IN->IN_Node.ln_Succ) {
			Write(file,IN->IN_FName,strlen(IN->IN_FName));
			Write(file,"\n",strlen("\n"));
		}
		Close(file);
		return(TRUE);
	}
	return(FALSE);
}
