/*
Auto:		smake	ForceIcon
*/

/* $Revision Header built automatically *************** (do not edit) ************
**
** © Copyright by GuntherSoft
**
** File             : SnakeSYS:CPrgs/Utils/ForceIcon.c
** Created on       : Wednesday, 20.10.93 15:55:50
** Created by       : Kai Iske
** Current revision : V1.0
**
**
** Purpose
** -------
**   - Forces Disk Icons to a specified position.
**     Usefull for CD-Rom users
**
** Revision V1.0
** --------------
** created on Wednesday, 20.10.93 15:55:50  by  Kai Iske.   LogMessage :
**     --- Initial release ---
**
*********************************************************************************/



/**********************************************************************/
/*                        External references                         */
/**********************************************************************/
extern struct	Window		*MainWinHandle;		// Window handles
extern struct	Window		*EditWinHandle;
extern struct	Window		*PosWinHandle;
extern struct	Window		*ManWinHandle;





/**********************************************************************/
/*                           Library bases                            */
/**********************************************************************/
struct	ExecBase	*SysBase;
struct	IntuitionBase	*IntuitionBase	= NULL;
struct	Library		*DiskfontBase	= NULL;
struct	GfxBase		*GfxBase	= NULL;
struct	Library		*GadToolsBase	= NULL;
struct	DosLibrary	*DOSBase	= NULL;
struct	Library		*IconBase	= NULL;
struct	Library		*UtilityBase	= NULL;
struct	Library		*CxBase		= NULL;
struct	Library		*IFFParseBase	= NULL;
struct	Library		*AslBase	= NULL;






/**********************************************************************/
/*                         Broker Definition                          */
/**********************************************************************/
struct NewBroker BrokerDef =
{
	NB_VERSION,
	"ForceIcon",
	"ForceIcon v"REVISION,
	"Forces icons to abolute position",
	NBU_NOTIFY|NBU_UNIQUE,
	COF_SHOW_HIDE,
	0,
	NULL,
	0
};



/**********************************************************************/
/*                        Commandline template                        */
/**********************************************************************/
static const char	*Template = "CX_PRIORITY/K/N,CX_POPUP/K,CX_POPKEY/K";
enum	{PRI_ARG, POP_ARG, KEY_ARG, LAST_ARG};


/**********************************************************************/
/*                         "No-StartUp vars"                          */
/**********************************************************************/
static const char	_VER[] = "\0$VER: ForceIcon "REVISION" ("REVDATE")\0";
char	_ProgramName[] = "ForceIcon";
LONG	_OSERR = 0;

/**********************************************************************/
/*                          Global variables                          */
/**********************************************************************/
static	ULONG	__asm (*OldGetIcon)(register __a0 UBYTE *, register __a1 struct DiskObject *, register __a2 struct FreeList *, register __a6 struct Library *);
static	ULONG	__asm (*OldLock)(register __d1 UBYTE *, register __d2 ULONG, register __a6 struct DosLibrary *);

struct	List		VolumeList;			// List of patched volumes
struct	SignalSemaphore	MySemaphore;			// My beautiful semaphore
struct	WBStartup	*_WBenchMsg	= NULL;		// StartUp message
struct	IClass		*GetFileClass;			// ImageClass for GetFile
static	UWORD	Active = TRUE;				// State of Broker





