
/******
 * Include vari
 ******/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libraries/toolmanager.h>
#include <proto/toolmanager.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <ProgED:sources/include/Ped.h>

#define NUMDOCKS	20



/******
 * Strutture e variabili globali
 ******/

struct tmTool
{
	APTR	exec,
		icon,
		sound;
};

struct APIClient	MyClient=
{
	NULL,			/* Questo campo sara' riempito dopo... */
	NOTIFY_ON_SHOW_HIDE,	/* Dimmi quando chiudi e riapri il tuo schermo */
	"Cliente DOCK",		/* Nome del cliente (non utilizzato ancora) */
	NULL			/* Porre a NULL e non manipolare! Grazie. */
};

struct MsgPort		*MyPort,
			*PEDPort;
struct APIMessage	 msg;
ULONG			 NumDock=0;
UWORD			 PunDock[NUMDOCKS],
			 DockX[NUMDOCKS],
			 DockY[NUMDOCKS];

UBYTE			 quitting=FALSE;



/*****
 *
 * FUNZIONE:	void SendMessageToPED(struct APIMessage	*msg)
 *
 * SCOPO:	Questa funzione spedisce un messaggio alla porta APi del
 *		ProgED.
 *
 * RESTITUISCE: -
 *
 ****/

void SendMessageToPED(struct APIMessage	*msg)
{
	msg->am_Message.mn_Node.ln_Succ=NULL;
	msg->am_Message.mn_Node.ln_Pred=NULL;
	msg->am_Message.mn_Node.ln_Type=NT_MESSAGE;
	msg->am_Message.mn_Node.ln_Pri=0;
	msg->am_Message.mn_Node.ln_Name=NULL;
	msg->am_Message.mn_ReplyPort=MyPort;
	msg->am_Message.mn_Length=sizeof(struct APIMessage);

	PutMsg(PEDPort,(struct Message *)msg);
	WaitPort(MyPort);
	while(GetMsg(MyPort));
}



/*****
 *
 * FUNZIONE:	struct TagItem *SetupDock(char *config,void *handle)
 *
 * SCOPO:	Crea il dock dato il nome del file di configurazione, l'handle
 *		per il toolmanager e due puntatori che restituiranno la
 *		posizione x ed y del dock.
 *
 * RESTITUISCE: Puntatore al vettore di definizione per creare il dock.
 *
 ****/

struct TagItem *SetupDock(char *config,void *handle)
{
	BPTR		 file;
	ULONG		 num=0,
			 oldnum=0,
			 totnum=0,
			 n=0,
			 orien=0,
			 col=1,
			 i;
	struct TagItem	*dock=NULL;
	struct RDArgs	*RDArgs;
	char		 buffer[300],
			 execName[10],
			 imageName[10];



