--LTLispToolImpl.mesa
--Created by
--   JFung.PASA	  	20-Sep-83 10:10:02

--last edited by
--   JFung.PASA	   	24-Sep-84 10:27:22



DIRECTORY
     CmFile,
     Cursor USING [Set],
     Display,
     Event,
     EventTypes,
     Exec,
     File,
     FileTransfer,
     Format,
     FormSW,
     Heap,
     LispToolOps,
     OthelloDefs,
     OthelloOps,
     OthelloOpsImpl,
     Process,
     Profile,
     Put,
     Runtime,
     String,
     StringLookUp,
     Supervisor,
     System,
     TemporaryBooting,
     Time,
     Token,
     Tool,
     ToolDriver,
     ToolWindow,
     UserInput,
     Version,
     Volume,
     Window;



LTLispToolImpl: PROGRAM
     IMPORTS
          CmFile, Cursor, Display, Exec, FormSW, Heap, LispToolOps, OthelloDefs,
OthelloOps, OthelloOpsImpl,
          Process, Profile, Put, Runtime, String, Supervisor, TemporaryBooting,
          Time, Token, Tool, ToolDriver, ToolWindow, UserInput, Version, Volume,
          Window

     EXPORTS LispToolOps =


     BEGIN OPEN ILT: LispToolOps;

     Indicator: TYPE = {off, left, right};


     twiddleLeft: Graphic = [
          111000B, 052000B, 034000B, 177000B, 034000B, 052000B, 111000B, 000000B,
          000222B, 000124B, 000070B, 000376B, 000070B, 000124B, 000222B, 000000B];
     twiddleRight: Graphic = [
          000222B, 000124B, 000070B, 000376B, 000070B, 000124B, 000222B, 000000B,
          111000B, 052000B, 034000B, 177000B, 034000B, 052000B, 111000B, 000000B];


     debug: BOOLEAN ← FALSE;
     floppyWH: Window.Handle ← NIL;
     toolData: PUBLIC ILT.DataHandle ← NIL;
     windowHandle: PUBLIC Window.Handle ← NIL;
     FSFileName: LONG STRING ←
          "[Host:]<Directory>SubDirectory>FileName.sysout"L;
     IFSFileName: LONG STRING ←
          "[Host]<Directory>SubDirectory>FileName.sysout"L;
     FloppyFileName: LONG STRING ← "Lisp.sysout"L;


     active: BOOLEAN ← FALSE;

     <<     agent: Supervisor.SubsystemHandle = Supervisor.CreateSubsystem[
          CheckDeactivate];
	>>

     Graphic: TYPE = ARRAY [0..16) OF WORD;

     formDisplay: ToolWindow.DisplayProcType ← NIL;
     indicatorBox: Window.Box = [[10, 10], [16, 16]];
     volume: Volume.ID ← Volume.nullID;


     CheckDeactivate: Supervisor.AgentProcedure =
          BEGIN
          ENABLE UNWIND => NULL;
          IF event = EventTypes.deactivate AND ILT.windowHandle # NIL
               AND ILT.windowHandle = eventData AND ILT.toolData.busy THEN
               BEGIN
               Put.Line[
                    ILT.toolData.msgSW,
                    "The tool is busy:  aborting deactivation"L];
               ERROR Supervisor.EnumerationAborted;
               END;
          END;  --CheckDeactivate


     ClearCommandSubwindow: PUBLIC PROCEDURE =
          BEGIN
          item: FormSW.ItemHandle;

          FOR i: CARDINAL ← 0, i + 1 UNTIL
               (item ← FormSW.FindItem[ILT.toolData.commandSW, i]) = NIL DO
               item.flags.invisible ← TRUE ENDLOOP;
          FormSW.Display[ILT.toolData.commandSW];
          ILT.toolData.indicator ← left;
          --formDisplay ← Window.GetDisplayProc[ILT.toolData.commandSW];
          formDisplay ← Window.SetDisplayProc[ILT.toolData.commandSW, DisplayEmpty];
          END;  --ClearCommandSubwindow


     ClearFileSubwindow: PUBLIC PROCEDURE =
          BEGIN
          item: FormSW.ItemHandle;

          FOR i: CARDINAL ← 0, i + 1 UNTIL
               (item ← FormSW.FindItem[ILT.toolData.fileSW, i]) = NIL DO
               item.flags.invisible ← TRUE ENDLOOP;
          FormSW.Display[ILT.toolData.fileSW];
          --formDisplay ← Window.GetDisplayProc[ILT.toolData.fileSW];
          END;  --ClearFileSubwindow


     ClearMsgSubwindow: PUBLIC PROCEDURE =
          BEGIN
          item: FormSW.ItemHandle;

          FOR i: CARDINAL ← 0, i + 1 UNTIL
               (item ← FormSW.FindItem[ILT.toolData.msgSW, i]) = NIL DO
               item.flags.invisible ← TRUE ENDLOOP;
          FormSW.Display[ILT.toolData.msgSW];
          --formDisplay ← Window.GetDisplayProc[ILT.toolData.msgSW];
          END;  --ClearMsgSubwindow



     ClearSubWindows: PROCEDURE =
          BEGIN
          --ClearFileSubwindow;
          ClearMsgSubwindow;
          END;  --ClearSubWindows


     ClientTransition: ToolWindow.TransitionProcType =
          -- This procedure is called whenever the system determines that this
          -- Tool's state is undergoing a user invoked transition.
          -- In this Example we demonstrate a technique that minimizes the memory
          -- requirements for a Tool that is inactive.
          BEGIN
          SELECT TRUE FROM
               old = inactive =>
                    BEGIN
                    IF ILT.toolData = NIL THEN
                         ILT.toolData ← Heap.systemZone.NEW[ILT.Data ← []];
                    ProcessUserDotCM[];
                    active ← TRUE;
                    END;
               new = inactive =>
                    BEGIN
                    <<Supervisor.RemoveDependency[
                        client: agent, implementor: Event.toolWindow];
			>>
                    IF ILT.toolData # NIL THEN
                         BEGIN
                         FormSW.Destroy[ILT.toolData.paramSW];
                         FormSW.Destroy[ILT.toolData.commandSW];
                         Heap.systemZone.FREE[@ILT.toolData];
                         END;
                    ToolDriver.RemoveSWs[tool: "LispTool"L];
                    active ← FALSE;
                    END;
               ENDCASE
          END;  



     Confirm: PUBLIC PROCEDURE RETURNS [okay: BOOLEAN] =
          BEGIN
          Cursor.Set[mouseRed];
          [, okay] ← UserInput.WaitForConfirmation[];
          Cursor.Set[textPointer];
          UserInput.WaitNoButtons[];
          END;  


     DisplayCommandSubwindow: PUBLIC PROCEDURE =
          BEGIN OPEN FormSW;
          item: FormSW.ItemHandle;

          ILT.toolData.indicator ← off;
          [] ← Window.SetDisplayProc[ILT.toolData.commandSW, formDisplay];
          FormSW.Display[ILT.toolData.commandSW];
          FOR i: CARDINAL ← 0, i + 1 UNTIL
               (item ← FormSW.FindItem[ILT.toolData.commandSW, i]) = NIL DO
               item.flags.invisible ← FALSE ENDLOOP;

          FormSW.Display[ILT.toolData.commandSW];
          END; 


     DisplayEmpty: PUBLIC ToolWindow.DisplayProcType =
          BEGIN
          ENABLE UNWIND => NULL;
          IF ~ILT.toolData.busy THEN RETURN;
          --Display.White[window, [[0, 0], window.GetBox[].dims]];
          DisplayIndicator[window];
          END;  


     DisplayFile: PUBLIC PROCEDURE[] =
          BEGIN
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "DisplayFile...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          IF ILT.toolData.fileServer = IFS THEN
               ILT.toolData.filePathName ← String.CopyToNewString[
                    s: IFSFileName, z: Heap.systemZone]
          ELSE
               IF ILT.toolData.fileServer = FS THEN
                    ILT.toolData.filePathName ← String.CopyToNewString[
                         s: FSFileName, z: Heap.systemZone]
               ELSE
                    ILT.toolData.filePathName ← String.CopyToNewString[
                         s: FloppyFileName, z: Heap.systemZone];
          FormSW.DisplayItem[ILT.toolData.paramSW, 3];
          END;  



     DisplayFileSize: PUBLIC PROCEDURE [size: File.PageCount] =
          BEGIN

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "DisplayFileSize...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          ILT.toolData.vMemSize ← size;
          IF debug THEN {
               Put.LongDecimal[ILT.toolData.fileSW, ILT.toolData.vMemSize];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          FormSW.DisplayItem[ILT.toolData.paramSW, 2];
          END;


     <<
     DisplayIndicator: ToolWindow.DisplayProcType =
          BEGIN
          pattern: ARRAY [0..1] OF ARRAY [0..8) OF WORD;
          left: WORD = 177400B;
          right: WORD = 000377B;
          SELECT ILT.toolData.indicator FROM
               left =>
                    BEGIN
                    pattern ← [ALL[left], ALL[right]];
                    Display.Bitmap[
                         window: window, box: indicatorBox,
                         address: [word: @pattern, bit: 0], bitmapBitWidth: 16];
                    END;
               right =>
                    BEGIN
                    pattern ← [ALL[right], ALL[left]];
                    Display.Bitmap[
                         window: window, box: indicatorBox,
                         address: [word: @pattern, bit: 0], bitmapBitWidth: 16];
                    END;
               ENDCASE;
          END;  --DisplayIndicator
>>


     --taken from StarFileTool
     DisplayIndicator: PUBLIC ToolWindow.DisplayProcType =
          BEGIN
          pattern: Graphic;
          SELECT ILT.toolData.indicator FROM
               left => {pattern ← twiddleLeft; };
               off, right => {pattern ← pattern ← twiddleRight; };
               ENDCASE;
          Display.Bitmap[
               window, indicatorBox, [@pattern, , 0], 16, Display.replaceFlags];
          END;  --DisplayIndicator



     DisplayVolAttributes: PROCEDURE[] =
          BEGIN

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "DisplayVolAttributes...."L];
               Process.Pause[Process.SecondsToTicks[10]];
               };
          [] ← GetVolAttributes[];
          FormSW.DisplayItem[ILT.toolData.paramSW, 5];
          FormSW.DisplayItem[ILT.toolData.paramSW, 6];
          END;


     DoInstall: UserInput.PeriodicProcType =
          BEGIN
	  file: File.File;
	  
          ClearSubWindows;
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Start Install ....."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          PutVolumeName[];
          IF Confirm[] THEN
               BEGIN
               ILT.LoginProc[];
               ClearCommandSubwindow;
               DisplayIndicator[ILT.toolData.commandSW];
               ILT.toolData.busy ← TRUE;
               IF ILT.toolData.fileServer = IFS OR ILT.toolData.fileServer = FS THEN
                    ILT.InstallProc[ILT.toolData.volName]
               ELSE [] ← ILT.FloppyReadSysout[ILT.toolData.filePathName];
	       ILT.toolData.busy ← FALSE;
               DisplayCommandSubwindow;
	       DisplayVolAttributes[];
               END;
          END;  


     FormSWBoot: FormSW.ProcType =
          BEGIN
	  
	  sysoutThreshold: CARDINAL ← 1000;
          ts: System.Switches;
          volumeID: Volume.ID;
          volumeOpen: BOOLEAN ← FALSE;

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "FormSWBoot...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          --ClearSubWindows;
          PutVolumeName[];
          IF Confirm[] THEN {
               IF ILT.toolData.vMemSize > sysoutThreshold THEN  -- some arbitrary no. for lisp sysout size
                    {
                    IF ILT.SetVolumeProc[ILT.toolData.volName] THEN
                         TemporaryBooting.BootButton[];
                    }
               ELSE {  -- non-lisp volumes
                    IF String.Equivalent[ILT.toolData.volName, "SystemTools"] THEN {
                         IF ~String.Equivalent[ILT.toolData.userPassword, "n0way!"L] THEN {
			      Put.Line[ILT.toolData.fileSW, "Feature disabled."L];
                              GOTO exit;
			      };
                         };
                    [volumeID, volumeOpen] ← ILT.GetVolumeID[ILT.toolData.volName];
                    IF volumeOpen THEN {
                         ts ← OthelloOps.DecodeSwitches["N"L 
			 	! OthelloOps.BadSwitches => {
					Put.Line[ILT.toolData.fileSW, "BadSwitches...."L];
					GOTO exit;
				};];
                        TemporaryBooting.BootFromVolume[volumeID, ts];
                         };
                    };
               EXITS exit => NULL;
               };
          END;  



     FormSWCopyVMem: FormSW.ProcType =
          BEGIN
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "FormSWCopyVMem...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          ILT.BootStuff[];
          END;


     FormSWEraseProc: FormSW.ProcType =
          BEGIN
          ILT.toolData.busy ← TRUE;
          ClearSubWindows;
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Start Erase Proc....."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          PutVolumeName[];
          IF Confirm[] THEN
               BEGIN
               ILT.EraseProc[ILT.toolData.volName];
               ILT.toolData.vMemSize ← 0;
               ILT.SetVMemFileSize[0];
               DisplayFileSize[0];
               END;
          DisplayVolAttributes[];
          ILT.toolData.busy ← FALSE;
          END;


     FormSWFloppyProc: FormSW.ProcType =
          BEGIN
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "FormSWFloppyDup...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          Put.Line[ILT.toolData.fileSW, "To Be Implemented."L];
          --ILT.FloppyStuff[];
          END;



     FormSWHelpProc: FormSW.ProcType =
          BEGIN
          ILT.toolData.busy ← TRUE;
          ClearSubWindows;
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "FormSWHelpProc...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          ILT.DisplayWriteUp;
          ILT.toolData.busy ← FALSE;
          END;


     FormSWInstallProc: FormSW.ProcType =
          BEGIN
          [] ← UserInput.CreatePeriodicNotify[
               proc: DoInstall, window: sw, rate: 0];
          END;



     FormSWLoginProc: FormSW.ProcType =
          BEGIN
          ILT.toolData.busy ← TRUE;
          ClearSubWindows;
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Start Login Proc....."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          ILT.LoginProc[];
          ILT.toolData.busy ← FALSE;
          END;


     FormSWMakeScript: FormSW.ProcType =
          BEGIN
          ILT.toolData.busy ← TRUE;
          ClearSubWindows;
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Start MakeScript....."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          --Put.Line[ILT.toolData.fileSW, "To be implemented..."L];     
          ILT.MakeScript[];
          ILT.toolData.busy ← FALSE;
          END;


     FormSWQuitProc: FormSW.ProcType =
          BEGIN
          --v: Volume.ID;
          all: Volume.TypeSet = [
               normal: TRUE, debugger: TRUE, debuggerDebugger: TRUE];

          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Quit Proc..."L];
               --Process.Pause[Process.SecondsToTicks[5]];
               };
          [] ← ToolWindow.Deactivate[windowHandle];

          --FOR v ← Volume.GetNext[Volume.nullID, all], Volume.GetNext[v, all] WHILE
          -- v ~= Volume.systemID DO ENDLOOP;
          --UserInput.ClearInputFocusOnMatch[windowHandle];
          --TemporaryBooting.BootFromVolume[v];
          END; 


     FormSWRemoteList: FormSW.ProcType =
          BEGIN
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "FormSWRemoteList...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };

          Put.Line[ILT.toolData.fileSW, "To be implemented...."L];
          END;  



     FormSWScavengeProc: FormSW.ProcType =
          BEGIN
          ILT.toolData.busy ← TRUE;
          ClearSubWindows;
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Scavenge Proc..."L];
               --Process.Pause[Process.SecondsToTicks[5]];
               };
          PutVolumeName[];
          IF Confirm[] THEN ILT.ScavengeProc[ILT.toolData.volName];
          ILT.toolData.busy ← FALSE;
          END;  



     FormSWSetFileSize: FormSW.ProcType =
          BEGIN
          ILT.toolData.busy ← TRUE;

          ClearSubWindows;
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "Start SetFileSize....."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          Put.Text[ILT.toolData.fileSW, "VMem size = "L];
          Put.LongDecimal[ILT.toolData.fileSW, ILT.toolData.vMemSize];
          Put.CR[ILT.toolData.fileSW];
          IF Confirm[] THEN ILT.SetVMemFileSize[ILT.toolData.vMemSize];
          DisplayVolAttributes[];
          ILT.toolData.busy ← FALSE;
          END;  



     FormSWSetProc: FormSW.ProcType =
          BEGIN
          ILT.toolData.busy ← TRUE;
          ClearSubWindows;
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "SetVolume Proc..."L];
               --Process.Pause[Process.SecondsToTicks[5]];
               };
          PutVolumeName[];
          IF Confirm[] THEN [] ← ILT.SetVolumeProc[ILT.toolData.volName];
          ILT.toolData.busy ← FALSE;
          END;



     FormSWVolHintsProc: FormSW.MenuProcType =
          BEGIN
          RETURN[
               hints: DESCRIPTOR[
               @ILT.toolData.volHints[0], ILT.toolData.volHints.length],
                    freeHintsProc: HintsNoLongerBusy, replace: TRUE];

          END;


     GetUser: PROCEDURE [name, password: LONG STRING] =
          BEGIN
          z: UNCOUNTED ZONE = Heap.systemZone;
          ILT.toolData.userName ← String.CopyToNewString[name, z];
          ILT.toolData.userPassword ← String.CopyToNewString[password, z]
          END; 


     GetDefaultDomain: PROCEDURE [domain: LONG STRING] =
          BEGIN
          z: UNCOUNTED ZONE = Heap.systemZone;
          ILT.toolData.domainName ← String.CopyToNewString[domain, z]
          END;  


     GetDefaultOrganization: PROCEDURE [organization: LONG STRING] =
          BEGIN
          z: UNCOUNTED ZONE = Heap.systemZone;
          ILT.toolData.organizationName ← String.CopyToNewString[organization, z]
          END; 


     GetProfileInfo: PROCEDURE =
          BEGIN
          --Profile.GetUser[GetUser];
          Profile.GetDefaultDomain[GetDefaultDomain];
          Profile.GetDefaultOrganization[GetDefaultOrganization];
          --Profile.GetDefaultRegistry[GetDefaultRegistry];
          --Profile.GetLibrarianNames[GetLibrarianNames];
          --Profile.GetLibrarian[GetLibrarian]
          END; 



     GetVolAttributes: PUBLIC PROCEDURE[] RETURNS [BOOLEAN] =
          BEGIN
 
          volumeID: Volume.ID ← Volume.nullID;
          volumeOpen: BOOLEAN ← FALSE;

          [volumeID, volumeOpen] ← ILT.GetVolumeID[ILT.toolData.volName];
          IF volumeID = Volume.nullID THEN RETURN[FALSE];

          [ILT.toolData.currentVolSize, ILT.toolData.currentVolFreeSize] ←
               Volume.GetAttributes[volumeID];

          IF debug THEN {
               Put.Text[ILT.toolData.fileSW, " \n Source Volume size = "L];
               Put.LongDecimal[ILT.toolData.fileSW, ILT.toolData.currentVolSize];
               Put.Line[ILT.toolData.fileSW, " pages"L];
               Put.Text[ILT.toolData.fileSW, " Free pages on source volume = "L];
               Put.LongDecimal[ILT.toolData.fileSW, ILT.toolData.currentVolFreeSize];
               Put.CR[ILT.toolData.fileSW];
               Process.Pause[Process.SecondsToTicks[10]];
               };

          RETURN[TRUE];
          END; 



     HintsNoLongerBusy: FormSW.FreeHintsProcType =
          BEGIN
          size: File.PageCount;
	  
          ClearMsgSubwindow;
          size ← ILT.GetFileSize[];
          DisplayFileSize[size];
          ILT.toolData.busy ← FALSE;
          DisplayVolAttributes[];
          END; 


     Init: PROCEDURE =
          BEGIN
          --h: Exec.Handle;
          --execWrite: Format.StringProc ← Exec.OutputProc[h];
          --execWrite["Creating tool window.."L]; 
          --Process.Pause[Process.SecondsToTicks[5]];
          Exec.AddCommand["LispTool.~"L, LispTool, Unload];
          END; 


     <<InvertIndicator: FileTransfer.ClientProc =
          BEGIN
          ENABLE UNWIND => NULL;
          IF ~ILT.toolData.busy THEN RETURN;
          SELECT ILT.toolData.indicator FROM
               left => ILT.toolData.indicator ← right;
               off, right => ILT.toolData.indicator ← left;
               ENDCASE;
          Display.Invert[ILT.toolData.commandSW, indicatorBox];
          END;  --InvertIndicator
	  >>


     --taken from StarFileTool with author's permission
     InvertIndicator: PUBLIC PROC[] =
          BEGIN
          ENABLE UNWIND => NULL;
          pattern: Graphic;

          IF ~ILT.toolData.busy THEN RETURN;
          SELECT ILT.toolData.indicator FROM
               left => {ILT.toolData.indicator ← right; pattern ← twiddleRight; };
               off, right => {ILT.toolData.indicator ← left; pattern ← twiddleLeft; };
               ENDCASE;

          Display.Bitmap[
               ILT.toolData.commandSW, indicatorBox, [@pattern, , 0], 16,
               Display.replaceFlags];
          END;



     ListLogicalVolumes: PUBLIC PROC RETURNS [nVols: CARDINAL] =
          BEGIN
          i: CARDINAL;

          s: STRING ← [80];
          v: Volume.ID;
          all: Volume.TypeSet = [
               normal: TRUE, debugger: TRUE, debuggerDebugger: TRUE];

          IF ILT.toolData.volName # NIL THEN RETURN;
          -- First, count the logical volumes.
          nVols ← 0;
          FOR v ← Volume.GetNext[Volume.nullID, all], Volume.GetNext[v, all] WHILE
               v ~= Volume.nullID DO nVols ← nVols + 1; ENDLOOP;

          -- Now build up the table
          ILT.toolData.volHints ← Heap.systemZone.NEW[ILT .VolHints[nVols]];
          FOR i IN [0..nVols) DO
               v ← Volume.GetNext[v, all];
               Volume.GetLabelString[v, s];
               ILT.toolData.volHints[i] ← String.CopyToNewString[s, Heap.systemZone];
               ENDLOOP;

          END; 



     LispActivate: PUBLIC PROCEDURE =
          BEGIN
          IF ILT.SetVolumeProc["Lisp"L] THEN TemporaryBooting.BootButton[];
          END;


     LispTool: Exec.ExecProc =
          BEGIN
          execWrite: Format.StringProc ← Exec.OutputProc[h];
          --execWrite["Creating tool window.."L]; 
          --Process.Pause[Process.SecondsToTicks[5]];
          IF (ILT.windowHandle # NIL) AND ~active THEN
               ToolWindow.Activate[ILT.windowHandle]
          ELSE ILT.windowHandle ← MakeTool[];
          END;  



     LispToolActivate: PUBLIC PROCEDURE =
          BEGIN
          IF windowHandle = NIL THEN windowHandle ← MakeTool[];
          ToolWindow.Activate[windowHandle];
          Window.Stack[
               windowHandle, Window.GetChild[Window.GetParent[windowHandle]]];  -- top me
          Window.ValidateTree[];
          END;



     MakeCommands: FormSW.ClientItemsProcType =
          BEGIN OPEN FormSW;

          tabs: ARRAY [0..6) OF CARDINAL ← [0, 15, 30, 45, 60, 75];
          nItems: CARDINAL = 11;
          items ← AllocateItemDescriptor[nItems];

          items[0] ← CommandItem[
               tag: "Install File"L, place: newLine, proc: FormSWInstallProc];
          items[1] ← CommandItem[tag: "Boot"L, proc: FormSWBoot];
          items[2] ← CommandItem[tag: "Erase"L, proc: FormSWEraseProc];
          items[3] ← CommandItem[tag: "Set VMem"L, proc: FormSWSetFileSize];
          items[4] ← CommandItem[tag: "Make Script"L, proc: FormSWMakeScript];
          items[5] ← CommandItem[tag: "Help"L, proc: FormSWHelpProc];

          items[6] ← CommandItem[
               tag: "Remote List"L, place: newLine, proc: FormSWRemoteList];
          items[7] ← CommandItem[tag: "Copy VMem"L, proc: FormSWCopyVMem];
          items[8] ← CommandItem[tag: "Scavenge"L, proc: FormSWScavengeProc];
          items[9] ← CommandItem[tag: "Floppy"L, proc: FormSWFloppyProc];
          items[10] ← CommandItem[tag: "Quit"L, proc: FormSWQuitProc];

          SetTagPlaces[items, DESCRIPTOR[tabs], FALSE];
          RETURN[items, TRUE];
          END;  --MakeCommands



     MakeParams: FormSW.ClientItemsProcType =
          BEGIN OPEN FormSW;

          i, nVols: CARDINAL;
          tabs: ARRAY [0..4) OF CARDINAL ← [0, 30, 60, 75];
          nItems: CARDINAL = 11;
          emptyString: LONG STRING ← NIL;

          docForm: ARRAY [0..2) OF Enumerated ← [
               ["General"L, ILT.DocType[general]], [
               "ErrorMsg"L, ILT.DocType[errorMsg]]];

          serverForm: ARRAY [0..3) OF Enumerated ← [
               ["IFS"L, ILT.ServerType[IFS]], ["FS"L, ILT.ServerType[FS]], [
               "FLOPPY"L, ILT.ServerType[FLOPPY]]];


          volForm: ARRAY [0..2) OF Enumerated ← [
               ["Lisp"L, ILT.VolType[Lisp]], ["NonLisp"L, ILT.VolType[NonLisp]]];

          items ← AllocateItemDescriptor[nItems];
          nVols ← ListLogicalVolumes[];

          String.Copy[ILT.toolData.volName, ILT.toolData.volHints[0]];
          FOR i IN [0..nVols) DO
               IF String.Equivalent[ILT.toolData.volHints[i], "Lisp"L] THEN
                    BEGIN
                    String.Replace[
                         @ILT.toolData.volName, ILT.toolData.volHints[i], Heap.systemZone];
                    EXIT;
                    END;
               ENDLOOP;


          items[0] ← EnumeratedItem[
               tag: "Document"L, place: newLine, z: Heap.systemZone, feedback: all,
               value: @ILT.toolData.docType, copyChoices: TRUE,
               choices: DESCRIPTOR[docForm]];
          items[1] ← EnumeratedItem[
               tag: "Device"L, z: Heap.systemZone, feedback: all,
               value: @ILT.toolData.fileServer, copyChoices: TRUE,
               proc: ServerNotifyProc, choices: DESCRIPTOR[serverForm]];
          items[2] ← NumberItem[tag: "VMem Size"L, value: @ILT.toolData.vMemSize];

          items[3] ← StringItem[
               tag: "File"L, place: newLine, string: @ILT.toolData.filePathName,
               inHeap: TRUE];

          items[4] ← StringItem[
               tag: "Volume Menu"L, place: newLine, string: @ILT.toolData.volName,
               inHeap: TRUE, menuProc: FormSWVolHintsProc];

          items[5] ← NumberItem[
               tag: "Volume Size"L, value: @ILT.toolData.currentVolSize];
          items[6] ← NumberItem[
               tag: "Free Size"L, value: @ILT.toolData.currentVolFreeSize];

          items[7] ← StringItem[
               tag: "User"L, place: newLine, string: @ILT.toolData.userName,
               inHeap: TRUE];
          items[8] ← StringItem[
               tag: "Password"L, string: @ILT.toolData.userPassword, inHeap: TRUE,
               feedback: password];

          items[9] ← StringItem[
               tag: "Domain"L, place: newLine, string: @ILT.toolData.domainName,
               inHeap: TRUE];
          items[10] ← StringItem[
               tag: "Organization"L, string: @ILT.toolData.organizationName,
               inHeap: TRUE];

          SetTagPlaces[items, DESCRIPTOR[tabs], FALSE];
          RETURN[items, TRUE]
          END;  --MakeParams



     MakeSWs: Tool.MakeSWsProc =
          BEGIN
          size: File.PageCount;

          logName: STRING ← [40];
          addresses: ARRAY [0..4) OF ToolDriver.Address;

          Tool.UnusedLogName[unused: logName, root: "LispTool.log"L];
          ILT.toolData.msgSW ← Tool.MakeMsgSW[window: window, lines: 5];

          ILT.toolData.paramSW ← Tool.MakeFormSW[
               window: window, formProc: MakeParams];
          ILT.toolData.commandSW ← Tool.MakeFormSW[
               window: window, formProc: MakeCommands];

          ILT.toolData.fileSW ← Tool.MakeFileSW[window: window, name: logName];
	  size ← ILT.GetFileSize[];
	  DisplayFileSize[size];
          DisplayFile[];
          DisplayVolAttributes[];

          --Supervisor.AddDependency[client: agent, implementor: Event.toolWindow];

          -- do the ToolDriver stuff
          addresses ← [
               [name: "msgSW"L, sw: ILT.toolData.msgSW],
               --[name: "formSW"L, sw: ILT.toolData.formSW],
               [name: "ParamSW"L, sw: ILT.toolData.paramSW], [
               name: "CmdSW"L, sw: ILT.toolData.commandSW], [
               name: "fileSW"L, sw: ILT.toolData.fileSW]];
          ToolDriver.NoteSWs[tool: "LispTool"L, subwindows: DESCRIPTOR[addresses]];

          END;  --MakeSWs



     MakeTool: PROCEDURE RETURNS [wh: Window.Handle] =
          BEGIN
          heraldName: STRING ← [80];

          String.AppendString[heraldName, "XEROX AISBU: Lisp System Tools"L];
          String.AppendString[heraldName, " of "L];
          Time.Append[heraldName, Time.Unpack[Runtime.GetBcdTime[]]];
          heraldName.length ← heraldName.length - 3;  -- gun the seconds
          --String.AppendString[heraldName, " on Pilot Version "L];
          --Version.Append[heraldName];
          RETURN[
               Tool.Create[
                    makeSWsProc: MakeSWs, initialState: default,
                    clientTransition: ClientTransition, name: heraldName,
                    initialBox: [[0, 0], [1024, 800]], 
		    --x, y, width, height
		    tinyName1: "Lisp"L,
                    tinyName2: "Tool"L]]
          END;  --MakeTool



     PutVolumeName: PROCEDURE[] =
          BEGIN
          Put.Text[ILT.toolData.fileSW, "Volume = "L];
          Put.LongString[ILT.toolData.fileSW, ILT.toolData.volName];
          Put.CR[ILT.toolData.fileSW];
          END;  


     -- move to profile
     ProcessUserDotCM: PROCEDURE =
          BEGIN
          CMOption: TYPE = MACHINE DEPENDENT{
               Domain, User, Password, FSFile, IFSFile, FloppyFile, Protocol, Org,
               noMatch(StringLookUp.noMatch)};
          DefinedOption: TYPE = CMOption [Domain..Org];
          cmOptionTable: ARRAY DefinedOption OF LONG STRING ← [
               Domain: "Domain"L, User: "User"L, Password: "Password"L,
               Org: "Organization"L, FSFile: "NSLisp", IFSFile: "PUPLisp",
               FloppyFile: "FloppyLisp", Protocol: "FileServer"L];
          cmIndex: CMOption;

          CheckType: PROCEDURE [h: CmFile.Handle, table: StringLookUp.TableDesc]
               RETURNS [index: CARDINAL] = CmFile.NextValue;

          MyNextValue: PROCEDURE [
               h: CmFile.Handle,
               table: LONG DESCRIPTOR FOR ARRAY DefinedOption OF LONG STRING]
               RETURNS [index: CMOption] = LOOPHOLE[CheckType];

          cmFile: CmFile.Handle ← CmFile.UserDotCmOpen[
               ! CmFile.Error => IF code = fileNotFound THEN GOTO return];

          IF CmFile.FindSection[cmFile, "LispTool"L] THEN
               DO
                    SELECT
                    (cmIndex ← MyNextValue[
                         h: cmFile, table: DESCRIPTOR[cmOptionTable] !
                         CmFile.TableError => RESUME ]) FROM
                         noMatch => EXIT;

                         User =>
                              BEGIN
                              value: LONG STRING = Token.Item[cmFile];
                              ILT.toolData.userName ← String.CopyToNewString[
                                   s: value, z: Heap.systemZone];
                              [] ← Token.FreeTokenString[value];
                              END;

                         Password =>
                              BEGIN
                              value: LONG STRING = Token.Item[cmFile];
                              ILT.toolData.userPassword ← String.CopyToNewString[
                                   s: value, z: Heap.systemZone];
                              [] ← Token.FreeTokenString[value];
                              END;


                         Domain =>
                              BEGIN
                              value: LONG STRING = Token.Item[cmFile];
                              ILT.toolData.domainName ← String.CopyToNewString[
                                   s: value, z: Heap.systemZone];
                              [] ← Token.FreeTokenString[value];
                              END;

                         Org =>
                              BEGIN
                              value: LONG STRING = Token.Item[cmFile];
                              ILT.toolData.organizationName ← String.CopyToNewString[
                                   s: value, z: Heap.systemZone];
                              [] ← Token.FreeTokenString[value];
                              END;


                         FSFile =>
                              BEGIN
                              value: LONG STRING ← Token.Item[cmFile];
                              --String.Copy[FSFileName, value];
			      FSFileName ← String.CopyToNewString[
                                   s: value, z: Heap.systemZone];
                              [] ← Token.FreeTokenString[value];
                              END;

                         IFSFile =>
                              BEGIN
                              value: LONG STRING ← Token.Item[cmFile];
                              IFSFileName ← String.CopyToNewString[
                                   s: value, z: Heap.systemZone];
                              [] ← Token.FreeTokenString[value];
                              END;

                         FloppyFile =>
                              BEGIN
                              value: LONG STRING ← Token.Item[cmFile];
                              FloppyFileName ← String.CopyToNewString[
                                   s: value, z: Heap.systemZone];
                              [] ← Token.FreeTokenString[value];
                              END;

                         Protocol =>
                              BEGIN
                              value: LONG STRING ← Token.Item[cmFile];
                              Put.Line[ILT.toolData.fileSW, value];
                              IF String.Equivalent[value, "FS"] THEN
                                   ILT.toolData.fileServer ← FS
                              ELSE ILT.toolData.fileServer ← IFS;
                              [] ← Token.FreeTokenString[value];
                              END;
                         ENDCASE;
                    ENDLOOP;
          --GetProfileInfo[]; 
	  --domain & org defined after login operation
          [] ← CmFile.Close[cmFile];
          EXITS return => NULL;
          END; 



     ServerNotifyProc: FormSW.EnumeratedNotifyProcType =
          BEGIN
          IF debug THEN {
               Put.Line[ILT.toolData.fileSW, "ServerNotifyProc...."L];
               Process.Pause[Process.SecondsToTicks[5]];
               };
          DisplayFile[];
          END;  


     TajoActivate: PUBLIC PROCEDURE =
          BEGIN OPEN OthelloOps, OthelloDefs;
	  --BEGIN
          ts: System.Switches;
          volumeID: Volume.ID;
          volumeOpen: BOOLEAN ← FALSE;
	
	  debug ← FALSE;
          [volumeID, volumeOpen] ← ILT.GetVolumeID["User"L];
          IF volumeOpen THEN {
               --ts ← OthelloOps.DecodeSwitches["N"];
	       ts ← DecodeSwitches["N"];
               TemporaryBooting.BootFromVolume[volumeID, ts];
               };
          END;  


     Unload: Exec.ExecProc =
          BEGIN
          IF ILT.windowHandle # NIL THEN Tool.Destroy[ILT.windowHandle];
          ILT.windowHandle ← NIL;
          [] ← Exec.RemoveCommand[h, "LispTool.~"L];
          END;  



     -- Mainline code
     Init[];
     END...LispToolImpl