/*
***************************************************************************
*
* Datei:
*	  RSysBroker.c
*
* Inhalt:
*
*      --- Globale Routinen ---
*
*    void HandleBrokerPort ( void );
*    void InstallBroker ( void );
*    void RemoveBroker ( void );
*
*      --- Lokale  Routinen ---
*
*    static void HandleBrokerInputEventMsg ( ULONG msgid );
*    static void HandleExchangeMsg ( ULONG msgid );
*    static void InstallHotKeys ( void );
*
* Bemerkungen:
*	  Broker-Verwaltungsroutinen unter Verwendung der Commodities-Library.
*
* Erstellungsdatum:
*	  07-Jul-93 	Rolf Böhme
*
* Änderungen:
*	  07-Jul-93 	Rolf Böhme	  Erstellung
*
***************************************************************************
*/

#include "RSys.h"

	/*
	 * Der Zeiger auf den Brokerport. An diesem liegen
	 * die Nachrichten an, die vom Programm Exchange
	 * abgesendet werden.
	 */
struct MsgPort *broker_mp = NULL;

	/*
	 * Die "Objekte", die die Eigenschaften der
	 * Nachrichten, die an den Broker gesendet werden
	 * sollen, festlegen.
	 */
CxObj *broker,
	  *filter[HOTKEYS+1],
	  *sender,
	  *translate;

	/*
	 * Die Tastenkombinationen, mit denen RSys gesteuert
	 * werden kann.
	 */
char	hotkey[HOTKEYS+1][30];

	/*
	 * In dieser Struktur werden alle Eigenschaften des
	 * Brokers definiert. Insbesondere der Name, die
	 * Version (systemabhängig), Eindeutigkeit des
	 * verwendeten Broker-Namens und ob Show/Hide-
	 * Nachrichten empfangen werden sollen.
	 */
struct NewBroker newbroker =
{
	NB_VERSION,
	NAME,
	NAME " " VERSION " - " COPYRIGHT,
	"RSys Commodity Handler",
	NBU_UNIQUE,
	NULL /*COF_SHOW_HIDE*/,
	0,
	0,
	0
};

	/*
	 * Ein Zeiger auf den letzten PublicScreen, auf dem
	 * das Hauptfenster von RSys geöffnet wurde.
	 */
struct Screen *lastpubscreen = NULL;

	/*
	 * Die Prozedur InstallHotKeys() bildet für alle zu
	 * installierenden HotKeys einen Filter und bindet
	 * diese dann in die Broker-Struktur ein.
	 */
static void
InstallHotKeys(void)
{
	register int i;

	for (i = 0; i < HOTKEYS+1; i++)
	{
		filter[i] = HotKey((UBYTE *) & hotkey[i][0], broker_mp, (long)(i + 1));
			/*
			 * Falls kein Filter erzeugt werden konnte, wird eine
			 * Fehlermeldung ausgegeben und das Programm beendet.
			 */
		if (NOT(filter[i])) ErrorHandle((char *)hotkey[i][0], BROKER_ERR, CREATE_FAIL, KILL);

		AttachCxObj(broker, filter[i]);
	}

	return;
}

	/*
	 * InstallBroker() öffnet die commodities.library,
	 * richtet einen MessagePort für die Nachrichten vom
	 * Broker ein, initialisiert ein Broker-
	 * Kontrollstruktur und startet den Broker.
	 */
void
InstallBroker(void)
{
	DPOS;
		/*
		 * Ein Kommunikations-Port wird erzeugt.
		 */
	if (broker_mp = CreatePort((UBYTE *) "RSys-Broker-Port", 0L))
	{
		newbroker.nb_Port = broker_mp;
		newbroker.nb_Pri	= 0;

			/*
			 * Falls der Broker erzeugt werden konnte, werden die
			 * HotKeys installiert und der Broker gestartet.
			 */
		if (broker = CxBroker(&newbroker, NULL)) InstallHotKeys();
		else
			ErrorHandle(newbroker.nb_Name, BROKER_ERR, CREATE_FAIL, KILL);

		ActivateCxObj(broker, TRUE);
	}
	else ErrorHandle("RSys-Broker-Port", PORT_ERR, CREATE_FAIL, KILL);

	return;
}

	/*
	 * RemoveBroker() entfernt alle mit dem Broker
	 * verbundenen Datenstrukturen aus dem System und
	 * schließt die commodities.library.
	 */
void
RemoveBroker(void)
{
	DPOS;

	if (broker)    DeleteCxObjAll(broker);
	if (broker_mp) DeletePort(broker_mp);

	return;
}