	if (file=Open(config,MODE_OLDFILE))
	{
		while(FGets(file,buffer,sizeof(buffer)-1))
		{
			if (!strncmp(buffer,"ADD",3))		totnum++;
			else if (!strncmp(buffer,"DOCK",4))	totnum+=10;
		}

		Close(file);

		if (dock=(struct TagItem *)calloc(totnum*sizeof(struct TagItem),1))
		{
			if (file=Open(config,MODE_OLDFILE))
			{
				if (RDArgs=AllocDosObject(DOS_RDARGS,NULL))
				{
					while(FGets(file,buffer,sizeof(buffer)-1))
					{
						ULONG	args[10]={0,0,0,0,0,0,0,0,0,0};



						RDArgs->RDA_Source.CS_Buffer=buffer+4;
						RDArgs->RDA_Source.CS_Length=strlen(buffer+4);
						RDArgs->RDA_Source.CS_CurChr=0;
						RDArgs->RDA_DAList=NULL;
						RDArgs->RDA_Buffer=NULL;

						if (!strncmp(buffer,"ADD",3))
						{
							if (ReadArgs("COMMAND/K/A,AREXX/S,SHELL/S,DIR/K,OUTPUT/K,IMAGE/K/A",args,RDArgs))
							{
								struct TagItem imageTags[]={
									TMOP_File,	NULL,
									TMOP_Data,	NULL,
								TAG_END};

								struct TagItem execTags[]={
									TMOP_Command,		NULL,
									TMOP_ExecType,		NULL,
									TMOP_Stack,		10000,
									TMOP_CurrentDir,	NULL,
									TMOP_Output,		NULL,
								TAG_END};

								imageTags[0].ti_Data=(ULONG)strdup((char *)args[5]);

								execTags[0].ti_Data=(ULONG)strdup((char *)args[0]);
								execTags[1].ti_Data=args[1] ? TMET_ARexx : TMET_CLI;
								execTags[3].ti_Data=args[3] ? (ULONG)strdup((char *)args[3]) : NULL;
								execTags[4].ti_Data=args[4] ? (ULONG)strdup((char *)args[4]) : NULL;

								sprintf(execName,"PED_E%d",num);
								sprintf(imageName,"PED_I%d",num++);

								CreateTMObjectTagList(handle,strdup(execName),TMOBJTYPE_EXEC,execTags);
								CreateTMObjectTagList(handle,strdup(imageName),TMOBJTYPE_IMAGE,imageTags);

								FreeArgs(RDArgs);
							}
						}
						else if (!strncmp(buffer,"DOCK",4))
						{
							if (ReadArgs("X/N,Y/N,HORIZONTAL/S,COLUMNS/N",args,RDArgs))
							{
								if (args[0])	DockX[NumDock]=*((ULONG *)args[0]);
								if (args[1])	DockY[NumDock]=*((ULONG *)args[1]);
								if (args[2])	orien=1;
								if (args[3])	col=*((ULONG *)args[3]);

						                if (num-oldnum>0)
								{
									PunDock[NumDock++]=n;

									dock[n].ti_Tag=TMOP_PubScreen;
									dock[n++].ti_Data=NULL;

									dock[n].ti_Tag=TMOP_LeftEdge;
									dock[n++].ti_Data=NULL;

									dock[n].ti_Tag=TMOP_TopEdge;
									dock[n++].ti_Data=NULL;

									dock[n].ti_Tag=TMOP_Activated;
									dock[n++].ti_Data=TRUE;

									dock[n].ti_Tag=TMOP_Centered;
									dock[n++].ti_Data=FALSE;

									dock[n].ti_Tag=TMOP_Columns;
									dock[n++].ti_Data=col;

									dock[n].ti_Tag=TMOP_Vertical;
									dock[n++].ti_Data=orien;

									dock[n].ti_Tag=TMOP_Text;
									dock[n++].ti_Data=FALSE;

									for(i=oldnum;i<num;i++)
									{
										struct tmTool *tool;

										if (tool=(struct tmTool *)calloc(sizeof(struct tmTool),1))
										{
											if ((tool->exec=calloc(12,1))&&(tool->icon=calloc(12,1)))
											{
												sprintf((char *)tool->exec,"PED_E%d",i);
												sprintf((char *)tool->icon,"PED_I%d",i);

												dock[n].ti_Tag=TMOP_Tool;
												dock[n++].ti_Data=(ULONG)tool;
											}
										}
									}

									dock[n++].ti_Tag=TAG_DONE;

									oldnum=num;
								}

								FreeArgs(RDArgs);
							}
						}
					}

					FreeDosObject(DOS_RDARGS,RDArgs);
				}

				Close(file);
			}
		}
	}

	return(dock);
}



/*****
 *
 * FUNZIONE:	void HandleMsg(void *handle,struct TagItem *dock)
 *
 * SCOPO:	Gestione dei messaggi.
 *
 * RESTITUISCE: -
 *
 ****/

