DIRECTORY Ascii, BasicTime, BiScrollers, Buttons, Commander, CommanderOps, MJSContainers, Convert, FileNames, FS, Icons, Imager, ImagerBackdoor, ImagerColor, ImagerMemory, ImagerPixel, ImagerPixelArray, ImagerPixelArrayAIS, ImagerSample, ImagerTransformation, InterpressInterpreter, IO, IPMaster, Labels, MessageWindow, PFS, PFSNames, PopUpButtons, PPreView, PPreViewClient, PPreViewOps, RasterEncodingStandardIO, Real, Rope, RopeList, Rules, Sliders, TIPUser, UserProfile, ViewerClasses, ViewerOps, ViewerSpecs, ViewerTools; PPreViewTool: CEDAR MONITOR IMPORTS Ascii, BiScrollers, Commander, CommanderOps, MJSContainers, Convert, FileNames, FS, Icons, Imager, ImagerBackdoor, ImagerColor, ImagerMemory, ImagerPixel, ImagerPixelArray, ImagerPixelArrayAIS, ImagerSample, ImagerTransformation, InterpressInterpreter, IO, IPMaster, Labels, MessageWindow, PFS, PFSNames, PopUpButtons, PPreView, RasterEncodingStandardIO, Real, Rope, RopeList, Rules, Sliders, TIPUser, UserProfile, ViewerOps, ViewerSpecs, ViewerTools EXPORTS PPreView, PPreViewClient, PPreViewOps ~ BEGIN ROPE: TYPE ~ Rope.ROPE; FileType: TYPE ~ PPreView.FileType; Data: TYPE ~ PPreView.Data; Rep: TYPE ~ PPreView.Rep; IPData: TYPE ~ PPreView.IPData; AISData: TYPE ~ PPreView.AISData; RESData: TYPE ~ PPreView.RESData; AISState: TYPE ~ PPreView.AISState; Viewer: TYPE ~ ViewerClasses.Viewer; pvIcon: Icons.IconFlavor ~ Icons.NewIconFromFile["PreView.icons", 0]; defaultPageHeight: REAL ~ 11.0*72.0; -- points defaultPageWidth: REAL ~ 8.5*72.0; -- points versatecPageHeight: REAL ~ 40.0*72.0; -- points versatecPageWidth: REAL ~ 40.0*72.0; -- points screenResolution: REAL ~ 72.0; -- points per inch pointsPerInch: REAL ~ 72.0; oneOverPointsPerInch: REAL ~ 1.0/72.0; pointsPerMica: REAL ~ 72.0/2540.0; micasPerPoint: REAL ~ 2540.0/72.0; pointsPerMeter: REAL ~ 72.0/.0254; metersPerPoint: REAL ~ .0254/72.0; visibleGrey: Imager.Color ~ ImagerBackdoor.MakeStipple[122645B]; invisibleGrey: Imager.Color ~ ImagerBackdoor.MakeStipple[100040B]; buttonAlign: INTEGER ¬ -2; -- align standard viewer with PopUp buttons labelAlign: INTEGER ¬ -1; -- align label with PopUp buttons entryHSpace: INTEGER ¬ 2; -- horizontal space between items on a line secondLine: INTEGER ¬ 14; bsY: INTEGER ¬ 31; ipY: INTEGER ¬ 32; xFudge: INTEGER ¬ 2; yFudge: INTEGER ¬ 2; ipPrefix: ROPE ~ "Interpress/"; ipHeader: ROPE ~ "Interpress/Xerox/"; defaultExtensionList: LIST OF ROPE ~ LIST["ip", "ais", "res", "interpress", "IP", "Interpress"]; extensionList: LIST OF ROPE ¬ defaultExtensionList; bsStyle: PUBLIC BiScrollers.BiScrollerStyle; pvBSClass: BiScrollers.BiScrollerClass; selClass, stuffClass: PopUpButtons.Class; toIPClass, pageClass: PopUpButtons.Class; IPLogError: PUBLIC InterpressInterpreter.LogProc ~ { -- [class: INT, code: ATOM, explanation: ROPE] Complain[message: Rope.Concat["InterpressMaster Error: ", explanation]]; }; WhichFileTypeAndPath: PROC [fileName: ROPE, mustBe: PPreView.FileType ¬ any, data: Data ¬ NIL] RETURNS [fileInfo: PPreView.FileInfo _ NIL, fullPath: PFS.PATH _ NIL] ~ { ENABLE PFS.Error => GOTO PFSError; bytes: INT ¬ -1; created: BasicTime.GMT ¬ BasicTime.nullGMT; -- no longer used path: PFS.PATH ¬ PFS.PathFromRope[fileName]; IF data#NIL THEN { wDir: PFS.PATH ¬ PFSNames.NarrowPath[ViewerOps.FetchProp[viewer: data.container, prop: $PVWDir]]; path ¬ PFSNames.ExpandName[path, wDir]; }; [fullFName: fullPath, bytes: bytes] ¬ PFS.FileInfo[name: path ! PFS.Error => CONTINUE]; IF bytes#-1 THEN { -- named file exists IF PFSNames.IsADirectory[fullPath] THEN { Complain[message: Rope.Concat[PFS.RopeFromPath[fullPath], " is a directory"]]; RETURN[NIL, fullPath]; }; fileInfo ¬ DiscoverFileType[fullPath, created, mustBe]; RETURN; }; IF extensionList = NIL THEN extensionList ¬ defaultExtensionList; FOR l: LIST OF ROPE ¬ extensionList, l.rest UNTIL l=NIL DO name: ROPE ¬ Rope.Cat[fileName, ".", l.first]; path ¬ PFS.PathFromRope[name]; [fullFName: fullPath, bytes: bytes] ¬ PFS.FileInfo[name: path ! PFS.Error => LOOP]; IF bytes <= -1 THEN LOOP; fileInfo ¬ DiscoverFileType[fullPath, created, mustBe]; RETURN[fileInfo, fullPath]; -- file with extension exists ENDLOOP; RETURN[NIL, NIL]; -- file does not exist EXITS PFSError => { Complain[message: Rope.Concat["PFS Error while processing ", fileName]]; }; }; DiscoverFileType: PROC [fullPath: PFS.PATH, created: BasicTime.GMT, mustBe: PPreView.FileType] RETURNS [fileInfo: PPreView.FileInfo] ~ { fileInfo ¬ NEW[PPreView.FileInfoRep ¬ []]; --initialize to fileType none, etc. { ref: REF ANY; s: IO.STREAM; fullName: ROPE; short: PFSNames.Component; -- looking for base.ext baseAndExtension: ROPE; -- should have base.ext whereExt: INT; ext: ROPE; s ¬ PFS.StreamOpen[fileName: fullPath ! IO.Error, PFS.Error => GOTO None]; fullName ¬ PFS.RopeFromPath[fullPath]; short ¬ PFSNames.ShortName[fullPath]; -- looking for base.ext baseAndExtension¬ Rope.Substr[base: short.name.base, start: short.name.start, len: short.name.len]; -- should have base.ext whereExt ¬ Rope.FindBackward[s1: baseAndExtension, s2: ".", case: FALSE]; ext ¬ IF whereExt<0 THEN NIL ELSE Rope.Substr[base: baseAndExtension, start: whereExt+1]; SELECT mustBe FROM any => { SELECT TRUE FROM Rope.Equal[s1: ext, s2: "ip", case: FALSE], Rope.Equal[s1: ext, s2: "interpress", case: FALSE] => IF Rope.Equal[IO.GetRope[s, Rope.Size[ipHeader]], ipHeader] THEN {fileInfo­ ¬ [ip, fullName, created, s]; RETURN;}; Rope.Equal[s1: ext, s2: "ais", case: FALSE] => IF (ref ¬ ImagerPixelArrayAIS.FromAIS[name: fullName ! UNCAUGHT => CONTINUE;])#NIL THEN {fileInfo­ ¬ [ais, fullName, created, ref]; RETURN;}; Rope.Equal[s1: ext, s2: "res", case: FALSE] => IF (ref ¬ RasterEncodingStandardIO.Read[fileName: fullName ! UNCAUGHT => CONTINUE])#NIL THEN {fileInfo­ ¬ [res, fullName, created, ref]; RETURN;}; ENDCASE => NULL; IO.SetIndex[s, 0]; --reset stream for subsequent calls IF Rope.Equal[IO.GetRope[s, Rope.Size[ipHeader]], ipHeader] THEN {fileInfo­ ¬ [ip, fullName, created, s]; RETURN;}; IO.SetIndex[s,0]; --reset stream for subsequent calls IF (ref ¬ ImagerPixelArrayAIS.FromAIS[name: fullName ! UNCAUGHT => CONTINUE;])#NIL THEN {fileInfo­ ¬ [ais, fullName, created, ref]; RETURN;}; IF (ref ¬ RasterEncodingStandardIO.Read[fileName: fullName ! UNCAUGHT => CONTINUE;])#NIL THEN {fileInfo­ ¬ [res, fullName, created, ref]; RETURN;}; fileInfo­ ¬ [none, NIL, BasicTime.nullGMT, NIL]; }; ip => { IF Rope.Equal[IO.GetRope[s, Rope.Size[ipHeader]], ipHeader] THEN fileInfo­ ¬ [ip, fullName, created, s] ELSE GOTO None; }; ais => { IF (ref ¬ ImagerPixelArrayAIS.FromAIS[name: fullName ! UNCAUGHT => CONTINUE;])#NIL THEN fileInfo­ ¬ [ais, fullName, created, ref] ELSE GOTO None; }; res => { IF (ref ¬ RasterEncodingStandardIO.Read[fileName: fullName ! UNCAUGHT => CONTINUE;])#NIL THEN fileInfo­ ¬ [res, fullName, created, ref] ELSE GOTO None; }; ENDCASE => GOTO None; EXITS None => fileInfo­ ¬ [none, NIL, BasicTime.nullGMT, NIL]; }; }; CreatePreViewer: PUBLIC PROC [fileNames: PPreView.NameList, switches: PPreView.Switches, xSize, ySize: REAL, mustBe: PPreView.FileType ¬ any] RETURNS [preViewer: Viewer] = { data: Data ¬ NIL; versionSpecified: BOOL ¬ FALSE; [data, versionSpecified] ¬ LoadPreViewData[fileNames, switches, xSize, ySize, mustBe, 1]; preViewer ¬ CreatePreViewerFromData[data, versionSpecified] }; LoadPreViewData: PROC [fileNames: PPreView.NameList, switches: PPreView.Switches, xSize, ySize: REAL, mustBe: PPreView.FileType ¬ any, pageNumber: INTEGER ¬ 1] RETURNS [data: Data ¬ NIL, versionSpecified: BOOL ¬ FALSE] = { path: PFS.PATH; fileInfo: PPreView.FileInfo ¬ NIL; lastPageNumber: INTEGER ¬ 1; fileName: ROPE ¬ NIL; IF fileNames=NIL THEN { Complain[message: "Empty file list"]; RETURN; }; IF switches['P] THEN { thisPage: INTEGER ¬ 1; lastPageNumber ¬ RopeList.Length[fileNames]; FOR list: LIST OF ROPE ¬ fileNames, list.rest UNTIL list=NIL DO IF thisPage = pageNumber THEN {fileName ¬ list.first; EXIT}; thisPage ¬ thisPage +1; ENDLOOP; } ELSE fileName ¬ fileNames.first; [fileInfo, path] ¬ WhichFileTypeAndPath[fileName, mustBe]; -- add file extension to named file if needed IF fileInfo=NIL OR path=NIL THEN { Complain[message: Rope.Concat["Unknown file: ", fileName]]; RETURN; }; IF fileInfo.filetype=none THEN { Complain[message: Rope.Concat["Unknown file type for: ", fileName]]; RETURN; }; IF mustBe # any AND fileInfo.filetype # mustBe THEN { Complain[Rope.Cat["Can't display ", fileName, " with currently loaded PreView packages"]]; RETURN; }; SELECT fileInfo.filetype FROM ip => { stream: IO.STREAM ~ NARROW[fileInfo.ref]; ipmaster: InterpressInterpreter.Master ¬ InterpressInterpreter.FromStream[stream: stream, log: IPLogError ! PFS.Error => { Complain[message: Rope.Cat[error.explanation, " for ", fileInfo.fullFName]]; GOTO Quit; }; IPMaster.Error => { --ErrorDesc: TYPE = RECORD[code: ATOM, explanation: ROPE, index: INT ¬ 0] Complain[message: Rope.Cat[error.explanation, " for ", fileInfo.fullFName]]; GOTO Quit; }; Imager.Error => { --ErrorDesc: TYPE = RECORD [code: ATOM, explanation: ROPE] Complain[message: Rope.Cat[error.explanation, " for ", fileInfo.fullFName]]; GOTO Quit; }; IO.Error, IO.EndOfStream => { Complain[message: Rope.Concat["IO Stream Error for ", fileInfo.fullFName]]; GOTO Quit; }; ]; IF ipmaster.pages=0 THEN { Complain[message: Rope.Concat["Zero pages in ", fileInfo.fullFName]]; RETURN; }; data ¬ NEW[ip Rep ¬ [fileInfo: fileInfo, pageNumber: 1, lastPageNumber: ipmaster.pages, pageHeight: IF switches['V] THEN versatecPageHeight ELSE ySize*72.0, pageWidth: IF switches['V] THEN versatecPageWidth ELSE xSize*72.0, switches: switches, kind: ip[ipMaster: ipmaster]]]; -- pages IN [1..end] }; ais => { aisData: AISData ¬ NEW[ais Rep ¬ [fileInfo: fileInfo, pageNumber: pageNumber, lastPageNumber: lastPageNumber, switches: switches, kind: ais[state: NEW[PPreView.AISStateRep ¬ []]]]]; [fileInfo.fullFName, versionSpecified] ¬ InitAIS[data: aisData, fileNames: fileNames, singleName: fileInfo.fullFName, fromAIS: NARROW[fileInfo.ref]]; IF fileInfo.fullFName = NIL THEN RETURN; aisData.pageHeight ¬ aisData.state.scans; aisData.pageWidth ¬ aisData.state.pixels; data ¬ aisData; }; res => { res: RasterEncodingStandardIO.RES ~ NARROW[fileInfo.ref]; data ¬ NEW[res Rep ¬ [fileInfo: fileInfo, pageNumber: 1, lastPageNumber: lastPageNumber, pageHeight: res.yDimension, pageWidth: res.xDimension, switches: switches, kind: res[image: res]]]; }; ENDCASE => { Complain[message: Rope.Concat["Unknown file type for: ", fileName]]; RETURN; }; versionSpecified ¬ PFSNames.ShortName[path].version.versionKind=numeric; data.fileNames ¬ fileNames; data.xSize ¬ xSize; data.ySize ¬ ySize; data.mustBe ¬ mustBe; RETURN[data, versionSpecified]; EXITS Quit => NULL; }; NewPageData: PROC [data: Data, pageNumber: INTEGER ¬ 1] = { fileInfo: PPreView.FileInfo ¬ NIL; fileName: ROPE ¬ NIL; path: PFS.PATH; versionSpecified: BOOL ¬ FALSE; IF data.switches['P] AND data.fileNames # NIL THEN { thisPage: INTEGER ¬ 1; FOR list: LIST OF ROPE ¬ data.fileNames, list.rest UNTIL list=NIL DO IF thisPage = pageNumber THEN {fileName ¬ list.first; EXIT}; thisPage ¬ thisPage +1; ENDLOOP; } ELSE IF data.fileNames # NIL THEN fileName ¬ data.fileNames.first; [fileInfo, path] ¬ WhichFileTypeAndPath[fileName, data.mustBe, data]; -- add file extension to named file if needed IF fileInfo=NIL THEN { Complain[message: Rope.Concat["Unknown file: ", fileName]]; RETURN; }; IF fileInfo.filetype=none THEN { Complain[message: Rope.Concat["Unknown file type for: ", fileName]]; RETURN; }; IF data.mustBe # any AND fileInfo.filetype # data.mustBe THEN { Complain[Rope.Cat["Can't display ", fileName, " with currently loaded PreView packages"]]; RETURN; }; data.fileInfo ¬ fileInfo; versionSpecified ¬ PFSNames.ShortName[path].version.versionKind=numeric; data.container.name ¬ IF versionSpecified THEN Rope.Concat["PreView: ", data.fileInfo.fullFName] ELSE Rope.Cat["PreView: ", FileNames.StripVersionNumber[data.fileInfo.fullFName], " (!", FileNames.Tail[data.fileInfo.fullFName, '!], ")"]; data.container.label ¬ FileNames.GetShortName[path: data.fileInfo.fullFName, stripOffVersionNumber: NOT versionSpecified]; data.container.file ¬ data.fileInfo.fullFName; SELECT fileInfo.filetype FROM res => { resData: RESData ¬ NARROW[data]; res: RasterEncodingStandardIO.RES ~ NARROW[fileInfo.ref]; resData.pageHeight ¬ res.yDimension; resData.pageWidth ¬ res.xDimension; resData.image ¬ NARROW[res]; }; ais => { aisData: AISData ¬ NARROW[data]; [fileInfo.fullFName, ] ¬ InitAIS[data: aisData, fileNames: data.fileNames, singleName: fileInfo.fullFName, fromAIS: NARROW[fileInfo.ref]]; IF fileInfo.fullFName = NIL THEN RETURN; aisData.pageHeight ¬ aisData.state.scans; aisData.pageWidth ¬ aisData.state.pixels; }; ENDCASE => { Complain[message: Rope.Concat["Paging not supported for filetype of: ", fileName]]; RETURN; }; }; CreatePreViewerFromData: PUBLIC PROC [data: Data, versionSpecified: BOOL] RETURNS [preViewer: Viewer] ~ { ENABLE PFS.Error => GOTO PFSError; MakeNewTextViewer: PROC [x, y, w, h: INTEGER] RETURNS [v: Viewer] ~ { v ¬ ViewerTools.MakeNewTextViewer[ info: [wx: x, wy: y, ww: w, wh: h, parent: data.container, border: FALSE, scrollable: FALSE], paint: FALSE]; ViewerTools.InhibitUserEdits[v]; }; curIndent: INTEGER ¬ 0; bs: BiScrollers.BiScroller ¬ NIL; tV: Viewer; button: Buttons.Button; rule: Rules.Rule; path: PFS.PATH; unversionedPath: PFS.PATH; short: PFSNames.Component; version: CARDINAL ¬ 0; IF data = NIL THEN RETURN[NIL]; IF data.fileInfo = NIL THEN data.fileInfo ¬ NEW[PPreView.FileInfoRep]; path ¬ PFS.PathFromRope[data.fileInfo.fullFName]; unversionedPath ¬ PFSNames.StripVersionNumber[path]; short ¬ PFSNames.ShortName[path]; version ¬ short.version.version; data.bBox ¬ NEW[PPreView.BBoxStateRep ¬ []]; data.iMemContext ¬ ImagerMemory.NewMemoryContext[]; data.container ¬ preViewer ¬ MJSContainers.Create[ viewerFlavor: $VanillaMJSContainer, info: [ name: IF versionSpecified THEN Rope.Concat["PreView: ", data.fileInfo.fullFName] ELSE Rope.Cat["PreView: ", PFS.RopeFromPath[unversionedPath], IO.PutFR1[" (!%g)", [cardinal[version]] ] ], label: Rope.Concat[Rope.Substr[short.name.base, short.name.start, short.name.len], IF versionSpecified THEN IO.PutFR1["!%g", [cardinal[version]] ] ELSE ""], file: data.fileInfo.fullFName, iconic: TRUE, menu: NIL, icon: pvIcon, data: data, scrollable: FALSE], paint: FALSE ]; bs ¬ bsStyle.CreateBiScroller[ class: pvBSClass, info: [ parent: data.container, wx: 0, wy: bsY, border: FALSE, scrollable: FALSE, data: data], paint: FALSE ]; tV ¬ BiScrollers.CreateScale[[parent: preViewer, wx: 0, wy: 0, border: FALSE], bs]; tV ¬ BiScrollers.CreateRotate[[parent: preViewer, wx: tV.wx+tV.ww+entryHSpace, wy: 0, border: FALSE], bs]; tV ¬ BiScrollers.CreateFit[[parent: preViewer, wx: tV.wx+tV.ww+entryHSpace, wy: 0, border: FALSE], bs]; tV ¬ BiScrollers.CreateReset[[parent: preViewer, wx: tV.wx+tV.ww+entryHSpace, wy: 0, border: FALSE], bs]; tV ¬ BiScrollers.CreateEdge[[parent: preViewer, wx: tV.wx+tV.ww+entryHSpace, wy: 0, border: FALSE], bs]; tV ¬ BiScrollers.CreatePrev[[parent: preViewer, wx: tV.wx+tV.ww+entryHSpace, wy: 0, border: FALSE], bs]; button ¬ stuffClass.Instantiate[viewerInfo: [name: "Stuff", wx: curIndent, wy: secondLine, border: FALSE, parent: data.container], instanceData: data, paint: FALSE]; curIndent ¬ button.wx + button.ww; button ¬ toIPClass.Instantiate[viewerInfo: [name: "ToIP", wx: curIndent, wy: secondLine, border: FALSE, parent: data.container], instanceData: data, paint: FALSE]; curIndent ¬ button.wx + button.ww; button ¬ selClass.Instantiate[viewerInfo: [name: "Selection", wx: curIndent, wy: secondLine, border: FALSE, parent: data.container], instanceData: data, paint: FALSE]; curIndent ¬ button.wx + button.ww; button ¬ pageClass.Instantiate[viewerInfo: [name: "Page", wx: curIndent, wy: secondLine, border: FALSE, parent: data.container], instanceData: data, paint: FALSE]; curIndent ¬ button.wx + button.ww; button ¬ Labels.Create[ info: [ name: "AtPage:", wx: curIndent, wy: secondLine+labelAlign, border: FALSE, parent: data.container], paint: FALSE]; curIndent ¬ button.wx + button.ww; data.pageNumberViewer ¬ MakeNewTextViewer[ curIndent, secondLine+ViewerSpecs.windowBorderSize+buttonAlign, 40, ViewerSpecs.scrollBarW+2*ViewerSpecs.windowBorderSize]; curIndent ¬ data.pageNumberViewer.wx + data.pageNumberViewer.ww; data.pageNumberSlider ¬ Sliders.Create[ info: [ wx: curIndent, wy: secondLine, ww: data.container.ww-curIndent, wh: ViewerSpecs.scrollBarW+2*ViewerSpecs.windowBorderSize, border: FALSE, parent: data.container, scrollable: FALSE], filterProc: NormalizePageNumber, sliderProc: PageNumberSlider, orientation: horizontal, foreground: visibleGrey, background: invisibleGrey, clientData: data, paint: FALSE]; MJSContainers.ChildXBound[data.container, data.pageNumberSlider]; button ¬ Labels.Create[ info: [ name: "Scaled Size: w: h: inches", wx: data.pageNumberViewer.wx+data.pageNumberViewer.ww-3, wy: labelAlign, border: FALSE, parent: data.container], paint: FALSE]; data.selectionWViewer ¬ MakeNewTextViewer[ button.wx+95, ViewerSpecs.windowBorderSize+buttonAlign, 45, ViewerSpecs.scrollBarW+2*ViewerSpecs.windowBorderSize]; data.selectionHViewer ¬ MakeNewTextViewer[ button.wx+165, ViewerSpecs.windowBorderSize+buttonAlign, 45, ViewerSpecs.scrollBarW+2*ViewerSpecs.windowBorderSize]; rule ¬ Rules.Create[ info: [ parent: data.container, wx: 0, wy: secondLine+ViewerSpecs.captionHeight+4*ViewerSpecs.windowBorderSize, wh: ViewerSpecs.menuBarHeight]]; MJSContainers.ChildXBound[data.container, rule]; data.preViewer ¬ bs.QuaViewer[inner: FALSE]; ViewerOps.AddProp[viewer: bs.QuaViewer[inner: TRUE], prop: $PVWDir, val: PFS.GetWDir[]]; ViewerOps.AddProp[viewer: data.container, prop: $PVWDir, val: PFS.GetWDir[]]; MJSContainers.ChildXBound[data.container, data.preViewer]; MJSContainers.ChildYBound[data.container, data.preViewer]; ViewerOps.PaintViewer[viewer: data.container, hint: all, clearClient: TRUE]; DeltaPage[data, 1]; EXITS PFSError => { Complain[message: Rope.Concat["PFS Error while processing ", data.fileInfo.fullFName]]; RETURN[NIL]; -- probably garbage fileName }; }; InitAIS: PROC [data: AISData, fileNames: PPreView.NameList, singleName: ROPE, fromAIS: ImagerPixelArray.PixelArray] RETURNS [newName: ROPE ¬ NIL, versionSpecified: BOOL ¬ FALSE] = { ENABLE { FS.Error => { Complain[message: error.explanation]; newName ¬ NIL; CONTINUE; }; PFS.Error => { Complain[message: error.explanation]; newName ¬ NIL; CONTINUE; }; ImagerPixelArray.Error => { Complain[message: error.explanation]; newName ¬ NIL; CONTINUE; }; }; state: AISState ¬ data.state; IF ~data.switches['P] AND fileNames.rest#NIL THEN { --multi-file color AIS image fullFName: ROPE; redName: ROPE ¬ fileNames.rest.rest.first; grnName: ROPE ¬ fileNames.rest.first; bluName: ROPE ¬ fileNames.first; fullCP: FS.ComponentPositions; -- a full FName grnCP: FS.ComponentPositions; -- not a full FName [fullFName, fullCP, ] ¬ FS.ExpandName[singleName]; -- a full FName grnCP ¬ FS.ExpandName[grnName].cp; -- not a full FName state.pa ¬ ImagerPixelArrayAIS.Join3AIS[name1: redName, name2: grnName, name3: bluName]; -- in red, green, blue order !! state.scans ¬ state.pa.sSize; -- must be identical raster info in all separations state.pixels¬ state.pa.fSize; -- must be identical raster info in all separations state.op ¬ ImagerColor.NewColorOperatorRGB[ImagerPixelArray.MaxSampleValue[pa: state.pa, i: 0]]; newName ¬ Rope.Concat[Rope.Substr[base: fileNames.first, start: 0, len: Rope.SkipTo[s: fileNames.first, pos: 0, skip: "-"]], "-*.ais"]; -- everything thru the name base IF fullCP.ver.length#0 THEN newName ¬ Rope.Cat[newName, "!", Rope.Substr[base: fullFName, start: fullCP.ver.start, len: fullCP.ver.length] ]; -- should be some version number, even 0, on a full name IF grnCP.ver.length#0 THEN versionSpecified ¬ TRUE; -- explicit version if not a full FName } ELSE { -- single file AIS image msv: [0..256) ¬ 0; state.pa ¬ fromAIS; state.scans ¬ state.pa.sSize; state.pixels¬ state.pa.fSize; msv ¬ ImagerPixelArray.MaxSampleValue[state.pa, 0]; SELECT msv FROM 0 => state.op ¬ NIL; 1 => { -- need complement of the pa for imaging with MaskPixel newpa: ImagerPixelArray.PixelArray; pa: ImagerPixelArray.PixelArray ¬ state.pa; box: ImagerSample.Box ¬ [min: [s: 0, f: 0], max: [s: state.scans, f: state.pixels]]; sm: ImagerSample.SampleMap ¬ ImagerSample.NewSampleMap[box: box, bitsPerSample: 1]; ImagerPixelArray.Transfer[pa: pa, i: 0, s: 0, f: 0, dst: sm, function: [null, complement]]; newpa ¬ ImagerPixelArray.FromPixelMap[pixelMap: ImagerPixel.MakePixelMap[s0: sm], box: box, scanMode: [slow: right, fast: up], immutable: TRUE]; newpa.m ¬ pa.m; state.pa ¬ newpa; state.op ¬ NIL; }; ENDCASE => state.op ¬ ImagerColor.NewColorOperatorGrayLinear[sWhite: ImagerPixelArray.MaxSampleValue[pa: state.pa, i: 0], sBlack: 0.0]; newName ¬ singleName; }; state.active ¬ TRUE; }; SelectionOps: PopUpButtons.PopUpButtonProc = { --PROC [viewer: Viewer, instanceData, classData, key: REF ANY] data: Data ¬ NARROW[instanceData]; viewer: Viewer ¬ BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE]; SELECT key FROM $Center => { -- center selection in viewer IF NOT data.bBox.active THEN GOTO NoSel; BiScrollers.Align[bs: BiScrollers.QuaBiScroller[data.preViewer], client: [variant: coord[x: data.bBox.rect.x+(data.bBox.rect.w/2.0), y: data.bBox.rect.y+(data.bBox.rect.h/2.0)]], viewer: [variant: fraction[fx: 0.5, fy: 0.5]], paint: TRUE]; }; $CenterAndFit, $CenterAndScale => { -- center selection in viewer then scale to fit inside viewer vH, vW, sH, sW: REAL ¬ 1.0; -- viewer and selection dimensions IF NOT data.bBox.active THEN GOTO NoSel; sH ¬ MAX[sH, data.bBox.rect.h]; sW ¬ MAX[sW, data.bBox.rect.w]; vH ¬ MAX[vH, viewer.ch]; vW ¬ MAX[vW, viewer.cw]; BiScrollers.Align[bs: BiScrollers.QuaBiScroller[data.preViewer], client: [variant: coord[x: data.bBox.rect.x+(data.bBox.rect.w/2.0), y: data.bBox.rect.y+(data.bBox.rect.h/2.0)]], viewer: [variant: fraction[fx: 0.5, fy: 0.5]], paint: FALSE]; IF key=$CenterAndFit THEN BiScrollers.Scale[bs: BiScrollers.QuaBiScroller[data.preViewer], op: [variant: reset[] ], paint: FALSE ]; -- reset scale before fitting BiScrollers.Scale[bs: BiScrollers.QuaBiScroller[data.preViewer], op: [variant: byArg[arg: MIN[vW/sW, vH/sH]]], paint: TRUE ]; }; $SelectPage => { -- select entire page IF data.bBox.active THEN PPreView.PVFeedback[data: data, v: BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE], op: remove]; -- remove any old selection data.bBox­ ¬ [active: TRUE, rect: [x: 0.0, y: 0.0, w: data.pageWidth, h: data.pageHeight], prev: [x: 0.0, y: 0.0, w: data.pageWidth, h: data.pageHeight], p0: [0.0, 0.0], p1: [data.pageWidth, data.pageHeight]]; -- fake the box into the right state to select the whole page PPreView.PVFeedback[data: data, v: BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE], op: paint]; -- paint new selection }; $SetSelection => { -- select x y w h (in inches) selAsStream: IO.STREAM = IO.RIS[ViewerTools.GetSelectionContents[]]; { ENABLE IO.Error, IO.EndOfStream => { Complain["Select \"x y w h\" (in inches) before clicking"]; GOTO NeverMind; }; x: REAL ¬ IO.GetReal[selAsStream]*pointsPerInch; y: REAL ¬ IO.GetReal[selAsStream]*pointsPerInch; w: REAL ¬ IO.GetReal[selAsStream]*pointsPerInch; h: REAL ¬ IO.GetReal[selAsStream]*pointsPerInch; data.bBox.rect ¬ [x, y, w, h]; data.bBox.p0 ¬ [data.bBox.rect.x, data.bBox.rect.y]; data.bBox.p1 ¬ [data.bBox.p0.x+data.bBox.rect.w, data.bBox.p0.y+data.bBox.rect.h]; data.bBox.active ¬ TRUE; }; PPreView.PVFeedback[data: data, v: viewer, op: change]; EXITS NeverMind => NULL; }; $ShowSelection => NULL; -- show x y w h (in inches) ENDCASE => ERROR; ShowSelection[data, viewer]; EXITS NoSel => Complain["No PreView Selection"]; }; GetTransformation: PUBLIC PROC [v: Viewer] RETURNS [Imager.Transformation] ~ { RETURN[PPreView.bsStyle.GetTransforms[BiScrollers.QuaBiScroller[v]].clientToViewer]; }; GetTransformedRect: PUBLIC PROC [data: PPreView.Data, v: ViewerClasses.Viewer] RETURNS [Imager.Rectangle] ~ { ctv: ImagerTransformation.Transformation ¬ GetTransformation[v]; RETURN[ImagerTransformation.TransformRectangle[m: ctv, r: data.bBox.rect]]; }; ShowSelection: PUBLIC PROC [data: Data, v: Viewer] ~ { IF data.bBox.active THEN { rect: Imager.Rectangle ¬ GetTransformedRect[data, v]; ViewerTools.SetContents[data.selectionWViewer, IO.PutFR1["%6.3f", IO.real[oneOverPointsPerInch*rect.w]]]; ViewerTools.SetContents[data.selectionHViewer, IO.PutFR1["%6.3f", IO.real[oneOverPointsPerInch*rect.h]]]; MessageWindow.Append[ IO.PutFLR["Selection = [x: %g, y: %g, w: %g, h: %g] inches", LIST[ IO.real[oneOverPointsPerInch*data.bBox.rect.x], IO.real[oneOverPointsPerInch*data.bBox.rect.y], IO.real[oneOverPointsPerInch*data.bBox.rect.w], IO.real[oneOverPointsPerInch*data.bBox.rect.h]]], TRUE]; } ELSE MessageWindow.Append["No PreView selection", TRUE]; }; GetSelection: PUBLIC PROC [data: PPreView.Data] RETURNS [x, y, w, h: REAL] = { IF data#NIL AND data.bBox.active THEN { v: Viewer ¬ BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE]; x ¬ oneOverPointsPerInch*data.bBox.rect.x; y ¬ oneOverPointsPerInch*data.bBox.rect.y; w ¬ oneOverPointsPerInch*data.bBox.rect.w; h ¬ oneOverPointsPerInch*data.bBox.rect.h; } ELSE RETURN [ 0, 0, 0, 0]; }; SetSelection: PUBLIC PROC [data: PPreView.Data, x, y, w, h: REAL] = { IF data#NIL THEN { v: Viewer ¬ BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE]; rx: REAL ¬ x*pointsPerInch; ry: REAL ¬ y*pointsPerInch; rw: REAL ¬ w*pointsPerInch; rh: REAL ¬ h*pointsPerInch; data.bBox.rect ¬ [rx, ry, rw, rh]; data.bBox.p0 ¬ [data.bBox.rect.x, data.bBox.rect.y]; data.bBox.p1 ¬ [data.bBox.p0.x+data.bBox.rect.w, data.bBox.p0.y+data.bBox.rect.h]; data.bBox.active ¬ TRUE; PPreView.PVFeedback[data: data, v: v, op: change]; }; }; ClearSelection: PUBLIC PROC [data: PPreView.Data] = { IF data#NIL THEN { v: Viewer ¬ BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE]; b: PPreView.BBoxState ¬ data.bBox; IF b.active THEN PPreView.PVFeedback[data: data, v: v, op: remove]; -- kill grey bbox b­ ¬ []; -- initialization default values cancel current clipping rectangle }; }; DoSelectionOp: PUBLIC PROC [data: PPreView.Data, op: ATOM] = { IF data#NIL THEN { v: Viewer ¬ BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE]; SelectionOps[view: v, instanceData: data, classData: NIL, key: op]; }; }; GetTransform: PUBLIC PROC [data: PPreView.Data] RETURNS [Imager.Transformation] = { RETURN[IF data#NIL THEN bsStyle.GetTransforms[BiScrollers.QuaBiScroller[data.preViewer]].clientToViewer ELSE NIL]; }; SetTransform: PUBLIC PROC [data: PPreView.Data, clientToViewer: Imager.Transformation] = { IF data#NIL THEN bsStyle.ChangeTransform[BiScrollers.QuaBiScroller[data.preViewer], clientToViewer, remember]; }; Stuff: PopUpButtons.PopUpButtonProc = { --PROC [viewer: Viewer, instanceData, classData, key: REF ANY] data: Data ¬ NARROW[instanceData]; IF key=$Page OR key=$PageFitted OR key=$PageBordered OR key=$PageBorderedAndFitted THEN { IF data.bBox.active THEN PPreView.PVFeedback[data: data, v: BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE], op: remove]; -- remove any old selection data.bBox­ ¬ [active: TRUE, rect: [x: 0.0, y: 0.0, w: data.pageWidth, h: data.pageHeight], p0: [0.0, 0.0], p1: [data.pageWidth, data.pageHeight]]; -- fake the box into the right state to select the whole page PPreView.PVFeedback[data: data, v: BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE], op: paint]; -- paint new selection } ELSE IF data.bBox.rect.w=0 OR data.bBox.rect.h=0 THEN { Complain["Specify clipping box before clicking Stuff"]; RETURN; }; data.stuffWithBorders ¬ key=$Bordered OR key=$BorderedAndFitted OR key=$PageBordered OR key=$PageBorderedAndFitted; data.stuffWithFit ¬ key=$Fitted OR key=$BorderedAndFitted OR key=$PageFitted OR key=$PageBorderedAndFitted; PPreView.DoFileOps[op: stuff, viewer: BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE], data: data, fileName: NIL, clip: TRUE]; }; ToIP: PopUpButtons.PopUpButtonProc = { --PROC [viewer: Viewer, instanceData, classData, key: REF ANY] ENABLE PFS.Error => GOTO PFSError; success: BOOL ¬ FALSE; data: Data ¬ NARROW[instanceData]; iv: Viewer ¬ BiScrollers.QuaBiScroller[data.preViewer].QuaViewer[inner: TRUE]; name: ROPE ¬ ViewerTools.GetSelectionContents[]; IF key=$Selection AND (data.bBox.rect.w=0 OR data.bBox.rect.h=0) THEN { Complain["Specify clipping box before left clicking ToIP"]; RETURN; }; IF Rope.Length[name]=0 OR Rope.Equal[name, data.container.file] THEN { -- no user specified name dotIndex: INT ¬ Rope.SkipTo[data.container.label, 0, "."]; -- find the label, strip the dot name ¬ IF dotIndex=Rope.Length[data.container.label] THEN data.container.label ELSE Rope.Substr[data.container.label, 0, Rope.SkipTo[data.container.label, 0, "."] ]; }; { path: PFS.PATH ¬ PFS.PathFromRope[name]; wDir: PFS.PATH ¬ PFSNames.NarrowPath[ViewerOps.FetchProp[viewer: iv, prop: $PVWDir]]; path ¬ PFSNames.ExpandName[path, wDir]; name ¬ PFS.RopeFromPath[path]; }; [name, success] ¬ GetGenericFileName[name, "ip", LIST["mesa", "tioga", "script", "ais", "press", "pd", "res", "griffin", "gargoyle"] ]; IF success THEN { PPreView.DoFileOps[op: ipMaster, viewer: iv, data: data, fileName: name, clip: key=$Selection]; IF data.abort THEN data.abort ¬ FALSE ELSE MessageWindow.Append[Rope.Cat["PreView: ", name, " written"], TRUE]; }; EXITS PFSError => { Complain[message: Rope.Concat["PFS Error while processing IP file name ", ViewerTools.GetSelectionContents[] ]]; RETURN; -- probably garbage fileName }; }; GetGenericFileName: PROC [fileName, defaultExt: ROPE, illegalExts: LIST OF ROPE] RETURNS [fullName: ROPE ¬ NIL, success: BOOL ¬ TRUE] = { path: PFS.PATH; IF Rope.Length[fileName]=0 THEN { Complain["No filename specified"]; RETURN[NIL, FALSE]; }; path ¬ PFS.PathFromRope[fileName ! PFS.Error => { success ¬ FALSE; Complain[IO.PutFR1["PFS Error during name expansion of %g", [rope[fileName]]]]; CONTINUE; }; ]; IF success THEN { short: PFSNames.Component ¬ PFSNames.ShortName[path]; -- looking for base.ext baseAndExtension: ROPE ¬ Rope.Substr[base: short.name.base, start: short.name.start, len: short.name.len]; -- should have base.ext whereExt: INT ¬ Rope.FindBackward[s1: baseAndExtension, s2: ".", case: FALSE]; extRope: ROPE ¬ IF whereExt<0 THEN NIL ELSE Rope.Substr[base: baseAndExtension, start: whereExt+1]; IF extRope#NIL THEN FOR ropeList: LIST OF ROPE ¬ illegalExts, ropeList.rest UNTIL ropeList=NIL DO IF Rope.Equal[ropeList.first, extRope, FALSE] THEN { Complain[IO.PutFR["%g extension for %g files not allowed", [rope[extRope]], [rope[defaultExt]]] ]; success ¬ FALSE; RETURN; }; ENDLOOP ELSE { baseAndExtension ¬ Rope.Cat[baseAndExtension, ".", defaultExt]; path ¬ PFSNames.ReplaceShortName[path, [name: [base: baseAndExtension, start: 0, len: Rope.Length[baseAndExtension]], version: [versionKind: none, version: 0] ]]; -- can't provide a version here }; fullName ¬ PFS.RopeFromPath[path]; }; }; Complain: PROC [message: ROPE, clearFirst: BOOL ¬ TRUE] = { MessageWindow.Append[Rope.Concat["PreView: ", message], clearFirst]; MessageWindow.Blink[]; }; PageTurn: PopUpButtons.PopUpButtonProc = { --PROC [viewer: Viewer, instanceData, classData, key: REF ANY] data: Data ¬ NARROW[instanceData]; SELECT key FROM $FirstPage => DeltaPage[data, 1]; $TurnForward => DeltaPage[data, MIN[MAX[data.pageNumber+1, 1], (data.lastPageNumber)]]; $TurnBackward => DeltaPage[data, MIN[MAX[data.pageNumber-1, 1], (data.lastPageNumber)]]; $LastPage => DeltaPage[data, data.lastPageNumber]; $FromTiogaSelection => { stream: IO.STREAM ¬ IO.RIS[ViewerTools.GetSelectionContents[]]; where: INT ¬ stream.GetInt[ ! IO.Error, IO.EndOfStream => { Complain["Select a valid page number"]; GOTO Abort; }; ]; DeltaPage[data, MIN[MAX[where, 1], (data.lastPageNumber)]]; }; ENDCASE => ERROR; EXITS Abort => NULL; }; NormalizePageNumber: Sliders.FilterProc = { data: Data ¬ NARROW[clientData]; lastPageNumber: REAL ¬ data.lastPageNumber; RETURN [Real.Round[value*lastPageNumber]/lastPageNumber]; }; PageNumberSlider: Sliders.SliderProc = { data: Data ¬ NARROW[clientData]; lastPageNumber: REAL ¬ data.lastPageNumber; SELECT reason FROM abort => { ViewerTools.SetContents[data.pageNumberViewer, IO.PutFR1["%-g", IO.int[data.pageNumber]]]; }; move => { ViewerTools.SetContents[data.pageNumberViewer, IO.PutFR1["%-g", IO.int[Real.Round[lastPageNumber*value]]]]; }; set => { DeltaPage[data, MIN[MAX[Real.Round[lastPageNumber*value], 1], data.lastPageNumber]]; }; ENDCASE; }; DeltaPage: PROCEDURE [data: Data, newvalue: INT] = { lastPageNumber: REAL ¬ data.lastPageNumber; ViewerTools.SetContents[data.pageNumberViewer, IO.PutFR1["%-g", IO.int[newvalue]]]; Sliders.SetContents[data.pageNumberSlider, newvalue/lastPageNumber]; IF data.pageNumber=newvalue THEN RETURN; -- just did the initialization needed data.pageNumber ¬ newvalue; WITH data SELECT FROM ipData: IPData => NULL; ENDCASE => NewPageData[data, newvalue]; -- Load new page into data ViewerOps.PaintViewer[viewer: data.preViewer, hint: all, clearClient: TRUE]; ViewerOps.PaintViewer[viewer: data.container, hint: caption, clearClient: FALSE]; }; IPPreView: PUBLIC Commander.CommandProc = { [result, msg] ¬ LetHerRip[cmd, ip]; }; AISPreView: PUBLIC Commander.CommandProc = { [result, msg] ¬ LetHerRip[cmd, ais]; }; RESPreView: PUBLIC Commander.CommandProc = { [result, msg] ¬ LetHerRip[cmd, res]; }; AnyPreView: PUBLIC Commander.CommandProc = { [result, msg] ¬ LetHerRip[cmd, any]; }; LetHerRip: PROC [cmd: Commander.Handle, mustBe: PPreView.FileType ¬ ip] RETURNS [result: REF ¬ NIL, msg: ROPE ¬ NIL] = { ENABLE Convert.Error => { result ¬ $Failure; msg ¬ "PreView: Specify positive real numbers for page sizes"; GOTO Abort; }; xSize: REAL ¬ 8.5; -- default size in inches ySize: REAL ¬ 11.0; -- default size in inches args: PPreView.NameList ¬ LIST[]; --LIST OF ROPE nameList: PPreView.NameList ¬ LIST[]; --LIST OF ROPE switches: PPreView.Switches ¬ ALL[FALSE]; argLength: NAT ¬ 0; [list: args, length: argLength] ¬ CommanderOps.ParseToList[cmd]; IF args = NIL OR argLength < 1 THEN RETURN[$Failure, "Unable to parse command line"]; UNTIL args=NIL DO IF Rope.Fetch[base: args.first, index: 0] = '- THEN { tChar: CHAR; IF (tChar ¬ Ascii.Upper[Rope.Fetch[base: args.first, index: 1]]) IN PPreView.SwitchRange THEN switches[tChar] ¬ TRUE; SELECT tChar FROM 'S => { -- command arguments are two real numbers specifying page size args ¬ args.rest; xSize ¬ Convert.RealFromRope[args.first]; args ¬ args.rest; ySize ¬ Convert.RealFromRope[args.first]; IF xSize<=0.1 OR ySize <=0.1 THEN { result ¬ $Failure; msg ¬ "PreView: Specify positive real numbers for page sizes"; GOTO Abort; } ELSE args ¬ args.rest; }; 'C => { FOR a: PPreView.NameList ¬ args.rest, a.rest UNTIL a=NIL DO nameList ¬ CONS[a.first, nameList]; ENDLOOP; [] ¬ CreatePreViewer[fileNames: nameList, switches: switches, xSize: xSize, ySize: ySize, mustBe: mustBe]; GOTO Done; }; 'P => { FOR rl: PPreView.NameList ¬ args.rest, rl.rest UNTIL rl = NIL DO expandedList: LIST OF ROPE ¬ ExpandStars[rl.first, cmd.err]; nameList ¬ RopeList.Append[nameList, expandedList]; ENDLOOP; [] ¬ CreatePreViewer[fileNames: nameList, switches: switches, xSize: xSize, ySize: ySize, mustBe: mustBe]; GOTO Done; }; ENDCASE => args ¬ args.rest; } ELSE EXIT; -- hit first non-switch argument ENDLOOP; FOR rl: PPreView.NameList ¬ args, rl.rest UNTIL rl = NIL DO --open a PreViewer on each file expandedList: LIST OF ROPE ¬ ExpandStars[rl.first, cmd.err]; FOR nl: PPreView.NameList ¬ expandedList, nl.rest UNTIL nl = NIL DO [] ¬ CreatePreViewer[fileNames: nl, switches: switches, xSize: xSize, ySize: ySize, mustBe: mustBe]; ENDLOOP; ENDLOOP; EXITS Done, Abort => NULL; }; ExpandStars: PROC [rope: ROPE, err: IO.STREAM] RETURNS [LIST OF ROPE] ~ { ENABLE PFS.Error => {CommanderOps.Failed[error.explanation]}; head: LIST OF ROPE ~ LIST[NIL]; last: LIST OF ROPE ¬ head; path: PFS.PATH ¬ PFS.PathFromRope[rope]; short: PFSNames.Component ~ path.ShortName[]; Each: PFS.InfoProc ~ { IF fileType # PFS.tDirectory THEN last ¬ last.rest ¬ LIST[PFS.RopeFromPath[fullFName]]; }; IF short.version=[none] THEN path ¬ path.ReplaceShortName[[short.name, [highest]]]; PFS.EnumerateForInfo[path, Each]; IF head.rest = NIL THEN { IF Rope.Find[rope, "*"] >= 0 THEN { IO.PutRope[err, "No files for pattern "]; IO.PutRope[err, rope]; IO.PutRope[err, "\n"]; } ELSE last ¬ last.rest ¬ LIST[rope]; -- return the original rope which may later be extended and a file actually found }; RETURN [head.rest] }; PVChangedProc: UserProfile.ProfileChangedProc = { extensionList ¬ UserProfile.ListOfTokens[key: "PreView.Extensions", default: defaultExtensionList]; }; PVUserAction: BiScrollers.BSUserActionProc = { iv: Viewer ¬ bs.style.QuaViewer[bs: bs, inner: TRUE]; data: Data ¬ NARROW[BiScrollers.ClientDataOfViewer[iv]]; BiScrollers.DoBSUserAction[bs, input]; ShowSelection[data, iv]; }; Init: PROC = { pvTIP: TIPUser.TIPTable ¬ TIPUser.InstantiateNewTIPTable["PreView.tip"]; bsStyle ¬ BiScrollers.GetStyle[]; -- default gets BiScrollersButtonned pvBSClass ¬ bsStyle.NewBiScrollerClass[[ flavor: $PreViewer, extrema: PPreView.PVExtremaProc, notify: PPreView.PVNotify, paint: PPreView.PVPaint, destroy: PPreView.PVDestroy, get: PPreView.PVGetName, bsUserAction: PVUserAction, tipTable: pvTIP, cursor: crossHairsCircle, mayStretch: TRUE, -- OK to scale X and Y differently vanilla: PPreView.PVBasicTransformProc, --proc which provides the vanilla transform for BiScrollers preserve: [X: 0.5, Y: 0.5] --this specifies that the center of the viewers stays fixed when viewer size changes. Also, scale/rotate around the center ]]; selClass ¬ PopUpButtons.MakeClass[[ proc: SelectionOps, choices: LIST[ [$Center, "Center PreView selection in viewer"], [$CenterAndFit, "Center and fit PreView selection in viewer"], [$CenterAndScale, "Center and scale PreView selection to viewer"], [$SelectPage, "Set PreView selection to entire page"], [$SetSelection, "Set PreView selection to \"x y w h\" (in inches)"], [$ShowSelection, "Show PreView selection (in inches) in Message Window"] ], doc: "Selection: selection operations for current page" ]]; stuffClass ¬ PopUpButtons.MakeClass[[ proc: Stuff, choices: LIST[ [$Selection, "Stuff PreView selection"], [$Page, "Stuff entire page"], PopUpButtons.nullChoice, [$Fitted, "Fit and Stuff PreView selection"], [$PageFitted, "Fit and Stuff entire page"], PopUpButtons.nullChoice, [$Bordered, "Stuff PreView selection with borders"], [$PageBordered, "Stuff entire page with borders"], PopUpButtons.nullChoice, [$BorderedAndFitted, "Fit and Stuff PreView selection with borders"], [$PageBorderedAndFitted, "Fit and Stuff entire page with borders"], PopUpButtons.nullChoice ], doc: "Stuff: stuff PreView images into Tioga document" ]]; toIPClass ¬ PopUpButtons.MakeClass[[ proc: ToIP, choices: LIST[ [$Selection, "PreView selection to IP file"], [$Page, "Entire page to IP file"] ], doc: "ToIP: convert to Interpress and store in (Tioga) selected filename " ]]; pageClass ¬ PopUpButtons.MakeClass[[ proc: PageTurn, choices: LIST[ [$TurnForward, "Display next page"], PopUpButtons.nullChoice, [$TurnBackward, "Display previous page"], [$FirstPage, "Display first page"], [$FromTiogaSelection, "Display (Tioga) selected page number"], [$LastPage, "Display last page"] ], doc: "Page: move among pages in PreView document" ]]; UserProfile.CallWhenProfileChanges[proc: PVChangedProc]; -- PVChangedProc called immediately after this registration call Commander.Register[key: "IPPreView", proc: IPPreView, doc: "Create a PreViewer for an Interpress file" ]; Commander.Register[key: "AISPreView", proc: AISPreView, doc: "Create a PreViewer for an AIS file" ]; Commander.Register[key: "RESPreView", proc: RESPreView, doc: "Create a PreViewer for an RES file(s)" ]; Commander.Register[key: "PreView", proc: AnyPreView, doc: "Create a PreViewer for an image file(s)" ]; }; Init[]; END. : PPreViewTool.mesa Copyright Ó 1989, 1992 by Xerox Corporation. All rights reserved. Pier, July 17, 1992 4:45 pm PDT Carl Hauser, August 18, 1989 4:38:21 pm PDT Michael Plass, March 25, 1992 12:36 pm PST Chauser, June 25, 1992 4:06 pm PDT Expects a file name which may not have an extension Didn't find full name, so try a few extensions Given fullPath, determine if it is an interpress, press, PD, AIS, Griffin, Gargoyle file (or none). Uses the extension as a hint as to the filetype. Extension as hint did not help; so try all other possibilities This is a multipage image document with pages in separate files Find filename for this page of image data aisData.state.openFile _ NARROW[fileInfo.ref]; -- DiscoverFileType did an AIS.OpenFile already --read the AIS file(s) and get ready for display. aisData.state will be further filled in by this call. This is a multipage image document with pages in separate files Find filename for this page of image data aisData.state.openFile _ NARROW[fileInfo.ref]; -- DiscoverFileType did an AIS.OpenFile already --read the AIS file(s) and get ready for display. aisData.state will be further filled in by this call. [scanCount: state.scans, scanLength: state.pixels] _ AIS.ReadRaster[state.openFile]^; -- must be identical raster info in all separations Now construct a viewer caption like Foo-*.ais!33 bps: [0..16] _ 0; [scanCount: state.scans, scanLength: state.pixels, scanMode: , bitsPerPixel: bps] _ AIS.ReadRaster[state.openFile]^; Routines added for export to PPreViewOps units are inches for x, y, w and h IF data.bBox.rect.w=0 OR data.bBox.rect.h=0 THEN { Complain["Specify clipping box before clicking Stuff"]; RETURN; }; data.stuffWithBorders _ mouseButton=blue; data.stuffWithFit _ shift; select entire page DoFileOps will set data.abort if it fails to write repaint caption in case of multiple files being viewed [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL]; [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL]; [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL]; [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL]; command arguments are RGB components of a single color image command arguments are separate pages of a multipage image document allow StarExpansion for the individual arguments BSUserActionProc: TYPE = PROC [bs: BiScroller, input: LORA]; Ê.@•NewlineDelimiter –(cedarcode) style™code™Kšœ Ïeœ7™BK™K™+K™*K™"—K˜šÏk ˜ Kšœdžœ«žœ#žœÊ˜ƒ—K˜šÏn œžœž˜KšžœQžœ«žœ#žœ˜ÊKšžœ)ž˜5K˜Kšžœžœžœ˜Kšœ žœ˜#Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ žœ˜!Kšœ žœ˜!Kšœ žœ˜#Kšœžœ˜$K˜K˜EKšœžœÏc ˜.Kšœžœ  ˜-Kšœžœ  ˜/Kšœžœ  ˜.Kšœžœ  ˜3Kšœžœ˜Kšœžœ ˜&Kšœžœ˜"Kšœžœ˜"Kšœžœ˜"Kšœžœ˜"K˜@K˜BKšœ žœ +˜GKšœ žœ !˜Kšžœ #˜6Kšžœ žœ,žœ*žœ˜sKšžœ #˜5K–[stream: STREAM]š žœ5¤œžœžœžœ-žœ˜K–[stream: STREAM]š žœ;¤œžœžœžœ-žœ˜“Kšœžœžœ˜0K˜—šÏtœ˜Kš žœ žœ,žœ(žœžœ˜xK˜—˜Kšžœ5¤œžœžœžœ+žœžœ˜‘K˜—˜Kšžœ;¤œžœžœžœ+žœžœ˜—K˜—Kšžœžœ˜—šž˜Kšœžœžœ˜8—K˜—K˜K˜—š ŸœžœžœKžœ#žœ˜­Kšœ žœ˜Kšœžœžœ˜K˜YK˜;K˜K˜K˜—šŸœžœKžœ/žœžœžœžœžœ˜ÞKšœžœžœ˜Kšœžœ˜"Kšœžœ˜Kšœ žœžœ˜K˜šžœ žœžœ˜K–-[message: ROPE, clearFirst: BOOL _ FALSE]˜%Kšžœ˜K˜—šžœžœ˜K™?Kšœ žœ˜K˜-K™)šžœžœžœžœžœžœžœ˜@Kšžœžœžœ˜[viewer: ViewerClasses.Viewer, prop: ATOM, val: REF ANY]šœ.žœ¤¢œ ˜XK–>[viewer: ViewerClasses.Viewer, prop: ATOM, val: REF ANY]šœ>¤¢œ ˜MK˜:K˜:KšœFžœ˜LK˜šž˜˜ K˜WKšžœžœ ˜)K˜——K˜K˜—šŸœžœ;žœ(žœ žœžœžœžœ˜µšžœ˜šžœ ˜ K˜%Kšœ žœžœ˜K˜—šžœ ˜K˜%Kšœ žœžœ˜K˜—˜K˜%Kšœ žœžœ˜K˜—K˜—K˜K˜šžœžœž˜,šžœ ˜#Kšœ žœ˜Kšœ žœ˜*Kšœ žœ˜%Kšœ žœ˜ Kšœžœ ˜.Kšœžœ ˜1Kšœžœ ˜CKšœžœ ˜6Kšœ¢œ2 ˜xKšœ5žœ 3™‰K–'[maxSampleValue: ImagerSample.Sample]šœ 3˜QK–'[maxSampleValue: ImagerSample.Sample]šœ 3˜QK˜`K™0K–)[s: ROPE, pos: INT _ 0, skip: ROPE]šœˆ  ˜¨Kšžœžœs 8˜ÆKšžœžœžœ '˜[K˜—šžœ ˜K™K˜K˜KšœTžœ™tK–'[maxSampleValue: ImagerSample.Sample]˜K–'[maxSampleValue: ImagerSample.Sample]˜K˜3šžœž˜Kšœžœ˜šœ 7˜>K–„[pa: ImagerPixelArray.PixelArray, i: NAT _ 0, s: INT _ 0, f: INT _ 0, dst: ImagerSample.SampleMap, dstMin: SF.Vec _ [s: 0, f: 0], size: SF.Vec _ [s: 32767, f: 32767], function: ImagerSample.Function _ [dstFunc: null, srcFunc: null]]˜#K˜+K–X[box: SF.Box, bitsPerSample: ImagerSample.BitsPerSample _ 1, bitsPerLine: INT _ 0]˜TK˜SK˜[K–´[s0: ImagerSample.SampleMap _ NIL, s1: ImagerSample.SampleMap _ NIL, s2: ImagerSample.SampleMap _ NIL, s3: ImagerSample.SampleMap _ NIL, s4: ImagerSample.SampleMap _ NIL]šœŠžœ˜K˜K˜Kšœ žœ˜K˜—Kšžœ€˜‡—K˜K˜——Kšœžœ˜K˜K˜—šÐan œ# >˜mKšœ žœ˜"KšœLžœ˜Ršžœž˜šœ  ˜*Kšžœžœžœžœ˜(K–œ[bs: BiScrollers.BiScroller, client: BiScrollers.Location, viewer: BiScrollers.Location, doX: BOOL _ TRUE, doY: BOOL _ TRUE, paint: BOOL _ TRUE]šœéžœ˜ïK˜—šœ$ =˜aKšœžœ "˜>Kšžœžœžœžœ˜(K–œ[bs: BiScrollers.BiScroller, client: BiScrollers.Location, viewer: BiScrollers.Location, doX: BOOL _ TRUE, doY: BOOL _ TRUE, paint: BOOL _ TRUE]šœžœžœ˜@Kšœžœžœ˜2Kšœéžœ˜ðK–O[bs: BiScrollers.BiScroller, op: BiScrollers.ScaleOp, paint: BOOL _ TRUE]šžœžœbžœ ˜¡KšœZžœžœ˜}K˜—šœ ˜&Kšžœžœ_žœ ˜¦Kšœžœ¸ =˜Kšœ^žœ ˜‡K˜—šœ ˜0Kš œ žœžœžœžœ%˜D˜šžœžœžœ˜$K˜;Kšžœ ˜K˜—Kšœžœžœ$˜0Kšœžœžœ$˜0Kšœžœžœ$˜0Kšœžœžœ$˜0K˜K˜4K˜RKšœžœ˜K˜—K˜7Kšžœžœ˜K˜—Kšœžœ ˜3Kšžœžœ˜—Kš¢ œ˜šž˜K˜*—K˜K˜—šŸœžœžœ žœ˜NKšžœN˜TK˜K˜—š Ÿœžœžœ£œ£œ˜NKšžœ˜K˜K˜@KšžœE˜KK˜J™—šŸ œžœžœ˜6šžœžœ˜K˜5šœ/žœ˜AKšžœ%˜'—šœ/žœ˜AKšžœ%˜'—˜šžœ@˜BKšžœ-˜/Kšžœ-˜/Kšžœ-˜/Kšžœ/˜1—Kšžœ˜—K˜—Kšžœ.žœ˜8K˜—K˜™(J™—š Ÿ œžœžœžœžœ˜Nšžœžœžœžœ˜'KšœGžœ˜MK˜*Kšœžœžœ&˜*K˜*K˜*K˜—Kšžœžœ˜K˜K˜—šŸ œž œ#žœ˜EJ™"šžœžœžœ˜KšœGžœ˜MKšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜K˜"K˜4K˜RKšœžœ˜K˜2K˜—K˜K˜—šŸœž œ˜5šžœžœžœ˜KšœGžœ˜MK˜"Kšžœ žœ3 ˜VKšœ  B˜KK˜—K˜K˜—šŸ œžœžœžœ˜>šžœžœžœ˜KšœGžœ˜MKšœ5žœ ˜CK˜—K˜K˜—šŸ œžœžœžœ˜Sšžœžœžœžœ˜K˜OKšžœžœ˜ —K˜K˜—šŸ œžœžœA˜Zšžœžœž˜K˜]—K˜—K˜K˜š©œ# >˜fKšœ žœ˜"šžœžœžœ™2K™7Kšžœ™K™—K™)K™š žœ žœžœžœžœ˜YK™Kšžœžœ_žœ ˜¦Kšœžœy =˜ÐKšœ^žœ ˜‡K˜—šžœžœžœžœ˜7K˜7Kšžœ˜K˜—Kšœ&žœžœžœ˜sKšœ žœžœžœ˜kKšœažœžœžœ˜K˜K˜—š©œ# >˜eKšžœžœ žœ ˜"Kšœ žœžœ˜Kšœ žœ˜"KšœHžœ˜NK–.[viewer: ViewerClasses.Viewer, prop: ATOM]šœžœ&˜0šžœžœžœžœ˜GK˜;Kšžœ˜K˜—šžœžœ'žœ ˜`Kšœ žœ.  ˜[Kšœžœ,žœžœR˜¥K˜—K˜˜Kšœžœžœžœ˜(KšœžœžœG˜UK˜'Kšœžœ˜K˜—K˜K˜Kšœ1žœR˜‡šžœ žœ˜K˜_K™2Kšžœ žœž˜%Kšžœ?žœ˜IK˜—šž˜˜ K˜pKšžœ ˜$K˜——K˜K˜—šŸœžœžœžœžœžœžœ žœžœ žœžœ˜‰Kšœžœžœ˜šžœžœ˜!K–Ò[gargoyleData: REF ANY, msgType: GGError.MsgType, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]˜"Kšžœžœžœ˜K˜—šœ¤œžœ ˜1Kšœ žœ˜K–Ò[gargoyleData: REF ANY, msgType: GGError.MsgType, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šœ žœD˜OKšžœ˜ K˜K˜—šžœ žœ˜Kšœ¢œ ¢œ ˜MKšœžœV ˜ƒK–9[base: ROPE, start: INT _ 0, len: INT _ 2147483647]šœ žœ:žœ˜NK–9[base: ROPE, start: INT _ 0, len: INT _ 2147483647]š œ žœžœ žœžœžœ8˜cšžœ žœžœžœ žœžœžœžœ žœž˜ašžœ%žœžœ˜4Kšœ žœW˜bKšœ žœ˜Kšžœ˜K˜—Kšž˜—šžœ˜K˜?Kšœ¢œ” ˜ÂK˜—Kšœ žœ˜"K˜—K˜K˜—š Ÿœžœ žœžœžœ˜;K˜DK˜K˜K˜—K˜šŸœ# >˜iKšœ žœ˜"šžœž˜K˜!Kšœ žœžœ0˜WKšœ!žœžœ0˜XK˜2˜Kš œžœžœžœžœ%˜?šœžœžœžœ˜;K˜'Kšžœ˜ K˜K˜—Kšœžœžœ$˜;K˜—Kšžœžœ˜—šž˜Kšœ žœ˜—K˜K˜—š©œ˜+Kšœ žœ ˜ Kšœžœ˜+Kšžœ3˜9K˜K˜—š©œ˜(Kšœ žœ ˜ Kšœžœ˜+šžœž˜˜ Kšœ/žœžœ˜ZK˜—˜ Kšœ/žœžœ)˜kK˜—˜Kšœžœžœ=˜TK˜—Kšžœ˜—K˜K˜—šŸ œž œžœ˜4Kšœžœ˜+Kšœ/žœžœ˜SK˜DKšžœžœžœ %˜NK˜šžœžœž˜Kšœžœ˜Kšžœ# ˜D—KšœFžœ˜LK™6KšœJžœ˜QK˜—K˜šŸ œžœ˜+Kš œžœ žœžœžœ™;K˜#K˜K˜—šŸ œžœ˜,Kš œžœ žœžœžœ™;K˜$K˜K˜—šŸ œžœ˜,Kš œžœ žœžœžœ™;K˜$K˜K˜—š© œžœ˜,Kš œžœ žœžœžœ™;K˜$K˜K˜—š© œžœ9žœ žœžœžœžœ˜xšžœ˜K˜K˜>Kšžœ˜ K˜—Kšœžœ ˜,Kšœžœ  ˜-Kšœžœ ˜0Kšœžœ ˜4Kšœžœžœ˜)Kšœ žœ˜K˜@Kš žœžœžœžœžœ+˜U– [base: ROPE, index: INT _ 0]šžœžœž˜šžœ-žœ˜5Kšœžœ˜ Kšžœ?žœžœžœ˜ušžœž˜šœ >˜FK˜K˜)K˜K˜)šžœ žœ žœ˜#K˜K˜>Kšžœ˜ K˜—Kšžœ˜K˜—˜K™K˜BK˜6K˜DK˜HK˜—K˜7K˜K˜—˜%K˜ šœ žœ˜K˜(K˜K˜K˜-K˜+K˜K˜4K˜2K˜K˜EK˜CK˜K˜—K˜6K˜K˜—˜$K˜ šœ žœ˜K˜-K˜!K˜—K˜JK˜—K˜˜$K˜šœ žœ˜K˜$K˜K˜)K˜#K˜>K˜ K˜—K˜1K˜K˜—Kšœ9 @˜yK˜iK˜dK˜gK˜fK˜—K˜˜K˜—Kšžœ˜—…—œŽÔ