DIRECTORY Carets USING [ResumeCarets, SuspendCarets], ColorWorld USING [NewContext], Graphics USING [black, ClipBox, Context, DrawBox, DrawRope, FontRef, Mark, NewContext, nullMark, PaintMode, Restore, Save, Scale, SetColor, SetCP, SetDefaultFont, SetPaintMode, Translate, white], GraphicsOps USING [Disable], IconManager USING [selectedIcon], Icons USING [DrawIcon], Menus USING [], MenusPrivate USING [DrawMenu], Process USING [Detach, GetCurrent, MsecToTicks, Pause, Ticks], Rope USING [ROPE], VFonts USING [defaultFont, defaultGFont, StringWidth], ViewerOps, ViewerClasses, ViewerLocks USING [CallUnderReadLock, CallUnderWriteLock, ColumnWedged, Wedged], ViewerSpecs, ViewersStallNotifier, ViewerTools USING [GetSelectedViewer]; ViewerPaintImpl: CEDAR MONITOR IMPORTS Carets, ColorWorld, Graphics, GraphicsOps, IconManager, Icons, MenusPrivate, Process, VFonts, ViewerLocks, ViewerTools, ViewerOps, ViewerSpecs EXPORTS ViewerOps, ViewersStallNotifier SHARES Menus, ViewerClasses, ViewerLocks = BEGIN OPEN Graphics, ViewerClasses, ViewerOps, ViewerSpecs; InvisiblePaint: PUBLIC SIGNAL = CODE; PaintDocumentHeader: PROC [viewer: Viewer, context: Context, clear: BOOL, hint: PaintHint, whatChanged: REF ANY] = BEGIN OPEN viewer; wbs: INTEGER = IF viewer.border THEN windowBorderSize ELSE 0; ClipBox[context, [wx, wy, wx+ww, wy+wh]]; IF hint#menu THEN BEGIN IF viewer.class.caption#NIL THEN BEGIN -- client-painted caption mark: Mark _ Save[context]; ClipBox[context, [wx+wbs, wy+wh-captionHeight-wbs, wx+ww-(2*wbs), wy+wh-wbs]]; viewer.class.caption[viewer, context]; Restore[context, mark]; END ELSE BEGIN headerW: INTEGER _ VFonts.StringWidth[name]; IF viewer.saveInProgress THEN headerW _ headerW + sipW ELSE IF viewer.newFile THEN headerW _ headerW + newFW ELSE IF viewer.newVersion THEN headerW _ headerW + newVW; IF viewer.link#NIL THEN headerW _ headerW + linkW; headerW _ MIN[headerW, ww]; DrawBox[context, XYWH2Box[wx, wy+wh-captionHeight, ww, captionHeight]]; SetColor[context, white]; SetCP[context, wx+((ww-headerW)/2), wy+wh-captionHeight+4]; DrawRope[context, name]; IF viewer.saveInProgress THEN DrawRope[context, sipT] ELSE IF viewer.newFile THEN DrawRope[context, newFT] ELSE IF viewer.newVersion THEN DrawRope[context, newVT]; IF viewer.link#NIL THEN DrawRope[context, linkT]; END; END; IF menu#NIL AND hint#caption THEN BEGIN height: INTEGER _ menu.linesUsed*menuHeight; IF whatChanged=NIL THEN BEGIN IF ~clear THEN BEGIN SetColor[context, white]; DrawBox[context, XYWH2Box[wx+wbs, wy+wh-captionHeight-height, ww-(2*wbs), height]]; END; SetColor[context, black]; DrawBox[context, XYWH2Box[wx, wy+wh-captionHeight-height-windowBorderSize, ww, menuBarHeight]]; END; MenusPrivate.DrawMenu[viewer.menu, context, wx+wbs, wy+wh-menuHeight-captionHeight, whatChanged]; END; END; PaintIcon: PROC [viewer: Viewer, hint: PaintHint, whatChanged: REF ANY _ NIL] = BEGIN context: Context; label: Rope.ROPE; IF viewer.parent#NIL THEN RETURN; context _ AcquireContext[viewer, FALSE]; -- all icons on b&w display IF viewer.icon=private THEN viewer.class.paint[viewer, context, whatChanged, hint=all] ELSE IF hint=all OR hint=caption THEN BEGIN mark: Mark _ Save[context]; -- since Icons.DrawIcon will set clipper 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; Icons.DrawIcon[flavor: viewer.icon, context: context, label: label]; Restore[context, mark]; IF IconManager.selectedIcon=viewer THEN BEGIN [] _ SetPaintMode[context, invert]; DrawBox[context, [0, 0, iconWidth, iconHeight]]; END; END; ReleaseContext[context]; END; SetIconLabel: PUBLIC PROC [viewer: Viewer, label: Rope.ROPE] = BEGIN ViewerOps.AddProp[viewer, $IconLabel, label]; END; RecursivelyPaintViewers: PROC [viewer: Viewer, hint: PaintHint, clearClient: BOOL, clear: BOOL, rect: PaintRectangle, whatChanged: REF ANY] = BEGIN OPEN viewer; vx, vy: INTEGER; context: Context _ NIL; bitmapY: INTEGER _ 0; FOR v: Viewer _ viewer, v.parent UNTIL v=NIL DO -- visibility test IF v.parent#NIL THEN BEGIN 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; END ENDLOOP; IF hint#client THEN BEGIN ENABLE UNWIND => IF context#NIL THEN ReleaseContext[context]; context _ AcquireContext[parent, viewer.column=color]; IF ~viewer.visible OR viewer.destroyed THEN SIGNAL InvisiblePaint; IF clearClient AND ~clear AND hint=all THEN BEGIN SetColor[context, white]; DrawBox[context, XYWH2Box[wx, wy, ww, wh]]; SetColor[context, black]; clear _ TRUE; END; IF border AND hint=all THEN BEGIN wbs: INTEGER ~ windowBorderSize; DrawBox[context, XYWH2Box[wx, wy, ww, wbs]]; DrawBox[context, XYWH2Box[wx, wy, wbs, wh]]; DrawBox[context, XYWH2Box[wx+ww-wbs, wy, wbs, wh]]; DrawBox[context, XYWH2Box[wx, wy+wh-wbs, ww, wbs]]; END; IF parent=NIL AND viewer.column#static THEN PaintDocumentHeader[viewer, context, clear, hint, whatChanged]; ReleaseContext[context]; END; IF hint=all OR hint=client THEN BEGIN ENABLE UNWIND => IF context#NIL THEN ReleaseContext[context]; context _ NIL; context _ AcquireContext[viewer, viewer.column=color]; IF ~viewer.visible OR viewer.destroyed THEN SIGNAL InvisiblePaint; IF rect#NIL AND class.bltContents = none THEN clearClient _ TRUE; IF clearClient AND ~clear THEN BEGIN SetColor[context, white]; DrawBox[context, [0, 0, cw, ch]]; SetColor[context, black]; IF rect # NIL THEN whatChanged _ NIL; rect _ NIL; clear _ TRUE; END; IF class.paint#NIL THEN class.paint[viewer, context, whatChanged, clear]; ReleaseContext[context]; END; 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 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; END; PaintViewer: PUBLIC PROC [viewer: Viewer, hint: PaintHint _ client, clearClient: BOOL _ TRUE, whatChanged: REF ANY _ NIL] = BEGIN LocalPaintViewer: PROC = { ENABLE ABORTED => {Carets.ResumeCarets[]; CONTINUE}; rect: PaintRectangle; IF ~viewer.visible OR viewer.destroyed THEN RETURN; IF viewer.iconic THEN {PaintIcon[viewer, hint, whatChanged]; RETURN}; Carets.SuspendCarets[]; IF ISTYPE[whatChanged, PaintRectangle] THEN rect _ NARROW[whatChanged]; RecursivelyPaintViewers[viewer, hint, clearClient AND ~(hint=menu OR hint=caption), FALSE, rect, whatChanged ! InvisiblePaint => CONTINUE]; Carets.ResumeCarets[]}; ViewerLocks.CallUnderReadLock[LocalPaintViewer, viewer ! ViewerLocks.Wedged => CONTINUE]; END; 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; Init: ENTRY PROC = BEGIN 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; newFW _ VFonts.StringWidth[newFT]; newVW _ VFonts.StringWidth[newVT]; linkW _ VFonts.StringWidth[linkT]; sipW _ VFonts.StringWidth[sipT]; colorVector _ NEW[PaintVectorRec]; colorVector.color _ TRUE; END; colorInit: BOOL _ FALSE; InitialiseColorPainting: PUBLIC PROC = BEGIN ColorCriticalInit: ENTRY PROC = BEGIN colorVector.context _ ColorWorld.NewContext[]; SetDefaultFont[colorVector.context, VFonts.defaultGFont]; colorInit _ TRUE; END; ColorCriticalInit[]; ViewerOps.GreyScreen[0, 0, 9999, 9999, TRUE, FALSE]; END; ZapVector: INTERNAL PROC [p: PaintVector] = BEGIN 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; END; UnWedgePainter: PUBLIC ENTRY PROC [process: PROCESS, kind: ATOM] = BEGIN 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; END; UnWedge: ENTRY PROC [process: PROCESS, kind: ATOM] = BEGIN 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; END; DisablePainting: PUBLIC ENTRY PROC [wait: BOOL _ TRUE] = BEGIN ENABLE UNWIND => NULL; InternalDisablePainting[wait]; END; InternalDisablePainting: INTERNAL PROC [wait: BOOL _ TRUE] = INLINE BEGIN IF wait THEN WHILE usedVectors#0 OR colorVector.inUse DO WAIT PaintVectorAvailable; ENDLOOP; paintingLock _ paintingLock+1; END; EnablePainting: PUBLIC ENTRY PROC = BEGIN ENABLE UNWIND => NULL; InternalEnablePainting[]; END; InternalEnablePainting: INTERNAL PROC = INLINE BEGIN IF paintingLock#0 THEN paintingLock _ paintingLock-1; IF paintingLock=0 THEN BROADCAST PaintVectorAvailable; END; DisablePaintingUnWedged: INTERNAL PROC [wait: BOOL _ TRUE] = INLINE BEGIN AllWedged: INTERNAL PROC RETURNS[BOOL] = INLINE BEGIN IF colorVector.inUse THEN BEGIN IF colorVector.viewer=NIL THEN RETURN[FALSE]; -- context = screen IF ~ViewerLocks.ColumnWedged[color].wedged THEN RETURN[FALSE]; END; 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]; END; IF wait THEN WHILE usedVectors#0 OR colorVector.inUse DO IF AllWedged[] THEN EXIT ELSE WAIT PaintVectorAvailable; ENDLOOP; paintingLock _ paintingLock+1; END; WaitForPaintingToFinish: PUBLIC ENTRY PROC = BEGIN WHILE usedVectors#0 AND colorVector.inUse DO WAIT PaintVectorAvailable ENDLOOP; END; ResetPaintCache: PUBLIC ENTRY PROC [viewer: Viewer _ NIL, wait: BOOL _ TRUE] = BEGIN ENABLE UNWIND => NULL; DisablePaintingUnWedged[wait]; FOR p: PaintVector _ vectorRoot, p.next UNTIL p=NIL DO IF p.inUse THEN BEGIN IF p.viewer = NIL OR ~ViewerLocks.ColumnWedged[ViewerColumn[p.viewer]].wedged THEN IF wait THEN RETURN WITH ERROR fatalViewersError; p.resetOnRelease _ TRUE; END ELSE IF p.viewer#NIL THEN BEGIN ResetContext[p.context]; p.viewer _ NIL; END; ENDLOOP; IF colorVector.context#NIL THEN BEGIN IF colorVector.inUse AND ~ViewerLocks.ColumnWedged[color].wedged THEN BEGIN IF wait THEN RETURN WITH ERROR fatalViewersError; colorVector.resetOnRelease _ TRUE; END ELSE IF colorVector.viewer#NIL THEN BEGIN ResetContext[colorVector.context]; colorVector.viewer _ NIL; END; END; InternalEnablePainting[]; END; fatalViewersError: ERROR = CODE; ReleaseContext: PUBLIC ENTRY PROC [free: Context] = BEGIN ENABLE UNWIND => NULL; CleanUp: INTERNAL PROC [p: PaintVector] = BEGIN 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 BEGIN ResetContext[p.context]; p.viewer _ NIL; p.resetOnRelease _ FALSE; END; p.process _ NIL; BROADCAST PaintVectorAvailable; END; 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; END; AcquireContext: PUBLIC ENTRY PROC [viewer: Viewer, color: BOOL _ FALSE] RETURNS [allocated: Context] = BEGIN ENABLE UNWIND => NULL; bestFit: PaintVector; nil: BOOL _ FALSE; MakeFirst: INTERNAL PROC [pv: PaintVector] = INLINE BEGIN -- 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; END; IF color THEN BEGIN 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; END ELSE BEGIN 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; END; PushContext: INTERNAL PROC [viewer: Viewer, context: Context] = BEGIN 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 BEGIN IF wy+wh > openBottomY THEN ClipIcon[context]; ClipBox[context, XYWH2Box[wx, wy, ww, wh]]; Translate[context, wx, wy]; END ELSE IF invertCoords THEN BEGIN ClipBox[context, XYWH2Box[cx, cy, cw, ch]]; Translate[context, cx, cy+ch]; Scale[context, 1, -1]; END ELSE BEGIN ClipBox[context, XYWH2Box[cx, cy, cw, ch]]; Translate[context, cx, cy]; END; END; PopContext: INTERNAL PROC [context: Context] = INLINE BEGIN Restore[context]; END; ResetContext: INTERNAL PROC [context: Context] = INLINE BEGIN screen: Mark = LOOPHOLE[0]; Restore[context, screen]; END; InvertForMenus: PUBLIC PROC [viewer: Viewer, x,y: INTEGER, w,h: INTEGER] = BEGIN context: Context; context _ AcquireContext[viewer.parent, viewer.column=color]; [] _ SetPaintMode[context, invert]; DrawBox[context, ViewerOps.XYWH2Box[viewer.wx+x, y, MIN[w,viewer.ww-x], h]]; ReleaseContext[context]; END; ClipIcon: PROC [context: Context] = BEGIN ClipOpenViewer: ViewerOps.EnumProc = BEGIN IF ~v.iconic AND (v.column=right OR v.column=left) THEN Graphics.ClipBox[context, [v.wx, v.wy, v.wx+v.ww, v.wy+v.wh], TRUE]; END; ViewerOps.EnumerateViewers[ClipOpenViewer]; END; BlinkIcon: PUBLIC PROC [viewer: Viewer, count, interval: NAT] = BEGIN 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]]}; END; BlinkProcess: PROC [viewer: Viewer, count, n: NAT] = BEGIN howOften: Process.Ticks = Process.MsecToTicks[500]; Blink: PROC = BEGIN OPEN viewer; context: Context; IF NOT visible OR destroyed THEN RETURN; context _ AcquireContext[viewer, IF iconic THEN FALSE ELSE column=color]; [] _ SetPaintMode[context, invert]; DrawBox[context, ViewerOps.XYWH2Box[0, 0, viewer.ww, viewer.wh]]; Process.Pause[Process.MsecToTicks[400]]; DrawBox[context, ViewerOps.XYWH2Box[0, 0, viewer.ww, viewer.wh]]; ReleaseContext[context]; Process.Pause[Process.MsecToTicks[350]]; -- so can be called back-to-back END; 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; END; newVT: Rope.ROPE = " [New Version]"; newVW: INTEGER; newFT: Rope.ROPE = " [New File]"; newFW: INTEGER; linkT: Rope.ROPE = " [Split]"; linkW: INTEGER; sipT: Rope.ROPE = " [Saving...]"; sipW: INTEGER; Init[]; ViewerOps.GreyScreen[0, 0, 9999, 9999, FALSE, FALSE]; END. pViewerPaintImpl.mesa; written by S. McGregor Edited by McGregor on May 2, 1983 11:11 am Edited by Maxwell, June 3, 1983 8:23 am Last Edited by: Pausch, June 20, 1983 10:40 pm 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 call from debugger broadcast since all are likely to be free assumes interesting paints already in progress RFP: altered to keep box within the viewer for partially visible buttons clips for overlapping top level windows given valid Context and Viewer Κi– "Mesa" style˜JšΟc,™,Jš*™*J™'J™.šΟk ˜ Jšœžœ˜+Jšœ žœ˜šœ žœ-˜;J˜>J˜H—Jšœ žœ ˜Jšœ žœ˜!Jšœžœ ˜Jšœžœ˜Jšœ žœ ˜Jšœžœ1˜>Jšœžœžœ˜Jšœžœ*˜6J˜ J˜Jšœ žœ@˜QJšœ ˜ J˜Jšœ žœ˜&J˜—Jšœž ˜J˜Jšžœ˜–Jšžœ ˜'Jšžœ$˜*J˜Jšžœžœ1˜;J˜Jšœžœžœžœ˜%J˜š Οnœžœ+žœ žœžœ˜rJšžœžœ˜Jš œžœžœžœžœ˜=J˜)šžœ žœž˜š žœžœžœžœ˜@J˜˜AJ˜ —J˜&J˜Jšž˜—šžœž˜ Jšœ žœ˜,Jšžœžœ˜6Jšžœžœžœ˜5Jšžœžœžœ˜9Jšžœ žœžœ˜2Jšœ žœ˜J˜GJ˜J˜;J˜Jšžœžœ˜5Jšžœžœžœ˜4Jšžœžœžœ˜8Jšžœ žœžœ˜1Jšžœ˜—Jšžœ˜—š žœžœžœžœž˜'Jšœžœ˜,šžœ žœžœž˜šžœžœž˜J˜˜=J˜—Jšžœ˜—J˜˜JJ˜—Jšžœ˜—˜3J˜-—Jšžœ˜—Jšžœ˜J˜—š Ÿ œžœ0žœžœžœž˜UJ˜Jšœ žœ˜J˜Jšžœžœžœžœ˜!J˜Jšœ!žœ˜DJ˜Jš7™7Jšžœžœ;˜VJ˜š žœžœ žœžœž˜+Jšœ(˜Dšžœžœžœž˜FJ˜—š žœžœžœžœžœž˜TJ˜—Jšœžœ*˜8Jšžœ žœžœ˜(J˜DJ˜šžœ!žœž˜-J˜#J˜0Jšžœ˜—Jšžœ˜J˜—J˜Jšžœ˜—J˜š Ÿ œžœžœžœž˜DJ˜-Jšžœ˜J˜—šŸœžœ0žœ˜RJš œžœ%žœžœžœžœ˜MJšœžœ˜Jšœžœ˜Jšœ žœ˜J˜š žœžœžœžœ˜Bšžœ žœžœž˜Jšžœžœžœžœ˜7Jšžœžœžœžœ˜7Jšž˜—Jšžœ˜—J˜šžœ žœž˜Jš žœžœžœ žœžœ˜=J˜6Jšžœžœžœžœ˜Bš žœ žœžœ žœž˜1J˜J˜+J˜Jšœžœ˜ Jšžœ˜—šžœžœ žœž˜!Jšœžœ˜ J˜,J˜,J˜3J˜3Jšžœ˜—šžœžœžœ˜'Jšžœ@˜D—J˜Jšžœ˜J˜—šžœ žœ žœž˜%Jš žœžœžœ žœžœ˜=Jšœ žœ8˜EJšžœžœžœžœ˜BJš žœžœžœžœžœ˜Ašžœ žœžœž˜$J˜J˜!J˜Jšžœžœžœžœ˜%Jšœžœ˜ Jšœžœ˜ Jšžœ˜—Jšžœ žœžœ2˜IJ˜Jšžœ˜J˜—Jšœ(™(š žœžœžœžœžœ˜.šžœžœ,ž˜IJšœžœ,žœžœ˜P——J˜Jš™šžœ žœ žœž˜(JšB™Bšžœ%žœžœž˜6šžœžœžœ2˜GJš-˜-šžœ˜JšžœA˜EJšžœ=˜A—šžœžœ ž˜6Jšœ žœ žœžœ˜;——Jšœ žœ˜AJšžœ˜J˜——Jšžœ˜J˜—š Ÿ œžœžœ9žœžœ˜]Jšœ žœžœžœž˜#šŸœžœ˜Jšžœžœžœ˜4J˜Jšžœžœžœžœ˜3Jšžœžœ(žœ˜EJ˜Jšžœžœžœžœ˜Gšœ2žœ žœ˜SJšžœ(žœ˜7—Jšœ˜—JšœOžœ˜YJšžœ˜J˜J˜—Jšœ žœžœ˜'šœžœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜J˜Jšœ žœžœ˜Jšœžœ˜Jšœžœ˜J˜—Jšœ žœ˜Jšœ žœ˜Jšœž œ˜ Jšœžœ˜J˜Jšœžœ˜Jšœžœ˜J˜šŸœžœžœž˜J˜šžœžœžœž˜#Jšœžœ˜J˜J˜1J˜Jšžœ žœžœ˜1J˜Jšžœ˜—J˜"J˜"J˜"J˜ Jšœžœ˜"Jšœžœ˜Jšžœ˜J˜—Jšœ žœžœ˜J˜šŸœžœžœž˜,šŸœžœžœž˜%J˜.J˜9Jšœ žœ˜Jšžœ˜—J˜Jšœ'žœžœ˜4Jšžœ˜J˜—šŸ œžœžœž˜1J˜ Jšœ žœ žœžœ˜FJ˜8Jšœ žœ˜Jšœ žœ˜Jšœ žœ˜J˜Jšžœ žœ˜/Jšœ! ˜-Jšž œ˜Jšžœ˜J˜—š Ÿœžœžœžœ žœžœž˜HJšžœžœžœ˜Jšžœžœžœ˜Pš žœžœ%žœžœž˜;Jšžœ žœžœ˜3Jšžœ˜—Jšžœ˜J˜—š Ÿœžœžœ žœžœž˜:Jš™Jšžœžœ˜0š žœžœ%žœžœž˜;Jšžœ žœ˜Jšžœ˜—Jšœ ˜Jšœ ˜Jšž œ˜Jšžœ˜J˜—š Ÿœžœžœžœžœžœž˜>Jšžœžœžœ˜J˜Jšžœ˜š Ÿœžœžœžœžœžœž˜Išžœž˜ Jšžœžœžœžœ˜GJšžœ˜J˜—Jšžœ˜J˜——š Ÿœžœžœžœž˜)Jšžœžœžœ˜J˜Jšžœ˜š Ÿœžœžœžœž˜4Jšžœžœ˜5Jš)™)Jšžœžœž œ˜6Jšžœ˜——J˜š Ÿœžœžœžœžœžœž˜Iš Ÿ œžœžœžœžœžœž˜5šžœžœž˜Jš žœžœžœžœžœ˜AJšžœ)žœžœžœ˜>Jšžœ˜—šžœ%žœžœž˜6Jšžœ žœžœ˜Jš žœ žœžœžœžœ˜9Jšžœ:žœžœžœ˜OJšžœ˜—Jšžœžœ˜ Jšžœ˜J˜—šžœž˜ šžœžœžœ˜,Jš žœ žœžœžœžœ˜9—Jšžœ˜J˜—Jšžœ˜J˜—š Ÿœžœžœžœž˜2Jš.™.Jš žœžœžœžœžœ˜OJšžœ˜J˜—šŸœžœžœžœžœžœžœž˜TJšžœžœžœ˜J˜šžœ%žœžœž˜6šžœ žœž˜šžœ žœžœ:˜NJš žœžœžœžœžœ˜6—Jšœžœ˜Jšž˜—š žœžœ žœžœž˜J˜Jšœ žœ˜Jšžœ˜—Jšžœ˜—šžœžœžœž˜%šžœžœ'žœž˜KJš žœžœžœžœžœ˜1Jšœžœ˜"Jšž˜—š žœžœžœžœž˜)J˜"Jšœžœ˜Jšžœ˜—Jšžœ˜—J˜Jšžœ˜J˜—Jšœžœžœ˜ J˜š Ÿœžœžœžœž˜9Jšžœžœžœ˜šŸœžœžœž˜/Jšœ ˜7Jšœ žœ˜J˜šžœ žœžœžœžœžœžœ˜KJšžœ˜"—šžœžœž˜J˜Jšœ žœ˜Jšœžœ˜Jšžœ˜—Jšœ žœ˜Jšž œ˜Jšžœ˜—Jš žœžœžœžœžœžœ˜5Jšžœžœ˜5š žœžœ%žœžœž˜;Jšžœžœžœ˜*Jšžœ˜—Jšžœ˜J˜—š Ÿœžœžœžœžœžœ˜GJšžœž˜$Jšžœžœžœ˜J˜Jšœžœžœ˜J˜š Ÿ œžœžœžœžœ˜OJšžœžœžœ˜J˜Jšžœ žœžœ ˜3J˜J˜J˜Jšžœ˜J˜—šžœžœž˜Jšžœ žœžœ˜+Jš žœžœžœžœžœ˜Pš žœžœžœžœž˜žœ˜D—Jšžœ˜—J˜+Jšžœ˜J˜—šŸ œž œ#žœž˜EJ˜2Jšžœžœ&˜?Jšžœ žœ&˜7Jšžœžœžœ)˜JJšžœ˜J˜—šŸ œžœžœž˜;Jšœ3˜3šŸœžœž œ˜ J˜Jš žœžœ žœ žœžœ˜(Jš œ!žœžœžœžœ˜IJ˜#J˜AJ˜(J˜AJ˜Jšœ) ˜IJšžœ˜J˜—šž˜J˜.Jšžœ žœžœ˜Jšžœ žœ˜$š žœžœžœ žœ8˜SJšœ˜šžœžœ˜&Jšžœ*žœžœ˜8—Jšžœ˜—Jšžœ˜—Jšžœ˜J˜—J˜Jšœ žœ˜%Jšœžœ˜J˜Jšœ žœ˜"Jšœžœ˜J˜Jšœ žœ˜Jšœžœ˜J˜Jšœ žœ˜"Jšœžœ˜J˜J˜J˜Jšœ'žœžœ˜5J˜Jšžœ˜J˜J˜—…—Ej_C