void HandleMsg(void *handle,struct TagItem *dock)
{
	ULONG			 i;
	struct APIMessage	*mess;
	struct Screen		*screen;
	char			*pubscrname,
				 tmp[25];



	/***** Ottieni l'indirizzo dello schermo del ProgED *****/
	msg.am_MsgType=PED_API_GET_SCREEN_ADDRESS;
	SendMessageToPED(&msg);
	screen=(struct Screen *)msg.am_RC;

	/***** Ottieni il nome dello schermo pubblico *****/
	msg.am_MsgType=PED_API_GET_PUBSCRNAME;
	SendMessageToPED(&msg);
	pubscrname=(char *)msg.am_RC;

	/***** Se lo schermo e' aperto apri anche il dock *****/
	if (screen)
	{
		for(i=0;i<NumDock;i++)
		{
			dock[PunDock[i]].ti_Data=(ULONG)pubscrname;
			dock[PunDock[i]+1].ti_Data=(DockX[i] == ~0) ? screen->Width : DockX[i];
			dock[PunDock[i]+2].ti_Data=(DockY[i] == ~0) ? screen->BarHeight+1 : DockY[i];

			sprintf(tmp,"PED_DOCK%d",i);
			CreateTMObjectTagList(handle,strdup(tmp),TMOBJTYPE_DOCK,&dock[PunDock[i]]);
		}
	}

	/***** Loop principale *****/
	while(!quitting)
	{
		WaitPort(MyPort);
		while(mess=(struct APIMessage *)GetMsg(MyPort))
		{
			switch(mess->am_MsgType)
			{
				/***** ProgED sta' per terminare! Terminiamo
					anche noi :-( *****/
				case	PED_API_QUIT:
					quitting=TRUE;
				break;

				/***** ProgED sta' per chiudere il suo schermo.
					Chiudiamo la nostra finestra. *****/
				case	PED_API_HIDE:
					for(i=0;i<NumDock;i++)
					{
						sprintf(tmp,"PED_DOCK%d",i);
						DeleteTMObject(handle,tmp);
					}
				break;

				/***** ProgED ha riaperto il suo schermo.
					Riapriamo la nostra finestra. *****/
				case	PED_API_SHOW:
					if (screen=(struct Screen *)mess->am_MsgArg[0])
					{
						for(i=0;i<NumDock;i++)
						{
							dock[PunDock[i]].ti_Data=(ULONG)pubscrname;
							dock[PunDock[i]+1].ti_Data=(DockX[i] == ~0) ? screen->Width : DockX[i];
							dock[PunDock[i]+2].ti_Data=(DockY[i] == ~0) ? screen->BarHeight+1 : DockY[i];

							sprintf(tmp,"PED_DOCK%d",i);
							CreateTMObjectTagList(handle,strdup(tmp),TMOBJTYPE_DOCK,&dock[PunDock[i]]);
						}
					}
				break;
			}

			mess->am_RC=0;

			ReplyMsg((struct Message *)mess);
		}
	}
}



/*****
 *
 * FUNZIONE:	void main(int argc,char *argv[])
 *
 * SCOPO:	MAIN.
 *
 * RESTITUISCE: -
 *
 ****/

void main(int argc,char *argv[])
{
	struct RDArgs		*RDArgs;
	ULONG			 args[2]={(ULONG)"progdir:docks.prefs",0,},
				 try,
				 i;
	void			*handle;
	struct TagItem		*dock;



	/***** Cancella i vettori DockX e DockY *****/
	for(i=0;i<NUMDOCKS;i++)	DockX[i]=DockY[i]=(UWORD)~0;

	/***** Cerca la porta del ProgED *****/
	if (!(PEDPort=FindPort("PED_API")))
	{
		printf("Can't find ProgED API Port!\n");
		exit(0);
	}

	/***** Crea una porta che utilizzeremo per ricevere i msg dal ProgED *****/
	if (!(MyPort=CreateMsgPort()))
	{
		printf("Can't create a MsgPort!\n");
		exit(0);
	}

	/***** Riempi il campo ac_ClientPort della struttura APIClient che
		utilizzeremo per la registrazione *****/
	MyClient.ac_ClientPort=MyPort;

	/***** Registriamoci come cliente presso il ProgED *****/
	msg.am_MsgType=PED_API_REGISTER;
	msg.am_MsgArg[0]=(ULONG)&MyClient;
	SendMessageToPED(&msg);

	/***** Ciclo principale *****/
	if (RDArgs=ReadArgs("CONFIG/K",args,NULL))
	{
	        /***** Aspetta il ToolManager *****/
		for (try = 20; !(handle = AllocTMHandle()) && try; try--)
			Delay(10);

		if (handle)
		{
			if (dock=SetupDock((char *)args[0],handle))
				HandleMsg(handle,dock);
			FreeTMHandle(handle);
		}

		FreeArgs(RDArgs);
	}

	/***** Togliamo la registrazione presso il ProgED (NON in caso di quit!)*****/
	if (!quitting)
	{
		msg.am_MsgType=PED_API_UNREGISTER;
		msg.am_MsgArg[0]=(ULONG)&MyClient;
		SendMessageToPED(&msg);
	}

	/***** Usciamo *****/
	DeleteMsgPort(MyPort);
	exit(0);
}



