(*----------------------------------------------------------------------------
 :Program.      SwitchNTSC.mod
 :Contents.     Turns on NTSC for every screen opened via OpenScreen(TagList).
 :Author.       Mario Kemper
 :Address.      GeistStr. 53, D-4780 Lippstadt
 :Phone.        02941/58635
 :E-Mail.       magick@uni-paderborn.de
 :Copyright.    Public Domain
 :Language.     Oberon
 :Translator.   Amiga Oberon Compiler V2.14d
 :Imports.      CXLib
 :History.      V2.4  -unknown- [Mario] First release Version.                        
 :History.      V2.5  23-Nov-91 [Mario] Removed Autoscroll bug.                       
 :History.      V2.6  01-Jan-92 [Mario] Now reads arguments from CLI. 
 :History.      V2.7  04-Jan-92 [Mario] Now you can use real PAL-Screens.
 :History.      V2.8  06-Jan-92 [Mario] Cli-Args and PAL-Bug removed.
 :History.      V2.9  15-Jan-92 [Mario] Disables Filter while Requester is active.
 :History.      V2.10 21-Feb-92 [Mario] Now patches OpenScreenTags,too.
 :History.      V2.11 29-Feb-92 [Mario] NewLook Option implemented.
 :History.      V3.0  21-May-92 [Mario] Now has PopUp-Window.
 :Bugs.         Might crash if other programs patched Openscreen.
 :Bugs.         Loses some Bytes every OpenScreenTaglist call.
 :Usage.        Put it in the WBStartup or run it from CLI.
 :Remarks.      Don't compile with SMALLDATA.
----------------------------------------------------------------------------*)
MODULE SwitchNTSC;

IMPORT e  : Exec,
       cx : CXLib,
       com: Commodities,
       int: Intuition,
       gr : Graphics,
       u  : Utility,
       s  : SYSTEM,(* $IF Output *)io,(* $END *)
       gad: GadTools;
       

CONST DefCXPri = 0;
      DefCXPopKey= "lalt esc";
      SwitchID = 42;
      VERSIONSTRING = "$VER: SwitchNTSC 3.0 14 (21-May-92) © Mario Kemper";
      SMALLVERSION  = "SwitchNTSC 3.0 15 © Mario Kemper";
      patchText = 0;       
      patch     = 1;
      newText   = 2;
      newLook   = 3;
      palText   = 4;
      pal       = 5;
      hide      = 6;
      quit      = 7;
      center    = 8;
      centerText= 9; 
      
TYPE TagArray = POINTER TO ARRAY 7 OF u.TagItem;
     OpenScreenProc = PROCEDURE (ens{8}:int.ExtNewScreenPtr):int.ScreenPtr;
     OpenScreenTagsProc = PROCEDURE (ns{8}:int.NewScreenPtr;
                                    tags{9}:TagArray):int.ScreenPtr;
     Action = RECORD 
                action: INTEGER;                                    
                doIt  : BOOLEAN;
              END;       
                         
VAR   OldOpenScreen     : OpenScreenProc;
      OldOpenScreenTags : OpenScreenTagsProc;
      MyPort            : e.MsgPortPtr;      
      CxMsg             : com.CxMsgPtr;
      msg               : e.MessagePtr;
      MyNewBroker       : com.NewBroker;
      Broker, 
      Filter            : com.CxObjPtr;
      Key               : cx.StrPtr;
      ToolTypes         : cx.ToolTypeArray;
      MsgType           : LONGSET;
      MsgID,long,
      error             : LONGINT;
      PATCHED,LETGO     : BOOLEAN;
      Version,SVersion  : e.STRPTR;
      PAL,NEWLOOK,
      WINDOW,POPUP,
      BYPASS,CENTER     : BOOLEAN;
      cxSig,winSig      : INTEGER;
      Signal            : LONGSET;
      winPtr            : int.WindowPtr;
      gads              : ARRAY 10 OF int.GadgetPtr;    
      context, 
      firstGad          : int.GadgetPtr; 
      vi                : gad.VisualInfo;
      fontAttr          : gr.TextAttr;
      act               : Action;
      XPos,YPos         : LONGINT;
      