static void
HandleBrokerInputEventMsg(ULONG msgid)
{
	struct Screen *activescr;
		/*
		 * Dieses Feld von Funktionenzeigern enthält alle
		 * Funktionen, die entsprechend der MessageID
		 * ausgeführt werden.
		 */
	void	(*func[HOTKEYS]) (void)=
	{CryptFile, FindFile, FormatDisk, HunkStruct,CRCSum,SaveWindows, DisplayFileRequest};
   int openit;

		/*
		 * Ist die MessageID 1, soll das RSys-Hauptfenster
		 * erscheinen.
		 */
	if(msgid == 1)
	{
			/*
			 * Falls das Hauptfenster bereits offen ist, wird der
			 * nächst Public screen gesucht und versucht, RSys auf
			 * diesem Screen zu öffnen. War das erfolgreich, wird
			 * das ListView des Hauptfensters aktualisiert.
			 */
		if (SysWnd)
		{
			activescr = SysWnd->WScreen;

			if (activescr != FindFrontPubScr(activescr))
			{
				CloseASysWindow(&SysWnd, &SysGList, &SysMenus);
				CloseDownScreen();

				OpenMainWindow();
				RefreshList(LastID);

            openit = CloseHelpOnScreen();
            OpenHelpOnScreen(openit);
			}
		}
		else
		{
				/*
				 * Ist das Hauptfenster noch nicht geöffnet, wird es
				 * mit der Standardprozedur geöffnet und das ListView
				 * aktualisiert.
				 */
			OpenMainWindow();
			RefreshList(LastID);

         openit = CloseHelpOnScreen();
         OpenHelpOnScreen(openit);
		}
	}
	else
	{
			/*
			 * Ist die MessageID größer als 1, werden die
			 * entsprechenden Funktionen aus dem
			 * Funktionenzeigerfeld ausgeführt.  Ist das
			 * Hauptfenster noch nicht geöffnet worden, muß der
			 * Screen, auf dem das Fenster der jeweiligen
			 * Funktion geöffnet werden soll, mit SetupScreen()
			 * vorbereitet werden.
			 */
		if (NOT(SysWnd))
			if (SetupScreen()) ErrorHandle((char *)namebuffer, SCREEN_ERR, INFO_FAIL, NO_KILL);

		(*func[msgid - 2]) ();

		if (NOT(SysWnd)) CloseDownScreen();
	}

   return;
}

static void
HandleExchangeMsg(ULONG msgid)
{
	switch (msgid)
	{
			/*
			 * Der Broker von RSys soll ausgeschaltet werden.
			 */
		case CXCMD_DISABLE:
			ActivateCxObj(broker, 0L);
			break;

			/*
			 * Der Broker von RSys soll eingeschaltet werden.
			 */
		case CXCMD_ENABLE:
			ActivateCxObj(broker, 1L);
			break;

			/*
			 * RSys soll ohne Sicherheitsabfrage beendet werden.
			 */
		case CXCMD_KILL:
			quit(FALSE);
			break;

		case CXCMD_UNIQUE:
				/*
				 * Ein Programm versucht einen Broker mit dem Namen
				 * RSys einzurichten. Es erscheint eine Fehlermeldung.
				 */
			ErrorHandle(newbroker.nb_Name, BROKER_ERR, DUPLICATE_FAIL, NO_KILL);
			break;
	}

   return;
}

	/*
	 * HandleBrokerPort() verarbeitet alle Nachrichten,
	 * die am Broker port eintreffen.
	 */
void
HandleBrokerPort(void)
{
	CxMsg *msg;
	ULONG msgid,
			msgtype;

	DPOS;
		/*
		 * Alle Messages, die am Brokerport anliegen, werden
		 * bearbeitet.
		 */
	while (msg = (CxMsg *) GetMsg(broker_mp))
	{
			/*
			 * Aus der Message werden die notwendigen Daten
			 * herauskopiert. Danach wird die Nachricht wieder
			 * so schnell wie möglich beantwortet, damit der
			 * Broker nicht wartet.
			 */
		msgid = CxMsgID(msg);
		msgtype = CxMsgType(msg);

		ReplyMsg((struct Message *) msg);

			/*
			 * Entsprechend dem Typ der Nachricht werden
			 * verschiedene Aktionen ausgelöst.
			 */
		switch (msgtype)
		{
				/*
				 * Es handelt sich um einen Inputevent.
				 */
			case CXM_IEVENT:
            HandleBrokerInputEventMsg(msgid);
				break;

				/*
				 * Es ist eine Nachricht vom Programm Exchange.
				 */
			case CXM_COMMAND:
            HandleExchangeMsg(msgid);
				break;
		}
	}

	return;
}