/**********************************************************************/
/*                      This is our main program                      */
/**********************************************************************/
ULONG __saveds main(void)
{
	struct	Class		*InitGetFile(void);
	struct	Process		*MyProc;
	struct	MsgPort		*BrokerPort;
	CxObj			*InputBroker;
	CxObj			*InputKey;
	ULONG			Error, Pri = 0;
	char			HotKeyDef[128];
	BOOL			PopUp = TRUE;

		// Get SysBase

	SysBase	= *((struct ExecBase **)0x4L);

		// Get address of our process

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

		// Determine where we were started from

	if(!MyProc->pr_CLI)
		_WBenchMsg = (struct WBStartup *)GetMsg(&MyProc->pr_MsgPort);

		// Initialize our semaphore

	InitSemaphore(&MySemaphore);

		// Open libraries

	if(OpenAll())
	{
			// Check for tooltypes or Commandline args

		if(CheckToolTypes(HotKeyDef, &Pri, &PopUp))
		{
			if((GetFileClass = (struct IClass *)InitGetFile()))
			{
					// Load in preferences

				LoadPrefs();

					// Create our Message Port for the Broker

				if((BrokerPort = CreateMsgPort()))
				{
						// Set up additional fields within broker structure

					BrokerDef.nb_Port	= BrokerPort;
					BrokerDef.nb_Pri	= Pri;

						// Create broker

					if((InputBroker = CxBroker(&BrokerDef, (LONG *)&Error)))
					{
							// Create HotKey

						if((InputKey = HotKey(HotKeyDef, BrokerPort, POPKEY)))
						{
								// Attach HotKey to Broker

							AttachCxObj(InputBroker, InputKey);

								// Activate Broker

							ActivateCxObj(InputBroker, TRUE);

							Forbid();
								// Patch icon.library functions

							OldGetIcon		= (ULONG *)SetFunction(IconBase, -0x0000002a, &MyGetIcon);

								// Patch dos.library functions

							OldLock			= (ULONG *)SetFunction(DOSBase, -0x00000054, &MyLock);
							Permit();

								// PopUp main window ???

							if(PopUp)
								OpenMainWin();

								// Handle all inputs

							HandleInput(BrokerPort, InputBroker);


							Forbid();
								// Reinstall old icon.library functions

							SetFunction(IconBase, -0x0000002a, OldGetIcon);

								// Restore DOS-Library functions

							SetFunction(DOSBase, -0x00000054, OldLock);
							Permit();
						}

							// Dispose Broker

						DeleteCxObjAll(InputBroker);
					}

						// Remove Msg-Port

					DeleteMsgPort(BrokerPort);
				}
					// Free list of patches

				FreeDevVolList(&VolumeList);

					// Dispose GetFile class

				FreeClass(GetFileClass);
			}
			else
				DisplayError(ERR_NOFILE, NULL);
		}
	}

		// Close libs

	CloseAll();

		// Send back WBStartUp Message

	if(_WBenchMsg)
	{
		Forbid();
		ReplyMsg((struct Message *)_WBenchMsg);
	}
	return(0);
}


/**********************************************************************/
/*                        Functionreplacements                        */
/**********************************************************************/
void chkabort(void){;}
void __stdargs _XCEXIT(LONG Val){;}