PROCEDURE NewOpenScreenTags* (ns{8}:int.NewScreenPtr;tags{9}:TagArray):int.ScreenPtr;
(* $StackChk- *)
(* $SaveRegs+ *) 
(* $ClearVars- *)

VAR height,
    width,
    left,nleft,
    pleft       : INTEGER;
    vm          : SET;
    id          : LONGINT;
    long        : LONGINT;
    dim         : gr.DimensionInfoPtr;
    array       : ARRAY 2 OF u.Tag;
    myTags      : TagArray;
    pens,scroll,
    overscan,
    clip        : BOOLEAN;
    penArray    : ARRAY 1 OF INTEGER;
    base        : int.IntuitionBasePtr;
    (* $IF Output THEN *)
    title       : POINTER TO e.STRING;
    (* $END *)
    
BEGIN  
  base:=s.REG(14);
  IF (BYPASS AND LETGO) THEN
     (* $IF Output THEN *)
        io.WriteString("Lasse einfach durch!\n");
     (* $END *)   
     s.SETREG(14,base);
     RETURN(OldOpenScreenTags(ns,tags));
  END;   
  (* $IF Output THEN *)
     io.WriteString("OpenScreenTags()\n");
  (* $END *)
  penArray[0]:=-1;
  height:=0;
  width:=0;
  left:=0;
  id:=0;
  NEW(dim);
  NEW(myTags);
  myTags[0].tag:=u.ignore;
  myTags[1].tag:=u.ignore;
  myTags[2].tag:=u.ignore;
  myTags[3].tag:=u.ignore;
  myTags[4].tag:=u.ignore;
  myTags[5].tag:=u.ignore;
  myTags[6].tag:=u.done;
  IF ns # NIL THEN
  (* $IF Output THEN *)
     io.WriteString("NewScreen # NIL\n");
     IF ns.defaultTitle # NIL THEN
        io.WriteString("Name: ");
        io.WriteString(ns.defaultTitle^);
        io.WriteLn;
     END;   
  (* $END *)   
     height := ns.height;
     width  := ns.width;
     left   := ns.leftEdge;
     vm:=ns.viewModes;
     id:=s.VAL(INTEGER,vm*{2,7,10,11});
     IF gr.hires IN vm THEN 
        INC(id,gr.hiresKey);
     END;
  END;  
  
  IF tags # NIL THEN
     (* $IF Output THEN *)
      io.WriteString("Tags # NIL \n");
      title:= s.VAL(e.ADDRESS,u.GetTagData(int.saTitle,NIL,tags^)); 
      IF title # NIL THEN 
         io.WriteString("Name: ");
         io.WriteString(title^);
         io.WriteLn;
      END;   
     (* $END *)   

     id:=u.GetTagData(int.saDisplayID,id,tags^);
     height:=SHORT(u.GetTagData(int.saHeight,height,tags^));
     width:= SHORT(u.GetTagData(int.saWidth,width,tags^));
     left := SHORT(u.GetTagData(int.saLeft,left,tags^));
     myTags[6].tag:=u.more;
     myTags[6].data:=tags;
     pens:=u.GetTagData(int.saPens,-2,tags^)#-2;
     scroll:=u.GetTagData(int.saAutoScroll,0,tags^)#0;
     overscan:=u.GetTagData(int.saOverscan,0,tags^)#0;
     clip:=u.GetTagData(int.saDClip,0,tags^)#0;
  ELSE  
     pens:=FALSE;
     scroll:=FALSE;
     overscan:=FALSE;
     clip:=FALSE;
  END;
  
     (* $IF Output THEN *)
        io.WriteString("left: ");
        io.WriteInt(left,4);
        io.WriteLn;
        io.WriteString("width: ");
        io.WriteInt(width,4);
        io.WriteLn;   
     (* $END *)   
     
     pleft:=left;
     nleft:=left;
     
  (* $IF Output THEN *)
     io.WriteString("MonitorID :");
     io.WriteHex(id,10);
     io.WriteLn;
     IF scroll THEN io.WriteString("Autoscroll gesetzt!\n")
     ELSE io.WriteString("Autoscroll nicht gesetzt!\n")
     END;
     IF clip THEN io.WriteString("DClip gesetzt!\n")
     ELSE io.WriteString("DClip nicht gesetzt!\n")
     END;
     IF pens THEN io.WriteString("Pens gesetzt!\n")
     ELSE io.WriteString("Pens nicht gesetzt!\n")
     END;
     IF overscan THEN io.WriteString("Overscan gesetzt!\n")
     ELSE io.WriteString("Overscan nicht gesetzt!\n")
     END;
  (* $END *)

  IF CENTER AND (NOT overscan) THEN
     IF gr.GetDisplayInfoData(NIL,dim^,s.SIZE(dim^),gr.dtagDims,id) # 0 THEN
        (* $IF Output THEN *)
             io.WriteString("MaxPAL: ");
             io.WriteInt(dim.txtOScan.maxX,4);
             io.WriteLn;
        (* $END *)   
        IF width > 0 THEN
          IF (width < dim.txtOScan.maxX) AND (left = 0) THEN
             pleft:=(dim.txtOScan.maxX - width) DIV 2;
             myTags[4].tag:=int.saLeft;
             (* $IF Output THEN *)
                io.WriteString("PLeft: ");
                io.WriteInt(pleft,4);
                io.WriteLn;
             (* $END *)
          END;   
        END;  
     END;   
  END;   
  
     
  IF (NEWLOOK AND (NOT pens)) THEN
     (* $IF Output THEN *)
        io.WriteString("Setze NewLook\n");
     (* $END *)   
     myTags[3].tag:=int.saPens;
     myTags[3].data:=s.ADR(penArray);
  END;   
  
  IF id < gr.ntscMonitorID THEN
     (* $IF Output THEN *)
        io.WriteString("Let's patch ID \n");
     (* $END *)   
     INC(id,gr.ntscMonitorID);
     IF CENTER AND (NOT overscan) THEN
        IF gr.GetDisplayInfoData(NIL,dim^,s.SIZE(dim^),gr.dtagDims,id) # 0 THEN
             (* $IF Output THEN *)
                io.WriteString("MaxNTSC: ");
                io.WriteInt(dim.txtOScan.maxX,4);
                io.WriteLn;
             (* $END *)
     
           IF width > 0 THEN       
             IF (width < dim.txtOScan.maxX) AND (left = 0) THEN
                myTags[4].tag:=int.saLeft;
                nleft:=(dim.txtOScan.maxX - width) DIV 2;
             (* $IF Output THEN *)
                io.WriteString("NLeft: ");
                io.WriteInt(nleft,4);
                io.WriteLn;
             (* $END *)
  
             END;   
           END;  
        END;   
     END;   
     myTags[0].tag:=int.saDisplayID;
     myTags[0].data:=id;
     IF gr.GetDisplayInfoData(NIL,dim^,s.SIZE(dim^),gr.dtagDims,id) # 0 THEN
       IF height > dim.txtOScan.maxY+1 THEN
         IF ((NOT PAL) AND (NOT (scroll AND clip))) THEN
            (* $IF Output THEN *)
              io.WriteString("Setze AutoScroll\n");
            (* $END *)   
            myTags[1].tag:=int.saAutoScroll;
            myTags[1].data:= LONG(-1);
            myTags[2].tag := int.saDClip;
            myTags[2].data:= s.ADR(dim.txtOScan);
            myTags[4].data:= LONG(nleft);
         ELSE   
            myTags[4].data:= LONG(pleft);
            myTags[0].tag := u.ignore;
         END;   
       ELSE  
         myTags[4].data:= LONG(nleft);
       END;  
     END;  
  ELSE
     myTags[4].data:= LONG(pleft);
  END;   
  
  (* $IF Output THEN *)
  io.WriteString("Fertig! \n");
  io.WriteString("------------------! \n");
  (* $END *)  
  s.SETREG(14,base);
  RETURN(OldOpenScreenTags(ns,myTags));
  
