// IfsScavDEdit.bcpl -- a simple disk editor // Copyright Xerox Corporation 1979 // Last modified December 22, 1979 3:14 PM by Boggs get "AltoFileSys.d" get "Streams.d" get "Disks.d" get "Tfs.d" external [ // outgoing procedures DiskEditor // incoming procedures OpenDisk; CloseDisk; VirtualDiskDA InitializeDiskCBZ; GetDiskCb; DoDiskCommand Allocate; Free; Resets; Puts; Gets; Closes Ws; PutTemplate; EraseBits; CharWidth ShowDisplayStream; CreateDisplayStream ScavConfirm; UnsnarfBuffer PrintDiskError; SysErr // incoming statics dsp; keys; sysZone; sysFont; pass ] static [ editDisk; label; data; number; address numberTyped; pageOpen; cellOpen; pageDirty ] //---------------------------------------------------------------------------- let DiskEditor(buffPtr, numBuffs) be //---------------------------------------------------------------------------- [ pass = 0 editDisk = OpenDisk("*NWhat disk would you like to edit? ", 0, true, false) if editDisk eq 0 then [ for i = 0 to numBuffs-1 do UnsnarfBuffer(buffPtr+i*256) return ] // replace the normal tiny display with a giant display let normalDsp = dsp>>ST.par1 ShowDisplayStream(normalDsp, DSdelete) dsp>>ST.par1 = CreateDisplayStream(800/((sysFont!-2) & -2), buffPtr, 256*numBuffs) ShowDisplayStream(dsp>>ST.par1, DSalone) let lenData = 1 lshift editDisk>>DSK.lnPageSize label = Allocate(sysZone, 10) data = Allocate(sysZone, lenData) pageOpen = false address, number = 0, 0 Puts(dsp, $*N) switchon GetNumber() into [ case $/: [ address = number ExaminePage(not numberTyped) endcase ] case $*L: [ test numberTyped ifso Oop() ifnot [ address = address +1 ExaminePage(true) ] endcase ] case $↑: [ test numberTyped ifso Oop() ifnot [ address = address -1 ExaminePage(true) ] endcase ] case $\: [ test numberTyped % not pageOpen ifso Oop() ifnot [ address = VirtualDiskDA(editDisk, lv label>>DL.previous) ExaminePage(true) ] endcase ] // DiskEditor (cont'd) case $L: case $l: [ test numberTyped % not pageOpen ifso Oop() ifnot EditPage(label, 10) endcase ] case $D: case $d: [ test numberTyped % not pageOpen ifso Oop() ifnot EditPage(data, lenData) endcase ] case $Q: case $q: [ if ScavConfirm("*NQuit Disk editor") break endcase ] case $*N: [ Puts(dsp, $*N) pageOpen = false endcase ] case $*177: [ Ws(" XXX"); endcase ] default: [ Oop(); endcase ] ] repeat Free(sysZone, label) Free(sysZone, data) CloseDisk(editDisk) Closes(dsp>>ST.par1) dsp>>ST.par1 = normalDsp ShowDisplayStream(dsp>>ST.par1, DSalone) Puts(dsp, $*N) for i = 0 to numBuffs-1 do UnsnarfBuffer(buffPtr+i*256) ] //---------------------------------------------------------------------------- and GetNumber() = valof //returns terminating character //---------------------------------------------------------------------------- [ manifest maxStringChars = 7 //6 octal digits + minus sign let string = vec maxStringChars //1 char per word let count = 0 //chars in string let char = nil [ char = Gets(keys) switchon char into [ case $0 to $7: case $-: [ if (char eq $-) ? (count eq 0), (count ls maxStringChars) then [ Puts(dsp, char) count = count +1 string!count = char ] endcase ] case $*001: case $*010: //↑A, BS [ if count ne 0 then [ EraseBits(dsp>>ST.par1, -CharWidth(dsp>>ST.par1, string!count)) count = count -1 ] endcase ] case $*027: //↑W [ for i = count to 1 by -1 do EraseBits(dsp>>ST.par1, -CharWidth(dsp>>ST.par1, string!i)) count = 0 endcase ] case $*177: count = 0 //falls through default: break ] ] repeat numberTyped = count ne 0 if numberTyped then [ number = 0 let minus = false if string!1 eq $- then minus = true for i = minus? 2,1 to count do number = number lshift 3 + (string!i & 7) if minus then number = -number ] resultis char ] //---------------------------------------------------------------------------- and Oop() be [ Ws(" ?"); Resets(keys) ] //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- and ExaminePage(displayAddress) be //---------------------------------------------------------------------------- [ if displayAddress then PutTemplate(dsp, "*N$UO", address) Ws("/*T") if DETransferPage(DCreadLD) then [ PutTemplate(dsp, "FID $EUO;$UO, page number $UO, num chars $UO ", lv label>>DL.fileId, label!2, label>>DL.pageNumber, label>>DL.numChars) let previous = VirtualDiskDA(editDisk, lv label>>DL.previous) let next = VirtualDiskDA(editDisk, lv label>>DL.next) PutTemplate(dsp, "previous vda $UO, next vda $UO", previous, next) number = next pageOpen = true ] ] //---------------------------------------------------------------------------- and DETransferPage(action) = valof //---------------------------------------------------------------------------- [ if address eq eofDA then [ Oop() pageOpen = false resultis false ] let cbz = Allocate(sysZone, CBzoneLength) InitializeDiskCBZ(editDisk, cbz, 0, CBzoneLength, TransferRetry, lv TransferError) TransferRetry: let cb = GetDiskCb(editDisk, cbz) cb>>CB.AddrL = label DoDiskCommand(editDisk, cb, data, address, lv label>>DL.fileId, label>>DL.pageNumber, action) while @cbz>>CBZ.queueHead ne 0 do GetDiskCb(editDisk, cbz) Free(sysZone, cbz) pageOpen = action eq DCreadLD resultis true ] //---------------------------------------------------------------------------- and TransferError(nil, cb, errorCode) be //---------------------------------------------------------------------------- test errorCode eq ecUnRecovDiskError ifso PrintDiskError(cb) ifnot SysErr(0, errorCode, cb) //---------------------------------------------------------------------------- and EditPage(buffer, length) be //---------------------------------------------------------------------------- [ PutTemplate(dsp, "*NEdit $S*N", buffer eq label? "label","data") let diskAddress = address; address = 0 let diskNumber = number; number = 0 pageDirty = false cellOpen = false switchon GetNumber() into [ case $/: [ address = number ExamineCell(buffer, length, not numberTyped) endcase ] case $*N: [ DepositCell(buffer) Puts(dsp, $*N) endcase ] case $*L: [ if DepositCell(buffer) then [ address = address +1 ExamineCell(buffer, length, true) ] endcase ] case $↑: [ if DepositCell(buffer) then [ address = address -1 ExamineCell(buffer, length, true) ] endcase ] case $Q: case $q: [ if ScavConfirm("*NQuit page editor") break endcase ] case $*177: [ Ws(" XXX"); endcase ] default: [ Oop(); endcase ] ] repeat number = diskNumber address = diskAddress if pageDirty then if ScavConfirm("*NRewrite page?") then DETransferPage(DCwriteLD) Puts(dsp, $*N) ] //---------------------------------------------------------------------------- and ExamineCell(buffer, length, printAddress) = valof //---------------------------------------------------------------------------- [ if printAddress then PutTemplate(dsp, "*N$UO", address) if buffer eq label then Ws(selecton address into [ case 0: " = SN1 " case 1: " = SN2 " case 2: " = VN " case 3: " = PackID " case 4: " = numChars " case 5: " = PN " case 6: " = Prev cyl " case 7: " = Prev hd, sec " case 8: " = Next cyl " case 9: " = Next hd, sec " default: "" ]) Ws("/*T") if address ge length % address ls 0 then [ Oop() cellOpen = false resultis false ] PutTemplate(dsp, "$6UO*T", buffer!address) if buffer eq data then //also display as characters [ let left = buffer!address rshift 8 let right = buffer!address & 377b PutTemplate(dsp, "$3UO $3UO*T", left, right) PrintChar(left) PrintChar(right) ] number = buffer!address cellOpen = true resultis true ] //---------------------------------------------------------------------------- and PrintChar(char) be //---------------------------------------------------------------------------- [ if char ls 40b then PutTemplate(dsp, "↑$C", char+100b) if char ge 40b & char ls 176b then Puts(dsp, char) ] //---------------------------------------------------------------------------- and DepositCell(buffer) = valof //---------------------------------------------------------------------------- //Does nothing if no number was typed [ if numberTyped test cellOpen ifso [ buffer!address = number pageDirty = true ] ifnot [ Oop() resultis false ] cellOpen = false resultis true ]