/**********************************************************************/
/*                        Check for ToolTypes                         */
/**********************************************************************/
BOOL CheckToolTypes(char *HotKeyDef, ULONG *Pri, BOOL *PopUp)
{
		// set default PopUp HotKey

	strcpy(HotKeyDef, "lalt lshift i");


		// Did we come from WB ???

	if(_WBenchMsg)
	{
		struct	WBArg		*MyArg = _WBenchMsg->sm_ArgList;
		struct	DiskObject	*MyObj;
		char	**ToolTypes, *ThisTool;

			// Switch to currentdir

		CurrentDir(MyArg->wa_Lock);

			// Try to get our icon

		if((MyObj = GetDiskObjectNew(MyArg->wa_Name)))
		{
				// Get tooltypes

			if((ToolTypes = MyObj->do_ToolTypes))
			{
					// Parse ToolTypes

				if((ThisTool = FindToolType(ToolTypes, "CX_PRIORITY")))
				{
					char	*Dummy;

					*Pri = strtol(ThisTool, &Dummy, 10);
				}

				if((ThisTool = FindToolType(ToolTypes, "CX_POPUP")))
					*PopUp = !(MatchToolValue(ThisTool, "NO"));

				if((ThisTool = FindToolType(ToolTypes, "CX_POPKEY")))
					strncpy(HotKeyDef, ThisTool, 127);
			}

				// Free our DiskObject again

			FreeDiskObject(MyObj);
		}
		return(TRUE);
	}
	else
	{
		APTR	*Args;
		struct	RDArgs	*MyRDArgs;
		BOOL	GoOn = FALSE;

			// Try to allocate buffer for ReadArgs

		if((Args = AllocVec((sizeof(ULONG) * LAST_ARG), MEMF_CLEAR)))
		{
				// Parse commandline

			if((MyRDArgs = ReadArgs((char *)Template, (LONG *)Args, NULL)))
			{
				GoOn = TRUE;

				if(Args[PRI_ARG])
					*Pri = *(ULONG *)Args[PRI_ARG];

				if(Args[POP_ARG])
				{
					if(!stricmp(Args[POP_ARG], "NO"))
						*PopUp = FALSE;
				}

				if(Args[KEY_ARG])
					strncpy(HotKeyDef, Args[KEY_ARG], 127);

				FreeArgs(MyRDArgs);
			}
			else
				PrintFault(IoErr(), "ForceIcon ");

			FreeVec(Args);
		}
		else
			PrintFault(ERROR_NO_FREE_STORE, "ForceIcon ");

		return(GoOn);
	}
}







/**********************************************************************/
/*                      My new GetIcon function                       */
/**********************************************************************/
ULONG __saveds __asm MyGetIcon(register __a0 UBYTE *Name, register __a1 struct DiskObject *DObj, register __a2 struct FreeList *FList, register __a6 struct Library *IconBase)
{
	struct	Process		*MyProc = (struct Process *)FindTask(NULL);
	ULONG	RetVal;

		// Calling process a real process and is it Workbench ?

	if((MyProc->pr_Task.tc_Node.ln_Type == NT_PROCESS) && !strcmp(MyProc->pr_Task.tc_Node.ln_Name, "Workbench"))
	{
			if(!stricmp(Name, "Disk"))
				RetVal = DoForce(Name, DObj, FList, IconBase);
			else
				RetVal = OldGetIcon(Name, DObj, FList, IconBase);
	}
	else
		RetVal = OldGetIcon(Name, DObj, FList, IconBase);

	return(RetVal);
}






