DIRECTORY Commander USING [CommandProc, Register], CommandTool USING [CurrentWorkingDirectory, ParseToList], Convert USING [IntFromRope], FS USING [ComponentPositions, Error, ExpandName, FileInfo], GriffinImageUtils USING [GriffinToImagerCalls, ReadGriffinImage], Icons USING [IconFlavor, NewIconFromFile], Imager, ImagerBackdoor USING [GetBounds], ImagerInterpress USING [Close, Create, DoPage, Ref], ImagerMemory USING [NewMemoryContext, Replay], ImagerTypeface USING [Find], ImagerTypefaceExtras USING [GenericCreatorProc, GenericCreatorRep, RegisterGenericCreator], Interpress USING [DoPage, LogProc, Open, OpenMaster], IO USING [PutRope], IPViewers, Menus USING [AppendMenuEntry, ClickProc, CreateEntry, CreateMenu, Menu], MessageWindow USING [Append, Blink], Rope USING [Cat, Find, Index, Length, ROPE, Substr], UserProfile USING [ListOfTokens], ViewerClasses USING [InitProc, PaintProc, SaveProc, Viewer, ViewerClass, ViewerClassRec, ViewerRec], ViewerOps USING [CreateViewer, DestroyViewer, PaintViewer, RegisterViewerClass, SaveViewer], ViewerTools USING [GetSelectionContents]; IPViewersImpl: CEDAR PROGRAM IMPORTS Commander, CommandTool, Convert, FS, GriffinImageUtils, Icons, Imager, ImagerBackdoor, ImagerInterpress, ImagerMemory, ImagerTypeface, ImagerTypefaceExtras, Interpress, IO, Menus, MessageWindow, Rope, UserProfile, ViewerOps, ViewerTools EXPORTS IPViewers ~ BEGIN OPEN IPViewers; Viewer: TYPE ~ ViewerClasses.Viewer; Context: TYPE ~ Imager.Context; ROPE: TYPE ~ Rope.ROPE; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ dirOnly: BOOLEAN _ FALSE, --TRUE => viewer.file contains only a working directory preamble: Context, --Played for every page currentPage: CARDINAL _ 0, pages: SEQUENCE nPages: CARDINAL OF Page ]; Page: TYPE ~ RECORD [ context: Context, bounds: Imager.Rectangle ]; InvalidPage: PUBLIC ERROR ~ CODE; BadName: ERROR ~ CODE; Create: PUBLIC PROC [info: ViewerClasses.ViewerRec _ [], paint: BOOL _ TRUE, pages: CARDINAL _ 1] RETURNS [v: IPViewer] ~ { data: Data; v _ ViewerOps.CreateViewer[$IPViewer, info, paint]; data _ NARROW[v.data]; IF data.dirOnly OR pages > data.nPages THEN SetNumberOfPages[v, pages]; }; DoActions: PUBLIC PROC [v: IPViewer, action: PROC [context: Imager.Context], page: CARDINAL _ 0] ~ { data: Data ~ NARROW[v.data]; IF ~(page IN [0..data.nPages)) THEN ERROR InvalidPage[]; action[data.pages[page].context]; IF ~v.newVersion THEN { v.newVersion _ TRUE; ViewerOps.PaintViewer[v, caption]; }; }; SetBounds: PUBLIC PROC [v: Viewer, bounds: Imager.Rectangle, page: CARDINAL _ 0] ~ { data: Data ~ NARROW[v.data]; IF ~(page IN [0..data.nPages)) THEN ERROR InvalidPage[]; data.pages[page].bounds _ bounds; }; GetContext: PUBLIC UNSAFE PROC [v: IPViewer, page: CARDINAL _ 0] RETURNS [context: Imager.Context] ~ { data: Data ~ NARROW[v.data]; IF ~(page IN [0..data.nPages)) THEN ERROR InvalidPage[]; RETURN [data.pages[page].context]; }; SetNumberOfPages: PUBLIC PROC [v: IPViewer, pages: CARDINAL] ~ { oldData: Data ~ NARROW[v.data]; newData: Data ~ NEW[DataRep[pages]]; numberToCopy: CARDINAL ~ MIN[oldData.nPages, pages]; v.data _ newData; newData.dirOnly _ oldData.dirOnly; newData.preamble _ oldData.preamble; newData.currentPage _ oldData.currentPage; FOR index: CARDINAL IN [0..numberToCopy) DO newData.pages[index] _ oldData.pages[index]; ENDLOOP; FOR index: CARDINAL IN [numberToCopy..newData.nPages) DO newData.pages[index].context _ ImagerMemory.NewMemoryContext[]; newData.pages[index].bounds _ [x: 0, y: 0, w: 8.5*Imager.metersPerInch, h: 11*Imager.metersPerInch]; ENDLOOP; }; IPSave: ViewerClasses.SaveProc ~ { ref: ImagerInterpress.Ref ~ ImagerInterpress.Create[fileName: self.file]; data: Data ~ NARROW[self.data]; IF ~self.newVersion THEN RETURN; --Don't waste time on unedited things IF data.dirOnly THEN { MessageWindow.Append["Can't SAVE -- no file name!"]; MessageWindow.Blink[]; RETURN; }; FOR index: CARDINAL IN [0..data.nPages) DO Action: PROC [c: Imager.Context] ~ { ImagerMemory.Replay[data.pages[index].context, c]; }; ImagerInterpress.DoPage[ref, Action]; ENDLOOP; ImagerInterpress.Close[ref]; self.newVersion _ FALSE; SetNameAndLabel[self]; ViewerOps.PaintViewer[self, caption]; }; IPInit: ViewerClasses.InitProc ~ { data: Data _ NEW[DataRep[1]]; data.pages[0] _ [context: ImagerMemory.NewMemoryContext[], bounds: [x: 0, y: 0, w: 8.5*Imager.metersPerInch, h: 11*Imager.metersPerInch]]; self.data _ data; IF Rope.Length[GetWDirFromName[self.file]]=0 THEN self.file _ Rope.Cat[CommandTool.CurrentWorkingDirectory[], self.file]; { --See if just a directory, and set name appropriately self.file _ FS.ExpandName[self.file ! FS.Error => IF error.group=user THEN GOTO DirectoryOnly].fullFName; EXITS DirectoryOnly => { fullFName: ROPE ~ FS.ExpandName[Rope.Cat[self.file, "Z"]].fullFName; self.file _ Rope.Substr[base: fullFName, len: Rope.Length[fullFName]-1]; data.dirOnly _ TRUE; }; }; SetNameAndLabel[self]; IF ~data.dirOnly THEN { LoadContext[self]; self.newVersion _ FALSE; ViewerOps.PaintViewer[self, caption]; }; }; IPPaint: ViewerClasses.PaintProc ~ { data: Data ~ NARROW[self.data]; page: CARDINAL ~ data.currentPage; screenBounds: Imager.Rectangle ~ ImagerBackdoor.GetBounds[context]; imageBounds: Imager.Rectangle ~ IF (data.currentPage IN [0..data.nPages)) THEN data.pages[page].bounds ELSE [0, 0, 8.5, 11]; dx: REAL ~ screenBounds.w/2; dy: REAL ~ screenBounds.h/2; scale: REAL ~ MIN[screenBounds.w/imageBounds.w, screenBounds.h/imageBounds.h]; IF ~data.currentPage IN [0..data.nPages) THEN RETURN; Imager.SetGray[context, .75]; --Background gray Imager.MaskRectangle[context, screenBounds]; Imager.TranslateT[context, [dx, dy]]; Imager.ScaleT[context, scale]; Imager.TranslateT[context, [-(imageBounds.x+imageBounds.w/2), -(imageBounds.y+imageBounds.h/2)]]; Imager.SetColor[context, Imager.white]; Imager.MaskRectangle[context, imageBounds]; Imager.ClipRectangle[context, imageBounds]; Imager.SetColor[context, Imager.black]; ImagerMemory.Replay[data.pages[page].context, context]; }; Clear: Menus.ClickProc ~ { v: Viewer ~ NARROW[parent]; SetNumberOfPages[v, 0]; v.file _ GetWDirFromName[v.file]; SetNameAndLabel[v]; ViewerOps.PaintViewer[v, all]; }; Get: Menus.ClickProc ~ { v: Viewer ~ NARROW[parent]; name: ROPE _ FigureFileNameFromSelection[v ! BadName => GOTO BailOut]; includesVersion: BOOLEAN _ Rope.Find[name, "!"]#-1; --Was a version specified? name _ FS.FileInfo[name ! FS.Error => { IF error.group=user THEN { MessageWindow.Append[Rope.Cat[name, " not found."], TRUE]; MessageWindow.Blink[]; GOTO BailOut; }; }].fullFName; IF ~includesVersion THEN name _ Rope.Substr[base: name, len: Rope.Index[s1: name, s2: "!"]]; v.file _ name; LoadContext[v]; SetNameAndLabel[v]; ViewerOps.PaintViewer[v, all]; EXITS BailOut => NULL }; Store: Menus.ClickProc ~ { v: Viewer ~ NARROW[parent]; data: Data ~ NARROW[v.data]; name: ROPE _ FigureFileNameFromSelection[v ! BadName => GOTO BailOut]; v.file _ name; v.newVersion _ TRUE; data.dirOnly _ FALSE; SetNameAndLabel[v]; ViewerOps.SaveViewer[v]; EXITS BailOut => NULL; }; StoreDocumentation: Menus.ClickProc ~ { v: Viewer ~ NARROW[parent]; name: ROPE _ FigureFileNameFromSelection[v ! BadName => GOTO BailOut]; MessageWindow.Append[Rope.Cat["Confirm Store to file: ", name]]; EXITS BailOut => NULL; }; Save: Menus.ClickProc ~ { v: Viewer ~ NARROW[parent]; SetNameAndLabel[v]; ViewerOps.SaveViewer[v]; }; LoadFromInterpress: Menus.ClickProc ~ { v: Viewer ~ NARROW[parent]; LoadContext[v, FigureFileNameFromSelection[v] ! BadName => GOTO BailOut]; EXITS BailOut => NULL }; LoadFromGriffin: Menus.ClickProc ~ { ImageGriffin: PROC [context: Context] ~ { OPEN GriffinImageUtils; Imager.ScaleT[context, Imager.metersPerMica]; GriffinToImagerCalls[context, ReadGriffinImage[name]]; v.newVersion _ TRUE; ViewerOps.PaintViewer[v, all]; }; v: Viewer ~ NARROW[parent]; data: Data ~ NARROW[v.data]; name: ROPE _ FigureFileNameFromSelection[v ! BadName => GOTO Fail]; name _ FS.FileInfo[name ! FS.Error => { IF error.group=user THEN { MessageWindow.Append[Rope.Cat[name, " not found."], TRUE]; MessageWindow.Blink[]; GOTO Fail; }; }].fullFName; DoActions[NARROW[parent], ImageGriffin, data.currentPage]; EXITS Fail => NULL }; TurnPage: Menus.ClickProc ~ { ENABLE ANY => GOTO InvalidNumber; v: Viewer ~ NARROW[parent]; data: Data ~ NARROW[v.data]; newPage: CARDINAL _ SELECT mouseButton FROM red => IF shift THEN LAST[CARDINAL] ELSE data.currentPage+1, yellow => CARDINAL[Convert.IntFromRope[ViewerTools.GetSelectionContents[] ! ANY => GOTO InvalidNumber]-1], blue => IF shift THEN 0 ELSE data.currentPage-1, ENDCASE => ERROR; IF data.nPages=0 THEN GOTO NoPages; newPage _ MIN[data.nPages-1, newPage]; data.currentPage _ newPage; ViewerOps.PaintViewer[v, client]; EXITS InvalidNumber => { MessageWindow.Append["Invalid number", TRUE]; MessageWindow.Blink[]; }; NoPages => { MessageWindow.Append["No pages to turn.", TRUE]; MessageWindow.Blink[]; }; }; IPOpen: Commander.CommandProc ~ { args: LIST OF ROPE ~ CommandTool.ParseToList[cmd].list; msg _ NIL; FOR each: LIST OF ROPE _ args, each.rest UNTIL each=NIL DO viewer: Viewer; fullName: ROPE _ FS.ExpandName[each.first, CommandTool.CurrentWorkingDirectory[]].fullFName; IF Rope.Find[each.first, "!"]=-1 THEN fullName _ Rope.Substr[base: fullName, len: Rope.Index[s1: fullName, s2: "!"]]; --Strip bang off viewer _ Create[[file: fullName, iconic: TRUE] ! FS.Error => IF error.group=user THEN { IO.PutRope[cmd.err, error.explanation]; IO.PutRope[cmd.err, "\n"]; result _ $Failure; IF viewer#NIL THEN ViewerOps.DestroyViewer[viewer ! ANY => CONTINUE]; CONTINUE; }]; ENDLOOP; }; IPNew: Commander.CommandProc~ { [] _ Create[[file: CommandTool.CurrentWorkingDirectory[], iconic: FALSE] ! BadName => CONTINUE]; }; LogProc: Interpress.LogProc ~ { ERROR; }; LoadContext: PROC [v: Viewer, file: ROPE _ NIL, expandIfNeeded: BOOLEAN _ TRUE] ~ { IF file=NIL THEN file _ v.file; file _ FS.FileInfo[file ! FS.Error => { IF error.group=user THEN { MessageWindow.Append[Rope.Cat[file, " not found."], TRUE]; MessageWindow.Blink[]; }; }].fullFName; { data: Data _ NARROW[v.data]; ipMaster: Interpress.OpenMaster ~ Interpress.Open[fileName: file, logProc: LogProc ! FS.Error => IF error.group=user THEN GOTO Fail]; IF expandIfNeeded AND ipMaster.pages > data.nPages THEN { SetNumberOfPages[v, ipMaster.pages]; data _ NARROW[v.data]; }; FOR index: CARDINAL IN [0..MIN[CARDINAL[ipMaster.pages], data.nPages]) DO Interpress.DoPage[ipMaster, index+1, data.pages[index].context]; ENDLOOP; v.newVersion _ TRUE; ViewerOps.PaintViewer[v, all]; }; EXITS Fail => ERROR BadName[]; }; FigureFileNameFromSelection: PROC [v: Viewer] RETURNS [f: ROPE] ~ { wDir: ROPE _ GetWDirFromName[v.file]; name: ROPE _ ViewerTools.GetSelectionContents[]; IF Rope.Length[name]=0 THEN { MessageWindow.Append["Please select file name."]; MessageWindow.Blink[]; ERROR BadName; }; f _ FS.ExpandName[name, wDir ! FS.Error => { IF error.group=user THEN { MessageWindow.Append["Illegal file name."]; MessageWindow.Blink[]; GOTO ReportBadName; }; } ].fullFName; EXITS ReportBadName => ERROR BadName; }; SetNameAndLabel: PROC [v: Viewer] ~ { data: Data ~ NARROW[v.data]; prefixes: LIST OF ROPE ~ UserProfile.ListOfTokens["Viewers.SuppressIconPrefix", NIL]; v.name _ v.label _ v.file; IF ~data.dirOnly THEN { v.name _ Rope.Cat[v.name, " (?)"]; }; v.icon _ IF v.newVersion THEN pvIconBlack ELSE pvIconWhite; FOR each: LIST OF ROPE _ prefixes, each.rest UNTIL each=NIL DO IF Rope.Find[s1: v.label, s2: each.first, case: FALSE]=0 THEN v.label _ Rope.Substr[base: v.label, start: Rope.Length[each.first]]; ENDLOOP; }; GetWDirFromName: PROC [name: ROPE] RETURNS [wDir: ROPE] ~ { cp: FS.ComponentPositions; fullName: ROPE; [fullFName: fullName, cp: cp] _ FS.ExpandName[name ! FS.Error => IF error.group=user AND error.code=$illegalName THEN { [fullFName: fullName, cp: cp] _ FS.ExpandName[Rope.Cat[name, "Z"]]; fullName _ Rope.Substr[base: fullName, len: Rope.Length[fullName]-1]; CONTINUE; }]; RETURN [Rope.Substr[base: fullName, len: cp.base.start]]; }; pvIconWhite: Icons.IconFlavor ~ Icons.NewIconFromFile["Persistent.icons", 0]; pvIconBlack: Icons.IconFlavor ~ Icons.NewIconFromFile["Persistent.icons", 1]; pvMenu: Menus.Menu _ Menus.CreateMenu[]; pvClass: ViewerClasses.ViewerClass ~ NEW[ViewerClasses.ViewerClassRec _ [ flavor: $IPViewer, save: IPSave, paint: IPPaint, init: IPInit, menu: pvMenu, icon: pvIconWhite ]]; FontSubstitution: ImagerTypefaceExtras.GenericCreatorProc ~ { RETURN [ImagerTypeface.Find["Xerox/PressFonts/Helvetica-mrr"]]; }; Init: PROC ~ { { --Set up the menu OPEN Menus; AppendMenuEntry[pvMenu, CreateEntry[name: "Clear", proc: Clear]]; AppendMenuEntry[pvMenu, CreateEntry[name: "Get", proc: Get]]; AppendMenuEntry[pvMenu, CreateEntry[name: "Store", proc: Store, documentation: NEW[ Menus.ClickProc _ StoreDocumentation], guarded: TRUE]]; AppendMenuEntry[pvMenu, CreateEntry[name: "Save", proc: Save]]; AppendMenuEntry[pvMenu, CreateEntry[name: "LoadFromInterpress", proc: LoadFromInterpress]]; AppendMenuEntry[pvMenu, CreateEntry[name: "LoadFromGriffin", proc: LoadFromGriffin]]; AppendMenuEntry[pvMenu, CreateEntry[name: "Page", proc: TurnPage]]; ViewerOps.RegisterViewerClass[$IPViewer, pvClass]; }; Commander.Register[key: "IPOpen", proc: IPOpen, doc: "IPOpen fileName - open an interpress viewer"]; Commander.Register[key: "IPNew", proc: IPNew, doc: "Open an empty interpress viewer"]; ImagerTypefaceExtras.RegisterGenericCreator[NEW[ImagerTypefaceExtras.GenericCreatorRep _ [data: NIL, proc: FontSubstitution, priority: 0]]]; }; Init[]; END. ΰIPViewersImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Eric Nickell, August 1, 1985 10:47:58 am PDT Michael Plass, September 24, 1985 11:27:47 am PDT PROC [self: Viewer, force: BOOL _ FALSE] PROC [self: Viewer, context: Imager.Context, whatChanged: REF, clear: BOOL] RETURNS [quit: BOOL _ FALSE] Center the context in the viewer PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE] PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE] PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE] PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE] IF v.newVersion THEN v.name _ Rope.Cat[v.name, " [Edited]"]; AppendMenuEntry[pvMenu, CreateEntry[name: "Reset", proc: Reset, documentation: ResetDocumentation, guarded: TRUE]]; Κ‡˜™Icodešœ Οmœ1™[s1: ROPE, pos1: INT _ 0, s2: ROPE, case: BOOL _ TRUE]šžœžœD˜\K˜K˜K˜K˜Kšžœ ž˜K˜—š‘œ˜Kšžœ žœžœžœžœžœ3žœžœ™pKšœ žœ ˜Kšœ žœ ˜Kšœžœ.žœ ˜FK˜Kšœžœ˜Kšœžœ˜K˜K˜Kšžœ žœ˜K˜—š‘œ˜'Kšœ žœ ˜Kšœžœ.žœ ˜FK˜@Kšžœ žœ˜K˜—š‘œ˜Kšžœ žœžœžœžœžœ3žœžœ™pKšœ žœ ˜K˜K˜K˜—š‘œ˜'Kšœ žœ ˜Kšœ;žœ ˜IKšžœ ž˜K˜K˜—šΟbœ˜$š‘ œžœ˜)Kšžœ˜K˜-K˜6Kšœžœ˜K˜Kšœ˜—Kšœ žœ ˜Kšœ žœ ˜Kšœžœ.žœ˜Cšœžœžœ ˜'šžœžœ˜Kšœ4žœ˜:K˜Kšžœ˜ Kšœ˜—Kšœ ˜ —Kšœ žœ*˜:Kšžœ ž˜K˜—code2š‘œ˜Kšžœžœžœ˜!Kšœ žœ ˜Kšœ žœ ˜šœ žœžœ ž˜+Kš œžœžœžœžœžœ˜[s1: ROPE, pos1: INT _ 0, s2: ROPE, case: BOOL _ TRUE]šžœžœQ ˜†šœ)žœžœžœ˜WKšžœ'žœ˜CK˜Kš žœžœžœ"žœžœ˜EKšžœ˜ Kšœ˜—Kšžœ˜—K˜—š‘œ˜KšœBžœžœ˜`K˜—K˜š‘œ˜Kšžœ˜K˜—š ‘ œžœžœžœžœžœ˜SKšžœžœžœ˜šœžœžœ ˜'šžœžœ˜Kšœ4žœ˜:K˜Kšœ˜—Kšœ ˜ —šœ˜Kšœ žœ ˜Kš œUžœ žœžœžœ˜…šžœžœžœ˜9Kšœ$˜$Kšœžœ ˜Kšœ˜—š žœžœžœžœžœ ž˜IK˜@Kšžœ˜—Kšœžœ˜K˜Kšœ˜—Kšžœ žœ ˜K˜—š‘œžœ žœžœ˜CKšœžœ˜%Kšœžœ&˜0šžœžœ˜K˜1K˜Kšžœ ˜Kšœ˜—˜šœ˜šžœžœ˜Kšœ+˜+K˜Kšžœ˜Kšœ˜—Kšœ˜—K˜ —Kšžœžœ ˜%K˜—š‘œžœ˜%Kšœ žœ ˜Kš œ žœžœžœ:žœ˜UK˜šžœžœ˜K˜"Kšœ˜—Kšžœžœ(™K–9[base: ROPE, start: INT _ 0, len: INT _ 2147483647]šžœ.žœžœF˜ƒKšžœ˜—K˜—š ‘œžœžœžœžœ˜;Kšœžœ˜Kšœ žœ˜K˜š œ žœžœ žœžœžœ˜wKšœ žœ!˜CK–9[base: ROPE, start: INT _ 0, len: INT _ 2147483647]šœE˜EKšžœ˜ Kšœ˜—K˜K–9[base: ROPE, start: INT _ 0, len: INT _ 2147483647]šžœ3˜9K˜—K˜K˜MK˜MK˜(šœI˜IK˜Kšœ ˜ Kšœ˜Kšœ ˜ K˜ K˜Kšœ˜K˜—K˜š‘œ-˜=Kšžœ9˜?K˜—š‘œžœ˜šœ ˜Kšžœ˜ K–’[name: ROPE, proc: Menus.ClickProc, clientData: REF ANY _ NIL, documentation: REF ANY _ NIL, fork: BOOL _ TRUE, guarded: BOOL _ FALSE]˜AK–’[name: ROPE, proc: Menus.ClickProc, clientData: REF ANY _ NIL, documentation: REF ANY _ NIL, fork: BOOL _ TRUE, guarded: BOOL _ FALSE]šœlžœ™sK–’[name: ROPE, proc: Menus.ClickProc, clientData: REF ANY _ NIL, documentation: REF ANY _ NIL, fork: BOOL _ TRUE, guarded: BOOL _ FALSE]˜=K–’[name: ROPE, proc: Menus.ClickProc, clientData: REF ANY _ NIL, documentation: REF ANY _ NIL, fork: BOOL _ TRUE, guarded: BOOL _ FALSE]šœOžœ2žœ˜‹K–’[name: ROPE, proc: Menus.ClickProc, clientData: REF ANY _ NIL, documentation: REF ANY _ NIL, fork: BOOL _ TRUE, guarded: BOOL _ FALSE]˜?K˜[K˜UK˜CKšœ2˜2Kšœ˜—K–x[key: ROPE, proc: Commander.CommandProc, doc: ROPE _ NIL, clientData: REF ANY _ NIL, interpreted: BOOL _ TRUE]˜dK–x[key: ROPE, proc: Commander.CommandProc, doc: ROPE _ NIL, clientData: REF ANY _ NIL, interpreted: BOOL _ TRUE]˜VKšœ,žœ1žœ)˜ŒK˜K˜—K˜—K˜Kšžœ˜—…—4ΨP?