DIRECTORY Atom USING [], Carets USING [ResumeCarets, SuspendCarets], Graphics USING [Context], IconManager USING [selectedIcon], Icons USING [DrawIcon], Imager USING [black, ClipRectangleI, Context, DoSave, ExcludeRectangleI, MaskRectangleI, SetColor, SetXYI, ShowText, white], ImagerOps USING [GraphicsFromImager, XOR], InputFocus USING [], Menus USING [], MenusPrivate USING [DrawMenu], Process USING [Detach, MsecToTicks, Pause, Ticks], RefText USING [AppendRope, ObtainScratch, ReleaseScratch, TrustTextAsRope], Rope USING [Length, ROPE, Run], VFonts USING [defaultFont, StringWidth], ViewerClasses USING [PaintRectangle, Viewer], ViewerLocks USING [CallUnderReadLock, CallUnderWriteLock, Wedged], ViewerOps USING [AddProp, ChangeColumn, EnumerateViewers, EnumProc, FetchProp, GreyScreen, PaintHint, UserToScreenCoords], ViewerSpecs USING [captionHeight, iconHeight, iconWidth, menuBarHeight, menuHeight, windowBorderSize], ViewersStallNotifier USING [], ViewerTools USING [GetSelectedViewer]; ViewerPaintImpl: CEDAR MONITOR IMPORTS Carets, Imager, ImagerOps, IconManager, Icons, MenusPrivate, Process, RefText, Rope, VFonts, ViewerLocks, ViewerTools, ViewerOps EXPORTS ViewerOps, ViewersStallNotifier SHARES Menus, ViewerClasses, ViewerLocks = BEGIN OPEN ViewerClasses, ViewerOps, ViewerSpecs; ROPE: TYPE = Rope.ROPE; InvisiblePaint: PUBLIC SIGNAL = CODE; PaintDefaultCaption: PROC[viewer: Viewer, context: Imager.Context] ~ { text: REF TEXT ~ RefText.ObtainScratch[100]; header: REF TEXT _ text; headerW: INTEGER _ 0; name: ROPE ~ viewer.name; nameLen: INT ~ Rope.Length[name]; file: ROPE ~ viewer.file; fileLen: INT ~ Rope.Length[file]; header _ RefText.AppendRope[to: header, from: name]; IF fileLen>nameLen AND Rope.Run[s1: name, s2: file, case: FALSE]=nameLen THEN { header _ RefText.AppendRope[to: header, from: " ("]; header _ RefText.AppendRope[to: header, from: file, start: nameLen]; header _ RefText.AppendRope[to: header, from: ")"]; }; IF viewer.saveInProgress THEN header _ RefText.AppendRope[to: header, from: " [Saving...]"] ELSE IF viewer.newFile THEN header _ RefText.AppendRope[to: header, from: " [New File]"] ELSE IF viewer.newVersion THEN header _ RefText.AppendRope[to: header, from: " [Edited]"]; IF viewer.link#NIL THEN header _ RefText.AppendRope[to: header, from: " [Split]"]; headerW _ VFonts.StringWidth[RefText.TrustTextAsRope[header]]; headerW _ MIN[headerW, viewer.ww]; Imager.SetColor[context, Imager.black]; Imager.MaskRectangleI[context, 0, viewer.wh, viewer.ww, -captionHeight]; Imager.SetColor[context, Imager.white]; Imager.SetXYI[context, (viewer.ww-headerW)/2, viewer.wh-captionHeight+4]; Imager.ShowText[context, header]; RefText.ReleaseScratch[text]; }; PaintDocumentHeader: PROC[viewer: Viewer, context: Imager.Context, clear: BOOL, hint: PaintHint, whatChanged: REF ANY] ~ { wbs: INTEGER = IF viewer.border THEN windowBorderSize ELSE 0; IF hint#menu THEN { IF viewer.class.caption#NIL THEN { -- client-painted caption action: PROC ~ { Imager.ClipRectangleI[context: context, x: 0, y: viewer.wh, w: viewer.ww, h: -captionHeight]; viewer.class.caption[viewer, ImagerOps.GraphicsFromImager[context]]; }; Imager.DoSave[context, action]; } ELSE PaintDefaultCaption[viewer, context]; }; IF viewer.menu#NIL AND hint#caption THEN { top: INTEGER ~ viewer.wh-captionHeight; height: INTEGER ~ viewer.menu.linesUsed*menuHeight; IF whatChanged=NIL THEN { IF ~clear THEN { Imager.SetColor[context, Imager.white]; Imager.MaskRectangleI[context, wbs, top, viewer.ww-(2*wbs), -height]; -- menu area }; Imager.SetColor[context, Imager.black]; Imager.MaskRectangleI[context, 0, top-height, viewer.ww, -menuBarHeight]; -- bar below }; MenusPrivate.DrawMenu[viewer.menu, ImagerOps.GraphicsFromImager[context], wbs, top-menuHeight, whatChanged]; }; }; PaintIcon: PROC [viewer: Viewer, hint: PaintHint, whatChanged: REF ANY _ NIL] = { label: Rope.ROPE; action: PROC[imager: Imager.Context] ~ { context: Graphics.Context ~ ImagerOps.GraphicsFromImager[imager]; IF viewer.icon=private THEN viewer.class.paint[viewer, context, whatChanged, hint=all] ELSE IF hint=all OR hint=caption THEN { draw: PROC ~ { Icons.DrawIcon[flavor: viewer.icon, context: context, label: label] }; IF viewer.icon=document AND (viewer.newVersion OR viewer.newFile) THEN viewer.icon _ dirtyDocument ELSE IF viewer.icon=dirtyDocument AND NOT(viewer.newVersion OR viewer.newFile) THEN viewer.icon _ document; label _ NARROW[ViewerOps.FetchProp[viewer, $IconLabel]]; IF label = NIL THEN label _ viewer.name; Imager.DoSave[imager, draw]; IF IconManager.selectedIcon=viewer THEN { Imager.SetColor[imager, ImagerOps.XOR]; Imager.MaskRectangleI[imager, 0, 0, iconWidth, iconHeight]; }; }; }; IF viewer.parent=NIL THEN PaintClient[viewer, action]; }; SetIconLabel: PUBLIC PROC [viewer: Viewer, label: Rope.ROPE] = { ViewerOps.AddProp[viewer, $IconLabel, label]; }; RecursivelyPaintViewers: PROC [viewer: Viewer, hint: PaintHint, clearClient: BOOL, clear: BOOL, rect: PaintRectangle, whatChanged: REF ANY] = { FOR v: Viewer _ viewer, v.parent UNTIL v=NIL DO -- visibility test IF v.parent#NIL THEN { IF (v.wy+v.wh < 0) OR (v.wy > v.parent.ch) THEN RETURN; IF (v.ww+v.ww < 0) OR (v.wx > v.parent.cw) THEN RETURN; }; ENDLOOP; IF hint#client THEN { windowPart: PROC[context: Imager.Context] ~ { IF clearClient AND ~clear AND hint=all THEN { Imager.SetColor[context, Imager.white]; Imager.MaskRectangleI[context, 0, 0, viewer.ww, viewer.wh]; clear _ TRUE; }; IF viewer.border AND hint=all THEN { wbs: INTEGER ~ ViewerSpecs.windowBorderSize; Imager.SetColor[context, Imager.black]; Imager.MaskRectangleI[context: context, x: 0, y: 0, w: viewer.ww, h: wbs]; Imager.MaskRectangleI[context: context, x: 0, y: viewer.wh, w: viewer.ww, h: -wbs]; Imager.MaskRectangleI[context: context, x: 0, y: 0, w: wbs, h: viewer.wh]; Imager.MaskRectangleI[context: context, x: viewer.ww, y: 0, w: -wbs, h: viewer.wh]; }; IF viewer.parent=NIL AND viewer.column#static THEN PaintDocumentHeader[viewer, context, clear, hint, whatChanged]; }; IF ~viewer.visible OR viewer.destroyed THEN SIGNAL InvisiblePaint; PaintWindow[viewer, windowPart]; }; IF hint=all OR hint=client THEN { clientPart: PROC[context: Imager.Context] ~ { IF rect#NIL AND viewer.class.bltContents=none THEN clearClient _ TRUE; IF clearClient AND ~clear THEN { Imager.SetColor[context, Imager.white]; Imager.MaskRectangleI[context, 0, 0, viewer.cw, viewer.ch]; Imager.SetColor[context, Imager.black]; IF rect # NIL THEN whatChanged _ NIL; rect _ NIL; clear _ TRUE; }; IF viewer.class.paint#NIL THEN viewer.class.paint[viewer, ImagerOps.GraphicsFromImager[context], whatChanged, clear]; }; IF ~viewer.visible OR viewer.destroyed THEN SIGNAL InvisiblePaint; PaintClient[viewer, clientPart]; }; IF rect # NIL AND viewer.parent = NIL THEN { IF viewer.cx >= rect.x AND (viewer.cx + viewer.cw <= rect.x + rect.w) AND viewer.cy >= rect.y AND (viewer.cy + viewer.ch <= rect.y + rect.h) THEN RETURN}; IF hint=all OR hint=client OR clear THEN FOR v: Viewer _ viewer.child, v.sibling UNTIL v=NIL DO IF rect # NIL THEN { -- don't paint if it is completely within the blt -- map to the coodinate system that rect uses vx, vy: INTEGER; IF viewer.class.coordSys = top THEN [vx, vy] _ ViewerOps.UserToScreenCoords[viewer, v.wx, v.wy+v.wh] ELSE [vx, vy] _ ViewerOps.UserToScreenCoords[viewer, v.wx, v.wy]; IF vx >= rect.x AND (vx + v.ww <= rect.x + rect.w) AND vy >= rect.y AND (vy + v.wh <= rect.y + rect.h) THEN LOOP}; RecursivelyPaintViewers[v, all, FALSE, clear, rect, whatChanged]; ENDLOOP; }; PaintViewer: PUBLIC PROC [viewer: Viewer, hint: PaintHint _ client, clearClient: BOOL _ TRUE, whatChanged: REF ANY _ NIL] = { LockedPaintViewer: PROC = { ENABLE ABORTED => CONTINUE; IF NOT viewer.visible OR viewer.destroyed THEN RETURN; IF viewer.iconic THEN PaintIcon[viewer, hint, whatChanged] ELSE { action: PROC ~ { rect: PaintRectangle _ NIL; WITH whatChanged SELECT FROM r: PaintRectangle => rect _ r; ENDCASE; RecursivelyPaintViewers[viewer: viewer, hint: hint, clearClient: clearClient AND ~(hint=menu OR hint=caption), clear: FALSE, rect: rect, whatChanged: whatChanged ! InvisiblePaint => CONTINUE]; }; Carets.SuspendCarets[]; action[! UNWIND => Carets.ResumeCarets[]]; Carets.ResumeCarets[]; }; }; ViewerLocks.CallUnderReadLock[LockedPaintViewer, viewer ! ViewerLocks.Wedged => CONTINUE]; }; Init: ENTRY PROC = { }; colorInit: BOOL _ FALSE; UnWedgePainter: PUBLIC ENTRY PROC [process: PROCESS, kind: ATOM] = { }; fatalViewersError: ERROR = CODE; InvertForMenus: PUBLIC PROC[viewer: Viewer, x,y: INTEGER, w,h: INTEGER] = { action: PROC[context: Imager.Context] ~ { Imager.SetColor[context, ImagerOps.XOR]; Imager.MaskRectangleI[context, x, y, MIN[w, viewer.ww-x], h]; }; PaintWindow[viewer, action]; }; ClipIcon: PROC[context: Imager.Context] = { ClipOpenViewer: ViewerOps.EnumProc = { IF ~v.iconic AND (v.column=right OR v.column=left) THEN Imager.ExcludeRectangleI[context, v.wx, v.wy, v.ww, v.wh]; }; ViewerOps.EnumerateViewers[ClipOpenViewer]; }; BlinkIcon: PUBLIC PROC [viewer: Viewer, count, interval: NAT] = { IF interval >= 1000 THEN interval _ interval/1000; IF viewer.offDeskTop THEN ViewerOps.ChangeColumn[viewer, left]; IF count = 1 THEN BlinkProcess[viewer, count, interval] ELSE TRUSTED {Process.Detach[FORK BlinkProcess[viewer, count, interval]]}; }; BlinkProcess: PROC [viewer: Viewer, count, n: NAT] = { howOften: Process.Ticks = Process.MsecToTicks[500]; Blink: PROC = { IF viewer.visible AND NOT viewer.destroyed THEN { action: PROC[context: Imager.Context] ~ { Imager.SetColor[context, ImagerOps.XOR]; Imager.MaskRectangleI[context, 0, 0, viewer.ww, viewer.wh]; Process.Pause[Process.MsecToTicks[400]]; Imager.MaskRectangleI[context, 0, 0, viewer.ww, viewer.wh]; }; PaintWindow[viewer, action]; Process.Pause[Process.MsecToTicks[350]]; -- so can be called back-to-back }; }; DO ViewerLocks.CallUnderWriteLock[Blink, viewer]; IF count = 1 THEN RETURN; IF count > 0 THEN count _ count - 1; FOR i: NAT IN [0..2*n) DO -- blink every n seconds, but wake up every half second. Process.Pause[howOften]; IF viewer.destroyed OR ~viewer.iconic OR viewer = ViewerTools.GetSelectedViewer[] THEN RETURN; ENDLOOP; ENDLOOP; }; PaintWindow: PUBLIC PROC[viewer: Viewer, action: PROC[Imager.Context]] ~ { }; PaintClient: PUBLIC PROC[viewer: Viewer, action: PROC[Imager.Context]] ~ { }; Init[]; ViewerOps.GreyScreen[0, 0, 9999, 9999, FALSE, FALSE]; END. "ViewerPaintImpl.mesa Copyright c 1983, 1984 Xerox Corporation. All rights reserved. written by S. McGregor Edited by McGregor on May 2, 1983 11:11 am Edited by Maxwell, June 3, 1983 8:23 am Russ Atkinson, September 1, 1983 11:47 am Doug Wyatt, September 4, 1984 4:34:32 pm PDT The intent of this crock is to show the file version for $Text viewers: if name is a prefix of file, show the remainder of file (presumably "!n") in parentheses IF flavor is private then client wants to draw the icon do we need to paint any of the children? recursively paint children these guys should be painted in reverse order for correct overlaps PaintVector: TYPE = REF PaintVectorRec; PaintVectorRec: TYPE = RECORD [ next: PaintVector _ NIL, viewer: Viewer _ NIL, inUse: BOOL _ FALSE, resetOnRelease: BOOL _ FALSE, color: BOOL _ FALSE, mark: Graphics.Mark _ nullMark, process: UNSAFE PROCESS _ NIL, context: Context _ NIL, previous: PaintVector _ NIL]; nVectors: CARDINAL = 5; usedVectors: CARDINAL _ 0; PaintVectorAvailable: CONDITION; paintingLock: CARDINAL _ 0; vectorRoot: PaintVector _ NIL; colorVector: PaintVector _ NIL; new: PaintVector; FOR n: CARDINAL IN [0..nVectors) DO new _ NEW[PaintVectorRec]; new.context _ NewContext[]; SetDefaultFont[new.context, VFonts.defaultGFont]; new.next _ vectorRoot; IF vectorRoot#NIL THEN vectorRoot.previous _ new; vectorRoot _ new; ENDLOOP; colorVector _ NEW[PaintVectorRec]; colorVector.color _ TRUE; InitialiseColorPainting: PUBLIC PROC = { ColorCriticalInit: ENTRY PROC = { colorVector.context _ ColorWorld.NewContext[]; SetDefaultFont[colorVector.context, VFonts.defaultGFont]; colorInit _ TRUE; }; ColorCriticalInit[]; ViewerOps.GreyScreen[0, 0, 9999, 9999, TRUE, FALSE]; }; ZapVector: INTERNAL PROC [p: PaintVector] = { oldContext: Context _ p.context; p.context _ IF p.color THEN ColorWorld.NewContext[] ELSE NewContext[]; Graphics.SetDefaultFont[p.context, VFonts.defaultGFont]; p.viewer _ NIL; p.inUse _ FALSE; p.process _ NIL; p.mark _ nullMark; IF ~p.color THEN usedVectors _ usedVectors - 1; GraphicsOps.Disable[oldContext]; -- smash old BROADCAST PaintVectorAvailable; }; ENABLE UNWIND => NULL; IF colorVector.inUse AND colorVector.process=process THEN ZapVector[colorVector] ELSE FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO IF p.inUse AND p.process=process THEN ZapVector[p]; ENDLOOP; UnWedge: ENTRY PROC [process: PROCESS, kind: ATOM] = { call from debugger IF colorVector.inUse THEN ZapVector[colorVector] ELSE FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO IF p.inUse THEN ZapVector[p]; ENDLOOP; usedVectors _ 0; -- make sure paintingLock _ 0; -- make sure BROADCAST PaintVectorAvailable; }; DisablePainting: PUBLIC ENTRY PROC [wait: BOOL _ TRUE] = { ENABLE UNWIND => NULL; InternalDisablePainting[wait]; }; InternalDisablePainting: INTERNAL PROC [wait: BOOL _ TRUE] = INLINE { IF wait THEN WHILE usedVectors#0 OR colorVector.inUse DO WAIT PaintVectorAvailable; ENDLOOP; paintingLock _ paintingLock+1; }; EnablePainting: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; InternalEnablePainting[]; }; InternalEnablePainting: INTERNAL PROC = INLINE { IF paintingLock#0 THEN paintingLock _ paintingLock-1; broadcast since all are likely to be free IF paintingLock=0 THEN BROADCAST PaintVectorAvailable; }; DisablePaintingUnWedged: INTERNAL PROC [wait: BOOL _ TRUE] = INLINE { AllWedged: INTERNAL PROC RETURNS[BOOL] = INLINE { IF colorVector.inUse THEN { IF colorVector.viewer=NIL THEN RETURN[FALSE]; -- context = screen IF ~ViewerLocks.ColumnWedged[color].wedged THEN RETURN[FALSE]; }; FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO IF ~p.inUse THEN LOOP; IF p.viewer = NIL THEN RETURN[FALSE]; -- context = screen IF ~ViewerLocks.ColumnWedged[ViewerColumn[p.viewer]].wedged THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; IF wait THEN WHILE usedVectors#0 OR colorVector.inUse DO IF AllWedged[] THEN EXIT ELSE WAIT PaintVectorAvailable; ENDLOOP; paintingLock _ paintingLock+1; }; WaitForPaintingToFinish: PUBLIC ENTRY PROC = { assumes interesting paints already in progress WHILE usedVectors#0 AND colorVector.inUse DO WAIT PaintVectorAvailable ENDLOOP; }; ResetPaintCache: PUBLIC ENTRY PROC [viewer: Viewer _ NIL, wait: BOOL _ TRUE] = { ENABLE UNWIND => NULL; DisablePaintingUnWedged[wait]; FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO IF p.inUse THEN { IF p.viewer = NIL OR ~ViewerLocks.ColumnWedged[ViewerColumn[p.viewer]].wedged THEN IF wait THEN RETURN WITH ERROR fatalViewersError; p.resetOnRelease _ TRUE; } ELSE IF p.viewer#NIL THEN { ResetContext[p.context]; p.viewer _ NIL; }; ENDLOOP; IF colorVector.context#NIL THEN { IF colorVector.inUse AND ~ViewerLocks.ColumnWedged[color].wedged THEN { IF wait THEN RETURN WITH ERROR fatalViewersError; colorVector.resetOnRelease _ TRUE; } ELSE IF colorVector.viewer#NIL THEN { ResetContext[colorVector.context]; colorVector.viewer _ NIL; }; }; InternalEnablePainting[]; }; ReleaseContext: PUBLIC ENTRY PROC [free: Context] = { ENABLE UNWIND => NULL; CleanUp: INTERNAL PROC [p: PaintVector] = { Restore[free, p.mark]; -- throw away any client changes p.inUse _ FALSE; p.mark _ nullMark; IF ~p.color THEN {IF usedVectors=0 THEN RETURN WITH ERROR fatalViewersError ELSE usedVectors _ usedVectors-1}; IF p.resetOnRelease THEN { ResetContext[p.context]; p.viewer _ NIL; p.resetOnRelease _ FALSE; }; p.process _ NIL; BROADCAST PaintVectorAvailable; }; IF free=NIL THEN RETURN WITH ERROR fatalViewersError; IF free=colorVector.context THEN CleanUp[colorVector] ELSE FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO IF free=p.context THEN {CleanUp[p]; EXIT}; ENDLOOP; }; AcquireContext: PUBLIC ENTRY PROC [viewer: Viewer, color: BOOL _ FALSE] RETURNS [allocated: Context] = { ENABLE UNWIND => NULL; bestFit: PaintVector; nil: BOOL _ FALSE; MakeFirst: INTERNAL PROC [pv: PaintVector] = INLINE { -- LRU caching scheme IF pv=vectorRoot THEN RETURN; pv.previous.next _ pv.next; IF pv.next#NIL THEN pv.next.previous _ pv.previous; pv.next _ vectorRoot; vectorRoot.previous _ pv; vectorRoot _ pv; }; IF color THEN { IF ~colorInit THEN ERROR fatalViewersError; WHILE colorVector.inUse OR paintingLock#0 DO WAIT PaintVectorAvailable; ENDLOOP; IF viewer#NIL AND (~viewer.visible OR viewer.destroyed) THEN SIGNAL InvisiblePaint; -- someone got changed while waiting in the loop above bestFit _ colorVector; } ELSE { UNTIL usedVectors NULL; viewer=NIL => ResetContext[pContext]; pViewer=viewer.parent => PushContext[viewer, pContext]; pViewer=NIL => RecursivelyPushParent[viewer]; pViewer.destroyed => {ResetContext[pContext]; RecursivelyPushParent[viewer]}; pViewer.parent=viewer => PopContext[pContext]; pViewer.parent=viewer.parent => {PopContext[pContext]; PushContext[viewer, pContext]}; ENDCASE => {ResetContext[pContext]; RecursivelyPushParent[viewer]}; paintVector.viewer _ viewer; }; PushContext: INTERNAL PROC [viewer: Viewer, context: Context] = { OPEN viewer; invertCoords: BOOL = IF viewer.parent=NIL THEN viewer.class.coordSys=top ELSE viewer.class.coordSys#viewer.parent.class.coordSys; [] _ Save[context]; IF viewer.iconic THEN { IF wy+wh > openBottomY THEN ClipIcon[context]; ClipBox[context, XYWH2Box[wx, wy, ww, wh]]; Translate[context, wx, wy]; } ELSE IF invertCoords THEN { ClipBox[context, XYWH2Box[cx, cy, cw, ch]]; Translate[context, cx, cy+ch]; Scale[context, 1, -1]; } ELSE { ClipBox[context, XYWH2Box[cx, cy, cw, ch]]; Translate[context, cx, cy]; }; }; PopContext: INTERNAL PROC [context: Context] = INLINE { Restore[context]; }; ResetContext: INTERNAL PROC [context: Context] = INLINE { screen: Mark = LOOPHOLE[0]; Restore[context, screen]; }; clips for overlapping top level windows given valid Context and Viewer Κe– "Mesa" style˜šΟc™Jšœ Οmœ4™?Jš™Jš*™*J™'J™)J™,—J™šΟk ˜ JšœŸœ˜JšœŸœ˜+Jšœ Ÿœ ˜Jšœ Ÿœ˜!JšœŸœ ˜JšœŸœp˜|Jšœ ŸœŸœ˜*Jšœ Ÿœ˜JšœŸœ˜Jšœ Ÿœ ˜JšœŸœ%˜2JšœŸœ>˜KJšœŸœ Ÿœ˜JšœŸœ˜(JšœŸœ˜-Jšœ Ÿœ1˜BJšœ Ÿœk˜zJšœ ŸœU˜fJšœŸœ˜Jšœ Ÿœ˜&J˜—JšœŸ ˜JšŸœ˜ˆJšŸœ ˜'JšŸœ"˜(JšœŸœŸœ'˜3J˜JšŸœŸœŸœ˜J˜JšœŸœŸœŸœ˜%J˜šΟnœŸœ-˜FJšœŸœŸœ˜,JšœŸœŸœ˜Jšœ Ÿœ˜JšœŸœ˜Jšœ Ÿœ˜!JšœŸœ˜Jšœ Ÿœ˜!Jšœ4˜4šŸœŸœ$Ÿœ Ÿœ˜OJšœ ™ Jšœ4˜4JšœD˜DJšœ3˜3J˜—šŸœŸ˜Jšœ>˜>—šŸœŸœŸ˜Jšœ=˜=—šŸœŸœŸ˜Jšœ<˜<—šŸœ ŸœŸ˜Jšœ;˜;—Jšœ>˜>Jšœ Ÿœ˜"J˜'J˜HJ˜'J˜IJšœ!˜!J˜J˜J˜—š œŸœ)˜BJšœŸœ ŸœŸœ˜7Jš œŸœŸœŸœŸœ˜=šŸœ Ÿœ˜šŸœŸœŸœ˜<šœŸœ˜˜'J˜5—J˜DJ˜—J˜Jšœ˜—JšŸœ&˜*Jšœ˜—šŸœ ŸœŸœŸœ˜*JšœŸœ˜'JšœŸœ$˜3šŸœ ŸœŸœ˜šŸœŸœ˜J˜'JšœF ˜RJšœ˜—J˜'JšœJ ˜VJšœ˜—šœI˜IJšœ"˜"—Jšœ˜—Jšœ˜J˜—š   œŸœ0ŸœŸœŸœ˜QJšœ Ÿœ˜šœŸœ˜(JšœA˜AJš7™7JšŸœŸœ;˜VšŸœŸœ ŸœŸœ˜'JšœŸœK˜UšŸœŸœŸœ˜AJšŸœ˜ —š ŸœŸœŸœŸœŸœ˜NJšŸœ˜—JšœŸœ*˜8JšŸœ ŸœŸœ˜(J˜šŸœ!Ÿœ˜)Jšœ"Ÿœ˜'Jšœ;˜;Jšœ˜—Jšœ˜—J˜—JšŸœŸœŸœ˜6Jšœ˜—J˜š  œŸœŸœŸœ˜@J˜-Jšœ˜J˜—š œŸœ0Ÿœ˜RJšœŸœ%ŸœŸœ˜Jšœ™—šŸœ%ŸœŸœŸ™6JšŸœ ŸœŸœ™Jš Ÿœ ŸœŸœŸœŸœ™9JšŸœ:ŸœŸœŸœ™OJšŸœ™—JšŸœŸœ™ Jšœ™—šŸœŸ™ šŸœŸœŸœ™,Jš Ÿœ ŸœŸœŸœŸœ™9—JšŸœ™J™—Jšœ™J™—š œŸœŸœŸœ™.Jš.™.Jš ŸœŸœŸœŸœŸœ™OJšœ™J™—š œŸœŸœŸœŸœŸœŸœ™PJšŸœŸœŸœ™J™šŸœ%ŸœŸœŸ™6šŸœ Ÿœ™šŸœ ŸœŸœ:™NJš ŸœŸœŸœŸœŸœ™6—JšœŸœ™Jšœ™—šŸœŸœ ŸœŸœ™J™Jšœ Ÿœ™Jšœ™—JšŸœ™—šŸœŸœŸœ™!šŸœŸœ'Ÿœ™GJš ŸœŸœŸœŸœŸœ™1JšœŸœ™"Jšœ™—šŸœŸœŸœŸœ™%J™"JšœŸœ™Jšœ™—Jšœ™—J™Jšœ™J™—JšœŸœŸœ˜ J˜š œŸœŸœŸœ™5JšŸœŸœŸœ™š œŸœŸœ™+Jšœ ™7Jšœ Ÿœ™J™šŸœ ŸœŸœŸœŸœŸœŸœ™KJšŸœ™"—šŸœŸœ™J™Jšœ Ÿœ™JšœŸœ™Jšœ™—Jšœ Ÿœ™JšŸ œ™Jšœ™—Jš ŸœŸœŸœŸœŸœŸœ™5JšŸœŸœ™5š ŸœŸœ%ŸœŸœŸ™;JšŸœŸœŸœ™*JšŸœ™—Jšœ™J™—š  œŸœŸœŸœŸœŸœ™GJšŸœ™ JšŸœŸœŸœ™J™JšœŸœŸœ™J™š   œŸœŸœŸœ™KJšŸœŸœŸœ™J™JšŸœ ŸœŸœ ™3J™J™J™Jšœ™J™—šŸœŸœ™JšŸœ ŸœŸœ™+Jš ŸœŸœŸœŸœŸœ™Pš ŸœŸœŸœŸœŸ™