
(* ------------------------------------------------------------------------
  :Program.       OneHand
  :Contents.      Qualifies keyboard and mouse actions.
  :Author.        Kamran Karimi
  :Address.       89-Nastaran/Ghandehari
  :Address.       Khosh Shomali str.
  :Address.       14578 - Tehran
  :Address.       IRAN 
  :Addrees.       Internet: karimik@sun.iust.ac.ir
  :Copyright.     Source and executable copyrighted, but can be used 
  :Copyright.     with no charges     
  :Language.      Oberon and Assembly
  :Translator.    AMIGA OBERON V3.00d, SAS/C 6.00 assembler
  :History.       V1.0 
------------------------------------------------------------------------ *)

MODULE OneHand;

IMPORT I:Intuition, SYS:SYSTEM,e:Exec,g:Graphics,
       input:Input,d:Dos,es:ExecSupport;

TYPE
 PointType = ARRAY 3 OF ARRAY 2 OF INTEGER;

CONST
 title = "OneHand! V1.0";
 NumKeys = 8;
 LShiftID = 0;
 RShiftID = 1;
 CapsID = 2;
 CtrlID = 3;
 LAltID = 4;
 RAltID = 5;
 LAmigaID = 6;
 RAmigaID = 7;
 ScrSwitchID = 8;

 winWidth = 210;
 winHeight = 57;
 bigGadWidth = 55;
 bigGadHeight = 10;
 gadWidth = 35;
 gadHeight = 10;
 smalGadWidth = 13;
 smalGadHeight = 10;
 firstRow = 14;
 secondRow = 28;
 thirdRow = 42;


 normalStyle = g.TextAttr(SYS.ADR("topaz.font"),8,
                                            g.normal,SHORTSET{g.romFont});

 italicStyle = g.TextAttr(SYS.ADR("topaz.font"),8,
                                  SHORTSET{g.italic},SHORTSET{g.romFont});

 shifText = I.IntuiText(1,0,g.jam2,7,1,SYS.ADR(normalStyle),
                                                        SYS.ADR("^"),NIL);

 capsText = I.IntuiText(1,0,g.jam2,2,2,SYS.ADR(normalStyle),
                                                      SYS.ADR("Caps"),NIL);

 ctrlText = I.IntuiText(1,0,g.jam2,2,2,SYS.ADR(normalStyle),
                                                      SYS.ADR("Ctrl"),NIL);

 altText = I.IntuiText(1,0,g.jam2,6,2,SYS.ADR(normalStyle),
                                                       SYS.ADR("Alt"),NIL);

 amigaText = I.IntuiText(1,0,g.jam2,12,2,SYS.ADR(italicStyle),
                                                         SYS.ADR("A"),NIL);

 scrswitchText = I.IntuiText(1,0,g.jam2,2,2,SYS.ADR(normalStyle),
                                                         SYS.ADR("X"),NIL);

 myText =  I.IntuiText(2,0,g.jam2,72,14,SYS.ADR(italicStyle),
                                          SYS.ADR("By Kamran Karimi"),NIL);

 bigBrightPoints = PointType(0,bigGadHeight + 1,0,0,bigGadWidth,0);

 bigDarkPoints = PointType(bigGadWidth,0,bigGadWidth,bigGadHeight + 1,
                                                       0,bigGadHeight + 1);

 smalBrightPoints = PointType(0,smalGadHeight + 1,0,0,smalGadWidth,0);

 smalDarkPoints = PointType(smalGadWidth,0,smalGadWidth,smalGadHeight + 1,
                                                      0,smalGadHeight + 1);

 brightPoints = PointType(0,gadHeight + 1,0,0,gadWidth,0);

 darkPoints = PointType(gadWidth,0,gadWidth,gadHeight + 1,0,gadHeight + 1);


