DIRECTORY Ascii USING [BS], BiScrollers USING [Align, BiScroller, QuaViewer, Scale, ViewportBox], Geom2D USING [id, Rect, Transform, Vec], Imager USING [Context, MaskRectangleI, SetColor, VEC, white], ImagerTransformation USING [PostScale, PostScale2, PostTranslate, Transform, TransformRectangle], MessageWindow USING [Append, Blink], Process USING [Detach], Real USING [RoundI], RefText USING [AppendChar, New], Rope USING [Fetch, FromChar, FromRefText, ToRefText, Cat, Equal], ViewerClasses USING [Viewer], ViewerOps USING [PaintViewer, SaveViewer, UserToScreenCoords], SilDisplay, SilDisplayCursors, SilDisplayInternal, SilDisplayPrivate, SilDisplayUtils, SilFile, SilKernel, SilUserInput ; SilDisplayImpl: CEDAR MONITOR IMPORTS BiScrollers, Geom2D, Imager, ImagerTransformation, MessageWindow, Process, Real, RefText, Rope, SilDisplay, SilDisplayCursors, SilDisplayUtils, SilFile, SilKernel, SilUserInput, ViewerOps EXPORTS SilKernel, SilDisplayPrivate = BEGIN OPEN SilFile; SilData: TYPE = SilKernel.SilData; SilModel: TYPE = SilFile.SilModel; SilUIData: TYPE = SilKernel.SilUIData; SilDisplayData: TYPE = REF SilDisplayDataRec; SilDisplayDataRec: PUBLIC TYPE = SilDisplayInternal.SilDisplayDataRec; UInputRec: TYPE = SilUserInput.UInputRec; SilSelection: TYPE = SilFile.SilSelection; RebuildAreaRec: TYPE = RECORD[ xMin, yMin: INTEGER _ LAST[INTEGER], xMax, yMax: INTEGER _ FIRST[INTEGER] ]; UpdateRebuildArea: PROC [s: SilObjectRec, a: RebuildAreaRec] RETURNS [r: RebuildAreaRec] = { RETURN[[MIN[a.xMin, s.xMin], MIN[a.yMin, s.yMin], MAX[a.xMax, s.xMax], MAX[a.yMax, s.yMax]]]; }; MergeRebuildArea: PROC [data: SilDisplayData, model: SilModel, a: RebuildAreaRec] = { IF a.xMin#LAST[INTEGER] THEN SilDisplayUtils.MergeRebuild[data, model, a.xMin, a.yMin, a.xMax, a.yMax]; }; InputFile: PUBLIC PROC [args: UInputRec.InputFile, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; SilDisplayCursors.DisableRopeInput[data, ctx]; dData.relativeInput _ args.mode=relative; SilDisplayUtils.GuessFileName[data, input]; }; StoreFile: PUBLIC PROC [args: UInputRec.StoreFile, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; SilDisplayCursors.DisableRopeInput[data, ctx]; dData.clipOutputFile _ args.clip; dData.largeFormat _ args.large; SilDisplayUtils.GuessFileName[data, output]; }; KillPicture: PUBLIC PROC [args: UInputRec.KillPicture, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; lViewer: ViewerClasses.Viewer _ SilUserInput.GetBiScroller[data.uiData].QuaViewer[].parent; SilDisplayCursors.DisableRopeInput[data, ctx]; IF NOT dData.edited THEN SilDisplayUtils.KillConfirmedFile[data, ctx, lViewer] ELSE { dData.mode _ WaitingForKillConfirmation; SilUserInput.InputingRope[data.uiData]; MessageWindow.Append["File has been edited, ", TRUE]; MessageWindow.Append["confirm with CR, ESC or any click, ", FALSE]; MessageWindow.Append["abort with DEL.", FALSE]; MessageWindow.Blink[]; }; }; SwapFonts: PUBLIC PROC [args: UInputRec.SwapFonts, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { SilDisplayUtils.SwapFonts[data: data, ctx: ctx]; --toggles between normal display and "hardcopy" mode }; HardCopy: PUBLIC PROC [args: UInputRec.HardCopy, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { SilDisplayCursors.DisableRopeInput[data, ctx]; SilDisplayUtils.GuessHardFileName[data, args.char]; }; TrackMouse: PUBLIC PROC [args: UInputRec.TrackMouse, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Pos, intArg1: args.x, intArg2: args.y]; }; SetCaret: PUBLIC PROC [args: UInputRec.SetCaret, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; SilDisplayCursors.DisableRopeInput[data, ctx]; SELECT args.caret FROM mark => { SilDisplayCursors.AquireAndDisableTheMark[data, ctx]; SELECT args.mode FROM absolute => { SilDisplayCursors.SetMarkX[args.x]; SilDisplayCursors.SetMarkY[args.y]; }; relative => SilDisplayCursors.SetMarkY[SilDisplayCursors.GetMarkY[] + dData.yInc]; ENDCASE; }; origin => { SilDisplayCursors.AquireAndDisableTheOrigin[data, ctx]; SELECT args.mode FROM absolute => { SilDisplayCursors.SetOriginX[args.x]; SilDisplayCursors.SetOriginY[args.y]; }; relative => SilDisplayCursors.SetOriginY[SilDisplayCursors.GetOriginY[] + dData.yInc]; ENDCASE; }; ENDCASE; SilUserInput.SetCaretChange[uiData]; }; SetCursor: PUBLIC PROC [args: UInputRec.SetCursor, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { sx, sy: INTEGER; viewerPos: Geom2D.Vec; selection: SilFile.SilSelection; dData: SilDisplayData _ data.displayData; bs: BiScrollers.BiScroller _ SilUserInput.GetBiScroller[data.uiData]; IF (selection _ SilFile.CopySelection[]).numObjects = 0 THEN RETURN; --no selection IF NOT (SilDisplayCursors.MarkAndSelectionInSameWindow[] AND SilDisplayCursors.OriginAndSelectionInSameWindow[]) THEN { MessageWindow.Append["Mark, Origin, and Selection must be in same Window", TRUE]; MessageWindow.Blink[]; RETURN; }; SilDisplayCursors.DisableRopeInput[data, ctx]; SilDisplayCursors.AquireAndDisableTheOrigin[data, ctx]; --get origin out of the bitmap SilDisplayCursors.AquireAndDisableTheMark[data, ctx]; --get mark out of the bitmap SilDisplayUtils.PaintAllSelectedAsDeselected[model: data.model, ctx: ctx]; --rebuild bitmap where origin and selection were viewerPos _ bs.style.GetTransforms[bs].clientToViewer.Transform[[ x: (SilDisplayCursors.GetOriginX[] + dData.xOffset) * dData.currentMagnification, y: -(SilDisplayCursors.GetOriginY[] + dData.yOffset) * dData.currentMagnification]]; [sx, sy] _ ViewerOps.UserToScreenCoords[viewer, Real.RoundI[viewerPos.x], Real.RoundI[viewerPos.y]]; SELECT args.caret FROM origin => SilDisplayCursors.BitmapToCursor[x: sx, y: sy, viewer: viewer]; mark => NULL; --not implemented ENDCASE; SilDisplayUtils.MergeRebuild[dData: data.displayData, model: data.model, xMin: selection.xMin, yMin: selection.yMin, xMax: selection.xMax, yMax: selection.yMax, selectedOnly: TRUE]; SilDisplayUtils.SilRebuild[data: data, ctx: ctx]; SilDisplayCursors.SilCursorsBlink[]; --turn origin back on }; SelectWithPos: PUBLIC ENTRY PROC [args: UInputRec.SelectWithPos, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; markX: INTEGER _ SilDisplayCursors.GetMarkX[]; markY: INTEGER _ SilDisplayCursors.GetMarkY[]; originX: INTEGER _ SilDisplayCursors.GetOriginX[]; originY: INTEGER _ SilDisplayCursors.GetOriginY[]; SilDisplayCursors.DisableRopeInput[data, ctx]; SilDisplayCursors.CheckSelectionWindow[data]; SELECT args.mode FROM relative => { SilDisplayCursors.AquireAndDisableTheOrigin[data, ctx]; SilDisplayUtils.DeselectAndPaintAll[model, ctx]; [originX, originY] _ SilFile.DefineSelectWithBox[model, markX, markY, args.x, args.y]; SilDisplayUtils.MergeRebuild[dData, model, MIN[markX, args.x], MIN[markY, args.y], MAX[markX, args.x], MAX[markY, args.y], TRUE]; SilUserInput.SetCaretChange[uiData]; }; change, add => { sob: SilObject _ ObjectAtPos[model, args.x, args.y]; SilDisplayCursors.AquireAndDisableTheOrigin[data, ctx]; IF args.mode = change THEN SilDisplayUtils.DeselectAndPaintAll[model, ctx]; SilFile.DefineSelectWithObject[model, sob]; IF sob # NIL THEN { --Move origin to upper left of selected object SilDisplayUtils.MergeRebuild[dData, model, sob.first.xMin, sob.first.yMin, sob.first.xMax, sob.first.yMax, TRUE]; originX _ sob.first.xMin; originY _ sob.first.yMin; } ELSE { --Move origin to place unsuccessfully selected originX _ args.x; originY _ args.y; }; }; remove => { sob: SilObject _ ObjectAtPos[model, args.x, args.y]; IF sob # NIL THEN { SilFile.Deselect[model, sob]; SilDisplayUtils.MergeRebuild[dData, model, sob.first.xMin, sob.first.yMin, sob.first.xMax, sob.first.yMax, FALSE]; }; }; delete => { sob: SilObject _ ObjectAtPos[model, args.x, args.y]; IF sob # NIL THEN { SilDisplayUtils.PaintObject[model, sob.first, erase, ctx]; SilDisplayCursors.AquireAndDisableTheMark[data, ctx]; markX _ sob.first.xMin; markY _ sob.first.yMin; SilFile.DeleteAndCacheObject[model, sob]; SilDisplayUtils.MergeRebuild[dData, model, sob.first.xMin, sob.first.yMin, sob.first.xMax, sob.first.yMax]; SilDisplayUtils.MarkFileAsEdited[data, ctx, viewer]; }; }; ENDCASE; SilDisplayCursors.SetOriginX[originX]; SilDisplayCursors.SetOriginY[originY]; SilDisplayCursors.SetMarkX[markX]; SilDisplayCursors.SetMarkY[markY]; SilUserInput.SetCaretChange[uiData]; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Selections, intArg1: SilFile.GetSelection[].numObjects]; }; SelectForAttrib: PUBLIC ENTRY PROC [args: UInputRec.SelectForAttrib, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { rebuildArea: RebuildAreaRec _ []; dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; AR: SilDisplayUtils.AttributeRec _ SilDisplayUtils.AttributeFromChar[args.char]; IF AR.referenced = invalid THEN { MessageWindow.Append["Illegal attribute given.", TRUE]; MessageWindow.Blink; RETURN; } ELSE MessageWindow.Append[Rope.FromChar[args.char], FALSE]; SilDisplayCursors.DisableRopeInput[data, ctx]; SilDisplayCursors.CheckSelectionWindow[data]; IF args.mode = change THEN { --Select the guys that pass inspection SilDisplayUtils.DeselectAndPaintAll[model, ctx]; FOR s: SilObject _ GetObjectList[model, fgnd], s.rest WHILE s # NIL DO IF SilDisplayUtils.AttributeFilter[AR, s.first] THEN { SilFile.DefineSelectWithObject[model, s]; rebuildArea _ UpdateRebuildArea[s.first, rebuildArea]; }; ENDLOOP; } ELSE { --Remove the guys that dont pass inspection s: SilObject _ SilFile.GetSelection[].objects; nextS: SilObject _ s; WHILE s # NIL DO nextS _ s.first.selectObj; IF NOT SilDisplayUtils.AttributeFilter[AR, s.first] THEN { SilFile.Deselect[model, s]; rebuildArea _ UpdateRebuildArea[s.first, rebuildArea]; }; s _ nextS; ENDLOOP; }; MergeRebuildArea[dData, model, rebuildArea]; -- rebuild area ONLY ONCE SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Selections, intArg1: SilFile.GetSelection[].numObjects]; }; CenterOnMark: PUBLIC PROC [args: UInputRec.CenterOnMark, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { ClientToSilXForm: PROC [] RETURNS [xform: Geom2D.Transform] = { xform _ Geom2D.id.PostScale2[[1.0, -1.0]].PostScale[IF dData.magnificationOn AND dData.currentMagnification#1 THEN 1.0/dData.currentMagnification ELSE 1.0].PostTranslate[[-dData.xOffset, -dData.yOffset]]; }; SilToClientCoords: PROC [silCoordX, silCoordY: REAL] RETURNS [clientCoordX, clientCoordY: REAL] = { point: Imager.VEC _ [silCoordX, silCoordY]; point.x _ point.x + dData.xOffset; point.y _ point.y + dData.yOffset; IF dData.magnificationOn AND dData.currentMagnification#1 THEN { point.x _ point.x * dData.currentMagnification; point.y _ point.y * dData.currentMagnification; }; RETURN[point.x, -point.y]; --note inversion of y coord }; bxMin, byMin, bxMax, byMax: INTEGER; -- for bounding box of context rMarkX, rMarkY: REAL; area: Geom2D.Rect; dData: SilDisplayData _ data.displayData; -- used by local procs above [rMarkX, rMarkY] _ SilToClientCoords[SilDisplayCursors.GetMarkX[], SilDisplayCursors.GetMarkY[]]; --BiScrollers wants Client coords [bxMin, byMin, bxMax, byMax] _ SilDisplayUtils.BoundingBoxOfContext[ctx]; Imager.SetColor[ctx, Imager.white]; --clear the viewer Imager.MaskRectangleI[ctx, bxMin, byMin, bxMax - bxMin, byMax - byMin]; BiScrollers.Align[bs: SilUserInput.GetBiScroller[data.uiData], client: [coord[x: rMarkX, y: rMarkY]], viewer: [fraction[fx: 0.5, fy: 0.5]], paint: FALSE]; --center the viewer on the Mark BiScrollers.Scale[bs: SilUserInput.GetBiScroller[data.uiData], op: [reset[]], paint: FALSE]; --and reset the Scale to 1:1. Note: paint_FALSE is CRITICAL !! area _ BiScrollers.ViewportBox[bs: SilUserInput.GetBiScroller[data.uiData]]; --find area needing rebuilding area _ ClientToSilXForm[].TransformRectangle[area]; --and convert to Sil coordinates SilDisplayUtils.MergeRebuild[dData, data.model, Real.RoundI[area.x], Real.RoundI[area.y], Real.RoundI[area.x+area.w], Real.RoundI[area.y+area.h], FALSE]; }; OperateOnSelected: PUBLIC ENTRY PROC [args: UInputRec.OperateOnSelected, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; sSel: SilSelection; SilDisplayCursors.DisableRopeInput[data, ctx]; SELECT args.op FROM delete => { sSel _ SilFile.GetSelection[]; SilDisplayCursors.AquireAndDisableTheMark[data, ctx]; SilDisplayCursors.SetMarkX[sSel.xMin]; SilDisplayCursors.SetMarkY[sSel.yMin]; SilDisplayCursors.DeleteAndEraseSelection[data: data, ctx: ctx, cache: TRUE]; SilUserInput.SetCaretChange[uiData]; }; copy, moveStretch, moveNoStretch => { xOffset, yOffset: INTEGER; xMin, yMin, xMax, yMax: INTEGER; IF NOT SilDisplayCursors.OriginAndSelectionInSameWindow[] THEN { MessageWindow.Append["Origin and Selection must be in same window", TRUE]; MessageWindow.Blink; RETURN; }; SELECT args.rel FROM relative => { xOffset _ SilDisplayCursors.GetMarkX[] - SilDisplayCursors.GetOriginX[]; yOffset _ SilDisplayCursors.GetMarkY[] - SilDisplayCursors.GetOriginY[]; }; absolute => { xOffset _ args.x - SilDisplayCursors.GetOriginX[]; yOffset _ args.y - SilDisplayCursors.GetOriginY[]; }; ENDCASE; sSel _ SilFile.CopySelection[]; xMin _ sSel.xMin; yMin _ sSel.yMin; xMax _ sSel.xMax; yMax _ sSel.yMax; IF NOT CheckSelectionsForMacroDefs[model] THEN { MessageWindow.Append["Selection contains macros undefined in destination window", TRUE]; MessageWindow.Blink; RETURN; }; IF args.op = copy THEN { SilDisplayCursors.DeselectAndRedraw[]; IF args.rel = absolute THEN { SilDisplayCursors.AquireAndDisableTheOrigin[data: data, ctx: ctx]; SilDisplayCursors.SetOriginX[args.x]; SilDisplayCursors.SetOriginY[args.y]; SilUserInput.SetCaretChange[uiData: uiData] } ELSE SilDisplayCursors.MoveOriginToMark[data, ctx]; } ELSE { -- move (not copy) SilDisplayCursors.DeleteAndEraseSelection[data: data, ctx: ctx, cache: FALSE]; SilDisplayCursors.InterchangeMarkAndOrigin[data, ctx]; IF args.rel = absolute THEN { SilDisplayCursors.AquireAndDisableTheOrigin[data: data, ctx: ctx]; SilDisplayCursors.SetOriginX[args.x]; SilDisplayCursors.SetOriginY[args.y]; SilUserInput.SetCaretChange[uiData: uiData] }; }; SilDisplayCursors.InitiateNewSelection[data]; FOR s: SilObject _ sSel.objects, s.rest WHILE s # sSel.lastObject DO sobr: SilObjectRec _ s.first; sobr.xMin _ sobr.xMin + xOffset; sobr.yMin _ sobr.yMin + yOffset; sobr.xMax _ sobr.xMax + xOffset; sobr.yMax _ sobr.yMax + yOffset; SilFile.DefineSelectWithObject[model, SilFile.AddObjectToMainPicture[model, sobr] ]; SilDisplayUtils.PaintObject[model, sobr, select, ctx]; ENDLOOP; IF args.op = moveStretch AND (xOffset # 0 OR yOffset # 0) AND (xOffset = 0 OR yOffset = 0) THEN { offsetDirection: SilDisplayUtils.Orientation _ IF xOffset = 0 THEN vertical ELSE horizontal; offset: INTEGER _ IF xOffset = 0 THEN yOffset ELSE xOffset; FOR s: SilObject _ GetObjectList[model, fgnd], s.rest WHILE s # NIL DO IF NOT ObjectIsSelected[model, s] THEN { bEnd: SilDisplayUtils.BoxEnd; passed: BOOL; [passed, bEnd] _ SilDisplayUtils.OffsetFilter[s.first, offsetDirection, offset, xMin, yMin, xMax, yMax]; IF passed THEN { SilDisplayUtils.PaintObject[model, s.first, erase, ctx]; SilDisplayUtils.StretchBox[s, offsetDirection, bEnd, offset]; SilDisplayUtils.PaintObject[model, s.first, show, ctx]; }; }; ENDLOOP; FOR s: SilObject _ GetObjectList[model, bkgnd], s.rest WHILE s # NIL DO IF NOT ObjectIsSelected[model, s] THEN { bEnd: SilDisplayUtils.BoxEnd; passed: BOOL; [passed, bEnd] _ SilDisplayUtils.OffsetFilter[s.first, offsetDirection, offset, xMin, yMin, xMax, yMax]; IF passed THEN { SilDisplayUtils.PaintObject[model, s.first, erase, ctx]; SilDisplayUtils.StretchBox[s, offsetDirection, bEnd, offset]; SilDisplayUtils.PaintObject[model, s.first, show, ctx]; }; }; ENDLOOP; IF offsetDirection = vertical THEN SilDisplayUtils.MergeRebuild[dData, model, xMin, MIN[yMin, yMin + yOffset], xMax, MIN[yMax, yMax + yOffset], FALSE] ELSE SilDisplayUtils.MergeRebuild[dData, model, MIN[xMin, xMin + xOffset], yMin, MIN[xMax, xMax + xOffset], yMax, FALSE] }; SilDisplayUtils.MarkFileAsEdited[data, ctx, viewer]; }; ENDCASE; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Selections, intArg1: SilFile.GetSelection[].numObjects]; }; ChangeSelected: PUBLIC ENTRY PROC [args: UInputRec.ChangeSelected, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { rebuildArea: RebuildAreaRec _ []; dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; AR: SilDisplayUtils.AttributeRec _ SilDisplayUtils.AttributeFromChar[args.char]; IF AR.referenced = invalid THEN { MessageWindow.Append["Illegal attribute given.", TRUE]; MessageWindow.Blink; RETURN; } ELSE MessageWindow.Append[Rope.FromChar[args.char], FALSE]; SilDisplayCursors.DisableRopeInput[data, ctx]; FOR s: SilObject _ SilFile.GetSelection[].objects, s.first.selectObj WHILE s # NIL DO SELECT AR.referenced FROM color => { SilDisplayUtils.PaintObject[model, s.first, erase, ctx]; s.first.color _ AR.color; rebuildArea _ UpdateRebuildArea[s.first, rebuildArea]; }; font => IF s.first.font IN SilFile.InternalPresetFonts AND AR.font IN SilFile.PresetFonts THEN { xMin, yMin, xMax, yMax: INTEGER; SilDisplayUtils.PaintObject[model, s.first, erase, ctx]; s.first.font _ IF SilFile.FontIsBold[s.first.font] THEN SilFile.InternalFontFromUserFont[AR.font, TRUE] ELSE SilFile.InternalFontFromUserFont[AR.font, FALSE]; [xMin, yMin, xMax, yMax] _ SilDisplayUtils.BoundingBoxOfObject[model, s.first]; s.first.xMax _ s.first.xMin + xMax; s.first.yMax _ s.first.yMin + yMax; rebuildArea _ UpdateRebuildArea[s.first, rebuildArea]; }; face => IF s.first.font IN SilFile.InternalPresetFonts THEN { xMin, yMin, xMax, yMax: INTEGER; SilDisplayUtils.PaintObject[model, s.first, erase, ctx]; SELECT AR.face FROM italic => s.first.italic _ TRUE; nonItalic => s.first.italic _ FALSE; bold => s.first.font _ SilFile.InternalFontFromUserFont[SilFile.UserFontFromInternalFont[s.first.font].font, TRUE]; nonBold => s.first.font _ SilFile.InternalFontFromUserFont[SilFile.UserFontFromInternalFont[s.first.font].font, FALSE]; ENDCASE; [xMin, yMin, xMax, yMax] _ SilDisplayUtils.BoundingBoxOfObject[model, s.first]; s.first.xMax _ s.first.xMin + xMax; s.first.yMax _ s.first.yMin + yMax; rebuildArea _ UpdateRebuildArea[s.first, rebuildArea]; }; ENDCASE; ENDLOOP; MergeRebuildArea[dData, model, rebuildArea]; -- rebuild area ONLY ONCE SilDisplayUtils.MarkFileAsEdited[data, ctx, viewer]; }; SetDefaultAttribs: PUBLIC PROC [args: UInputRec.SetDefaultAttribs, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; AR: SilDisplayUtils.AttributeRec _ SilDisplayUtils.AttributeFromChar[args.char]; IF AR.referenced = invalid THEN { MessageWindow.Append["Illegal attribute given.", TRUE]; MessageWindow.Blink; RETURN; } ELSE MessageWindow.Append[Rope.FromChar[args.char], FALSE]; SilDisplayCursors.DisableRopeInput[data, ctx]; SELECT AR.referenced FROM color => SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Color, intArg1: AR.color]; font => SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Font, intArg1: AR.font]; face => SELECT AR.face FROM italic =>SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Italic, boolArg: TRUE]; nonItalic => SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Italic, boolArg: FALSE]; bold => SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Bold, boolArg: TRUE]; nonBold => SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Bold, boolArg: FALSE]; ENDCASE; ENDCASE; IF dData.currentFont IN SilFile.PresetFonts THEN { dData.currentFontRef _ SilDisplayUtils.GetFont[ SilFile.InternalFontFromUserFont[dData.currentFont, dData.currentBoldState], dData.currentItalicState]; }; }; SetDetails: PUBLIC PROC [args: UInputRec.SetDetails, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; SilDisplayCursors.DisableRopeInput[data, ctx]; SELECT args.detail FROM boxWidth => IF args.char - '0 > 9 OR args.char - '0 < 1 THEN { MessageWindow.Append["Illegal line width given.", TRUE]; MessageWindow.Blink[]; } ELSE { MessageWindow.Append[Rope.FromChar[args.char], FALSE]; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: LineWidth, intArg1: args.char - '0]; }; gridSize => IF args.char - '0 > 9 OR args.char - '0 < 0 THEN { MessageWindow.Append["Illegal grid spacing given.", TRUE]; MessageWindow.Blink[]; } ELSE { grid: NAT _ 1; MessageWindow.Append[Rope.FromChar[args.char], FALSE]; FOR i: NAT IN [1..args.char - '0] DO grid _ grid * 2; ENDLOOP; IF grid > 64 THEN grid _ 64; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Grid, intArg1: grid]; SilUserInput.ChangeGridInterval[data.uiData, grid]; }; ENDCASE; }; ManipulateMacro: PUBLIC ENTRY PROC [args: UInputRec.ManipulateMacro, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; SilDisplayCursors.DisableRopeInput[data, ctx]; SELECT args.mode FROM expand => { markX: INTEGER _ SilDisplayCursors.GetMarkX[]; markY: INTEGER _ SilDisplayCursors.GetMarkY[]; IF NOT SilDisplayCursors.MouseAndMarkInSameWindow[data] THEN { MessageWindow.Append["Input Focus must be in same window as mark", TRUE]; MessageWindow.Blink; RETURN; }; IF NOT args.char IN SilFile.MacroName THEN { MessageWindow.Append["Illegal Macro Name: ", TRUE]; MessageWindow.Append[Rope.FromChar[args.char], FALSE]; MessageWindow.Blink; RETURN; }; MessageWindow.Append[Rope.FromChar[args.char], FALSE]; SilDisplayCursors.CheckSelectionWindow[data]; SilDisplayUtils.DeselectAndPaintAll[model, ctx]; SilDisplayUtils.ExpandMacro[model, args.char, markX, markY, dData.currentOneLevel, ctx]; }; define => IF CheckSelectionsForMacroDefs[model: data.model, disallowName: TRUE, name: args.char] AND args.char IN SilFile.MacroName THEN IF SilFile.GetObjectList[model: model, mode: macro, c: args.char] = NIL THEN { SilDisplayUtils.DefineConfirmedMacro[data, args.char, ctx]; MessageWindow.Append[Rope.FromChar[args.char], FALSE]; } ELSE { dData.mode _ WaitingForMacroDefConfirmation; SilUserInput.InputingRope[data.uiData]; dData.macroDefName _ args.char; MessageWindow.Append["Macro def for ", TRUE]; MessageWindow.Append[Rope.FromChar[args.char], FALSE]; MessageWindow.Append[" already exists. ", FALSE]; MessageWindow.Append["confirm with carriage return for overwrite.", FALSE]; MessageWindow.Blink; } ELSE { MessageWindow.Append["Illegal Macro definition", TRUE]; MessageWindow.Blink; }; clear => { dData.mode _ WaitingForMacroDeleteConfirmation; SilUserInput.InputingRope[data.uiData]; MessageWindow.Append["Confirm deletion of all macros ", TRUE]; MessageWindow.Append["with CR, ESC, or any click ", FALSE]; MessageWindow.Append["abort with DEL.", FALSE]; MessageWindow.Blink[]; }; ENDCASE; SilDisplayUtils.MarkFileAsEdited[data, ctx, viewer]; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Selections, intArg1: SilFile.GetSelection[].numObjects]; }; DrawBox: PUBLIC ENTRY PROC [args: UInputRec.DrawBox, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { Finite: PROC [sobr: SilObjectRec] RETURNS [BOOL] ~ { RETURN[(sobr.xMin#sobr.xMax) AND (sobr.yMin#sobr.yMax)]; }; dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; sobr: SilObjectRec; foregroundBoxFont: INTEGER = SilFile.foregroundBoxFont; backgroundBoxFont: INTEGER = SilFile.backgroundBoxFont; markX: INTEGER _ SilDisplayCursors.GetMarkX[]; markY: INTEGER _ SilDisplayCursors.GetMarkY[]; originX: INTEGER _ SilDisplayCursors.GetOriginX[]; originY: INTEGER _ SilDisplayCursors.GetOriginY[]; SilDisplayCursors.DisableRopeInput[data, ctx]; SilDisplayCursors.CheckSelectionWindow[data]; IF NOT SilDisplayCursors.MouseAndMarkInSameWindow[data] THEN { MessageWindow.Append["Can't draw lines across viewer boundaries", TRUE]; MessageWindow.Blink; RETURN; }; IF args.originRel=absolute AND NOT SilDisplayCursors.MarkAndOriginInSameWindow[] THEN { MessageWindow.Append["Can't draw boxes across viewer boundaries", TRUE]; MessageWindow.Blink; RETURN; }; SilDisplayCursors.AquireAndDisableTheMark[data, ctx]; SilDisplayCursors.AquireAndDisableTheOrigin[data, ctx]; SilDisplayUtils.DeselectAndPaintAll[model, ctx]; sobr.color _ dData.currentColor; sobr.font _ IF args.background THEN backgroundBoxFont ELSE foregroundBoxFont; sobr.italic _ FALSE; SELECT args.originRel FROM relative => { --Draw simple box IF ABS[markX - args.x] < ABS[markY - args.y] THEN { sobr.xMin _ markX; sobr.yMin _ MIN[markY, args.y]; sobr.xMax _ sobr.xMin + dData.currentBoxWidth; sobr.yMax _ MAX[markY, args.y]; markY _ args.y; sobr _ SilDisplayUtils.FixBoxConnectivity[dData, sobr, vertical]; } ELSE { sobr.xMin _ MIN[markX, args.x]; sobr.yMin _ markY; sobr.xMax _ MAX[markX, args.x]; sobr.yMax _ markY + dData.currentBoxWidth; markX _ args.x; sobr _ SilDisplayUtils.FixBoxConnectivity[dData, sobr, horizontal]; }; IF Finite[sobr] THEN SilFile.DefineSelectWithObject[model, SilFile.AddObjectToMainPicture[model, sobr]]; }; absolute => { --The box will use mark AND origin for control xMin, yMin, xMax, yMax: INTEGER; xMin _ sobr.xMin _ MIN[markX, originX]; yMin _ sobr.yMin _ MIN[markY, originY]; xMax _ sobr.xMax _ MAX[markX, originX]; yMax _ sobr.yMax _ MAX[markY, originY]; IF args.background THEN { --The box will be one large one in background IF Finite[sobr] THEN SilFile.DefineSelectWithObject[model, SilFile.AddObjectToMainPicture[model, sobr]]; } ELSE { --There will be 4 boxes: 2 vertical, 2 horizontal sobr.yMax _ yMin + dData.currentBoxWidth; --box 1 IF Finite[sobr] THEN SilFile.DefineSelectWithObject[model, SilFile.AddObjectToMainPicture[model, sobr]]; sobr.xMax _ xMin+ dData.currentBoxWidth; --box 2 sobr.yMax _ yMax; IF Finite[sobr] THEN SilFile.DefineSelectWithObject[model, SilFile.AddObjectToMainPicture[model, sobr]]; sobr.xMin _ xMax; --box 3 sobr.xMax _ xMax + dData.currentBoxWidth; IF Finite[sobr] THEN SilFile.DefineSelectWithObject[model, SilFile.AddObjectToMainPicture[model, sobr]]; sobr.xMin _ xMin; --box 4 sobr.yMin _ yMax; sobr.xMax _ xMax + dData.currentBoxWidth; sobr.yMax _ yMax + dData.currentBoxWidth; IF Finite[sobr] THEN SilFile.DefineSelectWithObject[model, SilFile.AddObjectToMainPicture[model, sobr]]; sobr.xMin _ xMin; sobr.yMin _ yMin; sobr.xMax _ xMax; sobr.yMax _ yMax; }; dData.lastBoxLeftToRight _ FALSE; dData.lastBoxTopToBottom _ FALSE; }; ENDCASE; FOR s: SilObject _ SilFile.GetSelection[].objects, s.first.selectObj WHILE s # NIL DO SilDisplayUtils.PaintObject[model, s.first, select, ctx]; --shortcut MergeRebuild ENDLOOP; SilDisplayCursors.SetOriginX[sobr.xMin]; SilDisplayCursors.SetOriginY[sobr.yMin]; SilDisplayCursors.SetMarkX[markX]; SilDisplayCursors.SetMarkY[markY]; SilUserInput.SetCaretChange[uiData]; IF NOT dData.yLock THEN { n: INTEGER _ (sobr.yMax - sobr.yMin) / dData.currentGridSpacing; m: INTEGER _ (sobr.yMax - sobr.yMin) MOD dData.currentGridSpacing; IF m # 0 THEN n _ n + 1; dData.yInc _ n * dData.currentGridSpacing; }; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Selections, intArg1: SilFile.GetSelection[].numObjects]; SilDisplayUtils.MarkFileAsEdited[data, ctx, viewer]; }; HandleInputChars: PUBLIC ENTRY PROC [args: UInputRec.UserChar, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { AbortInput: PROC [data: SilData] = { dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; SELECT dData.mode FROM InputingRope => SilDisplayCursors.DisableRopeInput[data, ctx]; EditingExistingRope => { SilDisplayUtils.PaintObject[model, dData.collectingObject, erase, ctx]; dData.collectingObject.value _ dData.oldText; SilFile.DefineSelectWithObject[model, SilFile.AddObjectToMainPicture[model, dData.collectingObject]]; SilDisplayUtils.PaintObject[model, dData.collectingObject, select, ctx]; SilDisplayCursors.InitiateNewSelection[data: data]; --notify SilDisplayCursorsImpl of reselection old rope SilUserInput.NotInputingRope[uiData]; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Selections, intArg1: SilFile.GetSelection[].numObjects]; }; InputingInputFileName, EditingExistingInputFileName, InputingOutputFileName, EditingExistingOutputFileName, InputingHardFileName, EditingExistingHardFileName => { MessageWindow.Append["", TRUE]; dData.collectingFileName.length _ 0; dData.mode _ WaitingToInputRope; SilUserInput.NotInputingRope[uiData]; }; WaitingForKillConfirmation, WaitingForMacroDefConfirmation, WaitingForMacroDeleteConfirmation => { dData.mode _ WaitingToInputRope; SilUserInput.NotInputingRope[uiData]; MessageWindow.Append["", TRUE]; }; ENDCASE; }; FinishInput: PROC [data: SilData] = { dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; lViewer: ViewerClasses.Viewer _ SilUserInput.GetBiScroller[uiData].QuaViewer[].parent; SELECT dData.mode FROM InputingInputFileName, EditingExistingInputFileName, InputingOutputFileName, EditingExistingOutputFileName, InputingHardFileName, EditingExistingHardFileName => IF dData.collectingFileName.length > 0 THEN { tName: ROPE _ Rope.FromRefText[dData.collectingFileName]; SELECT dData.mode FROM InputingInputFileName, EditingExistingInputFileName => SilDisplayUtils.InputNamedFile[data, tName, ctx]; InputingOutputFileName, EditingExistingOutputFileName => { ViewerOps.SaveViewer[viewer ! SilKernel.SilError => GOTO Done;]; --save inner viewer lViewer.newVersion _ lViewer.newFile _ FALSE; --Abutter lViewer.child.newVersion _ lViewer.child.newFile _ FALSE; --ViewRec viewer lViewer.child.sibling.newVersion _ lViewer.child.sibling.newFile _ FALSE; --BiScroller lViewer.icon _ SilDisplay.GetIcon[dirtyIcon: FALSE]; EXITS Done => NULL; }; InputingHardFileName, EditingExistingHardFileName => TRUSTED { Process.Detach[FORK SilDisplayUtils.HardcopyFile[data, tName]];}; ENDCASE; dData.collectingFileName.length _ 0; dData.mode _ WaitingToInputRope; SilUserInput.NotInputingRope[uiData]; IF NOT Rope.Equal[(tName _ SilFile.GetActiveFileName[data.model]), ""] THEN lViewer.name _ tName; MessageWindow.Append[Rope.Cat["File: ", tName, " completed"], TRUE]; ViewerOps.PaintViewer[lViewer, caption]; } ELSE MessageWindow.Append["", TRUE]; InputingRope, EditingExistingRope => IF dData.collectingText.length > 0 THEN { mxMin, myMin, mxMax, myMax: INTEGER; SilDisplayCursors.CheckSelectionWindow[data]; dData.collectingObject.value _ Rope.FromRefText[dData.collectingText]; [mxMin, myMin, mxMax, myMax] _ SilDisplayUtils.BoundingBoxOfObject[model, dData.collectingObject]; dData.collectingObject.xMax _ dData.collectingObject.xMin + mxMax - mxMin; dData.collectingObject.yMax _ dData.collectingObject.yMin + myMax - myMin; IF mxMax#0 AND myMax#0 THEN { --this is not an "empty" object SilDisplayUtils.DeselectAndPaintAll[model, ctx]; SilFile.DefineSelectWithObject[model, SilFile.AddObjectToMainPicture[model, dData.collectingObject]]; SilDisplayUtils.PaintObject[model, dData.collectingObject, select, ctx]; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Selections, intArg1: SilFile.GetSelection[].numObjects]; }; IF NOT dData.yLock THEN { n: INTEGER _ (dData.collectingObject.yMax - dData.collectingObject.yMin) / dData.currentGridSpacing; m: INTEGER _ (dData.collectingObject.yMax - dData.collectingObject.yMin) MOD dData.currentGridSpacing; IF m # 0 THEN n _ n + 1; dData.yInc _ n * dData.currentGridSpacing; }; SilDisplayCursors.AquireAndDisableTheMark[data, ctx]; SilDisplayCursors.AquireAndDisableTheOrigin[data, ctx]; SilDisplayCursors.SetMarkY[dData.collectingObject.yMin + dData.yInc]; SilDisplayCursors.SetMarkX[dData.collectingObject.xMin]; SilDisplayCursors.SetOriginX[dData.collectingObject.xMin]; SilDisplayCursors.SetOriginY[dData.collectingObject.yMin]; dData.collectingText.length _ 0; dData.mode _ WaitingToInputRope; SilUserInput.NotInputingRope[uiData]; SilDisplayUtils.MarkFileAsEdited[data, ctx, lViewer]; }; WaitingForKillConfirmation => { SilDisplayUtils.KillConfirmedFile[data, ctx, lViewer]; dData.mode _ WaitingToInputRope; SilUserInput.NotInputingRope[uiData]; MessageWindow.Append["", TRUE]; }; WaitingForMacroDefConfirmation => { -- assert: don't have to scan bkgnd list here FOR s: SilObject _ GetObjectList[model, fgnd], s.rest WHILE s # NIL DO IF s.first.font = InternalFileMacroFont AND Rope.Fetch[s.first.value] = dData.macroDefName THEN SilDisplayUtils.PaintObject[model, s.first, erase, ctx]; ENDLOOP; SilDisplayUtils.DefineConfirmedMacro[data, dData.macroDefName, ctx]; dData.mode _ WaitingToInputRope; SilUserInput.NotInputingRope[uiData]; MessageWindow.Append["", TRUE]; }; WaitingForMacroDeleteConfirmation => { SilDisplayUtils.ClearConfirmedMacroDefs[data, ctx]; dData.mode _ WaitingToInputRope; SilUserInput.NotInputingRope[uiData]; MessageWindow.Append["", TRUE]; }; ENDCASE; }; finished: BOOL; aborted: BOOL; backedUp: BOOL; dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; SELECT dData.mode FROM WaitingToInputRope => IF args.c = Ascii.BS THEN { IF NOT SilDisplayCursors.MarkAndSelectionInSameWindow[] THEN { MessageWindow.Append["Mark and Selection must be in same window", TRUE]; MessageWindow.Blink[]; RETURN;} ELSE { sSel: SilSelection _ SilFile.GetSelection[]; IF sSel.objects # NIL AND sSel.objects.first.font IN SilFile.InternalRopeFonts AND sSel.objects.first.selectObj = sSel.lastObject THEN { dData.mode _ EditingExistingRope; dData.collectingObject _ sSel.objects.first; dData.oldText _ sSel.objects.first.value; dData.collectingText _ Rope.ToRefText[sSel.objects.first.value]; SilDisplayCursors.DeleteAndEraseSelection[data: data, ctx: ctx, cache: FALSE]; aborted _ finished _ backedUp _ FALSE; SilUserInput.InputingRope[data.uiData]; } ELSE RETURN; }; } ELSE { dData.mode _ InputingRope; SilUserInput.InputingRope[data.uiData]; dData.collectingObject.xMin _ SilDisplayCursors.GetMarkX[]; dData.collectingObject.yMin _ SilDisplayCursors.GetMarkY[]; dData.collectingObject.color _ dData.currentColor; dData.collectingObject.font _ SilFile.InternalFontFromUserFont[dData.currentFont, dData.currentBoldState]; dData.collectingObject.italic _ dData.currentItalicState; dData.collectingObject.value _ ""; dData.collectingText.length _ 0; [dData.collectingText, finished, aborted, backedUp] _ SilDisplayUtils.EditText[dData.collectingText, args.c]; }; InputingRope, EditingExistingRope, WaitingForKillConfirmation, WaitingForMacroDefConfirmation, WaitingForMacroDeleteConfirmation => [dData.collectingText, finished, aborted, backedUp] _ SilDisplayUtils.EditText[dData.collectingText, args.c]; InputingInputFileName, EditingExistingInputFileName, InputingOutputFileName, EditingExistingOutputFileName, InputingHardFileName, EditingExistingHardFileName => [dData.collectingFileName, finished, aborted, backedUp] _ SilDisplayUtils.EditText[dData.collectingFileName, args.c]; ENDCASE; SELECT TRUE FROM NOT aborted AND NOT finished => SELECT dData.mode FROM InputingRope, EditingExistingRope => { IF backedUp THEN SilDisplayUtils.PaintObject[model, dData.collectingObject, erase, ctx]; dData.collectingObject.value _ Rope.FromRefText[dData.collectingText]; SilDisplayUtils.PaintObject[model, dData.collectingObject, show, ctx]; }; InputingInputFileName => { MessageWindow.Append["Input file: ", TRUE]; MessageWindow.Append[Rope.FromRefText[dData.collectingFileName], FALSE]; }; EditingExistingInputFileName => { dData.mode _ InputingInputFileName; MessageWindow.Append["Input file: ", TRUE]; MessageWindow.Append[Rope.FromRefText[dData.collectingFileName], FALSE]; }; InputingOutputFileName => { MessageWindow.Append["Output", TRUE]; IF dData.largeFormat THEN MessageWindow.Append[" Large Format", FALSE]; MessageWindow.Append[" file: ", FALSE]; MessageWindow.Append[Rope.FromRefText[dData.collectingFileName], FALSE]; }; EditingExistingOutputFileName => { dData.mode _ InputingOutputFileName; MessageWindow.Append["Output", TRUE]; IF dData.largeFormat THEN MessageWindow.Append[" Large Format", FALSE]; MessageWindow.Append[" file: ", FALSE]; MessageWindow.Append[Rope.FromRefText[dData.collectingFileName], FALSE]; }; InputingHardFileName => { MessageWindow.Append["Hardcopy file: ", TRUE]; MessageWindow.Append[Rope.FromRefText[dData.collectingFileName], FALSE]; }; EditingExistingHardFileName => { dData.mode _ InputingHardFileName; MessageWindow.Append["Hardcopy file: ", TRUE]; MessageWindow.Append[Rope.FromRefText[dData.collectingFileName], FALSE]; }; ENDCASE; aborted => AbortInput[data]; finished => FinishInput[data]; ENDCASE; }; Compliment: PUBLIC PROC [args: UInputRec.Compliment, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; SilDisplayCursors.DisableRopeInput[data, ctx]; SELECT args.mode FROM tics => { IF dData.ticsOn THEN SilDisplayUtils.DisplayGrid[erase, dData, model, ctx]; dData.ticsOn _ NOT dData.ticsOn; IF dData.ticsOn THEN SilDisplayUtils.DisplayGrid[show, dData, model, ctx]; }; frames => { IF dData.framesOn THEN SilDisplayUtils.DisplayFrames[erase, dData, model, ctx]; dData.framesOn _ NOT dData.framesOn; IF dData.framesOn THEN SilDisplayUtils.DisplayFrames[show, dData, model, ctx]; }; magnification => { xMin, yMin, xMax, yMax: INTEGER; legalBox: BOOL; [legalBox, xMin, yMin, xMax, yMax] _ SilDisplayCursors.GetBoundingBoxOfLast2Marks[data]; IF NOT legalBox THEN RETURN; SilDisplayUtils.MagnifyDrawing[data, ctx, xMin, yMin, xMax, yMax]; }; oneLevel => SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: MacExpand, boolArg: NOT dData.currentOneLevel]; yInc => { SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Ylock, boolArg: NOT dData.yLock]; IF dData.yLock THEN { n: INTEGER _ (SilDisplayCursors.GetOriginY[] - SilDisplayCursors.GetMarkY[]) / dData.currentGridSpacing; m: INTEGER _ (SilDisplayCursors.GetOriginY[] - SilDisplayCursors.GetMarkY[]) MOD dData.currentGridSpacing; IF m # 0 THEN n _ n + 1; dData.yInc _ n * dData.currentGridSpacing; }; }; ENDCASE; }; ShowMacros: PUBLIC PROC [args: UInputRec.ShowMacros, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { model: SilModel _ data.model; font: InternalMacroFonts; fonts: REF TEXT; SilDisplayCursors.DisableRopeInput[data, ctx]; SELECT args.char FROM '4, '5, '6, '7, '8, '9 => font _ SilFile.InternalFontFromUserFont[args.char - '0, FALSE]; ENDCASE => {MessageWindow.Append["Illegal Macro Name.", TRUE]; MessageWindow.Blink; RETURN; }; MessageWindow.Append["Font ", TRUE]; MessageWindow.Append[Rope.FromChar[args.char], FALSE]; MessageWindow.Append[": ", FALSE]; fonts _ RefText.New[SilFile.MacroNameSize]; --Maximum number of macro names FOR c: MacroName IN MacroName DO IF SilFile.GetObjectList[model, macro, font, c] # NIL THEN fonts _ RefText.AppendChar[fonts, c]; ENDLOOP; MessageWindow.Append[Rope.FromRefText[fonts], FALSE]; }; Undelete: PUBLIC ENTRY PROC [args: UInputRec.Undelete, data: SilData, viewer: ViewerClasses.Viewer, ctx: Imager.Context] = { xMin, yMin, xMax, yMax: INTEGER; sob: SilObject; dData: SilDisplayData _ data.displayData; model: SilModel _ data.model; uiData: SilUIData _ data.uiData; SilDisplayCursors.DisableRopeInput[data, ctx]; SilDisplayUtils.PaintAllSelectedAsDeselected[model, ctx]; SilDisplayCursors.CheckSelectionWindow[data]; sob _ SilFile.Undelete[model]; [xMin, yMin, xMax, yMax] _ SilDisplayUtils.BoundingBoxOfContext[ctx]; SilDisplayUtils.MergeRebuild[dData, model, xMin, yMin, xMax, yMax, TRUE]; SilDisplayUtils.MarkFileAsEdited[data, ctx, viewer]; SilDisplayUtils.ChangeCommandLineData[data: data, ctx: ctx, change: Selections, intArg1: SilFile.GetSelection[].numObjects]; }; END. , SilDisplayImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Tracy Larrabee, March 29, 1984 1:39:44 pm PST Last Edited by: Pier, December 18, 1985 5:50:54 pm PST This module AND its companion SilDisplayImplA implement the routines which get user input, process it, and modify the Sil internal file structures. These modules will call on SilDisplayUtils and SilDisplayCursors and use data structures defined in SilDisplayInternal. To understand what is going on, look at the SilPaintProc in SilDisplayImplA. Following are several procedures which take a UInputRec (a variant record, defined in SilUserInput). Following the real procedure definition there is a comment which indicates what this procedure is going to expect from ints variant record. -------File and Control operations-------- []; Input a Sil file. Collect the file name from the user. (.Sil extention will be assumed if none is supplied). 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). args.mode specifies whether the Sil objects read in should be origined at (0,0), as usual [mode=absolute], or origined at (markX, markY) [mode=relative]. [clip: BOOL _ TRUE, large: BOOL _ FALSE]; Output a Sil file. Collect the file name from the user. (.Sil extention will be assumed if none is supplied). If clip is true make sure that the output is clipped to the size of the old Alto screen when it is saved. If large is TRUE, then use the new CedarSil format, else output in the standard AltoSil format. []; Kill the current picture so that any further drawing will be done with a clean slate. []; [char: CHAR]; -----Tracking the mouse, and defining the mark, origin and current selection; scrolling to Mark [x: INTEGER _ 0, y: INTEGER _ 0]; Track the motion of the mouse (when a mouse button is depressed) for the command line. [caret: CaretSet, x: INTEGER _ 0, y: INTEGER _ 0, mode: Relation]; Set the desired caret. If mode is absolute, set the position to be , otherwise, change only the y value of the caret, acording to the value of Yinc (ingnore x and y) [caret: CaretSet]; Set the cursor bitmap from the screen bitmap near the caret. convert Sil coordinates to screen coordinates [x, y: INTEGER, mode: SelectMode _ change]; Each mode will cause the selection to change based on the current selection and the object at . If there is more than one object at the one we are concerned with is the element at with the smallest perimeter. If mode is change, the object at becomes the only current selection. If mode is add, the object at is added to the previously selected objects. In both cases the origin is moved to the upper left corner of the selected object; if no object exists at the origin is moved to . If mode is remove, the object at is deselected; in this case the origin does not change. If mode is relative, select all objects which are contained in the box defined by and the last mark. The origin is moved to the upper left corner of the bounding box containing the selected objects. If the mode is delete, delete the object at . Deselect all the old stuff, then select the new stuff Only difference between change and add is whether to keep old selections In process of deleting might have written over selected object [mode: SelectMode, char: CHAR]; Two modes will cause the selection to change based on the current selection and which objects in the main picture have certain attributes. If mode is change, all objects in the picture which have the attribute indicated are selected. If mode is reduce, all objects which were previously selected and have the attribute indicated become the current selection. No selectMode other than these two is valid. The user has typed ControlArrow, and wants the center of the BiScroller viewport to move to the current Mark position. Also resets the BiScroller Scale to 1:1. Before calling BiScrollers.Align, the current ctx is used to clear the viewer. Sil coordinates = (ClientCoords/scale) - offset xScale = gridMagnification; xOffset = dData.xOffset yScale = - gridMagnification; yOffset = dData.yOffset ClientCoord = (SilCoord + offset) * scale xScale = gridMagnification; xOffset = dData.xOffset yScale = - gridMagnification; yOffset = dData.yOffset -----Manipulation of the current selection-------- [op: OperationMode, rel: Relation _ relative, x: INTEGER _ 0, y: INTEGER _ 0]; Depending on op, either ignore or utilize to copy, move, or delete the selected objects. If op is delete, ignore rel and and delete all selected objects. If op is copy, copy the selected objects. If rel is absolute copy them such that the origin is at . If rel is relative copy them such that the origin is at the mark and ignore . If op is moveStretch, move the selected objects. If rel is absolute move them such that the origin is at . If rel is relative move them such that the origin is at the mark and ignore As a feature, if the selected objects are thought of as defining a rectangular window, and if they are moved ONLY in X or in Y, the endpoints of any boxes which cross the window boundary are moved (by shortening or lengthening the box) so that the endpoints have the same relation to the selected objects as in the original view. If the box would be shortened to a non-posotive length, or if it is fully in the window but not selected, it is not modified. If op is moveNoStretch, proceed as if it was moveStretch, but do not stretch any boxes (as described above). [char: CHAR]; Some attribute of the objects in the current selection will change, depending on char. s.first.xMin _ s.first.xMin + xMin; s.first.yMin _ s.first.yMin + yMin; s.first.xMin _ s.first.xMin + xMin; s.first.yMin _ s.first.yMin + yMin; -----Set Sil parameters-------- [char: CHAR]; Set the current attributes for future picture additions as indicated. Depending on att, certain arguments will be ignored. If att is color, the font and face arguments will be ignored, and future objects will be of the given color. The obvious extentions with respect to font and face are made. [detail: Details, char: CHAR]; Set the details as inidicated. If detail is boxWidth, the char should be an integer argument used to set the boxWidth. If detail is gridSize, the char should be an integer argument used to set the grid size. -----Manipulate Macros-------- [mode: MacroMode, char: CHAR]; If mode is expand, expand the macro with name such that its upper left corner is placed at the mark. Macros within name will not be expanded if the macro expansion level is set to oneLevel. If mode is define, define the set of selected objects to be the macro with name name. The name and the selected objects must have been previously checked as valid macro definitions. If mode is clear, delete all Macro definitions as well as all instances of them in the current picture (name will be ignored). -----Draw, Delete, and Show procedures-------- [markRel: Relation _ absolute, originRel: Relation _ absolute, x: INTEGER _ 0, y: INTEGER _ 0, background: BOOL _ FALSE]; Draw 1 or 4 boxes. If markRel and originRel are both absolute and background is FALSE, draw 4 boxes, with the origin and the mark defining the 2 points between which all 4 possible horizontal and vertical boxes are drawn, with width defined by the current box width. If markRel and originRel are both absolute and background is TRUE, draw 1 box in the background, with the origin and the mark defining the corners. If only markRel is absolute, draw 1 box having width defined by the current BoxWidth and having the appearance of a horizontal line if the difference betweeen the 2 defining points is larger in x than in y, else having the appearance of a vertical line. and the mark are the defining points. Move the mark to the end of the box nearest . In all cases the box is selected and the origin is moved to the upper left corner of the box. Preparation: mark and origin will be moved, and the new box(es) will be selected Box is from mark to new y coordinate, vertical box Box is from mark to new x coordinate, horizontal box: now set dimensions of effective object just added to model Display the results Move the origin to upper left hand corner of the new structure; [c: Char]; Handle this Input Char. Do the correct thing based on the current input mode of the system. Perform the correct actions to clean up after the user decides to abort the input Perform the correct actions upon completion of string input. Correct responses can include the input or output of a file, the creation of a new Sil string object, or the confirmation of an action which needed to be performed (such as killing a file - if the file has been edited the user must confirm the kill. The confirmation is treated as string input). This viewer is of Class = $Abutter and contains the BiScroller Only edit text if only one object is selected and it is a rope. SilDisplayUtils.DeselectAndPaintAll[model, ctx]; IF NOT backedUp THEN { dData.collectingFileName[0] _ dData.collectingFileName[dData.collectingFileName.length - 1]; dData.collectingFileName.length _ 1; }; IF NOT backedUp THEN { dData.collectingFileName[0] _ dData.collectingFileName[dData.collectingFileName.length - 1]; dData.collectingFileName.length _ 1; }; IF NOT backedUp THEN { dData.collectingFileName[0] _ dData.collectingFileName[dData.collectingFileName.length - 1]; dData.collectingFileName.length _ 1; }; [mode: CompMode]; If mode is tics, compliment the tics state (show them if they are not shown, and vice versa). If mode is frames, compliment the frames state (show them if they are not shown, and vice versa). If mode is magnification, compliment the magnification state (if not magnifying fill the screen with the area defined by the last 2 marks, else display the entire drawing). If mode is oneLevel compliment the oneLevel flag, which controls the depth of macro expansion. If the oneLevel flag is TRUE, macros will not be expanded past one level, and if it is FALSE, all macros contained in an expanded macro will also be expanded. The state of the oneLevel flag is shown in the CommandLine field MX (Macro eXpand). If mode is yInc, set (or clear, if it is set) the ylock flag. At the time ylock is set (changed from FALSE to TRUE by this command), the difference between the Y coordinates of the mark and the origin is saved as yinc (yIncrement is used when setting a caret relative.). [char: CHAR]; Show all the macros currently defined in font. Only show macros if char was macro font []; Undelete the last set of objects deleted by any previous operation. The newly undeleted object(s) will be THE current selection. A special case of Undo. August 13, 1985 3:00:44 pm PDT: added ENTRY to all PROC declarations that call GetSelection, to avoid changing a selection while the process is computing. If this serializes multiple viewers badly, will change back. Pier, December 18, 1985 5:36:49 pm PST changes to: HandleInputChars no longer erases existing file names when editing begins Ê%|˜code™Kšœ Ïmœ1™<—K™-K™6K˜K™ÚK˜šÏk ˜ šœž˜ Kšœžœ˜—šœ ž˜Kšœ3˜3—Kšœžœ˜(šœž˜ Kšœ$žœ ˜0—šœž˜KšœF˜F—šœž˜Kšœ˜—šœž˜ Kšœ ˜ —šœž˜ Kšœ ˜ —šœž˜ K˜—šœž˜ Kšœ6˜6—šœžœ˜Kšœ ˜ —šœ žœ˜Kšœ.˜.—Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ˜—K˜šÏbœžœžœ˜Kšžœ¼˜ÃKšžœ žœžœ ˜:—K˜Kšœ žœ˜"Kšœ žœ˜"Kšœ žœ˜&Kšœžœžœ˜-Kšœžœžœ(˜FKšœ žœ˜)Kšœžœ˜*Kšœžœžœžœžœžœžœžœžœ˜kK˜šÏnœžœ&žœ˜\Kš žœžœžœžœžœ˜]K˜K˜—š œžœ?˜UKšžœžœžœžœK˜gK˜K˜—Kšœò™òK™šÏc)œ™*K˜—š  œž œb˜xKšœ™KšœÜ™ÜK™Kšœ)˜)Kšœ.˜.Kšœ)˜)Kšœ+˜+Kšœ˜K˜—š  œž œa˜xKš œžœžœ žœžœ™)Kšœ¸™¸K™Kšœ)˜)Kšœ.˜.Kšœ!˜!Kšœ˜Kšœ,˜,K˜K™—š  œž œc˜|Kšœ™KšœTŸ™VKšœ)˜)Kšœ[˜[Kšœ.˜.Kšžœžœžœ6˜Nšžœ˜Kšœ(˜(Kšœ'˜'Kšœ/žœ˜5Kšœ<žœ˜CKšœ(žœ˜/Kšœ˜K˜—K˜K™—š  œž œa˜xKšœ™Kšœ1¡4˜eKšœ˜K™—š œž œ`˜vKšœžœ™ K™Kšœ.˜.Kšœ3˜3Kšœ˜K™—šœ* œ œ)™_K˜—š  œž œb˜zKšœžœ žœ™!K™VK™Kšœk˜kK˜K™—š œž œ`˜vKšœžœ žœ™BKšœ#Ÿœ™¬K™Kšœ)˜)Kšœ˜K˜ Kšœ.˜.šžœ ž˜šœ ˜ Kšœ5˜5šžœ ž˜˜ Kšœ#˜#Kšœ#˜#K˜—KšœR˜RKšžœ˜—K˜—šœ ˜ Kšœ7˜7šžœ ž˜˜ Kšœ%˜%Kšœ%˜%K˜—KšœV˜VKšžœ˜—K˜—Kšžœ˜—K˜$K˜K™—š  œž œa˜xKšœP™PK˜Kšœžœ˜Kšœ˜Kšœ ˜ K˜)KšœE˜EKšžœ6žœžœ¡˜Sšžœžœ3žœ5žœ˜wKšœKžœ˜QKšœ˜Kšžœ˜K˜—Kšœ.˜.Kšœ8¡˜VKšœ6¡˜RKšœK¡0˜{K™-šœA˜AKšœQ˜QKšœT˜T—Kšœd˜dšžœ ž˜KšœI˜IKšœžœ¡œ˜ Kšžœ˜—Kšœ¯žœ˜µKšœ1˜1Kšœ%¡˜:K˜K˜—š  œžœe˜†Kšœžœ™+Kšœæ™æKšœ Ÿœ;™LKšœ ŸœÕ™ãKšœ ŸœO™`Kšœ ŸœSŸœa™ÎKšœŸœ™3K˜Kšœ)˜)Kšœ˜K˜ Kšœžœ(žœ ˜]Kšœ žœ#˜3Kšœ žœ"˜2K˜Kšœ.˜.šœ-˜-K˜—šžœ ž˜šœ ˜ Kšœ7˜7K™5Kšœ0˜0KšœV˜VKš œ+žœžœžœžœžœ˜‚K˜$K˜—šœ˜Kšœ4˜4Kšœ7˜7K™HKšžœžœ1˜KKšœ+˜+šžœžœžœ¡.˜BKšœlžœ˜rKšœ˜Kšœ˜K˜—šžœ¡.˜5Kšœ˜Kšœ˜K˜—K˜—šœ ˜ Kšœ4˜4šžœžœžœ˜Kšœ˜Kšœkžœ˜rK˜—K˜—šœ ˜ Kšœ4˜4šžœžœžœ˜Kšœ:˜:Kšœ5˜5Kšœ˜Kšœ˜Kšœ)˜)K™>Kšœk˜kKšœ4˜4K˜—K˜—Kšžœ˜—Kšœ&˜&Kšœ&˜&Kšœ"˜"Kšœ"˜"K˜$Kšœ|˜|K˜K™—š œžœg˜ŠKšœžœ™Kšœ—ŸœZŸœ›™˜K™K˜!Kšœ)˜)Kšœ˜K˜ KšžœN˜Pšžœžœžœ˜!Kšœ1žœ˜LKšžœ˜Kšœ˜—Kšžœ0žœ˜;K˜Kšœ.˜.šœ-˜-K˜—šžœžœ¡&˜CKšœ0˜0šžœ3žœžœž˜Fšžœ!žœ žœ˜6Kšœ)˜)K˜6K˜—Kšžœ˜—K˜—šžœ¡+˜2Kšœ.˜.Kšœ˜šžœžœž˜Kšœ˜šžœžœ!žœ žœ˜:Kšœ˜K˜6K˜—K˜ Kšžœ˜—K˜—Kšœ.¡˜GKšœ|˜|K˜K˜—š  œž œe˜~K™îK™š œžœžœ˜?K™0Kšœ3™3Kšœ5™5K™Kš œ4žœžœžœ žœ6˜ÌKšœ˜—K˜š  œžœžœžœžœ˜cK™)Kšœ3™3Kšœ5™5K˜Kšœžœ˜+Kšœ"˜"Kšœ"˜"šžœžœžœ˜@Kšœ/˜/Kšœ/˜/K˜—Kšžœ¡˜6Kšœ˜—K˜Kšœžœ¡˜CKšœžœ˜Kšœ˜Kšœ*¡˜FKšœb¡!˜ƒKšœI˜IKšœ$¡˜6KšœG˜GKšœ“žœ¡˜ºKšœUžœ¡>˜›KšœM¡˜kKšœ4¡ ˜TKšœ’žœ˜™K˜K™—šœ2™2K˜—š œžœi˜ŽKšœ1žœ žœ™NK™_Kšœ Ÿœ8™GKš œ ŸœIŸœ;Ÿœ Ÿœ™¿Kš œ Ÿ œIŸœ;Ÿœ ŸœÜ™Kšœ Ÿ œV™lK™Kšœ)˜)Kšœ˜K˜ Kšœ˜K˜Kšœ.˜.šžœ ž˜šœ ˜ Kšœ˜Kšœ5˜5Kšœ&˜&Kšœ&˜&KšœGžœ˜MK˜$K˜—šœ%˜%Kšœžœ˜Kšœžœ˜ šžœžœ4žœ˜@KšœDžœ˜JKšœ˜Kšžœ˜K˜—šžœ ž˜˜ KšœI˜IKšœH˜HK˜—˜ Kšœ3˜3Kšœ2˜2K˜—Kšžœ˜—K™KšœÏv œ˜K˜K˜K˜K˜šžœžœ$žœ˜0KšœRžœ˜XKšœ˜Kšžœ˜K˜—šžœžœ˜Kšœ&˜&šžœžœ˜KšœB˜BK˜%Kšœ%˜%K•StartOfExpansion[uiData: SilKernel.SilUIData]šœ+˜+Kšœ˜—Kšžœ/˜3K˜—šžœ¡˜KšœGžœ˜NKšœ6˜6šžœžœ˜KšœB˜BK˜%Kšœ%˜%K–[uiData: SilKernel.SilUIData]šœ+˜+K˜—K˜K˜—Kšœ-˜-šžœ%žœž˜DK˜K˜ K˜ K˜ K˜ KšœT˜TKšœ6˜6Kšžœ˜—K˜š žœžœžœžœžœžœ˜bKšœ/žœ žœ žœ ˜\Kš œžœžœ žœ žœ ˜;šžœ2žœžœž˜Fšžœžœžœ˜(Kšœ˜Kšœžœ˜ Kšœh˜hšžœžœ˜Kšœ8˜8Kšœ=˜=Kšœ7˜7K˜—K˜—Kšžœ˜—šžœ3žœžœž˜Gšžœžœžœ˜(Kšœ˜Kšœžœ˜ Kšœh˜hšžœžœ˜Kšœ8˜8Kšœ=˜=Kšœ7˜7K˜—K˜—Kšžœ˜K˜—šžœž˜"Kšœ1žœžœžœ˜s—šžœ,žœžœžœ˜xK˜—K˜—Kšœ5˜5Kšœ˜—Kšžœ˜—šœ|˜|K˜—K˜K˜—š œžœf˜ˆKšœžœ™ KšœV™VK™K˜!Kšœ)˜)Kšœ˜K˜ KšžœN˜Pšžœžœžœ˜!Kšœ1žœ˜LKšžœ˜Kšœ˜—Kšžœ0žœ˜;Kšœ.˜.šžœBžœžœž˜Ušžœžœ ž˜šœ ˜ Kšœ8˜8Kšœžœ˜K˜6K˜K˜—š œžœžœžœžœžœžœ˜`Kšœžœ˜ Kšœ8˜8šœ˜šžœ"ž˜(Kšœ!žœžœ˜/—šžœ˜Kšœ!žœžœ˜1——KšœP˜PK˜#K˜#K™#K™#K˜6K˜—šœžœžœžœ˜=Kšœžœ˜ Kšœ8˜8šžœžœž˜Kšœžœ˜ Kšœžœ˜$Kšœnžœ˜tKšœqžœ˜xKšžœ˜—KšœO˜OK˜#K˜#K™#K™#K˜6K˜—Kšžœ˜—Kšžœ˜—Kšœ.¡˜GKšœ5˜5K˜K˜—šœ™K˜—š œž œi˜ˆKšœžœ™ Kšœ‡Ÿœ†ŸœŸœ ™©K™Kšœ)˜)KšžœN˜Pšžœžœžœ˜!Kšœ1žœ˜LKšžœ˜Kšœ˜—Kšžœ0žœ˜;K˜Kšœ.˜.šžœžœ ž˜Kšœ]žœ˜gKšœ\žœ˜ešœžœžœž˜Kšœ^žœ˜dKšœbžœ˜iKšœ[žœ˜aKšœ^žœ˜eKšžœ˜—Kšžœ˜—šžœžœžœ˜2Kšœ˜˜˜K˜—K˜K˜—š  œž œb˜zKšœžœ™Kšœ!™!Kšœ ŸœC™XKšœY™YK˜Kšœ)˜)Kšœ.˜.šžœ ž˜šœ žœžœžœ˜>šœ2žœ˜OKšœ˜—šžœ˜Kšœ/žœ˜6Kšœh˜hK˜——šœ žœžœžœ˜>šœ4žœ˜QK˜—šžœ˜Kšœžœ˜Kšœ/žœ˜6šžœžœžœž˜$K˜Kšžœ˜—Kšžœ žœ ˜KšœY˜YKšœ3˜3K˜——Kšžœ˜—K˜K˜—šœ™K˜—š œžœg˜ŠKšœžœ™Kšœ ŸœN œ[™¾Kšœ Ÿœ¤™µKšœ Ÿœn™~K™Kšœ)˜)Kšœ˜K˜ K˜Kšœ.˜.šžœ ž˜šœ ˜ Kšœžœ ˜.Kšœžœ ˜.šžœžœ2žœ˜>KšœCžœ˜IKšœ˜Kšžœ˜Kšœ˜—šžœžœ žœžœ˜,Kšœ-žœ˜3Kšœ/žœ˜6Kšœ˜Kšžœ˜Kšœ˜—Kšœ/žœ˜6Kšœ-˜-Kšœ0˜0KšœX˜XKšœ˜—šœ ˜ š žœ>žœžœ žœž˜~šžœBžœžœ˜NKšœ;˜;Kšœ/žœ˜6K˜—šžœ˜Kšœ,˜,Kšœ'˜'Kšœ˜Kšœ'žœ˜-Kšœ/žœ˜6Kšœ+žœ˜2KšœDžœ˜KKšœ˜K˜——šžœ˜Kšœ1žœ˜7Kšœ˜K˜——šœ ˜ Kšœ/˜/Kšœ'˜'Kšœ8žœ˜>Kšœ4žœ˜;Kšœ(žœ˜/Kšœ˜K˜—Kšžœ˜—Kšœ4˜4Kšœ|˜|K˜K˜—šœ.™.K™—š œžœ`˜zKš œBžœ žœžœžœ™yKšœ™Kšœ"Ÿœ1 œ  œ‰™÷Kšœ"Ÿœi™“Kš œŸœ¡ñÐcn¡œ £œ&™àKšœ)£œ.™]K™š œžœžœžœ˜4Kšžœžœ˜8K˜—K˜Kšœ)˜)Kšœ˜K˜ K˜K˜Kšœžœ˜8Kšœžœ˜7Kšœžœ ˜.Kšœžœ ˜.Kšœ žœ"˜2Kšœ žœ"˜2K˜Kšœ.˜.Kšœ-˜-šžœžœ2žœ˜>KšœBžœ˜HKšœ˜Kšžœ˜K˜—šžœžœžœ/žœ˜WKšœBžœ˜HKšœ˜Kšžœ˜K˜—K˜Kš¡P™PKšœ5˜5Kšœ7˜7Kšœ0˜0K˜K˜ Kšœ žœžœžœ˜MKšœžœ˜K˜šžœž˜šœ¡˜ šžœžœžœžœ˜3K™2Kšœ˜Kšœ žœ˜Kšœ.˜.Kšœ žœ˜Kšœ˜KšœA˜AK˜—šžœ˜K™5Kšœ žœ˜Kšœ˜Kšœ žœ˜Kšœ*˜*Kšœ˜KšœC˜CK˜—Kšžœ žœT˜hK˜—šœ ¡/˜˜>šœ˜KšœG˜GKšœ-˜-Kšœe˜eKšœH˜HKšœ4¡6˜jKšœ%˜%Kšœ|˜|K˜—šœ£˜£Kšœžœ˜Kšœ$˜$Kšœ ˜ Kšœ%˜%K˜—šœb˜bKšœ ˜ Kšœ%˜%Kšœžœ˜Kšœ˜—Kšžœ˜—Kšœ˜K˜—š  œžœ˜%K™æK™Kšœ)˜)Kšœ˜K˜ KšœV˜VK™>K˜šžœ ž˜šœ¢˜¢šžœ%žœ˜-Kšœžœ.˜9šžœ ž˜šœ6˜6Kšœ1˜1—šœ:˜:Kšœ4žœ¡˜TKšœ'žœ¡ ˜7Kšœ3žœ¡˜JKšœCžœ¡ ˜VKšœ-žœ˜4šž˜Kšœžœ˜ —K˜—šœ4˜4Kšžœžœ.˜K—Kšžœ˜—Kšœ$˜$Kšœ ˜ Kšœ%˜%KšžœžœAžœ˜aKšœ>žœ˜DKšœ(˜(K˜—Kšžœžœ˜$—šœ%žœ!žœ˜NKšœžœ˜$Kšœ-˜-KšœF˜FKšœb˜bKšœJ˜JKšœJ˜Jšžœ žœ žœ¡˜=Kšœ0˜0Kšœe˜eKšœH˜HKšœ|˜|K˜—šžœžœ žœ˜KšœžœZ˜dKšœžœ?žœ˜fKšžœžœ ˜Kšœ*˜*K˜—Kšœ5˜5Kšœ7˜7KšœE˜EKšœ8˜8Kšœ:˜:Kšœ:˜:Kšœ ˜ Kšœ ˜ Kšœ%˜%Kšœ6˜6K˜—šœ˜K˜6Kšœ ˜ Kšœ%˜%Kšœžœ˜K˜—šœ$¡-˜Qšžœ3žœžœž˜Fšžœ'žœ0žœ˜aKšœ8˜8Kšžœ˜——KšœD˜DKšœ ˜ Kšœ%˜%Kšœžœ˜K˜—šœ&˜&Kšœ3˜3Kšœ ˜ Kšœ%˜%Kšœžœ˜K˜—Kšžœ˜—Kšœ˜K˜—Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ)˜)Kšœ˜K˜ K˜šžœ ž˜šœ˜šžœžœžœ˜šžœžœ2žœ˜>KšœBžœ˜HKšœ˜Kšžœ˜—šžœ˜šœ-˜-K™?—š žœžœžœžœžœ0žœ˜ˆKšœ!˜!Kšœ,˜,Kšœ)˜)Kšœ@˜@KšœGžœ˜NKšœ žœ˜&Kšœ'˜'K˜—Kšžœžœ˜ K˜—K˜—šžœ˜Kšœ˜Kšœ'˜'Kšœ0™0Kšœ;˜;Kšœ;˜;Kšœ2˜2Kšœj˜jKšœ9˜9Kšœ"˜"Kšœ ˜ Kšœm˜mK˜——šœƒ˜ƒKšœm˜m—šœ¡˜¡Kšœu˜u—Kšžœ˜—K˜šžœžœž˜š žœ žœžœ žœ ž˜6šœ&˜&Kšžœ žœH˜XKšœF˜FKšœF˜FK˜—šœ˜Kšœ%žœ˜+KšœAžœ˜HK˜—šœ!˜!Kšœ#˜#šžœžœ žœ™Kšœ]™]Kšœ$™$K™—Kšœ%žœ˜+KšœAžœ˜HK˜—šœ˜Kšœžœ˜%Kšžœžœ'žœ˜GKšœ žœ˜'KšœAžœ˜HK˜—šœ"˜"Kšœ$˜$šžœžœ žœ™Kšœ]™]Kšœ$™$K™—Kšœžœ˜%Kšžœžœ'žœ˜GKšœ žœ˜'KšœAžœ˜HK˜—šœ˜Kšœ(žœ˜.KšœAžœ˜HK˜—šœ ˜ Kšœ"˜"šžœžœ žœ™Kšœ]™]Kšœ$™$K™—Kšœ(žœ˜.KšœAžœ˜HK˜—Kšžœ˜K˜—Kšœ˜Kšœ˜Kšžœ˜—Kšœ˜K˜—š  œž œb˜zKšœ™Kšœ ŸœO™^Kšœ ŸœQ™bKšœ Ÿ œ”Ÿ™­Kšœ Ÿ œdžœ;žœ–™ÒKšœ ŸœWžœžœ™K™Kšœ)˜)Kšœ˜K˜Kšœ.˜.šžœ ž˜šœ ˜ šžœžœ˜K˜6—Kšœžœ˜ šžœžœ˜K˜5—K˜—šœ ˜ šžœžœ˜K˜8—Kšœžœ˜$šžœžœ˜K˜7—K˜—šœ˜Kšœžœ˜ Kšœ žœ˜KšœX˜XKšžœžœ žœžœ˜KšœB˜BK˜—šœ ˜ KšœXžœ˜s—šœ ˜ KšœTžœ˜ešžœ žœ˜Kšœžœ^˜hKšœžœCžœ˜jKšžœžœ ˜Kšœ*˜*K˜—K˜—Kšžœ˜—K˜K™—š  œž œb˜zKšœžœ™ K™.Kšœ˜K˜Kšœžœžœ˜K˜šœ.˜.K™'—šžœ ž˜KšœRžœ˜Yšžœ1žœ˜>Kšœ˜Kšžœ˜Kšœ˜——Kšœžœ˜$Kšœ/žœ˜6Kšœžœ˜"Kšœ-¡˜Lšžœžœ ž˜ šžœ0žœžœ˜;Kšœ%˜%—Kšžœ˜—Kšœ.žœ˜5Kšœ˜K™—š œžœa˜|Kšœ™Kšœ• œ™šK™Kšœžœ˜ Kšœ˜Kšœ)˜)Kšœ˜K˜ K˜Kšœ.˜.K˜9K˜-Kšœ˜KšœE˜EKšœCžœ˜IKšœ5˜5Kšœ|˜|Kšœ˜K˜—Kšžœ˜K˜K™Ø™&Kšœ Ïrœ9™U—K™—…—žNïê