DIRECTORY BasicTime USING [GMT], File USING [PageCount, PageNumber], NSExec USING [Error, ClientID, ExecProc, GetTTY, Handle, OutputHandle], NSString USING [AppendString, EqualStrings, FreeString, nullString, String, StringRep], PSCommand USING [DeleteFont, Error, FileProc, FontProc, GetPrintServiceStatus], PSExec USING [GetClientID], PSExecInternal USING [ExpandKeyAndPrint], PSExecMessages USING [Key], PSKMessages USING [GetHandle], PSState USING [StateHandle], TextInput USING [GetYesNo, nilYesNo, YesOrNo], TTY USING [Handle, Rubout], XFormat USING [Blanks, CR, Date, Handle, NSStringObject], XMessage USING [Get, Handle, Compose, StringArray]; PSExecEImpl: CEDAR PROGRAM IMPORTS NSExec, NSString, PSCommand, PSExec, PSExecInternal, PSKMessages, TextInput, TTY, XFormat, XMessage EXPORTS PSExecInternal SHARES NSString = BEGIN psClientID: NSExec.ClientID _ PSExec.GetClientID[]; nsDateAndTime: NSString.String _ NEW[TEXT[40]]; nsDateTimeObject: XFormat.Handle _ XFormat.NSStringObject[nsDateAndTime]; execMsgs: XMessage.Handle _ PSKMessages.GetHandle[exec]; InstallFromFloppy: PUBLIC NSExec.ExecProc = BEGIN ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit; tty: TTY.Handle _ NSExec.GetTTY[exec]; outputHandle: XFormat.Handle _ NSExec.OutputHandle[exec]; UserAbort: ERROR = CODE; SendDataError: ERROR = CODE; Answer: TYPE = {no, yes, cancel}; -- no: skip and go to next, yes: do it, cancel: abort it. CommandType: TYPE = { nullcommand, closeFile, createFile, loadAll, loadPiece, requestVolume}; Command: TYPE = REF CommandRecord; CommandRecord: TYPE = RECORD [ type: CommandType _ nullcommand, parameter: NSString.String _ NIL]; State: TYPE = REF StateRecord; StateRecord: TYPE = RECORD [ nameDest: NSString.String _ NSString.nullString, sizeDest: File.PageCount _ 0, -- target file size sizeMapped: File.PageCount _ 0, -- actual size, use to check consistency of the destination file. create: BOOLEAN _ FALSE, -- set by Create File close: BOOLEAN _ FALSE, -- set by CloseFile, AnounceEndOfData. version: Version _ new, -- *MT in case of Error for multi-floppies. length: CARDINAL _ 0, -- number of source file pieces piece: SEQUENCE maxlength: [0..LAST[CARDINAL]) OF FilePiece]; FilePiece: TYPE = RECORD [ vol: NSString.String _ NIL, base: File.PageNumber _ [0], size: File.PageCount _ 0]; Version: TYPE = {new, newer, same, older}; scriptName: NSString.String = "FontScript."; nFontsInstalled: CARDINAL _ 0; -- total number of fonts installed. nTestPatternsInstalled: CARDINAL _ 0; -- total number of test patterns installed. state: State _ NIL; scriptPointer: LONG POINTER _ NIL; scriptBuffer: LONG POINTER TO PACKED ARRAY [0..0) OF CHARACTER _ NIL; scriptBytesRead: LONG CARDINAL _ 0; scriptOffset: CARDINAL _ 0; -- Next char to read from script file. scriptCommand: Command _ NIL; --Points to command just read from script file. scriptInterpretationMode: BOOLEAN _ FALSE; -- Whether it is in the script - interpretation mode. firstPieceFile: BOOLEAN _ FALSE; --Whether piece file is first one for given font. waitChange: CARDINAL _ 3000; -- m sec. to wait for change floppy systemAbort: BOOLEAN _ FALSE; --Set to true in SendFloppyData if data stream is aborted by receiver; referenced in LoadPiece. continue: TextInput.YesOrNo _ TextInput.nilYesNo; psState: PSState.StateHandle _ PSCommand.GetPrintServiceStatus[]; BeginInterprete: PROCEDURE RETURNS [ok: BOOLEAN] = BEGIN -- Read Script File... map script file into VM endOfScript: BOOLEAN _ FALSE; ok _ TRUE; systemAbort _ FALSE; --global var state _ NEW[StateRecord[30--10--]]; --*MT state.nameDest _ NIL; state.sizeDest _ 0; state.sizeMapped _ 0; state.create _ FALSE; state.close _ FALSE; state.length _ 0; scriptInterpretationMode _ TRUE; scriptBytesRead _ 0; scriptOffset _ 0; scriptCommand _ NEW[CommandRecord]; IF endOfScript THEN GOTO Exit; EXITS Exit => NULL; END; -- BeginInterprete. CheckInstalledFont: PSCommand.FontProc = BEGIN END; --CheckInstalledFont EnterScriptMode: PROCEDURE = BEGIN continue: BOOLEAN _ TRUE; fontPackageName: NSString.String _ NSString.nullString; BEGIN ENABLE UNWIND => {IF fontPackageName # NSString.nullString THEN PSCommand.DeleteFont[fontPackageName !PSCommand.Error => CONTINUE]; FreeGlobalSpace[]}; continue _ BeginInterprete[]; IF continue AND state.nameDest # NIL THEN BEGIN END; EndInterprete[fontPackageName]; END; --Enable Clause and code END; --EnterScriptMode. EndInterprete: PROCEDURE [fontPackageName: NSString.String] = BEGIN IF state.create AND fontPackageName # NSString.nullString THEN FreeGlobalSpace[]; scriptInterpretationMode _ FALSE; END; -- EndInterprete. FreeGlobalSpace: PROCEDURE = TRUSTED BEGIN IF scriptPointer # NIL THEN scriptBuffer _ NIL; IF scriptCommand # NIL THEN BEGIN IF scriptCommand.parameter # NIL THEN NSString.FreeString[scriptCommand.parameter]; FREE[@scriptCommand]; END; IF state # NIL THEN BEGIN IF state.nameDest # NIL THEN NSString.FreeString[state.nameDest]; FOR i: CARDINAL IN [0..state.length) DO IF state.piece[i].vol # NIL THEN NSString.FreeString[state.piece[i].vol]; ENDLOOP; FREE[@state]; END; END; --FreeGlobalSpace CloseFile: PRIVATE PROCEDURE [str: NSString.String] RETURNS [ok: BOOLEAN] = BEGIN ok _ NSString.EqualStrings[str, state.nameDest]; END; -- CloseFile. CreateFileName: PROCEDURE [str: NSString.String] RETURNS [ok: BOOLEAN] = BEGIN ok _ TRUE; END; -- CreateFileName RequestVolume: PRIVATE PROCEDURE [str: NSString.String] RETURNS [ok: BOOLEAN] = BEGIN stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; maxRetry: CARDINAL = 3; i: CARDINAL _ 0; displayMsg: BOOLEAN _ TRUE; --Indicates whether to display canceled msg on abort. FOR i IN [0..maxRetry) DO outputHandle.CR[]; PSExecInternal.ExpandKeyAndPrint[exec, mFloppyPleaseRemoveAndInsert, stringArray]; ENDLOOP; END; -- RequestVolume UpdateSourceState: PROCEDURE = BEGIN END; -- UpdateSourceState WindowOverlay: PROCEDURE RETURNS [overlay: BOOLEAN] = BEGIN overlay _ FALSE; FOR i: CARDINAL IN [0..state.length) UNTIL overlay DO ENDLOOP; END; -- WindowOverlay DisplayDates: PROCEDURE RETURNS [version: Version _ new] = BEGIN stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; DisplayCurrentDate: PROCEDURE [createDate: BasicTime.GMT] = BEGIN nsDateAndTime.length _ 0; XFormat.Date[nsDateTimeObject, createDate]; --appends createDate to nsDataAndTime stringArray[0] _ nsDateAndTime; PSExecInternal.ExpandKeyAndPrint[exec, mRDFileCreated, stringArray]; END; --DisplayCurrentDate DisplayCurrentFontDate: PSCommand.FontProc = BEGIN DisplayCurrentDate[createDate]; END; --DisplayCurrentFontDate DisplayCurrentTestPatternDate: PSCommand.FileProc = BEGIN DisplayCurrentDate[createDate]; END; --DisplayCurrentTestPatternDate outputHandle.Blanks[10]; nsDateAndTime.length _ 0; stringArray[0] _ nsDateAndTime; PSExecInternal.ExpandKeyAndPrint[exec, mFloppyFileCreated, stringArray]; END; --DisplayDates Done: PROCEDURE = TRUSTED BEGIN END; -- Done Install: PROCEDURE = BEGIN pieceFile: BOOLEAN _ FALSE; nsPrompt: NSString.String _ NEW[NSString.StringRep[100]]; nTestPatternsInstalled _ nFontsInstalled _ 0; nsPrompt _ NSString.AppendString[nsPrompt, M[mInstallFromFloppy]]; IF TextInput.GetYesNo[ tty, nsPrompt, yes ! TTY.Rubout => GOTO Exit] = no THEN GOTO Exit; DO IF pieceFile THEN {EnterScriptMode[]; EXIT}; SELECT LoadConfirmation[] FROM no => LOOP; cancel => EXIT; ENDCASE; ENDLOOP; BEGIN -- " files installed from <1>." stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; outputHandle.Blanks[2]; PSExecInternal.ExpandKeyAndPrint[exec, mFilesInstalled, stringArray]; END; Done[]; EXITS Exit => {Done[]; continue _ no}; END; --Install IsScriptFile: PROC [name: NSString.String] RETURNS [BOOLEAN] = BEGIN RETURN [NSString.EqualStrings[name, scriptName]]; END; --IsScriptFile LoadConfirmation: PROCEDURE RETURNS [answer: Answer] = BEGIN --Get confirmation from user to load file or not. stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; nsFreeThisString: NSString.String; version: Version; default: TextInput.YesOrNo _ no; version _ DisplayDates[]; SELECT version FROM new => { stringArray[0] _ M[mFloppyNew]; default _ yes}; newer => { stringArray[0] _ M[mFloppyNewer]; default _ yes}; same => stringArray[0] _ M[mFloppySame]; ENDCASE => stringArray[0] _ M[mFloppyOlder]; nsFreeThisString _ XMessage.Compose[M[mInstallFile], stringArray]; answer _ IF TextInput.GetYesNo[ tty, nsFreeThisString, default ! TTY.Rubout => {answer _ cancel; CONTINUE}] = yes THEN yes ELSE no; NSString.FreeString[nsFreeThisString]; IF answer = yes THEN BEGIN outputHandle.Blanks[8]; PSExecInternal.ExpandKeyAndPrint[exec, mInstalling, stringArray]; IF state # NIL THEN state.version _ version; --*MT for multi-floppies error END; END; --LoadConfirmation OfflineFP0: PROCEDURE = BEGIN END; -- OfflineFP0 DeleteBuffer: PROCEDURE = BEGIN END; --DeleteBuffer EXITS Exit => NULL; END; --InstallFromFloppy M: PROCEDURE [key: PSExecMessages.Key] RETURNS [string: NSString.String] = { RETURN[XMessage.Get[execMsgs, ORD[key]]]}; END. --PSExecEImpl LOG when/who/what 13-Mar-85 10:26:27 - Jacks - Created. Split off from PSExecBImpl. 8-May-85 13:20:06 - Jacks - Updated to Pilot/Mesa 12.0 (change in FloppyChannel). 20-Jun-85 10:42:59 - Jacks - Added copyright notice; updated to PS Euclid interfaces; turned off public error catching by SCS in development mode. 28-Jun-85 15:10:38 - Jacks - Added d1 to case stmts; removed SetCatching calls. 18-Jul-85 14:38:21 - Jacks - Converted to XMessage. 7-Aug-85 10:12:26 - Jacks - Converted to PSCommandExtras InstallFontX, DeleteFontX and ListFontsX; added catch phrases to PSCommandExtras.InstallFont, PSCommand.InstallFile and PSCommandExtras.DeleteFont; added kludge for loading d1 fonts with the correct type. 15-Aug-85 17:05:42 - Jacks - Added catchs for PSCommand.Error[undefined] which means documentInProgress. 10-Sep-85 10:39:10 - Jacks - Moved a string to the msg file; put d1 kludge in more places. 11-Sep-85 13:27:06 - Jacks - Went back to using PSCommand.InstallFont, DeleteFont and ListFonts, instead of PSCommandExtras; removed d1 and bansheeDl font type kludges. 24-Sep-85 14:30:31 - Jacks - PSCommandExtras folded into PSCommand. 6-Nov-85 13:15:18 - Jacks - Call PSKMessages for msg handle. 13-Dec-85 16:46:58 - Jacks - ExecMessages renamed to PSExecMessages. ˆPSExecEImpl.mesa Copyright (C) Xerox Corporation 1985. All rights reserved. Last edited by Jacks 13-Dec-85 16:47:12 Ruseli Binsol: December 16, 1986 1:51:25 pm PST Implements InstallFromFloppy command for PS exec interface. This module is really hard to understand, especially the code for loading multi-floppy fonts using the script file. In the future we will probably want to try and make use of the SCS code for manipulating files or something. Alot of InstallFromFloppy seem like one big kludge to me. **A. Jacks 5/30/84 All modules referencing AccessFloppy, AccessFloppyUtil, Floppy, FloppyChannel, and NSDataStream are commented out because there is currently no implementation to support these. **RBinsol 12/15/86 AccessFloppy USING [Attributes, AttributesRecord, Close, Error, ErrorType, GetAttributes, leaderLength, LookUp, maxDataSize, maxNameLength, Open], AccessFloppyUtil USING [CreateBuffer, DeleteBuffer, MesaStringFromAttributes], Floppy USING [DataError, Error, ErrorType, FileHandle, GetAttributes, GetNextFile, maxCharactersInLabel, nullFileID, nullVolumeHandle, PageNumber, Read, VolumeHandle], FloppyChannel USING [Error, GetHandle, Nop], IO USING [PutBlock], NSDataStream USING [Abort, Aborted, SinkStream], PrincOps USING [BYTE], Process USING [MsecToTicks, Pause], PSAssignedTypes USING [tFont200Rotated90, tFont300Rotated0, tFont300Rotated90], RefText USING [Map], TestPattern USING [alignment, bansheeAlignment, darkDusting, greyDusting, Name, NotFound], VM USING [Interval, nullInterval, PageCount], Volume USING [ID, InsufficientSpace], XString USING [ReaderBody]; Used for displaying dates from stored files and files on floppies: Message domain handle: ========================================= COMMAND PROCESSING ROUTINE ========================================= =============================================== =============================================== This is a very complex routine (a kludge!). There are really two modes in which it runs: normal and script mode. Normal mode is for installing floppy files which fit on a single floppy. Files which are installed from more than one floppy use script mode. The main procedure is Install. NORMAL MODE: In normal mode, the procedure Install reads and displays the names and certain attributes of the files on the floppy one by one. A call is made to LoadConfirmation for each file and the operator is asked to confirm whether or not the file should be installed. If so, a call is made to PSCommand.InstallFont or PSCommand.InstallFile (for test patterns), passing as a parameter the procedure SendFloppyData. The PSCommand implementation takes care of creating a data stream and calls SendFloppyData which puts the floppy data, block by block, on the sink stream. SCRIPT MODE: There is a script file on every floppy for multi-floppy files, which follows a certain language for specifying the pieces of the file being installed. If the procedure Install, while reading the names and attributes of the files on the floppy, comes across a "piece" file (a file not contained completely on one floppy) it calls EnterScriptMode. EnterScriptMode calls BeginInterprete, which reads the script file into memory, sets up the state record data and begins executing the script. The procedure GetCommand parses the script and places the next command and it's parameter in the global variable "scriptCommand". Currently supported script commands are: Create File (parameter = file name), Request Volume (parameter = name of the floppy containing the next file piece), Load Piece (parameter = name of file piece to load) and Close File (parameter = file name). (The command Load All is specified but not currently supported.) BeginInterprete first looks for the command Create File and then calls CreateFileName which justs records the file name in the state record as "state.nameDest". BeginInterprete next looks for the command Load Piece and then calls SetPieceFileContext before returning to EnterScriptMode. BeginInterprete calls SetPieceFileContext, even though that is done in the LoadPiece procedure anyway, because we need the create date of the file for the call to PSCommand.InstallFont. EnterScriptMode makes the call to PSCommand.InstallFont passing as a parameter the procedure InterpreteScript. The PSCommand implementation takes care of setting up the data stream and calls InterpreteScript to get the data. InterpreteScript first calls LoadPiece to execute the command already found by BeginInterprete. Then it enters a loop and interpretes the script file by calling GetCommand and then calling the appropriate procedure to carry out the command. Usually it calls RequestVolume, which prompt the operator to insert the next floppy, and then LoadPiece for each floppy until the font is completely installed. LoadPiece calls SendFloppyData, which actually puts the floppy data block by block on the data sink. At the end of the script file AnnounceEndOfData is called. Or, if an error is encountered, AbortInstall is called. Execution eventually falls back to the Install procedure and installation is complete. floppyHandle: Floppy.VolumeHandle _ Floppy.nullVolumeHandle; -- floppy volume handle. nullFloppyFileHandle: Floppy.FileHandle _ [ Floppy.nullVolumeHandle, Floppy.nullFileID]; null floppy file handle, should be updated when a floppy is opened or closed. DataType: TYPE = {font, testPattern}; FloppyFileContext: TYPE = LONG POINTER TO FloppyFileContextRecord; FloppyFileContextRecord: TYPE = RECORD [ id: Floppy.FileHandle _ nullFloppyFileHandle, -- File handle on floppy attributes: AccessFloppy.Attributes _ NIL, -- Floppy File Attributes fileName: LONG STRING _ NIL, nsFileName: NSString.String _ NSString.nullString, File names indicate destination file in case of multi-floppy fonts and, thus, may not be the name of the file with the given id. dataType: DataType _ font]; nameDest: LONG STRING _ NIL, nullSinkStream: NSDataStream.SinkStream = [[NIL]]; GLOBAL VARIABLES: floppyFile: FloppyFileContextRecord _ []; attributes: AccessFloppy.Attributes _ NIL; This attributes is used by all floppy file (except script file). Storage is created when confirmation is made to load a floppy first time and the space is freed before exits from LoadFileFromFloppy. labelString: LONG STRING _ [Floppy.maxCharactersInLabel]; -- floppy label string Used during script interpretation: scriptFile: FloppyFileContext _ NIL; Remember the file context of the script file. Points to script file in VM. For reading characters from script file. Variables used by mainline code of InstallFromFloppy Procedures for Processing Script AbortInstall: PROCEDURE [displayMsg: BOOLEAN _ TRUE, dataSink: NSDataStream.SinkStream _ nullSinkStream] RETURNS [NSDataStream.SinkStream] = BEGIN IF ~state.close THEN BEGIN state.close _ TRUE; IF displayMsg THEN BEGIN outputHandle.CR[]; outputHandle.NSLine[M[mFloppyCanceled]]; END; IF dataSink # nullSinkStream THEN BEGIN NSDataStream.Abort[dataSink ! NSDataStream.Aborted => CONTINUE]; Stream.Delete[dataSink ! NSDataStream.Aborted => CONTINUE]; END; END; RETURN [nullSinkStream]; END; -- AbortInstall AnnounceEndOfData: PROCEDURE [dataSink: NSDataStream.SinkStream] RETURNS [NSDataStream.SinkStream] = BEGIN IF ~state.close THEN BEGIN state.close _ TRUE; IF dataSink # nullSinkStream THEN Stream.Delete[dataSink ! NSDataStream.Aborted => CONTINUE]; END; RETURN [nullSinkStream]; END; -- AnnounceEndOfData scriptPointer _ Space.ScratchMap[scriptFile.attributes.totalSize]; Floppy.Read[scriptFile.id, AccessFloppy.leaderLength, scriptFile.attributes.totalSize, scriptPointer ! Floppy.Error, Floppy.DataError => { scriptPointer _ Space.Unmap[scriptPointer]; REJECT}]; scriptBuffer _ scriptPointer; STATE.CREATE AND STATE.CLOSE: Initial state: state.create = FALSE, state.close = FALSE. After LoadPiece has been called to send first floopy's data: state.create = TRUE, state.close = FALSE. After CloseFile or AnnounceEndOfData is called: state.create = TRUE, state.close = TRUE: This initial state causes NOP. After EndInterprete has been executed: state.create = FALSE, state.close = TRUE. Allocate buffer for storing 30 (_ 10 *MT) file - piece information. scriptCommand.parameter _ NSString.MakeString[AccessFloppy.maxNameLength]; [endOfScript,] _ GetCommand[]; UNTIL endOfScript OR ~ok DO SELECT scriptCommand.type FROM createFile => { ok _ CreateFileName[scriptCommand.parameter]; EXIT}; requestVolume => ok _ RequestVolume[scriptCommand.parameter,]; ENDCASE => GOTO Exit; [endOfScript,] _ GetCommand[]; ENDLOOP; IF NOT endOfScript AND ok THEN [endOfScript,] _ GetCommand[]; UNTIL endOfScript OR ~ok DO SELECT scriptCommand.type FROM loadPiece => { ok _ SetPieceFileContext[scriptCommand.parameter,]; firstPieceFile _ TRUE; EXIT}; requestVolume => ok _ RequestVolume[scriptCommand.parameter,]; ENDCASE => GOTO Exit; [endOfScript,] _ GetCommand[]; ENDLOOP; EXITS Exit => {[] _ AbortInstall[]; RETURN [ok _ FALSE]}; [type, packageName, sizeInBytes, createDate] RETURNS [continue]-- retries: CARDINAL _ 0; sizeInPages: LONG CARDINAL _ (sizeInBytes + PrincOps.bytesPerPage - 1)/PrincOps.bytesPerPage; IF (state.sizeDest > state.sizeMapped OR state.sizeDest > sizeInPages) AND state.version # same THEN --ignore the overwritten part if file is the same?? PSCommand.DeleteFont[packageName ! PSCommand.Error => WITH problem SELECT FROM disallowedInCurrentMode => IF retries = 3 THEN {nFontsInstalled _ nFontsInstalled + 1; CONTINUE} ELSE {retries _ retries + 1; RETRY}; ENDCASE ] ELSE nFontsInstalled _ nFontsInstalled + 1; RETURN [FALSE]; scriptFile _ NEW[FloppyFileContextRecord]; attributes recored of script floppy file. scriptFile.attributes _ NEW[ AccessFloppy.AttributesRecord[AccessFloppy.maxDataSize]]; scriptFile.nsFileName _ Str[scriptName]; scriptFile.id _ AccessFloppy.LookUp[ scriptFile.nsFileName, scriptFile.attributes]; AccessFloppy.GetAttributes[scriptFile.id, scriptFile.attributes]; IF IsPieceFile[scriptFile.attributes] THEN { outputHandle.CR[]; outputHandle.NSLine[M[mFloppyIncompleteScript]]; RETURN}; scriptFile.fileName _ scriptName; Enter Script-interpretation Mode... fontPackageName _ Str[state.nameDest]; PSCommand.InstallFont[ type: cdFont, packageName: fontPackageName, createDate: floppyFile.attributes.createDate, data: [proc[InterpreteScript]], packageSizeHintInBytes: floppyFile.attributes.totalSizeInBytes ! PSCommand.Error => { WITH p: problem SELECT FROM abortedByClient => NULL; insufficientSpace => { outputHandle.Blanks[4]; outputHandle.NSLine[M[mFloppyErrInsufficientVolSpace], 2]; outputHandle.NSLine[M[mFloppyCanceled]]}; disallowedInCurrentMode => BEGIN stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; nsFreeThisString: NSString.String; stringArray[0] _ M[mInstallFonts]; nsFreeThisString _ XMessage.Compose[M[mConflictingMode], stringArray]; outputHandle.NSLine[nsFreeThisString]; NSString.FreeString[nsFreeThisString]; END; documentInProgress => BEGIN We CAN get here since, with the advent of remote administration, two users may be logged at the same time. One could start printing before the other finishes installing fonts. stringArray: REF XMessage.StringArray _ NEW[XMessage.StringArray[2]]; nsFreeThisString: NSString.String; outputHandle.NSLine[M[mDocInProgress]]; stringArray[0] _ M[mInstallFonts]; nsFreeThisString _ XMessage.Compose[M[mPleaseStopPrinting], stringArray]; outputHandle.NSLine[nsFreeThisString]; NSString.FreeString[nsFreeThisString]; END; ENDCASE => { outputHandle.CR[]; outputHandle.NSLine[M[mFloppyCanceled]]}; CONTINUE}]; Exit Script-interpretation Mode... PSCommand.ListFonts[proc: CheckInstalledFont, filter: [packageName: fontPackageName]]; scriptPointer _ Space.Unmap[scriptPointer]; IF scriptFile # NIL THEN BEGIN IF scriptFile.attributes # NIL THEN FREE[@scriptFile.attributes]; FREE[@scriptFile]; END; GetCommand: PRIVATE PROCEDURE [dataSink: NSDataStream.SinkStream _ nullSinkStream] RETURNS [eof: BOOLEAN, returnDataSink: NSDataStream.SinkStream] = BEGIN error: BOOLEAN _ FALSE; node1: NSString.String _ NEW[TEXT[8]]; node2: NSString.String _ NEW[TEXT[8]]; ReadChar: PROC RETURNS [newChar: CHARACTER, end: BOOLEAN] = BEGIN end _ FALSE; newChar _ scriptBuffer[scriptOffset]; scriptOffset _ scriptOffset + 1; IF (scriptBytesRead _ scriptBytesRead + 1) = scriptFile.attributes.totalSizeInBytes THEN end _ TRUE; END; -- ReadChar Token: PROC [string: LONG STRING, parameterToken: BOOLEAN _ FALSE] = BEGIN "parameterToken" indicates whether the token begin read in is a parameter (e.g. file name), rather than a command. IF so, a space does not indicate the end of the token and double quotes are regarded as token delimiters. space: CHARACTER = 40C; cr: CHARACTER = 15C; semicolon: CHARACTER = 73C; doubleQuote: CHARACTER = 42C; i: CARDINAL _ 0; newChar: CHARACTER _ 40C; string.length _ 0; skip delimiting characters UNTIL eof DO [newChar, eof] _ ReadChar[]; IF (newChar # cr) AND (newChar # semicolon) AND (newChar # space) AND ((newChar # doubleQuote) OR NOT parameterToken) THEN EXIT ENDLOOP; FOR i IN [0..string.maxlength) UNTIL eof DO NSString.AppendCharacter[string, newChar]; [newChar, eof] _ ReadChar[]; IF (newChar # cr) AND (newChar # semicolon) AND ((newChar # space) OR parameterToken) AND ((newChar # doubleQuote) OR NOT parameterToken) THEN LOOP ELSE EXIT; ENDLOOP; END; --Token eof _ FALSE; Token[node1]; IF eof THEN RETURN [eof, dataSink]; Token[node2]; IF eof THEN RETURN [eof, dataSink]; Token[string: scriptCommand.parameter, parameterToken: TRUE]; --Spaces are allowed in file names. SELECT TRUE FROM NSString.EqualStrings[node1, "Load"] => { SELECT TRUE FROM NSString.EqualStrings[node2, "All"] => scriptCommand.type _ loadAll; NSString.EqualStrings[node2, "Piece"] => scriptCommand.type _ loadPiece; ENDCASE => error _ TRUE}; NSString.EqualStrings[node1, "Request"] => IF NSString.EqualStrings[node2, "Volume"] THEN scriptCommand.type _ requestVolume ELSE error _ TRUE; NSString.EqualStrings[node1, "Create"] => IF NSString.EqualStrings[node2, "File"] THEN scriptCommand.type _ createFile ELSE error _ TRUE; NSString.EqualStrings[node1, "Close"L] => IF NSString.EqualStrings[node2, "File"] THEN scriptCommand.type _ closeFile ELSE error _ TRUE; ENDCASE => error _ TRUE; IF error THEN { outputHandle.CR[]; outputHandle.NSLine[M[mFloppyScriptError]]; dataSink _ AbortInstall[,dataSink]; eof _ error}; RETURN [eof, dataSink]; END; -- GetCommand InterpreteScript: PROCEDURE [dataSink: NSDataStream.SinkStream] = BEGIN ENABLE BEGIN UNWIND => { stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]];; outputHandle.CR[]; stringArray[0] _ M[mFloppyErrUnknown]; PSExecInternal.ExpandKeyAndPrint[exec, mFloppyError, stringArray]; outputHandle.CR[]; dataSink _ AbortInstall[,dataSink]; }; AccessFloppy.Error => { --NOTE: add error messages specific to AccessFloppy for next release. stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; outputHandle.CR[]; stringArray[0] _ M[ SELECT type FROM volumeNotOpen => mFloppyErrVolumeNotOpen, fileNotFound => mFloppyFileError, --NOTE: add a better message for next release ENDCASE => mFloppyErrUnknown]; PSExecInternal.ExpandKeyAndPrint[exec, mFloppyError, stringArray]; outputHandle.CR[]; IF type = volumeNotOpen THEN { floppyHandle _ Floppy.nullVolumeHandle; nullFloppyFileHandle _ [floppyHandle, Floppy.nullFileID]}; GOTO Abort}; Floppy.Error => { stringArray: ARRAY [0..1) OF NSString.String; outputHandle.CR[]; stringArray[0] _ M[ SELECT error FROM badDisk => mFloppyErrBadDisk, badSectors => mFloppyErrBadSectors, hardwareError => mFloppyErrHardware, invalidVolumeHandle => mFloppyErrInvalidVolumeHandle, needsScavenging => mFloppyErrNeedsScavenging, noSuchDrive => mFloppyErrNoSuchDrive, notReady => mFloppyErrNotReady, stringTooShort => mFloppyErrStringTooShort, volumeNotOpen => mFloppyErrVolumeNotOpen, ENDCASE => mFloppyErrUnknown]; PSExecInternal.ExpandKeyAndPrint[exec, mFloppyError, DESCRIPTOR[stringArray]]; outputHandle.CR[]; floppyHandle _ Floppy.nullVolumeHandle; nullFloppyFileHandle _ [floppyHandle, Floppy.nullFileID]; GOTO Abort}; END; --Enable Clause end: BOOLEAN _ FALSE; ok: BOOLEAN _ TRUE; IF dataSink = nullSinkStream THEN RETURN; [ok, dataSink] _ LoadPiece[scriptCommand.parameter, dataSink]; [end, dataSink] _ GetCommand[dataSink]; UNTIL end OR ~ok DO -- end = TRUE if end of file SELECT scriptCommand.type FROM loadPiece => [ok, dataSink] _ LoadPiece[scriptCommand.parameter, dataSink]; loadAll => [ok, dataSink] _ LoadAll[scriptCommand.parameter, dataSink]; --not implemented closeFile => [ok, dataSink] _ CloseFile[scriptCommand.parameter, dataSink]; requestVolume => [ok, dataSink] _ RequestVolume[scriptCommand.parameter, dataSink]; ENDCASE => { outputHandle.CR[]; outputHandle.NSLine[M[mFloppyScriptError]]; GOTO Abort}; [end, dataSink] _ GetCommand[dataSink]; ENDLOOP; dataSink _ AnnounceEndOfData[dataSink]; EXITS Abort => dataSink _ AbortInstall[,dataSink]; END; -- InterpreteScript SetPieceFileContext: PROCEDURE [str: NSString.String, dataSink: NSDataStream.SinkStream _ nullSinkStream] RETURNS [ok: BOOLEAN, returnDataSink: NSDataStream.SinkStream] = BEGIN floppyFile _ []; floppyFile.attributes _ attributes; floppyFile.fileName _ str; floppyFile.nsFileName _ Str[str]; floppyFile.id _ AccessFloppy.LookUp[ floppyFile.nsFileName, floppyFile.attributes]; IF ~IsPieceFile[floppyFile.attributes] THEN BEGIN stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; stringArray[0] _ floppyFile.nsFileName; outputHandle.CR[]; PSExecInternal.ExpandKeyAndPrint[exec, mFloppyNotFilePiece, stringArray]; dataSink _ AbortInstall[,dataSink]; RETURN [ok _ FALSE, dataSink]; END ELSE RETURN [ok _ TRUE, dataSink]; END; --SetPieceFileContext command interpreter. IF ok THEN dataSink _ AnnounceEndOfData[dataSink] ELSE dataSink _ AbortInstall[dataSink]; RETURN [ok, dataSink]; state.nameDest _ NSString.MakeString[str.length]; NSString.AppendString[state.nameDest, str.length]; LoadPiece will only load file piece. LoadPiece: PRIVATE PROCEDURE [str: LONG STRING, dataSink: NSDataStream.SinkStream] RETURNS [ok: BOOLEAN, returnDataSink: NSDataStream.SinkStream] = BEGIN ok _ TRUE; IF ~firstPieceFile THEN BEGIN [ok, dataSink] _ SetPieceFileContext[str, dataSink]; IF ~ok THEN GOTO Exit; END; IF WindowOverlay[] THEN GOTO Exit; UpdateSourceState[]; IF firstPieceFile THEN BEGIN floppyFile.fileName _ state.nameDest; floppyFile.nsFileName _ Str[state.nameDest]; File name now indicates name of destination file rather that floppy file. SELECT LoadConfirmation[] FROM no, cancel => { dataSink _ AbortInstall[displayMsg: FALSE, dataSink: dataSink]; RETURN [ok _ FALSE, dataSink]}; ENDCASE; END; SendFloppyData[dataSink ! SendDataError => {dataSink _ nullSinkStream; GOTO Exit}]; IF systemAbort THEN RETURN [ok _ FALSE, dataSink _ nullSinkStream]; Stream was aborted by receiver. Error will be raised by PSCommand.InstallFont. IF firstPieceFile THEN BEGIN state.sizeDest _ floppyFile.attributes.totalSize; state.create _ TRUE; firstPieceFile _ FALSE; END; state.sizeMapped _ state.sizeMapped + floppyFile.attributes.size; RETURN [ok, dataSink]; EXITS Exit => {dataSink _ AbortInstall[,dataSink]; RETURN [ok _ FALSE, dataSink]}; END; -- LoadPiece. LoadAll: PRIVATE PROCEDURE [str: LONG STRING, dataSink: NSDataStream.SinkStream] RETURNS [ok: BOOLEAN, returnDataSink: NSDataStream.SinkStream] = BEGIN This procedure implements the merge function of prepress file. This is used to merge multiple font files into a destinateion font file (created by Create File). Note: NOT font PIECES. RETURN [ok _ TRUE, dataSink]; END; -- LoadAll. IF the requested volume is not online then request it, online, and save state otherwise RETURN. AwaitFloppyChange: PROC = BEGIN OPEN FloppyChannel; ^^^ Copied from PromOpsImpl.mesa if the floppy is ready, wait until it goes notReady first UNTIL FloppyChannel.Nop[ FloppyChannel.GetHandle[0] ! FloppyChannel.Error => IF type = invalidHandle THEN RETRY] = notReady DO Process.Pause[Process.MsecToTicks[waitChange]]; ENDLOOP; UNTIL FloppyChannel.Nop[ FloppyChannel.GetHandle[0] ! FloppyChannel.Error => IF type = invalidHandle THEN RETRY] # notReady DO Process.Pause[Process.MsecToTicks[waitChange]]; ENDLOOP; END; -- of AwaitFloppyChange IF ok _ NSString.EqualStrings[str, labelString] THEN RETURN [ok, dataSink] --##MT ELSE OfflineFP0[]; stringArray[0] _ Str[str]; AwaitFloppyChange[]; OpenVolume[labelString ! Floppy.Error => { stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; outputHandle.CR[]; stringArray[0] _ M[ SELECT error FROM hardwareError => mFloppyErrHardware, invalidVolumeHandle => mFloppyErrInvalidVolumeHandle, needsScavenging => mFloppyErrNeedsScavenging, ENDCASE => mFloppyErrUnknown]; PSExecInternal.ExpandKeyAndPrint[exec, mFloppyError, stringArray]; floppyHandle _ Floppy.nullVolumeHandle; nullFloppyFileHandle _ [floppyHandle, Floppy.nullFileID]; EXIT}; UserAbort => {displayMsg _ FALSE; EXIT} ]; IF NSString.EqualStrings[str, labelString] THEN RETURN [TRUE, dataSink] ELSE OfflineFP0[]; by here, failed! dataSink _ AbortInstall[displayMsg, dataSink]; RETURN [ok _ FALSE, dataSink]; i: CARDINAL _ state.length; state.piece[i].vol _ NSString.MakeString[labelString.maxlength]; NSString.CopyString[to: state.piece[i].vol, from: labelString]; state.piece[i].base _ floppyFile.attributes.offset; state.piece[i].size _ floppyFile.attributes.size; state.length _ i + 1; SELECT TRUE FROM state.piece[i].base = floppyFile.attributes.offset => overlay _ TRUE; state.piece[i].base < floppyFile.attributes.offset => IF state.piece[i].base + state.piece[i].size <= floppyFile.attributes.offset THEN LOOP ELSE overlay _ TRUE; ENDCASE => IF floppyFile.attributes.offset + floppyFile.attributes.size <= state.piece[i].base THEN LOOP ELSE overlay _ TRUE; End of script processing procedures. version _ SELECT TRUE FROM (createDate < floppyFile.attributes.createDate) => newer, (createDate = floppyFile.attributes.createDate) => same, ENDCASE => older; [type, packageName, sizeInBytes, createDate]-- RETURNS [continue _ TRUE]-- [type, name, sizeInBytes, createDate] XFormat.Date[nsDateTimeObject, floppyFile.attributes.createDate]; --appends date to nsDateAndTime IF floppyFile.dataType = font THEN PSCommand.ListFonts[proc: DisplayCurrentFontDate, filter: [packageName: floppyFile.nsFileName]] ELSE PSCommand.ListFiles[proc: DisplayCurrentTestPatternDate, filter: [type: testPattern, name: floppyFile.nsFileName]]; OfflineFP0[]; FREE[@attributes]; ENABLE BEGIN AccessFloppy.Error => { IF type = volumeNotOpen THEN { floppyHandle _ Floppy.nullVolumeHandle; nullFloppyFileHandle _ [floppyHandle, Floppy.nullFileID]}; GOTO Exit}; May be generated in SendFloppyData (Floppy.Read) among other(?) places: Floppy.Error => { stringArray: ARRAY [0..1) OF NSString.String; outputHandle.CR[]; stringArray[0] _ M[ SELECT error FROM badDisk => mFloppyErrBadDisk, badSectors => mFloppyErrBadSectors, hardwareError => mFloppyErrHardware, invalidVolumeHandle => mFloppyErrInvalidVolumeHandle, needsScavenging => mFloppyErrNeedsScavenging, noSuchDrive => mFloppyErrNoSuchDrive, notReady => mFloppyErrNotReady, stringTooShort => mFloppyErrStringTooShort, volumeNotOpen => mFloppyErrVolumeNotOpen, ENDCASE => mFloppyErrUnknown]; PSExecInternal.ExpandKeyAndPrint[exec, mFloppyError, DESCRIPTOR[stringArray]]; outputHandle.CR[]; outputHandle.NSLine[M[mFloppyCanceled]]; floppyHandle _ Floppy.nullVolumeHandle; nullFloppyFileHandle _ [floppyHandle, Floppy.nullFileID]; GOTO Exit}; PSCommand.Error => { WITH problem SELECT FROM abortedByClient => NULL; ENDCASE => { outputHandle.CR[]; outputHandle.NSLine[M[mFloppyCanceled]]}; GOTO Exit}; END; --Enable Clause BYTE: TYPE = CARDINAL [0..100]; nsPrompt: NSString.String _ [bytes: promptBytes, length: 0, maxlength: 100]; promptBytes: PACKED ARRAY [0..100) OF BYTE; ask for name confirmation sFileName: LONG STRING _ [AccessFloppy.maxNameLength]M floppyFile _ []; OpenVolume[labelString ! UserAbort => GOTO Exit]; -- floppyHandle, labelString, nullFloppyFileHandle will be set. nsPrompt _ NSString.AppendString[nsPrompt, labelString]; attributes _ NEW[AccessFloppy.AttributesRecord[AccessFloppy.maxDataSize]]; FOR floppyFileHandle: Floppy.FileHandle _ Floppy.GetNextFile[ nullFloppyFileHandle].nextFile, Floppy.GetNextFile[floppyFileHandle].nextFile UNTIL floppyFileHandle = nullFloppyFileHandle DO AccessFloppy.GetAttributes[floppyFileHandle, attributes]; AccessFloppyUtil.MesaStringFromAttributes[attributes, sFileName]; IF IsScriptFile[sFileName] THEN LOOP; pieceFile _ IsPieceFile[attributes]; floppyFile.id _ floppyFileHandle; floppyFile.attributes _ attributes; floppyFile.fileName _ sFileName; floppyFile.nsFileName _ Str[sFileName]; floppyFile.dataType _ IF floppyFile.attributes.type # PSAssignedTypes.tFont300Rotated0 AND floppyFile.attributes.type # PSAssignedTypes.tFont300Rotated90 AND floppyFile.attributes.type # PSAssignedTypes.tFont200Rotated90 THEN testPattern ELSE font; IF floppyFile.dataType = font THEN SELECT psState.option FROM bansheeDl, feps9700, fx3500, raven => IF floppyFile.attributes.type # PSAssignedTypes.tFont300Rotated0 THEN GOTO WrongFontFileType; d1 => d1 fonts can have either type tFont300Rotated0 or tFont300Rotated90, though we assume they are actually the 90 degree rotated fonts. IF (floppyFile.attributes.type # PSAssignedTypes.tFont300Rotated0) AND (floppyFile.attributes.type # PSAssignedTypes.tFont300Rotated90) THEN GOTO WrongFontFileType; fax295, fax495 => IF floppyFile.attributes.type # PSAssignedTypes.tFont200Rotated90 THEN GOTO WrongFontFileType; ENDCASE => ERROR ELSE BEGIN --file is a test pattern OPEN T: TestPattern; This is a bunch of ugly exception code to prevent the user from loading test patterns inappropriate for the printing option being supported. This only matters for the options that use the 300 spi fonts, since they all share the same Required Fonts floppy. The 200 spi Required Fonts floppy contains only the test patterns used by the fax. Resuming the NotFound signal below will return the name for the test pattern, even if the TP is not currently installed on the PS.... nsBansheeAlignment: NSString.String _ T.Name[T.bansheeAlignment ! T.NotFound => RESUME]; alignment pattern specific to banshee nsAlignment: NSString.String _ T.Name[T.alignment ! T.NotFound => RESUME]; alignment pattern for electronic printers nsDarkDusting: NSString.String _ T.Name[T.darkDusting ! T.NotFound => RESUME]; nsGreyDusting: NSString.String _ T.Name[T.greyDusting ! T.NotFound => RESUME]; SELECT psState.option FROM d1, fx3500, raven => IF NSString.EquivalentStrings[floppyFile.nsFileName, nsBansheeAlignment] THEN LOOP; --skip alignment pattern specific to banshee bansheeDl => BEGIN IF NSString.EquivalentStrings[floppyFile.nsFileName, nsAlignment] THEN LOOP; --skip alignment pattern not used for banshee IF NSString.EquivalentStrings[floppyFile.nsFileName, nsDarkDusting] THEN LOOP; --pattern not used for banshee (bad for engine) END; feps9700 => BEGIN IF NSString.EquivalentStrings[floppyFile.nsFileName, nsBansheeAlignment] THEN LOOP; --don't use any alignment pattern IF NSString.EquivalentStrings[floppyFile.nsFileName, nsAlignment] THEN LOOP; --don't use any alignment pattern IF NSString.EquivalentStrings[floppyFile.nsFileName, nsGreyDusting] THEN LOOP; --can't be printed by 9700 END; fax295, fax495 => NULL; --200 spi Required Fonts floppy contains only Cam.interpress. ENDCASE => ERROR; END; IF floppyFile.dataType = font THEN BEGIN PSCommand.InstallFont[ type: cdFont, packageName: floppyFile.nsFileName, createDate: floppyFile.attributes.createDate, data: [proc[SendFloppyData]], packageSizeHintInBytes: floppyFile.attributes.totalSizeInBytes ! SendDataError => EXIT; PSCommand.Error => WITH p: problem SELECT FROM insufficientSpace => BEGIN outputHandle.Blanks[4]; outputHandle.NSLine[M[mFloppyErrInsufficientVolSpace], 2]; outputHandle.NSLine[M[mFloppyCanceled]]; END; disallowedInCurrentMode => BEGIN stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; nsFreeThisString: NSString.String; stringArray[0] _ M[mInstallFonts]; nsFreeThisString _ Message.Expand[M[mConflictingMode], stringArray]; outputHandle.NSLine[nsFreeThisString]; NSString.FreeString[nsFreeThisString]; EXIT; END; documentInProgress => BEGIN --We CAN get here since, with the advent of remote administration, two users may be logged at the same time. One could start printing before the other finishes installing fonts. stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; nsFreeThisString: NSString.String; outputHandle.NSLine[M[mDocInProgress]]; stringArray[0] _ M[mInstallFonts]; nsFreeThisString _ Message.Expand[M[mPleaseStopPrinting], stringArray]; outputHandle.NSLine[nsFreeThisString]; NSString.FreeString[nsFreeThisString]; END; ENDCASE; ]; nFontsInstalled _ nFontsInstalled + 1; END ELSE BEGIN PSCommand.InstallFile[ type: testPattern, name: floppyFile.nsFileName, createDate: floppyFile.attributes.createDate, data: [proc[SendFloppyData]], fileSizeHintInBytes: floppyFile.attributes.totalSizeInBytes ! SendDataError => EXIT; PSCommand.Error => WITH problem SELECT FROM insufficientSpace => BEGIN outputHandle.Blanks[4]; outputHandle.NSLine[M[mFloppyErrInsufficientVolSpace], 2]; outputHandle.NSLine[M[mFloppyCanceled]]; END; disallowedInCurrentMode => BEGIN stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; nsFreeThisString: NSString.String; stringArray[0] _ M[mInstallFonts]; nsFreeThisString _ XMessage.Compose[M[mConflictingMode], stringArray]; outputHandle.NSLine[nsFreeThisString]; NSString.FreeString[nsFreeThisString]; EXIT; END; ENDCASE; ]; nTestPatternsInstalled _ nTestPatternsInstalled + 1; END; outputHandle.Blanks[10]; outputHandle.NSLine[M[mFloppyDone]]; IF NSExec.CheckForAbort[exec] THEN EXIT; stringArray[0] _ Str[labelString]; outputHandle.Decimal[nFontsInstalled + nTestPatternsInstalled]; WrongFontFileType => BEGIN stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; stringArray[0] _ floppyFile.nsFileName; PSExecInternal.ExpandKeyAndPrint[exec, mBadFontFileType, stringArray]; outputHandle.NSLine[M[mFloppyCanceled]]; Done[]; continue _ no END; IsPieceFile: PRIVATE PROC [attributes: AccessFloppy.Attributes] RETURNS [BOOLEAN] = BEGIN RETURN [attributes.totalSize > attributes.size]; END; --IsPieceFile stringArray[1] _ floppyFile.nsFileName; stringArray[0] _ floppyFile.nsFileName; IF floppyHandle # Floppy.nullVolumeHandle THEN { AccessFloppy.Close[!Floppy.Error => CONTINUE]; floppyHandle _ Floppy.nullVolumeHandle; nullFloppyFileHandle _ [floppyHandle, Floppy.nullFileID]}; OpenVolume: PROCEDURE [svName: LONG STRING] = BEGIN svName.length _ 0; floppyHandle _ AccessFloppy.Open[ ! Floppy.Error => SELECT error FROM invalidVolumeHandle, notReady => { outputHandle.CR[]; IF TextInput.GetYesNo[ tty, M[mInsertFloppy], yes ! TTY.Rubout => {GOTO Quit}] = yes THEN RETRY ELSE GOTO Quit}; ENDCASE => REJECT]; [] _ Floppy.GetAttributes[floppyHandle, svName]; nullFloppyFileHandle _ [floppyHandle, Floppy.nullFileID]; EXITS Quit => ERROR UserAbort; END; --OpenVolume SendFloppyData: PROCEDURE [dataSink: NSDataStream.SinkStream] = BEGIN bufferSize: VM.PageCount = 30; --one disk track buffer: VM.Interval _ VM.nullInterval; bufferBlock: Stream.Block; pagesRemaining: VM.PageCount _ floppyFile.attributes.size; base: Floppy.PageNumber _ AccessFloppy.leaderLength; filePiece: BOOLEAN _ floppyFile.attributes.totalSize # floppyFile.attributes.size; IF buffer # VM.nullInterval THEN BEGIN AccessFloppyUtil.DeleteBuffer[buffer.pointer]; buffer _ Space.nullInterval; END; BEGIN ENABLE BEGIN UNWIND => { IF dataSink # nullSinkStream THEN { NSDataStream.Abort[dataSink ! NSDataStream.Aborted => CONTINUE]; Stream.Delete[dataSink ! NSDataStream.Aborted => CONTINUE]}; DeleteBuffer[]}; Floppy.Error => { stringArray: ARRAY [0..1) OF NSString.String; stringArray[0] _ M[ SELECT error FROM invalidVolumeHandle => mFloppyErrInvalidVolumeHandle, notReady => mFloppyErrNotReady, volumeNotOpen => mFloppyErrVolumeNotOpen, hardwareError => mFloppyErrHardware, ENDCASE => mFloppyErrUnknown]; PSExecInternal.ExpandKeyAndPrint[exec, mFloppyError, DESCRIPTOR[stringArray]]; GOTO dataSendError}; Floppy.DataError => { outputHandle.Blanks[4]; outputHandle.NSLine[M[mFloppyReadError]]; GOTO dataSendError} END; --Enable clause IF dataSink = nullSinkStream THEN RETURN; buffer _ AccessFloppyUtil.CreateBuffer[bufferSize ! Space.InsufficientSpace, RefText.Error => { outputHandle.Blanks[4]; outputHandle.NSLine[M[mFloppyCreateFileError]]; GOTO dataSendError}; Volume.InsufficientSpace => { outputHandle.Blanks[4]; outputHandle.NSLine[M[mFloppyErrInsufficientVolSpace]]; GOTO dataSendError}]; bufferBlock _ [ blockPointer: buffer.pointer, startIndex: 0, stopIndexPlusOne: CARDINAL[bufferSize * Environment.bytesPerPage]]; Copy as many chunks of the standard buffer size as possible... UNTIL pagesRemaining < bufferSize DO Floppy.Read[floppyFile.id, base, bufferSize, buffer.pointer]; Stream.PutBlock[dataSink, bufferBlock ! NSDataStream.Aborted => GOTO aborted]; base _ base + bufferSize; pagesRemaining _ pagesRemaining - bufferSize; ENDLOOP; ...and then copy the fraction left over. IF pagesRemaining # 0 THEN BEGIN scratchPointer: LONG POINTER _ Space.ScratchMap[pagesRemaining]; scratchBlock: Stream.Block; bytesRemaining: CARDINAL _ CARDINAL[pagesRemaining * PrincOps.bytesPerPage]; scratchBlock _ [ blockPointer: scratchPointer, startIndex: 0, stopIndexPlusOne: bytesRemaining]; Floppy.Read[floppyFile.id, base, pagesRemaining, scratchPointer ! Floppy.Error, Floppy.DataError => { scratchPointer _ Space.Unmap[scratchPointer]; REJECT}]; Stream.PutBlock[dataSink, scratchBlock ! NSDataStream.Aborted => { scratchPointer _ Space.Unmap[scratchPointer]; GOTO aborted}]; scratchPointer _ Space.Unmap[scratchPointer]; END; DeleteBuffer[]; IF ~filePiece THEN Stream.Delete[dataSink ! NSDataStream.Aborted => CONTINUE]; EXITS aborted => { --PSCommand Install proc will return with raise error. Stream.Delete[dataSink ! NSDataStream.Aborted => CONTINUE]; DeleteBuffer[]; systemAbort _ TRUE}; dataSendError => { NSDataStream.Abort[dataSink ! NSDataStream.Aborted => CONTINUE]; Stream.Delete[dataSink ! NSDataStream.Aborted => CONTINUE]; DeleteBuffer[]; ERROR SendDataError}; END; --Enable clause and code END; --SendFloppyData IF psState.clientControl.formatterEnabled OR psState.clientControl.markerEnabled THEN BEGIN stringArray: REF XMessage.StringArray _ NEW [XMessage.StringArray[2]]; stringArray[0] _ M[mInstallFonts]; outputHandle.Blanks[2]; PSExecInternal.ExpandKeyAndPrint[exec, mPleaseStopPrinting, stringArray]; END ELSE Install[]; === === === === === === SUPPORT ROUTINES: === === === === === === Proc for getting NSString from XMessage key Κ$ϊ˜™J™:J™'Icode™/—˜Jšœ)Οkœ™<—J˜Jšœ΄œy™°J™JšœΔ™ΔJ˜š ˜ Kšœ œ€™’Kšœœ8™NKšœ œœ˜Kšœœ˜#Kšœœ›™§Kšœœ™,Kšœœ ™Kšœ œ™0Kšœœ;˜GKšœ œI˜WKšœ œœ™Kšœœ™#Kšœœ:™OKšœ œ@˜OKšœœ˜Kšœœ˜)Kšœœ˜Kšœ œ ˜Kšœœ˜Kšœœ™Kšœ œI™ZKšœ œ˜.Kšœœ˜Kšœœ%™-Kšœœœ™%Kšœœ œ ˜9Kšœ œ%˜3Kšœœ™K˜—šΟn œ ˜KšœNœ˜kKšœ˜Kšœ ˜K˜K˜3K˜KšœB™BKšœ!œœ˜/KšœI˜IK˜Kšœ™K˜8K˜—˜Kšœ)™)Kšœ™šœ)™)K˜K˜—Kšœ0™0Kšžœœ˜+Kšœ/™/K˜K™‘K™KšœœΆ™ΑK™Kšœœ±™Ό˜š˜Kšœœœœ˜œ˜C—Kšœ>Ÿ™V™+K™,—KšœM™MK˜Kšœ œ™%Kš œœœœœ™Bšœœœ™(Kšœ/Ÿ™GKšœ&œŸ™EKšœ œœœ™K™2Kšœ€™€K™K™—Kšœœœ ˜šœ œœ˜Kšœ0˜0Kšœ œœœ™KšœŸ˜2Kšœ!ŸA˜bKšœœœŸ˜/KšœœœŸ&˜?KšœŸ+˜DKšœœŸ˜6Kš œœœœœ ˜=K˜—šœ œœ˜Kšœœ9˜S—Kšœ œ˜*K˜Kšœ,˜,Kšœ,œ™2K™K™K™)Kšœ&œ™*KšœΗ™ΗKšœ œœ#Ÿ™QKšœœŸ#˜CKšœœŸ+˜RK˜Kšœ"™"Kšœœ˜K˜Kšœ œ™$Kšœ-™-Kšœœœœ˜"Kšœ™Kšœœœœœœœ œœ˜EKšœ(™(Kšœœœ˜#KšœœŸ&˜BKšœœŸ/˜MKšœœœŸ5˜aKšœœœŸ1˜RKšœ œ Ÿ#˜@Kšœ œœŸ_˜}K˜Kšœ4™4K˜1K˜AK˜Kšœ ™ š ž œ œœœ5œ™’šœ ™Kšœœ™šœ  ™Kšœ œ™K™(Kšœ™—šœ ™'Kšœ6œ™@Kšœ1œ™;Kšœ™—Kšœ™Kšœ™KšœŸ™K™——šžœ œ$œ™jšœœ™Kšœœ™šœ™!Kšœ1œ™;—Kšœ™—Kšœ™KšœŸ™K™—š žœ œœœœŸ/˜iKšœ œœ˜Kšœœ˜ KšœœŸ ˜!K˜K™B™6™0™#Kšœ,œ™5———K™K˜Kšœ™Kšœ9™9Kšœf™fKšœw™wKšœP™PK˜KšœœŸœŸ˜)Kšœœ˜K˜K˜Kšœœ˜Kšœœ˜K˜KšœC™CKšœœ˜ K˜K˜K˜Kšœœ˜#K™JK˜K™šœ œ™šœ™™Kšœ.œ™4—™K™-—Kšœœ™—K™Kšœ™K™—šœœ œ™K™šœ œ™šœ™™K™3Kšœœœ™—™K™-—Kšœœ™—K™Kšœ™K™——Kšœ œœ˜Kšœ œ˜Kšœœœ™9KšœŸ˜K˜—šžœ˜.KšœB™BKšœ œ™šœ œœ™K™@—šœ$œ™FšœœŸ3™Q™!šœœ œ™-šœœ ™*Kšœ)œ™7Kšœœ™$—Kš™—K™———Kšœ'™+Kšœœ™KšœŸ˜K™—šžœ œ˜"Kšœ œœ˜K˜7K˜šœœœ˜Kšœœ'˜.Kšœ9œ˜CK˜Kšœ œ™*Kšœ)™)šœœ™K™9—K™(™$K™.—K™Ašœ$œ™,Kšœ œ™K™0Kšœ™—K™!Kšœ#™#K˜šœ œœ ˜/K™&™K™K™K™.K™K™?™šœ œ™Kšœœ™™K™K™:K™)—šœ™ Kšœ œœ™FK™"K™"KšœF™FK™&K™&Kšœ™šœ™KšŸ@™@KšŸB™BKšŸ+™+Kšœ œœ™EK™"K™'K™"KšœI™IK™&K™&Kšœ™—Kšœ™ Kšœ œ™K™)——Kšœ™ ——šœ˜K˜——Kšœ"™"K˜KšœŸ˜—KšœŸ˜K˜—šž œ œ%˜Cšœœ'˜>K™V—K˜Kšœœ˜!KšœŸ˜K˜—šžœ œœ˜+šœœ˜K™+—Kšœœ˜šœœœ˜!šœœ˜%K˜-—Kšœ˜Kšœ˜—šœ œœ˜Kšœœœ%˜Ašœœœ˜'šœœ˜ K˜(—Kšœ˜—Kšœ ˜ Kšœ˜—šœœœ™Kšœœœœ™AKšœ™Kšœ™—KšœŸ˜K˜—š ž œœ œ5œœ,™šKšœœœ™Kšœœœ™&šœœœ™&K™—š žœœœ  œœ™AKšœœ™ K™%K™ šœR™XKšœœ™ —KšœŸ ™K™—š žœœ œœœœ™JKšœά™άKšœ œ™Kšœ œ™Kšœ  œ™Kšœ  œ™Kšœœ™Kšœ  œ™K™K™Kšœ™šœ™ K™Kšœœ™/šœœœœ™JKš™—Kšœ™—šœœœ™+K™*K™Kšœœ™/Kšœœ™)šœœœ™4Kš™—Kšœœ™ Kšœ™—KšœŸ™ K™—Kšœœ™ K™ Kšœœœ™#K™ Kšœœœ™#Kšœ7œŸ#™ašœœ™šœ)™)šœœ™KšœD™DKšœH™HKšœ œ™——šœ*™*šœ(™.K™"—Kšœ œ™—šœ)™)Kšœ&œ ™LKšœ œ™—šœ)™)Kšœ&œ™KKšœ œ™—Kšœ œ™—šœœ™Kšœ œ™K™+K™#K™ —Kšœ™KšœŸ ™K™—šžœ œ&™Gšœ™ šœ™ Kšœ œœ™GKšœ œ™K™&KšœB™BKšœ œ™K™#K™—šœŸE™]Kšœ œœ™FKšœ œ™™šœ™K™)Kšœ"Ÿ-™OKšœ™——KšœB™BKšœ œ™šœœ™K™'K™:—Kšœ™ —™Kšœ œœ™-Kšœ œ™™šœ™K™K™#K™$K™5K™-K™%K™K™+K™)Kšœ™——Kšœ5 œ™NKšœ œ™K™'K™9Kšœ™ —KšœŸ™K™—Kšœœœ™Kšœœœ™K™Kšœœœ™)K™K™>K™™'šœœœŸ™1šœ™K™KKšœHŸ™YK™KK™Sšœ™ Kšœ œ™K™+Kšœ™ ——K™'Kšœ™K™—K™'Kšœ-™2KšœŸ™K™——š žœ œKœœ,™°K™K™#K™K™!™$K™.—šœ%™+Kš™Kšœ œœ™FK™'Kšœ œ™KšœI™IK™#Kšœœ ™Kš™—Kšœœœ ™"šœŸ™K™——Kšœ™K™š ž œœ œœœ˜QKšœ0˜0šœœ'™1Kšœ#™'Kšœ™šœŸ ˜K™———š žœ œœœ˜NKšœœ˜ K™1K™2KšœŸ˜—K˜Kšœ$™$š ž œœ œœœ$™Ršœœ,™FKšœœ™ šœ ™K™4Kšœœœ™Kšœ™—Kšœœœ™"K™K™šœ ™K™%K™,KšœI™Išœ™™Kšœ$œ™?Kšœœ ™—Kšœ™—Kšœ™K™—šœ*™*Kšœœ™(—K™Kšœ œœœ™CKšœO™OK™šœ ™K™1Kšœœ™Kšœœ™Kšœ™K™—K™AKšœ™šœ-™2Kšœœ ™K™—šœŸ ™K™———šžœœ œœœ$ œœ,™˜KšœΈ™ΈKšœœ ™KšœŸ ™—K™š ž œœ œœœ˜UKšœ_™_Kšœ œœ˜FKšœ œ˜Kšœœ˜Kšœ œœŸ5˜QK˜šžœœœœ™3šœZ™Zšœ™™Kšœœœœ ™H—Kšœ0œ™8—šœ™™Kšœœœœ ™H—Kšœ0œ™8—KšœŸ™K™——Kšœ.œœŸ™QKšœ™šœœ˜Kšœ œ˜K™˜'Kšœ+˜+—K™™™Kšœ œœ™FKšœ œ™™šœ™K™$K™5K™-Kšœ™——KšœB™BK™'K™9Kšœ™—Kšœœœ™'K™—Kš œ)œœœ œ™ZKšœ˜—Kšœ™K™.Kšœœ ™KšœŸ˜K˜—šžœ œ˜$Kšœœ™K™@K™?K™3K™1K™KšœŸ˜K˜—š ž œ œœ œ˜;Kšœ œ˜š œœœœ ˜5šœœ™Kšœ@œ™E™5šœ-™/Kšœœ™&—Kšœ œ™—šœ™ šœ:™Kšœ œ™K™———šœ™"šœ™™&šœ?™EKšœ™——™K™DK™?šœA™FKšœA™EKšœ™——™šœ@™FKšœ™——Kšœ™——šœœŸ™#Kšœžœ™K™§K™¬Kšœ…™…šœPœ™XKšœ%™%—šœBœ™JKšœ)™)—KšœFœ™NKšœFœ™Nšœ™™KšœGœœŸ,™€—šœ ™Kšœ@œœŸ-™zKšœBœœŸ/™~Kšœ™—šœ ™KšœGœœŸ!™uKšœ@œœŸ!™nKšœBœœŸ™iKšœ™—KšœœŸ=™UKšœœ™—Kšœ™K˜—Kšœ œœ˜,šœ˜Kšœœ˜ Kšœ œ˜Kšœ˜K˜—šœœ™(™K™K™$K™.K™™@Kšœœ™šœœ œ™.šœ™K™K™:K™(Kšœ™—šœ™ Kšœ œœ™FK™"K™"KšœD™DK™&K™&Kšœ™Kšœ™—šœœŸ±™ΝKšœ œœ™FK™"K™'K™"KšœG™GK™&K™&Kšœ™—Kšœ™——K™—K™&Kš™—šœ™ ™K™0K™.K™™=Kšœœ™šœœ œ™+šœ™K™K™:K™(Kšœ™—šœ™ Kšœ œœ™FK™"K™"KšœF™FK™&K™&Kšœ™Kšœ™—Kšœ™——K™—K™4Kšœ™—K™K™$Kšœœœ™(Kšœ˜K˜—šœŸH˜OKšœ œœ˜FK™"K˜K™?KšœE˜EKšœ˜—K˜šœ˜šœ™Kšœ œœ™FK™'KšœF™FK™(K™Kšœ™—K˜ —KšœŸ ˜K˜—š ž œœœ&œœ™SKšœœ*™6KšœŸ ™K™—š ž œœœœ˜DKšœ+˜1KšœŸ˜K˜—šžœ œœ˜™>šœ™$K™=™'Kšœœ ™&—K™K™-Kšœ™K™——Kšœ(™(šœ ™ Kšœœœ$™@K™Kšœœœ)™L™K™,K™"—™A™#Kšœ.œ™7——™(™K™-Kšœ ™——K™-Kšœ™K™—K™šœ ™Kšœ1œ™;Kšœ™šœ Ÿ6™CKšœ1œ™;K™Kšœœ™—™šœ6œ™@Kšœ1œ™;—K™Kšœ™——KšœŸ™—KšœŸ™K™—šœ(œ%™Qšœ™ Kšœ œœ™FK™"K™KšœI™IKš™—Kšœ ™Kšœ œ˜——KšœŸ˜K˜—K™Kšœ™K™K™Kšœ+™+šžœ œœ˜LKšœœ ˜*—K˜KšœŸ ˜K˜K˜—Kšœ˜˜AK˜Q—Kšœ@œ8œ˜’K˜O˜3K˜…—K˜hK˜ZK˜¨˜CK˜<—K˜DK˜—…—(ΆΥΐ