END NewOpenScreenTags;
(* $StackChk= *)
(* $ClearVars= *)


PROCEDURE NewOpenScreen* (ens{8}:int.ExtNewScreenPtr):int.ScreenPtr;
(* $SaveRegs+ *)
(* $StackChk+ *)
(* $ClearVars- *)

VAR base:int.IntuitionBasePtr;

BEGIN
  base:=s.REG(14);
  IF (BYPASS AND LETGO) THEN
     (* $IF Output THEN *)
        io.WriteString("Lasse einfach durch!\n");
     (* $END *)   
     s.SETREG(14,base);
     RETURN(OldOpenScreen(ens));
  END;   
  (* $IF Output THEN *)
     io.WriteString("OpenScreen!\n");
  (* $END *)   
  IF int.nsExtended IN ens.ns.type THEN
     (* $IF Output THEN *)
        io.WriteString("ExtendedNewScreen!\n");
     (* $END *)   
    s.SETREG(14,base);
    RETURN(NewOpenScreenTags(ens,ens.extension));
  ELSE
     (* $IF Output THEN *)
        io.WriteString("Normale NewScreen!\n");
     (* $END *)   
    s.SETREG(14,base);
    RETURN(NewOpenScreenTags(ens,NIL));
  END;
END NewOpenScreen;
(* $StackChk= *)
(* $ClearVars= *)


