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, SetStipple, Translate, white], GraphicsColor USING [IntensityToColor], 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, GraphicsColor, 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] = 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 ~clear 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, whatChanged: REF ANY] = BEGIN OPEN viewer; 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 ~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]; 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 clearClient AND ~clear THEN BEGIN SetColor[context, white]; DrawBox[context, [0, 0, cw, ch]]; SetColor[context, black]; clear _ TRUE; END; IF class.paint#NIL THEN class.paint[viewer, context, whatChanged, clear]; ReleaseContext[context]; END; IF hint=all OR clear THEN FOR v: Viewer _ viewer.child, v.sibling UNTIL v=NIL DO RecursivelyPaintViewers[v, all, FALSE, clear, NIL]; 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}; IF ~viewer.visible OR viewer.destroyed THEN RETURN; IF viewer.iconic THEN {PaintIcon[viewer, hint, whatChanged]; RETURN}; Carets.SuspendCarets[]; RecursivelyPaintViewers[viewer, hint, clearClient AND ~(hint=menu OR hint=caption), FALSE, 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[]; 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 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.parent=viewer => PopContext[pContext]; pViewer.parent=viewer.parent => {PopContext[pContext]; PushContext[viewer, pContext]}; ENDCASE => {ResetContext[pContext]; RecursivelyPushParent[viewer]}; paintVector.viewer _ viewer; 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; 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, w, h]]; ReleaseContext[context]; END; GreyScreen: PUBLIC PROC [x,y,w,h: INTEGER, color, icon: BOOL, stipple: CARDINAL _ 104042B] = BEGIN context: Context _ AcquireContext[NIL, color]; IF icon AND y+h > openBottomY THEN ClipIcon[context]; IF color THEN SetColor[context, GraphicsColor.IntensityToColor[.5]] ELSE SetStipple[context, stipple]; DrawBox[context, ViewerOps.XYWH2Box[x, y, w, h]]; ReleaseContext[context]; 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[]; GreyScreen[0, 0, 9999, 9999, FALSE, FALSE]; END. ViewerPaintImpl.mesa; written by S. McGregor Edited by McGregor on April 5, 1983 5:01 pm Edited by Maxwell, February 7, 1983 1:37 pm IF flavor is private then client wants to draw the icon -- SetCP[context, 0, 0]; ++ normalise things for client now 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 clips for overlapping top level windows given valid Context and Viewer Κƒ– "Mesa" style˜JšΟc,™,Jš+™+J™+J™šΟk ˜ Jšœžœ˜+Jšœ žœ˜šœ žœ-˜;J˜>J˜T—Jšœžœ˜'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œžœ+žœ˜\Jšžœžœ˜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š œžœžœžœžœžœ˜7Jšœžœ˜Jšœ žœ˜J˜š žœžœžœžœ˜Bšžœ žœžœž˜Jšžœžœžœžœ˜7Jšžœžœžœžœ˜7Jšž˜—Jšžœ˜J˜—šžœ žœž˜Jš žœžœžœ žœžœ˜=J˜6Jšžœžœžœžœ˜Bšžœžœ žœž˜!J˜J˜+J˜Jšœžœ˜ Jšžœ˜—šžœžœ žœž˜!Jšœžœ˜ J˜,J˜,J˜3J˜3Jšžœ˜—šžœžœžœ˜'Jšžœ3˜7—J˜Jšžœ˜J˜—šžœ žœ žœž˜%Jš žœžœžœ žœžœ˜=Jšœ žœ8˜EJšžœžœžœžœ˜Bšžœ žœžœž˜$J˜J˜!J˜Jšœžœ˜ Jšžœ˜—Jšœ7™7Jšžœ žœžœ2˜IJ˜Jšžœ˜J˜—Jš™šžœ žœž˜JšB™Bšžœ%žœžœž˜6Jšœ žœ žœ˜3Jšžœ˜J˜——Jšžœ˜J˜—š Ÿ œžœžœ9žœžœ˜]Jšœ žœžœžœž˜#šŸœžœ˜Jšžœžœžœ˜4Jšžœžœžœžœ˜3Jšžœžœ(žœ˜EJ˜šœ2žœ žœ˜SJšžœ"žœ˜1—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šœžœžœ˜*Jšžœ˜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šžœ%žœžœž˜6Jšžœ žœžœ˜Jš žœ žœžœžœžœ˜9šžœ:˜žœ˜D—Jšžœ˜—J˜+Jšžœ˜J˜—š Ÿ œžœžœ&žœžœ˜Rš œžœžœžœžœ˜HJšžœ4˜8—J˜šžœžœž˜Jšžœžœ˜.J˜+J˜Jšž˜—šžœžœžœž˜J˜+J˜J˜Jšž˜—šžœž˜ J˜+J˜Jšžœ˜—Jšžœ˜J˜—š Ÿ œžœžœžœž˜;J˜Jšžœ˜J˜—š Ÿ œžœžœžœž˜=Jšœžœ˜J˜Jšžœ˜J˜—š Ÿœžœžœžœžœž˜PJ˜J˜=J˜#J˜;J˜Jšžœ˜J˜—š Ÿ œžœžœ žœžœ˜>Jšœ žœž˜$Jšœ"žœ ˜.Jšžœžœžœ˜5šžœžœ6˜CJšžœ˜"—J˜1J˜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šœžœžœ˜+J˜Jšžœ˜J˜J˜—…—BbZχ