VAR
 inputHandler : e.Interrupt;
 Port : e.MsgPortPtr;
 keyReq : e.IOStdReqPtr;

 OneHandnw : I.NewWindow;
 OneHandw : I.WindowPtr;

 LShift,RShift,Caps,Ctrl,LAlt,RAlt,LAmiga,RAmiga,ScrSwitch : I.Gadget;
 gadptr : I.GadgetPtr;

 imsgClass : LONGSET;
 imsg : I.IntuiMessagePtr;

 dark,bright,Seldark,Selbright : I.Border;
 smalDark,smalBright,smalSeldark,smalSelbright : I.Border;
 bigDark,bigBright,bigSeldark,bigSelbright : I.Border;

 onColor,offColor : SHORTINT;

 lampText : I.IntuiText;

 Qualify["Qualify"] : ARRAY NumKeys OF INTEGER; (* see ForceQualify.asm *)



PROCEDURE ForceQualify{"ForceQualify"}; (* see file ForceQualify.asm *)


PROCEDURE Init(); (* is there a better (shorter) way of initialization? *)
BEGIN

 smalBright.leftEdge := -1;
 smalBright.topEdge := -1;
 smalBright.frontPen := 2;
 smalBright.backPen := 0;
 smalBright.drawMode := g.jam1;
 smalBright.count := 3;
 smalBright.xy := SYS.ADR(smalBrightPoints);
 smalBright.nextBorder := SYS.ADR(smalDark);

 smalDark := smalBright;
 smalDark.frontPen := 1;
 smalDark.xy := SYS.ADR(smalDarkPoints);
 smalDark.nextBorder := NIL;

 smalSelbright := smalBright;
 smalSelbright.frontPen := 1;
 smalSelbright.xy := SYS.ADR(smalBrightPoints);
 smalSelbright.nextBorder := SYS.ADR(smalSeldark);

 smalSeldark := smalBright;
 smalSeldark.frontPen := 2;
 smalSeldark.xy := SYS.ADR(smalDarkPoints);
 smalSeldark.nextBorder := NIL;

 bigBright := smalBright;
 bigBright.frontPen := 2;
 bigBright.xy := SYS.ADR(bigBrightPoints);
 bigBright.nextBorder := SYS.ADR(bigDark);

 bigDark := smalBright;
 bigDark.frontPen := 1;
 bigDark.xy := SYS.ADR(bigDarkPoints);
 bigDark.nextBorder := NIL;

 bigSelbright := smalBright;
 bigSelbright.frontPen := 1;
 bigSelbright.xy := SYS.ADR(bigBrightPoints);
 bigSelbright.nextBorder := SYS.ADR(bigSeldark);

 bigSeldark := smalBright;
 bigSeldark.frontPen := 2;
 bigSeldark.backPen := 0;
 bigSeldark.xy := SYS.ADR(bigDarkPoints);
 bigSeldark.nextBorder := NIL;

 bright := smalBright;
 bright.frontPen := 2;
 bright.xy := SYS.ADR(brightPoints);
 bright.nextBorder := SYS.ADR(dark);

 dark := smalBright;
 dark.frontPen := 1;
 dark.xy := SYS.ADR(darkPoints);
 dark.nextBorder := NIL;

 Selbright := smalBright;
 Selbright.frontPen := 1;
 Selbright.xy := SYS.ADR(brightPoints);
 Selbright.nextBorder := SYS.ADR(Seldark);

 Seldark := smalBright;
 Seldark.frontPen := 2;
 Seldark.backPen := 0;
 Seldark.xy := SYS.ADR(darkPoints);
 Seldark.nextBorder := NIL;

 OneHandnw.leftEdge := 100;
 OneHandnw.topEdge := 50;
 OneHandnw.flags := LONGSET{I.windowDrag,I.windowDepth,I.windowClose};
 OneHandnw.idcmpFlags := LONGSET{I.gadgetUp,I.closeWindow};
 OneHandnw.type := {I.wbenchScreen};
 OneHandnw.width := winWidth;
 OneHandnw.height := winHeight;
 OneHandnw.firstGadget := SYS.ADR(LShift);
 OneHandnw.title := SYS.ADR(title);

 LShift.nextGadget := SYS.ADR(RShift);
 LShift.leftEdge := 15;
 LShift.topEdge := secondRow;
 LShift.width := bigGadWidth;
 LShift.height := bigGadHeight;
 LShift.gadgetText := SYS.ADR(shifText);
 LShift.gadgetRender := SYS.ADR(bigBright);
 LShift.selectRender := SYS.ADR(bigSelbright);
 LShift.flags      := {I.gadgHImage};
 LShift.gadgetType := I.boolGadget;
 LShift.activation  := {I.relVerify,I.toggleSelect};
 LShift.gadgetID := LShiftID;

 RShift := LShift;
 RShift.nextGadget := SYS.ADR(Caps);
 RShift.leftEdge := 145;
 RShift.gadgetID := RShiftID;

 Caps := LShift;
 Caps.nextGadget := SYS.ADR(Ctrl);
 Caps.leftEdge := 80;
 Caps.topEdge := secondRow;
 Caps.gadgetText := SYS.ADR(capsText);
 Caps.activation  := {I.relVerify};
 Caps.gadgetID := CapsID;

 Ctrl.nextGadget := SYS.ADR(LAlt);
 Ctrl.leftEdge := 15;
 Ctrl.topEdge := firstRow;
 Ctrl.width := gadWidth;
 Ctrl.height := gadHeight;
 Ctrl.gadgetText := SYS.ADR(ctrlText);
 Ctrl.gadgetRender := SYS.ADR(bright);
 Ctrl.selectRender := SYS.ADR(Selbright);
 Ctrl.flags      := {I.gadgHImage};
 Ctrl.gadgetType := I.boolGadget;
 Ctrl.activation  := {I.relVerify,I.toggleSelect};
 Ctrl.gadgetID := CtrlID;

 LAlt := Ctrl;
 LAlt.nextGadget := SYS.ADR(RAlt);
 LAlt.leftEdge := 10;
 LAlt.topEdge := thirdRow;
 LAlt.gadgetText := SYS.ADR(altText);
 LAlt.gadgetID := LAltID;

 RAlt := Ctrl;
 RAlt.nextGadget := SYS.ADR(LAmiga);
 RAlt.leftEdge := 165;
 RAlt.topEdge := thirdRow;
 RAlt.gadgetText := SYS.ADR(altText);
 RAlt.gadgetID := RAltID;

 LAmiga := Ctrl;
 LAmiga.nextGadget := SYS.ADR(RAmiga);
 LAmiga.leftEdge := 50;
 LAmiga.topEdge := thirdRow;
 LAmiga.gadgetText := SYS.ADR(amigaText);
 LAmiga.gadgetID := LAmigaID;

 RAmiga := Ctrl;
 RAmiga.nextGadget := SYS.ADR(ScrSwitch);
 RAmiga.leftEdge := 125;
 RAmiga.topEdge := thirdRow;
 RAmiga.gadgetText := SYS.ADR(amigaText);
 RAmiga.gadgetID := RAmigaID;

 ScrSwitch := Ctrl;
 ScrSwitch.nextGadget := NIL;
 ScrSwitch.leftEdge := 100;
 ScrSwitch.topEdge := thirdRow;
 ScrSwitch.width := smalGadWidth;
 ScrSwitch.height := smalGadHeight;
 ScrSwitch.gadgetRender := SYS.ADR(smalBright);
 ScrSwitch.selectRender := SYS.ADR(smalSelbright);
 ScrSwitch.activation  := {I.relVerify};
 ScrSwitch.gadgetText := SYS.ADR(scrswitchText);
 ScrSwitch.gadgetID := ScrSwitchID;

 onColor := 2;
 offColor := 1;

 IF e.exec.libNode.version < 36 THEN
  bright.frontPen := 1;
  dark.frontPen := 2;
  Selbright.frontPen := 2;
  Seldark.frontPen := 1;
  smalBright.frontPen := 1;
  smalDark.frontPen := 2;
  smalSelbright.frontPen := 2;
  smalSeldark.frontPen := 1;
  bigBright.frontPen := 1;
  bigDark.frontPen := 2;
  bigSelbright.frontPen := 2;
  bigSeldark.frontPen := 1;
  OneHandnw.detailPen := 0;
  OneHandnw.blockPen := 1;
  onColor := 1;
  offColor := 2;
 END;

 lampText.frontPen := offColor;
 lampText.backPen := 0;
 lampText.drawMode := g.jam2;
 lampText.leftEdge := 120;
 lampText.topEdge := 28;
 lampText.iTextFont := SYS.ADR(normalStyle);
 lampText.iText := SYS.ADR("*");
 lampText.nextText := NIL;