PROCEDURE Assert(cc:BOOLEAN;Text:ARRAY OF CHAR);

VAR es : int.EasyStruct;
    l  : LONGINT;
BEGIN
  IF NOT cc THEN
    es.structSize:=s.SIZE(int.EasyStruct);
    es.flags:=LONGSET{0};
    es.title:=SVersion;
    es.textFormat:=s.ADR(Text);
    es.gadgetFormat:=s.ADR("OK");
    l:=int.EasyRequest(NIL,s.ADR(es),NIL);
    HALT(20);
  END;  
END Assert;  


PROCEDURE Patch (new,by : BOOLEAN);

BEGIN
  IF (new AND (NOT PATCHED)) THEN
     IF (by AND BYPASS) THEN
        LETGO:=FALSE;
     ELSE   
       e.Forbid;
       OldOpenScreen:=s.VAL(OpenScreenProc,e.SetFunction(int.int,-0C6H,
                            s.VAL(e.PROC,NewOpenScreen)));
       OldOpenScreenTags:=s.VAL(OpenScreenTagsProc,e.SetFunction(int.int,-612,
                                s.VAL(e.PROC,NewOpenScreenTags)));
       e.Permit;
     END;  
       PATCHED:=TRUE;
  ELSE
    IF ((NOT new) AND PATCHED) THEN
       IF (by AND BYPASS) THEN
          LETGO:=TRUE;
       ELSE   
         e.Forbid;
         OldOpenScreen:=s.VAL(OpenScreenProc,e.SetFunction(int.int,-0C6H,
                              s.VAL(e.PROC,OldOpenScreen)));
         OldOpenScreenTags:=s.VAL(OpenScreenTagsProc,e.SetFunction(int.int,-612,
                                  s.VAL(e.PROC,OldOpenScreenTags)));
         e.Permit;
       END;  
       PATCHED:=FALSE;
    END;     
  END;   
END Patch;


PROCEDURE InitGad (VAR ng : gad.NewGadget; l,t,w,h,nr:INTEGER;
                   name:e.STRPTR;dir : INTEGER);
BEGIN
  ng.leftEdge := l;
  ng.topEdge := t;
  ng.width := w;
  ng.height := h;
  ng.textAttr:=s.ADR(fontAttr);
  ng.visualInfo:=vi;
  ng.gadgetID:=nr;
  ng.gadgetText:=name;
  ng.flags:=LONGSET{dir};
END InitGad;  


PROCEDURE Window(ON:BOOLEAN);

VAR checkPal,
    checkNewLook,
    checkPatched,
    checkCenter  : LONGINT;
    dummy        : INTEGER;
    newGad       : gad.NewGadget;

