DIRECTORY Ascii USING [BS, ControlA, ControlQ, ControlW, CR, DEL, Digit, ESC, SP], BiScrollers USING [BiScroller, QuaViewer, ViewportBox], ImagerFont USING [Extents, Font, RopeBoundingBox], FileNames USING [GetShortName, Directory], FS USING [Error, FileInfo], Geom2D USING [id, Rect], Imager USING [black, Box, Color, MakeGray, Context, MaskRectangleI, Rectangle, Scale2T, ScaleT, SetColor, SetPriorityImportant, TranslateT, white ], ImagerBackdoor USING [GetT, SetT, GetBounds], ImagerInterpress USING [Ref, Create, DoPage, Close], ImagerPress USING [SimpleCreate, NewPage, DoWithWarnings, Close, Warning, PrinterType], ImagerTransformation USING [PostScale2, PostTranslate, TransformRectangle], MessageWindow USING [Append, Blink], Real USING [Fix, RoundI, RealException], RefText USING [AppendChar, SkipTo], Rope USING [Cat, Concat, Equal, Fetch, Find, FromChar, Length, ROPE, Substr, SkipTo, ToRefText], UserProfile USING [ListOfTokens], ViewerClasses USING [Viewer], ViewerOps USING [PaintViewer, SetNewVersion], SilColor, SilDisplayInternal, SilDisplay, SilDisplayUtils, SilFile, SilKernel, SilUserInput ; SilDisplayUtilsImpl: CEDAR MONITOR IMPORTS Ascii, BiScrollers, FileNames, FS, Geom2D, Imager, ImagerBackdoor, ImagerFont, ImagerInterpress, ImagerPress, ImagerTransformation, MessageWindow, Real, Rope, RefText, UserProfile, SilFile, SilDisplay, SilUserInput, ViewerOps, SilColor, SilKernel, SilDisplayUtils EXPORTS SilDisplayUtils, SilKernel = BEGIN OPEN SilFile; ROPE: TYPE = Rope.ROPE; SilData: TYPE = SilKernel.SilData; SilDisplayData: TYPE = REF SilDisplayDataRec; SilDisplayDataRec: PUBLIC TYPE = SilDisplayInternal.SilDisplayDataRec; SilModel: TYPE = SilFile.SilModel; SilUIData: TYPE = SilKernel.SilUIData; ContextChoice: TYPE = SilDisplayUtils.ContextChoice; AttributeRec: TYPE = SilDisplayUtils.AttributeRec; Orientation: TYPE = SilDisplayUtils.Orientation; BoxEnd: TYPE = SilDisplayUtils.BoxEnd; FileType: TYPE = SilDisplayUtils.FileType; metersPerPoint: REAL = .0254/72.0; -- DO NOT USE Imager.metersPerPoint where point=72.27 pointsPerInch: REAL = 72.0; -- DO NOT USE Imager.pointsPerInch where point=72.27 margin: INTEGER _ 9; -- 1/4 inch (i.e.2*9=18) points ModifyContext: PUBLIC PROC [makeContext: ContextChoice _ normal, dData: SilDisplayData, ctx: Imager.Context] = { IF ctx = NIL THEN RETURN; IF makeContext = magnified THEN { dData.trans _ ImagerBackdoor.GetT[ctx]; -- save transformation for later Imager.ScaleT[ctx, dData.currentMagnification]; Imager.TranslateT[ctx, [dData.xOffset, dData.yOffset]]; } ELSE ImagerBackdoor.SetT[ctx, dData.trans]; -- restore transformation }; MagnifyDrawing: PUBLIC PROC [data: SilData, ctx: Imager.Context, xMin, yMin, xMax, yMax: INTEGER] = { largeMagnification: INTEGER = 10; maxMagnification: INTEGER = SilDisplayInternal.maxMagnification; dData: SilDisplayData _ data.displayData; bxMin, byMin, bxMax, byMax: INTEGER; [bxMin, byMin, bxMax, byMax] _ BoundingBoxOfContext [ctx]; Imager.SetColor[ctx, Imager.white]; Imager.MaskRectangleI[ctx, bxMin, byMin, bxMax - bxMin, byMax - byMin]; dData.magnificationOn _ NOT dData.magnificationOn; IF dData.magnificationOn THEN { bs: BiScrollers.BiScroller _ SilUserInput.GetBiScroller[data.uiData]; bb: Geom2D.Rect _ BiScrollers.ViewportBox[bs]; -- rect: x,y,w,h dData.currentMagnification _ Real.RoundI[MIN[ IF xMax - xMin # 0 THEN bb.w / (xMax - xMin) ELSE largeMagnification, IF yMax - yMin # 0 THEN bb.h / (yMax - yMin) ELSE largeMagnification, maxMagnification]]; dData.xOffset _ bb.x/dData.currentMagnification - xMin; dData.yOffset _ bb.y/(-dData.currentMagnification) - yMax; ModifyContext[magnified, dData, ctx]; } ELSE { dData.currentMagnification _ 1; dData.xOffset _ 0; dData.yOffset _ 0; ModifyContext[normal, dData, ctx]; }; SilUserInput.MagnifyGrid[data.uiData, dData.xOffset, dData.yOffset, dData.currentMagnification]; [xMin, yMin, xMax, yMax] _ BoundingBoxOfContext [ctx]; MergeRebuild[dData, data.model, xMin, yMin, xMax, yMax]; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Mag, intArg1: dData.currentMagnification] }; SilRebuild: PUBLIC PROC [data: SilData, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; sSel: SilSelection _ SilFile.GetSelection[]; cxMin, cyMin, cxMax, cyMax: INTEGER; [xMin: cxMin, yMin: cyMin, xMax: cxMax, yMax: cyMax] _ BoundingBoxOfContext[ctx]; SELECT dData.rebuildStage FROM Background => { --Do background main picture objects WHILE dData.currentBkgndObj # NIL AND NOT SilUserInput.InputAvailable[uiData] DO IF IBBoxFilter[cxMin, cyMin, cxMax, cyMax, dData.currentBkgndObj.first] AND IBBoxFilter[dData.rebuildMinX, dData.rebuildMinY, dData.rebuildMaxX, dData.rebuildMaxY, dData.currentBkgndObj.first] AND NOT (model=sSel.model AND dData.currentBkgndObj.first.selectObj#NIL) THEN SilDisplayUtils.PaintObject[model, dData.currentBkgndObj.first, show, ctx]; dData.currentBkgndObj _ dData.currentBkgndObj.rest; ENDLOOP; IF dData.currentBkgndObj = NIL THEN { --Reached end, now do next IF sSel.model = model THEN { dData.rebuildStage _ SelectedBackground; dData.currentBkgndObj _ sSel.objects; } ELSE { dData.currentFgndObj _ GetObjectList[model, fgnd]; dData.rebuildStage _ Foreground; }; SilRebuild[data, ctx]; }; }; SelectedBackground => { --Do selected background objects WHILE dData.currentBkgndObj # NIL AND NOT SilUserInput.InputAvailable[uiData] DO IF dData.currentBkgndObj.first.font IN InternalBackgroundBoxFonts AND IBBoxFilter[cxMin, cyMin, cxMax, cyMax, dData.currentBkgndObj.first] AND IBBoxFilter[dData.rebuildMinX, dData.rebuildMinY, dData.rebuildMaxX, dData.rebuildMaxY, dData.currentBkgndObj.first] THEN SilDisplayUtils.PaintObject[model, dData.currentBkgndObj.first, select, ctx]; --selected object dData.currentBkgndObj _ dData.currentBkgndObj.first.selectObj; ENDLOOP; IF dData.currentBkgndObj = NIL THEN { --Reached the end of selected objects IF dData.selectedOnly THEN { IF sSel.model = model THEN dData.currentFgndObj _ sSel.objects ELSE dData.currentFgndObj _ NIL; dData.rebuildStage _ SelectedForeground; } ELSE { dData.currentFgndObj _ GetObjectList[model, fgnd]; dData.rebuildStage _ Foreground; }; SilRebuild[data, ctx]; }; }; SelectedForeground => { --Do selected objects WHILE dData.currentFgndObj # NIL AND NOT SilUserInput.InputAvailable[uiData] DO IF NOT dData.currentFgndObj.first.font IN InternalBackgroundBoxFonts AND IBBoxFilter[cxMin, cyMin, cxMax, cyMax, dData.currentFgndObj.first] AND IBBoxFilter[dData.rebuildMinX, dData.rebuildMinY, dData.rebuildMaxX, dData.rebuildMaxY, dData.currentFgndObj.first] THEN SilDisplayUtils.PaintObject[model, dData.currentFgndObj.first, select, ctx]; --selected object dData.currentFgndObj _ dData.currentFgndObj.first.selectObj; ENDLOOP; IF dData.currentFgndObj = NIL THEN { --Reached the end of selected objects, now done IF dData.ticsOn THEN DisplayTicBox[show, dData, model, ctx, dData.rebuildMinX, dData.rebuildMinY, dData.rebuildMaxX, dData.rebuildMaxY]; IF dData.framesOn THEN { xMin, yMin, xMax, yMax: INTEGER; [xMin: xMin, yMin: yMin, xMax: xMax, yMax: yMax] _ BoundingBoxOfContext[ctx]; DisplayFrameBoxes[show, dData, model, ctx, xMin, yMin, xMax, yMax]; }; dData.inRebuild _ FALSE; dData.needRebuild _ FALSE; }; }; Foreground => { --Do main picture objects WHILE dData.currentFgndObj # NIL AND NOT SilUserInput.InputAvailable[uiData] DO IF IBBoxFilter[cxMin, cyMin, cxMax, cyMax, dData.currentFgndObj.first] AND IBBoxFilter[dData.rebuildMinX, dData.rebuildMinY, dData.rebuildMaxX, dData.rebuildMaxY, dData.currentFgndObj.first] AND NOT (model=sSel.model AND dData.currentFgndObj.first.selectObj#NIL) THEN SilDisplayUtils.PaintObject[model, dData.currentFgndObj.first, show, ctx]; dData.currentFgndObj _ dData.currentFgndObj.rest; ENDLOOP; IF dData.currentFgndObj = NIL THEN { --Reached the end of the objects, now do next dData.rebuildStage _ SelectedForeground; IF sSel.model = model THEN dData.currentFgndObj _ sSel.objects ELSE dData.currentFgndObj _ NIL; SilRebuild[data, ctx]; }; }; ENDCASE => NULL; }; MergeRebuild: PUBLIC PROC [dData: SilDisplayData, model: SilModel, xMin, yMin, xMax, yMax: INTEGER, selectedOnly: BOOL _ FALSE] = { IF dData.inRebuild THEN { xMin _ MIN[xMin, dData.rebuildMinX]; yMin _ MIN[yMin, dData.rebuildMinY]; xMax _ MAX[xMax, dData.rebuildMaxX]; yMax _ MAX[yMax, dData.rebuildMaxY]; selectedOnly _ (dData.rebuildStage = SelectedBackground OR dData.rebuildStage = SelectedForeground) AND selectedOnly; }; dData.needRebuild _ TRUE; dData.rebuildMinX _ xMin; dData.rebuildMinY _ yMin; dData.rebuildMaxX _ xMax; dData.rebuildMaxY _ yMax; dData.inRebuild _ TRUE; dData.selectedOnly _ selectedOnly; dData.rebuildStage _ IF selectedOnly THEN SelectedBackground ELSE Background; IF NOT selectedOnly THEN { dData.currentFgndObj _ GetObjectList[model, fgnd]; dData.currentBkgndObj _ GetObjectList[model, bkgnd]; } ELSE { dData.currentFgndObj _ GetSelection[].objects; dData.currentBkgndObj _ GetSelection[].objects; }; }; ExpandMacro: PUBLIC PROC [model: SilModel, char: CHAR, x, y: INTEGER, oneLevel: BOOL, ctx: Imager.Context] = { FOR s: SilObject _ GetObjectList[model, macro, InternalFileMacroFont, char], s.rest WHILE s # NIL DO macElem: SilObjectRec _ s.first; macElem.xMin _ macElem.xMin + x; macElem.yMin _ macElem.yMin + y; macElem.xMax _ macElem.xMax + x; macElem.yMax _ macElem.yMax + y; IF macElem.font IN SilFile.InternalFileMacroFonts AND NOT oneLevel THEN ExpandMacro[model, Rope.Fetch[macElem.value], macElem.xMin, macElem.yMin, oneLevel, ctx] ELSE { SilFile.DefineSelectWithObject[model, SilFile.AddObjectToMainPicture[model, macElem]]; SilDisplayUtils.PaintObject[model, macElem, select, ctx]; }; ENDLOOP; }; EraseArea: PUBLIC PROC [xMin, yMin, xMax, yMax: INTEGER, ctx: Imager.Context] = { Imager.SetColor[ctx, Imager.white]; Imager.MaskRectangleI[ctx, xMin, yMin, xMax - xMin, yMax - yMin]; }; MergeArea: PUBLIC PROC [dData: SilDisplayData, model: SilModel, xMin, yMin, xMax, yMax: INTEGER, ctx: Imager.Context] = { MergeRebuild[dData: dData, model: model, xMin: xMin, yMin: yMin, xMax: xMax, yMax: yMax, selectedOnly: FALSE]; }; BBoxFilter: PUBLIC PROC [xMin, yMin, xMax, yMax: INTEGER, sobr: SilObjectRec] RETURNS [BOOL] = { RETURN[ NOT (yMin > sobr.yMax OR xMin > sobr.xMax OR yMax < sobr.yMin OR xMax < sobr.xMin)]; }; IBBoxFilter: PROC [xMin, yMin, xMax, yMax: INTEGER, sobr: SilObjectRec] RETURNS [BOOL] = INLINE { RETURN[ NOT (yMin > sobr.yMax OR xMin > sobr.xMax OR yMax < sobr.yMin OR xMax < sobr.xMin)]; }; AttributeFromChar: PUBLIC PROC [char: CHAR] RETURNS [AR: AttributeRec] ={ hue: INTEGER _ Rope.Find[SilColor.colorOrder, Rope.FromChar[char], 0, FALSE]; SELECT TRUE FROM Ascii.Digit[char] => RETURN[ [referenced: font, font: char - '0] ]; hue # -1 => RETURN[ [referenced: color, color: hue] ]; char = 'b => RETURN[ [referenced: face, face: bold] ]; char = 'B => RETURN[ [referenced: face, face: nonBold] ]; char = 'i => RETURN[ [referenced: face, face: italic] ]; char = 'I => RETURN[ [referenced: face, face: nonItalic] ]; ENDCASE => RETURN[ [referenced: invalid] ]; }; AttributeFilter: PUBLIC PROC [AR: AttributeRec, sobr: SilObjectRec] RETURNS [passed: BOOL] = { SELECT AR.referenced FROM color => RETURN [sobr.color = AR.color]; font => RETURN [SilFile.InternalFontFromUserFont[AR.font, TRUE] = sobr.font OR SilFile.InternalFontFromUserFont[AR.font, FALSE] = sobr.font]; face => SELECT AR.face FROM italic => RETURN [sobr.italic]; nonItalic => RETURN [NOT sobr.italic]; bold => RETURN [SilFile.FontIsBold[sobr.font] ]; nonBold => RETURN [NOT SilFile.FontIsBold[sobr.font] ]; ENDCASE; ENDCASE; }; OffsetFilter: PUBLIC PROC [sobr: SilObjectRec, offsetDirection: Orientation, offset, xMin, yMin, xMax, yMax: INTEGER] RETURNS [passed: BOOL _ FALSE, bEnd: BoxEnd _ long] = { IF sobr.font NOT IN InternalBoxFonts THEN RETURN [passed: FALSE]; SELECT offsetDirection FROM vertical => { IF sobr.yMax - sobr.yMin <= sobr.xMax - sobr.xMin THEN RETURN [passed: FALSE]; IF sobr.xMin < xMin OR sobr.xMin > xMax THEN RETURN [passed: FALSE]; IF sobr.yMin >= yMin AND sobr.yMin <= yMax AND sobr.yMax > yMax THEN IF sobr.yMin + offset < sobr.yMax THEN RETURN [passed: TRUE, bEnd: short]; IF sobr.yMax >= yMin AND sobr.yMax <= yMax AND sobr.yMin < yMin THEN IF sobr.yMax + offset > sobr.yMin THEN RETURN [passed: TRUE, bEnd: long]; IF (sobr.yMax + sobr.yMin) / 2 >= yMin AND (sobr.yMax + sobr.yMin) / 2 <= yMax THEN RETURN [passed: FALSE]; RETURN [passed: FALSE]; }; horizontal => { IF sobr.xMax - sobr.xMin <= sobr.yMax - sobr.yMin THEN RETURN[passed: FALSE]; IF sobr.yMin < yMin OR sobr.yMin > yMax THEN RETURN [passed: FALSE]; IF sobr.xMin >= xMin AND sobr.xMin <= xMax AND sobr.xMax > xMax THEN IF sobr.xMin + offset < sobr.xMax THEN RETURN [passed: TRUE, bEnd: short]; IF sobr.xMax >= xMin AND sobr.xMax <= xMax AND sobr.xMin < xMin THEN IF sobr.xMax + offset > sobr.xMin THEN RETURN [passed: TRUE, bEnd: long]; IF (sobr.xMax + sobr.xMin) / 2 >= xMin AND (sobr.xMax + sobr.xMin) / 2 <= xMax THEN RETURN [passed: FALSE]; RETURN [passed: FALSE]; }; ENDCASE; }; StretchBox: PUBLIC PROC [sob: SilObject, offsetDirection: Orientation, bEnd: BoxEnd, offset: INTEGER] = { SELECT offsetDirection FROM vertical => SELECT bEnd FROM long => sob.first.yMax _ sob.first.yMax + offset; short => sob.first.yMin _ sob.first.yMin + offset; ENDCASE; horizontal => SELECT bEnd FROM long => sob.first.xMax _ sob.first.xMax + offset; short => sob.first.xMin _ sob.first.xMin + offset; ENDCASE; ENDCASE; }; FixBoxConnectivity: PUBLIC PROC [dData: SilDisplayData, sobrIn: SilObjectRec, boxDir: Orientation] RETURNS [sobr: SilObjectRec] = { sobr _ sobrIn; SELECT boxDir FROM vertical => { IF dData.lastBoxLeftToRight AND sobr.xMin = dData.lastBoxPointX AND sobr.yMax = dData.lastBoxPointY THEN sobr.yMax _ sobr.yMax + dData.currentBoxWidth; dData.lastBoxTopToBottom _ TRUE; dData.lastBoxPointX _ sobr.xMin; dData.lastBoxPointY _ sobr.yMax; }; horizontal => { IF dData.lastBoxTopToBottom AND sobr.xMax = dData.lastBoxPointX AND sobr.yMin = dData.lastBoxPointY THEN sobr.xMax _ sobr.xMax + dData.currentBoxWidth; dData.lastBoxLeftToRight _ TRUE; dData.lastBoxPointX _ sobr.xMax; dData.lastBoxPointY _ sobr.yMin; }; ENDCASE; }; BoundingBoxOfContext: PUBLIC PROC [ctx: Imager.Context] RETURNS [xMin, yMin, xMax, yMax: INTEGER] = { rect: Imager.Rectangle _ ImagerBackdoor.GetBounds[context: ctx]; --returns client coordinates xMin _ Real.RoundI[rect.x]; yMin _ Real.RoundI[rect.y]; xMax _ Real.RoundI[rect.x + rect.w]; yMax _ Real.RoundI[rect.y + rect.h]; }; DeselectAndPaintAll: PUBLIC ENTRY PROC [model: SilModel, ctx: Imager.Context] = { LocalPASAD[model, ctx]; SilFile.DeselectAll[]; }; PaintAllSelectedAsDeselected: PUBLIC ENTRY PROC [model: SilModel, ctx: Imager.Context] = { LocalPASAD[model: model, ctx: ctx]; }; LocalPASAD: PROC [model: SilModel, ctx: Imager.Context] = { bXmin, bYmin, bXmax, bYmax: INTEGER; sSel: SilSelection _ GetSelection[]; IF model # sSel.model THEN RETURN; [bXmin, bYmin, bXmax, bYmax] _ BoundingBoxOfContext [ctx]; FOR s: SilObject _ sSel.objects, s.first.selectObj WHILE s # sSel.lastObject DO IF IBBoxFilter[bXmin, bYmin, bXmax, bYmax, s.first] THEN SilDisplayUtils.PaintObject[model, s.first, show, ctx]; --UNselect all objects ENDLOOP; }; DisplayGrid: PUBLIC PROC [eraseOrShow: SilDisplayUtils.DisplayChoice, dData: SilDisplayData, model: SilModel, ctx: Imager.Context] = { bXmin, bYmin, bXmax, bYmax: INTEGER; [bXmin, bYmin, bXmax, bYmax] _ BoundingBoxOfContext [ctx]; DisplayTicBox[eraseOrShow, dData, model, ctx, bXmin, bYmin, bXmax, bYmax]; }; DisplayTicBox: PROC [eraseOrShow: SilDisplayUtils.DisplayChoice, dData: SilDisplayData, model: SilModel, ctx: Imager.Context, xMin, yMin, xMax, yMax: INTEGER] = { ticSpacing: INTEGER _ dData.ticSpacing; startX: INTEGER _ (xMin / ticSpacing) * ticSpacing; startY: INTEGER _ (yMin / ticSpacing) * ticSpacing; IF startX < xMin THEN startX _ startX + ticSpacing; IF startY < yMin THEN startY _ startY + ticSpacing; IF eraseOrShow = erase THEN Imager.SetColor[ctx, Imager.white] ELSE Imager.SetColor[ctx, Imager.black]; FOR j: INTEGER _ startY, j + ticSpacing WHILE j <= yMax DO FOR i: INTEGER _ startX, i + ticSpacing WHILE i <= xMax DO Imager.MaskRectangleI[ctx, i, j, 1, 1]; ENDLOOP; ENDLOOP; IF eraseOrShow = erase THEN MergeRebuild[dData, model, xMin, yMin, xMax, yMax]; }; DisplayFrames: PUBLIC PROC [eraseOrShow: SilDisplayUtils.DisplayChoice, dData: SilDisplayData, model: SilModel, ctx: Imager.Context] = { xMin, yMin, xMax, yMax: INTEGER; [xMin: xMin, yMin: yMin, xMax: xMax, yMax: yMax] _ BoundingBoxOfContext[ctx: ctx]; DisplayFrameBoxes[eraseOrShow, dData, model, ctx, xMin, yMin, xMax, yMax]; }; DisplayFrameBoxes: PROC [eraseOrShow: SilDisplayUtils.DisplayChoice, dData: SilDisplayData, model: SilModel, ctx: Imager.Context, xMin, yMin, xMax, yMax: REAL] = { Fix: PRIVATE PROC [r: REAL] RETURNS[INT] = { RETURN[Real.Fix[r]] }; Floor: PRIVATE PROC [a: REAL] RETURNS[c: REAL] = { c _ Fix[a ! Real.RealException => { c _ a; CONTINUE }]; IF c>a THEN RETURN[c-1] ELSE RETURN[c]; }; DrawFrame: PROC [xMin, yMin, xMax, yMax: INTEGER, mode: SilDisplayUtils.DisplayChoice, lineW: NAT] = { IF mode = erase THEN Imager.SetColor[ctx, Imager.white] ELSE Imager.SetColor[ctx, frameColor]; Imager.MaskRectangleI[ctx, xMin, yMin, xMax-xMin, lineW]; Imager.MaskRectangleI[ctx, xMin, yMin, lineW, yMax-yMin]; Imager.MaskRectangleI[ctx, xMax, yMin, lineW, yMax-yMin]; Imager.MaskRectangleI[ctx, xMin, yMax, xMax-xMin, lineW]; }; marginX, marginY: INTEGER _ margin; pageXSize: REAL _ 8.5; pageYSize: REAL _ 11.0; mXMinI, mYMinI, mXMaxI, mYMaxI: INTEGER _ 0; xMin4, yMin4, xMax4, yMax4: INTEGER _ 0; pageXPoints, pageYPoints: INTEGER; frameColor: Imager.Color _ Imager.MakeGray[f: 0.5]; pageXPoints _ Real.RoundI[pageXSize*pointsPerInch] - 2*marginX; --framed part pageYPoints _ Real.RoundI[pageYSize*pointsPerInch]- 2*marginY; --framed part mXMinI _ Real.RoundI[Floor[xMin/pageXPoints] * pageXPoints]; --round to nearest page boundary mYMinI _ Real.RoundI[Floor[yMin/pageYPoints] * pageYPoints]; mXMaxI _ Real.RoundI[xMax]; mYMaxI _ Real.RoundI[yMax]; FOR x: INTEGER _ mXMinI, x + pageXPoints UNTIL x > mXMaxI DO FOR y: INTEGER _ mYMinI, y+pageYPoints UNTIL y > mYMaxI DO xMin4 _ (x+marginX)+(4-((x+marginX) MOD 4)); -- round up to nearest four pixels yMin4 _ (y+marginY)+(4-((y+marginY) MOD 4)); xMax4 _ (x+pageXPoints-marginX)-((x+pageXPoints-marginX) MOD 4); --round down yMax4 _ (y+pageYPoints-marginY)-((y+pageYPoints-marginY) MOD 4); DrawFrame[xMin: xMin4, yMin: yMin4, xMax: xMax4, yMax: yMax4, mode: eraseOrShow, lineW: 2]; ENDLOOP; ENDLOOP; IF eraseOrShow = erase THEN MergeRebuild[dData, model, mXMinI, mYMinI, mXMaxI, mYMaxI]; }; AbortRopeInput: PUBLIC PROC [data: SilData, markX, markY: INTEGER, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; SELECT dData.mode FROM InputingRope => IF dData.collectingObject.value # NIL THEN { xMin, yMin, xMax, yMax: INTEGER; IF Rope.Length[dData.collectingObject.value] > 0 THEN { SilDisplayUtils.PaintObject[model, dData.collectingObject, erase, ctx]; [xMin, yMin, xMax, yMax] _ BoundingBoxOfObject[data.model, dData.collectingObject]; MergeRebuild[dData, model, dData.collectingObject.xMin + xMin, dData.collectingObject.yMin + yMin, dData.collectingObject.xMin + xMax, dData.collectingObject.yMin + yMax]; }; dData.collectingText.length _ 0; }; InputingInputFileName, EditingExistingInputFileName, InputingOutputFileName, EditingExistingOutputFileName, WaitingForKillConfirmation, WaitingForMacroDefConfirmation, WaitingForMacroDeleteConfirmation => { MessageWindow.Append["", TRUE]; dData.collectingFileName.length _ 0; }; WaitingForKillConfirmation => { MessageWindow.Append["", TRUE]; }; ENDCASE; dData.mode _ WaitingToInputRope; SilUserInput.NotInputingRope[uiData]; }; BoundingBoxOfModel: PUBLIC PROC [dData: SilDisplayData, model: SilModel, mapArea: BOOLEAN _ TRUE] RETURNS [rect: Geom2D.Rect] = { box: Imager.Box; fobList: SilFile.SilObject _ SilFile.GetObjectList[model, fgnd]; bobList: SilFile.SilObject _ SilFile.GetObjectList[model, bkgnd]; IF fobList=NIL AND bobList=NIL THEN RETURN [[0.0, 0.0, 1.0, 1.0]]; --no objects in mode, return small BBox box.xmin _ box.ymin _ LAST[INTEGER]; box.xmax _ box.ymax _ FIRST[INTEGER]; FOR s: SilObject _ fobList, s.rest WHILE s#NIL DO box.xmin _ MIN[box.xmin, s.first.xMin]; box.ymin _ MIN[box.ymin, s.first.yMin]; box.xmax _ MAX[box.xmax, s.first.xMax]; box.ymax _ MAX[box.ymax, s.first.yMax]; ENDLOOP; FOR s: SilObject _ bobList, s.rest WHILE s#NIL DO box.xmin _ MIN[box.xmin, s.first.xMin]; box.ymin _ MIN[box.ymin, s.first.yMin]; box.xmax _ MAX[box.xmax, s.first.xMax]; box.ymax _ MAX[box.ymax, s.first.yMax]; ENDLOOP; rect.x _ box.xmin; rect.y _ box.ymin; rect.w _ (box.xmax-box.xmin); rect.h _ (box.ymax-box.ymin); IF mapArea THEN rect _ ImagerTransformation.TransformRectangle[ Geom2D.id.PostTranslate[[dData.xOffset, dData.yOffset]].PostScale2[[dData.currentMagnification, -dData.currentMagnification]], rect]; }; BoundingBoxOfObject: PUBLIC PROC [model: SilModel, sobr: SilObjectRec] RETURNS [xMin, yMin, xMax, yMax: INTEGER]= { SELECT sobr.font FROM IN InternalPresetFonts => { extents: ImagerFont.Extents _ ImagerFont.RopeBoundingBox[font: SilDisplayUtils.GetFont[sobr.font, sobr.italic], rope: sobr.value]; RETURN[0, 0, Real.RoundI[extents.leftExtent+extents.rightExtent], Real.RoundI[extents.ascent+extents.descent]] }; IN InternalMacroFonts => { mxMin, myMin, mxMax, myMax: INTEGER; [xMin: xMin, yMin: yMin, xMax: xMax, yMax: yMax] _ SilFile.GetMacroBoundingBox[model, sobr.font, Rope.Fetch[sobr.value, 0]]; FOR i: INT IN [1..Rope.Length[sobr.value]) DO [mxMin, myMin, mxMax, myMax] _ SilFile.GetMacroBoundingBox[model, sobr.font, Rope.Fetch[sobr.value, i]]; yMin _ MIN[yMin, myMin]; yMax _ MAX[yMax, myMax]; xMax _ xMax + mxMax - mxMin; ENDLOOP; }; IN InternalBoxFonts => { RETURN[sobr.xMin, sobr.yMin, sobr.xMax, sobr.yMax]; }; ENDCASE; }; GuessFileName: PUBLIC PROC [data: SilData, file: FileType] = { dData: SilDisplayData _ data.displayData; name: ROPE _ SilFile.GetActiveFileName[data.model]; IF Rope.Equal[name, ""] THEN name _ SilFile.GetLastActiveFileName[data.model]; SELECT file FROM input => { MessageWindow.Append["Input file: ", TRUE]; IF Rope.Equal[name, ""] THEN dData.mode _ InputingInputFileName ELSE dData.mode _ EditingExistingInputFileName; }; output => { IF dData.largeFormat THEN MessageWindow.Append["Output Large Format file: ", TRUE] ELSE MessageWindow.Append["Output file: ", TRUE]; IF Rope.Equal[name, ""] THEN dData.mode _ InputingOutputFileName ELSE dData.mode _ EditingExistingOutputFileName; }; ENDCASE; MessageWindow.Append[name, FALSE]; dData.collectingFileName _ Rope.ToRefText[name]; SilUserInput.InputingRope[data.uiData]; }; GuessHardFileName: PUBLIC PROC [data: SilData, c: CHAR] = { dData: SilDisplayData _ data.displayData; name: ROPE _ SilFile.GetActiveFileName[data.model]; dir: ROPE _ FileNames.Directory[name]; name _ FileNames.GetShortName[name]; name _ Rope.Substr[base: name, len: Rope.SkipTo[s: name, skip: "."]]; SELECT c FROM 'R, 'r => dData.pdDev _ raven300; 'H, 'h => dData.pdDev _ raven384; 'M, 'm => dData.pdDev _ plateMaker; 'U, 'u => dData.pdDev _ puffin; 'C, 'c => dData.pdDev _ colorVersatec; 'D, 'd => dData.pdDev _ nil; -- Dover 'P, 'p => dData.pdDev _ nil; -- Press ENDCASE => { MessageWindow.Append["Illegal Hardcopy Device", TRUE]; MessageWindow.Blink; RETURN; }; MessageWindow.Append["Hardcopy file: ", TRUE]; IF Rope.Equal[name, ""] THEN dData.mode _ InputingHardFileName ELSE { dData.mode _ EditingExistingHardFileName; name _ CheckHardFileExtension[data, Rope.Concat[dir, name]]; --restore directory part MessageWindow.Append[name, FALSE]; dData.collectingFileName _ Rope.ToRefText[name]; }; SilUserInput.InputingRope[data.uiData]; }; InputNamedFile: PUBLIC PROC [data: SilData, name: ROPE, ctx: Imager.Context] = { bXmin, bYmin, bXmax, bYmax: INTEGER; dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; name _ CheckFileExtension[name, input]; SilFile.MainFileToModel[model, name, dData.relativeInput ! SilKernel.SilError => { MessageWindow.Append[name, TRUE]; MessageWindow.Append[" not found.", FALSE]; GOTO Done;}]; [bXmin, bYmin, bXmax, bYmax] _ BoundingBoxOfContext [ctx]; MergeRebuild[data.displayData, model, bXmin, bYmin, bXmax, bYmax, FALSE]; EXITS Done => NULL; }; OutputNamedFile: PUBLIC PROC [data: SilData, name: ROPE, viewer: ViewerClasses.Viewer] = { wasClipped: BOOL _ FALSE; dData: SilDisplayData _ data.displayData; AltoScreenWidth: INTEGER = SilDisplayInternal.AltoScreenWidth; AltoScreenLength: INTEGER = SilDisplayInternal.AltoScreenLength; name _ CheckFileExtension[name, IF dData.largeFormat THEN largeOutput ELSE output]; [wasClipped] _ SilFile.ModelToFile[model: data.model, name: name, clipIt: dData.clipOutputFile, large: dData.largeFormat, xMin: 0, yMin: 0, xMax: AltoScreenWidth, yMax: AltoScreenLength ! SilKernel.SilError => { MessageWindow.Append["Not possible to store ", TRUE]; MessageWindow.Append[name, FALSE]; REJECT}]; --propogate signal to caller. Retain status as "edited". IF wasClipped THEN MessageWindow.Append["Objects outside of Alto screen boundaries not saved. ", TRUE]; dData.edited _ FALSE; }; KillConfirmedFile: PUBLIC PROC [data: SilData, ctx: Imager.Context, viewer: ViewerClasses.Viewer] = { bXmin, bYmin, bXmax, bYmax: INTEGER; dData: SilDisplayData _ data.displayData; SilFile.ClearModel[data.model]; viewer.name _ "SilNoName"; [bXmin, bYmin, bXmax, bYmax] _ BoundingBoxOfContext [ctx]; EraseArea[bXmin, bYmin, bXmax, bYmax, ctx]; MergeRebuild[dData, data.model, bXmin, bYmin, bXmax, bYmax]; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Selections, intArg1: SilFile.GetSelection[].numObjects]; dData.edited _ FALSE; viewer.newVersion _ viewer.newFile _ FALSE; --Abutter viewer.child.newVersion _ viewer.child.newFile _ FALSE; --ViewRec viewer.child.sibling.newVersion _ viewer.child.sibling.newFile _ FALSE; --BiScroller viewer.icon _ SilDisplay.GetIcon[dirtyIcon: FALSE]; ViewerOps.PaintViewer[viewer, caption]; }; HardcopyFile: PUBLIC PROC [data: SilData, name: ROPE] = { ENABLE FS.Error => { MessageWindow.Append["Error Attempting File: ", TRUE]; MessageWindow.Append[name, FALSE]; MessageWindow.Append[" ", FALSE]; MessageWindow.Append[error.explanation, FALSE]; GOTO ErrorOut; }; Fix: PRIVATE PROC [r: REAL] RETURNS[INT] = { RETURN[Real.Fix[r]] }; Floor: PRIVATE PROC [a: REAL] RETURNS[c: REAL] = { c _ Fix[a ! Real.RealException => { c _ a; CONTINUE }]; IF c>a THEN RETURN[c-1] ELSE RETURN[c] }; ipRef: ImagerInterpress.Ref _ NIL; spruceCtx: Imager.Context _ NIL; pageXSize, pageYSize: REAL _ 0.0; marginX, marginY: INTEGER _ margin; dData: SilDisplayData _ data.displayData; name _ CheckHardFileExtension[data, name]; MessageWindow.Append["Creating Hardcopy file: ", TRUE]; MessageWindow.Append[name, FALSE]; SELECT dData.pdDev FROM nil => { -- nil means make a Spruce style Press file spruceCtx _ ImagerPress.SimpleCreate[fileName: name, printerType: spruce]; pageXSize _ 8.5; pageYSize _ 11.0;}; IN [raven300..colorVersatec] => { ipRef _ ImagerInterpress.Create[fileName: name]; SELECT dData.pdDev FROM raven300 => {pageXSize _ 8.5; pageYSize _ 11.0;}; raven384 => {pageXSize _ 8.5; pageYSize _ 11.0;}; plateMaker => {pageXSize _ 11.0; pageYSize _ 8.5;}; puffin => {pageXSize _ 11.0; pageYSize _ 8.5;}; colorVersatec => {pageXSize _ 40.0; pageYSize _ 100.0;}; ENDCASE => {MessageWindow.Append["UnImplemented PD Device", TRUE]; RETURN;}; }; ENDCASE => {MessageWindow.Append["UnImplemented Output Device", TRUE]; RETURN;}; { DoSpruceProc: PROC [] = { --this PROC will be called by the ImagerPress package to make a Spruce style Press file page ImagerPress.NewPage[context: spruceCtx]; --resets context to initial state (meters) DoPageProc[context: spruceCtx]; }; DoPageProc: PROC [context: Imager.Context] = { --this PROC will be called to image a page obCount: INT _ 0; maxObCount: INT _ 100; Imager.Scale2T[context, [metersPerPoint, -metersPerPoint]]; Imager.TranslateT[context,[ -boxXMin, -boxYMin-pageYPoints-marginY]]; --translate origin to current page. Includes margins. Imager.SetPriorityImportant[context, TRUE]; FOR o: SilObject _ GetObjectList[model: data.model, mode: bkgnd], o.rest WHILE o # NIL DO IF IBBoxFilter[xMin: boxXMin, yMin: boxYMin, xMax: boxXMax, yMax: boxYMax, sobr: o.first] THEN SilDisplayUtils.PaintObject[model: data.model, sobr: o.first, dMode: show, ctx: context, oneLevel: FALSE, foregroundOnly: FALSE, print: TRUE]; ENDLOOP; FOR o: SilObject _ GetObjectList[model: data.model, mode: fgnd], o.rest WHILE o # NIL DO IF IBBoxFilter[xMin: boxXMin, yMin: boxYMin, xMax: boxXMax, yMax: boxYMax, sobr: o.first] THEN { SilDisplayUtils.PaintObject[model: data.model, sobr: o.first, dMode: show, ctx: context, oneLevel: FALSE, foregroundOnly: FALSE, print: TRUE]; IF (obCount _ obCount+1) = maxObCount THEN { MessageWindow.Append[".", FALSE]; obCount _ 0; }; }; ENDLOOP; }; modelXMin, modelYMin, modelXMax, modelYMax: REAL _ 0.0; modelXMinI, modelYMinI, modelXMaxI, modelYMaxI: INTEGER _ 0; boxXMin, boxYMin, boxXMax, boxYMax: INTEGER _ 0; pageXPoints, pageYPoints: INTEGER _ 0; pageXPoints _ Real.RoundI[pageXSize*pointsPerInch] - 2*marginX; pageYPoints _ Real.RoundI[pageYSize*pointsPerInch] - 2*marginY; [[x: modelXMin, y: modelYMin, w: modelXMax, h: modelYMax]] _ BoundingBoxOfModel[dData: dData, model: data.model, mapArea: FALSE]; modelXMax _ modelXMax+modelXMin; --change w to xmax modelYMax _ modelYMax+modelYMin; --change h to ymax modelXMinI _ Real.RoundI[Floor[modelXMin/pageXPoints] * pageXPoints]; --round to nearest page boundary modelYMinI _ Real.RoundI[Floor[modelYMin/pageYPoints] * pageYPoints]; modelXMaxI _ Real.RoundI[modelXMax]; modelYMaxI _ Real.RoundI[modelYMax]; FOR x: INTEGER _ modelXMinI, x + pageXPoints UNTIL x > modelXMaxI DO boxXMin _ x-marginX; boxXMax _ x + pageXPoints + marginX - 1; FOR y: INTEGER _ modelYMinI, y+pageYPoints UNTIL y > modelYMaxI DO boxYMin _ y-marginY; boxYMax _ y + pageYPoints + marginY - 1; IF ipRef=NIL THEN ImagerPress.DoWithWarnings[context: spruceCtx, action: DoSpruceProc ! ImagerPress.Warning => { MessageWindow.Append["ImagerPress Warning: ", TRUE]; MessageWindow.Append[explanation, FALSE]; RESUME;};] ELSE ImagerInterpress.DoPage[self: ipRef, action: DoPageProc]; MessageWindow.Append["!", FALSE]; ENDLOOP ENDLOOP; }; IF ipRef=NIL THEN ImagerPress.Close[spruceCtx] ELSE ImagerInterpress.Close[ipRef]; MessageWindow.Append["Hardcopy file: ", TRUE]; MessageWindow.Append[name, FALSE]; MessageWindow.Append[" created.", FALSE]; EXITS ErrorOut => NULL; --FS.Error detected }; DefineConfirmedMacro: PUBLIC PROC [data: SilData, name: CHAR, ctx: Imager.Context] = { MacroDefGrid: INTEGER = 4; macroAlreadyInUse: BOOL _ FALSE; dData: SilDisplayData _ data.displayData; sSel: SilSelection _ GetSelection[]; xRef: INTEGER _ sSel.xMin; yRef: INTEGER _ sSel.yMin; xRef _ (xRef / MacroDefGrid) * MacroDefGrid; yRef _ (yRef / MacroDefGrid) * MacroDefGrid; FOR s: SilObject _ GetObjectList[data.model, fgnd], s.rest WHILE s # NIL DO IF s.first.font = InternalFileMacroFont THEN { FOR i: INT IN [0..Rope.Length[s.first.value]) DO IF Rope.Fetch[s.first.value, i] = dData.macroDefName THEN { SilDisplayUtils.PaintObject[data.model, s.first, erase, ctx]; macroAlreadyInUse _ TRUE; EXIT; --need not look further }; ENDLOOP; }; ENDLOOP; SilFile.DefineMacroFromSelection[data.model, name, xRef, yRef]; IF macroAlreadyInUse THEN { bXmin, bYmin, bXmax, bYmax: INTEGER; [bXmin, bYmin, bXmax, bYmax] _ BoundingBoxOfContext [ctx]; MergeRebuild[dData, data.model, bXmin, bYmin, bXmax, bYmax]; }; }; ClearConfirmedMacroDefs: PUBLIC PROC [data: SilData, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; bXmin, bYmin, bXmax, bYmax: INTEGER; [bXmin, bYmin, bXmax, bYmax] _ BoundingBoxOfContext [ctx]; SilFile.ClearMacros[data.model]; -- also deletes macro containing objects EraseArea[bXmin, bYmin, bXmax, bYmax, ctx]; MergeRebuild[dData, data.model, bXmin, bYmin, bXmax, bYmax]; }; CheckFileExtension: PUBLIC PROC [name: ROPE, type: FileType] RETURNS[nameAndExt: ROPE] = { dir: ROPE _ FileNames.Directory[name]; sName: ROPE _ FileNames.GetShortName[name]; IF Rope.Find[s1: sName, s2: ".", case: FALSE] #-1 THEN RETURN[name]; --already has an extension SELECT type FROM -- no dot, so add extension output => RETURN[Rope.Concat[name, ".Sil"]]; largeOutput => RETURN[Rope.Concat[name, ".LSil"]]; input => { -- test a series of possible file name extensions until find one that exists list: LIST OF Rope.ROPE _ UserProfile.ListOfTokens[key: "Sil.FileExtensions", default: LIST[".LSil", ".Sil"]]; FOR l: LIST OF Rope.ROPE _ list, l.rest UNTIL l=NIL DO fname: ROPE _ Rope.Cat[name, ".", l.first]; [] _ FS.FileInfo[name: fname, wDir: dir ! FS.Error => LOOP]; RETURN[fname]; -- file with extension exists ENDLOOP; }; ENDCASE => NULL; RETURN[name]; -- file does not exist }; CheckHardFileExtension: PROC [data: SilData, name: ROPE] RETURNS[nameAndExt: ROPE] = { dData: SilDisplayData _ data.displayData; sName: ROPE _ FileNames.GetShortName[name]; IF Rope.Find[s1: sName, s2: ".", case: FALSE] #-1 THEN RETURN[name]; --already has an extension SELECT dData.pdDev FROM raven300 => RETURN[Rope.Concat[name, ".ip.raven"] ]; raven384 => RETURN[Rope.Concat[name, ".ip.hornet"] ]; plateMaker => RETURN[Rope.Concat[name, ".ip.plateMaker"] ]; puffin => RETURN[Rope.Concat[name, ".ip.puffin"] ]; colorVersatec => RETURN[Rope.Concat[name, ".ip.colorVersatec"] ]; nil => RETURN[Rope.Concat[name, ".press"] ]; ENDCASE; }; MarkFileAsEdited: PUBLIC PROC [data: SilData, ctx: Imager.Context, viewer: ViewerClasses.Viewer] = { dData: SilDisplayData _ data.displayData; lViewer: ViewerClasses.Viewer _ SilUserInput.GetBiScroller[data.uiData].QuaViewer[]; IF NOT dData.edited THEN { dData.edited _ TRUE; ViewerOps.SetNewVersion[lViewer]; -- needed for emergency SAVE to work ViewerOps.SetNewVersion[lViewer.parent]; -- needed for emergency SAVE to work lViewer.parent.icon _ SilDisplay.GetIcon[dirtyIcon: TRUE]; IF SilFile.MarkFileAsEdited[data.model] THEN { FOR i: BuildMarkIndex IN BuildMarkIndex DO EraseArea[buildMarks[i].xMin, buildMarks[i].yMin, buildMarks[i].xMax, buildMarks[i].yMax, ctx]; MergeRebuild[dData, data.model, buildMarks[i].xMin, buildMarks[i].yMin, buildMarks[i].xMax, buildMarks[i].yMax]; ENDLOOP; }; }; }; EditText: PUBLIC PROC [EditThis: REF TEXT, c: CHAR] RETURNS [Edited: REF TEXT, Finished: BOOL _ FALSE, Aborted: BOOL _ FALSE, BackedUp: BOOL _ FALSE]= { SELECT c FROM IN SilFile.PrintingChars, Ascii.SP => EditThis _ RefText.AppendChar[EditThis, c]; Ascii.BS, Ascii.ControlA => IF EditThis.length > 0 THEN { EditThis.length _ EditThis.length - 1; BackedUp _ TRUE; }; Ascii.ControlQ => { EditThis.length _ 0; BackedUp _ TRUE; }; Ascii.ControlW => { stop: INTEGER _ 0; lastStop: INTEGER _ 0; WHILE stop # EditThis.length AND stop # EditThis.length - 1 DO lastStop _ stop; stop _ RefText.SkipTo[EditThis, lastStop + 1, " ./!<["]; ENDLOOP; IF lastStop # EditThis.length AND lastStop # 0 THEN EditThis.length _ lastStop + 1 ELSE EditThis.length _ 0; BackedUp _ TRUE; }; Ascii.DEL => { Aborted _ TRUE; BackedUp _ TRUE; }; Ascii.ESC, Ascii.CR => Finished _ TRUE; ENDCASE => NULL; Edited _ EditThis; }; END. DSilDisplayUtilsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. See also SilDisplayUtilsImplA.mesa Tracy Larrabee: March 29, 1984 1:37:04 pm PST Last Edited by Ken Pier, May 7, 1986 10:34:48 am PDT A module implementing some display service routines. Modify the context to reflect the current state of the window as supplied in the display data. Enter Magnify mode. Modify the display of the drawing and the state of the display data to reflect the change. Send the boundin box of the region intended to be magnified. Rebuild the display inside the box given in dData. Set the fields in dData to reflect the fact that any current rebuilds should include the box defined by xMin, yMin, xMax, yMax. If SelectedOnly then only rebuild the selected objects. Expand the Macro Given. If oneLevel then don't expand any contained macros. If a library uses a macro, it must be a macro in its own font Erase an area of the screen. Used for making sure the screen starts from scratch. merge an area into the area needing rebuilding RETURN TRUE if some part of sobr appears inside the box. INLINE COPY OF BBoxFilter Return information about which attribute is referenced by the given char. char = 0-9 => font. char = D,R,O,Y,L,G,T,C,A,V,U,M,P,S,N,or W => color. char = b,B,i,or I => face. The AttributeRec contains a discription of certain attributes which sobr may or may not have Return TRUE if sobr has the attribute described in AR. Return TRUE if sobr represents a box with just one end inside the box defined by xMin, yMin, xMax, yMax and could be appropriately shortened or lengthened in the direction and by the amount given. Stretch the box given by sob by the amount given by offset in the direction given by offsetDirection at the box end given by bEnd. Figure out from the dData given if the current box is going to have to be extended by a box length in order to provide a nice connection in the lower right hand corner (you may have to draw a few boxes in Sil to feel comfortable with this statement). Return the bounding box of the context given, in client coordinates. Deselect all of the objects which are currently selected. If there are objects selected from this model, paint all of them as deselected, but dont change the data structure. Erase or display the grids as specified in dData. Erase or display the tics in the box given as specified in dData. Erase or display the page frames as specified in dData. Erase or display the page frames in the box given. Frames are constrained to lie on a four pixel boundary. THE FOLLOWING CODE STOLEN FROM HardcopyFile Call this if the user was inputting a rope, but changed his mind for some reason. This module originally made many calls to BoundingBoxOfObject which is an expensive routine. We will assume instead that all the objects in the model know their bounds. BoundingBoxOfObject is normally called for the boundaries of new character objects. Return the bounding box of the Object given. Do not assume that the bounding box given in sobr is correct. Guess as to the appropriate file name for input or output. Set appropriate data values and place file name in message window for user to edit. Guess as to the appropriate file name to produce for hardcopy output. Set appropriate data values and place file name in message window for user to edit. C will indicate what type of device to produce the Interpress file for: PD files are no longer produced directly R for Raven/300, H for Hornet/384, M for PlateMaker, U for Puffin, C for ColorVersatec, and D for Dover printer format. now strip the current file name back so a proper hardcopy extension will be added Input a named Sil file. It should be noted that a Sil file maybe read in more than once, and will result in two copies of each file object existing in the Sil environment (any number of different files can also be read in and co-exist). Output a named Sil file. Kill a Sil file. User has already confirmed this kill. viewer is the Abutter Produce a hardcopy file with the name given for the sil data given. With the advent of BiScrollers, Sil files can now be multipage. This code breaks drawings into separate pages for printing. adjust the imager context to view this page properly now, scan the model for all objects in this page Define a macro from the selected objects. User has already confirmed this definition. now find any old uses and get rid of them Clear all Macro Definitions. User has already confirmed this drastic act. This is going to look drastic (erasing the screen and then redrawing it), but it is a drastic step. Also, I think that erasing only the objects defined by macros would be not much better and a lot more work to program. If the fileName given has no extension and no dot on the end add an appropriate extension If the fileName given has no extension and no dot on the end add an appropriate extension. Mark the file as edited. This may involve the removal of "build marks." (Visual cues put in Sil files by post processing DA programs. This viewer is of a BiScroller; its parent is an Abutter Reflect the effect of this input char on the text given. If the input character implies that this rope has been aborted or finished, return the apropriate values. Return BackedUp TRUE if the some characters in the rope had to be removed. Don't do anything - spurious input probably the result of a confused user Κ%u˜codešœ™Kšœ Οmœ1™<—Kšœ"™"Kšœ-™-™4K™—K™4K™šΟk ˜ šœž˜ Kš œžœ žœžœ žœžœ˜<—šœ ž˜K˜%—šœ ž˜Kšœ!˜!—šœ ž˜Kšœ˜—šžœž˜Kšœ˜—šœž˜ Kšœ ˜ —šœž˜ Kšœ‡˜‡—šœž˜Kšœ˜—šœž˜Kšœ˜—šœ ž˜KšœE˜E—šœž˜Kšœ0˜0—šœž˜Kšœ˜—šœž˜ Kšœ˜—šœž˜ Kšœ˜—šœž˜ Kšœ4žœ˜U—šœ ž˜Kšœ˜—šœž˜K˜ —šœ ž˜Kšœ˜—K˜ K˜K˜ K˜K˜K˜ K˜ Kšœ˜—šΟnœžœž˜"Kšžœ žœθ˜‘Kšžœ˜"Kšœžœžœ ˜—K˜Kšžœžœžœ˜Kšœ žœ˜"Kšœžœžœ˜-Kšœžœžœ(˜FKšœ žœ˜"Kšœ žœ˜&K˜Kšœžœ!˜4Kšœžœ ˜2Kšœ žœ˜0Kšœžœ˜&Kšœ žœ˜*K˜KšœžœΟc5˜XKšœžœ  4˜PKšœžœ ˜4K˜šŸ œžœžœV˜pK™^K˜Kšžœžœžœžœ˜šžœžœ˜!Kšœ(  ˜HKšœ/˜/Kšœ7˜7K˜—Kšžœ( ˜EKšœ˜K™—šŸœžœžœ>žœ˜fK™­K™Kšœžœ˜!Kšœžœ'˜@Kšœ)˜)Kšœžœ˜$K˜Kšœ:˜:Kšœ#˜#KšœG˜GKšœžœ˜2šžœžœ˜KšœE˜EKšœ/ ˜?šœ)žœ˜-Kšžœžœžœ˜EKšžœžœžœ˜EKšœ˜—Kšœ7˜7Kšœ:˜:Kšœ%˜%K˜—šžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ"˜"K˜—Kšœ`˜`Kšœ6˜6Kšœ8˜8Kšœm˜mK˜K™—šŸ œžœžœ)˜@K™2K™Kšœ)˜)Kšœ˜K˜ Kšœ,˜,Kšœžœ˜$KšœQ˜QK˜šžœž˜šœ $˜4š žœžœžœžœ%ž˜PšžœFžœvžœžœžœ'žœžœ˜KšœK˜K—Kšœ3˜3Kšžœ˜—šžœžœžœ ˜@šžœžœ˜Kšœ(˜(Kšœ%˜%K˜—šžœ˜Kšœ2˜2Kšœ ˜ K˜—Kšœ˜K˜—K˜—šœ  ˜8š žœžœžœžœ%ž˜Pš žœ"žœžœFžœvžœ˜‰KšœM ˜_—Kšœ>˜>Kšžœ˜—šžœžœžœ %˜Kšžœžœ˜Kšžœžœ$˜>Kšžœžœ˜ Kšœ(˜(K˜—šžœ˜Kšœ2˜2Kšœ ˜ K˜—Kšœ˜K˜—K˜—šœ ˜-š žœžœžœžœ%ž˜Oš žœžœ!žœžœEžœužœ˜ŠKšœL ˜^—Kšœ<˜Kšžœžœ˜ Kšœ˜K˜—K˜—Kšžœžœ˜—Kšœ˜K˜—š Ÿ œžœžœAžœžœžœ˜ƒKšœ·™·šžœžœ˜Kšœžœ˜$Kšœžœ˜$Kšœžœ˜$Kšœžœ˜$Kšœ8žœ+žœ˜vKšœ˜—Kšœžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœžœ˜Kšœ"˜"Kšœžœžœžœ ˜Nšžœžœžœ˜Kšœ3˜3Kšœ5˜5K˜—šžœ˜Kšœ.˜.Kšœ0˜0Kšœ˜—K˜K˜—š Ÿ œžœžœžœžœ žœ˜nK™LšžœQžœžœž˜dK˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ K™=š žœžœ žœžœ ž˜GKšœX˜X—šžœ˜KšœV˜VKšœ9˜9K˜—Kšžœ˜—šœ˜K˜——šŸ œžœžœžœ˜QK™RK˜#KšœA˜AKšœ˜K˜—šŸ œžœžœAžœ˜yK™.K•StartOfExpansion¬[dData: SilDisplayUtilsImpl.SilDisplayData, model: SilKernel.SilModel, xMin: INTEGER, yMin: INTEGER, xMax: INTEGER, yMax: INTEGER, selectedOnly: BOOL _ FALSE]šœgžœ˜nKšœ˜K˜—š Ÿ œžœžœžœžœžœ˜`K™8K˜Kš žœžœžœžœžœ˜\K˜K˜—š Ÿ œžœžœžœžœžœ˜aKšžœžœžœ ™Kš žœžœžœžœžœ˜\K˜K˜—š Ÿœžœžœžœžœžœ˜IšœI™IK™K™3K™K˜—Kšœžœ:žœ˜Mšžœžœž˜Kšœžœ*˜EKšœ žœ%˜8Kšœžœ$˜8Kšœžœ'˜;Kšœžœ&˜:Kšœžœ)˜=Kšžœžœ˜,—˜K™——š Ÿœžœžœžœ$žœ žœ˜^Kšœ”™”šžœžœ ž˜Kšœžœžœ˜(Kš œžœ#žœžœžœ"žœžœ˜šœžœžœž˜Kšœ žœ˜Kšœ žœžœ˜&Kšœžœ"˜0Kšœ žœžœ!˜7Kšžœ˜—Kšžœ˜—˜K˜——šŸ œžœžœSžœžœ žœžœ˜­K™ΔKš žœ žœžœžœžœ žœ˜Ašžœž˜˜ Kšžœ1žœžœ žœ˜OKš žœžœžœžœ žœ˜Dšžœžœžœž˜DKšžœ žœžœ žœ˜J—šžœžœžœž˜DKšžœ žœžœ žœ˜I—Kš žœ&žœ&žœžœ žœ˜mKšžœ žœ˜K˜—˜Kšžœ0žœžœ žœ˜MKš žœžœžœžœ žœ˜Dšžœžœžœž˜DKšžœ žœžœ žœ˜J—šžœžœžœž˜DKšžœ žœžœ žœ˜I—Kš žœ&žœ&žœžœ žœ˜mKšžœ žœ˜K˜—Kšžœ˜—K˜K˜—šŸ œžœžœEžœ˜iKšœ‚™‚šžœž˜šœ žœž˜Kšœ1˜1Kšœ2˜2Kšžœ˜—šœžœž˜Kšœ1˜1Kšœ2˜2Kšžœ˜—Kšžœ˜—˜K˜——šŸœžœžœCžœ˜ƒK™ϋK™Kšœ˜šžœž˜šœ ˜ Kšžœžœ!žœ!žœ/˜—Kšœžœ˜ Kšœ ˜ Kšœ ˜ K˜—šœ˜Kšžœžœ!žœ!žœ/˜—Kšœžœ˜ Kšœ ˜ Kšœ ˜ K˜—Kšžœ˜—K˜K™—š Ÿœžœžœžœžœ˜eK™DKšœA ˜]Kšœ˜Kšœ˜Kšœ$˜$Kšœ$˜$K˜K˜—šŸœžœž œ+˜QKšœ9™9Kšœ˜Kšœ˜Kšœ˜K˜—šŸœžœžœžœ+˜ZKšœ#˜#Kšœ˜K˜—šŸ œžœ+˜;K™sK™Kšœžœ˜$Kšœ$˜$Kšžœžœžœ˜"Kšœ:˜:šžœ0žœž˜OKšžœ2žœ˜9šœ8 ˜NKšžœ˜——K˜K˜—šŸ œžœžœn˜†K™1K™Kšœžœ˜$Kšœ:˜:KšœJ˜JK˜K˜—šŸ œžœƒžœ˜’K™AK™Kšœ žœ˜'Kšœžœ$˜3Kšœžœ$˜3Kšžœžœ˜3Kšžœžœ˜3Kšžœžœ#˜>Kšžœ$˜(šžœžœžœ ž˜:šžœžœžœ ž˜:Kšœ'˜'Kšžœ˜—Kšžœ˜—šžœž˜Kšœ3˜3—K˜K˜—šŸ œžœžœn˜ˆK™7K™Kšœžœ˜ KšœR˜RKšœJ˜JK˜K˜—šŸœžœƒžœ˜£K™kK™KšŸœžœžœžœžœžœžœ˜Cš Ÿœžœžœžœžœžœ˜2Kšœ+žœ˜7Kš žœžœžœžœžœ˜'K˜—K˜šŸ œžœžœ.žœ˜fKšžœžœ#˜7Kšžœ"˜&Kšœ9˜9Kšœ9˜9Kšœ9˜9Kšœ9˜9Kšœ˜—K˜Kšœžœ ˜#Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜,Kšœžœ˜(Kšœžœ˜"Kšœ3˜3K˜K™+KšœA  ˜NKšœ@  ˜MKšœ=  ˜]Kšœ<˜K™K™Kšœ)˜)Kšœžœ)˜3Kšžœžœ2˜Nšžœž˜šœ ˜ Kšœ%žœ˜+šžœžœ˜Kšœ"˜"—šžœ˜Kšœ*˜*—K˜—šœ ˜ Kš žœžœ4žœžœ&žœ˜„šžœžœ˜Kšœ#˜#—šžœ˜Kšœ+˜+—K˜—Kšžœ˜—Kšœžœ˜"Kšœ0˜0Kšœ'˜'K˜K˜—šŸœžœžœžœ˜;šœŒ™ŒKšœw™w—K™Kšœ)˜)K™QKšœžœ)˜3Kšœžœ˜&Kšœ$˜$KšœE˜Ešžœž˜ Kšœ!˜!Kšœ!˜!Kšœ#˜#Kšœ˜Kšœ&˜&Kšœ%˜%Kšœ%˜%šžœ˜ Kšœ0žœ˜KKšžœ˜Kšœ˜——Kšœ(žœ˜.Kšžœžœ"˜>šžœ˜Kšœ)˜)Kšœ= ˜UKšœžœ˜"Kšœ0˜0K˜—Kšœ'˜'K˜K˜—šŸœžœžœžœ˜PKšœν™νK™Kšœžœ˜$Kšœ)˜)Kšœ˜K˜'šœR˜RKšœžœ˜!Kšœ$žœ˜+Kšžœ ˜ —Kšœ:˜:KšœBžœ˜Išž˜Kšœžœ˜ —K˜K˜—šŸœžœžœžœ#˜ZKšœ™K™Kšœ žœžœ˜Kšœ)˜)Kšœžœ&˜>Kšœžœ'˜@K˜Kšœ žœžœ žœ ˜S–[]šœΣ˜ΣKšœ/žœ˜5Kšœžœ˜"Kšžœ 8˜B—šžœ žœ˜KšœNžœ˜T—Kšœžœ˜K˜K˜—šŸœžœžœF˜eKšœF ™MK™Kšœžœ˜$Kšœ)˜)Kšœ˜Kšœ˜Kšœ:˜:Kšœ+˜+Kšœ<˜˜>šžœžœžœ_˜pKšœ4˜4Kšœ)˜)Kšžœ˜ —Kšžœ:˜>Kšœžœ˜!Kšž˜—Kšžœ˜—K˜—K˜Kšžœžœžœžœ˜RKšœ(žœ˜.Kšœžœ˜"Kšœ"žœ˜)šž˜Kšœ žœ ˜&—K˜K˜—šŸœžœžœžœ˜VKšœV™VK™Kšœžœ˜Kšœžœžœ˜ Kšœ)˜)Kšœ$˜$Kšœžœ ˜Kšœžœ ˜Kšœ,˜,Kšœ,˜,K™)šžœ8žœžœž˜Kšžœ'žœ˜/šžœžœžœ!ž˜0Kšžœ3žœ˜;Kšœ=˜=Kšœžœ˜Kšžœ ˜K˜Kšžœ˜—K˜—Kšžœ˜—Kšœ?˜?šžœžœ˜Kšœžœ˜$Kšœ:˜:Kšœ<˜[s1: ROPE, s2: ROPE, pos1: INT _ 0, case: BOOL _ TRUE]š žœ%žœžœžœ ˜_šžœžœ ˜,Kšœ žœ˜,Kšœžœ˜2šœ  L˜WKš œžœžœžœ@žœ˜nš žœžœžœžœžœžœž˜6Kšœžœ ˜+Kšœžœ#žœ žœ˜[s1: ROPE, s2: ROPE, pos1: INT _ 0, case: BOOL _ TRUE]š žœ%žœžœžœ ˜_šžœ ž˜Kšœ žœ"˜4Kšœ žœ#˜5Kšœžœ'˜;Kšœ žœ#˜3Kšœžœ*˜AKšœžœ˜,Kšžœ˜—K˜K˜—šŸœžœžœF˜dK™‡K™Kšœ)˜)KšœT˜TK™8šžœžœžœ˜Kšœžœ˜Kšœ" $˜FKšœ) $˜MKšœ4žœ˜:šžœ&žœ˜.šžœžœž˜*Kšœ_˜_Kšœp˜pKšžœ˜—K˜—K˜—K˜K˜—šŸœžœžœ žœžœžœžœ žœžœ žœžœ žœžœ žœžœ˜˜Kšœν™νK™šžœž˜ šžœžœ˜&Kšœ+˜+—šœžœžœžœ˜9Kšœ&˜&Kšœ žœ˜K˜—šœ˜Kšœ˜Kšœ žœ˜K˜—šœ˜Kšœžœ˜Kšœ žœ˜šžœžœž˜>Kšœ˜Kšœ8˜8Kšžœ˜—šžœžœžœ˜4Kšœ˜—šžœ˜Kšœ˜—Kšœ žœ˜Kšœ˜—šœžœ˜Kšœ žœ˜Kšœ žœ˜K˜—šœžœžœ˜Kšœ žœ˜KšœJ™J—Kšžœžœ˜—K˜K˜K˜—Kšžœ˜—…—ŠRΕ