END Init;


PROCEDURE InstallHandler():BOOLEAN;
VAR
 res : SHORTINT;
 ret : BOOLEAN;

BEGIN
 ret := TRUE;
 Port := es.CreatePort("",0);
 IF Port # NIL THEN
  keyReq := es.CreateExtIO(Port,SIZE(e.IOStdReq));
  IF keyReq # NIL THEN
   IF e.OpenDevice("input.device",0,keyReq,LONGSET{}) = 0 THEN
    inputHandler.code := ForceQualify;
    inputHandler.data := NIL;
    inputHandler.node.pri := 127;
    keyReq.command := input.addHandler;
    keyReq.data := SYS.ADR(inputHandler);
    res := e.DoIO(keyReq);
   ELSE ret := FALSE; END;
  ELSE ret := FALSE; END;
 ELSE ret := FALSE; END;
 RETURN ret;
END InstallHandler;


PROCEDURE RemoveHandler();
VAR
 res : SHORTINT;

BEGIN
 keyReq.command := input.remHandler;
 keyReq.data := SYS.ADR(inputHandler);
 res := e.DoIO(keyReq);
 e.CloseDevice(keyReq);
 es.DeleteExtIO(keyReq);
 es.DeletePort(Port);
END RemoveHandler; 


PROCEDURE HandleScrSwitch();
VAR
 IBase : LONGINT;