BEGIN    
  IF ON AND (NOT WINDOW) THEN
    checkPal:=int.BoolToLong(PAL);
    checkNewLook:=int.BoolToLong(NEWLOOK);
    checkPatched:=int.BoolToLong(PATCHED);
    checkCenter:=int.BoolToLong(CENTER);
    fontAttr:=gr.TextAttr(s.ADR("topaz.font"),8,SHORTSET{},SHORTSET{});
    winPtr:=int.OpenWindowTagsA(NIL,int.waIDCMP,
                               s.VAL(LONGINT,LONGSET{int.closeWindow,int.vanillaKey} +
                                             gad.checkBoxIDCMP +
                                             gad.buttonIDCMP),
                              int.waFlags,s.VAL(LONGINT,LONGSET{int.windowClose,
                                                int.windowDrag,int.windowDepth}),
                              int.waWidth,200,int.waHeight,140,
                              int.waPubScreen,0,
                              int.waTitle,SVersion,
                              int.waTop,YPos,int.waLeft,XPos,
                              int.waAutoAdjust,1,
                              u.done);
    IF winPtr # NIL THEN                              
      vi := gad.GetVisualInfo(winPtr.wScreen);
      context:=gad.CreateContext(firstGad);
      InitGad(newGad,15,30,0,15,patchText,s.ADR("_Patch"),gad.placeTextRight);
      gads[patchText]:=gad.CreateGadget(gad.textKind,context,newGad,
                                        gad.underscore,ORD("_"),u.done);
      InitGad(newGad,15,50,0,15,newText,s.ADR("_NewLook"),gad.placeTextRight);
      gads[newText]:=gad.CreateGadget(gad.textKind,gads[patchText],newGad,
                                        gad.underscore,ORD("_"),u.done);
      InitGad(newGad, 15,70, 0,15,palText,s.ADR("_UsePal"),gad.placeTextRight);
      gads[palText]:=gad.CreateGadget(gad.textKind,gads[newText],newGad,
                                        gad.underscore,ORD("_"),u.done);
      InitGad(newGad, 15,90, 0,15,centerText,s.ADR("_Center"),gad.placeTextRight);
      gads[centerText]:=gad.CreateGadget(gad.textKind,gads[palText],newGad,
                                         gad.underscore,ORD("_"),u.done);
      InitGad(newGad,140,30,10,10,patch,NIL,0);
      gads[patch]:=gad.CreateGadget(gad.checkBoxKind,gads[centerText],newGad,
                                    gad.cbChecked,checkPatched);
      InitGad(newGad,140,50,10,10,newLook,NIL,0);
      gads[newLook]:=gad.CreateGadget(gad.checkBoxKind,gads[patch],newGad,
                                        gad.cbChecked,checkNewLook);
      InitGad(newGad,140,70,10,10,pal,NIL,0);
      gads[pal]:=gad.CreateGadget(gad.checkBoxKind,gads[newLook],newGad,
                                        gad.cbChecked,checkPal);
      InitGad(newGad,140,90,10,10,center,NIL,0);
      gads[center]:=gad.CreateGadget(gad.checkBoxKind,gads[pal],newGad,
                                        gad.cbChecked,checkCenter);
      InitGad(newGad, 20,110,40,15,hide,s.ADR("_Hide"),gad.placeTextIn);
      gads[hide]:=gad.CreateGadget(gad.buttonKind,gads[center],newGad,
                                   gad.underscore,ORD("_"),u.done);
      InitGad(newGad,140,110,40,15,quit,s.ADR("_Quit"),gad.placeTextIn);
      gads[quit]:=gad.CreateGadget(gad.buttonKind,gads[hide],newGad,
                                   gad.underscore,ORD("_"),u.done);
      dummy:=int.AddGList(winPtr,context,0,-1,NIL);                             
      int.RefreshGadgets(firstGad,winPtr,NIL);
      gad.RefreshWindow(winPtr,NIL);
      WINDOW := TRUE;
      winSig := winPtr.userPort.sigBit;
    ELSE   
       WINDOW := FALSE;
    END;   
  END;  
  IF ON AND WINDOW THEN 
     int.ScreenToFront(winPtr.wScreen);
     int.WindowToFront(winPtr);
     IF int.ActivateWindow(winPtr)THEN  END;
  END;   
  IF (NOT ON) AND WINDOW THEN 
     XPos:=winPtr.leftEdge;
     YPos:=winPtr.topEdge;
     IF winPtr   # NIL THEN int.CloseWindow(winPtr)   END;
     IF firstGad # NIL THEN gad.FreeGadgets(firstGad) END;
     IF vi       # NIL THEN gad.FreeVisualInfo(vi)    END;
     WINDOW := FALSE;
  END;   
