DIRECTORY BansheeTest USING [RunRepairMode, RunServeTestMode], BasicTime USING [GetGMT, GetUniversalID, gmtEpoch, GMT, NetworkAddress, SecondsSinceEpoch], ControlMessages USING [Key], D1Test USING [RunRepairMode, RunServeTestMode], DecomposerControl USING [DocumentInProgress, SetBannerMode, Status, UnloadOldFonts], FaxTest USING [RunServeTestMode], FontConverter USING [ConvertFontFile, CreateResources, DestroyResources, ErrorCode], ForwardingControl USING [SetTargetPrintService], FX3500Test USING [RunRepairMode, RunServeTestMode], MarkerControl USING [EngineSpecific], NSAssignedTypes USING [FileType], NSDataStream USING [Source], NSFile USING [Attribute, AttributesProc, ChangeAttributes, Close, Create, Delete, DeleteByName, Error, Handle, ID, List, Move, neverBackup, nullHandle, nullID, OpenByName, OpenChild, Replace, Scope, Selections, Session, Store, Time], NSName USING [Name], NSString USING [AppendString, EquivalentStrings, nullString, String, StringFromMesaString], PaperHandling USING [Banner, PaperFeed, PaperStacking, PaperSupply, PrintOrder, Registration], PaperTypes USING [PaperMMDimension], PrintQueue USING [CopyStringIn, nilQueueObjectHandle, QueueObjectHandle, Requeue], PSAssignedTypes USING [tFont200Rotated90, tFont300Rotated0, tFont300Rotated90, tTestPatterns], PSAsyncMsg USING [ExpandArrayAndPutString, Insert], PSCommand USING [allFiles, allFontPackages, Error, FaxTransmissionRetryReason, FileType, FileProc, FileFilter, FontFilter, FontProc, FontType, maxPhoneNoLength, PrintFileOptions], PSCommandInternal USING [DisablePrinting, DisableQueuing, EnablePrinting, EnableQueuing, fontsNoticed, markerProcs, PutAsyncMsgFromKey, state, stateSpace, testPatternsNoticed], PSKMessages USING [GetHandle], PSState USING [OperationState], PSVolume USING [Error, GetDefaultSession, GetDirectory], RavenTest USING [RunRepairMode, RunServeTestMode], Space USING [ForceOut], String USING [AppendDecimal, AppendLongDecimal], TargetPS USING [Error, GetPrinterProperties, GetPrinterStatus], TargetPSStatus USING [Communication, Current, Properties], TestPattern USING [CatalogTPs, Locate, NotFound], XMessage USING [Handle, MsgKey]; PSCommandBImpl: CEDAR MONITOR IMPORTS BansheeTest, D1Test, DecomposerControl, FaxTest, FontConverter, ForwardingControl, FX3500Test, NSFile, NSString, PrintQueue, PSAsyncMsg, PSCommand, PSCommandInternal, PSKMessages, PSVolume, RavenTest, Space, String, System, TargetPS, TestPattern EXPORTS PSCommand, PSCommandInternal = BEGIN OPEN PSCommandInternal; session: NSFile.Session = PSVolume.GetDefaultSession[]; nsNil: NSString.String = NSString.nullString; controlMsgs: XMessage.Handle _ PSKMessages.GetHandle[control]; ListFonts: PUBLIC PROCEDURE [proc: PSCommand.FontProc, filter: PSCommand.FontFilter _ PSCommand.allFontPackages] = BEGIN --NOT MONITORED dirH: NSFile.Handle _ NSFile.nullHandle; selections: NSFile.Selections = [[createdOn: TRUE, dataSize: TRUE, name: TRUE, type: TRUE]]; scope: NSFile.Scope _ []; nameAttribute: name NSFile.Attribute; ListFontPackage: NSFile.AttributesProc = BEGIN continue _ proc[cdFont, attributes.name, attributes.dataSize, attributes.createdOn]; END; --ListFontPackage dirH _ PSVolume.GetDirectory[SELECT state.option FROM bansheeDl, d1 => PSAssignedTypes.tFont300Rotated90, fax295, fax495 => PSAssignedTypes.tFont200Rotated90, fx3500, feps9700, raven => PSAssignedTypes.tFont300Rotated0, ENDCASE => ERROR ! PSVolume.Error => GOTO Exit]; IF filter.packageName # nsNil THEN BEGIN nameAttribute _ [name[filter.packageName]]; scope.filter _ [matches[nameAttribute]]; END; NSFile.List[directory: dirH, proc: ListFontPackage, selections: selections, scope: scope, session: session]; EXITS Exit => NULL; END; --ListFonts InstallFont: PUBLIC PROCEDURE [ type: PSCommand.FontType, packageName: NSString.String, createDate: NSFile.Time, data: NSDataStream.Source, packageSizeHintInBytes: LONG CARDINAL _ 0] = BEGIN --MONITORED OPERATION fileHandle, fontDir: NSFile.Handle; newFile: BOOLEAN _ FALSE; fontFileType: NSAssignedTypes.FileType _ SELECT state.option FROM d1 => PSAssignedTypes.tFont300Rotated90, fax295, fax495 => PSAssignedTypes.tFont200Rotated90, bansheeDl, feps9700, fx3500, raven => PSAssignedTypes.tFont300Rotated0 ENDCASE => ERROR; IF packageName # NSString.nullString AND data.type # none THEN BEGIN CheckAndUpdateCurrentMode[fromMode: normal, toMode: fileWrite]; DecomposerControl.UnloadOldFonts[ ! DecomposerControl.DocumentInProgress => { ResetCurrentMode[]; ERROR PSCommand.Error[[documentInProgress[]]]} ]; PSCommandInternal.fontsNoticed _ FALSE; fontDir _ PSVolume.GetDirectory[fontFileType]; fileHandle _ NSFile.OpenByName[ fontDir, packageName, , session ! NSFile.Error => IF error = [access[fileNotFound]] THEN {newFile _ TRUE; CONTINUE} ELSE {ResetCurrentMode[]; REJECT}]; IF newFile THEN BEGIN storeFileAttributes: ARRAY [0..5) OF NSFile.Attribute _ [ [createdOn[createDate]], [type[fontFileType]], [name[packageName]], [backedUpOn[NSFile.neverBackup]], [dataSize[packageSizeHintInBytes]]]; storeFileAttributesDesc: LONG DESCRIPTOR FOR ARRAY OF NSFile.Attribute _ DESCRIPTOR[NIL, 0]; IF packageSizeHintInBytes # 0 THEN storeFileAttributesDesc _ DESCRIPTOR[storeFileAttributes] ELSE storeFileAttributesDesc _ DESCRIPTOR[BASE[storeFileAttributes], 4]; fileHandle _ NSFile.Store[ fontDir, data, storeFileAttributesDesc, , session ! NSFile.Error => { ResetCurrentMode[]; SELECT error FROM [transfer[aborted]] => ERROR PSCommand.Error[[abortedByClient[]]]; [space[mediumFull]] => ERROR PSCommand.Error[[insufficientSpace[]]]; ENDCASE => ERROR PSCommand.Error[[systemError[]]]} ]; END ELSE BEGIN --this font package already exist on the server replaceFileAttributes: ARRAY [0..2) OF NSFile.Attribute _ [ [createdOn[createDate]], [dataSize[packageSizeHintInBytes]]]; replaceFileAttributesDesc: LONG DESCRIPTOR FOR ARRAY OF NSFile.Attribute _ DESCRIPTOR[NIL, 0]; IF packageSizeHintInBytes # 0 THEN replaceFileAttributesDesc _ DESCRIPTOR[replaceFileAttributes] ELSE replaceFileAttributesDesc _ DESCRIPTOR[BASE[replaceFileAttributes], 1]; NSFile.Replace[ fileHandle, data, replaceFileAttributesDesc, session ! NSFile.Error => { ResetCurrentMode[]; SELECT error FROM [transfer[aborted]] => ERROR PSCommand.Error[[abortedByClient[]]]; [space[mediumFull]] => ERROR PSCommand.Error[[insufficientSpace[]]]; ENDCASE => ERROR PSCommand.Error[[systemError[]]]} ]; IF state.option = bansheeDl THEN BEGIN newFontTypeAttribute: ARRAY [0..1) OF NSFile.Attribute _ [[type[PSAssignedTypes.tFont300Rotated0]]]; NSFile.ChangeAttributes [ file: fileHandle, attributes: DESCRIPTOR[newFontTypeAttribute], session: session]; END; END; NSFile.Close[fileHandle, session]; ResetCurrentMode[]; --Also backs up the state record. END ELSE ERROR PSCommand.Error[[invalidParameters[]]]; END; --InstallFont DeleteFont: PUBLIC PROCEDURE [packageName: NSString.String] = BEGIN --MONITORED OPERATION fontDir: NSFile.Handle; IF packageName # NSString.nullString THEN BEGIN CheckAndUpdateCurrentMode[fromMode: normal, toMode: fileDelete]; PSCommandInternal.fontsNoticed _ FALSE; DecomposerControl.UnloadOldFonts[ ! DecomposerControl.DocumentInProgress => { ResetCurrentMode[]; ERROR PSCommand.Error[[documentInProgress[]]]} ]; fontDir _ PSVolume.GetDirectory[SELECT state.option FROM bansheeDl, d1 => PSAssignedTypes.tFont300Rotated90, fax295, fax495 => PSAssignedTypes.tFont200Rotated90, feps9700, fx3500, raven => PSAssignedTypes.tFont300Rotated0, ENDCASE => ERROR]; NSFile.DeleteByName[ fontDir, packageName, session ! NSFile.Error => { ResetCurrentMode[]; IF error = [access[fileNotFound]] THEN ERROR PSCommand.Error[[fileNotFound[]]] ELSE REJECT}]; ResetCurrentMode[]; END ELSE ERROR PSCommand.Error[[invalidParameters[]]]; END; --DeleteFont RotateFonts90: PUBLIC PROCEDURE = BEGIN dirH: NSFile.Handle _ NSFile.nullHandle; selections: NSFile.Selections = [[fileID: TRUE, type: TRUE, createdOn: TRUE, name: TRUE]]; fontFileAttributes: ARRAY [0..3) OF NSFile.Attribute; oldFontFile, newFontFile: NSFile.Handle _ NSFile.nullHandle; fontConverterError: FontConverter.ErrorCode _ none; insertArray: ARRAY [0..1) OF PSAsyncMsg.Insert; rotationActuallyAttempted: BOOLEAN _ FALSE; fontsRotated: CARDINAL _ 0; count: LONG STRING _ [10]; startRotation, endRotation: System.GMT _ System.gmtEpoch; graphicsFontName: NSString.String = Str["Xerox.Graphics.Newvec"L]; Rotate90: NSFile.AttributesProc = BEGIN SELECT attributes.type FROM PSAssignedTypes.tFont300Rotated0 => BEGIN IF NSString.EquivalentStrings[attributes.name, graphicsFontName] THEN BEGIN newAttribute: ARRAY [0..1) OF NSFile.Attribute _ [[type[PSAssignedTypes.tFont300Rotated90]]]; graphicsFontFile: NSFile.Handle _ NSFile.OpenChild[ directory: dirH, id: attributes.fileID, session: session]; NSFile.ChangeAttributes[ file: graphicsFontFile, attributes: DESCRIPTOR[newAttribute], session: session]; NSFile.Close[file: graphicsFontFile, session: session]; RETURN [continue: TRUE]; --go on to other font files in directory END; IF NOT rotationActuallyAttempted THEN BEGIN DecomposerControl.UnloadOldFonts[ ! DecomposerControl.DocumentInProgress => ERROR PSCommand.Error[[documentInProgress[]]]]; PSCommandInternal.fontsNoticed _ FALSE; insertArray[0] _ [m: [domain: controlMsgs, key: XKey[mBanshee]]]; PSCommandInternal.PutAsyncMsgFromKey[ msg: [domain: controlMsgs, key: XKey[mBeginFontRotation]], insertArray: DESCRIPTOR[insertArray]]; rotationActuallyAttempted _ TRUE; END; insertArray[0] _ [s: attributes.name]; PSCommandInternal.PutAsyncMsgFromKey[ msg: [domain: controlMsgs, key: XKey[mRotatingFont]], insertArray: DESCRIPTOR[insertArray]]; fontFileAttributes[1] _ [createdOn[attributes.createdOn]]; fontFileAttributes[2] _ [name[attributes.name]]; oldFontFile _ NSFile.OpenChild[ directory: dirH, id: attributes.fileID, session: session]; newFontFile _ NSFile.Create[ directory: NSFile.nullHandle, attributes: DESCRIPTOR[fontFileAttributes], session: session ! NSFile.Error => BEGIN NSFile.Close[file: oldFontFile, session: session]; insertArray[0] _ [m: [domain: controlMsgs, key: XKey[mInsufficientVolSpace]]]; PSCommandInternal.PutAsyncMsgFromKey[ msg: [domain: controlMsgs, key: XKey[mRotationError]], insertArray: DESCRIPTOR[insertArray]]; GOTO Abort; END; ]; fontConverterError _ FontConverter.ConvertFontFile[ session: session, fileOld: oldFontFile, fileNew: newFontFile, rotationNew: 90 --degrees--, resolutionNew: dpi300]; IF fontConverterError = none THEN BEGIN NSFile.Move[file: newFontFile, destination: dirH, session: session]; NSFile.Close[file: newFontFile, session: session]; NSFile.Delete[file: oldFontFile, session: session]; fontsRotated _ fontsRotated + 1; END ELSE BEGIN NSFile.Close[file: oldFontFile, session: session]; NSFile.Delete[file: newFontFile, session: session]; insertArray[0] _ [m: [domain: controlMsgs, key: XKey[SELECT fontConverterError FROM noFileSpace => mInsufficientVolSpace, ENDCASE => mUnknown]]]; PSCommandInternal.PutAsyncMsgFromKey[ msg: [domain: controlMsgs, key: XKey[mRotationError]], insertArray: DESCRIPTOR[insertArray]]; END; END; PSAssignedTypes.tFont300Rotated90 => NULL; ENDCASE => ERROR; EXITS Abort => RETURN [continue: FALSE]; END; --Rotate90 IF state.option # bansheeDl THEN ERROR; IF DecomposerControl.Status[].decomposing THEN ERROR PSCommand.Error[[documentInProgress[]]]; dirH _ PSVolume.GetDirectory[PSAssignedTypes.tFont300Rotated0]; fontFileAttributes[0] _ [type[PSAssignedTypes.tFont300Rotated90]]; startRotation _ System.GetGMT[]; FontConverter.CreateResources[]; --gets file space for rotating fonts NSFile.List[directory: dirH, proc: Rotate90, selections: selections, session: session]; FontConverter.DestroyResources[]; --releases file space used for rotating fonts endRotation _ System.GetGMT[]; IF rotationActuallyAttempted THEN BEGIN count.length _ 0; String.AppendDecimal[s: count, n: fontsRotated]; insertArray[0] _ [s: Str[count]]; PSCommandInternal.PutAsyncMsgFromKey[ msg: [domain: controlMsgs, key: XKey[mRotationDone]], insertArray: DESCRIPTOR[insertArray]]; IF state.formatterTrace # none AND fontsRotated > 0 THEN BEGIN nsRotationTime: NSString.String _ Str[ "Total Rotation Time: <1> minutes, <2> seconds"L]; stringArray: ARRAY [0..2) OF NSString.String; sMinutes: LONG STRING _ [10]; sSeconds: LONG STRING _ [10]; startSinceEpoch: LONG CARDINAL _ System.SecondsSinceEpoch[startRotation]; endSinceEpoch: LONG CARDINAL _ System.SecondsSinceEpoch[endRotation]; timeElapsed, minElapsed, secElapsed: LONG CARDINAL _ 0; IF endSinceEpoch > startSinceEpoch THEN BEGIN timeElapsed _ endSinceEpoch - startSinceEpoch; minElapsed _ timeElapsed/60; secElapsed _ timeElapsed MOD 60; END; String.AppendLongDecimal[sMinutes, minElapsed]; String.AppendLongDecimal[sSeconds, secElapsed]; stringArray[0] _ Str[sMinutes]; stringArray[1] _ Str[sSeconds]; PSAsyncMsg.ExpandArrayAndPutString[nsRotationTime, DESCRIPTOR[stringArray]]; END; END; END; --RotateFonts90 ListFiles: PUBLIC PROCEDURE [proc: PSCommand.FileProc, filter: PSCommand.FileFilter _ PSCommand.allFiles] = BEGIN --NOT MONITORED dirH: NSFile.Handle _ NSFile.nullHandle; selections: NSFile.Selections = [[createdOn: TRUE, dataSize: TRUE, name: TRUE]]; scope: NSFile.Scope _ []; nameAttribute: name NSFile.Attribute; ListFile: NSFile.AttributesProc = BEGIN continue _ proc[testPattern, attributes.name, attributes.dataSize, attributes.createdOn]; END; --ListFile dirH _ PSVolume.GetDirectory[PSAssignedTypes.tTestPatterns ! PSVolume.Error => GOTO Exit]; IF filter.name # nsNil THEN BEGIN nameAttribute _ [name[filter.name]]; scope.filter _ [matches[nameAttribute]]; END; NSFile.List[directory: dirH, proc: ListFile, selections: selections, scope: scope, session: session]; EXITS Exit => NULL; END; --ListFiles InstallFile: PUBLIC PROCEDURE [ type: PSCommand.FileType, name: NSString.String, createDate: NSFile.Time, data: NSDataStream.Source, fileSizeHintInBytes: LONG CARDINAL _ 0] = BEGIN --MONITORED OPERATION fileHandle, tpDirectory: NSFile.Handle; newFile: BOOLEAN _ FALSE; storeFileAttributes: ARRAY [0..3) OF NSFile.Attribute _ [ [createdOn[createDate]], [type[PSAssignedTypes.tTestPatterns]], [name[name]]]; replaceFileAttributes: ARRAY [0..1) OF NSFile.Attribute _ [ [createdOn[createDate]]]; IF name # NSString.nullString AND data.type # none AND type = testPattern THEN BEGIN CheckAndUpdateCurrentMode[fromMode: normal, toMode: fileWrite]; tpDirectory _ PSVolume.GetDirectory[PSAssignedTypes.tTestPatterns]; fileHandle _ NSFile.OpenByName[ tpDirectory, name, , session ! NSFile.Error => IF error = [access[fileNotFound]] THEN {newFile _ TRUE; CONTINUE} ELSE {ResetCurrentMode[]; REJECT}]; IF newFile THEN BEGIN storeFileAttributes: ARRAY [0..4) OF NSFile.Attribute _ [ [createdOn[createDate]], [type[PSAssignedTypes.tTestPatterns]], [name[name]], [dataSize[fileSizeHintInBytes]]]; storeFileAttributesDesc: LONG DESCRIPTOR FOR ARRAY OF NSFile.Attribute _ DESCRIPTOR[NIL, 0]; IF fileSizeHintInBytes # 0 THEN storeFileAttributesDesc _ DESCRIPTOR[storeFileAttributes] ELSE storeFileAttributesDesc _ DESCRIPTOR[BASE[storeFileAttributes], 3]; fileHandle _ NSFile.Store[ tpDirectory, data, LONG[DESCRIPTOR[storeFileAttributes]], , session ! NSFile.Error => { ResetCurrentMode[]; SELECT error FROM [transfer[aborted]] => ERROR PSCommand.Error[[abortedByClient[]]]; [space[mediumFull]] => ERROR PSCommand.Error[[insufficientSpace[]]]; ENDCASE => ERROR PSCommand.Error[[systemError[]]]} ] END ELSE BEGIN --this font package already exist on the server replaceFileAttributes: ARRAY [0..2) OF NSFile.Attribute _ [ [createdOn[createDate]], [dataSize[fileSizeHintInBytes]]]; replaceFileAttributesDesc: LONG DESCRIPTOR FOR ARRAY OF NSFile.Attribute _ DESCRIPTOR[NIL, 0]; IF fileSizeHintInBytes # 0 THEN replaceFileAttributesDesc _ DESCRIPTOR[replaceFileAttributes] ELSE replaceFileAttributesDesc _ DESCRIPTOR[BASE[replaceFileAttributes], 1]; NSFile.Replace[ fileHandle, data, LONG[DESCRIPTOR[replaceFileAttributes]], session ! NSFile.Error => { ResetCurrentMode[]; SELECT error FROM [transfer[aborted]] => ERROR PSCommand.Error[[abortedByClient[]]]; [space[mediumFull]] => ERROR PSCommand.Error[[insufficientSpace[]]]; ENDCASE => ERROR PSCommand.Error[[systemError[]]]} ]; END; NSFile.Close[fileHandle, session]; PSCommandInternal.testPatternsNoticed _ FALSE; ResetCurrentMode[]; END ELSE ERROR PSCommand.Error[[invalidParameters[]]]; END; --InstallFile DeleteFile: PUBLIC PROCEDURE [name: NSString.String] = BEGIN --MONITORED OPERATION tpDirectory: NSFile.Handle; IF name # NSString.nullString THEN BEGIN CheckAndUpdateCurrentMode[fromMode: normal, toMode: fileDelete]; tpDirectory _ PSVolume.GetDirectory[PSAssignedTypes.tTestPatterns]; NSFile.DeleteByName[ tpDirectory, name, session ! NSFile.Error => { ResetCurrentMode[]; IF error = [access[fileNotFound]] THEN ERROR PSCommand.Error[[fileNotFound[]]] ELSE REJECT}]; PSCommandInternal.testPatternsNoticed _ FALSE; ResetCurrentMode[]; END ELSE ERROR PSCommand.Error[[invalidParameters[]]]; END; --DeleteFile PrintFile: PUBLIC PROCEDURE [ fileName, senderName: NSString.String, copies: CARDINAL, options: PSCommand.PrintFileOptions] = BEGIN --NOT MONITORED fileID: NSFile.ID _ NSFile.nullID; qOH: PrintQueue.QueueObjectHandle; wrongPrintingOption, badPhoneNumber, badOptions: BOOLEAN _ FALSE; WITH o: options SELECT FROM fax495 => IF NOT o.localPrint AND NOT o.transmit THEN RETURN; ENDCASE; IF NOT PSCommandInternal.testPatternsNoticed THEN BEGIN TestPattern.CatalogTPs[]; PSCommandInternal.testPatternsNoticed _ TRUE; END; [fileID,] _ TestPattern.Locate[fileName ! TestPattern.NotFound => {ERROR PSCommand.Error[[fileNotFound[]]]} ]; qOH _ PrintQueue.Requeue[ qOH:, fromQueue: tpInactive, toQueue: temp]; -- so we can add info to it IF qOH = PrintQueue.nilQueueObjectHandle THEN BEGIN -- none in tpInactive queue??? qOH _ PrintQueue.Requeue[ qOH:, fromQueue: inactive, toQueue: temp]; IF qOH = PrintQueue.nilQueueObjectHandle THEN ERROR PSCommand.Error[[systemError[]]]; END; qOH.fileID _ fileID; qOH.uid _ System.GetUniversalID[]; --uid needed so that clients can delete tp jobs by listing documents and getting uid of job to cancel; uid is also used in DecomposerControlImpl qOH.deleteInactiveFile _ FALSE; PrintQueue.CopyStringIn[qOH: qOH, fromString: senderName, toField: sender]; PrintQueue.CopyStringIn[qOH: qOH, fromString: fileName, toField: fileName]; qOH.numberCopies _ copies; qOH.currentStatus _ spooled; qOH.firstPageToPrint _ 1; qOH.lastPageToPrint _ LAST[CARDINAL]; WITH s: state SELECT FROM bansheeDl => BEGIN dStatus: MarkerControl.EngineSpecific _ markerProcs.status[].engine; WITH d: dStatus SELECT FROM bansheeDl => qOH.paper _ d.paper; ENDCASE => ERROR; END; d1 => qOH.paper _ [knownSize: s.paperSize]; fax295 => WITH o: options SELECT FROM fax295 => IF PaperTypes.PaperMMDimension[o.paperSize].short <= s.paperWidth THEN qOH.paper _ [knownSize: o.paperSize] ELSE badOptions _ TRUE; ENDCASE => wrongPrintingOption _ TRUE; fax495 => WITH o: options SELECT FROM fax495 => IF PaperTypes.PaperMMDimension[o.paperSize].short <= s.paperWidth THEN WITH q: qOH SELECT FROM fax495 => BEGIN char: CHARACTER; blankChar: CHARACTER = ' ; q.paper _ [knownSize: o.paperSize]; IF o.localPrint THEN q.localPrintStatus _ queued; IF o.transmit THEN BEGIN IF o.phoneNumber.length > PSCommand.maxPhoneNoLength THEN badPhoneNumber _ TRUE ELSE BEGIN q.phoneNoCount _ 1; q.transmitData[0].status _ queued; q.transmitData[0].phoneNumber.length _ o.phoneNumber.length; FOR i: CARDINAL IN [0..o.phoneNumber.length) DO char _ LOOPHOLE[o.phoneNumber.bytes[i]]; SELECT char FROM IN ['0..'9], '-, '(, '), 'P, '*, '#, blankChar => q.transmitData[0].phoneNumber.bytes[i] _ o.phoneNumber.bytes[i]; ENDCASE => badPhoneNumber _ TRUE; ENDLOOP; END; END; END; ENDCASE => ERROR --Queue object and state record do not agree on printing option. ELSE badOptions _ TRUE; ENDCASE => wrongPrintingOption _ TRUE; feps9700 => qOH.paper _ [knownSize: s.paperSupply.size1]; fx3500 => WITH o: options SELECT FROM fx3500 => BEGIN dStatus: MarkerControl.EngineSpecific _ markerProcs.status[].engine; WITH d: dStatus SELECT FROM fx3500 => IF o.tray = top THEN qOH.paper _ [knownSize: d.paperSupply.size2] ELSE --tray = bottom or either (forced to bottom) qOH.paper _ [knownSize: d.paperSupply.size1]; ENDCASE => ERROR; END; ENDCASE => wrongPrintingOption _ TRUE; raven => WITH o: options SELECT FROM raven => IF o.tray = top THEN qOH.paper _ [knownSize: s.paperSupply.size2] ELSE --tray = bottom or either (forced to bottom) qOH.paper _ [knownSize: s.paperSupply.size1]; ENDCASE => wrongPrintingOption _ TRUE; ENDCASE => wrongPrintingOption _ TRUE; IF wrongPrintingOption THEN BEGIN [] _ PrintQueue.Requeue[qOH: qOH, fromQueue: temp, toQueue: inactive]; ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; END; IF badPhoneNumber THEN BEGIN [] _ PrintQueue.Requeue[qOH: qOH, fromQueue: temp, toQueue: inactive]; ERROR PSCommand.Error[[invalidPhoneNumber[]]]; END; IF badOptions THEN BEGIN [] _ PrintQueue.Requeue[qOH: qOH, fromQueue: temp, toQueue: inactive]; ERROR PSCommand.Error[[parameterOptionNotAvailable[]]]; END; [] _ PrintQueue.Requeue[qOH: qOH, fromQueue: temp, toQueue: tpSpooled]; state.testPatternsPrinted.total _ state.testPatternsPrinted.total + 1; Space.ForceOut[stateSpace]; END; --PrintFile SetBanner: PUBLIC PROCEDURE [banner: PaperHandling.Banner] = BEGIN WITH s: state SELECT FROM bansheeDl => WITH b: banner SELECT FROM bansheeDl => BEGIN s.banner _ b.banner; WITH m: markerProcs SELECT FROM bansheeDl => m.setBanner[b.banner]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. DecomposerControl.SetBannerMode[ enableBanner: b.banner # suppressed]; END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; d1 => WITH b: banner SELECT FROM d1 => BEGIN s.banner _ b.banner; WITH m: markerProcs SELECT FROM d1 => m.setBanner[b.banner]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. DecomposerControl.SetBannerMode[ enableBanner: b.banner # suppressed]; END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; fax295 => WITH b: banner SELECT FROM fax295 => BEGIN s.banner _ b.banner; WITH m: markerProcs SELECT FROM fax295 => m.setBanner[b.banner]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. DecomposerControl.SetBannerMode[ enableBanner: b.banner # suppressed]; END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; fax495 => WITH b: banner SELECT FROM fax495 => BEGIN s.banner _ b.banner; WITH m: markerProcs SELECT FROM fax495 => m.setBanner[b.banner]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. DecomposerControl.SetBannerMode[ enableBanner: b.banner.local # suppressed OR b.banner.remote # suppressed]; END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; feps9700 => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; fx3500 => WITH b: banner SELECT FROM fx3500 => BEGIN s.banner _ b.banner; WITH m: markerProcs SELECT FROM fx3500 => m.setBanner[b.banner]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. DecomposerControl.SetBannerMode[ enableBanner: b.banner # suppressed]; END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; raven => WITH b: banner SELECT FROM raven => BEGIN s.banner _ b.banner; WITH m: markerProcs SELECT FROM raven => m.setBanner[b.banner]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. DecomposerControl.SetBannerMode[ enableBanner: b.banner # suppressed]; END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; ENDCASE => ERROR; Space.ForceOut[stateSpace]; END; --SetBanner SetPrintOrder: PUBLIC PROCEDURE [printOrder: PaperHandling.PrintOrder] = BEGIN state.printOrder _ printOrder; markerProcs.setPrintOrder[state.printOrder]; Space.ForceOut[stateSpace]; END; --SetPrintOrder SetMultipleCopies: PUBLIC PROCEDURE [ multLocalCopiesAllowed, multRemoteCopiesAllowed: BOOLEAN] = BEGIN --Applies to fax495 WITH s: state SELECT FROM fax495 => BEGIN s.multLocalCopiesAllowed _ multLocalCopiesAllowed; s.multRemoteCopiesAllowed _ multRemoteCopiesAllowed; END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; WITH m: markerProcs SELECT FROM fax495 => m.setMultipleCopies[multLocalCopiesAllowed, multRemoteCopiesAllowed]; ENDCASE => ERROR; --state and markerProcs disagree about printing option Space.ForceOut[stateSpace]; END; --SetMultipleCopies SetPaperFeed: PUBLIC PROCEDURE [paperFeed: PaperHandling.PaperFeed] = BEGIN --Applies to raven and fx3500 WITH s: state SELECT FROM raven => BEGIN s.paperFeed _ paperFeed; WITH m: markerProcs SELECT FROM raven => m.setFeeding[paperFeed]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. END; fx3500 => BEGIN s.paperFeed _ paperFeed; WITH m: markerProcs SELECT FROM fx3500 => m.setFeeding[paperFeed]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; Space.ForceOut[stateSpace]; END; --SetPaperFeed SetPaperStacking: PUBLIC PROCEDURE [paperStacking: PaperHandling.PaperStacking] = BEGIN --Applies to raven WITH s: state SELECT FROM raven => IF s.engineBuild > b1 THEN BEGIN s.paperStacking _ paperStacking; WITH m: markerProcs SELECT FROM raven => m.setStacking[paperStacking]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. END ELSE ERROR PSCommand.Error[[parameterOptionNotAvailable[]]]; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; Space.ForceOut[stateSpace]; END; --SetPaperStacking SetPaperSupply: PUBLIC PROCEDURE [paperSupply: PaperHandling.PaperSupply] = BEGIN --Applies to raven, fax495 and fax295 WITH s: state SELECT FROM raven => WITH p: paperSupply SELECT FROM raven => BEGIN SELECT p.paper.size1 FROM letter, legal, a4 => s.paperSupply.size1 _ p.paper.size1; ENDCASE => ERROR PSCommand.Error[[parameterOptionNotAvailable[]]]; SELECT p.paper.size2 FROM letter, legal, a4 => s.paperSupply.size2 _ p.paper.size2; ENDCASE => ERROR PSCommand.Error[[parameterOptionNotAvailable[]]]; WITH m: markerProcs SELECT FROM raven => m.setPaper[s.paperSupply]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; fax295 => WITH p: paperSupply SELECT FROM fax295 => BEGIN SELECT p.paperWidth FROM PaperTypes.PaperMMDimension[letter].short, PaperTypes.PaperMMDimension[a4].short => s.paperWidth _ p.paperWidth; ENDCASE => ERROR PSCommand.Error[[parameterOptionNotAvailable[]]]; WITH m: markerProcs SELECT FROM fax295 => m.setPaper[s.paperWidth]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; fax495 => WITH p: paperSupply SELECT FROM fax495 => BEGIN SELECT p.paperWidth FROM PaperTypes.PaperMMDimension[letter].short, PaperTypes.PaperMMDimension[a4].short => s.paperWidth _ p.paperWidth; ENDCASE => ERROR PSCommand.Error[[parameterOptionNotAvailable[]]]; WITH m: markerProcs SELECT FROM fax495 => m.setPaper[s.paperWidth]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; Space.ForceOut[stateSpace]; END; --SetPaperSupply SetRegistration: PUBLIC PROCEDURE [registration: PaperHandling.Registration] = BEGIN --Applies to raven and fx3500 WITH s: state SELECT FROM d1 => WITH r: registration SELECT FROM d1 => BEGIN s.registration _ r.reg; WITH m: markerProcs SELECT FROM d1 => m.setRegistration[r.reg]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; fx3500 => WITH r: registration SELECT FROM fx3500 => BEGIN s.registration _ r.reg; WITH m: markerProcs SELECT FROM fx3500 => m.setRegistration[r.reg]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; raven => WITH r: registration SELECT FROM raven => BEGIN s.registration _ r.reg; WITH m: markerProcs SELECT FROM raven => m.setRegistration[r.reg]; ENDCASE => ERROR; --Marker procs engine type disagrees with state record. END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; Space.ForceOut[stateSpace]; END; --SetRegistration SetTransmissionResolution: PUBLIC PROCEDURE [fineResolutionSupported: BOOLEAN] = BEGIN --Applies to fax495 WITH s: state SELECT FROM fax495 => s.fineResolutionSupported _ fineResolutionSupported; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; WITH m: markerProcs SELECT FROM fax495 => m.setTransmissionResolution[fineResolutionSupported]; ENDCASE => ERROR; --state and markerProcs disagree about printing option Space.ForceOut[stateSpace]; END; --SetTransmissionResolution SetTransmissionRetries: PUBLIC PROCEDURE [ retries: CARDINAL, delayInSeconds: LONG CARDINAL, reason: PSCommand.FaxTransmissionRetryReason _ always] = BEGIN --Applies to fax495 WITH s: state SELECT FROM fax495 => BEGIN IF reason = noConnectionMade OR reason = always THEN BEGIN s.retries[noConnection].count _ retries; s.retries[noConnection].delayInSecs _ delayInSeconds; END; IF reason = transmitError OR reason = always THEN BEGIN s.retries[transmitError].count _ retries; s.retries[transmitError].delayInSecs _ delayInSeconds; END; END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; WITH m: markerProcs SELECT FROM fax495 => BEGIN IF reason = noConnectionMade OR reason = always THEN m.setTransmissionRetries[noConnection, retries, delayInSeconds]; IF reason = transmitError OR reason = always THEN m.setTransmissionRetries[transmitError, retries, delayInSeconds]; END; ENDCASE => ERROR; --state and markerProcs disagree about printing option Space.ForceOut[stateSpace]; END; --SetTransmissionRetries SetTargetPrintService: PUBLIC PROCEDURE [address: System.NetworkAddress, name: NSName.Name _ NIL] = BEGIN targetStatus: TargetPSStatus.Current _ []; targetProperties: TargetPSStatus.Properties _ []; targetError: TargetPSStatus.Communication _ okay; WITH s: state SELECT FROM feps9700 => BEGIN OPEN s.targetPSName.record; s.targetPSAddress _ address; local.length _ domain.length _ org.length _ 0; IF name # NIL THEN BEGIN local _ NSString.AppendString[to: local, from: name.local]; domain _ NSString.AppendString[to: domain, from: name.domain]; org _ NSString.AppendString[to: org, from: name.org]; END; ForwardingControl.SetTargetPrintService[s.targetPSAddress]; targetStatus _ TargetPS.GetPrinterStatus[s.targetPSAddress ! TargetPS.Error => {targetError _ why; GOTO CantReachTarget}]; targetProperties _ TargetPS.GetPrinterProperties[s.targetPSAddress ! TargetPS.Error => {targetError _ why; GOTO CantReachTarget}]; s.paperSupply.size1 _ targetStatus.paperSupply.size1; s.paperSupply.size2 _ targetStatus.paperSupply.size2; s.twoSidedCopy _ targetProperties.twoSided; s.stapling _ targetProperties.staple; EXITS CantReachTarget => BEGIN s.paperSupply.size1 _ letter; --default first paper size to letter s.paperSupply.size2 _ max; --default second paper size to undefined (none) s.twoSidedCopy _ s.stapling _ FALSE; --default two sided coping and stapling to unavailable Space.ForceOut[stateSpace]; ERROR PSCommand.Error[[targetPS[targetError]]]; END; END; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; Space.ForceOut[stateSpace]; END; --SetTargetPrintService PutPrinterDisplay: PUBLIC PROCEDURE [leftChar, rightChar: CHARACTER _ 0C] = BEGIN WITH m: markerProcs SELECT FROM fx3500 => IF state.mode.current = repair THEN m.putPrinterDisplay[leftChar, rightChar] ELSE ERROR PSCommand.Error[[disallowedInCurrentMode[]]]; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; END; --PutPrinterDisplay GetPrinterDisplay: PUBLIC PROCEDURE RETURNS [leftChar, rightChar: CHARACTER _ 0C] = BEGIN WITH m: markerProcs SELECT FROM fx3500 => IF state.mode.current = repair THEN [leftChar, rightChar] _ m.getPrinterDisplay[] ELSE ERROR PSCommand.Error[[disallowedInCurrentMode[]]]; ENDCASE => ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; END; --GetPrinterDisplay StartDiagnosticMode: PUBLIC PROCEDURE = BEGIN incompatibleOption: BOOLEAN _ FALSE; CheckAndUpdateCurrentMode[fromMode: normal, toMode: diagnostic]; PSCommandInternal.DisablePrinting[]; PSCommandInternal.DisableQueuing[disabledForDiag]; SELECT state.option FROM bansheeDl => BansheeTest.RunServeTestMode[]; d1 => D1Test.RunServeTestMode[]; fax295 => FaxTest.RunServeTestMode[fax295]; fax495 => FaxTest.RunServeTestMode[fax495]; fx3500 => FX3500Test.RunServeTestMode[]; raven => RavenTest.RunServeTestMode[]; ENDCASE => incompatibleOption _ TRUE; ResetCurrentMode[]; PSCommandInternal.EnablePrinting[]; PSCommandInternal.EnableQueuing[]; IF incompatibleOption THEN ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; END; --StartDiagnosticMode StartRepairMode: PUBLIC PROCEDURE = BEGIN incompatibleOption: BOOLEAN _ FALSE; SELECT state.mode.current FROM repair => NULL; --already in repair mode notStarted => CheckAndUpdateCurrentMode[fromMode: notStarted, toMode: repair]; --can go into repair mode before the Start proc is called ENDCASE => CheckAndUpdateCurrentMode[fromMode: normal, toMode: repair]; --otherwise must be in normal mode to go into repair mode PSCommandInternal.DisablePrinting[]; PSCommandInternal.DisableQueuing[disabledForRepair]; SELECT state.option FROM bansheeDl => BansheeTest.RunRepairMode[]; d1 => D1Test.RunRepairMode[]; fx3500 => FX3500Test.RunRepairMode[]; raven => RavenTest.RunRepairMode[]; ENDCASE => incompatibleOption _ TRUE; ResetCurrentMode[]; PSCommandInternal.EnablePrinting[]; PSCommandInternal.EnableQueuing[]; IF incompatibleOption THEN ERROR PSCommand.Error[[incompatiblePrintingOption[]]]; END; --StartRepairMode CheckAndUpdateCurrentMode: ENTRY PROCEDURE [fromMode, toMode: PSState.OperationState] = BEGIN IF state.mode.current = fromMode THEN BEGIN state.mode.returnTo _ state.mode.current; state.mode.current _ toMode; Space.ForceOut[stateSpace]; END ELSE ERROR PSCommand.Error[[disallowedInCurrentMode[]]]; END; --CheckAndUpdateCurrentMode ResetCurrentMode: ENTRY PROCEDURE = BEGIN state.mode.current _ state.mode.returnTo; Space.ForceOut[stateSpace]; END; --ResetCurrentMode XKey: PROCEDURE [key: ControlMessages.Key] RETURNS [xKey: XMessage.MsgKey] = {RETURN[ORD[key]]}; Str: PROCEDURE [s: LONG STRING] RETURNS [ns: NSString.String] = INLINE { RETURN[NSString.StringFromMesaString[s]]}; END. --PSCommandBImpl LOG (when/who/what) ****EARLIER LOG ENTRIES DELETED. See archived version from 8.0. 15-Sep-84 11:35:15 - Jacks - Updated to 9.0 PS interfaces. 31-Oct-84 13:45:40 - Jacks - Added SetTargetPrintService. 14-Nov-84 11:53:52 - Jacks - Updated to second round 9.0 interface changes. 7-Dec-84 9:55:15 - Jacks - Added RotateFonts90. 13-Dec-84 11:41:48 - Jacks - SetTargetPrintService now calls GetPrinterProperties as well as GetPrinterStatus and raises error if can't reach target; removed ControlMessagesExtras. 16-Jan-85 15:50:42 - Jacks - Added "ps" prefix to all new msg keys for 9.0. 28-Feb-85 9:55:31 - Jacks - Added banshee choice to StartDiagnosticMode and StartRepairMode; minor message changes in RotateFonts90; try to rotate all banshee font files even if run out of space with one in RotateFonts90; set file type correctly when doing NSFile.Replace on banshee fonts in InstallFont; now implement InstallFontX and InstallFileX from PSCommandExtras instead of InstallFont and InstallFile from PSCommand (set file sizes prior to reading in files); allow entering repair mode when mode=notStarted. 18-Jun-85 15:18:19 - Jacks - Added copyright notice; updated to PS Euclid interfaces. 26-Jun-85 10:12:43 - Jacks - Added d1 code. 19-Jul-85 17:57:29 - Jacks - Updated to Services Euclid interfaces, including XMessage; added senderName parm to PrintFile. 7-Aug-85 19:36:22 - Jacks - Changed RotateFonts90 to moved rotated files to new tFont300Rotated90 subdirectory; InstallFont and DeleteFont "type" parm changed; set firstPageToPrint and lastPageToPrint in PrintFile. 15-Aug-85 17:08:07 - Jacks - Catch DecomposerControl.DocumentInProgress in InstallFont and DeleteFont. 21-Aug-85 10:09:39 - Jacks - Added fax to StartDiagnosticMode. 5-Sep-85 15:00:10 - Jacks - Added catch phrase to NSFile.Create in Rotate90. 11-Sep-85 15:52:49 - Jacks - Went back to a single 300 dpi font dir in Rotate90; went back to ListFonts, InstallFont and DeleteFont as defined in PSCommand not PSCommandExtras. 24-Sep-85 14:08:34 - Jacks - Folded PSCommandExtras into PSCommand. 15-Oct-85 9:42:31 - Jacks - Converted to new banshee paper in PSState. 6-Nov-85 13:04:01 - Jacks - Get msg handle from PSKMessages; check that decomposer isn't busy in RotateFonts90. 20-May-86 13:23:09 - Jacks - Unload fonts in Rotate90 so that if fonts have already been cataloged, the old files can be deleted. PSCommandBImpl.mesa Copyright (C) Xerox Corporation 1983, 1984, 1985, 1986. All rights reserved. Last edited by Jacks 20-May-86 13:23:46 Ruseli Binsol: October 17, 1986 10:17:13 am PDT <> Message domain handle: =============================== PUBLIC PROCEDURES: =============================== ====================================== Font Operations: ====================================== [attributes] RETURNS [continue]-- It is TBD how we will tell one font type from another when we have font types other that cdFont. In the current implementation font type in the filter is ignored. Both rotated and unrotated banshee fonts will get listed since tFont300Rotated90 and tFont300Rotated0 fonts are in the same directory. Font installed is assumed to be of correct format for current printing option!! Banshee fonts initially have type tFont300Rotated0 before they are rotated and the type is changed to tFont300Rotated90. <> <> <> <> <> Exported by PSCommandInternal: Rotates installed fonts by 90 degrees. Currently used to rotate raven fonts for banshee. [attributes] RETURNS [continue]-- If the font has raven font file type, rotate it for banshee... The Newvec font should not be rotated. We change the file type to the banshee file type anyway so we won't have to keep checking to see if it needs to be rotated... <> Display name of font file being rotated... Create temporary new font file, which will be made permanent when rotation is completed... Not enough space even for small temp file! Display async error message... Move new font file to font directory, thus making the file permanent... Delete the old file... Display async error message... We will continue to list the rest of the font files installed in case there are smaller ones that can be rotated successfully. Have NSFile enumerate each font in the directory and rotate the font if necessary... Display closing message giving number of font files rotated... Display rotation time if tracing is on... ======= ====================================== File Operations (for Test Patterns, etc.): ============================================= NOTE: Currently the only type of files that can be listed are test patterns. Must change code if new file types are added. [attributes] RETURNS [continue]-- The only kind of files this proc handles right now are test patterns. <> <> <> <> The only kind of files this proc handles right now are test patterns. ================================================= Set Operational Parameters: (NONE ARE MONITORED) ================================================= ****Apply to all printing options:**** ****Apply to certain printing options:**** Currently the only valid paper sizes for the raven are letter, legal and a4. This code will have to be changed if other valid paper sizes are added. ============================================= Remote9700 Operation: (NONE ARE MONITORED) ============================================= =================================================== FX3500 Display Operations: (NONE ARE MONITORED) =================================================== ============================================================= Print Service Control Operations: (MONITORED OPERATIONS) ============================================================= ========================== PRIVATE PROCEDURES ========================== Κ"Ώ˜codešœ™KšœL™LKšœ'™'K™/—K˜K™όK˜šΟk ˜ Kšœ œ#˜4Kšœ œœœ%˜[Kšœœ˜Kšœœ#˜/Kšœœ=˜TKšœœ˜!KšœœA˜TKšœœ˜0Kšœ œ#˜3Kšœœ˜%Kšœœ ˜!Kšœ œ ˜Kšœœcœx˜ιKšœœ˜Kšœ œM˜[KšœœK˜^Kšœ œ˜$Kšœ œB˜RKšœœI˜^Kšœ œ$˜4Kšœ œ€˜³Kšœœ™˜°Kšœ œ ˜Kšœœ˜Kšœ œ*˜8Kšœ œ#˜2Kšœœ ˜Kšœœ$˜0Kšœ œ1˜?Kšœœ&˜:Kšœ œ ˜1Kšœ œ˜ —K˜šΟnœœ˜Kšœφ˜ύKšœ ˜,Kšœ˜K˜K˜7K˜-K˜Kšœ™K˜>K˜Kšœ™Kšœ™Kšœ™K˜Kšœ&™&Kšœ™Kšœ&™&K˜šž œœ œ˜7Kšœ;œΟc˜QK˜(Kš œ-œ œœœ˜\K˜K˜%K˜šžœ˜.Kšœ!™!Kšœ£™£K˜TKšœŸ˜—K˜šœœ˜5˜3Kšœ†™†—K˜4K˜™>Kšœ$˜)˜Kšœ:™:Kšœ9™9Kšœ1™1šœ?œ˜Kšœœœ˜0K˜,—˜3K˜:—˜Kšœ$ œ˜=K˜—K˜7Kšœ œŸ(˜AKšœ˜————˜KšœU™UKšœU™UKšœ™šœœœ˜+˜!˜*Kšœ*˜/——Kšœ!œ˜'K˜A˜%K˜;Kšœ  œ˜&—Kšœœ˜!šœ˜K˜——Kšœ*™*K˜&˜%K˜6Kšœ  œ˜&—K˜K˜:K˜0˜K˜:—Kšœ<™™>K˜K˜0K˜!˜%K˜6Kšœ  œ˜&—K˜Kšœ)™)šœœœ˜?˜&K˜2—Kšœ œœ˜-Kšœ œœ˜Kšœ œœ˜Kšœœœ+˜IKšœœœ)˜EKšœ%œœ˜7šœ!œ˜-K˜.K˜Kšœœ˜ Kšœ˜—K˜/K˜/K˜K˜Kšœ3 œ˜LKšœ˜—Kšœ˜—KšœŸ˜K˜—K˜Kšœ.™.Kšœ*™*šœ-™-K˜—šž œœ œP˜kKšœŸ˜Kšœ{™{K˜(Kšœ-œ œœ˜PK˜K˜%K˜šžœ˜'Kšœ!™!K˜YKšœŸ ˜K˜—KšœOœ˜Zšœœ˜!K˜$K˜(Kšœ˜—K˜eKšœ œ˜KšœŸ ˜K˜K˜—šž œœ œ˜K˜1K˜4Kšœœœ˜)—šœE™EKšœŸ˜K˜'Kšœ œœ˜šœœœ˜9K˜?K˜—šœœœ˜;K˜K˜—šœœœ˜NKš˜K˜?—˜K˜C˜˜.Kšœ˜!Kšœ œœ˜Kšœœ˜#—K˜—šœ œ˜šœœœ˜9K˜?K˜/—Kšœœ œœœœ œœ˜\K˜Kšœœ˜ K™J™#Kšœ œ˜9—š˜K™RK™%Kšœ œœ˜CK˜—˜šœœ œ#˜E˜K˜šœ˜˜Kšœ&˜+—˜Kšœ(˜-—Kšœœ"˜2———K˜—Kš˜—šœœŸ/˜:šœœœ˜;K˜:—Kšœœ œœœœ œœ˜^K˜Kšœœ˜ K™U™Kšœ œ˜=—š˜K™TK™Kšœ œœ˜GK˜—˜šœœ œ#˜D˜K˜šœ˜˜Kšœ&˜+—˜Kšœ(˜-—Kšœœ"˜2———K˜—Kšœ˜K˜—K˜"Kšœ(œ˜.K˜Kš˜—Kšœœ(˜2KšœŸ ˜K˜K˜—Kšž œœ œ˜6šœE™EKšœŸ˜˜K˜—šœœ˜(K˜@K˜K˜C˜˜.K˜Kšœ˜!Kšœœ"˜,Kšœœ˜—K˜—Kšœ(œ˜.K˜Kš˜—Kšœœ(˜2KšœŸ ˜K˜K˜—šž œœ œ˜Kšœ/œ˜9Kšœ&œŸ˜Kšœœ1˜A—šœœ˜K˜?KšœœŸ6˜H—K˜KšœŸ˜ K˜K˜—šžœœ œ˜*Kšœ œœœ˜1K˜8KšœŸ˜šœ œ˜šœ ˜šœœœ˜:K˜(K˜5Kšœ˜—šœœœ˜7K˜)K˜6Kšœ˜—Kšœ˜—Kšœœ1˜A—šœœ˜šœ ˜šœœ˜4K˜@—šœœ˜1K˜A—Kšœ˜—KšœœŸ6˜H—K˜KšœŸ˜K˜K˜—Kšœ-™-Kšœ*™*Kšœ-™-K˜š žœœ œ6œ˜iK˜*K˜1K˜1šœ œ˜šœ œœ˜-K˜K˜.šœœœ˜K˜;K˜>K˜5Kšœ˜—K˜;˜:Kšœ(œ˜?—˜BKšœ(œ˜?—K˜5K˜5K˜+K˜%šœ˜KšœŸ$˜BKšœŸ/˜JKšœœŸ6˜[K˜Kšœ*˜/Kšœ˜—Kšœ˜—Kšœœ1˜A—K˜KšœŸ˜K˜K˜—Kšœ3™3Kšœ/™/Kšœ3™3K˜š žœœ œ œ˜Qšœœ˜šœ œ˜-K˜(Kšœœ.˜8—Kšœœ1˜A—KšœŸ˜K˜K˜—š žœœ œœ œ˜SKš˜šœœ˜šœ œ˜-K˜-Kšœœ.˜8—Kšœœ1˜A—KšœŸ˜K˜—K˜Kšœ=™=Kšœ8™8Kšœ=™=K˜šžœœ œ˜-Kšœœœ˜$K˜@K˜$K˜2šœ˜K˜,K˜ K˜+K˜+K˜(K˜&Kšœœ˜%—K˜K˜#K˜"šœ˜Kšœ1˜6—KšœŸ˜K˜K˜—šžœœ œ˜)Kšœœœ˜$šœ˜Kšœ œŸ˜(KšœOŸ9˜ˆKšœAŸ9˜—K˜$K˜4šœ˜K˜)K˜K˜%K˜#Kšœœ˜%—K˜K˜#K˜"šœ˜Kšœ1˜6—KšœŸ˜K˜K˜—Kšœ™Kšœ™Kšœ™K˜šžœœ œ-˜]šœœ˜+K˜)K˜K˜Kš˜—Kšœœ.˜8KšœŸ˜ K˜—K˜šžœœ œ˜)K˜)K˜KšœŸ˜K˜K˜—šžœ œœ˜LKšœœœ˜K˜—š žœ œœœœœ˜HKšœ$˜*K˜—KšœŸ˜K˜Kšœ˜—Kš œœœœœ!˜@Kšœ,œ ˜:K˜9˜KK˜0—K˜΅K˜KK˜…Kšœ@œ˜UK˜+˜{K˜Φ—K˜f˜>K˜L—K˜°K˜C˜GK˜o—K˜—…—‘Ηι