DIRECTORY Atom, BasicTime, Icons, Imager, ImagerBackdoor, ImagerColor, ImagerPath, ImagerPrivate, ImagerTransformation, InputFocus, IO, MessageWindow, MJSContainers, PopUpButtons, Process, Real, Rope, Rules, SF, TIPUser, ViewerClasses, ViewerContexts, ViewerLocks, ViewerOps, ViewerPrivate, ViewerTools; ViewerContextsImpl: CEDAR MONITOR IMPORTS Atom, Icons, Imager, ImagerBackdoor, ImagerColor, ImagerPath, ImagerPrivate, ImagerTransformation, InputFocus, IO, MessageWindow, MJSContainers, PopUpButtons, Process, Real, Rules, TIPUser, ViewerLocks, ViewerOps, ViewerPrivate, ViewerTools EXPORTS Imager, ViewerContexts = BEGIN OPEN Ctrs:MJSContainers, IT:ImagerTransformation, PUB:PopUpButtons, ViewerContexts; LORA: TYPE ~ LIST OF REF ANY; ROPE: TYPE ~ Rope.ROPE; VEC: TYPE ~ Imager.VEC; Rectangle: TYPE ~ Imager.Rectangle; Xfm: TYPE ~ IT.Transformation; PixelArray: TYPE ~ Imager.PixelArray; SampleMap: TYPE ~ Imager.SampleMap; PixelMap: TYPE ~ Imager.PixelMap; ScanMode: TYPE ~ Imager.ScanMode; Color: TYPE ~ Imager.Color; Font: TYPE ~ Imager.Font; ColorOperator: TYPE ~ Imager.ColorOperator; XStringProc: TYPE ~ Imager.XStringProc; Clipper: TYPE ~ ImagerBackdoor.Clipper; Outline: TYPE ~ ImagerPath.Outline; PathProc: TYPE ~ ImagerPath.PathProc; ViewerList: TYPE ~ LIST OF Viewer; ContextList: TYPE ~ LIST OF Context; Class: TYPE ~ REF ClassRep; ClassRep: PUBLIC TYPE ~ ImagerPrivate.ClassRep; ContextViewer: TYPE ~ REF ContextViewerPrivate; ContextViewerPrivate: PUBLIC TYPE ~ RECORD [ size: VECI, NoteClear: PROC [clientData: REF ANY], NoteChange: PROC [clientData: REF ANY, idealToViewer, viewerToScreen, viewerSize, idealSize: VECI], NoteDestruction: PROC [clientData: REF ANY], clientData: REF ANY, scrollable: BOOL, ctr, inner, rule, menuPane: Viewer ¬ NIL, sizeButton, scrollCtl: Viewer ¬ NIL, panes: ViewerList ¬ NIL, --includes menu pane menuWidth: INTEGER ¬ 0, ctxs: ContextList ¬ NIL, i2w, w2s, i2s: VECI ¬ [0, 0], --ideal to viewer, viewer to screen, ideal to screen vcs: VECI ¬ [0, 0], --viewer clip size scbKnown: BOOL ¬ FALSE, scb: BoxI ¬ [0, 0, 0, 0], --screen clip box focused: BOOL ¬ FALSE, --have input focus needClear: BOOL ¬ FALSE, --need to clear before painting wantOut: BOOL ¬ FALSE, --paint would like to exit in: BOOL ¬ FALSE, --the viewer lock is held cIn: ViewerContext ¬ NIL, --the context, if any, accessing viewer data wantIn: INTEGER ¬ 0, --how many contexts want the viewer lock to be held stayIn: StayList ¬ NIL, --other reasons to hold the viewer lock destroyed: BOOL ¬ FALSE, change: CONDITION]; ViewerContext: TYPE ~ REF ViewerContextPrivate; ViewerContextPrivate: TYPE ~ RECORD [ cv: ContextViewer, base: Context, baseClass: Class, viewToIdeal: VECI ¬ [0, 0], clipList: ClipList ¬ NIL, valid: BOOL ¬ TRUE, destroyed: BOOL ¬ FALSE]; StayList: TYPE ~ LIST OF Stay; Stay: TYPE ~ RECORD [def: StayDef, name: ROPE ¬ NIL]; StayDef: TYPE ~ RECORD [vc: ViewerContext, reason: StayReason, name: ATOM ¬ NIL, where: RectI ¬ [0, 0, 0, 0]]; StayReason: TYPE ~ {savedBuffer, doWithBuffer}; ClipList: TYPE ~ LIST OF ClipItem; ClipItem: TYPE ~ RECORD [ exclude: BOOL, shape: SELECT kind: * FROM rect => [ri: RectI], outline => [o: Outline, oddWrap: BOOL], ENDCASE]; RectI: TYPE ~ RECORD [x, y, w, h: INTEGER]; BoxI: TYPE ~ RECORD [xmin, ymin, xmax, ymax: INTEGER]; idXfm: Xfm ~ IT.Translate[[0, 0]]; msHold: INTEGER ¬ 1000; ruleHeight: INTEGER ¬ 3; tip: TIPUser.TIPTable ~ TIPUser.InstantiateNewTIPTable["ContextViewer.tip"]; icon: Icons.IconFlavor ¬ Icons.NewIconFromFile["ContextViewer.icons", 0]; ctrFlavor: ATOM ~ $ContextViewerContainer; ctrClass: Ctrs.MJSContainerClass ~ NEW [Ctrs.MJSContainerClassRep ¬ [ icon: icon]]; alignerName: PUB.Image ~ PUB.ImageForRope["Align"]; alignerClass: PUB.Class ~ PUB.MakeClass[[ proc: CVPop, choices: LIST[ [LIST[$Left, $Top]], [LIST[$Top]], [LIST[$Right, $Top]], [LIST[$Left]], [LIST[$HCenter, $VCenter]], [LIST[$Right]], [LIST[$Left, $Bottom]], [LIST[$Bottom]], [LIST[$Right, $Bottom]] ], doc: "various alignment ops"]]; menuHeight: INTEGER ¬ Real.Ceiling[alignerName.size.y]; menuSep: INTEGER ¬ menuHeight; destroyerClass: PUB.Class ~ PUB.MakeClass[[ proc: CVPop, choices: LIST[ [$Destroy] ], doc: "destroy this viewer"]]; sizeClass: PUB.Class ~ PUB.MakeClass[[ proc: CVPop, choices: LIST[[$SetSize, "Set size"], [$FitSize, "Set ideal size to current visible size"]] ]]; toScrollableClass: PUB.Class ~ PUB.MakeClass[[ proc: CVPop, choices: LIST[[$ToScrollable, "-> Scrollable"]], image: PUB.ImageForRope["-> Scrollable"] ]]; toUnscrollableClass: PUB.Class ~ PUB.MakeClass[[ proc: CVPop, choices: LIST[[$ToUnscrollable, "-> Unscrollable"]], image: PUB.ImageForRope["-> Unscrollable"] ]]; vcClass: Class ~ NEW [ClassRep ¬ [ type: $ViewerContext, Save: VCSave, Restore: VCRestore, SetInt: VCSetInt, SetReal: VCSetReal, SetT: VCSetT, SetFont: VCSetFont, SetColor: VCSetColor, SetClipper: VCSetClipper, GetInt: VCGetInt, GetReal: VCGetReal, GetT: VCGetT, GetFont: VCGetFont, GetColor: VCGetColor, GetClipper: VCGetClipper, ConcatT: VCConcatT, Scale2T: VCScale2T, RotateT: VCRotateT, TranslateT: VCTranslateT, Move: VCMove, SetXY: VCSetXY, SetXYRel: VCSetXYRel, GetCP: VCGetCP, StartUnderline: VCStartUnderline, MaskUnderline: VCMaskUnderline, CorrectMask: VCCorrectMask, CorrectSpace: VCCorrectSpace, Space: VCSpace, SetCorrectMeasure: VCSetCorrectMeasure, SetCorrectTolerance: VCSetCorrectTolerance, Correct: VCCorrect, DontCorrect: VCDontCorrect, SetGray: VCSetGray, SetSampledColor: VCSetSampledColor, SetSampledBlack: VCSetSampledBlack, Clip: VCClip, ClipRectangle: VCClipRectangle, ClipRectangleI: VCClipRectangleI, Show: VCShow, ShowBackward: VCShowBackward, MaskFill: VCMaskFill, MaskRectangle: VCMaskRectangle, MaskStroke: VCMaskStroke, MaskPixel: VCMaskPixel, ShowAndFixedXRel: VCShowAndFixedXRel, ShowText: VCShowText, MaskRectangleI: VCMaskRectangleI, MaskVector: VCMaskVector, MaskDashedStroke: VCMaskDashedStroke, MaskBitmap: VCMaskBitmap, DrawBitmap: VCDrawBitmap, DrawPixels: VCDrawPixels, DoIfVisible: VCDoIfVisible, DoWithBuffer: VCDoWithBuffer, DrawObject: VCDrawObject, GetBounds: VCGetBounds, ViewReset: VCViewReset, ViewTranslateI: VCViewTranslateI, ViewClip: VCViewClip, ViewClipRectangleI: VCViewClipRectangleI, GetTransformation: VCGetTransformation, Transform: ImagerPrivate.DefaultTransform, MoveViewRectangle: VCMoveViewRectangle, TestViewRectangle: VCTestViewRectangle, GetBufferColorOperator: VCGetBufferColorOperator, AccessBuffer: ImagerPrivate.DefaultAccessBuffer, SaveBuffer: VCSaveBuffer, RestoreBuffer: VCRestoreBuffer, DiscardBuffer: VCDiscardBuffer, propList: NIL]]; Create: PUBLIC PROC [viewerInit: ViewerClasses.ViewerRec, size: VECI, NoteClear: PROC [clientData: REF ANY] ¬ NIL, NoteChange: PROC [clientData: REF ANY, idealToViewer, viewerToScreen, viewerSize, idealSize: VECI] ¬ NIL, NoteDestruction: PROC [clientData: REF ANY] ¬ NIL, clientData: REF ANY ¬ NIL] RETURNS [cv: ContextViewer] ~ { unique: REF ROPE ~ NEW [ROPE ¬ "Another Context Viewer Class"]; ua: CARD ~ LOOPHOLE[unique]; cvClass: ViewerClasses.ViewerClass ~ NEW [ViewerClasses.ViewerClassRec ¬ [ flavor: Atom.MakeAtom[IO.PutFR1["ContextViewer[%g]", [cardinal[ua]] ]], notify: Notify, paint: Paint, modify: CVModify, destroy: CVDestroy, scroll: Scroll, hscroll: HScroll, tipTable: tip, icon: icon, props: NIL]]; innerScroll: RECORD [x, y: BOOL] ~ [viewerInit.hscrollable, viewerInit.scrollable]; ViewerOps.RegisterViewerClass[cvClass.flavor, cvClass]; cv ¬ NEW [ContextViewerPrivate ¬ [size, NoteClear, NoteChange, NoteDestruction, clientData, viewerInit.scrollable]]; TRUSTED {Process.InitializeCondition[@cv.change, Process.MsecToTicks[5000]]; Process.EnableAborts[@cv.change]}; viewerInit.hscrollable ¬ viewerInit.scrollable ¬ FALSE; viewerInit.data ¬ cv; cv.ctr ¬ Ctrs.Create[ctrFlavor, viewerInit]; cv.menuPane ¬ CreateMenuPane[cv]; Ctrs.ChildXBound[cv.ctr, cv.menuPane]; cv.panes ¬ LIST[cv.menuPane]; cv.rule ¬ Rules.Create[[name: "the rule", parent: cv.ctr, wy: cv.menuPane.wh, ww: cv.ctr.cw, wh: ruleHeight]]; Ctrs.ChildXBound[cv.ctr, cv.rule]; cv.inner ¬ ViewerOps.CreateViewer[cvClass.flavor, [wy: cv.menuPane.wh+1, ww: cv.ctr.cw, wh: cv.ctr.ch-cv.menuPane.wh-1, name: "inner", scrollable: TRUE, hscrollable: TRUE, border: FALSE, parent: cv.ctr, data: cv]]; Ctrs.ChildXBound[cv.ctr, cv.inner]; Ctrs.ChildYBound[cv.ctr, cv.inner]; TRUSTED {Process.Detach[FORK PaintDriver[cv]]}; RETURN}; QuaViewer: PUBLIC PROC [cv: ContextViewer, which: WhichViewer] RETURNS [Viewer] ~ { SELECT which FROM inner => RETURN [cv.inner]; outer => RETURN [cv.ctr]; ENDCASE => ERROR}; QuaContextViewer: PUBLIC PROC [v: Viewer] RETURNS [MaybeContextViewer] ~ { IF v.class.flavor = ctrFlavor THEN RETURN [[TRUE, NARROW[Ctrs.GetClientData[v], ContextViewer]]]; WITH v.data SELECT FROM x: ContextViewer => RETURN [[TRUE, x]]; ENDCASE => NULL; RETURN [[FALSE, NIL]]}; DoWithInfo: PUBLIC PROC [cv: ContextViewer, With: PROC [idealToViewer, viewerToScreen, viewerSize, idealSize: VECI, destroyed: BOOL]] ~ { XfmsWithLock: PROC ~ { With[cv.i2w, cv.w2s, [cv.inner.cw, cv.inner.ch], cv.size, cv.destroyed OR cv.ctr.destroyed]; RETURN}; ViewerLocks.CallUnderWriteLock[XfmsWithLock, cv.inner]; RETURN}; SetIdealSize: PUBLIC PROC [cv: ContextViewer, size: VECI] ~ { SetIdealSizeWithLock: ENTRY PROC ~ { ENABLE UNWIND => NULL; cv.size ¬ size; PUB.AmbushInstance[button: cv.sizeButton, image: ImageForSize[cv.size], specImage: TRUE]; IF cv.NoteChange#NIL THEN cv.NoteChange[cv.clientData, cv.i2w, cv.w2s, cv.vcs, cv.size]; RETURN}; ViewerLocks.CallUnderWriteLock[SetIdealSizeWithLock, cv.sizeButton]; RETURN}; GetMenuPane: PUBLIC PROC [cv: ContextViewer] RETURNS [Viewer] ~ {RETURN [cv.menuPane]}; AddMenuElt: PUBLIC PROC [cv: ContextViewer, elt: Viewer, paint: BOOL] ~ { AddEltWithLock: PROC ~ { ViewerOps.EstablishViewerPosition[elt, cv.menuWidth+menuSep, 0, elt.ww, elt.wh]; cv.menuWidth ¬ cv.menuWidth + menuSep + elt.ww; IF elt.wh > cv.menuPane.ch THEN { ViewerOps.EstablishViewerPosition[cv.menuPane, 0, cv.menuPane.wy, cv.menuPane.ww, elt.wh]; Reposition[cv, paint]} ELSE IF paint THEN ViewerOps.PaintViewer[elt, all, TRUE]; RETURN}; ViewerLocks.CallUnderWriteLock[AddEltWithLock, cv.ctr]; RETURN}; AddPane: PUBLIC PROC [cv: ContextViewer, pane: Viewer, above, paint: BOOL] ~ { AddWithLock: PROC ~ { IF above THEN cv.panes ¬ CONS[pane, cv.panes] ELSE {last: ViewerList ¬ cv.panes; WHILE last.rest#NIL DO last ¬ last.rest ENDLOOP; last.rest ¬ LIST[pane]}; Ctrs.ChildXBound[cv.ctr, pane]; Reposition[cv, paint]; RETURN}; ViewerLocks.CallUnderWriteLock[AddWithLock, cv.ctr]; RETURN}; DeletePane: PUBLIC PROC [cv: ContextViewer, pane: Viewer, paint: BOOL] ~ { err: BOOL ¬ FALSE; DeleteWithLock: PROC ~ { last: ViewerList ¬ NIL; FOR pl: ViewerList ¬ cv.panes, pl.rest WHILE pl#NIL DO IF pl.first=pane THEN { IF last=NIL THEN cv.panes ¬ pl.rest ELSE last.rest ¬ pl.rest; ViewerOps.DestroyViewer[pane, FALSE]; Reposition[cv, paint]; RETURN}; ENDLOOP; err ¬ TRUE}; IF pane = cv.menuPane THEN ERROR; ViewerLocks.CallUnderWriteLock[DeleteWithLock, cv.ctr]; IF err THEN ERROR; RETURN}; Reposition: PROC [cv: ContextViewer, paint: BOOL] ~ { y: INTEGER ¬ 0; FOR pl: ViewerList ¬ cv.panes, pl.rest WHILE pl#NIL DO ViewerOps.EstablishViewerPosition[pl.first, 0, y, cv.ctr.cw, pl.first.wh]; y ¬ y + pl.first.wh; ENDLOOP; ViewerOps.EstablishViewerPosition[cv.rule, 0, y, cv.ctr.cw, ruleHeight]; ViewerOps.EstablishViewerPosition[cv.inner, 0, y+ruleHeight, cv.ctr.cw, cv.ctr.ch-y-ruleHeight]; IF paint THEN ViewerOps.PaintViewer[cv.ctr, client, TRUE]; RETURN}; CreateContext: PUBLIC PROC [cv: ContextViewer] RETURNS [ctx: Context] ~ { base: Context ~ ViewerPrivate.CreateContext[ViewerPrivate.Screen.FIRST]; vc: ViewerContext ~ NEW [ViewerContextPrivate ¬ [cv, base, base.class]]; IF NOT cv.scbKnown THEN { br: Rectangle ~ ImagerBackdoor.GetBounds[base]; cv.scb ¬ [Real.Ceiling[br.x], Real.Ceiling[br.y], Real.Floor[br.x+br.w], Real.Floor[br.y+br.h]]; cv.scbKnown ¬ TRUE}; ctx ¬ NEW [Imager.ContextRep ¬ [class: vcClass, state: NIL, data: vc]]; cv.ctxs ¬ CONS[ctx, cv.ctxs]; RETURN}; QuaViewerContext: PUBLIC PROC [c: Context] RETURNS [MaybeContextViewer] ~ { IF c.class=vcClass AND c.data#NIL THEN WITH c.data SELECT FROM x: ViewerContext => RETURN [[TRUE, x.cv]]; ENDCASE => NULL; RETURN [[FALSE, NIL]]}; SetCursor: PUBLIC PROC [cv: ContextViewer, ct: ViewerClasses.CursorType] ~ { cv.inner.class.cursor ¬ ct; RETURN}; CVDestroy: PROC [self: Viewer] --ViewerClasses.DestroyProc-- ~ { cv: ContextViewer ~ NARROW[self.data]; Destroy[cv]; RETURN}; Destroy: PUBLIC PROC [cv: ContextViewer] ~ { IF NOT cv.destroyed THEN { cv.destroyed ¬ TRUE; IF NOT cv.ctr.destroyed THEN TRUSTED {Process.Detach[FORK ViewerOps.DestroyViewer[cv.ctr]]}; IF cv.NoteDestruction#NIL THEN cv.NoteDestruction[cv.clientData]; }; RETURN}; CreateMenuPane: PROC [cv: ContextViewer] RETURNS [menuPane: Viewer] ~ { aligner, destroyer: Viewer; menuPane ¬ Ctrs.Create[$VanillaMJSContainer, [parent: cv.ctr, ww: cv.ctr.cw, wh: menuHeight, border: FALSE, scrollable: FALSE], FALSE]; aligner ¬ alignerClass.Instantiate[viewerInfo: [parent: menuPane, name: "Align", border: FALSE], instanceData: cv, paint: FALSE]; destroyer ¬ destroyerClass.Instantiate[viewerInfo: [parent: menuPane, name: "Destroy", wx: aligner.ww+menuSep, border: FALSE], instanceData: cv, paint: FALSE]; cv.sizeButton ¬ sizeClass.Instantiate[viewerInfo: [parent: menuPane, name: "Size", wx: destroyer.wx+destroyer.ww+menuSep, border: FALSE], instanceData: cv, image: ImageForSize[cv.size], paint: FALSE]; cv.scrollCtl ¬ (IF cv.scrollable THEN toUnscrollableClass ELSE toScrollableClass).Instantiate[viewerInfo: [parent: menuPane, wx: cv.sizeButton.wx+cv.sizeButton.ww+menuSep, border: FALSE], instanceData: cv, paint: FALSE]; cv.menuWidth ¬ cv.scrollCtl.wx + cv.scrollCtl.ww; RETURN}; ImageForSize: PROC [size: VECI] RETURNS [PUB.Image] ~ {RETURN PUB.ImageForRope[IO.PutFR["Size: [w: %g, h: %g]", [integer[size.x]], [integer[size.y]] ]]}; CVPop: PROC [view, instanceData, classData, key: REF ANY] --PUB.PopUpButtonProc-- ~ { cv: ContextViewer ~ NARROW[instanceData]; WITH key SELECT FROM a: ATOM => SELECT a FROM $Destroy => Destroy[cv]; $SetSize => { seln: ROPE ~ ViewerTools.GetSelectionContents[]; in: IO.STREAM ~ IO.RIS[seln]; newSize: RECORD [x, y: INT] ¬ [0, 0]; {ENABLE IO.Error, IO.EndOfStream => GOTO Bitch; newSize.x ¬ in.GetInt[]; newSize.y ¬ in.GetInt[]; IF NOT (newSize.x IN [5..5000] AND newSize.y IN [5..5000] ) THEN GOTO Bitch; EXITS Bitch => { MessageWindow.Append["Selection should be two whitespace-separated integers (of reasonable value)", TRUE]; RETURN}; }; in.Close[]; SetIdealSize[cv, [newSize.x, newSize.y]]; }; $FitSize => { SetIdealSize[cv, [cv.inner.cw, cv.inner.ch]]; }; $ToScrollable => { cv.scrollable ¬ TRUE; PUB.AmbushInstance[cv.scrollCtl, toUnscrollableClass]}; $ToUnscrollable => { cv.scrollable ¬ FALSE; PUB.AmbushInstance[cv.scrollCtl, toScrollableClass]}; ENDCASE => ERROR; lora: LORA => { h, v: REAL ¬ -1.0; Alignit: PROC ~ { IF h>=0.0 THEN cv.i2w.x ¬ Real.Round[h * (cv.vcs.x-cv.size.x)]; IF v>=0.0 THEN cv.i2w.y ¬ Real.Round[v * (cv.vcs.y-cv.size.y)]; cv.i2s ¬ ViAdd[cv.i2w, cv.w2s]; cv.needClear ¬ TRUE; IF cv.NoteChange#NIL THEN cv.NoteChange[cv.clientData, cv.i2w, cv.w2s, cv.vcs, cv.size]; InvalidateEm[cv]; RETURN}; FOR l: LORA ¬ lora, l.rest WHILE l#NIL DO SELECT l.first FROM $Left => h ¬ 0.0; $HCenter => h ¬ 0.5; $Right => h ¬ 1.0; $Bottom => v ¬ 0.0; $VCenter => v ¬ 0.5; $Top => v ¬ 1.0; ENDCASE => ERROR; ENDLOOP; ViewerLocks.CallUnderWriteLock[Alignit, cv.inner]; RETURN}; ENDCASE => ERROR; }; NestedEnter: ERROR ~ CODE; Enter: PROC [vc: ViewerContext] ~ { cv: ContextViewer ~ vc.cv; destroy: BOOL ¬ FALSE; GetIn: ENTRY PROC [cv: ContextViewer] ~ { ENABLE UNWIND => NULL; IF cv.in AND cv.cIn=vc THEN RETURN WITH ERROR NestedEnter; cv.wantIn ¬ cv.wantIn.SUCC; Wait[]; cv.cIn ¬ vc; RETURN}; Wait: INTERNAL PROC ~ { ENABLE UNWIND => cv.wantIn ¬ cv.wantIn.PRED; BROADCAST cv.change; UNTIL cv.destroyed OR cv.ctr.destroyed OR cv.in AND cv.cIn=NIL AND (cv.stayIn#NIL OR NOT cv.wantOut) DO WAIT cv.change; ENDLOOP; destroy ¬ cv.destroyed OR cv.ctr.destroyed; RETURN}; GetIn[cv]; IF destroy AND NOT vc.destroyed THEN {vc.destroyed ¬ TRUE; vc.base.SetNoImage[TRUE]}; IF NOT vc.valid THEN { xmin: INTEGER ~ MAX[cv.w2s.x, cv.i2s.x]; ymin: INTEGER ~ MAX[cv.w2s.y, cv.i2s.y]; xmax: INTEGER ~ MIN[cv.w2s.x+cv.vcs.x, cv.i2s.x+cv.size.x]; ymax: INTEGER ~ MIN[cv.w2s.y+cv.vcs.y, cv.i2s.y+cv.size.y]; cp: VEC ~ vc.baseClass.GetCP[vc.base, FALSE]; ImagerBackdoor.ViewReset[vc.base]; ImagerBackdoor.ViewClipRectangleI[vc.base, xmin, ymin, MAX[xmax-xmin, 0], MAX[ymax-ymin, 0]]; ImagerBackdoor.ViewTranslateI[vc.base, cv.i2s.x, cv.i2s.y]; FOR cr: ClipList ¬ vc.clipList, cr.rest WHILE cr#NIL DO WITH cr.first SELECT FROM q: rect ClipItem => vc.baseClass.ViewClipRectangleI[vc.base, q.ri.x, q.ri.y, q.ri.w, q.ri.h, cr.first.exclude]; q: outline ClipItem => { ClipPath: ImagerPath.PathProc ~ { ImagerPath.MapOutline[q.o, moveTo, lineTo, curveTo, conicTo, arcTo]; RETURN}; vc.baseClass.ViewClip[vc.base, ClipPath, q.oddWrap, cr.first.exclude]}; ENDCASE => ERROR; ENDLOOP; ImagerBackdoor.ViewTranslateI[vc.base, vc.viewToIdeal.x, vc.viewToIdeal.y]; vc.baseClass.SetXY[vc.base, cp]; vc.valid ¬ TRUE}; RETURN}; Exit: ENTRY PROC [vc: ViewerContext] ~ { ENABLE UNWIND => NULL; IF vc.cv.cIn # vc THEN ERROR; vc.cv.wantIn ¬ vc.cv.wantIn.PRED; vc.cv.cIn ¬ NIL; BROADCAST vc.cv.change; RETURN}; PaintDriver: PROC [cv: ContextViewer] ~ { Test: ENTRY PROC RETURNS [BOOL] ~ { ENABLE UNWIND => NULL; UNTIL cv.destroyed OR cv.ctr.destroyed OR (cv.needClear OR cv.wantIn>0) AND NOT cv.ctr.iconic DO WAIT cv.change ENDLOOP; RETURN [cv.destroyed OR cv.ctr.destroyed]}; exit: BOOL; DO ENABLE ABORTED => CONTINUE; exit ¬ Test[]; IF exit THEN EXIT; ViewerOps.PaintViewer[cv.inner, client, FALSE]; ENDLOOP; RETURN}; Paint: ENTRY PROC [self: Viewer, context: Context, whatChanged: REF, clear: BOOL] RETURNS [quit: BOOL ¬ FALSE] --ViewerClasses.PaintProc-- ~ { ENABLE UNWIND => {cv: ContextViewer ~ NARROW[self.data]; cv.wantOut ¬ cv.in ¬ FALSE}; cv: ContextViewer ~ NARROW[self.data]; wts: VECI; IF self.destroyed THEN RETURN; IF cv.needClear AND NOT clear THEN { context.SetColor[Imager.white]; context.MaskRectangleI[0, 0, self.cw, self.ch]; clear ¬ TRUE}; IF clear THEN { cv.needClear ¬ FALSE; IF cv.NoteClear#NIL THEN cv.NoteClear[cv.clientData]}; [wts.x, wts.y] ¬ ViewerOps.UserToScreenCoords[self, 0, 0]; IF cv.w2s#wts OR cv.vcs#[self.cw, self.ch] THEN { cv.w2s ¬ wts; cv.i2s ¬ ViAdd[cv.i2w, cv.w2s]; cv.vcs ¬ [self.cw, self.ch]; IF cv.NoteChange#NIL THEN cv.NoteChange[cv.clientData, cv.i2w, cv.w2s, cv.vcs, cv.size]; InvalidateEm[cv]}; IF cv.wantIn>0 THEN TRUSTED { hold: CONDITION; Process.InitializeCondition[@hold, Process.MsecToTicks[msHold]]; Process.EnableAborts[@hold]; cv.in ¬ TRUE; BROADCAST cv.change; WAIT hold; cv.wantOut ¬ TRUE; UNTIL cv.destroyed OR cv.cIn=NIL AND cv.stayIn=NIL DO WAIT cv.change ENDLOOP; cv.wantOut ¬ cv.in ¬ FALSE}; RETURN}; Scroll: PROC [self: Viewer, op: ViewerClasses.ScrollOp, amount: INTEGER, shift, control: BOOL ¬ FALSE] RETURNS [top, bottom: INTEGER ¬ LAST[INTEGER]] --ViewerClasses.ScrollProc-- ~ { cv: ContextViewer ~ NARROW[self.data]; UpdateY: PROC ~ { cv.i2s ¬ ViAdd[cv.i2w, cv.w2s]; cv.needClear ¬ TRUE; IF cv.NoteChange#NIL THEN cv.NoteChange[cv.clientData, cv.i2w, cv.w2s, cv.vcs, cv.size]; InvalidateEm[cv]; RETURN}; IF op#query AND NOT cv.scrollable THEN { MessageWindow.Append["This viewer is not currently scrollable.", TRUE]; RETURN}; SELECT op FROM query => { botr: REAL ~ REAL[cv.size.y+cv.i2w.y]/cv.size.y; topr: REAL ~ REAL[cv.size.y+cv.i2w.y-cv.vcs.y]/cv.size.y; RETURN [MIN[MAX[Real.Round[topr*100.0], 0], 100], MIN[MAX[Real.Round[botr*100.0], 0], 100] ]}; up, down => cv.i2w.y ¬ cv.i2w.y + amount * (IF op=up THEN 1 ELSE -1); thumb => cv.i2w.y ¬ Real.Round[(amount/100.0 - 1.0)*cv.size.y] + cv.vcs.y; ENDCASE => ERROR; ViewerLocks.CallUnderWriteLock[UpdateY, self]; RETURN}; HScroll: PROC [self: Viewer, op: ViewerClasses.HScrollOp, amount: INTEGER, shift, control: BOOL ¬ FALSE] RETURNS [left, right: INTEGER ¬ LAST[INTEGER]] --ViewerClasses.HScrollProc-- ~ { cv: ContextViewer ~ NARROW[self.data]; UpdateX: PROC ~ { cv.i2s ¬ ViAdd[cv.i2w, cv.w2s]; cv.needClear ¬ TRUE; IF cv.NoteChange#NIL THEN cv.NoteChange[cv.clientData, cv.i2w, cv.w2s, cv.vcs, cv.size]; InvalidateEm[cv]; RETURN}; IF op#query AND NOT cv.scrollable THEN { MessageWindow.Append["This viewer is not currently scrollable.", TRUE]; RETURN}; SELECT op FROM query => { leftr: REAL ~ REAL[-cv.i2w.x]/cv.size.x; rightr: REAL ~ REAL[cv.vcs.x-cv.i2w.x]/cv.size.x; RETURN [MIN[MAX[Real.Round[leftr*100.0], 0], 100], MIN[MAX[Real.Round[rightr*100.0], 0], 100] ]}; left, right => cv.i2w.x ¬ cv.i2w.x + amount * (IF op=right THEN 1 ELSE -1); thumb => cv.i2w.x ¬ Real.Round[(-amount/100.0)*cv.size.y]; ENDCASE => ERROR; ViewerLocks.CallUnderWriteLock[UpdateX, self]; RETURN}; InvalidateEm: --Viewer INTERNAL-- PROC [cv: ContextViewer] ~ { cv.in ¬ cv.in; FOR cl: ContextList ¬ cv.ctxs, cl.rest WHILE cl#NIL DO vc: ViewerContext ~ NARROW[cl.first.data]; vc.valid ¬ FALSE; ENDLOOP; cv.ctxs ¬ NIL; RETURN}; Notify: ViewerClasses.NotifyProc ~ { cv: ContextViewer ~ NARROW[self.data]; IF NOT cv.focused THEN InputFocus.SetInputFocus[self]; RETURN}; CVModify: PROC [self: Viewer, change: ViewerClasses.ModifyAction] ~ { cv: ContextViewer ~ NARROW[self.data]; SELECT change FROM set, pop => cv.focused ¬ TRUE; kill, push => cv.focused ¬ FALSE; ENDCASE => ERROR; RETURN}; VCSave: PROC [context: Context, all: BOOL] RETURNS [REF] ~ { vc: ViewerContext ~ NARROW[context.data]; ans: REF; Enter[vc]; {ENABLE UNWIND => Exit[vc]; ans ¬ vc.baseClass.Save[vc.base, all]}; Exit[vc]; RETURN [ans]}; VCRestore: PROC [context: Context, ref: REF] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.Restore[vc.base, ref]}; Exit[vc]; RETURN}; VCSetInt: PROC [context: Context, key: ImagerBackdoor.IntKey, val: INT] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetInt[vc.base, key, val]}; Exit[vc]; RETURN}; VCSetReal: PROC [context: Context, key: ImagerBackdoor.RealKey, val: REAL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetReal[vc.base, key, val]}; Exit[vc]; RETURN}; VCSetT: PROC [context: Context, m: Xfm] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetT[vc.base, m]}; Exit[vc]; RETURN}; VCSetFont: PROC [context: Context, font: Imager.Font] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetFont[vc.base, font]}; Exit[vc]; RETURN}; VCSetColor: PROC [context: Context, color: Imager.Color] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetColor[vc.base, color]}; Exit[vc]; RETURN}; VCSetClipper: PROC [context: Context, clipper: ImagerBackdoor.Clipper] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetClipper[vc.base, clipper]}; Exit[vc]; RETURN}; VCGetInt: PROC [context: Context, key: ImagerBackdoor.IntKey] RETURNS [INT] ~ { vc: ViewerContext ~ NARROW[context.data]; ans: INT; Enter[vc]; {ENABLE UNWIND => Exit[vc]; ans ¬ vc.baseClass.GetInt[vc.base, key]}; Exit[vc]; RETURN [ans]}; VCGetReal: PROC [context: Context, key: ImagerBackdoor.RealKey] RETURNS [REAL] ~ { vc: ViewerContext ~ NARROW[context.data]; ans: REAL; Enter[vc]; {ENABLE UNWIND => Exit[vc]; ans ¬ vc.baseClass.GetReal[vc.base, key]}; Exit[vc]; RETURN [ans]}; VCGetT: PROC [context: Context] RETURNS [Xfm] ~ { vc: ViewerContext ~ NARROW[context.data]; ans: Xfm; Enter[vc]; {ENABLE UNWIND => Exit[vc]; ans ¬ vc.baseClass.GetT[vc.base]}; Exit[vc]; RETURN [ans]}; VCGetFont: PROC [context: Context] RETURNS [Imager.Font] ~ { vc: ViewerContext ~ NARROW[context.data]; ans: Imager.Font; Enter[vc]; {ENABLE UNWIND => Exit[vc]; ans ¬ vc.baseClass.GetFont[vc.base]}; Exit[vc]; RETURN [ans]}; VCGetColor: PROC [context: Context] RETURNS [Imager.Color] ~ { vc: ViewerContext ~ NARROW[context.data]; ans: Imager.Color; Enter[vc]; {ENABLE UNWIND => Exit[vc]; ans ¬ vc.baseClass.GetColor[vc.base]}; Exit[vc]; RETURN [ans]}; VCGetClipper: PROC [context: Context] RETURNS [ImagerBackdoor.Clipper] ~ { vc: ViewerContext ~ NARROW[context.data]; ans: ImagerBackdoor.Clipper; Enter[vc]; {ENABLE UNWIND => Exit[vc]; ans ¬ vc.baseClass.GetClipper[vc.base]}; Exit[vc]; RETURN [ans]}; VCConcatT: PROC [context: Context, m: Xfm] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.ConcatT[vc.base, m]}; Exit[vc]; RETURN}; VCScale2T: PROC [context: Context, s: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.Scale2T[vc.base, s]}; Exit[vc]; RETURN}; VCRotateT: PROC [context: Context, a: REAL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.RotateT[vc.base, a]}; Exit[vc]; RETURN}; VCTranslateT: PROC [context: Context, t: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.TranslateT[vc.base, t]}; Exit[vc]; RETURN}; VCMove: PROC [context: Context, rounded: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.Move[vc.base, rounded]}; Exit[vc]; RETURN}; VCSetXY: PROC [context: Context, p: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetXY[vc.base, p]}; Exit[vc]; RETURN}; VCSetXYRel: PROC [context: Context, v: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetXYRel[vc.base, v]}; Exit[vc]; RETURN}; VCGetCP: PROC [context: Context, rounded: BOOL] RETURNS [ans: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; ans ¬ vc.baseClass.GetCP[vc.base, rounded]}; Exit[vc]; RETURN}; VCStartUnderline: PROC [context: Context] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.StartUnderline[vc.base]}; Exit[vc]; RETURN}; VCMaskUnderline: PROC [context: Context, dy, h: REAL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.MaskUnderline[vc.base, dy, h]}; Exit[vc]; RETURN}; VCCorrectMask: PROC [context: Context] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.CorrectMask[vc.base]}; Exit[vc]; RETURN}; VCCorrectSpace: PROC [context: Context, v: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.CorrectSpace[vc.base, v]}; Exit[vc]; RETURN}; VCSpace: PROC [context: Context, x: REAL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.Space[vc.base, x]}; Exit[vc]; RETURN}; VCSetCorrectMeasure: PROC [context: Context, v: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetCorrectMeasure[vc.base, v]}; Exit[vc]; RETURN}; VCSetCorrectTolerance: PROC [context: Context, v: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetCorrectTolerance[vc.base, v]}; Exit[vc]; RETURN}; VCCorrect: PROC [context: Context, action: PROC] ~ { vc: ViewerContext ~ NARROW[context.data]; vc.baseClass.Correct[vc.base, action]; RETURN}; VCDontCorrect: PROC [context: Context, action: PROC, saveCP: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; IF saveCP THEN { cp: VEC; Enter[vc]; {ENABLE UNWIND => Exit[vc]; cp ¬ vc.baseClass.GetCP[vc.base, FALSE]}; Exit[vc]; vc.baseClass.DontCorrect[vc.base, action, saveCP]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetXY[vc.base, cp]}; Exit[vc]} ELSE vc.baseClass.DontCorrect[vc.base, action, saveCP]; RETURN}; VCSetGray: PROC [context: Context, f: REAL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetGray[vc.base, f]}; Exit[vc]; RETURN}; VCSetSampledColor: PROC [context: Context, pa: PixelArray, m: Xfm, colorOperator: ColorOperator] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetSampledColor[vc.base, pa, m, colorOperator]}; Exit[vc]; RETURN}; VCSetSampledBlack: PROC [context: Context, pa: PixelArray, m: Xfm, clear: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.SetSampledBlack[vc.base, pa, m, clear]}; Exit[vc]; RETURN}; VCClip: PROC [context: Context, path: PathProc, oddWrap: BOOL, exclude: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.Clip[vc.base, path, oddWrap, exclude]}; Exit[vc]; RETURN}; VCClipRectangle: PROC [context: Context, r: Imager.Rectangle, exclude: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.ClipRectangle[vc.base, r, exclude]}; Exit[vc]; RETURN}; VCClipRectangleI: PROC [context: Context, x, y, w, h: INTEGER, exclude: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.ClipRectangleI[vc.base, x, y, w, h, exclude]}; Exit[vc]; RETURN}; VCShow: PROC [context: Context, string: XStringProc, xrel: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.Show[vc.base, string, xrel]}; Exit[vc]; RETURN}; VCShowBackward: PROC [context: Context, string: XStringProc] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.ShowBackward[vc.base, string]}; Exit[vc]; RETURN}; VCMaskFill: PROC [context: Context, path: PathProc, oddWrap: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.MaskFill[vc.base, path, oddWrap]}; Exit[vc]; RETURN}; VCMaskRectangle: PROC [context: Context, r: Imager.Rectangle] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.MaskRectangle[vc.base, r]}; Exit[vc]; RETURN}; VCMaskStroke: PROC [context: Context, path: PathProc, closed: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.MaskStroke[vc.base, path, closed]}; Exit[vc]; RETURN}; VCMaskPixel: PROC [context: Context, pa: PixelArray] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.MaskPixel[vc.base, pa]}; Exit[vc]; RETURN}; VCShowAndFixedXRel: PROC [context: Context, string: XStringProc, x: REAL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.ShowAndFixedXRel[vc.base, string, x]}; Exit[vc]; RETURN}; VCShowText: PROC [context: Context, text: REF READONLY TEXT, start, len: NAT, xrel: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.ShowText[vc.base, text, start, len, xrel]}; Exit[vc]; RETURN}; VCMaskRectangleI: PROC [context: Context, x, y, w, h: INTEGER] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.MaskRectangleI[vc.base, x, y, w, h]}; Exit[vc]; RETURN}; VCMaskVector: PROC [context: Context, p1, p2: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.MaskVector[vc.base, p1, p2]}; Exit[vc]; RETURN}; VCMaskDashedStroke: PROC [context: Context, path: PathProc, patternLen: NAT, pattern: PROC [NAT] RETURNS [REAL], offset, length: REAL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.MaskDashedStroke[vc.base, path, patternLen, pattern, offset, length]}; Exit[vc]; RETURN}; VCMaskBitmap: PROC [context: Context, bitmap: SampleMap, referencePoint: SF.Vec, scanMode: ScanMode, position: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.MaskBitmap[vc.base, bitmap, referencePoint, scanMode, position]}; Exit[vc]; RETURN}; VCDrawBitmap: PROC [context: Context, bitmap: SampleMap, referencePoint: SF.Vec, scanMode: ScanMode, position: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.DrawBitmap[vc.base, bitmap, referencePoint, scanMode, position]}; Exit[vc]; RETURN}; VCDrawPixels: PROC [context: Context, pixelMap: PixelMap, colorOperator: ColorOperator, referencePoint: SF.Vec, scanMode: ScanMode, position: VEC] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.DrawPixels[vc.base, pixelMap, colorOperator, referencePoint, scanMode, position]}; Exit[vc]; RETURN}; VCDoIfVisible: PROC [context: Context, r: Rectangle, action: PROC] ~ { vc: ViewerContext ~ NARROW[context.data]; vc.baseClass.DoIfVisible[vc.base, r, action]; RETURN}; VCDoWithBuffer: PROC [context: Context, action: PROC, x, y, w, h: INTEGER, backgroundColor: Color] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; AddStay[vc.cv, [vc, doWithBuffer, NIL, [x, y, w, h]]]}; Exit[vc]; vc.baseClass.DoWithBuffer[vc.base, action, x, y, w, h, backgroundColor]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; RemStay[vc.cv, [vc, doWithBuffer, NIL, [x, y, w, h]]]}; Exit[vc]; RETURN}; VCDrawObject: PROC [context: Context, object: Imager.Object, position: VEC, interactive: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.DrawObject[vc.base, object, position, interactive]}; Exit[vc]; RETURN}; VCGetBounds: PROC [context: Context] RETURNS [Rectangle] ~ { vc: ViewerContext ~ NARROW[context.data]; RETURN vc.baseClass.GetBounds[vc.base]}; VCViewReset: PROC [context: Context] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.viewToIdeal ¬ [0, 0]; vc.clipList ¬ NIL; vc.valid ¬ FALSE}; Exit[vc]; RETURN}; VCViewTranslateI: PROC [context: Context, x, y: INTEGER] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; cp: VEC ~ vc.baseClass.GetCP[vc.base, FALSE]; vc.viewToIdeal ¬ ViAdd[vc.viewToIdeal, [x, y]]; vc.baseClass.ViewTranslateI[vc.base, x, y]; vc.baseClass.SetXY[vc.base, cp]}; Exit[vc]; RETURN}; VCViewClip: PROC [context: Context, path: PathProc, oddWrap: BOOL, exclude: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; m: Xfm ~ IT.Translate[[vc.viewToIdeal.x, vc.viewToIdeal.y]]; o: Outline ~ ImagerPath.OutlineFromPath[path, oddWrap, m]; vc.clipList ¬ CONS[[exclude, outline[o, oddWrap]], vc.clipList]; vc.baseClass.ViewClip[vc.base, path, oddWrap, exclude]}; Exit[vc]; RETURN}; VCViewClipRectangleI: PROC [context: Context, x, y, w, h: INTEGER, exclude: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.clipList ¬ CONS[[exclude, rect[[x+vc.viewToIdeal.x, y+vc.viewToIdeal.y, w, h]]], vc.clipList]; vc.baseClass.ViewClipRectangleI[vc.base, x, y, w, h, exclude]}; Exit[vc]; RETURN}; VCGetTransformation: PROC [context: Context, from, to: ImagerBackdoor.CoordSys] RETURNS [Xfm] ~ { vc: ViewerContext ~ NARROW[context.data]; RETURN vc.baseClass.GetTransformation[vc.base, from, to]}; VCMoveViewRectangle: PROC [context: Context, width, height, fromX, fromY, toX, toY: INTEGER] ~ { vc: ViewerContext ~ NARROW[context.data]; cv: ContextViewer ~ vc.cv; Enter[vc]; {ENABLE UNWIND => Exit[vc]; bClipIdeal: BoxI ~ [0, 0, cv.size.x, cv.size.y]; bClipViewer: BoxI ~ BiOffset[[0, 0, cv.vcs.x, cv.vcs.y], [-cv.i2w.x, -cv.i2w.y]]; bClipScreen: BoxI ~ BiOffset[cv.scb, [-cv.i2s.x, -cv.i2s.y]]; bClip: BoxI ~ BiOffset[BiIntersect[BiIntersect[bClipIdeal, bClipViewer], bClipScreen], [-vc.viewToIdeal.x, -vc.viewToIdeal.y]]; bFrom: BoxI ¬ BiIntersect[bClip, [fromX, fromY, fromX+width, fromY+height]]; bTo: BoxI ¬ BiIntersect[bClip, [toX, toY, toX+width, toY+height]]; toW: INTEGER ¬ bTo.xmax - bTo.xmin; toH: INTEGER ¬ bTo.ymax - bTo.ymin; dx: INTEGER ¬ toX - fromX; dy: INTEGER ¬ toY - fromY; bFrom ¬ BiIntersect[bFrom, BiOffset[bTo, [-dx, -dy]]]; {fromW: INTEGER ¬ bFrom.xmax - bFrom.xmin; fromH: INTEGER ¬ bFrom.ymax - bFrom.ymin; IF fromW>0 AND fromH>0 THEN vc.baseClass.MoveViewRectangle[vc.base, fromW, fromH, bFrom.xmin, bFrom.ymin, bFrom.xmin+dx, bFrom.ymin+dy]; IF toW>0 AND toH>0 AND (toW#fromW OR toH#fromH) THEN { dun: BoxI ~ BiOffset[bFrom, [dx, dy]]; MarkForgotten: PROC ~ { midY: INTEGER ~ dun.ymin; midH: INTEGER ~ fromH; vc.baseClass.SetT[vc.base, idXfm]; vc.baseClass.SetColor[vc.base, forgottenColor]; IF dun.ymin > bTo.ymin THEN vc.baseClass.MaskRectangleI[vc.base, bTo.xmin, bTo.ymin, toW, dun.ymin - bTo.ymin]; IF bTo.ymax > dun.ymax THEN vc.baseClass.MaskRectangleI[vc.base, bTo.xmin, dun.ymax, toW, bTo.ymax - dun.ymax]; IF midH>0 THEN { IF dun.xmin > bTo.xmin THEN vc.baseClass.MaskRectangleI[vc.base, bTo.xmin, midY, dun.xmin - bTo.xmin, midH]; IF bTo.xmax > dun.xmax THEN vc.baseClass.MaskRectangleI[vc.base, dun.xmax, midY, bTo.xmax - dun.xmax, midH]; }; RETURN}; vc.base.DoSave[MarkForgotten]; width ¬ width}; }}; Exit[vc]; RETURN}; forgottenColor: Color ¬ ImagerColor.ColorFromRGB[[1, 0, 0]]; VCTestViewRectangle: PROC [context: Context, x, y, w, h: INTEGER] RETURNS [ImagerBackdoor.Visibility] ~ { vc: ViewerContext ~ NARROW[context.data]; RETURN vc.baseClass.TestViewRectangle[vc.base, x, y, w, h]}; VCGetBufferColorOperator: PROC [context: Context] RETURNS [ColorOperator] ~ { vc: ViewerContext ~ NARROW[context.data]; RETURN vc.baseClass.GetBufferColorOperator[vc.base]}; VCSaveBuffer: PROC [context: Context, id: ATOM, path: PathProc, oddWrap: BOOL] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; AddStay[vc.cv, [vc, savedBuffer, id]]; vc.baseClass.SaveBuffer[vc.base, id, path, oddWrap]}; Exit[vc]; RETURN}; VCRestoreBuffer: PROC [context: Context, id: ATOM] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; vc.baseClass.RestoreBuffer[vc.base, id]}; Exit[vc]; RETURN}; VCDiscardBuffer: PROC [context: Context, id: ATOM] ~ { vc: ViewerContext ~ NARROW[context.data]; Enter[vc]; {ENABLE UNWIND => Exit[vc]; RemStay[vc.cv, [vc, savedBuffer, id]]; vc.baseClass.DiscardBuffer[vc.base, id]}; Exit[vc]; RETURN}; AddStay: --Viewer INTERNAL-- PROC [cv: ContextViewer, stay: StayDef] ~ {cv.stayIn ¬ CONS[[stay, IF stay.name#NIL THEN Atom.GetPName[stay.name] ELSE NIL], cv.stayIn]}; RemStay: --Viewer INTERNAL-- PROC [cv: ContextViewer, stay: StayDef] ~ { last: StayList ¬ NIL; FOR this: StayList ¬ cv.stayIn, this.rest WHILE this#NIL DO IF this.first.def = stay THEN { IF last=NIL THEN cv.stayIn ¬ this.rest ELSE last.rest ¬ this.rest; RETURN}; last ¬ this; ENDLOOP; ERROR}; BiIntersect: PROC [a, b: BoxI] RETURNS [BoxI] ~ { xmin: INTEGER ~ MAX[a.xmin, b.xmin]; ymin: INTEGER ~ MAX[a.ymin, b.ymin]; RETURN[[xmin, ymin, MAX[xmin, MIN[a.xmax, b.xmax]], MAX[ymin, MIN[a.ymax, b.ymax]]]]}; BiOffset: PROC [b: BoxI, o: VECI] RETURNS [BoxI] ~ {RETURN[[b.xmin+o.x, b.ymin+o.y, b.xmax+o.x, b.ymax+o.y]]}; ViAdd: PROC [a, b: VECI] RETURNS [VECI] ~ INLINE {RETURN [[a.x+b.x, a.y+b.y]]}; Ctrs.RegisterClass[ctrFlavor, ctrClass]; END. Θ ViewerContextsImpl.Mesa Copyright Σ 1990, 1992 by Xerox Corporation. All rights reserved. Last tweaked by Mike Spreitzer on February 20, 1992 11:34 am PST Willie-s, April 21, 1992 5:24 pm PDT Κ.A–(cedarcode) style•NewlineDelimiter ™code™Kšœ Οeœ7™BK™@K™$—K˜KšΟk œ{žœJžœ]˜―K˜šΟnœžœž˜!Kšžœpžœ˜ψKšžœ˜K˜—K˜Kš žœžœŸœžœžœ˜YK˜Kš žœžœžœžœžœžœ˜Kšžœžœžœ˜Kšžœžœ žœ˜Kšœ žœ˜#Kšœžœžœ˜Kšœ žœ˜%Kšœ žœ˜#Kšœ žœ˜!Kšœ žœ˜!Kšœžœ˜Kšœžœ˜Kšœžœ˜+Kšœ žœ˜'Kšœ žœ˜'Kšœ žœ˜#Kšœ žœ˜%K˜Kšœ žœžœžœ˜"Kšœ žœžœžœ ˜$Kšœžœžœ ˜Kšœ žœžœ˜/K˜Kšœžœžœ˜/šœžœžœžœ˜,Kšœžœ˜ KšŸ œžœžœžœ˜&Kš Ÿ œžœžœžœ8žœ˜cKšŸœžœžœžœ˜,Kšœ žœžœ˜Kšœ žœ˜Kšœ%žœ˜)Kšœ žœ˜$KšœžœΟc˜-Kšœ žœ˜Kšœžœ˜Kšœžœ  4˜RKšœžœ  ˜&Kšœ žœžœ˜Kšœ ˜+Kšœ žœžœ ˜)Kšœ žœžœ ˜8Kšœ žœžœ ˜1Kšœžœžœ ˜+Kšœžœ ,˜FKšœžœ 3˜HKšœžœ '˜?Kšœ žœžœ˜Kšœž œ˜—K˜Kšœžœžœ˜/šœžœžœ˜%Kšœ˜K˜K˜Kšœ žœ ˜Kšœžœ˜Kšœžœžœ˜Kšœ žœžœ˜—K˜Kšœ žœžœžœ˜Kš œžœžœžœžœ˜5Kš œ žœžœ/žœžœ˜nKšœ žœ˜/K˜Kšœ žœžœžœ ˜"šœ žœžœ˜Kšœ žœ˜šœžœ ž˜K˜Kšœ!žœ˜'Kšžœ˜ ——K˜Kšœžœžœžœ˜+Kšœžœžœžœ˜6K˜Kšœ žœ˜"K˜Kšœžœ˜Kšœ žœ˜K˜K˜LK˜IK˜Kšœ žœ˜*šœ#žœ˜EKšœ ˜ —K˜Kšœ žœ žœ˜3šœžœ žœ ˜)Kšœ ˜ šœ žœ˜Kšœžœ˜Kšœžœ˜ Kšœžœ˜Kšœžœ ˜Kšœžœ˜Kšœžœ ˜Kšœžœ˜Kšœžœ ˜Kšœžœ˜K˜—K˜—K˜Kšœ žœ$˜7Kšœ žœ˜K˜šœžœ žœ ˜+Kšœ ˜ Kšœ žœ˜K˜—K˜šœ žœ žœ ˜&Kšœ ˜ Kšœ žœN˜[K˜—K˜šœžœ žœ ˜.K˜ Kšœ žœ#˜0Kšœžœ˜(K˜—K˜šœžœ žœ ˜0K˜ Kšœ žœ'˜4Kšœžœ ˜*K˜—K˜šœžœ˜"K˜KšŸœ ˜ KšŸœ ˜KšŸœ ˜KšŸœ ˜KšŸœ ˜ KšŸœ ˜KšŸœ ˜KšŸ œ˜KšŸœ ˜KšŸœ ˜KšŸœ ˜ KšŸœ ˜KšŸœ ˜KšŸ œ˜KšŸœ ˜KšŸœ ˜KšŸœ ˜KšŸ œ˜KšŸœ ˜ KšŸœ ˜KšŸœ ˜KšŸœ ˜KšŸœ˜!KšŸ œ˜KšŸ œ˜KšŸ œ˜KšŸœ ˜KšŸœ˜'KšŸœ˜+KšŸœ ˜KšŸ œ˜KšŸœ ˜KšŸœ˜#KšŸœ˜#KšŸœ ˜ KšŸ œ˜KšŸœ˜!KšŸœ ˜ KšŸ œ˜KšŸœ ˜KšŸ œ˜KšŸ œ˜KšŸ œ˜KšŸœ˜%KšŸœ ˜KšŸœ˜!KšŸ œ˜KšŸœ˜%KšŸ œ˜KšŸ œ˜KšŸ œ˜KšŸ œ˜KšŸ œ˜KšŸ œ˜KšŸ œ˜KšŸ œ˜KšŸœ˜!KšŸœ ˜KšŸœ˜)KšŸœ˜'KšŸ œ!˜*KšŸœ˜'KšŸœ˜'KšŸœ˜1KšŸ œ$˜0KšŸ œ˜KšŸ œ˜KšŸ œ˜Kšœ žœ˜—K˜šŸœžœž˜šœ%˜%Kšœžœ˜ Kš Ÿ œžœžœžœžœ˜,Kš Ÿ œžœžœžœ8žœžœ˜iKš Ÿœžœžœžœžœ˜2Kšœ žœžœžœ˜—Kšžœ˜Kš œžœžœžœžœ#˜?Kšœžœžœ ˜šœ%žœ"˜JKšœžœ/˜GK˜K˜ K˜K˜K˜K˜K˜K˜ Kšœžœ˜ —Kšœ žœžœ4˜SK˜7Kšœžœl˜tšžœE˜LK˜"—Kšœ1žœ˜7K˜K˜,K˜!Kšœ&˜&Kšœ žœ˜K˜nKšœ"˜"Kšœ“žœžœ žœ˜ΦKšœ#˜#Kšœ#˜#Kšžœžœ˜/Kšžœ˜—K˜šŸ œžœžœ)žœ ˜Sšžœž˜Kšœ žœ ˜Kšœ žœ ˜Kšžœžœ˜——K˜šŸœžœžœ žœ˜JKš žœžœžœžœžœ)˜ašžœžœž˜Kšœžœžœ˜'Kšžœžœ˜—Kšžœžœžœ˜—K˜šŸ œžœžœŸœžœ8žœ žœ˜‰šŸ œžœ˜KšœGžœ˜\Kšžœ˜—K˜7Kšžœ˜—K˜šŸ œžœžœžœ˜=šŸœžœžœ˜$Kšžœžœžœ˜K˜KšžœPžœ˜YKšžœžœžœ?˜XKšžœ˜—KšœD˜DKšžœ˜—K˜šŸ œžœžœžœ ˜=Kšœžœ˜—K˜šŸ œžœžœ)žœ˜IšŸœžœ˜K˜PK˜/šžœžœ˜!K˜ZKšœ˜—Kšžœžœžœ!žœ˜9Kšžœ˜—Kšœ7˜7Kšžœ˜—K˜šŸœžœžœ1žœ˜NšŸ œžœ˜Kšžœžœ žœ˜-šžœ˜"Kšžœ žœžœžœ˜0Kšœ žœ˜—Kšœ˜K˜Kšžœ˜—K˜4Kšžœ˜—K˜šŸ œžœžœ*žœ˜JKšœžœžœ˜šŸœžœ˜Kšœžœ˜šžœ$žœžœž˜6šžœžœ˜Kšžœžœžœžœ˜=Kšœžœ˜%K˜Kšžœ˜—Kšžœ˜—Kšœžœ˜ —Kšžœžœžœ˜!Kšœ7˜7Kšžœžœžœ˜Kšžœ˜—K˜šŸ œžœžœ˜5Kšœžœ˜šžœ$žœžœž˜6KšœJ˜JK˜Kšžœ˜—KšœH˜HKšœ`˜`Kšžœžœ'žœ˜:Kšžœ˜—K˜šŸ œžœžœžœ˜IKšœAžœ˜HKšœžœ1˜Hšžœžœ žœ˜Kšœ/˜/K˜`Kšœžœ˜—Kšœžœ.žœ ˜GKšœ žœ˜Kšžœ˜—K˜šŸœžœžœžœ˜Kš žœžœžœžœžœžœž˜>Kšœžœžœ ˜*Kšžœžœ˜—Kšžœžœžœ˜—K˜šŸ œžœžœ6˜LK˜Kšžœ˜—K˜šŸ œžœ œ˜@Kšœžœ ˜&Kšœ ˜ Kšžœ˜—K˜šŸœžœžœ˜,šžœžœžœ˜Kšœžœ˜Kš žœžœžœžœžœ#˜\Kšžœžœžœ#˜AK˜—Kšžœ˜—K˜šŸœžœžœ˜GK˜Kšœežœžœžœ˜‡KšœYžœžœ˜Kšœwžœžœ˜ŸKšœ‚žœ:žœ˜ΘKš œžœžœžœvžœžœ˜άK˜1Kšžœ˜—K˜š Ÿ œžœžœžœžœ˜3KšœžœžœžœH˜e—K˜š Ÿœžœ&žœžœ œ˜UKšœžœ˜)šžœžœž˜šœžœžœž˜K˜šœ ˜ Kšœžœ&˜0Kš œžœžœžœžœ˜Kšœ žœžœ ˜%Kš œžœžœžœžœ˜/K˜K˜Kšžœžœ žœ žœ žœ žœžœ˜Lšžœ ˜Kšœdžœ˜jKšžœ˜—K˜K˜ Kšœ)˜)K˜—šœ ˜ Kšœ-˜-K˜—˜Kšœžœ˜Kšžœ4˜7—˜Kšœžœ˜Kšžœ2˜5—Kšžœžœ˜—šœžœ˜Kšœžœ˜šŸœžœ˜Kšžœžœ1˜?Kšžœžœ1˜?K˜Kšœžœ˜Kšžœžœžœ?˜XK˜Kšžœ˜—š žœžœžœžœž˜)šžœ ž˜K˜K˜K˜K˜K˜K˜Kšžœžœ˜—Kšžœ˜—K˜2Kšžœ˜—Kšžœžœ˜—K˜—K˜KšŸ œžœžœ˜K˜šŸœžœ˜#Kšœ˜Kšœ žœžœ˜šŸœžœžœ˜)Kšžœžœžœ˜Kš žœžœ žœžœžœžœ ˜:Kšœžœ˜K˜K˜ Kšžœ˜—šŸœžœžœ˜Kšžœžœžœ˜,Kšž œ ˜šžœžœžœžœžœžœ žœžœžœ ž˜gKšžœ ˜Kšžœ˜—Kšœžœ˜+Kšžœ˜—K˜ šžœ žœžœ ˜Kšžœžœžœ˜5—šžœžœ žœ˜Kšœžœžœ˜(Kšœžœžœ˜(Kšœžœžœ(˜;Kšœžœžœ(˜;Kšœžœžœ˜-K˜"Kšœ7žœžœ˜]Kšœ;˜;šžœ%žœžœž˜7šžœ žœž˜Kšœo˜ošœ˜šŸœ˜!K˜DKšžœ˜—KšœG˜G—Kšžœžœ˜—Kšžœ˜—KšœK˜KKšœ ˜ Kšœ žœ˜—Kšžœ˜—K˜šŸœžœžœ˜(Kšžœžœžœ˜Kšžœžœžœ˜Kšœžœ˜!Kšœ žœ˜Kšž œ˜Kšžœ˜—K˜šŸ œžœ˜)š Ÿœžœžœžœžœ˜#Kšžœžœžœ˜Kšžœžœžœžœžœžœžœžœ žœ˜xKšžœžœ˜+—Kšœžœ˜ šžœžœžœžœ˜K˜Kšžœžœžœ˜Kšœ(žœ˜/Kšžœ˜—Kšžœ˜—K˜šŸœžœžœ/žœ žœžœžœžœ œ˜ŽKšžœžœžœ"žœ˜UKšœžœ ˜&Kšœžœ˜ Kšžœžœžœ˜šžœžœžœžœ˜$K˜K˜/Kšœžœ˜—šžœžœ˜Kšœžœ˜Kšžœžœžœ˜6—K˜:šžœ žœžœ˜1K˜ K˜K˜Kšžœžœžœ?˜XK˜—šžœ žœžœ˜Kšœž œ˜Kšœ@˜@Kšœ˜Kšœžœ˜ Kšž œ ˜Kšžœ˜ Kšœ žœ˜Kšžœžœžœžœ žœžœžœ žœ˜MKšœžœ˜—Kšžœ˜—K˜šŸœžœ4žœžœžœžœžœžœžœ œ˜ΆKšœžœ ˜&šŸœžœ˜K˜Kšœžœ˜Kšžœžœžœ?˜XK˜Kšžœ˜—šžœ žœžœžœ˜(KšœAžœ˜GKšžœ˜—šžœž˜šœ ˜ Kšœžœžœ˜0Kšœžœžœ(˜9Kš žœžœžœ#žœžœ%˜^—Kšœ,žœžœžœ˜EK˜JKšžœžœ˜—Kšœ.˜.Kšžœ˜—K˜šŸœžœ5žœžœžœžœžœžœžœ œ˜ΉKšœžœ ˜&šŸœžœ˜K˜Kšœžœ˜Kšžœžœžœ?˜XK˜Kšžœ˜—šžœ žœžœžœ˜(KšœAžœ˜GKšžœ˜—šžœž˜šœ ˜ Kšœžœžœ˜(Kšœžœžœ˜1Kš žœžœžœ$žœžœ'˜a—Kšœ/žœ žœžœ˜KK˜:Kšžœžœ˜—Kšœ.˜.Kšžœ˜—K˜šŸ œ œžœ˜>K˜šžœ$žœžœž˜6Kšœžœ˜*Kšœ žœ˜Kšžœ˜—Kšœ žœ˜Kšžœ˜—K˜šŸœœ˜$Kšœžœ ˜&Kšžœžœ žœ ˜6Kšžœ˜—K˜šŸœžœ7˜EKšœžœ ˜&šžœž˜Kšœžœ˜Kšœžœ˜!Kšžœžœ˜—Kšžœ˜—K˜š Ÿœžœžœžœžœ˜Kšœžœ˜)Kšœ˜Kšœ žœžœ ˜&K˜&Kšœ žœ˜—K˜šŸ œžœžœ˜JKšœžœ˜)Kšœ˜Kšœ žœžœ ˜&K˜(Kšœ žœ˜—K˜šŸ œžœ˜.Kšœžœ˜)Kšœ žœžœ ˜&Kšœ"˜"Kšœ žœ˜—K˜šŸ œžœžœ˜.Kšœžœ˜)Kšœ žœžœ ˜&Kšœ"˜"Kšœ žœ˜—K˜šŸ œžœžœ˜/Kšœžœ˜)Kšœ žœžœ ˜&Kšœ"˜"Kšœ žœ˜—K˜šŸ œžœžœ˜1Kšœžœ˜)Kšœ žœžœ ˜&Kšœ%˜%Kšœ žœ˜—K˜šŸœžœžœ˜2Kšœžœ˜)Kšœ žœžœ ˜&Kšœ%˜%Kšœ žœ˜—K˜šŸœžœžœ˜,Kšœžœ˜)Kšœ žœžœ ˜&Kšœ ˜ Kšœ žœ˜—K˜šŸ œžœžœ˜/Kšœžœ˜)Kšœ žœžœ ˜&Kšœ#˜#Kšœ žœ˜—K˜š Ÿœžœžœžœžœ˜FKšœžœ˜)Kšœ žœžœ ˜&K˜,Kšœ žœ˜—K˜šŸœžœ˜-Kšœžœ˜)Kšœ žœžœ ˜&Kšœ&˜&Kšœ žœ˜—K˜šŸœžœžœ˜9Kšœžœ˜)Kšœ žœžœ ˜&Kšœ,˜,Kšœ žœ˜—K˜šŸ œžœ˜*Kšœžœ˜)Kšœ žœžœ ˜&Kšœ#˜#Kšœ žœ˜—K˜šŸœžœžœ˜3Kšœžœ˜)Kšœ žœžœ ˜&Kšœ'˜'Kšœ žœ˜—K˜šŸœžœžœ˜-Kšœžœ˜)Kšœ žœžœ ˜&Kšœ ˜ Kšœ žœ˜—K˜šŸœžœžœ˜8Kšœžœ˜)Kšœ žœžœ ˜&Kšœ,˜,Kšœ žœ˜—K˜šŸœžœžœ˜:Kšœžœ˜)Kšœ žœžœ ˜&Kšœ.˜.Kšœ žœ˜—K˜šŸ œžœžœ˜4Kšœžœ˜)Kšœ&˜&Kšžœ˜—K˜šŸ œžœžœ žœ˜FKšœžœ˜)šžœžœ˜Kšœžœ˜Kšœ žœžœ ˜&Kšœ!žœ˜)K˜ Kšœ2˜2Kšœ žœžœ ˜&Kšœ!˜!K˜ —Kšžœ3˜7Kšžœ˜—K˜šŸ œžœžœ˜/Kšœžœ˜)Kšœ žœžœ ˜&Kšœ"˜"Kšœ žœ˜—K˜šŸœžœM˜dKšœžœ˜)Kšœ žœžœ ˜&Kšœ=˜=Kšœ žœ˜—K˜šŸœžœ3žœ˜SKšœžœ˜)Kšœ žœžœ ˜&Kšœ5˜5Kšœ žœ˜—K˜šŸœžœ-žœ žœ˜QKšœžœ˜)Kšœ žœžœ ˜&Kšœ4˜4Kšœ žœ˜—K˜šŸœžœ2žœ˜PKšœžœ˜)Kšœ žœžœ ˜&Kšœ1˜1Kšœ žœ˜—K˜šŸœžœ žœ žœ˜QKšœžœ˜)Kšœ žœžœ ˜&Kšœ;˜;Kšœ žœ˜—K˜šŸœžœ/žœ˜DKšœžœ˜)Kšœ žœžœ ˜&Kšœ*˜*Kšœ žœ˜—K˜šŸœžœ,˜@Kšœžœ˜)Kšœ žœžœ ˜&Kšœ,˜,Kšœ žœ˜—K˜šŸ œžœ-žœ˜FKšœžœ˜)Kšœ žœžœ ˜&Kšœ/˜/Kšœ žœ˜—K˜šŸœžœ,˜AKšœžœ˜)Kšœ žœžœ ˜&Kšœ(˜(Kšœ žœ˜—K˜šŸ œžœ,žœ˜GKšœžœ˜)Kšœ žœžœ ˜&Kšœ0˜0Kšœ žœ˜—K˜šŸ œžœ'˜8Kšœžœ˜)Kšœ žœžœ ˜&Kšœ%˜%Kšœ žœ˜—K˜šŸœžœ,žœ˜MKšœžœ˜)Kšœ žœžœ ˜&Kšœ3˜3Kšœ žœ˜—K˜šŸ œžœžœžœžœžœžœ˜]Kšœžœ˜)Kšœ žœžœ ˜&Kšœ8˜8Kšœ žœ˜—K˜šŸœžœ žœ˜BKšœžœ˜)Kšœ žœžœ ˜&Kšœ2˜2Kšœ žœ˜—K˜šŸ œžœžœ˜6Kšœžœ˜)Kšœ žœžœ ˜&Kšœ*˜*Kšœ žœ˜—K˜šŸœžœ0žœ žœžœžœžœžœ˜ŠKšœžœ˜)Kšœ žœžœ ˜&KšœS˜SKšœ žœ˜—K˜šŸ œžœ7žœ$žœ˜wKšœžœ˜)Kšœ žœžœ ˜&KšœN˜NKšœ žœ˜—K˜šŸ œžœ7žœ$žœ˜wKšœžœ˜)Kšœ žœžœ ˜&KšœN˜NKšœ žœ˜—K˜šŸ œžœVžœ$žœ˜–Kšœžœ˜)Kšœ žœžœ ˜&Kšœ_˜_Kšœ žœ˜—K˜šŸ œžœ*žœ˜FKšœžœ˜)K˜-Kšžœ˜—K˜šŸœžœžœžœ˜fKšœžœ˜)Kšœ žœžœ ˜&Kšœ"žœ˜7K˜ KšœH˜HKšœ žœžœ ˜&Kšœ"žœ˜7Kšœ žœ˜—K˜šŸ œžœ5žœžœ˜bKšœžœ˜)Kšœ žœžœ ˜&KšœA˜AKšœ žœ˜—K˜šŸ œžœžœ˜