END Window;



(* $IF Debug THEN *)
PROCEDURE TestScreen;
VAR scr:int.ScreenPtr;
    tags:u.Tags3;
    
BEGIN
  tags:=u.Tags3(int.saDisplayID,gr.hiresLaceKey+gr.ntscMonitorID,int.saHeight,200,int.saWidth,640);
  s.SETREG(14,int.int);
  scr := NewOpenScreenTags(NIL,s.ADR(tags));
  int.OldCloseScreen(scr);
END TestScreen;  
(* $END *)


PROCEDURE CheckWindow(VAR ret : Action);
VAR msg   : int.IntuiMessagePtr;
    closed: BOOLEAN;
    gptr  : int.GadgetPtr;
    
    
  PROCEDURE Toggle (id:INTEGER);
  VAR select : LONGINT;
      state  : BOOLEAN;
      
  BEGIN
    ret.action:=id;
    state:=(int.selected IN gads[id].flags);
    select:=int.BoolToLong(NOT(state));
    gad.SetGadgetAttrs(gads[id]^,winPtr,NIL,gad.cbChecked,select);
    ret.doIt:=NOT(state);
  END Toggle;  
  
  
BEGIN
  ret:=Action(-1,FALSE);
  closed := FALSE;
  msg:=gad.GetIMsg(winPtr.userPort);
  WHILE (msg # NIL) AND (NOT closed) DO
    IF int.gadgetUp IN msg.class THEN
       gptr:=s.VAL(int.GadgetPtr,msg.iAddress);
       CASE gptr.gadgetID OF 
       |hide : closed := TRUE;
       |quit : ret.action := quit;        
               closed:=TRUE;
       |patch,newLook,pal,center :
               ret.action:=gptr.gadgetID; 
               ret.doIt := (int.selected IN gptr.flags);
       ELSE   
       END;
    END;   
    IF int.closeWindow IN msg.class THEN
        closed:=TRUE;
    END;    
    IF int.vanillaKey IN msg.class THEN
       CASE CAP(CHR(msg.code)) OF
       |"H" : closed     := TRUE;
       |"Q" : ret.action := quit;       
              closed     := TRUE;
       |"U" : Toggle(pal);
       |"P" : Toggle(patch);
       |"N" : Toggle(newLook);
       |"C" : Toggle(center);
(* $IF Debug THEN *)
       |"D" : TestScreen;
(* $END *)
       ELSE
       END;
    END;   
    gad.ReplyIMsg(msg);
    msg:=gad.GetIMsg(winPtr.userPort);
  END;  
  WHILE msg # NIL DO 
    gad.ReplyIMsg(msg);
    msg:=gad.GetIMsg(winPtr.userPort);
  END;  
  IF closed THEN Window(FALSE) END;
END CheckWindow;  
    
PROCEDURE CheckArg(name:cx.String;default : cx.StrPtr) : BOOLEAN;    
VAR res : e.STRPTR;
BEGIN
  res:=cx.ArgString(ToolTypes,name,default);
  RETURN(res^#default^);
END CheckArg;  

                        
BEGIN      
  (* $IF SmallData THEN *)
  Assert(FALSE,"SwitchNTSC won't run with SMALLDATA!");
  (* $END *)
  WINDOW:=FALSE;
  LETGO:=FALSE;
  Version := s.ADR(VERSIONSTRING);
  SVersion := s.ADR(SMALLVERSION);
  ToolTypes:=cx.ArgArrayInit();
  MyNewBroker:=com.NewBroker(com.nbVersion,s.ADR("SwitchNTSC"),
                             s.ADR(SMALLVERSION),
                             s.ADR("Forces Screens to open on NTSC"),
                             com.notify+com.unique,{com.showHide},0,NIL,0);
  IF ToolTypes # NIL THEN
     MyNewBroker.pri:=SHORT(SHORT(cx.ArgInt(ToolTypes,"CX_PRIORITY",
                                                       DefCXPri)));
  ELSE    
     MyNewBroker.pri:=DefCXPri;
  END;   
  MyPort:=e.CreateMsgPort();
  Assert(MyPort#NIL,"Fatal Error!");
  MyNewBroker.port:=MyPort;                           
  cxSig := MyPort.sigBit;
  Broker := com.CxBroker(MyNewBroker,error);
  IF Broker = NIL THEN HALT(20) END;
  IF ToolTypes # NIL THEN
     Key    := cx.ArgString(ToolTypes,"CX_POPKEY",s.ADR(DefCXPopKey));
     PAL    := CheckArg("USEPAL",s.ADR("OFF"));
     NEWLOOK:= CheckArg("NEWLOOK",s.ADR("OFF"));
     POPUP  := CheckArg("CX_POPUP",s.ADR("NO"));
     BYPASS := CheckArg("BYPASS",s.ADR("OFF"));
     CENTER := CheckArg("CENTER",s.ADR("OFF"));
     XPos   := cx.ArgInt(ToolTypes,"XPOS",0);
     YPos   := cx.ArgInt(ToolTypes,"YPOS",10);
  ELSE   
     Key:=s.ADR(DefCXPopKey);
     PAL:=FALSE;
     NEWLOOK:=FALSE;
     POPUP:=FALSE;
     BYPASS:=FALSE;
     CENTER:=FALSE;
     XPos:=0;
     YPos:=10;

  END;   
  
  Filter:=cx.HotKey(Key,MyPort,SwitchID);
  Assert(Filter#NIL,"Fatal Error!");
  com.AttachCxObj(Broker,Filter);
  IF com.CxObjError(Filter)=LONGSET{} THEN
     long:=com.ActivateCxObj(Broker,-1);
     Patch(TRUE,FALSE);
     Window(POPUP);
     LOOP
       IF WINDOW THEN Signal := e.Wait(LONGSET{cxSig,winSig})
       ELSE Signal:=e.Wait(LONGSET{cxSig})
       END;
       IF cxSig IN Signal THEN
         CxMsg := s.VAL(com.CxMsgPtr,e.GetMsg(MyPort));
         WHILE CxMsg # NIL DO
           MsgType:= com.CxMsgType(CxMsg);
           MsgID  := com.CxMsgID(CxMsg); 
           e.ReplyMsg(s.VAL(e.MessagePtr,CxMsg));
           IF com.cxmIEvent IN MsgType THEN
              Window(TRUE);
           END;
           IF com.cxmCommand IN MsgType THEN
              CASE MsgID OF
                |com.cmdDisable   : long:=com.ActivateCxObj(Broker,0);Patch(FALSE,FALSE);
                                    IF WINDOW THEN Window(FALSE) END;
                |com.cmdEnable    : long:=com.ActivateCxObj(Broker,-1);Patch(TRUE,FALSE);
                |com.cmdKill      : Patch(FALSE,FALSE);IF WINDOW THEN Window(FALSE) END;EXIT;
                |com.cmdUnique    : IF NOT WINDOW THEN Window(TRUE) END;
                |com.cmdAppear    : Window(TRUE);
                |com.cmdDisappear : IF WINDOW THEN Window(FALSE) END;
              ELSE
              END (* CASE *);
           END; (* IF *)  
           CxMsg := s.VAL(com.CxMsgPtr,e.GetMsg(MyPort));
         END (* WHILE *)
       END;  
       IF (winSig IN Signal) AND WINDOW THEN
          CheckWindow(act);
          CASE act.action OF
          |quit   : Patch(FALSE,FALSE);EXIT;
          |patch  : Patch(act.doIt,TRUE);
          |newLook: NEWLOOK := act.doIt;
          |pal    : PAL := act.doIt;
          |center : CENTER := act.doIt;
          ELSE
          END;
       END;   
    END (* LOOP *)  
  END (* IF *)   
          
CLOSE
  IF WINDOW THEN Window(FALSE) END;
  IF MyPort # NIL THEN 
     msg:= e.GetMsg(MyPort);
     WHILE msg # NIL DO 
       e.ReplyMsg(msg);
       msg:=e.GetMsg(MyPort);
     END;  
     e.DeleteMsgPort(MyPort);
  END; (* IF *)   
  
  IF Broker # NIL THEN 
     long:=com.ActivateCxObj(Broker,0);
     com.DeleteCxObjAll(Broker) 
  END (* IF *);

END SwitchNTSC.