/**********************************************************************/
/*                       Main forcement routine                       */
/**********************************************************************/
ULONG __asm DoForce(register __a0 UBYTE *Name, register __a1 struct DiskObject *DObj, register __a2 struct FreeList *FList, register __a6 struct Library *IconBase)
{
	struct	FileLock	*Dir;
	struct	DosList		*DList;
	char	VolName[130], DevName[130];
	BPTR	MyLock, CheckLock;
	ULONG	RetVal = 0;
	BOOL	Found = FALSE;

		// Get our semaphore

	ObtainSemaphore(&MySemaphore);

		// Are we active ???

	if(Active)
	{
			// Switch to current dir

		MyLock	= CurrentDir(NULL);
		Dir	= (struct FileLock *)BADDR(MyLock);
		DList	= (struct DosList *)BADDR(Dir->fl_Volume);

			// Get name of volume inserted

		setmem(VolName, 130, 0);
		setmem(DevName, 130, 0);
		strncpy(VolName, ((char *)BADDR(DList->dol_Name) + 1), *((char *)BADDR(DList->dol_Name)));

			// Reset current dir

		CurrentDir(MyLock);

			// Get Name of Device

		if((DList = LockDosList(LDF_DEVICES|LDF_READ)))
		{
			while((DList = NextDosEntry(DList, LDF_DEVICES|LDF_READ)))
			{
				if(Dir->fl_Task == DList->dol_Task)
					strncpy(DevName, ((char *)BADDR(DList->dol_Name) + 1), *((char *)BADDR(DList->dol_Name)));
			}
			UnLockDosList(LDF_DEVICES|LDF_READ);
		}

			// Really to load from ROOT ???

		if(!(CheckLock = ParentDir(MyLock)))
		{
				// Do we have patches waiting ???

			if(!IsListEmpty(&VolumeList))
			{
				struct	VolEntry	*ThisEntry = (struct VolEntry *)VolumeList.lh_Head;

				do
				{
						// This one to patch ???

					if(ThisEntry->Link.ln_Type == LDF_DEVICES && !stricmp(ThisEntry->VolName, DevName))
						Found = TRUE;

					else if(ThisEntry->Link.ln_Type == LDF_VOLUMES && !stricmp(ThisEntry->VolName, VolName))
						Found = TRUE;

					else
						ThisEntry = (struct VolEntry *)ThisEntry->Link.ln_Succ;

				} while(!Found && ThisEntry->Link.ln_Succ);

					// Object to be patched ?

				if(Found)
				{
						// Alternative icon ???

					if(ThisEntry->UseAlt)
					{
						char	*End;

							// Check for name and remove extension

						strcpy(VolName, ThisEntry->IconName);
						strlwr(VolName);
						if((End = strstr(VolName, ".info")))
						{
							BPTR	TestLock;

							setmem(VolName, 130, 0);
							strncpy(VolName, ThisEntry->IconName, (End - VolName));

								// Try to get supplied name

							if((TestLock = Lock(ThisEntry->IconName, ACCESS_READ)))
							{
								UnLock(TestLock);

									// Try to read in this icon

								if(!(RetVal = OldGetIcon(VolName, DObj, FList, IconBase)))
									RetVal = OldGetIcon(Name, DObj, FList, IconBase);
								else
								{
										// Ok, we`ve loaded a new icon, so set appropriate flags ;)

									if(DObj->do_Type == WBTOOL || DObj->do_Type == WBPROJECT)
									{
											// Try to set drawerdata for tool and project icons

										if((DObj->do_DrawerData = AllocMem(sizeof(struct DrawerData), MEMF_CLEAR|MEMF_PUBLIC)))
										{
											struct	DrawerData	*DDat = DObj->do_DrawerData;

												// Fill in structure

											DDat->dd_NewWindow.LeftEdge	= ThisEntry->LeftEdge;
											DDat->dd_NewWindow.TopEdge	= ThisEntry->TopEdge;
											DDat->dd_NewWindow.Width	= ThisEntry->Width;
											DDat->dd_NewWindow.Height	= ThisEntry->Height;
											DDat->dd_NewWindow.DetailPen	= 255;
											DDat->dd_NewWindow.BlockPen	= 255;
											DDat->dd_NewWindow.Flags	= WFLG_HASZOOM|WFLG_WINDOWTICKED|WFLG_REPORTMOUSE|WFLG_SIMPLE_REFRESH|WFLG_SIZEBRIGHT|WFLG_SIZEBBOTTOM|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_DRAGBAR|WFLG_SIZEGADGET;
											DDat->dd_NewWindow.MinWidth	= 90;
											DDat->dd_NewWindow.MinHeight	= 40;
											DDat->dd_NewWindow.MaxWidth	= 0xffff;
											DDat->dd_NewWindow.MaxHeight	= 0xffff;

												// A Ok, set new type of icon

											DObj->do_Type = WBDISK;
										}
									}
									else
										DObj->do_Type = WBDISK;
								}
							}
							else
								RetVal = OldGetIcon(Name, DObj, FList, IconBase);
						}
						else
							RetVal = OldGetIcon(Name, DObj, FList, IconBase);
					}
					else
						RetVal = OldGetIcon(Name, DObj, FList, IconBase);

						// Patch position ???

					if(RetVal)
					{
						struct	Screen	*WBScreen	= LockPubScreen("Workbench");

						if(WBScreen)
						{
								// Do so

							DObj->do_CurrentX = (ThisEntry->IconPos) ? ThisEntry->Left : NO_ICON_POSITION;
							DObj->do_CurrentY = (ThisEntry->IconPos) ? ThisEntry->Top - WBScreen->BarHeight - 1 : NO_ICON_POSITION;

							UnlockPubScreen(NULL, WBScreen);
						}
					}
				}
			}
		}
		else
			UnLock(CheckLock);
	}

		// No entry found and not the orig. icon read -> use supplied name

	if(!Found && !RetVal)
		RetVal = OldGetIcon(Name, DObj, FList, IconBase);

		// Release that fine semaphore

	ReleaseSemaphore(&MySemaphore);

	return(RetVal);
}





