(*---------------------------------------------------------------------------
  :Program.    Hotkey.mod
  :Author.     Thomas Igracki
  :Address.    Obstallee 45, 1000 Berlin 20, W-Germany
  :E-Mail.     T.IGRACKI@BAMP.ZER
  :Version.    V1.0
  :Date.       28-Apr-92
  :Copyright.  Me
  :Language.   Oberon
  :Translator. Amiga Oberon 2.14d
  :Contents.   Modul zur Unterstützung von Hotkeys mittels der Commodities.lib.
  :Usage.      IMPORT Hotkey
  :Remark.     OS2.0 Only!
---------------------------------------------------------------------------*)

MODULE HotKey;
IMPORT
   s: SYSTEM, c: Commodities, e: Exec, OberonLib; 
VAR
   nb       : c.NewBroker;
   broker,
   filter   : c.CxObjPtr;
   ComPort,
   SendPort : e.MsgPortPtr;
   portSig*,            (* Signal des Ports für HandleExCh() *)
   comErr*  : SHORTINT; (* Commo-Error, wenn Init() = -1 *)

(* ---------------------------------------------------------------------- 
 * Es wird das Signal, auf das gewartet werden kann, zurückgeliefert oder *
 * -1 bei einem Fehler, dann steht in comErr der CommodityError (c.err#?),*
 * falls es nicht an der Commodities.lib lag (z.B. keine Speicher für den *
 * MsgPort), dann steht dort -1.                                          *
 * ------------------------------- Input -------------------------------- *
 * name: Name des Brokers                                                 *
 * title, descr: Der Text der bei Exchange erscheinen soll                *
 * ---------------------------------------------------------------------- *)
PROCEDURE Init* (name,title,descr: ARRAY OF CHAR): SHORTINT; (* $CopyArrays- *)
VAR err: LONGINT;
BEGIN
     IF ComPort # NIL THEN comErr := -1; RETURN -1 END;
     SendPort:= e.CreateMsgPort(); IF SendPort = NIL THEN comErr := -1; RETURN -1 END;
     ComPort := e.CreateMsgPort();
     IF ComPort = NIL THEN e.DeleteMsgPort(SendPort); SendPort := NIL; RETURN -1 END;
     portSig := ComPort.sigBit;
     nb := c.NewBroker (c.nbVersion,NIL,NIL,NIL, c.notify, {c.showHide},10,NIL,0);
     nb.name := s.ADR(name); nb.title := s.ADR(title); nb.descr := s.ADR(descr);
     nb.port := ComPort; broker := c.CxBroker (nb,err);
     IF err = c.ErrOk THEN RETURN SendPort.sigBit
     ELSE
        e.DeleteMsgPort (ComPort); ComPort := NIL;
        e.DeleteMsgPort (SendPort); SendPort := NIL;
        comErr := SHORT(SHORT(err)); RETURN -1
     END
END Init;

(* ------------------------------------------------ *
 * Mit dieser Proz. definiert man ein neuen HotKey. *
 * ----------------- Input ------------------------ *
 * descr: Beschreibung der HotKeys, z.B. 'alt 1'    *
 * ID: Zum identifizieren des HotKeys (GetID()).    *
 * ------------------------------------------------ *)
PROCEDURE AddKey* (descr: ARRAY OF CHAR; ID: INTEGER); (* $CopyArrays- *)
VAR filter: c.CxObjPtr;
BEGIN
     IF ComPort = NIL THEN RETURN END;

     filter := c.CxFilter (s.ADR(descr)); IF filter = NIL THEN RETURN END;
     c.AttachCxObj (filter, c.CxSender (SendPort, ID));
     c.AttachCxObj (filter, c.CxTranslate (NIL));
     c.AttachCxObj (broker,filter);
END AddKey;

(* ------------------------------------------------------------------------ *
 * Hiermit wird der Broker, und damit alle HotKeys, ein oder ausgeschaltet. *
 * ------------------------------------------------------------------------ *)
PROCEDURE Activate* (ON: BOOLEAN);
BEGIN     s.SETREG (0,c.ActivateCxObj (broker,s.VAL(SHORTINT,ON)));
END Activate;

(* --------------------------------------------------- *
 * Wenn das Signal von Init() angekommen ist, kann man *
 * damit feststellen, welcher HotKey gedrückt wurde.   *
 * --------------------------------------------------- *)
PROCEDURE GetID*(): INTEGER;
VAR msg: c.CxMsgPtr;
BEGIN
     IF SendPort = NIL THEN RETURN -1 END;
     msg := s.VAL(s.ADDRESS,e.GetMsg (SendPort)); RETURN SHORT(c.CxMsgID (msg))
END GetID;

(* --------------------------------------------------------------------- *
 * Wenn das Signal 'portSig' angekommen ist, sollte man diese Proz. auf- *
 * rufen. show, hide, kill gibt an was per ExChange gewählt wurde.       *
 * Active wird selbständig verwaltet, indem Activate() aufgerufen wird.  *
 * --------------------------------------------------------------------- *)
PROCEDURE HandleExCh* (VAR show, hide, kill: BOOLEAN);
VAR msg: c.CxMsgPtr; id: LONGINT;
BEGIN
     show := FALSE; hide := FALSE; kill := FALSE;
     msg := s.VAL(s.ADDRESS,e.GetMsg (ComPort)); id := c.CxMsgID (msg);
     CASE id OF
          c.cmdDisable   : Activate(FALSE)|
          c.cmdEnable    : Activate(TRUE)|
          c.cmdAppear    : show := TRUE|
          c.cmdDisappear : hide := TRUE|
          c.cmdUnique,
          c.cmdKill      : kill := TRUE
     ELSE
     END
END HandleExCh;

(* -------------------------------------------------------------------- *
 * Hiermit kann man vorzeitig alle HotKeys und auch den Broker löschen. *
 * Diese Proz. wird auch im CLOSE-Teil dieses Moduls aufgerufen.        *
 * -------------------------------------------------------------------- *)
PROCEDURE DelKeys*;
BEGIN
    e.DeleteMsgPort (ComPort); ComPort := NIL;
    e.DeleteMsgPort (SendPort);SendPort:= NIL;
    IF broker  # NIL THEN c.DeleteCxObjAll (broker); broker := NIL END;
END DelKeys;

CLOSE
    DelKeys
END HotKey.
