home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 2 / FFMCD02.bin / new / amigalibdisks / disk938 / angie / angie.mod < prev    next >
Text File  |  1993-12-21  |  104KB  |  3,344 lines

  1.  
  2. (* --------------------------------------------------------------------------
  3.   :Program.       Angie.mod
  4.   :Contents.      "ANGIE - ANother Great Intuition Enhancer" - commodity
  5.   :Author.        Franz Schwarz
  6.   :Copyright.     Giftware (Freely distributable, yet copyrighted software. 
  7.   :Copyright.     If you like this magnificent;-) piece of software, you 
  8.   :Copyright.     are encouraged to send the author a present, a nice
  9.   :Copyright.     postcard, money, or something else pleasing the author.)
  10.   :Language.      Oberon-2
  11.   :Translator.    Amiga Oberon 3.00
  12.   :History.       v1.0 20.10.93 [fSchwarz]
  13.   :History.       v1.1 22.10.93 [fSchwarz] improved setDefPubScreen action
  14.   :History.         fixed ActivateXXXXScreen, fixed Menu Attrs selection
  15.   :History.       v1.2 23.10.93 [fSchwarz] doesn't send any closeWindow
  16.   :History.         event on Close action when window is blocked by
  17.   :History.         requesters.
  18.   :History.       v1.3 24.10.93 [fSchwarz] added Edithook for hotkey
  19.   :History.         definition gadget
  20.   :History.       v1.4a 29.10.93 [fSchwarz] major code cleanup, now
  21.   :History.         supports dos command and inputevent insertion type
  22.   :History.       v1.5 4.11.93 [fSchwarz] now really uses the frontmost
  23.   :History.         window of screens instead of just screen.firstWindow;
  24.   :History.         improved Key Screen Activation handling for screens
  25.   :History.         without windows
  26.   :History.       v1.6 4.11.93 [fSchwarz] removed last Intuition stuff from
  27.   :History.         cxcustom inputhandler - now all accesses to Intuition
  28.   :History.         structures are safeguarded by official CBM protocols;
  29.   :History.         enhanced Intuition/GadTools V37 GUI
  30.   :Imports.       CxLib 1.0b, BlackMagic 1.13
  31.   :Address.       Mühlenstraße 2, D-78591 Durchhausen, Germany / R.F.A.
  32.   :Address.       uucp: Franz_Schwarz@mil.ka.sub.org - Fido: 2:2476/506.18
  33.   :Remark.        Requires OS3.0 interface modules update by hartmut Goebel
  34.   :Remark.        Amiga-Oberon 3.00 checks string pointers to be even if
  35.   :Remark.        OddChk is enabled; thus don't compile with OddChk. The
  36.   :Remark.        compiler's options stack is broken as of Amiga-Oberon 3.00
  37.   :Usage.         Angie [args] (see doc / icon for help)
  38. -------------------------------------------------------------------------- *)
  39.  
  40. (* $SET NODEBUG *)
  41.  
  42. MODULE Angie;
  43.  
  44. IMPORT
  45.   b: BlackMagic, co: Commodities, cx: CxLib, ie: InputEvent,
  46.   e: Exec, I: Intuition, ti: Timer, H: Hardware, g: Graphics,
  47.   l: Layers, d: Dos, ic: Icon, o: OberonLib, st: Strings, u: Utility,
  48.   gt: GadTools, ag: AngieGUI, y: SYSTEM, es: ExecSupport, wb: Workbench,
  49.   sp: SPrintf
  50.   (* $IF DEBUG *) , io, NoGuru (* $END *) ;
  51.  
  52. CONST
  53.   verTag = "\000$VER: Angie 1.6 (4.11.93) © Franz Schwarz - Giftware";
  54.  
  55. CONST
  56.   true = TRUE; false = FALSE; (* adapt to common lower case CONST style *)
  57.  
  58. CONST
  59.   strGadLen = 256; (* size shrunk since I'm tired of e.STRPTR-related problems *)
  60.  
  61.           (* ** Interface module bug fixes: ** *)
  62. VAR
  63.   coBase: e.LibraryPtr;
  64. (* CxBroker err parameter register mismatch in Commodities.mod! *)
  65. PROCEDURE CxBroker {coBase, -36} (VAR nb{8}: co.NewBroker;
  66.                                   err{0}   : UNTRACED POINTER TO LONGINT): co.CxObjPtr;
  67. CONST
  68.   sposMakeVisible = 1; (* misdefinition in Intuition.mod   *)
  69.   unique = 0;          (* misdefinition in Commodities.mod *)
  70.   notify = 1;          (* misdefinition in Commodities.mod *)
  71.  
  72. CONST
  73.   cnb = co.NewBroker (co.nbVersion, y.ADR ("Angie"), y.ADR (verTag[7]),
  74.                       y.ADR ("ANother Great Intuition Enhancer"),
  75.                       {unique, notify}, {co.showHide}, 0, NIL, 0);
  76.  
  77.  
  78.   frontAttrStr   = "WFront";
  79.   frontAttrConst = 256;
  80.   
  81.   noKeyScrActAttrStr   = "NoKeyScrAct";
  82.   noKeyScrActAttrConst = 512;
  83.  
  84.   repeatAttrStr   = "Repeatable";
  85.   repeatAttrConst = 1024;
  86.   
  87.   cxPopUpStr = "CX_POPUP";
  88.  
  89.   cxPriorityStr = "CX_PRIORITY";
  90.   
  91.   keyActivateStr = "KEYACTIVATE";
  92.   
  93.   shuffleBackdropStr = "SHUFFLEBACKDROP";
  94.   
  95.   shufflePatStr = "SHUFFLEPAT";
  96.   
  97.   defaultShufflePat = "#?";
  98.  
  99.   huntAlwaysStr = "HUNTMODEALWAYS";
  100.  
  101.   huntWinToFrontStr = "HUNTMODEWFRONT";
  102.   
  103.   huntSetDefPubModeStr = "HUNTMODESETDEFPUBSCR";
  104.  
  105.   stableTimeStr = "STABLETIME";
  106.  
  107.   snoopDelayStr = "SNOOPDELAY";
  108.  
  109.   incWinTaskPriStr = "RAISEWINTASKPRI";
  110.  
  111.   scrMoveStepsStr = "SCRMOVESTEPS";
  112.  
  113.   winMoveStepsStr = "WINMOVESTEPS";
  114.   
  115.   doNotWaitStr = "DONOTWAIT";
  116.  
  117. TYPE
  118.   MiscTTNamesArr = ARRAY 14 OF b.LStrPtr;
  119.   
  120. CONST
  121.   miscTTNames = MiscTTNamesArr (y.ADR (cxPopUpStr),  
  122.                                 y.ADR (cxPriorityStr),
  123.                                 y.ADR (keyActivateStr),
  124.                                 y.ADR (shuffleBackdropStr),
  125.                                 y.ADR (shufflePatStr),
  126.                                 y.ADR (huntAlwaysStr),
  127.                                 y.ADR (huntWinToFrontStr),
  128.                                 y.ADR (huntSetDefPubModeStr),
  129.                                 y.ADR (stableTimeStr),
  130.                                 y.ADR (snoopDelayStr),
  131.                                 y.ADR (incWinTaskPriStr),
  132.                                 y.ADR (scrMoveStepsStr),
  133.                                 y.ADR (winMoveStepsStr),
  134.                                 y.ADR (doNotWaitStr));
  135.  
  136.  
  137.  
  138.  
  139.   popGUI = 0;
  140.   popGUINam = "CX_POPKEY";
  141.  
  142.   huntWindow = 1;
  143.   huntWindowNam = "HuntWindow";
  144.  
  145.   activate = 2;
  146.   activateNam = "Activate";
  147.  
  148.   activateNext = 3;
  149.   activateNextNam = "ActivateNext";
  150.  
  151.   activatePrev = 4;
  152.   activatePrevNam = "ActivatePrev";
  153.  
  154.   activateBackDrop = 5;
  155.   activateBackDropNam = "ActivateBackDrop";
  156.  
  157.   activateFrontScr = 6;
  158.   activateFrontScrNam = "ActivateFrontScr";
  159.  
  160.   lastActive = 7;
  161.   lastActiveNam = "LastActive";
  162.  
  163.   lastActiveScr = 8;
  164.   lastActiveScrNam = "LastActiveScr";
  165.  
  166.   activeToFront = 9;
  167.   activeToFrontNam = "ToFront";
  168.  
  169.   activeToBack = 10;
  170.   activeToBackNam = "ToBack";
  171.  
  172.   adaptWindow = 11;
  173.   adaptWindowNam = "AdaptWindow";
  174.   
  175.   centerWin = 12;
  176.   centerWinNam = "Center";
  177.  
  178.   zipWin = 13;
  179.   zipWinNam = "Zip";
  180.  
  181.   closeWin = 14;
  182.   closeWinNam = "Close";
  183.  
  184.   maxWin = 15;
  185.   maxWinNam = "Max"; 
  186.  
  187.   maxWinWidth = 16;
  188.   maxWinWidthNam = "MaxWidth";
  189.  
  190.   maxWinHeight = 17;
  191.   maxWinHeightNam = "MaxHeight";
  192.  
  193.   minWin = 18;
  194.   minWinNam = "Min"; 
  195.  
  196.   moveWinLeft = 19;
  197.   moveWinLeftNam = "MoveLeft";
  198.  
  199.   moveWinRight = 20;
  200.   moveWinRightNam = "MoveRight";
  201.  
  202.   moveWinUp = 21;
  203.   moveWinUpNam = "MoveUp";
  204.  
  205.   moveWinDown = 22;
  206.   moveWinDownNam = "MoveDown";
  207.   
  208.   upperLeftWin = 23;
  209.   upperLeftWinNam = "UpperLeft";
  210.  
  211.   lowerLeftWin = 24;
  212.   lowerLeftWinNam = "LowerLeft";
  213.  
  214.   upperRightWin = 25;
  215.   upperRightWinNam = "UpperRight";
  216.  
  217.   lowerRightWin = 26;
  218.   lowerRightWinNam = "LowerRight";
  219.  
  220.   expandWidth = 27;
  221.   expandWidthNam = "ExpandWidth";
  222.  
  223.   expandHeight = 28;
  224.   expandHeightNam = "ExpandHeight";
  225.  
  226.   shrinkWidth = 29;
  227.   shrinkWidthNam = "ShrinkWidth";
  228.  
  229.   shrinkHeight = 30;
  230.   shrinkHeightNam = "ShrinkHeight";
  231.  
  232.   doubleWidth = 31;
  233.   doubleWidthNam = "DoubleWidth";
  234.  
  235.   doubleHeight = 32;
  236.   doubleHeightNam = "DoubleHeight";
  237.  
  238.   halveWidth = 33;
  239.   halveWidthNam = "HalveWidth";
  240.  
  241.   halveHeight = 34;
  242.   halveHeightNam = "HalveHeight";
  243.   
  244.  
  245.   activateNextScreen = 35;
  246.   activateNextScreenNam = "ActivateNextScreen";
  247.  
  248.   activatePrevScreen = 36;
  249.   activatePrevScreenNam = "ActivatePrevScreen";
  250.  
  251.   activateWBenchScreen = 37;
  252.   activateWBenchScreenNam = "ActivateWBenchScreen";
  253.  
  254.   activateDefPubScreen = 38;
  255.   activateDefPubScreenNam = "ActivateDefPubScreen";
  256.  
  257.   nextScreen = 39;
  258.   nextScreenNam = "NextScreen";
  259.  
  260.   prevScreen = 40;
  261.   prevScreenNam = "PrevScreen";
  262.  
  263.   wbenchScreen = 41;
  264.   wbenchScreenNam = "WBenchScreen";
  265.  
  266.   defPubScreen = 42;
  267.   defPubScreenNam = "DefPubScreen";
  268.  
  269.   scrollScrLeft = 43;
  270.   scrollScrLeftNam = "ScrollScrLeft";
  271.  
  272.   scrollScrRight = 44;
  273.   scrollScrRightNam = "ScrollScrRight";
  274.  
  275.   scrollScrUp = 45;
  276.   scrollScrUpNam = "ScrollScrUp";
  277.  
  278.   scrollScrDown = 46;
  279.   scrollScrDownNam = "ScrollScrDown";
  280.  
  281.   upperLeftScr = 47;
  282.   upperLeftScrNam = "UpperLeftScr";
  283.  
  284.   lowerLeftScr = 48;
  285.   lowerLeftScrNam = "LowerLeftScr";
  286.  
  287.   upperRightScr = 49;
  288.   upperRightScrNam = "UpperRightScr";
  289.  
  290.   lowerRightScr = 50;
  291.   lowerRightScrNam = "LowerRightScr";
  292.  
  293.   showScrCenter = 51;
  294.   showScrCenterNam = "ShowScrCenter";
  295.   
  296.   screenTop = 52;
  297.   screenTopNam = "ScreenTop";
  298.   
  299.   setDefPubScreen = 53;
  300.   setDefPubScreenNam = "SetDefPubScreen";
  301.  
  302.   filter = 54;
  303.   filterNam = "Filter";
  304.   
  305.   noKeyActivate = 55;
  306.   noKeyActivateNam = "NoKeyActivate";
  307.  
  308.   custom = 56;
  309.   customNam = "Custom";
  310.   
  311.   hotKeys = 57;
  312.  
  313.  
  314.   huntZipped       = hotKeys;  
  315.   huntSigd         = hotKeys+1;
  316.   scrActivateMagic = hotKeys+2;
  317.  
  318.   sendHuntZipped = huntZipped + frontAttrConst;  
  319.   sendHuntSigd = huntSigd + frontAttrConst;
  320.  
  321. TYPE
  322.   HotArr = ARRAY hotKeys+1 OF b.LStrPtr;
  323.  
  324.  
  325. CONST
  326.   hotnames = HotArr (
  327.     y.ADR (popGUINam),
  328.     y.ADR (huntWindowNam),
  329.     y.ADR (activateNam),
  330.     y.ADR (activateNextNam),
  331.     y.ADR (activatePrevNam),
  332.     y.ADR (activateBackDropNam),
  333.     y.ADR (activateFrontScrNam),
  334.     y.ADR (lastActiveNam),
  335.     y.ADR (lastActiveScrNam),
  336.     y.ADR (activeToFrontNam),
  337.     y.ADR (activeToBackNam),
  338.     y.ADR (adaptWindowNam),
  339.     y.ADR (centerWinNam),
  340.     y.ADR (zipWinNam),
  341.     y.ADR (closeWinNam),
  342.     y.ADR (maxWinNam),
  343.     y.ADR (maxWinWidthNam),
  344.     y.ADR (maxWinHeightNam),
  345.     y.ADR (minWinNam),
  346.     y.ADR (moveWinLeftNam),
  347.     y.ADR (moveWinRightNam),
  348.     y.ADR (moveWinUpNam),
  349.     y.ADR (moveWinDownNam),
  350.     y.ADR (upperLeftWinNam),
  351.     y.ADR (lowerLeftWinNam),
  352.     y.ADR (upperRightWinNam),
  353.     y.ADR (lowerRightWinNam),
  354.     y.ADR (expandWidthNam),
  355.     y.ADR (expandHeightNam),
  356.     y.ADR (shrinkWidthNam),
  357.     y.ADR (shrinkHeightNam),
  358.     y.ADR (doubleWidthNam),
  359.     y.ADR (doubleHeightNam),
  360.     y.ADR (halveWidthNam),
  361.     y.ADR (halveHeightNam),
  362.     y.ADR (activateNextScreenNam),
  363.     y.ADR (activatePrevScreenNam),
  364.     y.ADR (activateWBenchScreenNam),
  365.     y.ADR (activateDefPubScreenNam),
  366.     y.ADR (nextScreenNam),
  367.     y.ADR (prevScreenNam),
  368.     y.ADR (wbenchScreenNam),
  369.     y.ADR (defPubScreenNam),
  370.     y.ADR (scrollScrLeftNam),
  371.     y.ADR (scrollScrRightNam),
  372.     y.ADR (scrollScrUpNam),
  373.     y.ADR (scrollScrDownNam),
  374.     y.ADR (upperLeftScrNam),
  375.     y.ADR (lowerLeftScrNam),
  376.     y.ADR (upperRightScrNam),
  377.     y.ADR (lowerRightScrNam),
  378.     y.ADR (showScrCenterNam),
  379.     y.ADR (screenTopNam),
  380.     y.ADR (setDefPubScreenNam),
  381.     y.ADR (filterNam),
  382.     y.ADR (noKeyActivateNam),
  383.     y.ADR (customNam),
  384.     NIL
  385.   );
  386.  
  387.  
  388. CONST
  389.   close1 = ie.InputEventAdr (NIL, ie.closewindow, 0, 0, {}, NIL, 0, 0);
  390.  
  391. VAR
  392.   Close1: ie.InputEventAdr;
  393.  
  394. VAR
  395.   ScrKeys, ScrKeys1, ScrKeys2: UNTRACED POINTER TO ARRAY OF co.IX;
  396.   DummyIX: co.IX;
  397.  
  398.  
  399. VAR
  400.   cx38              : BOOLEAN;
  401.   int39             : BOOLEAN;
  402.   active            : BOOLEAN;
  403.   nb                : co.NewBroker;
  404.   br, cxcustom      : co.CxObjPtr;  
  405.   cxcustomfilter    : co.CxObjPtr;
  406.   huntwindowalways  : BOOLEAN;
  407.   huntwindowwfr     : BOOLEAN;
  408.   setdefpubonhunt   : BOOLEAN;
  409.   keyactivate       : BOOLEAN;
  410.   shufflebackdrop   : BOOLEAN;
  411.   incwintaskpri     : BOOLEAN;
  412.   shuffle           : b.DynStrPtr;
  413.   shufflestr        : b.DynStrPtr;
  414.   stabletime        : LONGINT;
  415.   snoopdelay        : LONGINT;
  416.   scrMoveSteps      : INTEGER;
  417.   winMoveSteps      : INTEGER;
  418.   cxpopup           : BOOLEAN;
  419.  
  420.   hotdeflist        : e.List;  
  421.  
  422. TYPE
  423.   WinScr = STRUCT
  424.     scr : I.ScreenPtr;
  425.     win : I.WindowPtr;
  426.   END;
  427.  
  428. VAR
  429.   ScrArr      : ARRAY 40 OF WinScr;
  430.   lastwin     : WinScr;
  431.   lastscrwin  : WinScr;
  432.   zipwin      : WinScr;
  433.  
  434.  
  435. CONST
  436.   nilWinScr = WinScr (NIL, NIL);
  437.  
  438. TYPE
  439.   DispInfo = STRUCT
  440.     activeScr: I.ScreenPtr;
  441.     activeWin: WinScr;
  442.     winBox   : I.IBox;
  443.     time     : ti.TimeVal;
  444.   END;
  445.  
  446. VAR
  447.   dinfopass         : DispInfo;
  448.   dinfotask         : DispInfo;
  449.   dinfochange       : BOOLEAN;
  450.   dinfosig          : INTEGER;
  451.   chieftask         : e.TaskPtr;
  452.   IncTask           : e.TaskPtr;
  453.   chiefpri          : SHORTINT;
  454.   retpri            : SHORTINT;
  455.   tval1, tval2      : ti.TimeVal;
  456.   stabletval        : ti.TimeVal;
  457.  
  458.  
  459. CONST
  460.   init          = 1; (* ChildTask states *)
  461.   ok            = 2;
  462.   requestDie    = 3;
  463.   died          = 4;
  464.   yetUnlaunched = 0;
  465.  
  466. VAR
  467.   ChildState        : SHORTINT;
  468.   ChildStack        : ARRAY 1001 OF LONGINT;
  469.   tcb               : e.Task;
  470.  
  471. CONST
  472.   ctcbnd = e.Node (NIL, NIL, e.task, 9, y.ADR ("Angie Snoop"));
  473.  
  474. (*
  475.  * $StackChk- 
  476.  * !!No stack checking in cxcustom & child task accessable code, please!!
  477.  *)
  478.  
  479. PROCEDURE IsValidScr (scr: I.ScreenPtr): BOOLEAN;
  480. VAR
  481.   si: I.ScreenPtr;
  482. BEGIN
  483.   si := I.int.firstScreen;
  484.   WHILE (si # NIL) & (si # scr) DO si := si.nextScreen; END;
  485.   RETURN si # NIL;
  486. END IsValidScr;  
  487.  
  488. PROCEDURE IsValidWinScr (VAR sa: WinScr): BOOLEAN;
  489. VAR
  490.   wi: I.WindowPtr;
  491.  
  492. BEGIN
  493.   IF ~IsValidScr (sa.scr) THEN RETURN false; END;
  494.   wi := sa.scr.firstWindow;
  495.   WHILE (wi # NIL) & (wi # sa.win) DO wi := wi.nextWindow; END;
  496.   RETURN wi # NIL;
  497. END IsValidWinScr;
  498.  
  499. PROCEDURE ValidateScrArr ();
  500. VAR
  501.   i: INTEGER;
  502. BEGIN
  503.   FOR i := 0 TO LEN (ScrArr)-1 DO
  504.     IF ~IsValidWinScr (ScrArr[i]) THEN
  505.       e.Disable();
  506.       ScrArr[i] := nilWinScr;
  507.       e.Enable();
  508.     END;
  509.   END;
  510. END ValidateScrArr;
  511.  
  512. PROCEDURE UpdateScrArr (VAR sa: WinScr);
  513. VAR
  514.   i, j  : INTEGER;
  515. BEGIN
  516.   IF (sa.win = NIL) OR (sa.scr = NIL) THEN RETURN; END;
  517.   FOR i := 0 TO LEN (ScrArr)-1 DO
  518.     IF sa.scr = ScrArr[i].scr THEN
  519.       e.Disable(); ScrArr[i].win := sa.win; e.Enable();
  520.       RETURN;
  521.     END;
  522.   END;
  523.   FOR j := 0 TO 1 DO
  524.     FOR i := 0 TO LEN (ScrArr)-1 DO
  525.       IF ScrArr[i].scr = NIL THEN
  526.         e.Disable();
  527.         ScrArr[i].scr := sa.scr;
  528.         ScrArr[i].win := sa.win;
  529.         e.Enable();
  530.         RETURN;
  531.       END;
  532.     END; (* FOR i *)
  533.     ValidateScrArr();
  534.   END; (* FOR j *)
  535.   e.Disable();
  536.   ScrArr[LEN (ScrArr) DIV 2].scr := sa.scr;
  537.   ScrArr[LEN (ScrArr) DIV 2].win := sa.win;
  538.   e.Enable();
  539. END UpdateScrArr;
  540.  
  541. PROCEDURE ScrFrontWin (scr: I.ScreenPtr): I.WindowPtr;
  542. VAR
  543.   ly: g.LayerPtr;
  544.   w : I.WindowPtr;
  545. BEGIN
  546.   w := NIL;
  547.   IF scr = NIL THEN RETURN NIL; END;
  548.   l.LockLayerInfo (y.ADR (scr.layerInfo));
  549.   ly := scr.layerInfo.topLayer;
  550.   LOOP
  551.     IF ly = NIL THEN EXIT; END;
  552.     IF ly # scr.barLayer THEN w := ly.window; END;
  553.     IF w # NIL THEN EXIT; END;
  554.     ly := ly.back;
  555.   END;  
  556.   IF w = NIL THEN w := scr.firstWindow; END;
  557.   l.UnlockLayerInfo (scr.layerInfo);
  558.   RETURN w;
  559. END ScrFrontWin;  
  560.  
  561. CONST
  562.   exactWin    = 0;
  563.   multiScrWin = 1;
  564.  
  565. PROCEDURE MouseWin (mode: INTEGER): I.WindowPtr;
  566. VAR
  567.   ly : g.LayerPtr;
  568.   scr: I.ScreenPtr;
  569.   lsc: I.ScreenPtr;
  570.   w  : I.WindowPtr;
  571. BEGIN
  572.   CASE mode OF exactWin, multiScrWin: ELSE RETURN NIL; END;
  573.   scr := I.int.firstScreen; lsc := NIL;
  574.   LOOP
  575.     IF mode = multiScrWin THEN
  576.       WHILE (scr # NIL) & (scr.firstWindow = NIL) DO scr := scr.nextScreen; END;
  577.     END;  
  578.     IF scr = NIL THEN
  579.       IF mode = exactWin THEN RETURN NIL; END;
  580.       RETURN ScrFrontWin (lsc);
  581.     END;
  582.     IF g.vpHide IN scr.viewPort.modes THEN
  583.       IF mode = exactWin THEN RETURN NIL; END;
  584.       RETURN ScrFrontWin (lsc);
  585.     END;
  586.     IF scr.mouseY >=0 THEN
  587.       ly := l.WhichLayer (y.ADR (scr.layerInfo), scr.mouseX, scr.mouseY);
  588.       IF ly # NIL THEN        
  589.         IF ly # scr.barLayer THEN 
  590.           w := ly.window;
  591.           IF w # NIL THEN RETURN w; END;
  592.         END;  
  593.       END;
  594.       IF mode = exactWin THEN RETURN NIL; END;
  595.       RETURN ScrFrontWin (scr);
  596.     END;
  597.     lsc := scr; scr := scr.nextScreen;
  598.   END;
  599. END MouseWin;
  600.  
  601.  
  602. PROCEDURE GetScrWin (s: I.ScreenPtr): I.WindowPtr;
  603. VAR
  604.   i: INTEGER;
  605.   w: I.WindowPtr;
  606.  
  607. BEGIN
  608.   FOR i := 0 TO LEN (ScrArr)-1 DO
  609.     IF ScrArr[i].scr = s THEN
  610.       IF IsValidWinScr (ScrArr[i]) THEN
  611.         w :=  ScrArr[i].win;
  612.         RETURN w;
  613.       END;
  614.     END;
  615.   END; (* FOR *)
  616.   RETURN NIL;
  617. END GetScrWin;
  618.  
  619. PROCEDURE GetBestWin (): I.WindowPtr;
  620. VAR
  621.   w1,w2: I.WindowPtr;
  622.   s: I.ScreenPtr;
  623. BEGIN
  624.   w1 := MouseWin (multiScrWin);
  625.   IF w1 # NIL THEN s := w1.wScreen; ELSE s := I.int.firstScreen; END;
  626.   w2 := GetScrWin (s);
  627.   IF w2 # NIL THEN RETURN w2; END;
  628.   IF w1 # NIL THEN RETURN w1; END;
  629.   RETURN ScrFrontWin (s);
  630. END GetBestWin;
  631.  
  632.  
  633. VAR
  634.   qual    : SET;
  635.   lmbstate: SET;
  636.  
  637. CONST
  638.   lmbPressed    = 0;
  639.   lmbEmulated   = 1;
  640.   lmbEffective  = 2;
  641.  
  642.  
  643. PROCEDURE CxCustomHandler * (obj: co.CxObjPtr; msg: co.CxMsgPtr);
  644. VAR
  645.   ev    : ie.InputEventPtr;
  646.   w     : I.WindowPtr;
  647.   s     : I.ScreenPtr;
  648.   i     : LONGINT;
  649. (* $DeallocPars- $SaveRegs+ *)
  650. BEGIN
  651.   ev := co.CxMsgData (msg);
  652.   IF qual # ev.qualifier THEN
  653.     qual := ev.qualifier;
  654.     IF (lmbPressed IN lmbstate) & ~(ie.leftButton IN qual) THEN 
  655.       lmbstate := lmbstate - {lmbPressed, lmbEffective};
  656.     ELSIF ~(lmbPressed IN lmbstate) & (ie.leftButton IN qual) THEN
  657.       lmbstate := lmbstate + {lmbPressed, lmbEffective};
  658.     END;  
  659.     IF (lmbEmulated IN lmbstate) & ~(ie.lAlt IN qual) THEN
  660.       lmbstate := lmbstate - {lmbEmulated, lmbEffective};
  661.     ELSIF ~(lmbEmulated IN lmbstate) & (ie.lAlt IN qual) &
  662.           ({ie.lCommand, ie.rCommand} * qual # {}) THEN
  663.       lmbstate := lmbstate + {lmbEmulated, lmbEffective};
  664.     END;  
  665.   END;  
  666.   IF ~keyactivate OR ~active THEN RETURN; END;
  667.   IF ev.class # ie.rawkey THEN RETURN; END;
  668.   IF ev.code >= ie.upPrefix THEN RETURN; END;
  669.   IF cx38 THEN (* MatchIX() available: *)
  670.     IF ScrKeys # NIL THEN
  671.       FOR i := 0 TO LEN (ScrKeys^)-1 DO
  672.         IF co.MatchIX (ev, y.ADR (ScrKeys[i])) THEN RETURN; END;
  673.       END;
  674.     END;  
  675.   END;
  676.   w := I.int.activeWindow;
  677.   IF (y.VAL (LONGSET, w) * LONGSET {0, 31} = LONGSET {}) &
  678.      (w # NIL) & (I.menuState IN w.flags) THEN RETURN; END;
  679.   s := I.int.activeScreen;
  680.   IF (s = NIL) OR (y.VAL (LONGSET, s) * LONGSET {0, 31} # LONGSET {}) OR
  681.      ~(g.vpHide IN s.viewPort.modes) THEN RETURN; END;
  682.   co.DivertCxMsg (msg, cxcustomfilter, cxcustom);
  683. END CxCustomHandler;
  684.  
  685. (* $IF SmallData *)
  686. TYPE
  687.   CustomCxStubT = STRUCT
  688.     code1 : ARRAY 2 OF INTEGER;
  689.     a5    : e.APTR;
  690.     code2 : ARRAY 6 OF INTEGER;
  691.     jsr   : co.CustomProcType;
  692.     code3 : ARRAY 3 OF INTEGER;
  693.   END;
  694.  
  695. CONST
  696.   customCxStub = CustomCxStubT (02F0DU, 02A7CU, NIL, 04CEFU, 00003U, 00008U, 
  697.                                 048E7U, 0C000U, 04EB9U, CxCustomHandler,
  698.                                 0508FU, 02A5FU, 04E75U);
  699.  
  700. VAR
  701.   CustomCxStub: CustomCxStubT;  
  702. (* $END *)
  703.  
  704.  
  705. CONST
  706.   nilTVal = ti.TimeVal (0, 0);
  707.  
  708. PROCEDURE SetStableTime (n: LONGINT);
  709. BEGIN
  710.   e.Forbid ();
  711.   stabletime := b.Max2 (-1, b.Min2 (1000, n));
  712.   IF stabletime >= 0 THEN
  713.     stabletval.secs  := stabletime DIV 1000;
  714.     stabletval.micro := (stabletime MOD 1000) * 1000;
  715.   ELSE
  716.     stabletval := nilTVal;
  717.   END;  
  718.   e.Permit ();
  719. END SetStableTime;  
  720.  
  721.  
  722. VAR
  723.   snooptval         : ti.TimeVal;
  724.  
  725. PROCEDURE SetSnoopDelay (n: LONGINT);
  726. BEGIN
  727.   snoopdelay := b.Max2 (10, b.Min2 (1000, n));
  728.   e.Forbid();
  729.   snooptval.secs  := snoopdelay DIV 1000;
  730.   snooptval.micro := (snoopdelay MOD 1000) * 1000;
  731.   e.Permit();
  732. END SetSnoopDelay;
  733.  
  734. (*
  735.  * CHILDTASK LOCAL VARS - global due to access efficiency considerations
  736.  * from within IBaseChanged():
  737.  *)
  738.  
  739. VAR
  740.   childtimerport         : e.MsgPortPtr;
  741.   childtio               : ti.TimeRequestPtr;
  742.   dinfoold, dinfonew     : DispInfo;
  743.  
  744. PROCEDURE ChildTask * ();
  745.  
  746.   PROCEDURE Init(): BOOLEAN;
  747.   BEGIN
  748.     LOOP
  749.       childtimerport := e.CreateMsgPort ();
  750.       childtio := e.CreateIORequest (childtimerport, SIZE (childtio^));
  751.       IF childtio = NIL THEN EXIT; END;
  752.       IF e.OpenDevice (ti.timerName, ti.vBlank, childtio, LONGSET{}) # 0 THEN EXIT; END;
  753.       ti.base := childtio.node.device;
  754.       childtio.node.command := ti.addRequest;
  755.       ChildState := ok;
  756.       EXIT;
  757.     END;  
  758.     e.Signal (chieftask, LONGSET {dinfosig});
  759.     RETURN ChildState = ok;
  760.   END Init;
  761.  
  762.   PROCEDURE CleanUp();
  763.   BEGIN
  764.     IF childtio # NIL THEN e.CloseDevice (childtio); END;
  765.     e.DeleteIORequest (childtio);
  766.     e.DeleteMsgPort (childtimerport);
  767.     e.Forbid();
  768.     ChildState := died;
  769.     e.Signal (chieftask, LONGSET {dinfosig});
  770.   END CleanUp;
  771.  
  772.  
  773. PROCEDURE IBaseChanged (): BOOLEAN;
  774. VAR
  775.   lk  : LONGINT;
  776.   r   : BOOLEAN;
  777. BEGIN
  778.   r := false;
  779.   lk := I.LockIBase (0);
  780.   LOOP
  781.     IF stabletime < 0 THEN dinfochange := false; END;
  782.     dinfoold := dinfonew;
  783.     dinfonew.activeWin := nilWinScr;
  784.     e.Disable();
  785.     dinfonew.activeScr := I.int.activeScreen;
  786.     dinfonew.activeWin.win := I.int.activeWindow;
  787.     IF dinfonew.activeWin.win # NIL THEN
  788.       dinfonew.activeWin.scr := dinfonew.activeWin.win.wScreen;
  789.     END;
  790.     e.Enable();
  791.     IF (dinfonew.activeWin.scr # dinfonew.activeScr) OR (dinfonew.activeScr = NIL) THEN
  792.       dinfonew.activeWin := nilWinScr;
  793.     END;
  794.     IF dinfonew.activeWin.win # NIL THEN
  795.       dinfonew.activeWin.scr := dinfonew.activeWin.win.wScreen;
  796.       dinfonew.winBox := y.VAL (I.IBoxPtr, y.ADR (dinfonew.activeWin.win.leftEdge))^;
  797.       IF dinfoold.activeWin.win # dinfonew.activeWin.win THEN
  798.         IF dinfoold.activeWin.win # NIL THEN
  799.           lastwin := dinfoold.activeWin;
  800.           IF dinfoold.activeWin.scr # dinfonew.activeWin.scr THEN
  801.             lastscrwin := dinfoold.activeWin;
  802.           END;  
  803.         END;  
  804.         UpdateScrArr(dinfonew.activeWin);
  805.       ELSIF ~huntwindowalways & ~incwintaskpri & (IncTask = NIL) THEN 
  806.         EXIT;        
  807.       ELSE
  808.         IF dinfoold.activeScr = dinfonew.activeScr THEN
  809.           IF dinfoold.winBox.left = dinfonew.winBox.left THEN
  810.             IF dinfoold.winBox.top = dinfonew.winBox.top THEN
  811.               IF dinfoold.winBox.width = dinfonew.winBox.width THEN
  812.                 IF dinfoold.winBox.height = dinfonew.winBox.height THEN
  813.                   IF dinfoold.time.secs = dinfonew.time.secs THEN
  814.                     IF dinfoold.time.micro = dinfonew.time.micro THEN
  815.                       IF dinfochange & ~(lmbEffective IN lmbstate) THEN
  816.                         ti.GetSysTime (tval1);
  817.                         e.Forbid(); tval2 := stabletval; e.Permit();
  818.                         ti.AddTime (tval2, dinfonew.time);
  819.                         IF ti.CmpTime (tval2, tval1) >= 0 THEN
  820.                           dinfopass := dinfonew;
  821.                           dinfochange := false;
  822.                           r := true;
  823.                         END;
  824.                       END;
  825.                       EXIT;
  826.                     END;
  827.                   END;
  828.                 END;
  829.               END;
  830.             END;
  831.           END;
  832.         END;
  833.       END;
  834.     END;
  835.     ti.GetSysTime (dinfonew.time);
  836.     IF stabletime < 0 THEN
  837.       IF lmbEffective IN lmbstate THEN
  838.         dinfonew.activeWin := nilWinScr;
  839.       ELSE  
  840.         dinfopass := dinfonew; r := true;
  841.       END; 
  842.     ELSE
  843.       dinfochange := true;
  844.     END;
  845.     EXIT;
  846.   END; (* LOOP *)
  847.   I.UnlockIBase (lk);
  848.   IF ~huntwindowalways & ~incwintaskpri & (IncTask = NIL) THEN r := false; END;
  849.   RETURN r
  850. END IBaseChanged;
  851.  
  852. BEGIN
  853.   (* $IF SmallData *) 
  854.     y.SETREG (13, e.exec.thisTask.userData);
  855.   (* $END *)
  856.   IF ~Init() THEN CleanUp(); RETURN; END;
  857.   LOOP
  858.     IF IBaseChanged() THEN e.Signal (chieftask, LONGSET {dinfosig}); END;
  859.     e.Forbid(); childtio.time := snooptval; e.Permit();
  860.     e.OldDoIO (childtio);
  861.     IF ChildState = requestDie THEN EXIT; END;
  862.   END;
  863.   CleanUp();
  864. END ChildTask;
  865.  
  866. (* $StackChk= !!end of code that is accessable from cxcustom or child task!! *)
  867.  
  868. PROCEDURE BoolToLBool (bool: BOOLEAN): I.LONGBOOL;
  869. BEGIN
  870.   IF bool THEN RETURN I.LTRUE; ELSE RETURN I.LFALSE; END;
  871. END BoolToLBool;  
  872.  
  873. VAR
  874.   guiwndsig: INTEGER;
  875.  
  876. VAR
  877.   hotdefs: b.DynTTPtr;  
  878.  
  879.   SelectedHotKey: LONGINT;
  880.  
  881. TYPE
  882.   HotKeyNodePtr = UNTRACED POINTER TO HotKeyNode;
  883.   HotKeyNode = STRUCT (node: e.Node)
  884.     cxobj: co.CxObjPtr;
  885.     type : LONGINT;
  886.     text : b.DynStrPtr;
  887.     def  : b.DynStrPtr;
  888.   END;  
  889.  
  890.  
  891.  
  892. PROCEDURE AttrsOfId (id: LONGINT): LONGINT;
  893. BEGIN
  894.   RETURN y.VAL (LONGINT, y.VAL (LONGSET, id) * LONGSET {8..10});
  895. END AttrsOfId;  
  896.  
  897. PROCEDURE PlainId (id: LONGINT): LONGINT;
  898. BEGIN
  899.   RETURN y.VAL (LONGINT, y.VAL (LONGSET, id) * LONGSET {0..7});
  900. END PlainId;  
  901.  
  902. PROCEDURE IsToFrontId (id: LONGINT): BOOLEAN;
  903. BEGIN
  904.   CASE PlainId (id) OF
  905.   activeToFront, huntWindow, popGUI:
  906.     RETURN true; |
  907.   nextScreen, prevScreen, wbenchScreen, defPubScreen, scrollScrLeft, 
  908.   scrollScrRight, scrollScrUp, scrollScrDown, upperLeftScr, lowerLeftScr, 
  909.   upperRightScr, lowerRightScr, showScrCenter, activeToBack, setDefPubScreen, 
  910.   screenTop, filter, noKeyActivate:
  911.     RETURN false; 
  912.   ELSE 
  913.     RETURN y.VAL (LONGSET, id) * y.VAL (LONGSET, frontAttrConst) # LONGSET {};
  914.   END;  
  915. END IsToFrontId;
  916.  
  917. PROCEDURE IsRepeatId (id: LONGINT): BOOLEAN;
  918. BEGIN
  919.   CASE PlainId (id) OF
  920.   noKeyActivate, filter:
  921.     RETURN true;
  922.   ELSE  
  923.     RETURN y.VAL (LONGSET, id) * y.VAL (LONGSET, repeatAttrConst) # LONGSET {};
  924.   END;  
  925. END IsRepeatId;
  926.  
  927. PROCEDURE IsNoKeyScrActId (id: LONGINT): BOOLEAN;
  928. BEGIN
  929.   CASE PlainId (id) OF
  930.   noKeyActivate:
  931.     RETURN true;
  932.   ELSE  
  933.     RETURN y.VAL (LONGSET, id) * y.VAL (LONGSET, noKeyScrActAttrConst) # LONGSET {};
  934.   END;  
  935. END IsNoKeyScrActId;
  936.  
  937. PROCEDURE IsValidId (id: LONGINT): BOOLEAN;
  938. BEGIN
  939.   IF (PlainId (id) < 0) OR (PlainId (id) >= hotKeys) THEN RETURN false; END;
  940.   RETURN y.VAL (LONGSET, id) * LONGSET {11..15} = LONGSET {};
  941. END IsValidId;
  942.  
  943. PROCEDURE AdaptIdToEntry (id: LONGINT; entry: LONGINT): LONGINT;
  944. BEGIN
  945.   id := PlainId (id) + AttrsOfId (id);
  946.   IF PlainId (id) = custom THEN INC (id, ASH (entry, 16)); END;
  947.   RETURN id;
  948. END AdaptIdToEntry;  
  949.   
  950. PROCEDURE GetHotKeyNode (i: LONGINT): HotKeyNodePtr;
  951. BEGIN
  952.   IF (i < 0) OR (i >= b.DynTTLen (hotdefs)) THEN RETURN NIL; END;
  953.   RETURN y.VAL (HotKeyNodePtr, hotdefs[i]);
  954. END GetHotKeyNode;  
  955.  
  956.  
  957. TYPE
  958.   editnmenu1T = ARRAY 7 OF gt.NewMenu;
  959.   
  960. CONST
  961.   MNfrontattr = 2000H;
  962.   MNnokeyscractattr = 2001H;
  963.   MNrepeatattr = 2002H;
  964.  
  965. TYPE
  966.   AttrT = STRUCT
  967.     isProc  : PROCEDURE (id: LONGINT): BOOLEAN;
  968.     menuId: e.APTR;
  969.     const : INTEGER;
  970.     name  : b.LStrPtr;
  971.   END;    
  972.  
  973.   AttrArr = ARRAY 3 OF AttrT;  
  974.   
  975. CONST
  976.   attrs = AttrArr (
  977.    IsToFrontId, MNfrontattr, frontAttrConst, y.ADR (frontAttrStr),
  978.    IsNoKeyScrActId, MNnokeyscractattr, noKeyScrActAttrConst, y.ADR (noKeyScrActAttrStr),
  979.    IsRepeatId, MNrepeatattr, repeatAttrConst, y.ADR (repeatAttrStr));
  980.   
  981. CONST  
  982.   editnmenu1 = editnmenu1T (
  983.     gt.title, y.ADR ("Edit·Hotkey·Type"), NIL, {}, y.VAL (LONGSET, 0), -1,
  984.     gt.item, y.ADR ("Attributes"), NIL, {}, y.VAL (LONGSET, 0), -1,
  985.     gt.sub, y.ADR ("Window To Front?"), y.ADR ("1"), {I.checkIt,I.menuToggle}, y.VAL (LONGSET, 0), MNfrontattr,
  986.     gt.sub, y.ADR ("No Key Screen Activation?"), y.ADR ("2"), {I.checkIt,I.menuToggle}, y.VAL (LONGSET, 0), MNnokeyscractattr,
  987.     gt.sub, y.ADR ("Repeatable?"), y.ADR ("3"), {I.checkIt,I.menuToggle}, y.VAL (LONGSET, 0), MNrepeatattr,
  988.     gt.item, gt.barLabel, NIL, {}, LONGSET {}, -1,
  989.     gt.end, NIL, NIL, {}, LONGSET {}, -1);
  990.  
  991. VAR
  992.   editnewmenu: ARRAY hotKeys+6 OF gt.NewMenu;
  993.   
  994.   editmenu: I.MenuPtr;
  995.  
  996. PROCEDURE SetupEditMenu(): INTEGER;
  997. VAR
  998.   i: INTEGER;
  999. BEGIN
  1000.   IF editmenu = NIL THEN
  1001.     FOR i := 0 TO 5 DO editnewmenu [i] := editnmenu1 [i]; END;
  1002.     editnewmenu [LEN (editnewmenu)-1] := editnmenu1 [LEN (editnmenu1)-1];
  1003.     FOR i := 0 TO hotKeys-1 DO
  1004.       editnewmenu [i+6] := editnmenu1 [1];
  1005.       editnewmenu [i+6].label := b.StrIndexA (hotnames[i]^, 0);
  1006.       editnewmenu [i+6].userData := i;
  1007.     END;
  1008.     editmenu := gt.CreateMenus (editnewmenu, gt.mnFrontPen, 0, u.done);
  1009.   END;  
  1010.   IF editmenu = NIL THEN RETURN 3 END;
  1011.   I.ClearMenuStrip (ag.AngieWnd);
  1012.   ag.AngieMenus.nextMenu := editmenu;
  1013.   IF NOT gt.LayoutMenus (ag.AngieMenus, ag.VisualInfo, 
  1014.                          gt.mnNewLookMenus, I.LTRUE, u.done) THEN RETURN 4 END;
  1015.   IF ~ I.SetMenuStrip (ag.AngieWnd, ag.AngieMenus^) THEN RETURN 5 END;
  1016.   RETURN 0;    
  1017. END SetupEditMenu;  
  1018.  
  1019. PROCEDURE GetMenuAttrs(): INTEGER;
  1020. VAR
  1021.   result: INTEGER;
  1022.   i     : INTEGER;
  1023.   item  : I.MenuItemPtr;
  1024. BEGIN
  1025.   result := 0;
  1026.   FOR i := 0 TO LEN (attrs)-1 DO  
  1027.     item := b.gtItemAddr (ag.AngieMenus, attrs[i].menuId);
  1028.     IF item # NIL THEN IF I.checked IN item.flags THEN 
  1029.       INC (result, attrs[i].const);
  1030.     END; END;  
  1031.   END;  
  1032.   RETURN result;
  1033. END GetMenuAttrs;
  1034.   
  1035. PROCEDURE SetMenuAttrs (n: LONGINT);
  1036. VAR
  1037.   i       : INTEGER;
  1038.   item    : I.MenuItemPtr;
  1039. BEGIN
  1040.   I.ClearMenuStrip (ag.AngieWnd);
  1041.   FOR i := 0 TO LEN (attrs)-1 DO
  1042.     item := b.gtItemAddr (ag.AngieMenus, attrs[i].menuId);
  1043.     IF item # NIL THEN
  1044.       IF attrs[i].isProc (n) THEN
  1045.         INCL (item.flags, I.checked); 
  1046.       ELSE 
  1047.         EXCL (item.flags, I.checked);
  1048.       END;
  1049.     END;  
  1050.   END;  
  1051.  IF I.ResetMenuStrip (ag.AngieWnd, ag.AngieMenus^) THEN END;
  1052. END SetMenuAttrs;
  1053.  
  1054. PROCEDURE SuspendHotKeyDisplay();
  1055. BEGIN
  1056.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDhotkeys]^, ag.AngieWnd, NIL,
  1057.                      gt.lvLabels, -1, u.done);
  1058. END SuspendHotKeyDisplay;                     
  1059.  
  1060. PROCEDURE^ ProperType (type: LONGINT): LONGINT;
  1061.  
  1062. CONST
  1063.   fixType = 0;      (* flag for UpdateHotKeyDisplay *)
  1064.  
  1065. PROCEDURE UpdateHotKeyDisplay (flags: SET);
  1066. VAR
  1067.   l   : LONGINT;
  1068.   tg  : LONGINT;
  1069.   nd  : HotKeyNodePtr;
  1070.   ls  : b.LStrPtr;
  1071. BEGIN
  1072.   l := b.DynTTLen (hotdefs);
  1073.   IF (SelectedHotKey < 0) & (l > 0) THEN SelectedHotKey := 0; END;
  1074.   SelectedHotKey := b.Max2 (-1, b.Min2 (SelectedHotKey, l-1));
  1075.   IF SelectedHotKey >= 0 THEN
  1076.     IF int39 THEN tg := gt.lvMakeVisible; ELSE tg := gt.lvTop; END;
  1077.     gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDhotkeys]^, ag.AngieWnd, NIL,
  1078.                        gt.lvLabels, y.ADR (hotdeflist), gt.lvSelected, 
  1079.                        SelectedHotKey, tg, SelectedHotKey, u.done);
  1080.     tg := I.LFALSE;
  1081.     nd := GetHotKeyNode (SelectedHotKey);
  1082.     IF fixType IN flags THEN
  1083.       nd.type := AdaptIdToEntry (ProperType (nd.type), SelectedHotKey);
  1084.     END;  
  1085.     gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDattrs]^, ag.AngieWnd, NIL,
  1086.                        gt.cyActive, ASH (AttrsOfId (nd.type), -8), u.done);
  1087.     SetMenuAttrs (nd.type);
  1088.     IF PlainId (nd.type) # custom THEN
  1089.       ls := hotnames [PlainId (nd.type)];
  1090.     ELSE
  1091.       ls := y.ADR (nd.text[0]);
  1092.     END;      
  1093.   ELSE
  1094.     gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDhotkeys]^, ag.AngieWnd, NIL,
  1095.                        gt.lvLabels, y.ADR (hotdeflist), u.done);                   
  1096.     tg := I.LTRUE;
  1097.     ls := y.ADR ("");
  1098.   END;  
  1099.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDhotkeys]^, ag.AngieWnd, NIL,
  1100.                      I.gaDisabled, tg, u.done);
  1101.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDtype]^, ag.AngieWnd, NIL,
  1102.                      gt.stString, ls, I.gaDisabled, tg, u.done);
  1103.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDattrs]^, ag.AngieWnd, NIL,
  1104.                      I.gaDisabled, tg, u.done);
  1105.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDdefinition]^, ag.AngieWnd, NIL,
  1106.                      I.gaDisabled, tg, u.done);
  1107.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDdel]^, ag.AngieWnd, NIL,
  1108.                      I.gaDisabled, tg, u.done);
  1109.   tg := BoolToLBool (SelectedHotKey <= 0);
  1110.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDup]^, ag.AngieWnd, NIL,
  1111.                      I.gaDisabled, tg, u.done);
  1112.   tg := BoolToLBool (SelectedHotKey >= l-1);
  1113.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDdown]^, ag.AngieWnd, NIL,
  1114.                      I.gaDisabled, tg, u.done);
  1115.   I.ClearMenuStrip (ag.AngieWnd);
  1116.   IF SelectedHotKey >= 0 THEN 
  1117.     INCL (editmenu.flags, I.menuEnabled);
  1118.   ELSE  
  1119.     EXCL (editmenu.flags, I.menuEnabled);
  1120.   END;  
  1121.   IF I.ResetMenuStrip (ag.AngieWnd, ag.AngieMenus^) THEN END;
  1122. END UpdateHotKeyDisplay;  
  1123.  
  1124. PROCEDURE CloseGUI();
  1125. BEGIN
  1126.   guiwndsig := d.ctrlC;
  1127.   ag.CloseAngieWindow ();
  1128.   gt.FreeMenus (editmenu); editmenu := NIL;  
  1129.   ag.CloseDownScreen ();  
  1130. END CloseGUI;  
  1131.  
  1132. PROCEDURE OpenGUI1(): BOOLEAN;
  1133. VAR
  1134.   pat: b.LStrPtr;
  1135. BEGIN
  1136.   IF ag.AngieWnd # NIL THEN RETURN true; END;
  1137.   ag.hotnames := y.ADR (hotnames);
  1138.   IF ag.Scr = NIL THEN IF ag.SetupScreen ("") = 0 THEN
  1139.     IF ag.OpenAngieWindow (true) = 0 THEN
  1140.       IF SetupEditMenu() = 0 THEN
  1141.         I.SetWindowTitles (ag.AngieWnd, nb.title, nb.title);
  1142.         guiwndsig := ag.AngieWnd.userPort.sigBit;      
  1143.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDpri]^, ag.AngieWnd, NIL,
  1144.                            gt.slLevel, nb.pri, u.done);
  1145.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDdelay]^, ag.AngieWnd, NIL,
  1146.                            gt.slLevel, snoopdelay, u.done);
  1147.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDstable]^, ag.AngieWnd, NIL,
  1148.                            gt.slLevel, stabletime, u.done);
  1149.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDpop]^, ag.AngieWnd, NIL,
  1150.                            gt.cbChecked, BoolToLBool (cxpopup), u.done);
  1151.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDkeyact]^, ag.AngieWnd, NIL,
  1152.                            gt.cbChecked, BoolToLBool (keyactivate), u.done);
  1153.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDincwintaskpri]^, ag.AngieWnd, NIL,
  1154.                            gt.cbChecked, BoolToLBool (incwintaskpri), u.done);
  1155.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDhuntalways]^, ag.AngieWnd, NIL,
  1156.                            gt.cbChecked, BoolToLBool (huntwindowalways), u.done);
  1157.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDhuntwintofront]^, ag.AngieWnd, NIL,
  1158.                            gt.cbChecked, BoolToLBool (huntwindowwfr), u.done);
  1159.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDshufflebdrop]^, ag.AngieWnd, NIL,
  1160.                            gt.cbChecked, BoolToLBool (shufflebackdrop), u.done);
  1161.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDscrsteps]^, ag.AngieWnd, NIL,
  1162.                            gt.slLevel, scrMoveSteps, u.done);
  1163.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDwinsteps]^, ag.AngieWnd, NIL,
  1164.                            gt.slLevel, winMoveSteps, u.done);
  1165.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDhuntdefpub]^, ag.AngieWnd, NIL,
  1166.                            gt.cbChecked, BoolToLBool (setdefpubonhunt), u.done);
  1167.         IF shufflestr # NIL THEN 
  1168.           pat := y.ADR (shufflestr[0]); 
  1169.         ELSE 
  1170.           pat := y.ADR ("#?"); 
  1171.         END;                   
  1172.         gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDshufflepat]^, ag.AngieWnd, NIL,                   
  1173.                            gt.stString, pat, u.done);                         
  1174.         UpdateHotKeyDisplay ({fixType});
  1175.         RETURN true;
  1176.       END;  
  1177.     END;  
  1178.   END; END;
  1179.   CloseGUI();
  1180.   RETURN false;
  1181. END OpenGUI1;
  1182.  
  1183. PROCEDURE^ DoIntuiAction (actionid: LONGINT);
  1184.  
  1185. PROCEDURE OpenGUI (): BOOLEAN;
  1186. VAR
  1187.   orighuntwindowwfr: BOOLEAN;
  1188. BEGIN
  1189.   IF ~OpenGUI1() THEN RETURN false; END;
  1190.   I.ScreenToFront (ag.AngieWnd.wScreen);
  1191.   I.ActivateWindow (ag.AngieWnd);
  1192.   IF I.int.activeWindow # ag.AngieWnd THEN d.Delay (10); END;  
  1193.   IF I.int.activeWindow = ag.AngieWnd THEN 
  1194.     orighuntwindowwfr := huntwindowwfr; huntwindowwfr := true;
  1195.     DoIntuiAction (activeToFront + frontAttrConst); 
  1196.     huntwindowwfr := orighuntwindowwfr;
  1197.   END;
  1198.   RETURN true;
  1199. END OpenGUI;  
  1200.   
  1201. PROCEDURE CreateCustom();
  1202. BEGIN  
  1203.   IF cxcustom = NIL THEN
  1204.     (* $IF SmallData *)
  1205.       CustomCxStub := customCxStub;
  1206.       CustomCxStub.a5 := y.REG (13);
  1207.       e.CacheClearU();
  1208.       cxcustom := co.CxCustom (y.VAL (co.CustomProcType, y.ADR (CustomCxStub)), 0);
  1209.     (* $ELSE *)
  1210.       cxcustom := co.CxCustom (CxCustomHandler, 0);
  1211.     (* $END *)
  1212.     y.SETREG (0, co.SetCxObjPri (cxcustom, 1));
  1213.   END;  
  1214.   co.RemoveCxObj (cxcustom);
  1215.   IF br # NIL THEN co.EnqueueCxObj (br, cxcustom); END;
  1216. END CreateCustom;
  1217.  
  1218. PROCEDURE CreateCustomFilter();
  1219. BEGIN
  1220.   IF cxcustomfilter = NIL THEN
  1221.     cxcustomfilter := cx.HotKey ("diskinserted", nb.port, scrActivateMagic);
  1222.   END;  
  1223. END CreateCustomFilter;  
  1224.  
  1225. PROCEDURE DeleteCxObjs();
  1226. VAR
  1227.   i  : LONGINT;
  1228.   nd : HotKeyNodePtr;
  1229. BEGIN
  1230.   FOR i := 0 TO b.DynTTLen (hotdefs)-1 DO 
  1231.     nd := GetHotKeyNode (i);
  1232.     co.DeleteCxObjAll (nd.cxobj); nd.cxobj := NIL;
  1233.   END;
  1234.   co.DeleteCxObjAll (cxcustom); cxcustom := NIL;
  1235. END DeleteCxObjs;
  1236.  
  1237. PROCEDURE ResetBroker();
  1238. VAR
  1239.   i  : LONGINT;
  1240.   nd : HotKeyNodePtr;
  1241. BEGIN
  1242.   FOR i := 0 TO b.DynTTLen (hotdefs)-1 DO 
  1243.     nd := GetHotKeyNode (i);
  1244.     co.RemoveCxObj (nd.cxobj);
  1245.   END;
  1246.   co.RemoveCxObj (cxcustom);
  1247.   co.DeleteCxObj (br); br := NIL;
  1248.   br := CxBroker (nb, NIL);
  1249.   IF br # NIL THEN
  1250.     FOR i := 0 TO b.DynTTLen (hotdefs)-1 DO 
  1251.       nd := GetHotKeyNode (i);
  1252.       IF nd.cxobj # NIL THEN co.EnqueueCxObj (br, nd.cxobj); END;
  1253.     END;  
  1254.     co.EnqueueCxObj (br, cxcustom);
  1255.   END;  
  1256. END ResetBroker;
  1257.  
  1258.  
  1259. PROCEDURE ResetNoActScrKeys();
  1260. VAR
  1261.   i,n : LONGINT;
  1262.   nd  : HotKeyNodePtr;
  1263. BEGIN
  1264.   DISPOSE (ScrKeys1); n := 0;
  1265.   FOR i := 0 TO b.DynTTLen (hotdefs)-1 DO
  1266.     nd := GetHotKeyNode (i);
  1267.     IF PlainId (nd.type) = noKeyActivate THEN INC (n); END;
  1268.   END;  
  1269.   IF n > 0 THEN
  1270.     y.ALLOCATE (ScrKeys1, n);
  1271.     IF ScrKeys1 # NIL THEN
  1272.       n := 0;
  1273.       FOR i := 0 TO b.DynTTLen (hotdefs)-1 DO
  1274.         nd := GetHotKeyNode (i);
  1275.         IF PlainId (nd.type) = noKeyActivate THEN
  1276.           IF co.ParseIX (nd.node.name^, ScrKeys1[n]) = 0 THEN END;
  1277.           INC (n);
  1278.         END;  
  1279.       END; (* FOR *)  
  1280.     END;  
  1281.   END;
  1282.   ScrKeys2 := ScrKeys;
  1283.   e.Disable(); ScrKeys := ScrKeys1; e.Enable();
  1284.   DISPOSE (ScrKeys2); ScrKeys1 := NIL;
  1285. END ResetNoActScrKeys;  
  1286.  
  1287. PROCEDURE UpdateHotKeyNodeTypes();
  1288. VAR
  1289.   i : LONGINT;
  1290.   nd: HotKeyNodePtr;
  1291. BEGIN
  1292.   FOR i := 0 TO b.DynTTLen (hotdefs)-1 DO
  1293.     nd := GetHotKeyNode (i);
  1294.     IF PlainId (nd.type) = custom THEN
  1295.       nd.type := AdaptIdToEntry (nd.type, i);
  1296.       IF nd.cxobj # NIL THEN
  1297.         co.DeleteCxObjAll (nd.cxobj); nd.cxobj := NIL;
  1298.         nd.cxobj := cx.HotKey (nd.node.name^, nb.port, nd.type);        
  1299.         IF IsNoKeyScrActId (nd.type) THEN 
  1300.           y.SETREG (0, co.SetCxObjPri (nd.cxobj, 2)); 
  1301.         END;
  1302.         IF br # NIL THEN co.EnqueueCxObj (br, nd.cxobj); END;
  1303.       END;  
  1304.     END;  
  1305.   END;  
  1306. END UpdateHotKeyNodeTypes;  
  1307.  
  1308. PROCEDURE DelHotKey (entry: LONGINT);
  1309. VAR
  1310.   nd: HotKeyNodePtr;
  1311.   l : LONGINT;
  1312.   type: LONGINT;
  1313. BEGIN
  1314.   type := 0;
  1315.   l := b.DynTTLen (hotdefs);
  1316.   IF entry = -1 THEN entry := l-1; END;
  1317.   IF (entry < 0) OR (entry >= l) THEN RETURN END;
  1318.   nd := GetHotKeyNode (entry);
  1319.   IF nd # NIL THEN 
  1320.     type := nd.type;
  1321.     co.DeleteCxObjAll (nd.cxobj); nd.cxobj := NIL;
  1322.     IF nd.node.succ # NIL THEN e.Remove (nd); nd.node.succ := NIL; END;
  1323.     DISPOSE (nd.text); DISPOSE (nd.def);    
  1324.   END;  
  1325.   IF b.RemDynTTEntry (hotdefs, entry) THEN END;
  1326.   UpdateHotKeyNodeTypes();
  1327.   IF PlainId (type) = noKeyActivate THEN ResetNoActScrKeys(); END;
  1328. END DelHotKey;  
  1329.  
  1330. PROCEDURE GetHotKeyNodeFromList (entry: LONGINT): e.NodePtr;
  1331. VAR
  1332.   n: e.NodePtr;
  1333.   j: LONGINT;
  1334. BEGIN
  1335.   IF (entry < 0) OR (entry >= b.DynTTLen (hotdefs)) THEN RETURN NIL; END;
  1336.   n := hotdeflist.head;
  1337.   FOR j := 1 TO entry DO; 
  1338.     IF n.succ = NIL THEN RETURN NIL; END;
  1339.     n := n.succ;
  1340.   END;
  1341.   RETURN n;
  1342. END GetHotKeyNodeFromList;
  1343.  
  1344. PROCEDURE SwapHotKeys (entry1, entry2: LONGINT): BOOLEAN;
  1345. VAR
  1346.   l       : LONGINT;
  1347.   nd1, nd2: HotKeyNodePtr;
  1348. BEGIN
  1349.   IF entry1 < entry2 THEN l := entry1; entry1 := entry2; entry2 := l; END;
  1350.   l := b.DynTTLen (hotdefs);
  1351.   IF (entry1 < 0) OR (entry1 >= l) OR
  1352.      (entry2 < 0) OR (entry2 >= l) OR (entry1 = entry2) THEN RETURN false; END;
  1353.   nd1 := GetHotKeyNode (entry1);
  1354.   nd2 := GetHotKeyNode (entry2);
  1355.   IF (nd1 = NIL) OR (nd2 = NIL) THEN RETURN false; END;
  1356.   IF (nd1.node.succ = NIL) OR (nd2.node.succ = NIL) THEN RETURN false; END;
  1357.   e.Remove (nd1); e.Remove (nd2);
  1358.   hotdefs[entry1] := y.VAL (e.APTR, nd2);
  1359.   hotdefs[entry2] := y.VAL (e.APTR, nd1);
  1360.   e.Insert (hotdeflist, nd1, GetHotKeyNodeFromList (entry2-1));  
  1361.   e.Insert (hotdeflist, nd2, GetHotKeyNodeFromList (entry1-1));
  1362.   UpdateHotKeyNodeTypes();
  1363.   RETURN true;
  1364. END SwapHotKeys;  
  1365.  
  1366. CONST
  1367.   replaceMode = false;
  1368.   insertMode  = true;
  1369.  
  1370. VAR
  1371.   nilNode: HotKeyNode;
  1372.  
  1373. VAR
  1374.   addname, addtext: b.DynStrPtr;
  1375.  
  1376. PROCEDURE AddHotKey (type : LONGINT;
  1377.                      name : ARRAY OF CHAR;
  1378.                      text : ARRAY OF CHAR;
  1379.                      entry: LONGINT;
  1380.                      mode : BOOLEAN       ): BOOLEAN;
  1381. VAR  
  1382.   l, j: LONGINT;
  1383.   matchok: BOOLEAN;
  1384.   nd: HotKeyNodePtr;
  1385. (* $CopyArrays- *)
  1386. BEGIN
  1387.   IF (st.Length (name) >= strGadLen) OR (st.Length (text) >= strGadLen) OR
  1388.      ~IsValidId (type) THEN RETURN false; END;  
  1389.   l := b.DynTTLen (hotdefs);
  1390.   IF l >= MAX (INTEGER)-2 THEN RETURN false; END; (* for all you hardcore users out there;-) *)
  1391.   IF entry = -1 THEN entry := l; END;
  1392.   IF (entry < 0) OR (entry > l) THEN RETURN false; END;
  1393.   IF mode = replaceMode THEN
  1394.     DISPOSE (addname); DISPOSE (addtext);
  1395.     IF ~b.DynAppend (addname, name) THEN RETURN false; END;
  1396.     IF ~b.DynAppend (addtext, text) THEN RETURN false; END;
  1397.     DelHotKey (entry);
  1398.     RETURN AddHotKey (type, addname^, addtext^, entry, insertMode);
  1399.   END;
  1400.   (* insertMode *)
  1401.   type := AdaptIdToEntry (type, entry);
  1402.   IF ~b.DynInsertTT (hotdefs, entry, nilNode, {b.noNulTerm}) THEN RETURN false; END;
  1403.   nd := GetHotKeyNode (entry);
  1404.   IF ~b.DynAppend (nd.def, name) THEN DelHotKey (entry); RETURN false; END;
  1405.   IF ~b.DynAppend (nd.text, text) THEN DelHotKey (entry); RETURN false; END;
  1406.   nd.type := type;
  1407.   nd.node.name := y.ADR (nd.def[0]);
  1408.   e.Insert (hotdeflist, nd, GetHotKeyNodeFromList (entry-1));
  1409.   UpdateHotKeyNodeTypes();
  1410.   IF PlainId (type) = noKeyActivate THEN
  1411.     nd.cxobj := NIL;
  1412.     matchok := co.ParseIX (name, DummyIX) = 0;
  1413.     ResetNoActScrKeys();
  1414.     RETURN matchok;
  1415.   END;
  1416.   nd.cxobj := cx.HotKey (name, nb.port, type);
  1417.   IF IsNoKeyScrActId (type) THEN y.SETREG (0, co.SetCxObjPri (nd.cxobj, 2)); END;
  1418.   IF br # NIL THEN co.EnqueueCxObj (br, nd.cxobj); END;
  1419.   RETURN nd.cxobj # NIL;
  1420. END AddHotKey;
  1421.  
  1422. PROCEDURE SetShufflePattern (patarg: ARRAY OF CHAR): BOOLEAN;
  1423. VAR
  1424.   pat: b.LStrPtr;
  1425.   l  : LONGINT;
  1426. (* $CopyArrays- *)
  1427. BEGIN
  1428.   IF patarg # "" THEN pat := y.ADR (patarg[0]); ELSE pat := y.ADR ("#?"); END;
  1429.   l := st.Length (pat^);
  1430.   IF l < strGadLen THEN
  1431.     IF b.DynExpand (shufflestr, l) THEN
  1432.       IF b.DynExpand (shuffle, (l+1)*4) THEN
  1433.         IF d.ParsePatternNoCase (pat^, shuffle^, LEN (shuffle^)) >= 0 THEN
  1434.           COPY (pat^, shufflestr^);
  1435.           RETURN true;
  1436.         END;  
  1437.       END;  
  1438.     END;
  1439.   END;  
  1440.   DISPOSE (shuffle); DISPOSE (shufflestr);
  1441.   RETURN false;                         
  1442. END SetShufflePattern;  
  1443.   
  1444. CONST
  1445.   prefsName = "PROGDIR:Angie";
  1446.  
  1447. VAR
  1448.   readdstr: b.DynStrPtr;
  1449.  
  1450. PROCEDURE ReadSettings();
  1451. VAR
  1452.   tt, tti   : b.TTPtr;
  1453.   i         : SHORTINT;
  1454.   j         : LONGINT;
  1455.   k         : INTEGER;
  1456.   v         : b.LStrPtr;
  1457.   si        : LONGINT;
  1458.   type      : LONGINT;
  1459.   textstr   : b.LStrPtr;
  1460.  
  1461. BEGIN
  1462.   tt := cx.ArgArrayInit();
  1463.   IF tt = NIL THEN HALT (20); END;
  1464.   huntwindowalways := cx.ArgBool (NIL, huntAlwaysStr, true);
  1465.   huntwindowwfr := cx.ArgBool (NIL, huntWinToFrontStr, true);
  1466.   setdefpubonhunt := cx.ArgBool (NIL, huntSetDefPubModeStr, false);
  1467.   incwintaskpri := cx.ArgBool (NIL, incWinTaskPriStr, true);
  1468.   keyactivate := cx.ArgBool (NIL, keyActivateStr, true);
  1469.   shufflebackdrop := cx.ArgBool (NIL, shuffleBackdropStr, false);
  1470.   cxpopup := cx.ArgBool (NIL, cxPopUpStr, true);
  1471.   scrMoveSteps := SHORT (b.Max2 (1, b.Min2 (50, cx.ArgInt (NIL, scrMoveStepsStr, 5))));
  1472.   winMoveSteps := SHORT (b.Max2 (1, b.Min2 (50, cx.ArgInt (NIL, winMoveStepsStr, 5))));
  1473.   SetSnoopDelay (cx.ArgInt (NIL, snoopDelayStr, 30));
  1474.   SetStableTime (cx.ArgInt (NIL, stableTimeStr, 20));
  1475.   IF SetShufflePattern (cx.ArgString (NIL, shufflePatStr, 
  1476.                                       defaultShufflePat)^) THEN END;
  1477.   nb.pri := SHORT (SHORT (b.Max2 (MIN (SHORTINT),
  1478.                                   b.Min2 (MAX (SHORTINT),
  1479.                                           cx.ArgInt (NIL, cxPriorityStr, 0)))));
  1480.  
  1481.   j := 0;
  1482.   WHILE tt[j] # NIL DO
  1483.     LOOP 
  1484.       FOR i := 0 TO hotKeys-1 DO
  1485.         IF b.CmpToolNames (tt[j]^, hotnames[i]^) THEN
  1486.           IF readdstr # NIL THEN readdstr[0] := CHR (0); END;
  1487.           IF b.DynAppend (readdstr, b.GetToolValue (tt[j]^)^) THEN
  1488.             type := i;  si := 0;
  1489.             WHILE (readdstr[si] # ':') & (readdstr[si] # '\000') DO INC (si); END;
  1490.             IF readdstr[si] = ':' THEN
  1491.               readdstr[si] := '\000';
  1492.               FOR k := 0 TO LEN (attrs)-1 DO
  1493.                 IF ic.MatchToolValue (readdstr^, attrs[k].name^) THEN
  1494.                   INC (type, attrs[k].const);
  1495.                 END;  
  1496.               END;
  1497.               v := b.StrIndex (readdstr^, si+1);
  1498.             ELSE  
  1499.               v := b.StrIndex (readdstr^, 0);
  1500.             END;            
  1501.             type := ProperType (type);
  1502.             textstr := y.ADR ("");
  1503.             IF PlainId (type) = custom THEN
  1504.               si := 0;
  1505.               WHILE (v[si] # CHR (27)) & (v[si] # '\000') DO INC (si); END;
  1506.               IF v[si] = CHR (27) THEN
  1507.                 v[si] := '\000';
  1508.                 textstr := y.ADR (v[si+1]);
  1509.               END;  
  1510.             END;  
  1511.             IF AddHotKey (type, v^, textstr^, -1, insertMode) THEN END;
  1512.           END;
  1513.           EXIT; 
  1514.         END; (* IF b.CmpToolNames ... *)       
  1515.       END; (* FOR i *)      
  1516.     EXIT;
  1517.     END; (* LOOP *)
  1518.     INC (j);
  1519.   END; (* WHILE *)
  1520. END ReadSettings;
  1521.  
  1522. PROCEDURE ActivateBroker (b: BOOLEAN);
  1523. BEGIN
  1524.   IF co.ActivateCxObj (br, BoolToLBool (b)) = e.false THEN END;
  1525.   active := b;
  1526. END ActivateBroker;
  1527.  
  1528. VAR
  1529.   instimerport         : e.MsgPortPtr;
  1530.   instio               : ti.TimeRequestPtr;
  1531.   instimeropen         : BOOLEAN;
  1532.  
  1533.   inserttval           : ti.TimeVal;
  1534.  
  1535. VAR
  1536.   OldCd: d.FileLockPtr;
  1537.  
  1538.  
  1539. PROCEDURE Init();
  1540. VAR
  1541.   i         : INTEGER;
  1542.   
  1543. BEGIN
  1544.   dinfosig := -1;
  1545.   guiwndsig := d.ctrlC;
  1546.   chieftask := e.FindTask (NIL);
  1547.   retpri := chieftask.node.pri;
  1548.   OldCd := chieftask (d.Process).currentDir;
  1549.   IF o.wbStarted THEN
  1550.     y.SETREG (0, d.CurrentDir (o.wbenchMsg (wb.WBStartup).argList[0].lock));
  1551.   END;  
  1552.   chiefpri := SHORT (SHORT (b.Min2 (MAX (SHORTINT), b.Max2 (retpri, 2))));
  1553.   IF (co.base = NIL) OR (e.exec.libNode.version < 37) THEN HALT (20); END;
  1554.   coBase := co.base;
  1555.   cx38 := co.base.version >= 38;
  1556.   int39 := I.int.libNode.version >= 39;
  1557.   es.NewList (hotdeflist);
  1558.   nb := cnb;
  1559.   nb.port := e.CreateMsgPort();
  1560.   IF nb.port = NIL THEN HALT (20); END;
  1561.   ReadSettings();
  1562.   CreateCustom();
  1563.   ResetBroker();
  1564.   IF br = NIL THEN HALT (20); END;  
  1565.   IF co.CxObjError (br) # LONGSET{} THEN HALT (20); END;
  1566.   CreateCustomFilter();
  1567.   IF cxcustomfilter = NIL THEN HALT (20); END;
  1568.  
  1569.   dinfosig := e.AllocSignal (-1);
  1570.   IF dinfosig = -1 THEN HALT (20); END;
  1571.  
  1572.   tcb.node := ctcbnd;
  1573.   tcb.spLower := y.ADR (ChildStack [0]);
  1574.   tcb.spUpper := y.ADR (ChildStack [LEN (ChildStack)-1]);
  1575.   tcb.spReg   := tcb.spUpper;
  1576.   e.CacheClearU();
  1577.  
  1578.   (* $IF SmallData *)
  1579.     tcb.userData := y.REG (13);
  1580.   (* $END *)  
  1581.   
  1582.   ChildState := init;
  1583.   e.AddTask (y.ADR (tcb), ChildTask, NIL);
  1584.   y.SETREG (0, e.Wait (LONGSET {dinfosig}));
  1585.   IF ChildState # ok THEN HALT (20); END;
  1586.  
  1587.   instimerport := e.CreateMsgPort ();
  1588.   instio := e.CreateIORequest (instimerport, SIZE (instio^));
  1589.   IF instio = NIL THEN HALT (20); END;
  1590.  
  1591.   ActivateBroker (true);
  1592.   IF cxpopup THEN IF OpenGUI() THEN END; END;
  1593.   y.SETREG (0, e.SetTaskPri (chieftask, chiefpri));
  1594. END Init;
  1595.  
  1596. PROCEDURE^ SaveProcCleanUp(): BOOLEAN;
  1597.  
  1598. VAR
  1599.   OldPri : INTEGER;
  1600.   
  1601. CONST
  1602.   invalidPri = 4000H;
  1603.   incPri = 4001H;
  1604.  
  1605. PROCEDURE SecureSetTaskPri (task: e.TaskPtr; pri: INTEGER): INTEGER;
  1606. VAR
  1607.   t: e.TaskPtr;
  1608.   r: INTEGER;
  1609. BEGIN
  1610.   r := invalidPri;
  1611.   IF (task = NIL) OR (pri = invalidPri) THEN RETURN r; END;
  1612.   e.Disable ();
  1613.   LOOP
  1614.     t := e.exec.taskReady.head;
  1615.     WHILE (t.node.succ # NIL) & (t # task) DO t := t.node.succ; END;
  1616.     IF t.node.succ # NIL THEN EXIT; END;
  1617.     t := e.exec.taskWait.head;
  1618.     WHILE (t.node.succ # NIL) & (t # task) DO t := t.node.succ; END;
  1619.     EXIT;
  1620.   END;  
  1621.   IF (t.node.succ # NIL) & (e.FindTask (NIL) # t) THEN 
  1622.     IF pri = incPri THEN
  1623.       pri := LONG (t.node.pri)+1;
  1624.     ELSE  
  1625.       IF pri+1 # t.node.pri THEN pri := invalidPri; END;
  1626.     END;
  1627.     IF pri # invalidPri THEN
  1628.       pri := SHORT (b.Max2 (MIN (SHORTINT), b.Min2 (MAX (SHORTINT), pri)));
  1629.       r := e.SetTaskPri (t, SHORT (pri)); 
  1630.     END;  
  1631.   END;
  1632.   e.Enable ();
  1633.   RETURN r;
  1634. END SecureSetTaskPri;
  1635.  
  1636. PROCEDURE CleanUp();
  1637. VAR
  1638.   msg: e.MessagePtr;
  1639. BEGIN
  1640.   y.SETREG (0, e.SetTaskPri (chieftask, retpri));
  1641.   y.SETREG (0, SecureSetTaskPri (IncTask, OldPri)); IncTask := NIL; 
  1642.   y.SETREG (0, SaveProcCleanUp());
  1643.   CloseGUI();
  1644.   IF instimeropen THEN e.CloseDevice (instio); instimeropen := false; END;
  1645.   e.DeleteIORequest (instio); instio := NIL;
  1646.   e.DeleteMsgPort (instimerport); instimerport := NIL;
  1647.   DeleteCxObjs();
  1648.   co.DeleteCxObj (br); br := NIL;
  1649.   IF nb.port # NIL THEN
  1650.     LOOP
  1651.       msg := e.GetMsg (nb.port);
  1652.       IF msg = NIL THEN EXIT; END;
  1653.       e.ReplyMsg (msg);
  1654.     END;
  1655.   END;  
  1656.   e.DeleteMsgPort (nb.port); nb.port := NIL;
  1657.   co.DeleteCxObjAll (cxcustomfilter); cxcustomfilter := NIL;
  1658.   IF ChildState # yetUnlaunched THEN
  1659.     e.Forbid();
  1660.     IF ChildState # died THEN ChildState := requestDie; END;
  1661.     e.Permit();
  1662.     WHILE ChildState # died DO y.SETREG (0,e.Wait (LONGSET {dinfosig})); END;
  1663.   END;
  1664.   DISPOSE (shuffle);
  1665.   e.FreeSignal (dinfosig); dinfosig := -1;
  1666.   y.SETREG (0, d.CurrentDir (OldCd));
  1667.   IF o.Result > 5 THEN I.DisplayBeep (NIL); END;
  1668. END CleanUp;
  1669.  
  1670.  
  1671. PROCEDURE PrepareScrPos (scr: I.ScreenPtr; x1, y1, x2, y2: LONGINT;
  1672.                          VAR sx: LONGINT; VAR sy: LONGINT);
  1673. VAR
  1674.   vpe : g.ViewPortExtraPtr;
  1675.   rect: g.Rectangle;
  1676. BEGIN
  1677.   sx := 0; sy := 0;
  1678.   IF ~int39 & (scr # NIL) THEN
  1679.     vpe := b.ScrVPExtra (scr);
  1680.     IF (vpe # NIL) & b.VisibleOfScreen (scr, rect) THEN
  1681.       IF vpe.displayClip.maxX-vpe.displayClip.minX+1 < x2-x1+1 THEN
  1682.         sx := rect.minX-x1-(vpe.displayClip.maxX-vpe.displayClip.minX+1)+
  1683.               (rect.maxX-rect.minX+1);
  1684.       ELSIF rect.minX > x1 THEN
  1685.         sx := b.Max2 (rect.minX-x1, 0);
  1686.       ELSE
  1687.         sx := b.Min2 (rect.maxX-x2, 0);
  1688.       END;
  1689.       IF vpe.displayClip.maxY-vpe.displayClip.minY+1 < y2-y1+1 THEN
  1690.         sy := rect.minY-y1-(vpe.displayClip.maxY-vpe.displayClip.minY+1)+
  1691.               (rect.maxY-rect.minY+1);
  1692.       ELSIF rect.minY > y1 THEN
  1693.         sy := b.Max2 (rect.minY-y1, 0);
  1694.       ELSE
  1695.         sy := b.Min2 (rect.maxY-y2, 0);
  1696.       END;
  1697.     END;
  1698.   END;
  1699. END PrepareScrPos;
  1700.  
  1701. PROCEDURE ScrPos (scr: I.ScreenPtr; x1, y1, x2, y2, sx, sy: LONGINT);
  1702. BEGIN
  1703.   IF scr # NIL THEN
  1704.     IF ~int39 OR (sx # 0) OR (sy # 0) THEN
  1705.       I.MoveScreen (scr, sx, sy);
  1706.     ELSE
  1707.       I.ScreenPosition (scr, LONGSET{sposMakeVisible},
  1708.                         x1, y1, x2, y2);
  1709.     END;
  1710.   END;
  1711. END ScrPos;
  1712.  
  1713. PROCEDURE IsActivationId (id: LONGINT): BOOLEAN;
  1714. BEGIN
  1715.   CASE PlainId (id) OF
  1716.   activate, activateNext, activatePrev, activateBackDrop,
  1717.   activateFrontScr, nextScreen, prevScreen, wbenchScreen, defPubScreen,
  1718.   lastActive, lastActiveScr, activateNextScreen, activatePrevScreen, 
  1719.   activateWBenchScreen, activateDefPubScreen:
  1720.     RETURN true;
  1721.   ELSE
  1722.     RETURN false;
  1723.   END;
  1724. END IsActivationId;
  1725.  
  1726. PROCEDURE IsHuntId (id: LONGINT): BOOLEAN;
  1727. BEGIN
  1728.   RETURN huntwindowalways OR (IsToFrontId (id) & huntwindowwfr) OR
  1729.          (PlainId (id)=huntWindow);
  1730. END IsHuntId;
  1731.  
  1732.  
  1733. PROCEDURE IsPubScreen (scr: I.ScreenPtr; VAR name: b.DynStrPtr): BOOLEAN;
  1734. VAR
  1735.   ScrList: e.ListPtr;
  1736.   nd1    : I.PubScreenNodePtr;
  1737.   res    : BOOLEAN;
  1738.  
  1739. BEGIN
  1740.   res := false;
  1741.   IF scr = NIL THEN RETURN false; END;
  1742.   ScrList := I.LockPubScreenList ();
  1743.   nd1 := ScrList.head;      
  1744.   WHILE (nd1.node.succ # NIL) & ~res DO
  1745.     IF ~(I.psnfPrivate IN nd1.flags) THEN
  1746.       IF nd1.screen = scr THEN
  1747.         IF b.DynExpand (name, st.Length (nd1.node.name^)) THEN
  1748.           COPY (nd1.node.name^, name^);
  1749.           res := true;
  1750.         END;  
  1751.       END;
  1752.     END;  
  1753.     nd1 := nd1.node.succ;
  1754.   END; (* WHILE *)
  1755.   I.UnlockPubScreenList ();
  1756.   RETURN res;
  1757. END IsPubScreen;
  1758.  
  1759.  
  1760. VAR
  1761.   pubnam: b.DynStrPtr;
  1762.   
  1763. PROCEDURE MakeDefPubScr (scr: I.ScreenPtr; failWB: BOOLEAN);
  1764. VAR
  1765.   dps: I.ScreenPtr;
  1766. BEGIN
  1767.   dps := I.LockPubScreen (NIL);
  1768.   I.UnlockPubScreen (NIL, dps);
  1769.   IF dps # scr THEN
  1770.     IF IsPubScreen (scr, pubnam) THEN 
  1771.       I.SetDefaultPubScreen (pubnam^); 
  1772.     ELSE
  1773.       IF failWB THEN I.SetDefaultPubScreen (NIL); END;
  1774.     END;
  1775.   END;  
  1776. END MakeDefPubScr;  
  1777.  
  1778. CONST
  1779.   minStack = 4096;
  1780.  
  1781. VAR
  1782.   ConTitle: ARRAY strGadLen OF CHAR;
  1783.  
  1784. PROCEDURE DoIntuiAction (actionid: LONGINT);
  1785. VAR
  1786.   newtask      : e.TaskPtr;
  1787.   lk           : LONGINT;
  1788.   scr,bscr,fscr: I.ScreenPtr;
  1789.   auxscr       : I.ScreenPtr;
  1790.   pscr         : I.ScreenPtr;
  1791.   rect         : g.Rectangle;
  1792.   sx, sy       : LONGINT;
  1793.   vpe          : g.ViewPortExtraPtr;
  1794.   dcwidth      : LONGINT;
  1795.   dcheight     : LONGINT;
  1796.   vswidth      : LONGINT;
  1797.   vsheight     : LONGINT;
  1798.   w,w0, w1,w2,w3: I.WindowPtr;
  1799.   wl,wt,ww,wh  : LONGINT;
  1800.   wx,wy,nww,nwh: LONGINT;
  1801.   x1,y1,x2,y2  : LONGINT;
  1802.   reallyzip    : BOOLEAN;
  1803.   reallychwbox : BOOLEAN;
  1804.   reallymovewnd: BOOLEAN;
  1805.   reallytofront: BOOLEAN;
  1806.   reallytoback : BOOLEAN;
  1807.   reallyactivate: BOOLEAN;
  1808.   reallymovescr: BOOLEAN;
  1809.   reallyscrtofront: BOOLEAN;
  1810.   reallymakedefpub: BOOLEAN;
  1811.   tmpport         : e.MsgPortPtr;
  1812.   nd              : HotKeyNodePtr;
  1813.   text            : b.LStrPtr;
  1814.   entr            : LONGINT;
  1815.   inp             : d.FileHandlePtr;
  1816.   ok              : BOOLEAN;
  1817.   iev             : ie.InputEventPtr;
  1818.   stk             : LONGINT;
  1819.   insertdelay     : LONGINT;
  1820.   chrscvted       : LONGINT;
  1821.  
  1822.   PROCEDURE CheckHuntWindow();
  1823.   VAR
  1824.     vpe : g.ViewPortExtraPtr;
  1825.   BEGIN
  1826.     sx := 0; sy := 0;
  1827.     IF (w # NIL) & IsHuntId (actionid) THEN
  1828.       scr := w.wScreen;
  1829.       IF setdefpubonhunt THEN reallymakedefpub := true; END;
  1830.       IF I.backDrop IN w.flags THEN
  1831.         vpe := b.ScrVPExtra (scr);
  1832.         IF (vpe # NIL) & b.VisibleOfScreen (scr, rect) THEN
  1833.           sy := rect.maxY-rect.minY+1 - 
  1834.                 b.Min2 (scr.height, vpe.displayClip.maxY-vpe.displayClip.minY+1);
  1835.           IF sy < 0 THEN reallymovescr := true; END;  
  1836.         END;  
  1837.       ELSE
  1838.         PrepareScrPos (scr, wl, wt, wl+ww-1, wt+wh-1, sx, sy);
  1839.         reallymovescr := true;
  1840.       END;  
  1841.       IF I.int.firstScreen # scr THEN reallyscrtofront := true; END;
  1842.     END; (* IF w # NIL *)
  1843.   END CheckHuntWindow;
  1844.  
  1845.   PROCEDURE HuntWindow();
  1846.   BEGIN
  1847.     IF reallymovescr THEN ScrPos (scr, wl, wt, wl+ww-1, wt+wh-1, sx, sy); END;
  1848.     IF reallyscrtofront THEN I.ScreenToFront (scr); END;
  1849.     IF reallymakedefpub THEN MakeDefPubScr (scr, true); END;
  1850.   END HuntWindow;
  1851.  
  1852.   PROCEDURE ResetActionFlags();
  1853.   BEGIN
  1854.     w := NIL; scr := NIL; bscr := NIL; fscr := NIL; pscr := NIL;
  1855.     reallytofront := false; reallyactivate := false;
  1856.     reallymovescr := false; reallyscrtofront := false;
  1857.     reallyzip := false; reallychwbox := false;
  1858.     reallymovewnd := false; reallytoback := false;
  1859.     reallymakedefpub := false;
  1860.   END ResetActionFlags;
  1861.  
  1862.   PROCEDURE MatchWindow (w: I.WindowPtr): BOOLEAN;
  1863.   VAR
  1864.     wtitle: e.STRPTR;
  1865.   BEGIN
  1866.     IF w # NIL THEN
  1867.       IF ~(I.backDrop IN w.flags) OR shufflebackdrop THEN
  1868.         wtitle := w.title;
  1869.         IF wtitle = NIL THEN wtitle := y.ADR (""); END;
  1870.         IF shuffle = NIL THEN RETURN true; END;
  1871.         IF d.MatchPatternNoCase (shuffle^, wtitle^) THEN RETURN true; END;
  1872.       END;
  1873.     END;  
  1874.     RETURN false;
  1875.   END MatchWindow;  
  1876.  
  1877.   PROCEDURE PutIEventsDelayed (iev: ie.InputEventPtr);
  1878.   VAR
  1879.     iev1: ie.InputEventPtr;
  1880.   BEGIN
  1881.     WHILE iev # NIL DO
  1882.       IF d.ctrlC IN e.SetSignal (LONGSET{}, LONGSET{}) THEN RETURN; END;
  1883.       iev1 := iev.nextEvent;
  1884.       iev.nextEvent := NIL;
  1885.       co.AddIEvents (iev);
  1886.       iev.nextEvent := iev1;
  1887.       iev := iev1;
  1888.       instio.time := inserttval;
  1889.       instio.node.command := ti.addRequest; e.OldDoIO (instio);
  1890.     END;  
  1891.   END PutIEventsDelayed;
  1892.   
  1893. BEGIN
  1894.   IF ~active THEN RETURN; END;
  1895.   lk := I.LockIBase (0);
  1896.   w := I.int.activeWindow;
  1897.   IF w # NIL THEN 
  1898.     IF I.menuState IN w.flags THEN I.UnlockIBase (lk); RETURN; END; 
  1899.   END;
  1900.   ResetActionFlags();
  1901.   CASE PlainId (actionid) OF
  1902.   custom:
  1903.     I.UnlockIBase (lk); 
  1904.     entr := ASH (actionid, -16);    
  1905.     nd := GetHotKeyNode (entr);
  1906.     IF (nd # NIL) & (PlainId (nd.type) = custom) THEN
  1907.       ok := false;
  1908.       IF (nd.text[0] # '#') & (nd.text[0] # '~') THEN
  1909.         (* launching a background shell isn't necessarily an 'IntuiAction', though ;-> *)
  1910.         scr := I.LockPubScreen (NIL);
  1911.         vpe := b.ScrVPExtra (scr);
  1912.         IF (vpe # NIL) & b.VisibleOfScreen (scr, rect) THEN        
  1913.           vswidth := rect.maxX-rect.minX+1;
  1914.           vsheight := rect.maxY-rect.minY+1;
  1915.           dcwidth := vpe.displayClip.maxX-vpe.displayClip.minX+1;
  1916.           dcheight := vpe.displayClip.maxY-vpe.displayClip.minY+1;
  1917.           sp.SPrintF (ConTitle, 
  1918.                       "CON:%ld/%ld/%ld/%ld/Angie Output/AUTO/CLOSE/WAIT/"
  1919.                       "ALT%ld/%ld/%ld/%ld/SCREEN",
  1920.                       rect.minX + vswidth DIV 64, rect.minY + vsheight DIV 7,
  1921.                       vswidth - vswidth DIV 16+1, vsheight DIV 3+1,
  1922.                       rect.minX, rect.minY, dcwidth, dcheight);
  1923.           inp := d.Open (ConTitle, d.oldFile);
  1924.           IF inp # NIL THEN
  1925.             IF chieftask (d.Process).cli # NIL THEN
  1926.               stk := ASH (chieftask (d.Process).cli.defaultStack, 2);  
  1927.             ELSE  
  1928.               stk := chieftask (d.Process).stackSize; 
  1929.             END;
  1930.             IF stk < minStack THEN stk := minStack; END;
  1931.             IF d.SystemTags(nd.text^, d.sysInput, b.BPtrVal (inp), d.sysAsynch, e.LTRUE, 
  1932.                             d.sysOutput, NIL, d.npStackSize, stk, 
  1933.                             d.npPriority, retpri, u.done) = d.DOSTRUE THEN
  1934.               d.OldClose (inp);               
  1935.             ELSE
  1936.               ok := true;
  1937.             END;  
  1938.           END;  
  1939.         END;  
  1940.         I.UnlockPubScreen (NIL, scr);
  1941.         IF ok & IsToFrontId (actionid) THEN 
  1942.           DoIntuiAction (defPubScreen);
  1943.         END;
  1944.       ELSE (* we have an input description string *)
  1945.         text := y.ADR (nd.text[1]);
  1946.         IF nd.text[0] = '#' THEN
  1947.           insertdelay := 50;
  1948.           CASE text[0] OF '0'..'9':
  1949.             chrscvted := d.StrToLong (text^, insertdelay);
  1950.             IF chrscvted > 0 THEN
  1951.               CASE text[chrscvted] OF '~', ' ': INC (chrscvted); ELSE END;
  1952.               text := y.ADR (text[chrscvted]);
  1953.             ELSE
  1954.               insertdelay := 50;              
  1955.             END;  
  1956.           END;
  1957.           insertdelay := b.Max2 (0, b.Min2 (999, insertdelay));
  1958.         END;
  1959.         iev := cx.InvertStringForwd (text^, NIL);
  1960.         IF iev # NIL THEN
  1961.           IF (nd.text[0] # '#') OR (insertdelay = 0) THEN
  1962.             co.AddIEvents (iev);
  1963.             ok := true;
  1964.           ELSIF ~instimeropen THEN (* do the delay stuff *)  
  1965.             instimeropen := e.OpenDevice (ti.timerName, 
  1966.                                           ti.microHz, instio, LONGSET{}) = 0;
  1967.             IF instimeropen THEN
  1968.               inserttval.micro := insertdelay * 1000;
  1969.               PutIEventsDelayed (iev);
  1970.               e.CloseDevice (instio); instimeropen := false;
  1971.               ok := true;
  1972.             END;  
  1973.           END;    
  1974.         END;  
  1975.         cx.FreeIEvents (iev);
  1976.       END;  
  1977.       IF ~ok THEN I.DisplayBeep (NIL); END;        
  1978.     END;  |
  1979.   filter:
  1980.     I.UnlockIBase (lk); |
  1981.   activate, activateNext, activatePrev, activeToFront, activateBackDrop,
  1982.   activateFrontScr, nextScreen, prevScreen, wbenchScreen, defPubScreen,
  1983.   activateNextScreen, activatePrevScreen, activateWBenchScreen, 
  1984.   activateDefPubScreen,
  1985.   lastActive, lastActiveScr, huntWindow, zipWin, maxWin, minWin, closeWin,
  1986.   centerWin, activeToBack, setDefPubScreen, moveWinLeft, moveWinRight,
  1987.   moveWinUp, moveWinDown, upperLeftWin, lowerLeftWin, upperRightWin,
  1988.   lowerRightWin, expandWidth, expandHeight, shrinkWidth, shrinkHeight,
  1989.   doubleWidth, doubleHeight, halveWidth, halveHeight, adaptWindow,
  1990.   maxWinWidth, maxWinHeight, huntZipped, huntSigd:
  1991.     CASE PlainId (actionid) OF
  1992.     huntZipped:
  1993.       e.Forbid();
  1994.       IF IsValidWinScr (zipwin) THEN w := zipwin.win; END;
  1995.       e.Permit();
  1996.       IF I.int.activeWindow # w THEN w := NIL; END; |
  1997.     huntSigd:      
  1998.       e.Forbid(); dinfotask := dinfopass; e.Permit();
  1999.       w := dinfotask.activeWin.win;
  2000.       scr := dinfotask.activeScr;
  2001.       IF incwintaskpri THEN
  2002.         newtask := NIL;
  2003.         e.Disable();
  2004.         IF w # NIL THEN
  2005.           tmpport := w.userPort;
  2006.           IF (y.VAL (LONGSET, tmpport) * LONGSET {0,31} = LONGSET {}) &
  2007.              (tmpport # NIL) & (e.public IN e.TypeOfMem (tmpport)) &
  2008.              (e.public IN e.TypeOfMem (y.ADR (tmpport.msgList))) THEN
  2009.             newtask := tmpport.sigTask;
  2010.           END;  
  2011.         END;  
  2012.         e.Enable();
  2013.         IF newtask # IncTask THEN 
  2014.           y.SETREG (0, SecureSetTaskPri (IncTask, OldPri));
  2015.           IncTask := newtask;
  2016.           OldPri := SecureSetTaskPri (IncTask, incPri);
  2017.           IF OldPri = invalidPri THEN IncTask := NIL; END;
  2018.         END;
  2019.       ELSE
  2020.         y.SETREG (0, SecureSetTaskPri (IncTask, OldPri)); IncTask := NIL;
  2021.       END;  
  2022.       IF ~huntwindowalways THEN
  2023.         w := NIL;
  2024.       ELSE  
  2025.         IF w # NIL THEN
  2026.           wl := dinfotask.winBox.left;
  2027.           wt := dinfotask.winBox.top;
  2028.           ww := dinfotask.winBox.width;
  2029.           wh := dinfotask.winBox.height;
  2030.           LOOP
  2031.             IF scr = I.int.activeScreen THEN
  2032.               IF w = I.int.activeWindow THEN
  2033.                 IF wl = w.leftEdge THEN
  2034.                   IF wt = w.topEdge THEN
  2035.                     IF ww = w.width THEN
  2036.                       IF wh = w.height THEN
  2037.                         EXIT;
  2038.                       END;
  2039.                     END;
  2040.                   END;
  2041.                 END;
  2042.               END;
  2043.             END;
  2044.             IF stabletime >= 0 THEN dinfochange := true; END;
  2045.             w := NIL;
  2046.             EXIT;
  2047.           END; (* LOOP *)
  2048.         END;
  2049.       END; |  
  2050.     setDefPubScreen:
  2051.       scr := I.int.activeScreen;
  2052.       auxscr := I.int.firstScreen;
  2053.       IF (scr = NIL) OR 
  2054.          ((g.vpHide IN scr.viewPort.modes) & (auxscr # NIL) & 
  2055.           (auxscr.firstWindow = NIL)) THEN
  2056.         scr := auxscr;
  2057.       END;  
  2058.       IF scr # NIL THEN reallymakedefpub := true; END; |
  2059.     closeWin:
  2060.       w := I.int.activeWindow;  
  2061.       IF (w # NIL) & (~(I.windowClose IN w.flags) OR (w.reqCount > 0)) THEN
  2062.         w := NIL; 
  2063.       END;  
  2064.       IF w # NIL THEN
  2065.         Close1 := close1;
  2066.         Close1.addr := y.VAL (ie.IEDummyPtr, w);
  2067.         co.AddIEvents (y.VAL (ie.InputEventPtr, y.ADR (Close1)));
  2068.       END; |
  2069.     activate:
  2070.       w := MouseWin (exactWin); |
  2071.     activateNext:
  2072.       w1 := I.int.activeWindow;
  2073.       IF w1 # NIL THEN
  2074.         w := w1.nextWindow;
  2075.         LOOP
  2076.           IF w = NIL THEN w := w1.wScreen.firstWindow; END;
  2077.           IF (w = NIL) OR (w = w1) THEN EXIT; END;
  2078.           IF MatchWindow (w) THEN EXIT; END;
  2079.           w := w.nextWindow;
  2080.         END;
  2081.       END; |
  2082.     activatePrev:
  2083.       w0 := I.int.activeWindow;
  2084.       IF w0 # NIL THEN
  2085.         w1 := w0;
  2086.         LOOP
  2087.           w3 := w1.wScreen.firstWindow;
  2088.           w2 := w3; w := w2;
  2089.           WHILE (w2 # NIL) & ((w2 # w1) OR (w2 = w3)) DO
  2090.             w := w2; w2 := w2.nextWindow;
  2091.           END;
  2092.           IF w = NIL THEN EXIT; END;
  2093.           IF MatchWindow (w) THEN EXIT; END;
  2094.           w1 := w; w := NIL;
  2095.           IF w1 = w0 THEN EXIT; END;
  2096.         END;  
  2097.       END; |
  2098.     activeToFront, huntWindow:
  2099.       w := I.int.activeWindow; |
  2100.     activeToBack:  
  2101.       w := I.int.activeWindow;
  2102.       IF w # NIL THEN 
  2103.         IF ~(I.backDrop IN w.flags) THEN reallytoback := true; END;
  2104.       END; |        
  2105.     lastActive:
  2106.       e.Forbid();
  2107.       IF IsValidWinScr (lastwin) THEN 
  2108.         w := lastwin.win;
  2109.       ELSIF (lastwin.scr # I.int.activeScreen) & IsValidScr (lastwin.scr) THEN
  2110.         w := ScrFrontWin (lastwin.scr);
  2111.       END;      
  2112.       e.Permit(); |
  2113.     lastActiveScr:
  2114.       e.Forbid();
  2115.       IF IsValidWinScr (lastscrwin) THEN 
  2116.         w := lastscrwin.win;
  2117.       ELSIF IsValidScr (lastscrwin.scr) THEN  
  2118.         w := ScrFrontWin (lastscrwin.scr);
  2119.       END;      
  2120.       e.Permit(); |      
  2121.     activateBackDrop:
  2122.       scr := I.int.activeScreen;
  2123.       IF scr # NIL THEN
  2124.         w := scr.firstWindow;
  2125.         LOOP
  2126.           IF w = NIL THEN EXIT; END;
  2127.           IF I.backDrop IN w.flags THEN EXIT; END;
  2128.           w := w.nextWindow;
  2129.         END;
  2130.       END; |
  2131.     activateFrontScr:
  2132.       scr := I.int.firstScreen;
  2133.       w := ScrFrontWin (scr); |
  2134.     nextScreen, prevScreen, wbenchScreen, defPubScreen,
  2135.     activateNextScreen, activatePrevScreen, activateWBenchScreen, 
  2136.     activateDefPubScreen:
  2137.       CASE PlainId (actionid) OF
  2138.       nextScreen, activateNextScreen:
  2139.         scr := I.int.firstScreen;
  2140.         LOOP
  2141.           IF scr = NIL THEN EXIT; END;
  2142.           IF scr.nextScreen = NIL THEN EXIT; END;
  2143.           scr := scr.nextScreen;
  2144.         END;
  2145.         IF scr = I.int.firstScreen THEN scr := NIL; END;
  2146.         fscr := scr; |
  2147.       prevScreen, activatePrevScreen:
  2148.         bscr := I.int.firstScreen;
  2149.         IF bscr.nextScreen = NIL THEN bscr := NIL; END;
  2150.         IF bscr # NIL THEN scr := bscr.nextScreen; END; |
  2151.       wbenchScreen, defPubScreen, activateWBenchScreen, activateDefPubScreen:
  2152.         I.UnlockIBase (lk);
  2153.         CASE PlainId (actionid) OF
  2154.         wbenchScreen, activateWBenchScreen: 
  2155.           pscr := I.LockPubScreen ("Workbench"); |
  2156.         defPubScreen, activateDefPubScreen:
  2157.           pscr := I.LockPubScreen (NIL);
  2158.         ELSE END;
  2159.         lk := I.LockIBase (0);
  2160.         scr := pscr;
  2161.         IF I.int.firstScreen = scr THEN scr := NIL; END;
  2162.         fscr := scr;
  2163.       ELSE END;
  2164.       w := GetScrWin (scr);
  2165.       IF (w = NIL) & (scr # NIL) THEN w := ScrFrontWin (scr); END;
  2166.       CASE PlainId (actionid) OF
  2167.       nextScreen, prevScreen, wbenchScreen, defPubScreen:
  2168.         w := NIL;
  2169.       ELSE 
  2170.         IF (scr # NIL) & setdefpubonhunt & IsHuntId (actionid) THEN 
  2171.           reallymakedefpub := true; 
  2172.         END; 
  2173.       END; |
  2174.     zipWin:
  2175.       w := I.int.activeWindow;
  2176.       IF w # NIL THEN
  2177.         IF ~(I.hasZoom IN w.flags) THEN w := NIL; END;
  2178.       END;
  2179.       IF w # NIL THEN
  2180.         wl := w.leftEdge; wt := w.topEdge; ww := w.width; wh := w.height;
  2181.         zipwin.win := w; zipwin.scr := w.wScreen;
  2182.         reallyzip := true;
  2183.       END; |
  2184.     maxWinWidth, maxWinHeight,  
  2185.     doubleWidth, doubleHeight, halveWidth, halveHeight, adaptWindow,
  2186.     maxWin, minWin, expandWidth, expandHeight, shrinkWidth, shrinkHeight,
  2187.     moveWinLeft, moveWinRight, moveWinUp, moveWinDown, upperLeftWin,
  2188.     lowerLeftWin, upperRightWin, lowerRightWin, centerWin:
  2189.       w := I.int.activeWindow;
  2190.       IF w # NIL THEN
  2191.         CASE PlainId (actionid) OF
  2192.         doubleWidth, doubleHeight, halveWidth, halveHeight,
  2193.         maxWin, minWin, expandWidth, expandHeight, shrinkWidth, shrinkHeight,
  2194.         maxWinWidth, maxWinHeight:
  2195.           IF ~(I.windowSizing IN w.flags) THEN w := NIL; END;
  2196.         ELSE END;
  2197.         CASE PlainId (actionid) OF
  2198.         moveWinLeft, moveWinRight, moveWinUp, moveWinDown, upperLeftWin,
  2199.         lowerLeftWin, upperRightWin, lowerRightWin, centerWin:
  2200.           IF w # NIL THEN IF ~(I.windowDrag IN w.flags) THEN w := NIL; END; END;
  2201.         ELSE END; 
  2202.       END;  
  2203.       IF w # NIL THEN
  2204.         vpe := b.ScrVPExtra (w.wScreen);
  2205.         IF (vpe = NIL) OR ~b.VisibleOfScreen (w.wScreen, rect) THEN w := NIL; END;
  2206.       END;
  2207.       IF w # NIL THEN
  2208.         dcwidth := vpe.displayClip.maxX-vpe.displayClip.minX+1;
  2209.         dcheight := vpe.displayClip.maxY-vpe.displayClip.minY+1;
  2210.         vswidth := rect.maxX-rect.minX+1;
  2211.         vsheight := rect.maxY-rect.minY+1;
  2212.         wx := b.Max2 (dcwidth DIV winMoveSteps, 1);
  2213.         wy := b.Max2 (dcheight DIV winMoveSteps, 1);
  2214.         wl := w.leftEdge; wt := w.topEdge; ww := w.width; wh := w.height;
  2215.         CASE PlainId (actionid) OF
  2216.         adaptWindow:
  2217.           IF ~(I.windowDrag IN w.flags) THEN
  2218.             IF I.windowSizing IN w.flags THEN
  2219.               IF (wl <= rect.maxX) & (wt <= rect.maxY) &
  2220.                  (wl+ww-1 >= rect.minX) & (wt+wh-1 >= rect.minY) THEN
  2221.                 IF (wl+ww-1 > rect.maxX) & (wl + w.minWidth -1 <= rect.maxX) THEN   
  2222.                   ww := b.Max2 (1, (b.Max2 (w.minWidth, rect.maxX-wl+1)));
  2223.                 END;  
  2224.                 IF (wt+wh-1 > rect.maxY) & (wt + w.minHeight-1 <= rect.maxY) THEN  
  2225.                   wh := b.Max2 (1, b.Max2  (w.minHeight, rect.maxY-wt+1));
  2226.                 END;  
  2227.               END;  
  2228.             END
  2229.           ELSE  
  2230.             IF I.windowSizing IN w.flags THEN
  2231.               IF ww > vswidth  THEN  
  2232.                 ww := b.Max2 (1, b.Max2 (w.minWidth , vswidth ));
  2233.               END;  
  2234.               IF wh > vsheight THEN
  2235.                 wh := b.Max2 (1, b.Max2 (w.minHeight, vsheight)); 
  2236.               END;
  2237.             END;
  2238.             IF wl+ww-1 > rect.maxX THEN wl := b.Max2 (0, rect.maxX+1-ww); END;
  2239.             IF wt+wh-1 > rect.maxY THEN wt := b.Max2 (0, rect.maxY+1-wh); END;
  2240.             IF wl < rect.minX THEN 
  2241.               wl := b.Max2 (0, b.Min2 (rect.minX, w.wScreen.width -ww));
  2242.             END;
  2243.             IF wt < rect.minY THEN 
  2244.               wt := b.Max2 (0, b.Min2 (rect.minY, w.wScreen.height-wh));
  2245.             END;
  2246.           END; |
  2247.         maxWin, maxWinWidth, maxWinHeight:
  2248.           IF I.windowDrag IN w.flags THEN
  2249.             nww := vswidth; nwh := vsheight;
  2250.             CASE PlainId (actionid) OF
  2251.             maxWin, maxWinWidth:
  2252.               wl := b.Max2 (0, b.Min2 (rect.minX, w.wScreen.width-w.minWidth)); |
  2253.             ELSE END;
  2254.             CASE PlainId (actionid) OF
  2255.             maxWin, maxWinHeight:
  2256.               wt := b.Max2 (0, b.Min2 (rect.minY, w.wScreen.height-w.minHeight));
  2257.             ELSE END;  
  2258.           ELSE
  2259.             nww := dcwidth; nwh := dcheight;
  2260.           END;            
  2261.           CASE PlainId (actionid) OF
  2262.           maxWin, maxWinWidth:
  2263.             ww := b.Max2 (1, b.Max2 (w.minWidth, 
  2264.                                      b.Min2 (b.Min2 (nww, w.wScreen.width-wl), 
  2265.                                              I.UIntToLong (w.maxWidth ))));
  2266.           ELSE END;                                   
  2267.           CASE PlainId (actionid) OF
  2268.           maxWin, maxWinHeight:
  2269.             wh := b.Max2 (1, b.Max2 (w.minHeight,
  2270.                                      b.Min2 (b.Min2 (nwh, w.wScreen.height-wt),
  2271.                                              I.UIntToLong (w.maxHeight))));
  2272.           ELSE END; |
  2273.         minWin:
  2274.           ww := b.Max2 (1, b.Min2 (w.wScreen.width , w.minWidth ));
  2275.           wh := b.Max2 (1, b.Min2 (w.wScreen.height, w.minHeight));
  2276.           IF I.windowDrag IN w.flags THEN
  2277.             wl := b.Max2 (0, rect.maxX-ww+1);
  2278.             wt := b.Max2 (0, rect.maxY-wh+1);
  2279.           END; |
  2280.         doubleWidth, expandWidth:
  2281.           CASE PlainId (actionid) OF
  2282.           doubleWidth: nww := 2 * ww; |
  2283.           expandWidth: nww := ww+wx
  2284.           END;
  2285.           IF I.windowDrag IN w.flags THEN
  2286.             ww := b.Max2 (1, b.Min2 (w.wScreen.width,
  2287.                                      b.Min2 (nww, I.UIntToLong (w.maxWidth))));
  2288.             wl := b.Max2 (0, b.Min2 (wl, w.wScreen.width-ww));
  2289.           ELSE  
  2290.             ww := b.Max2 (1, b.Min2 (w.wScreen.width-wl,
  2291.                                      b.Min2 (nww, I.UIntToLong (w.maxWidth))));          
  2292.           END; |                           
  2293.         doubleHeight, expandHeight:  
  2294.           CASE PlainId (actionid) OF
  2295.           doubleHeight: nwh := 2 * wh; |
  2296.           expandHeight: nwh := wh+wy
  2297.           END;
  2298.           IF I.windowDrag IN w.flags THEN
  2299.             wh := b.Max2 (1, b.Min2 (w.wScreen.height,
  2300.                                      b.Min2 (nwh, I.UIntToLong (w.maxHeight))));
  2301.             wt := b.Max2 (0, b.Min2 (wt, w.wScreen.height-wh));
  2302.           ELSE  
  2303.             wh := b.Max2 (1, b.Min2 (w.wScreen.height-wt,
  2304.                                      b.Min2 (nwh, I.UIntToLong (w.maxHeight))));
  2305.           END; |                           
  2306.         halveWidth:  
  2307.           ww := b.Max2 (1, b.Max2 (w.minWidth, ww DIV 2)); |
  2308.         halveHeight:  
  2309.           wh := b.Max2 (1, b.Max2 (w.minHeight, wh DIV 2)); |
  2310.         shrinkWidth:  
  2311.           ww := b.Max2 (1, b.Max2 (w.minWidth, ww-wx)); |
  2312.         shrinkHeight:  
  2313.           wh := b.Max2 (1, b.Max2 (w.minHeight, wh-wy)); |
  2314.         moveWinRight: 
  2315.           wl := b.Max2 (0, b.Min2 (wl+wx, w.wScreen.width-ww)); |
  2316.         moveWinLeft : 
  2317.           wl := b.Max2 (0, wl-wx); |
  2318.         moveWinDown : 
  2319.           wt := b.Max2 (0, b.Min2 (wt+wy, w.wScreen.height-wh)); |
  2320.         moveWinUp   : 
  2321.           wt := b.Max2 (0, wt-wy); |
  2322.         upperLeftWin: 
  2323.           wl := b.Max2 (0, b.Min2 (rect.minX, w.wScreen.width -ww));
  2324.           wt := b.Max2 (0, b.Min2 (rect.minY, w.wScreen.height-wh)); |
  2325.         lowerLeftWin:  
  2326.           wl := b.Max2 (0, b.Min2 (rect.minX, w.wScreen.width -ww));
  2327.           wt := b.Max2 (0, rect.maxY-wh+1); |
  2328.         upperRightWin:
  2329.           wl := b.Max2 (0, rect.maxX-ww+1);
  2330.           wt := b.Max2 (0, b.Min2 (rect.minY, w.wScreen.height-wh)); |
  2331.         lowerRightWin:
  2332.           wl := b.Max2 (0, rect.maxX-ww+1);
  2333.           wt := b.Max2 (0, rect.maxY-wh+1); |
  2334.         centerWin:  
  2335.           wl := b.Max2 (0, vswidth -w.width ) DIV 2 + rect.minX;
  2336.           wt := b.Max2 (0, vsheight-w.height) DIV 2 + rect.minY;
  2337.         ELSE END;  
  2338.         wx := wl - w.leftEdge;
  2339.         wy := wt - w.topEdge;
  2340.         IF (wl # w.leftEdge) OR 
  2341.             (wt # w.topEdge) OR (ww # w.width) OR (wh # w.height) THEN
  2342.           CASE PlainId (actionid) OF
  2343.           moveWinLeft, moveWinRight, moveWinUp, moveWinDown, upperLeftWin,
  2344.           lowerLeftWin, upperRightWin, lowerRightWin, centerWin:
  2345.             reallymovewnd := true;            
  2346.           ELSE END;  
  2347.           IF ~(I.windowSizing IN w.flags) THEN
  2348.             reallymovewnd := true;
  2349.           END;  
  2350.           IF ~reallymovewnd THEN reallychwbox := true; END;
  2351.         END;  
  2352.       END;
  2353.     ELSE END;
  2354.     IF w # NIL THEN
  2355.       IF IsActivationId (actionid) THEN reallyactivate := true; END;
  2356.       IF IsToFrontId (actionid) THEN
  2357.         IF ~(I.backDrop IN w.flags) THEN reallytofront := true; END;
  2358.       END;
  2359.       IF ~reallyzip & ~reallychwbox & ~reallymovewnd THEN
  2360.         wl := w.leftEdge; wt := w.topEdge; ww := w.width; wh := w.height;
  2361.       END;
  2362.     END;
  2363.     CheckHuntWindow();
  2364.     y.SETREG (0, e.SetTaskPri (chieftask, 100));
  2365.     I.UnlockIBase (lk);
  2366.     IF fscr # NIL THEN I.ScreenToFront (fscr); END;
  2367.     IF bscr # NIL THEN I.ScreenToBack (bscr); END;
  2368.     IF reallyactivate THEN I.ActivateWindow (w); END;
  2369.     IF reallytofront THEN I.WindowToFront (w); END;
  2370.     IF reallytoback THEN I.WindowToBack (w); END;
  2371.     IF reallyzip THEN I.ZipWindow (w); END;
  2372.     IF reallychwbox THEN I.ChangeWindowBox (w, wl, wt, ww, wh); END;
  2373.     IF reallymovewnd THEN I.MoveWindow (w, wx, wy); END;
  2374.     I.UnlockPubScreen (NIL, pscr);
  2375.     HuntWindow();
  2376.     y.SETREG (0, e.SetTaskPri (chieftask, chiefpri));
  2377.     IF reallyzip & IsToFrontId (actionid) THEN
  2378.       d.Delay (10);
  2379.       DoIntuiAction (sendHuntZipped);
  2380.     END; |
  2381.   scrollScrLeft, scrollScrRight, scrollScrUp, scrollScrDown:
  2382.     sx := 0; sy := 0;
  2383.     scr := I.int.activeScreen;
  2384.     vpe := b.ScrVPExtra (scr);
  2385.     IF vpe # NIL THEN
  2386.       sx := b.Max2((vpe.displayClip.maxX-vpe.displayClip.minX+1) 
  2387.                    DIV scrMoveSteps, 1);
  2388.       sy := b.Max2((vpe.displayClip.maxY-vpe.displayClip.minY+1) 
  2389.                    DIV scrMoveSteps, 1);
  2390.       CASE PlainId (actionid) OF
  2391.       scrollScrLeft : sy := 0; |
  2392.       scrollScrRight: sy := 0; sx := -sx; |
  2393.       scrollScrUp   : sx := 0; sy := b.Min2 (scr.topEdge+sy,
  2394.                                           vpe.displayClip.maxY)-scr.topEdge; |
  2395.       scrollScrDown : sx := 0; sy := -sy;
  2396.       ELSE END;
  2397.     END;
  2398.     IF (sx # 0) OR (sy # 0) THEN reallymovescr := true; END;
  2399.     y.SETREG (0, e.SetTaskPri (chieftask, 100));
  2400.     I.UnlockIBase (lk);
  2401.     IF reallymovescr THEN I.MoveScreen (scr, sx, sy); END;
  2402.     y.SETREG (0, e.SetTaskPri (chieftask, chiefpri)); |
  2403.   upperLeftScr, lowerLeftScr, upperRightScr, lowerRightScr, showScrCenter, screenTop:
  2404.     scr := I.int.activeScreen;
  2405.     vpe := b.ScrVPExtra (scr);
  2406.     IF (vpe # NIL) & b.VisibleOfScreen (scr, rect) THEN
  2407.       sx := b.Min2 (vpe.displayClip.maxX-vpe.displayClip.minX+1, scr.width);
  2408.       sy := b.Min2 (vpe.displayClip.maxY-vpe.displayClip.minY+1, scr.height);
  2409.       CASE PlainId (actionid) OF
  2410.       screenTop:
  2411.         x1 := rect.minX; y1 := 0; sx := rect.maxX-rect.minX+1; |
  2412.       upperLeftScr:
  2413.         x1 := 0; y1 := 0; |
  2414.       lowerLeftScr:
  2415.         x1 := 0; y1 := scr.height-sy; |
  2416.       upperRightScr:
  2417.         x1 := scr.width-sx; y1 := 0; |
  2418.       lowerRightScr:
  2419.         x1 := scr.width-sx; y1 := scr.height-sy; |
  2420.       showScrCenter:
  2421.         x1 := (scr.width-sx) DIV 2; y1 := (scr.height-sy) DIV 2;
  2422.       ELSE END;
  2423.       x2 := x1+sx-1; y2 := y1+sy-1;
  2424.       reallymovescr := true;
  2425.       PrepareScrPos (scr, x1, y1, x2, y2, sx, sy);
  2426.     END;
  2427.     y.SETREG (0, e.SetTaskPri (chieftask, 100));
  2428.     I.UnlockIBase (lk);
  2429.     IF reallymovescr THEN ScrPos (scr, x1, y1, x2, y2, sx, sy); END;
  2430.     y.SETREG (0, e.SetTaskPri (chieftask, chiefpri));
  2431.   ELSE
  2432.     I.UnlockIBase (lk);
  2433.     I.DisplayBeep (NIL);
  2434.   END;
  2435. END DoIntuiAction;
  2436.  
  2437.  
  2438.  
  2439. VAR
  2440.   AngieMsg: I.IntuiMessage;
  2441.   AngieGad: I.GadgetPtr;
  2442.  
  2443. TYPE
  2444.   GadProcArrT = ARRAY LEN (ag.AngieGadgets) OF PROCEDURE (): BOOLEAN;
  2445.  
  2446. VAR
  2447.   defprocstr: b.DynStrPtr;
  2448.  
  2449. PROCEDURE^ HotKeysKeyProc (): BOOLEAN;
  2450.  
  2451. PROCEDURE DefinitionProc (): BOOLEAN;
  2452. VAR
  2453.   l : LONGINT;
  2454.   nd: HotKeyNodePtr;
  2455. BEGIN
  2456.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2457.   nd := GetHotKeyNode (SelectedHotKey);
  2458.   DISPOSE (defprocstr);
  2459.   IF ~b.DynAppend (defprocstr, nd.node.name^) THEN END;
  2460.   l := b.DynTTLen (hotdefs);
  2461.   SuspendHotKeyDisplay();
  2462.   IF (AngieMsg.code # 27) &
  2463.      ~AddHotKey (nd.type, 
  2464.                  ag.AngieGadgets [ag.GDdefinition].specialInfo (I.StringInfo).buffer^,
  2465.                  nd.text^, SelectedHotKey, replaceMode) &
  2466.      (l = b.DynTTLen (hotdefs)) & (defprocstr # NIL) &
  2467.      ~AddHotKey (nd.type, defprocstr^, nd.text^, 
  2468.                  SelectedHotKey, replaceMode) THEN END;
  2469.   UpdateHotKeyDisplay ({fixType});
  2470.   IF b.DynTTLen (hotdefs) = l THEN
  2471.     CASE AngieMsg.code OF
  2472.     ag.rawCrsrUp, ag.rawCrsrDown:
  2473.       RETURN HotKeysKeyProc ();
  2474.     ELSE END;  
  2475.   END;  
  2476.   RETURN true;                   
  2477. END DefinitionProc;                     
  2478.  
  2479. PROCEDURE DefinitionKeyProc (): BOOLEAN;
  2480. BEGIN
  2481.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2482.   IF I.ActivateGadget (ag.AngieGadgets [ag.GDdefinition]^, 
  2483.                        ag.AngieWnd, NIL) THEN END;
  2484.   RETURN true;                     
  2485. END DefinitionKeyProc;                       
  2486.  
  2487. PROCEDURE HotKeysProc (): BOOLEAN;
  2488. BEGIN
  2489.   SelectedHotKey := AngieMsg.code;
  2490.   UpdateHotKeyDisplay ({fixType});
  2491.   RETURN true;
  2492. END HotKeysProc;  
  2493.  
  2494. PROCEDURE HotKeysKeyProc (): BOOLEAN;
  2495. BEGIN
  2496.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2497.   CASE AngieMsg.code OF
  2498.   ag.rawCrsrUp:
  2499.     IF SelectedHotKey > 0 THEN DEC (SelectedHotKey); END; |
  2500.   ag.rawCrsrDown:
  2501.     IF SelectedHotKey < b.DynTTLen (hotdefs)-1 THEN INC (SelectedHotKey); END;
  2502.   ELSE END;  
  2503.   UpdateHotKeyDisplay ({fixType});
  2504.   RETURN true;
  2505. END HotKeysKeyProc;  
  2506.  
  2507. PROCEDURE PriProc (): BOOLEAN;
  2508. BEGIN
  2509.   nb.pri := SHORT (AngieMsg.code);
  2510.   LOOP
  2511.     ResetBroker();
  2512.     IF co.CxObjError (br) = LONGSET {} THEN EXIT; END;
  2513.     IF b.SimpleRequestArgs (ag.AngieWnd, LONGSET {b.lockWindow, b.ignoreTitle},
  2514.                             "", "Problems during resetting the broker",
  2515.                             "Retry|Quit Angie", NIL) = 0 THEN HALT (20); END;    
  2516.   END;
  2517.   IF active THEN ActivateBroker (true); END;
  2518.   RETURN true;
  2519. END PriProc;
  2520.  
  2521. PROCEDURE PriKeyProc (): BOOLEAN;
  2522. BEGIN
  2523.   IF {ie.lShift, ie.rShift} * AngieMsg.qualifier = {} THEN
  2524.     IF nb.pri >= MAX (SHORTINT) THEN RETURN true; END;
  2525.     INC (nb.pri, 1);
  2526.   ELSE  
  2527.     IF nb.pri <= MIN (SHORTINT) THEN RETURN true; END;
  2528.     DEC (nb.pri, 1);
  2529.   END;
  2530.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDpri]^, ag.AngieWnd, NIL,
  2531.                      gt.slLevel, nb.pri, u.done);
  2532.   AngieMsg.code := nb.pri;
  2533.   RETURN PriProc();
  2534. END PriKeyProc;  
  2535.  
  2536. PROCEDURE DelayProc (): BOOLEAN;
  2537. BEGIN
  2538.   SetSnoopDelay (AngieMsg.code);
  2539.   RETURN true;
  2540. END DelayProc;  
  2541.  
  2542. PROCEDURE DelayKeyProc (): BOOLEAN;
  2543. BEGIN
  2544.   IF {ie.lShift, ie.rShift} * AngieMsg.qualifier = {} THEN
  2545.     SetSnoopDelay (snoopdelay + b.Max2 (1, snoopdelay DIV 10));
  2546.   ELSE  
  2547.     SetSnoopDelay (snoopdelay - b.Max2 (1, snoopdelay DIV 10));
  2548.   END;
  2549.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDdelay]^, ag.AngieWnd, NIL,
  2550.                      gt.slLevel, snoopdelay, u.done);
  2551.   RETURN true;
  2552. END DelayKeyProc;  
  2553.  
  2554. PROCEDURE StableProc (): BOOLEAN;
  2555. BEGIN
  2556.   SetStableTime (AngieMsg.code);
  2557.   RETURN true;
  2558. END StableProc;
  2559.  
  2560. PROCEDURE StableKeyProc (): BOOLEAN;
  2561. BEGIN
  2562.   IF {ie.lShift, ie.rShift} * AngieMsg.qualifier = {} THEN
  2563.     SetStableTime (stabletime + b.Max2 (1, stabletime DIV 10));
  2564.   ELSE  
  2565.     SetStableTime (stabletime - b.Max2 (1, stabletime DIV 10));
  2566.   END;
  2567.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDstable]^, ag.AngieWnd, NIL,
  2568.                      gt.slLevel, stabletime, u.done);
  2569.   RETURN true;
  2570. END StableKeyProc;
  2571.  
  2572. PROCEDURE PopProc (): BOOLEAN;
  2573. BEGIN
  2574.   cxpopup := I.selected IN AngieGad.flags;
  2575.   RETURN true;
  2576. END PopProc;
  2577.  
  2578. PROCEDURE PopKeyProc(): BOOLEAN;
  2579. BEGIN
  2580.   cxpopup := ~cxpopup;
  2581.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDpop]^, ag.AngieWnd, NIL,
  2582.                      gt.cbChecked, BoolToLBool (cxpopup), u.done);
  2583.   RETURN true;
  2584. END PopKeyProc;
  2585.  
  2586. PROCEDURE KeyActProc (): BOOLEAN;
  2587. BEGIN
  2588.   keyactivate := I.selected IN AngieGad.flags;
  2589.   RETURN true;
  2590. END KeyActProc;
  2591.   
  2592. PROCEDURE KeyActKeyProc (): BOOLEAN;
  2593. BEGIN
  2594.   keyactivate := ~keyactivate;
  2595.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDkeyact]^, ag.AngieWnd, NIL,
  2596.                      gt.cbChecked, BoolToLBool (keyactivate), u.done);  
  2597.   RETURN true;
  2598. END KeyActKeyProc;
  2599.   
  2600. PROCEDURE IncWinTaskPriProc (): BOOLEAN;
  2601. BEGIN
  2602.   incwintaskpri := I.selected IN AngieGad.flags;
  2603.   IF ~incwintaskpri THEN
  2604.     y.SETREG (0, SecureSetTaskPri (IncTask, OldPri)); IncTask := NIL; 
  2605.   END;  
  2606.   RETURN true;
  2607. END IncWinTaskPriProc;
  2608.  
  2609. PROCEDURE IncWinTaskPriKeyProc (): BOOLEAN;
  2610. BEGIN
  2611.   incwintaskpri := ~incwintaskpri;
  2612.   IF ~incwintaskpri THEN
  2613.     y.SETREG (0, SecureSetTaskPri (IncTask, OldPri)); IncTask := NIL; 
  2614.   END;  
  2615.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDincwintaskpri]^, ag.AngieWnd, NIL,
  2616.                      gt.cbChecked, BoolToLBool (incwintaskpri), u.done);
  2617.   RETURN true;
  2618. END IncWinTaskPriKeyProc;
  2619.  
  2620. PROCEDURE HuntAlwaysProc (): BOOLEAN;
  2621. BEGIN
  2622.   huntwindowalways := I.selected IN AngieGad.flags;
  2623.   RETURN true;
  2624. END HuntAlwaysProc;
  2625.   
  2626. PROCEDURE HuntAlwaysKeyProc (): BOOLEAN;
  2627. BEGIN
  2628.   huntwindowalways := ~huntwindowalways;
  2629.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDhuntalways]^, ag.AngieWnd, NIL,
  2630.                      gt.cbChecked, BoolToLBool (huntwindowalways), u.done);
  2631.   RETURN true;
  2632. END HuntAlwaysKeyProc;
  2633.   
  2634. PROCEDURE HuntWinToFrontProc (): BOOLEAN;
  2635. BEGIN
  2636.   huntwindowwfr := I.selected IN AngieGad.flags;
  2637.   RETURN true;
  2638. END HuntWinToFrontProc;
  2639.  
  2640. PROCEDURE HuntWinToFrontKeyProc (): BOOLEAN;
  2641. BEGIN
  2642.   huntwindowwfr := ~huntwindowwfr;
  2643.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDhuntwintofront]^, ag.AngieWnd, NIL,
  2644.                      gt.cbChecked, BoolToLBool (huntwindowwfr), u.done);
  2645.   RETURN true;
  2646. END HuntWinToFrontKeyProc;
  2647.  
  2648. VAR
  2649.   shufflepatprocstr: b.DynStrPtr;
  2650.  
  2651. PROCEDURE ShufflePatProc (): BOOLEAN;
  2652. VAR
  2653.   pat: b.LStrPtr;
  2654. BEGIN
  2655.   IF shufflestr # NIL THEN 
  2656.     pat := y.ADR (shufflestr[0]); 
  2657.   ELSE 
  2658.     pat := y.ADR ("#?"); 
  2659.   END;                   
  2660.   DISPOSE (shufflepatprocstr);
  2661.   IF ~b.DynAppend (shufflepatprocstr, pat^) THEN END;
  2662.   IF (AngieMsg.code = 27) OR
  2663.      ~SetShufflePattern (ag.AngieGadgets 
  2664.                          [ag.GDshufflepat].specialInfo 
  2665.                                            (I.StringInfo).buffer^) THEN
  2666.     IF shufflepatprocstr # NIL THEN 
  2667.       pat := y.ADR (shufflepatprocstr[0]); 
  2668.     ELSE 
  2669.       pat := y.ADR ("#?"); 
  2670.     END;                   
  2671.     IF ~SetShufflePattern (pat^) THEN END;
  2672.   END;  
  2673.   IF shufflestr # NIL THEN 
  2674.     pat := y.ADR (shufflestr[0]); 
  2675.   ELSE 
  2676.     pat := y.ADR ("#?"); 
  2677.   END;                       
  2678.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDshufflepat]^, ag.AngieWnd, NIL,
  2679.                      gt.stString, pat, u.done);
  2680.   RETURN true;
  2681. END ShufflePatProc;
  2682.  
  2683. PROCEDURE ShufflePatKeyProc (): BOOLEAN;
  2684. BEGIN
  2685.   IF I.ActivateGadget (ag.AngieGadgets [ag.GDshufflepat]^, 
  2686.                        ag.AngieWnd, NIL) THEN END;
  2687.   RETURN true;                     
  2688. END ShufflePatKeyProc;                 
  2689.  
  2690. PROCEDURE ShuffleBDropProc (): BOOLEAN;
  2691. BEGIN
  2692.   shufflebackdrop := I.selected IN AngieGad.flags;
  2693.   RETURN true;
  2694. END ShuffleBDropProc;  
  2695.  
  2696. PROCEDURE ShuffleBDropKeyProc (): BOOLEAN;
  2697. BEGIN
  2698.   shufflebackdrop := ~shufflebackdrop;
  2699.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDshufflebdrop]^, ag.AngieWnd, NIL,
  2700.                      gt.cbChecked, BoolToLBool (shufflebackdrop), u.done);  
  2701.   RETURN true;
  2702. END ShuffleBDropKeyProc;  
  2703.  
  2704. PROCEDURE ScrStepsProc (): BOOLEAN;
  2705. BEGIN
  2706.   scrMoveSteps := AngieMsg.code;
  2707.   RETURN true;
  2708. END ScrStepsProc;  
  2709.  
  2710. PROCEDURE ScrStepsKeyProc (): BOOLEAN;
  2711. BEGIN
  2712.   IF {ie.lShift, ie.rShift} * AngieMsg.qualifier = {} THEN
  2713.     scrMoveSteps := SHORT (b.Min2 (50, scrMoveSteps+1));
  2714.   ELSE  
  2715.     scrMoveSteps := SHORT (b.Max2 (1, scrMoveSteps-1));
  2716.   END;
  2717.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDscrsteps]^, ag.AngieWnd, NIL,
  2718.                      gt.slLevel, scrMoveSteps, u.done);
  2719.   RETURN true;
  2720. END ScrStepsKeyProc;
  2721.  
  2722. PROCEDURE WinStepsProc (): BOOLEAN;
  2723. BEGIN
  2724.   winMoveSteps := AngieMsg.code;
  2725.   RETURN true;
  2726. END WinStepsProc;  
  2727.   
  2728. PROCEDURE WinStepsKeyProc (): BOOLEAN;
  2729. BEGIN
  2730.   IF {ie.lShift, ie.rShift} * AngieMsg.qualifier = {} THEN
  2731.     winMoveSteps := SHORT (b.Min2 (50, winMoveSteps+1));
  2732.   ELSE  
  2733.     winMoveSteps := SHORT (b.Max2 (1, winMoveSteps-1));
  2734.   END;
  2735.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDwinsteps]^, ag.AngieWnd, NIL,
  2736.                      gt.slLevel, winMoveSteps, u.done);
  2737.   RETURN true;
  2738. END WinStepsKeyProc;
  2739.  
  2740. PROCEDURE HuntDefPubProc (): BOOLEAN;
  2741. BEGIN
  2742.   setdefpubonhunt := I.selected IN AngieGad.flags;
  2743.   RETURN true;
  2744. END HuntDefPubProc;
  2745.   
  2746. PROCEDURE HuntDefPubKeyProc (): BOOLEAN;
  2747. BEGIN
  2748.   setdefpubonhunt := ~setdefpubonhunt;
  2749.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDhuntdefpub]^, ag.AngieWnd, NIL,
  2750.                      gt.cbChecked, BoolToLBool (setdefpubonhunt), u.done);
  2751.   RETURN true;
  2752. END HuntDefPubKeyProc;
  2753.  
  2754. CONST
  2755.   newItemTxt ="(new entry)";
  2756.  
  2757. PROCEDURE AddProc (): BOOLEAN;
  2758. VAR
  2759.   l1, l2: LONGINT;
  2760. BEGIN
  2761.   l1 := b.DynTTLen (hotdefs);
  2762.   SuspendHotKeyDisplay();
  2763.   IF AddHotKey (0, newItemTxt, "", SelectedHotKey+1, insertMode) THEN END;
  2764.   l2 := b.DynTTLen (hotdefs);
  2765.   IF l1 < l2 THEN 
  2766.     INC (SelectedHotKey);
  2767.   ELSE
  2768.     I.DisplayBeep (ag.AngieWnd.wScreen); 
  2769.   END;
  2770.   UpdateHotKeyDisplay ({fixType});
  2771.   IF (SelectedHotKey >= 0) & (l1 < l2) THEN
  2772.     IF I.ActivateGadget (ag.AngieGadgets [ag.GDdefinition]^, 
  2773.                          ag.AngieWnd, NIL) THEN END;
  2774.   END;                       
  2775.   RETURN true;
  2776. END AddProc;
  2777.  
  2778. PROCEDURE DelProc (): BOOLEAN;  
  2779. BEGIN
  2780.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2781.   SuspendHotKeyDisplay();
  2782.   DelHotKey (SelectedHotKey);
  2783.   UpdateHotKeyDisplay ({fixType});
  2784.   RETURN true;
  2785. END DelProc;  
  2786.  
  2787. PROCEDURE UpProc (): BOOLEAN;
  2788. BEGIN
  2789.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2790.   IF SelectedHotKey > 0 THEN
  2791.     SuspendHotKeyDisplay();
  2792.     IF SwapHotKeys (SelectedHotKey, SelectedHotKey-1) THEN
  2793.       DEC (SelectedHotKey);
  2794.     ELSE  
  2795.       I.DisplayBeep (ag.AngieWnd.wScreen);
  2796.     END;  
  2797.   END;  
  2798.   UpdateHotKeyDisplay ({fixType});
  2799.   RETURN true;
  2800. END UpProc;  
  2801.  
  2802. PROCEDURE DownProc (): BOOLEAN;
  2803. BEGIN
  2804.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2805.   IF SelectedHotKey < b.DynTTLen (hotdefs)-1 THEN
  2806.     SuspendHotKeyDisplay();
  2807.     IF SwapHotKeys (SelectedHotKey, SelectedHotKey+1) THEN
  2808.       INC (SelectedHotKey);
  2809.     ELSE  
  2810.       I.DisplayBeep (ag.AngieWnd.wScreen);
  2811.     END;  
  2812.   END;  
  2813.   UpdateHotKeyDisplay ({fixType});
  2814.   RETURN true;
  2815. END DownProc;  
  2816.  
  2817. VAR
  2818.   chaux: b.DynStrPtr;
  2819.  
  2820. PROCEDURE ChangeHotKeyType (type: LONGINT; text: ARRAY OF CHAR);
  2821. VAR 
  2822.   nd  : HotKeyNodePtr;
  2823.   succ: BOOLEAN;
  2824.   oldtype: LONGINT;
  2825. (* $CopyArrays- *)
  2826. BEGIN
  2827.   oldtype := 0;
  2828.   succ := false;
  2829.   IF SelectedHotKey < 0 THEN RETURN; END;
  2830.   nd := GetHotKeyNode (SelectedHotKey);
  2831.   IF IsValidId (type) THEN
  2832.     type := AdaptIdToEntry (type, SelectedHotKey);
  2833.     DISPOSE (chaux);
  2834.     IF b.DynAppend (chaux, text) THEN
  2835.       DISPOSE (nd.text);
  2836.       nd.text := chaux; chaux := NIL;
  2837.     END;  
  2838.     oldtype := nd.type;
  2839.     nd.type := type; 
  2840.     co.DeleteCxObjAll (nd.cxobj); nd.cxobj := NIL;
  2841.     IF PlainId (type) # noKeyActivate THEN
  2842.       nd.cxobj := cx.HotKey (nd.node.name^, nb.port, type);
  2843.       IF IsNoKeyScrActId (type) THEN y.SETREG (0, co.SetCxObjPri (nd.cxobj, 2)); END;
  2844.       IF br # NIL THEN co.EnqueueCxObj (br, nd.cxobj); END;
  2845.       succ := nd.cxobj # NIL;
  2846.     ELSE  
  2847.       succ := co.ParseIX (nd.node.name^, DummyIX) = 0;
  2848.     END;  
  2849.     IF (PlainId (oldtype) = noKeyActivate) OR (PlainId (type) = noKeyActivate) THEN
  2850.       ResetNoActScrKeys();
  2851.     END;  
  2852.   END;
  2853.   IF ~succ THEN I.DisplayBeep (ag.AngieWnd.wScreen); END;
  2854.   UpdateHotKeyDisplay ({});
  2855.   RETURN;
  2856. END ChangeHotKeyType;  
  2857.  
  2858. PROCEDURE TypeProc (): BOOLEAN;
  2859. VAR
  2860.   type: LONGINT;
  2861.   i   : INTEGER;
  2862.   str: e.STRPTR;
  2863. BEGIN
  2864.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2865.   str := ag.AngieGadgets [ag.GDtype].specialInfo (I.StringInfo).buffer;
  2866.   i := 0;
  2867.   WHILE (i < hotKeys) & (u.Stricmp (str^, hotnames[i]^) # 0) DO INC (i); END;
  2868.   IF i >= hotKeys THEN i := custom; END;
  2869.   type := i;
  2870.   IF AngieMsg.code # 27 THEN
  2871.     IF i # custom THEN str := y.ADR (""); END;
  2872.     ChangeHotKeyType (AttrsOfId (GetHotKeyNode (SelectedHotKey).type) + type, str^);
  2873.   END;  
  2874.   UpdateHotKeyDisplay ({fixType});
  2875.   RETURN true;
  2876. END TypeProc;
  2877.  
  2878. PROCEDURE MTypeProc (): BOOLEAN;
  2879. VAR
  2880.   str: e.STRPTR;
  2881.   nd : HotKeyNodePtr;
  2882. BEGIN
  2883.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2884.   nd := GetHotKeyNode (SelectedHotKey);
  2885.   IF (AngieMsg.code = PlainId (nd.type)) & (AngieMsg.code = custom) THEN
  2886.     str := y.ADR (nd.text[0]);
  2887.   ELSE  
  2888.     str := y.ADR ("");
  2889.   END;  
  2890.   ChangeHotKeyType (AttrsOfId (nd.type) + AngieMsg.code, str^);
  2891.   UpdateHotKeyDisplay ({fixType});
  2892.   RETURN true;
  2893. END MTypeProc;  
  2894.  
  2895. PROCEDURE TypeKeyProc (): BOOLEAN;
  2896. BEGIN
  2897.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2898.   IF I.ActivateGadget (ag.AngieGadgets [ag.GDtype]^, 
  2899.                        ag.AngieWnd, NIL) THEN END;
  2900.   RETURN true;                     
  2901. END TypeKeyProc;                       
  2902.  
  2903. PROCEDURE AttrsProc (): BOOLEAN;
  2904. VAR
  2905.   nd: HotKeyNodePtr;
  2906. BEGIN
  2907.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2908.   nd := GetHotKeyNode (SelectedHotKey);
  2909.   ChangeHotKeyType (PlainId (nd.type) + ASH (AngieMsg.code, 8), nd.text^);
  2910.   RETURN true;
  2911. END AttrsProc;
  2912.  
  2913. PROCEDURE AttrsKeyProc (): BOOLEAN;
  2914. VAR
  2915.   cyc: LONGINT;
  2916.   nd : HotKeyNodePtr;
  2917. BEGIN
  2918.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2919.   nd := GetHotKeyNode (SelectedHotKey);
  2920.   cyc := ASH (AttrsOfId (nd.type), -8);
  2921.   IF {ie.lShift, ie.rShift} * AngieMsg.qualifier = {} THEN
  2922.     INC (cyc, 1); IF cyc >= 8 THEN cyc := 0; END;
  2923.   ELSE  
  2924.     DEC (cyc, 1); IF cyc < 0 THEN cyc := 7; END;
  2925.   END;
  2926.   gt.SetGadgetAttrs (ag.AngieGadgets [ag.GDattrs]^, ag.AngieWnd, NIL,
  2927.                      gt.cyActive, cyc, u.done);  
  2928.   ChangeHotKeyType (PlainId (nd.type) + ASH (cyc, 8), nd.text^);
  2929.   RETURN true;
  2930. END AttrsKeyProc;
  2931.  
  2932. PROCEDURE ProperType (type: LONGINT): LONGINT;
  2933. VAR
  2934.   i    : INTEGER;
  2935.   type1: LONGINT;
  2936. BEGIN
  2937.   type1 := PlainId (type);
  2938.   FOR i := 0 TO LEN (attrs)-1 DO
  2939.     IF attrs[i].isProc (type) THEN INC (type1, attrs[i].const); END;
  2940.   END;
  2941.   RETURN type1;
  2942. END ProperType;  
  2943.  
  2944. PROCEDURE MAttrsProc (): BOOLEAN;
  2945. VAR
  2946.   nd: HotKeyNodePtr;
  2947. BEGIN
  2948.   IF SelectedHotKey < 0 THEN RETURN true; END;
  2949.   nd := GetHotKeyNode (SelectedHotKey);
  2950.   ChangeHotKeyType (ProperType (PlainId (nd.type) + GetMenuAttrs ()), nd.text^);
  2951.   RETURN true;                    
  2952. END MAttrsProc;
  2953.  
  2954.  
  2955. PROCEDURE BoolToInt (b: BOOLEAN): INTEGER;
  2956. BEGIN
  2957.   IF b THEN RETURN 1; END;
  2958.   RETURN 0;
  2959. END BoolToInt;
  2960.  
  2961. TYPE  
  2962.   BoolStrArr = ARRAY 2 OF b.LStrPtr;
  2963.   
  2964. CONST  
  2965.   boolstrs = BoolStrArr (y.ADR ("NO"), y.ADR ("YES"));
  2966.   
  2967.  
  2968. VAR
  2969.   newdtt : b.DynTTPtr;
  2970.   saveaux: b.DynStrPtr;
  2971.   ad     : ARRAY 2 OF CHAR;
  2972.   do     : wb.DiskObjectPtr;
  2973.   dott   : b.TTPtr;
  2974.   arg    : ARRAY 2 OF e.APTR;
  2975.   wlk    : b.WinLockPtr;
  2976.  
  2977.   PROCEDURE SaveProcCleanUp(): BOOLEAN;  (* NOTEZ-BIEN: Amiga-Oberon3.00 compiles
  2978.                                             trash if this is located within SaveProc()
  2979.                                             and you invoke SaveProc() using
  2980.                                             'function pointer' indirection !! *)
  2981.   BEGIN
  2982.     IF do # NIL THEN 
  2983.       do.toolTypes := dott; 
  2984.       ic.FreeDiskObject (do); do := NIL; 
  2985.     END;
  2986.     b.FreeDynTT (newdtt); DISPOSE (saveaux);
  2987.     b.UnlockWindow (wlk);
  2988.     RETURN true;
  2989.   END SaveProcCleanUp;  
  2990.  
  2991. PROCEDURE WriteStrTT (name, val: ARRAY OF CHAR): BOOLEAN;
  2992. (* $CopyArrays- *)
  2993. BEGIN
  2994.   arg[0] := y.ADR (name[0]); arg[1] := y.ADR (val[0]);
  2995.   IF saveaux # NIL THEN saveaux[0] := '\000'; END;
  2996.   IF ~b.VDSPrintf (saveaux, "%s=%s", y.ADR (arg[0])) THEN RETURN false END;
  2997.   IF ~b.DynAppendTT (newdtt, saveaux^, {}) THEN RETURN false; END;
  2998.   RETURN true;
  2999. END WriteStrTT;
  3000.  
  3001. PROCEDURE WriteBoolTT (name: ARRAY OF CHAR; b: BOOLEAN): BOOLEAN;
  3002. (* $CopyArrays- *)
  3003. BEGIN
  3004.   RETURN WriteStrTT (name, boolstrs [BoolToInt (b)]^);
  3005. END WriteBoolTT;  
  3006.  
  3007. PROCEDURE WriteIntTT (name: ARRAY OF CHAR; val: LONGINT): BOOLEAN;
  3008. (* $CopyArrays- *)
  3009. BEGIN
  3010.   arg[0] := y.ADR (name[0]); arg[1] := val;
  3011.   IF saveaux # NIL THEN saveaux[0] := '\000'; END;
  3012.   IF ~b.VDSPrintf (saveaux, "%s=%ld", y.ADR (arg[0])) THEN RETURN false END;
  3013.   IF ~b.DynAppendTT (newdtt, saveaux^, {}) THEN RETURN false; END;
  3014.   RETURN true;
  3015. END WriteIntTT;
  3016.  
  3017. PROCEDURE SaveProc (): BOOLEAN;
  3018. VAR
  3019.   i,n: LONGINT;
  3020.   j,k: INTEGER;
  3021.   nd: HotKeyNodePtr;
  3022.   pat: b.LStrPtr;
  3023.  
  3024. BEGIN
  3025.   b.FreeDynTT (newdtt); DISPOSE (saveaux);
  3026.   wlk := b.LockWindow (ag.AngieWnd, wlk);
  3027.   do := ic.GetDiskObjectNew (prefsName);
  3028.   IF do = NIL THEN RETURN SaveProcCleanUp(); END;
  3029.   dott := do.toolTypes;
  3030.   
  3031.   IF ~b.DynAppendTT (newdtt, doNotWaitStr, {}) THEN RETURN SaveProcCleanUp(); END;
  3032.  
  3033.   IF ~WriteBoolTT (cxPopUpStr, cxpopup) THEN RETURN SaveProcCleanUp(); END;
  3034.  
  3035.   IF ~WriteIntTT (cxPriorityStr, nb.pri) THEN RETURN SaveProcCleanUp(); END;
  3036.  
  3037.   IF ~WriteBoolTT (keyActivateStr, keyactivate) THEN RETURN SaveProcCleanUp(); END;
  3038.  
  3039.   IF ~WriteBoolTT (shuffleBackdropStr, shufflebackdrop) THEN RETURN SaveProcCleanUp() END;
  3040.  
  3041.   IF shufflestr # NIL THEN pat := y.ADR (shufflestr[0]); ELSE pat := y.ADR ("#?") END;
  3042.   IF ~WriteStrTT (shufflePatStr, pat^) THEN RETURN SaveProcCleanUp(); END;
  3043.  
  3044.   IF ~WriteBoolTT (huntAlwaysStr, huntwindowalways) THEN RETURN SaveProcCleanUp(); END;
  3045.  
  3046.   IF ~WriteBoolTT (huntWinToFrontStr, huntwindowwfr) THEN RETURN SaveProcCleanUp(); END;
  3047.  
  3048.   IF ~WriteBoolTT (huntSetDefPubModeStr, setdefpubonhunt) THEN RETURN SaveProcCleanUp(); END;
  3049.  
  3050.   IF ~WriteIntTT (stableTimeStr, stabletime) THEN RETURN SaveProcCleanUp(); END;
  3051.  
  3052.   IF ~WriteIntTT (snoopDelayStr, snoopdelay) THEN RETURN SaveProcCleanUp(); END;
  3053.  
  3054.   IF ~WriteBoolTT (incWinTaskPriStr, incwintaskpri) THEN RETURN SaveProcCleanUp(); END;
  3055.  
  3056.   IF ~WriteIntTT (scrMoveStepsStr, scrMoveSteps) THEN RETURN SaveProcCleanUp(); END;
  3057.  
  3058.   IF ~WriteIntTT (winMoveStepsStr, winMoveSteps) THEN RETURN SaveProcCleanUp(); END;
  3059.  
  3060.   FOR i := 0 TO b.DynTTLen (hotdefs)-1 DO
  3061.     nd := GetHotKeyNode (i);
  3062.     DISPOSE (saveaux);
  3063.     IF ~b.VDSPrintf (saveaux, "%s=", y.ADR (hotnames[PlainId (nd.type)])) THEN
  3064.       RETURN SaveProcCleanUp();
  3065.     END;  
  3066.     ad[0] := "\000"; arg[0] := y.ADR (ad[0]);
  3067.     FOR k := 0 TO LEN (attrs)-1 DO
  3068.       IF attrs[k].isProc (nd.type) THEN
  3069.         arg[1] := attrs[k].name;
  3070.         IF ~b.VDSPrintf (saveaux, "%s%s", y.ADR (arg[0])) THEN RETURN SaveProcCleanUp(); END;
  3071.         ad[0] := '|';
  3072.       END;  
  3073.     END;
  3074.     FOR n := 0 TO st.Length (saveaux^)-1 DO saveaux[n] := u.ToUpper (saveaux[n]); END;
  3075.     IF ~b.VDSPrintf (saveaux, ":%s", y.ADR (nd.node.name)) THEN RETURN SaveProcCleanUp(); END;
  3076.     IF PlainId (nd.type) = custom THEN
  3077.       arg[1] := y.ADR (nd.text[0]);
  3078.       IF ~b.VDSPrintf (saveaux, "\x1b%s", y.ADR (arg[1])) THEN RETURN SaveProcCleanUp(); END;
  3079.     END;  
  3080.     IF ~b.DynAppendTT (newdtt, saveaux^, {}) THEN RETURN SaveProcCleanUp(); END;
  3081.   END; (* FOR *)
  3082.  
  3083.   IF dott # NIL THEN
  3084.     i := 0;    
  3085.     WHILE dott[i] # NIL DO
  3086.       LOOP
  3087.         FOR j := 0 TO hotKeys-1 DO
  3088.           IF b.CmpToolNames (hotnames[j]^ , dott[i]^) THEN EXIT; END;
  3089.         END;  
  3090.         FOR j := 0 TO LEN (miscTTNames)-1 DO
  3091.           IF b.CmpToolNames (miscTTNames[j]^, dott[i]^) THEN EXIT; END;
  3092.         END;  
  3093.         IF ~b.DynAppendTT (newdtt, dott[i]^, {}) THEN RETURN SaveProcCleanUp(); END;
  3094.         EXIT;
  3095.       END; (* LOOP *)
  3096.       INC (i);
  3097.     END; (* WHILE *);
  3098.   END;
  3099.  
  3100.   IF ~b.DynAppendTT (newdtt, "", {b.createEmpty}) THEN RETURN SaveProcCleanUp(); END;
  3101.   do.toolTypes := b.TTAPtr (newdtt);  
  3102.   y.SETREG (0, ic.PutDiskObject (prefsName, do));
  3103.   RETURN SaveProcCleanUp();
  3104. END SaveProc;  
  3105.  
  3106. PROCEDURE HideProc (): BOOLEAN;
  3107. BEGIN
  3108.   RETURN false; (* signal: CloseWindow *)
  3109. END HideProc;  
  3110.  
  3111. PROCEDURE AboutProc (): BOOLEAN;
  3112. VAR
  3113.   act: BOOLEAN;
  3114. BEGIN
  3115.   act := active;
  3116.   ActivateBroker (false);
  3117.   IF b.SimpleRequestArgs (ag.AngieWnd, LONGSET {b.lockWindow, b.ignoreTitle},
  3118.                           "", "%s\n\n  %s - Commodity\n\n  Written & © 1993 by\n"
  3119.                           "  Franz Schwarz\n  Mühlenstraße 2\n"
  3120.                           "  D-78591 Durchhausen, Germany\n"
  3121.                           "  Uucp: Franz_Schwarz@mil.ka.sub.org\n"
  3122.                           "  Fido: 2:2476/506.18\n\n"
  3123.                           "  GUI created with assistance of GadToolsBox 37.300\n\n"
  3124.                           "Since Angie is Giftware you are encouraged to send the\n"
  3125.                           "author a present, money, a postcard, etc. if you use it.",
  3126.                           "Terrific", y.ADR (nb.title)) = 0 THEN END;
  3127.   ActivateBroker (act);
  3128.   RETURN true;
  3129. END AboutProc;  
  3130.  
  3131. PROCEDURE QuitProc (): BOOLEAN;
  3132. BEGIN
  3133.   HALT (0);
  3134.   RETURN true;
  3135. END QuitProc;  
  3136.  
  3137. CONST
  3138.   gadProcs = GadProcArrT (DefinitionProc, HotKeysProc, PriProc, DelayProc,
  3139.                           StableProc, PopProc, KeyActProc, IncWinTaskPriProc,
  3140.                           HuntAlwaysProc, HuntWinToFrontProc, TypeProc,
  3141.                           ShuffleBDropProc, ScrStepsProc, WinStepsProc,
  3142.                           HuntDefPubProc, AddProc, DelProc, UpProc, DownProc,
  3143.                           ShufflePatProc, AttrsProc);
  3144.  
  3145. CONST
  3146.   gadKeyProcs = GadProcArrT (DefinitionKeyProc, HotKeysKeyProc, 
  3147.                              PriKeyProc, DelayKeyProc, StableKeyProc,
  3148.                              PopKeyProc, KeyActKeyProc,
  3149.                              IncWinTaskPriKeyProc, HuntAlwaysKeyProc,
  3150.                              HuntWinToFrontKeyProc, TypeKeyProc,
  3151.                              ShuffleBDropKeyProc, ScrStepsKeyProc,
  3152.                              WinStepsKeyProc, HuntDefPubKeyProc,
  3153.                              AddProc, DelProc, UpProc, DownProc, 
  3154.                              ShufflePatKeyProc, AttrsKeyProc);
  3155.  
  3156.  
  3157. TYPE
  3158.   MenuPair = STRUCT
  3159.     id  : LONGINT;
  3160.     proc: PROCEDURE (): BOOLEAN;
  3161.   END;  
  3162.  
  3163.   menuPairArrT = ARRAY 7 OF MenuPair;
  3164.  
  3165. CONST  
  3166.   menuProcs = menuPairArrT (ag.MNsave, SaveProc, ag.MNabout, AboutProc, 
  3167.                             ag.MNhide, HideProc, ag.MNquit, QuitProc, 
  3168.                             MNfrontattr, MAttrsProc, MNnokeyscractattr, MAttrsProc,
  3169.                             MNrepeatattr, MAttrsProc);
  3170.   
  3171.  
  3172. PROCEDURE GUIMsgHandler();
  3173. VAR
  3174.   m  : I.IntuiMessagePtr;
  3175.   i,j: LONGINT;
  3176.   mi : I.MenuItemPtr;
  3177. BEGIN
  3178.   LOOP
  3179.     IF ag.AngieWnd = NIL THEN RETURN; END;
  3180.     m := gt.GetIMsg (ag.AngieWnd.userPort);
  3181.     IF m = NIL THEN RETURN; END;
  3182.     AngieMsg := m^;
  3183.     gt.ReplyIMsg (m);
  3184.     IF I.refreshWindow IN AngieMsg.class THEN
  3185.       gt.BeginRefresh (ag.AngieWnd);
  3186.       gt.EndRefresh (ag.AngieWnd, e.true);
  3187.     ELSIF I.closeWindow IN AngieMsg.class THEN  
  3188.       CloseGUI();
  3189.       RETURN;
  3190.     ELSIF I.vanillaKey IN AngieMsg.class THEN
  3191.       LOOP  
  3192.         FOR i := 0 TO LEN (ag.AngieGadgets)-1 DO
  3193.           IF u.ToUpper (CHR (AngieMsg.code)) = ag.AngieHotKeys [i] THEN
  3194.             IF ~gadKeyProcs [i]() THEN CloseGUI(); RETURN; END;
  3195.             EXIT;
  3196.           END;  
  3197.         END; (* FOR *)  
  3198.         IF AngieMsg.code = 27 THEN CloseGUI(); RETURN; END; (* ESC key *)
  3199.         IF u.ToUpper (CHR (AngieMsg.code)) = 'Z' THEN 
  3200.           I.ZipWindow (ag.AngieWnd); 
  3201.           EXIT; 
  3202.         END;
  3203.         EXIT;
  3204.       END; (* LOOP *)  
  3205.     ELSIF I.rawKey IN AngieMsg.class THEN  
  3206.       CASE AngieMsg.code OF
  3207.       ag.rawCrsrUp, ag.rawCrsrDown: (* ListView cursor browsing *)
  3208.         IF ~gadKeyProcs [ag.GDhotkeys]() THEN CloseGUI(); RETURN; END;
  3209.       ELSE END;  
  3210.     ELSIF LONGSET {I.gadgetUp, I.gadgetDown} * AngieMsg.class # LONGSET {} THEN
  3211.       AngieGad := AngieMsg.iAddress;
  3212.       IF AngieGad # NIL THEN
  3213.         i := AngieGad.gadgetID;
  3214.         IF (i >= 0) & (i < LEN (gadProcs)) THEN
  3215.           IF ~gadProcs [i]() THEN CloseGUI(); RETURN; END;
  3216.         END;  
  3217.       END;  
  3218.     ELSIF I.menuPick IN AngieMsg.class THEN  
  3219.       LOOP
  3220.         IF AngieMsg.code = I.menuNull THEN EXIT; END;
  3221.         mi := I.ItemAddress (ag.AngieMenus^, AngieMsg.code);
  3222.         i := gt.MenuItemUserData (mi);
  3223.         LOOP 
  3224.           FOR j := 0 TO LEN (menuProcs)-1 DO
  3225.             IF i = menuProcs[j].id THEN
  3226.               IF ~menuProcs [j].proc() THEN CloseGUI(); RETURN; END;
  3227.               EXIT;
  3228.             END;  
  3229.           END; (* FOR *)
  3230.           IF (i >= 0) & (i < hotKeys) THEN 
  3231.             AngieMsg.code := SHORT (i);
  3232.             IF ~MTypeProc() THEN CloseGUI(); RETURN; END;
  3233.           END;              
  3234.           EXIT;
  3235.         END; (* LOOP *)          
  3236.         AngieMsg.code := mi.nextSelect;
  3237.       END; (* LOOP *)
  3238.     END;      
  3239.   END;  
  3240. END GUIMsgHandler;  
  3241.     
  3242. PROCEDURE DoScrActivateMagic (ev: ie.InputEventPtr);
  3243. VAR
  3244.   lk           : LONGINT;
  3245.   w, actw      : I.WindowPtr;
  3246.   s            : I.ScreenPtr;
  3247.   nev          : ie.InputEventPtr;
  3248.  
  3249. BEGIN          
  3250.   actw := NIL;
  3251.   IF ev = NIL THEN RETURN; END;
  3252.   lk := I.LockIBase (0);
  3253.   LOOP
  3254.     w := I.int.activeWindow;
  3255.     IF (w # NIL) & (I.menuState IN w.flags) THEN EXIT; END;
  3256.     s := I.int.activeScreen;
  3257.     IF s = NIL THEN EXIT; END;
  3258.     IF ~(g.vpHide IN s.viewPort.modes) THEN EXIT; END;
  3259.     actw := GetBestWin ();
  3260.     y.SETREG (0, e.SetTaskPri (chieftask, 100));
  3261.     EXIT;
  3262.   END;  
  3263.   I.UnlockIBase (lk);
  3264.   IF actw # NIL THEN I.ActivateWindow (actw); END;
  3265.   y.SETREG (0, e.SetTaskPri (chieftask, chiefpri));
  3266.   nev := ev.nextEvent; ev.nextEvent := NIL;
  3267.   co.AddIEvents (ev);
  3268.   ev.nextEvent := nev;
  3269. END DoScrActivateMagic;
  3270.  
  3271. PROCEDURE MsgHandler;
  3272. VAR
  3273.   flgs         : LONGSET;
  3274.   msg          : e.APTR;
  3275.   msgid        : LONGINT;
  3276.   msgtype      : LONGSET;
  3277.   ev           : ie.InputEventPtr;
  3278.   qualifier    : SET;
  3279.  
  3280. BEGIN
  3281.   LOOP
  3282.     flgs := e.Wait (LONGSET {d.ctrlC, nb.port.sigBit, dinfosig, guiwndsig});
  3283.     IF dinfosig IN flgs THEN
  3284.       IF huntwindowalways OR incwintaskpri OR (IncTask # NIL) THEN 
  3285.         DoIntuiAction (sendHuntSigd);
  3286.       END;
  3287.     END;    
  3288.     IF (guiwndsig IN flgs) & (guiwndsig # d.ctrlC) THEN
  3289.       GUIMsgHandler();
  3290.     END;
  3291.     IF nb.port.sigBit IN flgs THEN
  3292.       LOOP
  3293.         msg := e.GetMsg (nb.port);
  3294.         IF msg = NIL THEN EXIT; END;
  3295.         ev := NIL; qualifier := {};
  3296.         msgid := co.CxMsgID (msg);
  3297.         msgtype := co.CxMsgType (msg);
  3298.         IF msgtype = LONGSET {co.cxmIEvent} THEN
  3299.           ev := co.CxMsgData (msg);
  3300.           IF ev # NIL THEN qualifier := ev.qualifier; END;
  3301.         END;
  3302.         IF (msgtype = LONGSET {co.cxmIEvent}) & (msgid = scrActivateMagic) THEN
  3303.           DoScrActivateMagic (ev);
  3304.           msgtype := LONGSET {};
  3305.         END;  
  3306.         e.ReplyMsg (msg);
  3307.         IF msgtype = LONGSET {co.cxmIEvent} THEN
  3308.           IF PlainId (msgid) = popGUI THEN
  3309.             IF OpenGUI() THEN END;
  3310.           ELSIF ~(~IsRepeatId (msgid) & (ie.repeat IN qualifier)) THEN
  3311.             DoIntuiAction (msgid);
  3312.           END;  
  3313.         ELSIF msgtype = LONGSET {co.cxmCommand} THEN
  3314.           CASE msgid OF
  3315.           co.cmdKill:
  3316.             HALT (0); |
  3317.           co.cmdEnable:
  3318.             ActivateBroker (true); |
  3319.           co.cmdDisable:
  3320.             ActivateBroker (false); 
  3321.             y.SETREG (0, SecureSetTaskPri (IncTask, OldPri)); IncTask := NIL; |
  3322.           co.cmdAppear, co.cmdUnique:
  3323.             IF OpenGUI() THEN END; |
  3324.           co.cmdDisappear:  
  3325.             CloseGUI();
  3326.           ELSE END;
  3327.         END;
  3328.       END; (* LOOP *)
  3329.     END;
  3330.     IF d.ctrlC IN flgs THEN HALT (5); END;
  3331.   END;
  3332. END MsgHandler;
  3333.  
  3334. BEGIN
  3335.   Init();
  3336.  
  3337.   MsgHandler();
  3338.  
  3339. CLOSE
  3340.   CleanUp();
  3341.  
  3342. END Angie.
  3343.  
  3344.