-- LTFloppyImpl.mesa -- Created by -- JFung.pasa 14-Dec-83 12:37:04 -- last edited by -- JFung.pasa 24-Sep-84 10:27:36 DIRECTORY AccessFloppy, AccessFloppyUtil, Ascii, Environment, Exec, File, FileName, FileTypes USING [tUntypedFile], Floppy, Format, FormSW, Heap USING [systemZone], Inline, LispToolOps, MFile, MStream, NSString, OthelloDefs, OthelloOps, Process USING [Pause, SecondsToTicks], Put, Runtime, Space, SpecialMFile USING [GetCapaWithAccess, LeaderPages], Storage, Stream, String, StringLookUp, Time, Tool USING [ Create, Destroy, MakeFileSW, MakeFormSW, MakeMsgSW, MakeSWsProc, UnusedLogName], ToolDriver, ToolWindow, Token, UserInput, Version, Volume, Window; LTFloppyImpl: PROGRAM IMPORTS AccessFloppy, File, FileName, Floppy, FormSW, Heap, Inline, LispToolOps, MFile, NSString, OthelloOps, Process, Put, SpecialMFile, Storage, String, Volume, Time, Tool, ToolDriver, Token, UserInput EXPORTS LispToolOps = BEGIN OPEN ILT: LispToolOps; -- constant nullNextFile: NextFile = []; -- TYPEs Indicator: TYPE = {off, left, right}; DataHandle: TYPE = LONG POINTER TO Data; Data: TYPE = MACHINE DEPENDENT RECORD [ -- Message subwindow stuff msgSW(0): Window.Handle ← NIL, -- File subwindow stuff fileSW(2): Window.Handle ← NIL, -- Form subwindow stuff -- Note: enumerateds and booleans must be word boundary -- aligned as addresses for them must be generated --formSW: Window.Handle ← NIL, paramSW(4): Window.Handle ← NIL, commandSW(6): Window.Handle ← NIL, busy(8): BOOLEAN ← FALSE, -- command is running volName(9): LONG STRING ← NIL, pattern(11): LONG STRING ← NIL, indicator(13): Indicator ← left, floppyName(14): LONG STRING ← NIL, stream(16): MStream.Handle ← NIL, from(18): LONG STRING ← NIL, to(20): LONG STRING ← NIL, numberOfFiles(22): INTEGER ← 0, current(23): LptNextFile ← NIL, fileList(25): LptNextFile ← NIL]; EnumProc: TYPE = PROCEDURE [ attributes: AccessFloppy.Attributes, fH: Floppy.FileHandle, name: LONG STRING] RETURNS [stop: BOOLEAN ← FALSE]; LptNextFile: TYPE = LONG POINTER TO NextFile; NextFile: TYPE = RECORD [ file: LONG STRING ← NIL, size: LONG CARDINAL ← 0, -- file size including leader page if it has one. type: File.Type ← AccessFloppy.tFloppyLeaderPage, -- specify whether it has leader page. next: LptNextFile ← NIL]; VolHints: TYPE = RECORD [names: SEQUENCE length: CARDINAL OF LONG STRING]; SizeHints: TYPE = RECORD [names: SEQUENCE length: CARDINAL OF CARDINAL]; -- global variables Abort: ERROR [s: STRING] = CODE; active: BOOLEAN ← FALSE; atSource: PUBLIC CARDINAL ← 0; attributes: AccessFloppy.Attributes ← NIL; bufferSize: Space.PageCount ← 30; dataVersion: CARDINAL = 02222; -- version of clientData debug: BOOLEAN ← FALSE; floppyWH: Window.Handle ← NIL; formDisplay: ToolWindow.DisplayProcType ← NIL; heraldName: STRING ← [50]; indicatorBox: Window.Box = [[10, 10], [16, 16]]; nullFile: Floppy.FileHandle; opened: BOOLEAN ← FALSE; --spaceHandle: Space.Handle ← Space.nullHandle; toolData: DataHandle ← NIL; vH: Floppy.VolumeHandle ← Floppy.nullVolumeHandle; volumeID: Volume.ID ← Volume.nullID; volumeOpen: BOOLEAN ← FALSE; z: UNCOUNTED ZONE = Heap.systemZone; SetOutcome: SIGNAL [value: Exec.Outcome] = CODE; CleanUp: PROC = BEGIN current: LptNextFile ← toolData.fileList; releaseData: MFile.ReleaseData ← [NIL, NIL]; WHILE current↑ # nullNextFile DO file: MFile.Handle ← NIL; scratchName: LONG STRING ← [120]; String.AppendString[scratchName, current.file]; String.AppendString[scratchName, ".Scratch$"L]; toolData.current ← current.next; file ← MFile.Acquire[ scratchName, MFile.Access[delete], releaseData]; MFile.Delete[file]; --current.file ← Storage.FreeStringNil[current.file]; Storage.Free[current]; current ← toolData.current; ENDLOOP; toolData.fileList ← toolData.current ← Storage.FreeNodeNil[ toolData.current]; toolData.from ← Storage.FreeStringNil[toolData.from]; toolData.to ← Storage.FreeStringNil[toolData.to]; END; -- CleanUp. << CopyCmd: PROCEDURE = BEGIN END; -- from AccessFloppyUtil CreateBuffer: PUBLIC PROC [size: Space.PageCount] RETURNS [spH: Space.Handle, spSize: Space.PageCount] = BEGIN END; -- CreateBuffer. DeleteBuffer: PUBLIC PROC [spH: Space.Handle] = BEGIN END; -- DeleteBuffer. DiskToFloppy: PROC = BEGIN END; -- DiskToFloppy. >> DisplayFloppyName: PROCEDURE [] = BEGIN IF debug THEN { Put.Line[ILT.toolData.fileSW, "DisplayFile...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; FormSW.DisplayItem[toolData.paramSW, 3]; END; --DisplayFloppyName EnumerateFloppyFiles: PROCEDURE [ v: Floppy.VolumeHandle, proc: EnumProc, pattern: LONG STRING] = BEGIN nullFile: Floppy.FileHandle = [volume: v, file: Floppy.nullFileID]; attributes: AccessFloppy.Attributes ← Heap.systemZone.NEW[ AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]]; name: LONG STRING = LOOPHOLE[@attributes.length]; IF debug THEN { Put.Line[ILT.toolData.fileSW, "EnumerateFloppyFiles...."L]; --Process.Pause[Process.SecondsToTicks[5]]; }; FOR current: Floppy.FileHandle ← Floppy.GetNextFile[nullFile].nextFile, Floppy.GetNextFile[current].nextFile WHILE current # nullFile DO ENABLE UNWIND => Heap.systemZone.FREE[@attributes]; IF Floppy.GetFileAttributes[current].type # AccessFloppy.tFloppyLeaderPage THEN LOOP; IF debug THEN { Put.Line[ILT.toolData.fileSW, "Floppy.GetNextFile"L]; --Process.Pause[Process.SecondsToTicks[5]]; Put.Text[ILT.toolData.fileSW, "Pattern = "L]; Put.Line[ILT.toolData.fileSW, pattern]; }; AccessFloppy.GetAttributes[current, attributes]; IF --(pattern = NIL --OR Exec.MatchPattern[string: name, pattern: pattern]) OR proc[attributes, current, name] THEN { Put.Line[ILT.toolData.fileSW, "Exited loop."L]; EXIT; }; ENDLOOP; Heap.systemZone.FREE[@attributes]; END; --EnumerateFloppyFiles FileLookUp: PROC [nsName: NSString.String] RETURNS [fFile: Floppy.FileHandle, continue: BOOLEAN] = BEGIN continue ← TRUE; IF debug THEN { Put.Line[ILT.toolData.fileSW, "FileLookUp"L]; --Put.Text[ILT.toolData.msgSW, nsName]; --Process.Pause[Process.SecondsToTicks[5]]; }; fFile ← AccessFloppy.LookUp[ nsName, attributes ! AccessFloppy.Error => { continue ← FALSE; Put.Line[ILT.toolData.fileSW, "Floppy Error"L]; SELECT type FROM attributesNotAllowed => { Put.Line[ ILT.toolData.msgSW, "attributesNotAllowed"L]; }; fileNotFound => { --Put.Text[ILT.toolData.msgSW, name]; Put.Line[ILT.toolData.msgSW, "File name not found"L]; }; invalidParameter => { Put.Line[ILT.toolData.msgSW, "invalidParameter"L]; }; nameInUse => { Put.Line[ILT.toolData.msgSW, "nameInUse"L]; }; volumeNotOpen => { Put.Line[ILT.toolData.msgSW, "volumeNotOpen"L]; }; ENDCASE => Put.Line[ILT.toolData.msgSW, "others"L]; IF debug THEN Process.Pause[Process.SecondsToTicks[10]]; }]; RETURN[fFile, continue]; END; --FileLookUp FixDirectory: PUBLIC PROC [dir: LONG POINTER TO LONG STRING] = BEGIN IF dir↑ = NIL THEN RETURN; SELECT dir[dir.length - 1] FROM '>, '# => RETURN; ENDCASE; String.AppendCharAndGrow[dir, '>, z]; END; --FixDirectory FloppyDelete: PUBLIC PROCEDURE [pattern: LONG STRING] RETURNS [deleted: BOOLEAN] = BEGIN name: LONG STRING ← NIL; vH: Floppy.VolumeHandle; DeleteOne: EnumProc = BEGIN deleted ← TRUE; Put.Text[ILT.toolData.msgSW, name]; Put.Text[ILT.toolData.msgSW, "... "L]; AccessFloppy.DeleteFile[ NSString.StringFromMesaString[name] ! AccessFloppy.Error => SELECT type FROM fileNotFound => { Put.Line[ILT.toolData.msgSW, "not found"L]; IF debug THEN Process.Pause[Process.SecondsToTicks[5]]; GOTO error; }; ENDCASE]; Put.Line[ILT.toolData.msgSW, "deleted"L]; IF debug THEN Process.Pause[Process.SecondsToTicks[10]]; RETURN[]; EXITS error => {deleted ← FALSE; RETURN[]; }; END; --DeleteOne [vH] ← OpenFloppy[]; IF ~opened THEN RETURN; BEGIN ENABLE UNWIND => {AccessFloppy.Close[ ! Floppy.Error => CONTINUE]}; --name ← toolData.pattern; --IF toolData.pattern = NIL THEN EXIT; IF WildCards[pattern] THEN EnumerateFloppyFiles[vH, DeleteOne, pattern] ELSE [] ← DeleteOne[NIL, [vH, Floppy.nullFileID], pattern]; END; IF debug THEN { Put.Text[ILT.toolData.fileSW, "AccessFloppy.Close"L]; Process.Pause[Process.SecondsToTicks[5]]; }; AccessFloppy.Close[]; END; --FloppyDelete FloppyDuplicate: PUBLIC PROCEDURE = BEGIN END; FloppyFormat: PROCEDURE [ nFiles: CARDINAL, label: LONG STRING, sides: Floppy.Sides, density: Floppy.Density] RETURNS [gotError: BOOLEAN] = BEGIN gotError: BOOLEAN ← FALSE; BEGIN v: Floppy.VolumeHandle; v ← AccessFloppy.Open[ ! Floppy.Error => SELECT error FROM invalidFormat => GOTO virgin; needsScavenging => {gotError ← TRUE; CONTINUE}; ENDCASE => gotError ← TRUE; ]; IF ~gotError THEN { [] ← Floppy.GetAttributes[v, label]; Floppy.Close[v]; Put.Text[ILT.toolData.fileSW, "Floppy volume """L]; Put.Text[ILT.toolData.fileSW, label]; Put.Line[ILT.toolData.fileSW, """ already formatted"L]; } ELSE Put.Line[ toolData.fileSW, "Floppy probably contains valid information"L]; EXITS virgin => NULL; END; Put.Line[ toolData.fileSW, "Formatting will DESTROY all contents, confirm to continue"L]; IF ~ILT.Confirm[] THEN RETURN; --label.length ← 0; IF label = NIL THEN { Put.Line[toolData.fileSW, "Please supply floppy name"]; Process.Pause[Process.SecondsToTicks[5]]; RETURN; }; << IF label # NIL THEN toolData.floppyName ← String.CopyToNewString[ s: label, z: Heap.systemZone] ELSE toolData.floppyName ← String.CopyToNewString[ s: "UnnamedFloppy"L, z: Heap.systemZone]; >> IF label # NIL OR toolData.floppyName # NIL THEN { Put.Text[toolData.fileSW, "label # Nil:"L]; Put.Text[toolData.fileSW, label]; Put.Line[toolData.fileSW, "<"L]; Process.Pause[Process.SecondsToTicks[5]]; toolData.floppyName ← label; Put.Text[toolData.fileSW, "floppyName:"L]; Put.Text[toolData.fileSW, toolData.floppyName]; Put.Line[toolData.fileSW, "<"L]; Process.Pause[Process.SecondsToTicks[5]]; toolData.floppyName ← String.CopyToNewString[ s: label, z: Heap.systemZone]; Put.Text[toolData.fileSW, "floppyName:"L]; Put.Text[toolData.fileSW, toolData.floppyName]; Put.Line[toolData.fileSW, "<"L]; }; IF debug THEN { Put.Line[ILT.toolData.fileSW, toolData.floppyName]; Process.Pause[Process.SecondsToTicks[5]]; }; IF ~ILT.Confirm[] THEN RETURN; --temp Put.Text[toolData.fileSW, "Formatting... "L]; Floppy.Format[ 0, nFiles, toolData.floppyName, density, sides ! Floppy.Error => SELECT error FROM onlyOneSide => {sides ← one; RETRY}; onlySingleDensity => {density ← single; RETRY}; badDisk => { Put.Line[ toolData.fileSW, "Can't format this disk; may be write protecte"L]; gotError ← TRUE; Process.Pause[Process.SecondsToTicks[5]]; GOTO noGood; }; ENDCASE; -- ERROR Abort["Can't format this disk; may be write protected"L]; Floppy.AlreadyFormatted => RESUME ]; Put.Line[toolData.fileSW, "...done"L]; EXITS noGood => RETURN; END; -- FloppyFormat FloppyInfo: PROCEDURE [] = BEGIN density: Floppy.Density; sides: Floppy.Sides; label: STRING ← [Floppy.maxCharactersInLabel]; freeSpace, largestBlock: LONG CARDINAL; v: Floppy.VolumeHandle; IF debug THEN { Put.Line[ILT.toolData.fileSW, "InfoDisk...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; [v] ← OpenFloppy[]; IF ~opened THEN RETURN; IF debug THEN { Put.Line[ILT.toolData.fileSW, "GetAttributes...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; [freeSpace, largestBlock, , , density, sides] ← Floppy.GetAttributes[ v, label]; toolData.floppyName ← String.CopyToNewString[ s: label, z: Heap.systemZone]; Put.CR[toolData.fileSW]; Put.Text[toolData.fileSW, "Floppy """L]; Put.Text[toolData.fileSW, label]; Put.Text[toolData.fileSW, """; "L]; Put.Text[toolData.fileSW, IF sides = one THEN "single"L ELSE "double"L]; Put.Text[toolData.fileSW, " sided; "L]; Put.Text[ toolData.fileSW, IF density = single THEN "single"L ELSE "double"L]; Put.Line[toolData.fileSW, " density"L]; Put.LongDecimal[toolData.fileSW, freeSpace]; Put.Text[toolData.fileSW, " free pages; largest free block = "L]; Put.LongDecimal[toolData.fileSW, largestBlock]; Put.Line[toolData.fileSW, " pages"L]; AccessFloppy.Close[]; FormSW.DisplayItem[toolData.paramSW, 2]; END; --FloppyInfo FloppyList: PROCEDURE [] = BEGIN pattern: LONG STRING ← NIL; v: Floppy.VolumeHandle; ListOne: EnumProc = BEGIN Put.CR[toolData.fileSW]; Put.Text[toolData.fileSW, name]; FOR i: CARDINAL IN [name.length + WritePartial[attributes]..24) DO Put.Text[toolData.fileSW, " "]; ENDLOOP; Put.Number[toolData.fileSW, attributes.type, [10, FALSE, TRUE, 5]]; Put.Text[toolData.fileSW, " "L]; Put.LongNumber[ toolData.fileSW, attributes.totalSizeInBytes, [ 10, FALSE, TRUE, 9]]; Put.Text[toolData.fileSW, " "L]; Put.Date[toolData.fileSW, attributes.createDate, noSeconds]; Put.Text[toolData.fileSW, " "L]; Put.Date[toolData.fileSW, attributes.lastWrittenDate, noSeconds]; END; --ListOne IF debug THEN { Put.Line[ILT.toolData.fileSW, "ListFiles: AccessFloppy.Open...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; [v] ← OpenFloppy[]; IF ~opened THEN RETURN; Put.Text[toolData.fileSW, " NAME "L]; --23 Put.Text[toolData.fileSW, " TYPE "L]; -- 5+2 Put.Text[toolData.fileSW, " LENGTH "L]; -- 9+2 Put.Text[toolData.fileSW, " CREATE "L]; -- 20+2 Put.Line[toolData.fileSW, " WRITE"L]; EnumerateFloppyFiles[ v, ListOne, "*"L ! UNWIND => {AccessFloppy.Close[ ! Floppy.Error => CONTINUE]}]; AccessFloppy.Close[]; END; --FloppyList FloppyReadSysout: PUBLIC PROCEDURE [pattern: LONG STRING] RETURNS [BOOLEAN] = BEGIN altName: LONG STRING ← NIL; pagesRemaining: INTEGER ← 1; created: BOOLEAN ← FALSE; continue: BOOLEAN ← TRUE; file: File.File; firstTime: BOOLEAN ← TRUE; fFile: Floppy.FileHandle; firstPage: File.PageNumber; freePages: Volume.PageCount; loopCnt: CARDINAL ← 1; nextFile: LONG STRING ← ILT.toolData.filePathName; nsName: NSString.String; readName: LONG STRING ← NIL; switches: LONG STRING ← NIL; v: Floppy.VolumeHandle; volSize: Volume.PageCount; --ReadOne: EnumProc = ReadOne: PROCEDURE [ attributes: AccessFloppy.Attributes, fH: Floppy.FileHandle, name: LONG STRING] RETURNS [stop: BOOLEAN ← FALSE] = BEGIN --mFile: MFile.Handle ← NIL; type: MFile.Type ← unknown; destName: LONG STRING ← NIL; srcVFN, destVFN: FileName.VirtualFilename ← NIL; IF debug THEN { Put.Line[ILT.toolData.fileSW, "ReadOne"L]; Process.Pause[Process.SecondsToTicks[5]]; }; --InvertIndicator[]; IF name # NIL THEN srcVFN ← FileName.AllocVFN[name]; IF String.Length[altName] # 0 THEN destVFN ← FileName.AllocVFN[altName] ELSE destVFN ← FileName.AllocVFN["[dummy]"L]; IF String.Length[destVFN.name] = 0 THEN { destName ← FileName.PackFilename[ srcVFN, FALSE, FALSE, TRUE, FALSE]; FileName.UnpackFilename[destName, destVFN]; FileName.FreeFilename[destName]; }; destName ← FileName.PackFilename[destVFN, FALSE, TRUE, TRUE, FALSE]; Put.Text[ILT.toolData.fileSW, name]; Put.Text[ILT.toolData.fileSW, "... "L]; IF attributes.clientDataLength = 2 AND attributes.clientData[0] = dataVersion THEN type ← attributes.clientData[1]; Put.Text[ILT.toolData.fileSW, "copying to "L]; Put.Text[ILT.toolData.fileSW, destName]; [] ← WritePartial[attributes]; Put.Text[ILT.toolData.fileSW, "... "L]; IF debug THEN { Put.LongDecimal[ ILT.toolData.fileSW, attributes.totalSizeInBytes]; Process.Pause[Process.SecondsToTicks[5]]; }; IF attributes.size # 0 THEN Floppy.CopyToPilotFile[ floppyFile: fH, pilotFile: file, firstFloppyPage: AccessFloppy.leaderLength, firstPilotPage: SpecialMFile.LeaderPages[] + attributes.offset, count: attributes.size ! Floppy.Error => { Put.Line[ ILT.toolData.msgSW, "incompatibleSizes/Insufficient space for floppy file"L]; continue ← FALSE; Process.Pause[Process.SecondsToTicks[5]]; }]; Put.Line[ILT.toolData.fileSW, "copied"L]; --MFile.Release[mFile]; IF destVFN # NIL THEN FileName.FreeVFN[destVFN]; IF srcVFN # NIL THEN FileName.FreeVFN[srcVFN]; IF destName # NIL THEN FileName.FreeFilename[destName]; --EXITS return => NULL; END; --ReadOne; [volumeID, volumeOpen] ← ILT.GetVolumeID[ILT.toolData.volName]; [volSize, freePages] ← Volume.GetAttributes[volumeID]; [file, firstPage] ← OthelloOps.GetVolumeBootFile[ volumeID, hardMicrocode]; Put.Text[ILT.toolData.fileSW, "Creating file."L]; IF (created ← file = File.nullFile) THEN { file ← File.Create[ volumeID, freePages, FileTypes.tUntypedFile ! Volume.InsufficientSpace => { Put.Text[ILT.toolData.fileSW, "."L]; freePages ← freePages - 100; RETRY; }]; Put.CR[ILT.toolData.fileSW]; } ELSE { IF debug THEN { Put.Line[ILT.toolData.fileSW, "MakeUnbootable.."L]; --Process.Pause[Process.SecondsToTicks[10]]; }; OthelloOps.MakeUnbootable[ file, hardMicrocode, OthelloDefs.leaderPages]; }; WHILE pagesRemaining > 0 DO SELECT loopCnt FROM 1 => Put.Line[ ILT.toolData.fileSW, "Insert first (#1) floppy "L]; 2 => Put.Line[ ILT.toolData.fileSW, "Insert second (#2) floppy "L]; 3 => Put.Line[ ILT.toolData.fileSW, "Insert third (#3) floppy "L]; 4 => Put.Line[ ILT.toolData.fileSW, "Insert fourth (#4) floppy "L]; 5 => Put.Line[ ILT.toolData.fileSW, "Insert fifth (#5) floppy "L]; 6 => Put.Line[ ILT.toolData.fileSW, "Insert sixth (#6) floppy "L]; ENDCASE => Put.Line[ILT.toolData.fileSW, "Insert next floppy "L]; IF ~ILT.Confirm[] THEN {continue ← FALSE; EXIT; }; [v] ← OpenFloppy[]; IF ~opened THEN RETURN[FALSE]; IF String.Length[ILT.toolData.filePathName] # 0 THEN { Put.Text[ILT.toolData.fileSW, "Retrieving... "L]; Put.Line[ILT.toolData.fileSW, ILT.toolData.filePathName]; } ELSE { AccessFloppy.Close[ ! Floppy.Error => CONTINUE]; --ERROR Abort["Please enter source file name(s)."L]; Put.Line[ILT.toolData.msgSW, "Please enter source file name"L]; }; atSource ← 0; IF attributes = NIL THEN attributes ← z.NEW[ AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]]; IF String.Length[altName] # 0 THEN FixDirectory[@altName]; readName ← String.MakeString[z, 80]; nextFile ← GetNextFilename[]; IF nextFile = NIL THEN EXIT; String.AppendStringAndGrow[@readName, nextFile, z, 80]; [] ← Token.FreeTokenString[nextFile]; IF readName = NIL THEN EXIT; [nsName] ← NSString.StringFromMesaString[readName]; IF WildCards[readName] THEN { Put.Line[ILT.toolData.msgSW, "Wild Cards not allowed here"L]; continue ← FALSE; EXIT; }; [fFile, continue] ← FileLookUp[nsName]; IF ~continue THEN EXIT; IF firstTime THEN { pagesRemaining ← attributes.totalSize; firstTime ← FALSE; }; IF debug THEN { Put.Line[ILT.toolData.fileSW, "Floppy.CopyToPilotFile"L]; Put.Decimal[ILT.toolData.fileSW, AccessFloppy.leaderLength]; Put.CR[ILT.toolData.fileSW]; Put.LongDecimal[ ILT.toolData.fileSW, SpecialMFile.LeaderPages[]]; Put.CR[ILT.toolData.fileSW]; Put.Text[ILT.toolData.fileSW, " attributes.offset"L]; Put.LongDecimal[ILT.toolData.fileSW, attributes.offset]; Put.CR[ILT.toolData.fileSW]; Put.Text[ILT.toolData.fileSW, " attributes.size"L]; Put.LongDecimal[ILT.toolData.fileSW, attributes.size]; Put.CR[ILT.toolData.fileSW]; Process.Pause[Process.SecondsToTicks[5]]; }; [] ← ReadOne[attributes, fFile, NameFromAttributes[attributes]]; pagesRemaining ← pagesRemaining - attributes.size; Put.LongDecimal[ILT.toolData.fileSW, pagesRemaining]; Put.Line[ILT.toolData.fileSW, " pages more"L]; IF debug THEN { Put.Line[ILT.toolData.fileSW, "UserInput.UserAbort"L]; --Process.Pause[Process.SecondsToTicks[5]]; }; IF UserInput.UserAbort[ILT.windowHandle] THEN { Put.Text[ILT.toolData.fileSW, "User Abort! "L]; Put.Line[ILT.toolData.fileSW, "Aborted"L]; UserInput.ResetUserAbort[ILT.windowHandle]; continue ← FALSE; }; IF debug THEN { Put.Line[ILT.toolData.fileSW, "z.FREE"L]; --Process.Pause[Process.SecondsToTicks[5]]; }; z.FREE[@attributes]; IF debug THEN { Put.Line[ILT.toolData.fileSW, "String.FreeString"L]; --Process.Pause[Process.SecondsToTicks[5]]; }; IF readName # NIL THEN String.FreeString[z, readName]; IF altName # NIL THEN String.FreeString[z, altName]; IF debug THEN { Put.Line[ILT.toolData.fileSW, "AccessFloppy.Close"L]; --Process.Pause[Process.SecondsToTicks[5]]; }; AccessFloppy.Close[]; IF ~continue THEN EXIT; loopCnt ← loopCnt + 1; ENDLOOP; IF continue THEN { ILT.ExpandVMemSize[file, volumeID]; ILT.SetupBootFile[file, volumeID]; }; RETURN[continue]; END; --FloppyReadSysout FloppyStuff: PUBLIC PROCEDURE = BEGIN aborted: BOOLEAN ← FALSE; IF toolData = NIL THEN toolData ← Heap.systemZone.NEW[Data ← []]; IF attributes = NIL THEN attributes ← z.NEW[ AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]]; IF debug THEN { Put.Line[ILT.toolData.fileSW, "FloppyStuff...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; floppyWH ← MakeTool[]; BEGIN ENABLE { Abort => {Put.Line[toolData.fileSW, s]; aborted ← TRUE; }; AccessFloppy.Error => { Put.Text[toolData.fileSW, "unexpected "L]; WriteAccessFloppyError[type]; Put.CR[toolData.fileSW]; aborted ← TRUE; }; AccessFloppy.InconsistentFile => { Put.Line[toolData.fileSW, "AccessFloppy.InconsistentFile"L]; aborted ← TRUE; }; AccessFloppy.InvalidVersion => { Put.Line[toolData.fileSW, "AccessFloppy.InvalidVersion"L]; aborted ← TRUE; }; AccessFloppy.NoRoomForClientData => { Put.Line[toolData.fileSW, "AccessFloppy.NoRoomForClientData"L]; aborted ← TRUE; }; Floppy.Error => { IF error = writeInhibited THEN Put.Line[toolData.fileSW, "Floppy is write protected"L] ELSE { Put.Text[toolData.fileSW, "unexpected "L]; WriteFloppyError[error]; Put.CR[toolData.fileSW]; }; aborted ← TRUE; }; }; END; END; --FloppyStuff << FloppyToDisk: PROC = BEGIN handle: MStream.Handle ← NIL; releaseData: MStream.ReleaseData ← []; FOR current: Floppy.FileHandle ← Floppy.GetNextFile[nullFile].nextFile, Floppy.GetNextFile[current].nextFile WHILE current # nullFile DO scratchName: LONG STRING ← [120]; IF debug THEN { Put.Line[toolData.fileSW, ".Floppy.GetFileAttributes...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; [toolData.current.size, toolData.current.type] ← Floppy.GetFileAttributes[current]; IF debug THEN { Put.Line[ toolData.fileSW, ".AccessFloppy.GetFileAttributes...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; AccessFloppy.GetAttributes[current, attributes]; IF debug THEN { Put.Line[toolData.fileSW, ".String.MakeString...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; toolData.current.file ← String.MakeString[ z, AccessFloppy.maxNameLength]; IF debug THEN { Put.Line[ toolData.fileSW, "AccessFloppyUtil.MesaStringFromAttributes...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; MesaStringFromAttributes[attributes, toolData.current.file]; IF debug THEN { Put.Line[toolData.fileSW, ".String.AppendString...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; String.AppendString[scratchName, toolData.current.file]; String.AppendString[scratchName, ".Scratch$"L]; IF debug THEN { Put.Line[toolData.fileSW, ".String.AppendString...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; handle ← MStream.ReadWrite[ name: scratchName, release: releaseData, type: MFile.Type[unknown]]; attributes.size ← toolData.current.size; -- modify size to actual file size. IF debug THEN { Put.Line[toolData.fileSW, "RetrieveFilePiece..."L]; Process.Pause[Process.SecondsToTicks[5]]; }; RetrieveFilePiece[current, handle, attributes]; toolData.numberOfFiles ← toolData.numberOfFiles + 1; toolData.current ← toolData.current.next ← z.NEW[NextFile ← []]; IF debug THEN { Put.Line[toolData.fileSW, "handle.delete..."L]; Process.Pause[Process.SecondsToTicks[5]]; }; handle.delete[handle]; ENDLOOP; -- will have current points to a NextFile[NIL, NIL]. END; -- FloppyToDisk. >> FloppyWrite: PUBLIC PROCEDURE [name: LONG STRING] = BEGIN attributes: AccessFloppy.Attributes ← NIL; altName, switches: LONG STRING ← NIL; fileType: File.Type ← FileTypes.tUntypedFile; mFile: MFile.Handle; --[] ← AccessFloppy.Open[! AccessFloppy.Error => ERROR Abort["Can't open floppy"L]]; [vH] ← OpenFloppy[]; IF ~opened THEN RETURN; -- DO BEGIN ENABLE UNWIND => { IF mFile # NIL THEN MFile.Release[mFile]; Heap.systemZone.FREE[@attributes]; AccessFloppy.Close[ ! Floppy.Error => CONTINUE]}; fFile: Floppy.FileHandle; failed: BOOLEAN ← FALSE; mFileError: MFile.ErrorCode; offset, length: CARDINAL; IF attributes = NIL THEN attributes ← Heap.systemZone.NEW[ AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]]; mFile ← NIL; IF name = NIL AND switches = NIL THEN GOTO done; [offset, length] ← ParsePartial[ name ! Token.SyntaxError => { Put.Line[ILT.toolData.fileSW, name]; Put.Line[ILT.toolData.fileSW, " - bad name syntax"L]; --SetOutcome[error]; --LOOP; }]; IF switches = NIL THEN altName ← name; mFile ← MFile.ReadOnly[ name, [] ! MFile.Error => {mFileError ← code; CONTINUE}]; IF mFile = NIL THEN SELECT mFileError FROM noSuchFile => { Put.Line[ILT.toolData.msgSW, " not found"L]; --SetOutcome[error]; --LOOP; }; conflictingAccess => { Put.Line[ILT.toolData.msgSW, " conflicting access"L]; --SetOutcome[error]; --LOOP; }; ENDCASE => ERROR Abort[" unexpected MFile.Error"L]; MakeAttributes[mFile, altName, attributes, fileType]; attributes.offset ← offset; attributes.size ← MIN[length, attributes.totalSize - offset]; --Put.Text[ILT.toolData.msgSW, name]; [] ← WritePartial[attributes]; Put.Text[ILT.toolData.msgSW, "... "L]; Put.Text[ILT.toolData.msgSW, "copying to "L]; Put.Text[ILT.toolData.msgSW, altName]; Put.Text[ILT.toolData.msgSW, "... "L]; IF debug THEN Process.Pause[Process.SecondsToTicks[10]]; fFile ← AccessFloppy.CreateFile[ attributes ! AccessFloppy.Error => IF type = nameInUse THEN {failed ← TRUE; CONTINUE}; Floppy.Error => SELECT error FROM fileListFull => ERROR Abort["too many files"L]; insufficientSpace => ERROR Abort["floppy is full"L]; ENDCASE]; IF failed THEN { Put.Line[ ILT.toolData.msgSW, "floppy file already exists - skipped"L]; Process.Pause[Process.SecondsToTicks[5]]; --SetOutcome[error]; } ELSE { IF attributes.size # 0 THEN Floppy.CopyFromPilotFile[ floppyFile: fFile, pilotFile: SpecialMFile.GetCapaWithAccess[mFile], firstFloppyPage: AccessFloppy.leaderLength, firstPilotPage: SpecialMFile.LeaderPages[] + offset, count: attributes.size]; Put.Line[ILT.toolData.msgSW, "copied"L]}; Process.Pause[Process.SecondsToTicks[5]]; MFile.Release[mFile]; --ENDLOOP; EXITS done => NULL; END; Heap.systemZone.FREE[@attributes]; AccessFloppy.Close[]; END; -- FloppyWrite FormatAndOpen: PROC [] RETURNS [skip: BOOLEAN] = BEGIN density: Floppy.Density ← double; sides: Floppy.Sides ← two; nFile: CARDINAL ← 2 * toolData.numberOfFiles + 1; ok: BOOLEAN; skip ← TRUE; Put.Line[toolData.fileSW, "Please Remove Floppy Disk, are you ready? "L]; IF ~ILT.Confirm[] THEN RETURN; Put.Line[toolData.fileSW, "format..."L]; [ok] ← FloppyFormat[nFile, toolData.floppyName, sides, density]; IF ~ok THEN {CleanUp; RETURN}; Put.Line[toolData.fileSW, "...ted"L]; vH ← AccessFloppy.Open[]; nullFile ← [vH, Floppy.nullFileID]; skip ← FALSE; END; -- FormatAndOpen. FormSWDeleteProc: FormSW.ProcType = BEGIN IF debug THEN { Put.Line[ILT.toolData.fileSW, "FormSWDeleteProc...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; [] ← FloppyDelete[toolData.pattern]; END; --FormSWDeleteProc FormSWDuplicateProc: FormSW.ProcType = BEGIN IF debug THEN { Put.Line[toolData.fileSW, "FormSWDuplicateProc...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; Put.Line[toolData.fileSW, "to be implemented"L]; FloppyDuplicate; END; --FormSWDuplicateProc FormSWFormatProc: FormSW.ProcType = BEGIN ok: BOOLEAN; IF debug THEN { Put.Line[toolData.fileSW, "FormSWFormatProc...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; [ok] ← FloppyFormat[256, toolData.floppyName, default, default]; END; --FormSWFormatProc FormSWInfoProc: FormSW.ProcType = BEGIN IF debug THEN { Put.Line[toolData.fileSW, "FormSWInfoProc...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; FloppyInfo; END; --FormSWInfoProc FormSWListProc: FormSW.ProcType = BEGIN IF debug THEN { Put.Line[toolData.fileSW, "FormSWListProc...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; FloppyList; END; --FormSWListProc FormSWReadProc: FormSW.ProcType = BEGIN IF debug THEN { Put.Line[toolData.fileSW, "FormSWReadProc...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; Put.Line[toolData.fileSW, "to be implemented"L]; END; --FormSWReadProc FormSWWriteProc: FormSW.ProcType = BEGIN IF debug THEN { Put.Line[toolData.fileSW, "FormSWWriteProc...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; Put.Line[toolData.fileSW, "to be implemented"L]; FloppyWrite[toolData.pattern]; END; --FormSWWriteProc FormSWQuitProc: FormSW.ProcType = BEGIN IF toolData # NIL THEN BEGIN Tool.Destroy[floppyWH]; Heap.systemZone.FREE[@toolData]; END; END; --FormSWQuitProc FormSWVolHintsProc: FormSW.MenuProcType = BEGIN RETURN[ hints: DESCRIPTOR[ @ILT.toolData.volHints[0], ILT.toolData.volHints.length], freeHintsProc: HintsNoLongerBusy, replace: TRUE]; END; GetNextFilename: PUBLIC PROC RETURNS [fn: LONG STRING ← NIL] = BEGIN MyGet: PROC [Token.Handle] RETURNS [c: CHARACTER] = BEGIN IF atSource >= ILT.toolData.filePathName.length THEN c ← Ascii.NUL ELSE BEGIN c ← ILT.toolData.filePathName[atSource]; atSource ← atSource + 1; END; END; getObject: Token.Object ← [getChar: MyGet, break: Ascii.NUL]; IF atSource >= ILT.toolData.filePathName.length THEN RETURN[NIL]; fn ← Token.Item[h: @getObject, temporary: FALSE]; END; --GetNextFilename HintsNoLongerBusy: FormSW.FreeHintsProcType = BEGIN END; MesaStringFromAttributes: PUBLIC PROC [ attris: AccessFloppy.Attributes, name: LONG STRING] = BEGIN -- should protect against a bogus attris (i.e., one from a non AccessFloppy file). name.length ← 0; IF attris = NIL THEN RETURN WITH ERROR AccessFloppy.Error[invalidParameter]; IF attris.length > attris.maxlength THEN -- invalidAttributes? RETURN WITH ERROR AccessFloppy.Error[invalidParameter]; IF name.maxlength < attris.length THEN RETURN WITH ERROR AccessFloppy.Error[invalidParameter]; IF debug THEN { Put.Line[toolData.fileSW, "Inline.LongCOPY...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; [] ← Inline.LongCOPY[ to: @name.text, nwords: attris.length / 2, from: @attris.name]; name.length ← attris.length; IF name.length # 0 THEN -- pick up odd character. name[name.length - 1] ← LOOPHOLE[attris.name[name.length - 1]]; END; -- MesaStringFromAttributes. MakeAttributes: PROCEDURE [ file: MFile.Handle, name: LONG STRING, attributes: AccessFloppy.Attributes, type: File.Type] = BEGIN attributes.version ← AccessFloppy.currentVersion; attributes.type ← type; attributes.lastWrittenDate ← Time.Current[]; attributes.name ← ALL[0]; attributes.clientDataLength ← 2; attributes.clientData[0] ← dataVersion; [length: attributes.totalSizeInBytes, create: attributes.createDate, type: attributes.clientData[1]] ← MFile.GetProperties[file]; attributes.totalSize ← PagesFromBytes[attributes.totalSizeInBytes]; attributes.size ← attributes.totalSize; attributes.length ← MIN[name.length, AccessFloppy.maxNameLength]; FOR i: CARDINAL IN [0..attributes.length) DO attributes.name[i] ← LOOPHOLE[name[i]]; ENDLOOP END; --MakeAttributes MakeCommands: FormSW.ClientItemsProcType = BEGIN OPEN FormSW; tabs: ARRAY [0..5) OF CARDINAL ← [0, 20, 40, 60, 70]; nItems: CARDINAL = 8; items ← AllocateItemDescriptor[nItems]; items[0] ← CommandItem[ tag: "Info"L, place: newLine, proc: FormSWInfoProc]; items[1] ← CommandItem[tag: "List"L, proc: FormSWListProc]; items[2] ← CommandItem[tag: "Read"L, proc: FormSWReadProc]; items[3] ← CommandItem[tag: "Write"L, proc: FormSWWriteProc]; items[4] ← CommandItem[ tag: "Format"L, place: newLine, proc: FormSWFormatProc]; items[5] ← CommandItem[tag: "Delete"L, proc: FormSWDeleteProc]; items[6] ← CommandItem[tag: "Duplicate"L, proc: FormSWDuplicateProc]; items[7] ← 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 = 3; items ← AllocateItemDescriptor[nItems]; nVols ← ILT.ListLogicalVolumes[]; String.Copy[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[ @toolData.volName, ILT.toolData.volHints[i], Heap.systemZone]; EXIT; END; ENDLOOP; items[0] ← StringItem[ tag: "Source Volume"L, place: newLine, string: @toolData.volName, inHeap: TRUE, menuProc: FormSWVolHintsProc]; items[1] ← StringItem[ tag: "Pattern"L, string: @toolData.pattern, inHeap: TRUE]; items[2] ← StringItem[ tag: "Floppy Name"L, string: @toolData.floppyName, place: newLine, inHeap: TRUE]; SetTagPlaces[items, DESCRIPTOR[tabs], FALSE]; RETURN[items, TRUE] END; --MakeParams MakeSWs: Tool.MakeSWsProc = BEGIN addresses: ARRAY [0..4) OF ToolDriver.Address; logName: STRING ← [20]; IF debug THEN { Put.Line[ILT.toolData.fileSW, "MakeSWs...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; Tool.UnusedLogName[unused: logName, root: "FloppyOptions.log"L]; toolData.msgSW ← Tool.MakeMsgSW[window: window, lines: 2]; toolData.paramSW ← Tool.MakeFormSW[window: window, formProc: MakeParams]; toolData.commandSW ← Tool.MakeFormSW[ window: window, formProc: MakeCommands]; --note: logName is compulsory, else it bombs toolData.fileSW ← Tool.MakeFileSW[window: window, name: logName]; --Supervisor.AddDependency[client: agent, implementor: Event.toolWindow]; -- do the ToolDriver stuff addresses ← [ [name: "msgSW"L, sw: toolData.msgSW], --[name: "formSW"L, sw: toolData.formSW], [name: "ParamSW"L, sw: toolData.paramSW], [ name: "CmdSW"L, sw: toolData.commandSW], [ name: "fileSW"L, sw: toolData.fileSW]]; ToolDriver.NoteSWs[ tool: "FloppyOptions"L, subwindows: DESCRIPTOR[addresses]]; END; --MakeSWs MakeTool: PROCEDURE RETURNS [wh: Window.Handle] = BEGIN heraldName: STRING ← [80]; String.AppendString[heraldName, "XSIS:Xerox Floppy Option"L]; --String.AppendString[heraldName, " of "L]; --Time.Append[heraldName, Time.Unpack[Runtime.GetBcdTime[]]]; --heraldName.length ← heraldName.length - 3; --String.AppendString[heraldName, " on Pilot Version "L]; --Version.Append[heraldName]; RETURN[ Tool.Create[ makeSWsProc: MakeSWs, initialState: default, --clientTransition: Transit, name: heraldName]]; --initialBox: [ --place: sw.BitmapPlace[[10, hisBox.dims.h]], --dims: [hisBox.dims.w - 20, 180]]]; END; --MakeTool NameFromAttributes: PROCEDURE [attributes: AccessFloppy.Attributes] RETURNS [LONG STRING] = INLINE {RETURN[LOOPHOLE[@attributes.length]]}; OpenFloppy: PROCEDURE [] RETURNS [v: Floppy.VolumeHandle] = BEGIN IF debug THEN { Put.Line[ILT.toolData.fileSW, "OpenFloppy...."L]; Process.Pause[Process.SecondsToTicks[5]]; }; opened ← TRUE; v ← AccessFloppy.Open[ ! Floppy.Error => SELECT error FROM notReady => { Put.Line[ILT.toolData.msgSW, "Floppy Not Closed"L]; IF debug THEN Process.Pause[Process.SecondsToTicks[10]]; GOTO noGood; }; invalidFormat => { Put.Line[ ILT.toolData.msgSW, "Invalid Floppy Format"L]; GOTO noGood; }; needsScavenging => { Put.Line[ ILT.toolData.msgSW, "Floppy Needs Scavenging"L]; GOTO noGood; }; ENDCASE]; EXITS noGood => opened ← FALSE; END; -- OpenFloppy ParsePartial: PROCEDURE [name: LONG STRING] RETURNS [offset: CARDINAL ← 0, length: CARDINAL ← LAST[CARDINAL]] = BEGIN h: Token.Handle; i: CARDINAL; IF name = NIL THEN RETURN; FOR i IN [1..name.length) DO IF name[i] = '[ THEN EXIT; REPEAT FINISHED => RETURN ENDLOOP; h ← Token.StringToHandle[name, i + 1]; BEGIN ENABLE UNWIND => [] ← Token.FreeStringHandle[h]; offset ← Token.Decimal[h]; SELECT h.break FROM '. => IF h.getChar[h] = '. THEN length ← Token.Decimal[h] - offset + 1 ELSE ERROR Token.SyntaxError[NIL]; '! => length ← Token.Decimal[h]; '] => NULL; ENDCASE => ERROR Token.SyntaxError[NIL]; END; name.length ← i; [] ← Token.FreeStringHandle[h]; END; --ParsePartial PagesFromBytes: PROCEDURE [bytes: LONG CARDINAL] RETURNS [LONG CARDINAL] = BEGIN RETURN[ (bytes + Environment.bytesPerPage - 1) / Environment.bytesPerPage]; END; --PagesFromBytes PutVolumeName: PROCEDURE [] = BEGIN Put.Text[toolData.fileSW, "Volume = "L]; Put.LongString[toolData.fileSW, toolData.volName]; Put.CR[toolData.fileSW]; END; --PutVolumeName << RetrieveFilePiece: PROC [ floppyFile: Floppy.FileHandle, mStream: MStream.Handle, attributes: AccessFloppy.Attributes] = BEGIN mFile: MFile.Handle ← NIL; block: Environment.Block; bufferSizeInBytes, bytesRemaining, bytesToRead, bytesTransfered: AccessFloppy.LengthInBytes; start, pagesToRead: File.PageNumber; bytesTransfered ← 0; -- starting page number of the floppy file, page count of the floppy file, and byte count of the floppy file. start ← 0; bytesRemaining ← attributes.size*Environment.bytesPerPage; bufferSizeInBytes ← bufferSize*Environment.bytesPerPage; -- set attributes mFile ← MStream.GetFile[mStream]; MFile.SetTimes[ file: mFile, create: attributes.createDate, write: attributes.lastWrittenDate]; MFile.SetType[mFile, MFile.Type[binary]]; MStream.SetLength[mStream, bytesRemaining]; -- set up block block.blockPointer ← Space.LongPointer[spaceHandle]; block.startIndex ← 0; --copy as many chunks of the standard buffer size as possible..... UNTIL bytesRemaining = 0 DO bytesToRead ← MIN[bytesRemaining, bufferSizeInBytes]; pagesToRead ← PagesFromBytes[bytesToRead]; Floppy.Read[floppyFile, start, pagesToRead, block.blockPointer]; block.stopIndexPlusOne ← Inline.LowHalf[bytesToRead]; mStream.put[mStream, block, FALSE]; start ← start + pagesToRead; bytesTransfered ← bytesTransfered + bytesToRead; bytesRemaining ← bytesRemaining - bytesToRead; ENDLOOP; END; -- RetrieveFilePiece. StoreFilePiece: PROC [ mStream: MStream.Handle, floppyFile: Floppy.FileHandle, size: File.PageNumber] = BEGIN -- store data from disk to floppy block: Environment.Block; bufferSizeInBytes, bytesRemaining, bytesToWrite, bytesTransfered: AccessFloppy.LengthInBytes; start, pagesToWrite: File.PageNumber; why: Stream.CompletionCode ← normal; bytesTransfered ← 0; -- starting page number of the floppy file, page count of the floppy file, and byte count of the floppy file. start ← 0; bytesRemaining ← (size*Environment.bytesPerPage); bufferSizeInBytes ← bufferSize*Environment.bytesPerPage; -- set up block block.blockPointer ← Space.LongPointer[spaceHandle]; block.startIndex ← 0; bytesToWrite ← bytesRemaining; --copy as many chunks of the standard buffer size as possible..... UNTIL bytesRemaining = 0 OR why = endOfStream DO bytesToWrite ← MIN[bytesRemaining, bufferSizeInBytes]; block.stopIndexPlusOne ← Inline.LowHalf[bytesToWrite]; [bytesToWrite, why, ] ← mStream.get[ mStream, block, Stream.defaultInputOptions]; pagesToWrite ← PagesFromBytes[bytesToWrite]; Floppy.Write[floppyFile, start, pagesToWrite, block.blockPointer]; start ← start + pagesToWrite; bytesTransfered ← bytesTransfered + bytesToWrite; bytesRemaining ← bytesRemaining - bytesToWrite; ENDLOOP; END; -- StoreFilePiece. >> Transit: ToolWindow.TransitionProcType = BEGIN SELECT TRUE FROM old = inactive => BEGIN IF toolData = NIL THEN toolData ← Heap.systemZone.NEW[Data ← []]; IF attributes = NIL THEN attributes ← z.NEW[ AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]]; --UserInput.ResetUserAbort[window]; --data.logSW ← window; -- data.window ← ToolWindow.WindowForSubwindow[window]; -- data.ttyWindow ← TTYSW.GetTTYHandle[window]; -- destroy ← FALSE; active ← TRUE; END; new = inactive => BEGIN IF toolData # NIL THEN BEGIN FormSW.Destroy[toolData.paramSW]; FormSW.Destroy[toolData.commandSW]; Heap.systemZone.FREE[@toolData]; END; IF attributes # NIL THEN { z.FREE[@attributes]; attributes ← NIL}; --ToolDriver.RemoveSWs[tool: "LispTool"L]; active ← FALSE; END; ENDCASE; END; -- Transit WriteAccessFloppyError: PROCEDURE [type: AccessFloppy.ErrorType] = BEGIN Put.Text[toolData.fileSW, "AccessFloppy.Error["L]; Put.Text[ toolData.fileSW, SELECT type FROM attributesNotAllowed => "attributesNotAllowed"L, fileNotFound => "fileNotFound"L, invalidParameter => "invalidParameter"L, nameInUse => "nameInUse"L, volumeNotOpen => "volumeNotOpen"L, ENDCASE => "?"L]; Put.Text[toolData.fileSW, "]"L]; END; --WriteAccessFloppyError WriteFloppyError: PROCEDURE [error: Floppy.ErrorType] = BEGIN Put.Text[toolData.fileSW, "Floppy.Error["L]; Put.Text[ toolData.fileSW, SELECT error FROM badDisk => "badDisk"L, badSectors => "badSectors"L, endOfFile => "endOfFile"L, fileListFull => "fileListFull"L, fileNotFound => "fileNotFound"L, hardwareError => "hardwareError"L, incompatibleSizes => "incompatibleSizes"L, invalidFormat => "invalidFormat"L, invalidPageNumber => "invalidPageNumber"L, invalidVolumeHandle => "invalidVolumeHandle"L, insufficientSpace => "insufficientSpace"L, needsScavenging => "needsScavenging"L, noSuchDrive => "noSuchDrive"L, notReady => "notReady"L, onlyOneSide => "onlyOneSide"L, onlySingleDensity => "onlySingleDensity"L, initialMicrocodeSpaceNotAvailable => "initialMicrocodeSpaceNotAvailable"L, stringTooShort => "stringTooShort"L, volumeNotOpen => "volumeNotOpen"L, writeInhibited => "writeInhibited"L, zeroSizeFile => "zeroSizeFile"L, ENDCASE => "?"L]; Put.Line[toolData.fileSW, "]"L]; END; --WriteFloppyError -- used by both ILT and subwindows WritePartial: PROCEDURE [attributes: AccessFloppy.Attributes] RETURNS [chars: CARDINAL ← 0] = BEGIN CountedNumber: PROCEDURE [n: LONG CARDINAL] RETURNS [CARDINAL] = { s: STRING = [12]; String.AppendLongDecimal[s, n]; Put.Text[ILT.toolData.fileSW, s]; RETURN[s.length]}; IF attributes.offset # 0 OR attributes.size # attributes.totalSize THEN { chars ← 4; Put.Char[ILT.toolData.fileSW, '[]; chars ← chars + CountedNumber[attributes.offset]; -- Write[".."L]; chars ← chars + CountedNumber[attributes.offset + attributes.size - 1]; Put.Char[ILT.toolData.fileSW, ']]}; END; --WritePartial << WriteFiles: PROCEDURE [gSwitches: LONG STRING, h: Exec.Handle] = BEGIN attributes: AccessFloppy.Attributes ← NIL; name, altName, switches: LONG STRING ← NIL; fileType: File.Type ← FileTypes.tUntypedFile; mFile: MFile.Handle; Write: Format.StringProc = Exec.OutputProc[h]; IF gSwitches # NIL THEN fileType ← [ String.StringToNumber[ gSwitches ! String.InvalidNumber => CONTINUE]]; [] ← AccessFloppy.Open[ ! AccessFloppy.Error => ERROR Abort["Can't open floppy"L]]; DO ENABLE UNWIND => { IF altName # name THEN altName ← Exec.FreeTokenString[altName]; name ← Exec.FreeTokenString[name]; switches ← Exec.FreeTokenString[switches]; IF mFile # NIL THEN MFile.Release[mFile]; Heap.systemZone.FREE[@attributes]; AccessFloppy.Close[ ! Floppy.Error => CONTINUE]}; fFile: Floppy.FileHandle; failed: BOOLEAN ← FALSE; mFileError: MFile.ErrorCode; offset, length: CARDINAL; IF attributes = NIL THEN attributes ← Heap.systemZone.NEW[ AccessFloppy .AttributesRecord[AccessFloppy.maxDataSize]]; mFile ← NIL; IF altName # name THEN altName ← Exec.FreeTokenString[altName]; name ← Exec.FreeTokenString[name]; switches ← Exec.FreeTokenString[switches]; [name, switches] ← Exec.GetToken[h]; IF name = NIL AND switches = NIL THEN EXIT; [offset, length] ← ParsePartial[ name ! Token.SyntaxError => { Write[name]; Format.Line[Write, " - bad name syntax"L]; SetOutcome[error]; LOOP}]; IF switches # NIL AND switches.length # 0 THEN SELECT switches[0] FROM 's => { switches ← Exec.FreeTokenString[switches]; [altName, switches] ← Exec.GetToken[h]}; 't => { fileType ← [ String.StringToNumber[ name ! String.InvalidNumber => CONTINUE]]; switches ← Exec.FreeTokenString[switches]; LOOP}; ENDCASE ELSE altName ← name; mFile ← MFile.ReadOnly[ name, [] ! MFile.Error => {mFileError ← code; CONTINUE}]; IF mFile = NIL THEN SELECT mFileError FROM noSuchFile => { Format.Line[Write, " not found"L]; SetOutcome[error]; LOOP}; conflictingAccess => { Format.Line[Write, " conflicting access"L]; SetOutcome[error]; LOOP}; ENDCASE => ERROR Abort[" unexpected MFile.Error"L]; MakeAttributes[mFile, altName, attributes, fileType]; attributes.offset ← offset; attributes.size ← MIN[length, attributes.totalSize - offset]; Write[name]; [] ← WritePartial[attributes]; Write["... "L]; Write["copying to "L]; Write[altName]; Write["... "L]; fFile ← AccessFloppy.CreateFile[ attributes ! AccessFloppy.Error => IF type = nameInUse THEN {failed ← TRUE; CONTINUE}; Floppy.Error => SELECT error FROM fileListFull => ERROR Abort["too many files"L]; insufficientSpace => ERROR Abort["floppy is full"L]; ENDCASE]; IF failed THEN { Format.Line[Write, "floppy file already exists - skipped"L]; SetOutcome[error]} ELSE { IF attributes.size # 0 THEN Floppy.CopyFromPilotFile[ floppyFile: fFile, pilotFile: SpecialMFile.GetCapaWithAccess[mFile], firstFloppyPage: AccessFloppy.leaderLength, firstPilotPage: SpecialMFile.LeaderPages[] + offset, count: attributes.size]; Format.Line[Write, "copied"L]}; MFile.Release[mFile]; ENDLOOP; Heap.systemZone.FREE[@attributes]; AccessFloppy.Close[]; END; -- WriteFiles >> WildCards: PROCEDURE [pattern: LONG STRING] RETURNS [BOOLEAN] = BEGIN IF pattern # NIL THEN FOR i: CARDINAL IN [0..pattern.length) DO SELECT pattern[i] FROM '*, '# => RETURN[TRUE]; ENDCASE; ENDLOOP; IF debug THEN { Put.Line[ILT.toolData.fileSW, " NOT WildCards"L]; Process.Pause[Process.SecondsToTicks[5]]; }; RETURN[FALSE]; END; END.