/**********************************************************************/
/*                        My new Lock routine                         */
/**********************************************************************/
ULONG __saveds __asm MyLock(register __d1 UBYTE *Name, register __d2 ULONG Mode, register __a6 struct DosLibrary *DOSBase)
{
	struct	Process		*MyProc = (struct Process *)FindTask(NULL);
	struct	FileLock	*Dir;
	struct	DosList		*DList;
	char	VolName[130], DevName[130];
	BPTR	MyLock, CheckLock;
	ULONG	RetVal;
	BOOL	Found = FALSE;


		// Calling process a real process and is it Workbench ?

	if((MyProc->pr_Task.tc_Node.ln_Type == NT_PROCESS) && !strcmp(MyProc->pr_Task.tc_Node.ln_Name, "Workbench"))
	{
			// Trying to load a Disk.info ???

		if(!stricmp(Name, "Disk.info"))
		{
				// Get my semaphore

			ObtainSemaphore(&MySemaphore);

				// Broker active ???

			if(Active)
			{
					// Switch to current dir

				MyLock	= CurrentDir(NULL);
				Dir	= (struct FileLock *)BADDR(MyLock);
				DList	= (struct DosList *)BADDR(Dir->fl_Volume);

					// Get name of volume inserted

				setmem(VolName, 130, 0);
				setmem(DevName, 130, 0);
				strncpy(VolName, ((char *)BADDR(DList->dol_Name) + 1), *((char *)BADDR(DList->dol_Name)));

					// Reset current dir

				CurrentDir(MyLock);

					// Get Name of Device

				if((DList = LockDosList(LDF_DEVICES|LDF_READ)))
				{
					while((DList = NextDosEntry(DList, LDF_DEVICES|LDF_READ)))
					{
						if(Dir->fl_Task == DList->dol_Task)
							strncpy(DevName, ((char *)BADDR(DList->dol_Name) + 1), *((char *)BADDR(DList->dol_Name)));
					}
					UnLockDosList(LDF_DEVICES|LDF_READ);
				}

					// Really load from ROOT ?

				if(!(CheckLock = ParentDir(MyLock)))
				{
						// Do we have patches waiting ???

					if(!IsListEmpty(&VolumeList))
					{
						struct	VolEntry	*ThisEntry = (struct VolEntry *)VolumeList.lh_Head;

						do
						{
								// This one to patch ???

							if(ThisEntry->Link.ln_Type == LDF_DEVICES && !stricmp(ThisEntry->VolName, DevName))
								Found = TRUE;

							else if(ThisEntry->Link.ln_Type == LDF_VOLUMES && !stricmp(ThisEntry->VolName, VolName))
								Found = TRUE;

							else
								ThisEntry = (struct VolEntry *)ThisEntry->Link.ln_Succ;

						} while(!Found && ThisEntry->Link.ln_Succ);

							// Object to be patched ?

						if(Found)
						{
								// If an alternative icon is to be used
								// lock this one, otherwise lock Disk.info

							if(ThisEntry->UseAlt)
							{
								struct	DiskObject	*OldDiskObject;
								WORD	OldLeft = 50, OldTop = 50, OldWidth = 400, OldHeight = 100;

								if(!(RetVal = OldLock(ThisEntry->IconName, Mode, DOSBase)))
									RetVal = OldLock(Name, Mode, DOSBase);
								else
								{
										// Get original Disk.info file, in order to obtain
										// the correct window position and size

									strcat(DevName, ":Disk");
									if(!(OldDiskObject = GetDiskObject(DevName)))
									{
										strcat(VolName, ":Disk");
										OldDiskObject = GetDiskObject(VolName);
									}

									if(OldDiskObject)
									{
										OldLeft		= OldDiskObject->do_DrawerData->dd_NewWindow.LeftEdge;
										OldTop		= OldDiskObject->do_DrawerData->dd_NewWindow.TopEdge;
										OldWidth	= OldDiskObject->do_DrawerData->dd_NewWindow.Width;
										OldHeight	= OldDiskObject->do_DrawerData->dd_NewWindow.Height;

										FreeDiskObject(OldDiskObject);
									}

									ThisEntry->LeftEdge	= OldLeft;
									ThisEntry->TopEdge	= OldTop;
									ThisEntry->Width	= OldWidth;
									ThisEntry->Height	= OldHeight;
								}
							}
							else
								Found = FALSE;
						}
					}
				}
				else
					UnLock(CheckLock);
			}

			ReleaseSemaphore(&MySemaphore);
		}
	}

	if(!Found)
		RetVal = OldLock(Name, Mode, DOSBase);

	return(RetVal);
}