BEGIN
 I.CloseWindow(OneHandw);
 d.Delay(200);
 OneHandnw.type := I.customScreen;
 IBase := I.LockIBase(0);
 OneHandnw.screen := I.int.firstScreen;
 I.UnlockIBase(IBase);
 OneHandw := I.OpenWindow(OneHandnw);
 IF OneHandw = NIL THEN  RemoveHandler(); HALT(20); END;
 I.PrintIText(OneHandw.rPort,myText,0,0);
 I.PrintIText(OneHandw.rPort,lampText,0,0);
END HandleScrSwitch;


PROCEDURE HandleCaps();
BEGIN
 IF Qualify[CapsID] = 0 THEN
  lampText.frontPen := onColor;
  I.PrintIText(OneHandw.rPort,lampText,0,0);
  Qualify[CapsID] := 1;
 ELSE
  lampText.frontPen := offColor;
  I.PrintIText(OneHandw.rPort,lampText,0,0);
  Qualify[CapsID] := 0;
 END;
END HandleCaps;


BEGIN
 Init();
 OneHandw := I.OpenWindow(OneHandnw);
 IF OneHandw = NIL THEN HALT(20); END;
 IF InstallHandler() = FALSE THEN
  I.CloseWindow(OneHandw);
  HALT(20);
 END;
 I.PrintIText(OneHandw.rPort,myText,0,0);
 I.PrintIText(OneHandw.rPort,lampText,0,0);
 LOOP
  e.WaitPort(OneHandw.userPort);
  imsg := e.GetMsg(OneHandw.userPort);
  imsgClass := imsg.class;
  gadptr := imsg.iAddress;
  e.ReplyMsg(imsg);
  IF (I.gadgetUp IN imsgClass) THEN
   IF gadptr.gadgetID = ScrSwitchID THEN HandleScrSwitch();
   ELSIF gadptr.gadgetID = CapsID THEN HandleCaps();
   ELSIF I.selected IN gadptr.flags THEN Qualify[gadptr.gadgetID] := 1;
   ELSE  Qualify[gadptr.gadgetID] := 0; END;
  ELSE I.CloseWindow(OneHandw); RemoveHandler(); EXIT; END;
 END;
END OneHand.