/**********************************************************************/
/*                           Open libraries                           */
/**********************************************************************/
BOOL OpenAll(void)
{
	if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"intuition.library");
		return(FALSE);
	}

	if(!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"dos.library");
		return(FALSE);
	}

	if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"graphics.library");
		return(FALSE);
	}

	if(!(GadToolsBase = OpenLibrary("gadtools.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"gadtools.library");
		return(FALSE);
	}

	if(!(IconBase = OpenLibrary("icon.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"icon.library");
		return(FALSE);
	}

	if(!(UtilityBase = OpenLibrary("utility.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"utility.library");
		return(FALSE);
	}

	if(!(CxBase = OpenLibrary("commodities.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"commodities.library");
		return(FALSE);
	}

	if(!(IFFParseBase = OpenLibrary("iffparse.library", 37)))
	{
		DisplayError(ERR_OPEN, (ULONG)"iffparse.library");
		return(FALSE);
	}

	if(!(DiskfontBase = OpenLibrary("diskfont.library", 36)))
	{
		DisplayError(ERR_OPEN, (ULONG)"diskfont.library");
		return(FALSE);
	}

	if(!(AslBase = OpenLibrary("asl.library", 36)))
	{
		DisplayError(ERR_OPEN, (ULONG)"asl.library");
		return(FALSE);
	}

	return(TRUE);
}








/**********************************************************************/
/*                          Close libraries                           */
/**********************************************************************/
void CloseAll(void)
{
	if(AslBase)
		CloseLibrary(AslBase);

	if(DiskfontBase)
		CloseLibrary(DiskfontBase);

	if(IFFParseBase)
		CloseLibrary(IFFParseBase);

	if(CxBase)
		CloseLibrary(CxBase);

	if(UtilityBase)
		CloseLibrary(UtilityBase);

	if(IconBase)
		CloseLibrary(IconBase);

	if(DOSBase)
		CloseLibrary((struct Library *)DOSBase);

	if(GadToolsBase)
		CloseLibrary(GadToolsBase);

	if(GfxBase)
		CloseLibrary((struct Library *)GfxBase);

	if(IntuitionBase)
		CloseLibrary((struct Library *)IntuitionBase);
}





/**********************************************************************/
/*                         Handle all inputs                          */
/**********************************************************************/
void HandleInput(struct MsgPort *BrokerPort, CxObj *InputBroker)
{
	CxMsg			*MyMsg;
	ULONG	BrokerSig	= (1L << BrokerPort->mp_SigBit),
		MainSig, EditSig, PosSig, ManSig, MySig;
	ULONG	MsgType, MsgID;
	BOOL	QuitIT = FALSE;



	while(!QuitIT)
	{
			// Main window open ???

		if(MainWinHandle)
			MainSig = (1L << MainWinHandle->UserPort->mp_SigBit);
		else
			MainSig = 0;

			// Edit window open ???

		if(EditWinHandle)
			EditSig = (1L << EditWinHandle->UserPort->mp_SigBit);
		else
			EditSig = 0;

			// Position window open ???

		if(PosWinHandle)
			PosSig = (1L << PosWinHandle->UserPort->mp_SigBit);
		else
			PosSig = 0;

			// Manual input window open ???

		if(ManWinHandle)
			ManSig = (1L << ManWinHandle->UserPort->mp_SigBit);
		else
			ManSig = 0;

			// Wait for some signals

		MySig = Wait(BrokerSig | MainSig | EditSig | PosSig | ManSig | SIGBREAKF_CTRL_C);


			// Go a CTRL-C ???

		if((MySig & SIGBREAKF_CTRL_C))
			QuitIT = TRUE;


			// Signal from Broker-Port ???

		if((MySig & BrokerSig))
		{
				// Loop on all messages

			while((MyMsg = (CxMsg *)GetMsg(BrokerPort)))
			{
				MsgType	= CxMsgType(MyMsg);
				MsgID	= CxMsgID(MyMsg);

				ReplyMsg((struct Message *)MyMsg);

				switch(MsgType)
				{
					case CXM_COMMAND :
					{
						switch(MsgID)
						{
								// Remove...

							case CXCMD_KILL :
							{
								QuitIT = TRUE;
								break;
							}
								// On appear or unique, open main window

							case CXCMD_APPEAR :
							case CXCMD_UNIQUE :
							{
								if(!MainWinHandle)
									OpenMainWin();
								else
									WindowToFront(MainWinHandle);
								break;
							}
								// Close all windows

							case CXCMD_DISAPPEAR :
							{
								CloseManWin();
								CloseEditWin();
								CloseMainWin();
								break;
							}
								// Disable ourself

							case CXCMD_DISABLE :
							{
									// Get semaphore, set state and flag

								ObtainSemaphore(&MySemaphore);
								ActivateCxObj(InputBroker, FALSE);
								Active = FALSE;
								ReleaseSemaphore(&MySemaphore);
								break;
							}
								// Enable ourself

							case CXCMD_ENABLE :
							{
									// Get semaphore, set state and flag

								ObtainSemaphore(&MySemaphore);
								ActivateCxObj(InputBroker, TRUE);
								Active = TRUE;
								ReleaseSemaphore(&MySemaphore);
								break;
							}
						}
						break;
					}
						// Had a hotkey

					case CXM_IEVENT :
					{
						switch(MsgID)
						{
								// Open main window

							case POPKEY :
							{
								if(!MainWinHandle)
									OpenMainWin();
								else
									WindowToFront(MainWinHandle);
								break;
							}
						}
						break;
					}
				}
			}
		}

			// Message from mainwindow

		if(MainWinHandle && (MySig & MainSig))
		{
				// Handle inputs

			if(HandleMainWin(&QuitIT))
			{
					// Quit ???

				if(!QuitIT)
					CloseMainWin();
			}
		}

			// Message from edit window

		if(EditWinHandle && (MySig & EditSig))
		{
			if(HandleEditWin())
				CloseEditWin();
		}

			// Message from manual input window

		if(ManWinHandle && (MySig & ManSig))
		{
			if(HandleManWin())
				CloseManWin();
		}

			// Message from position window

		if(PosWinHandle && (MySig & PosSig))
			HandlePosWin();
	}

		// Close all windows on exit

	CloseManWin();
	CloseEditWin();
	CloseMainWin();
}
