DIRECTORY Basics, BasicTime, Idle, IdleBackdoor, Imager, ImagerBackdoor, ImagerFont, ImagerSample, InputFocus, KeySymsKB, KeyMapping, KeyTypes, MultiCursors, Process, Real, Rope, SpecialKeySyms, TIPPrivate, UserInput, UserInputOps, ViewerClasses, ViewerOps, ViewerPrivate, ViewersWorld, ViewersWorldInstance, ViewersWorldTypes, ViewersWorldRefType; IdleImpl: CEDAR MONITOR IMPORTS Basics, BasicTime, Imager, ImagerBackdoor, ImagerFont, ImagerSample, InputFocus, KeyMapping, MultiCursors, Process, Real, TIPPrivate, UserInputOps, ViewerOps, ViewerPrivate, ViewersWorld, ViewersWorldInstance EXPORTS Idle, IdleBackdoor, ViewersWorldRefType = BEGIN ViewersWorldRef: TYPE = REF ViewersWorldObj; ViewersWorldObj: PUBLIC TYPE = ViewersWorldTypes.ViewersWorldObj; Activity: TYPE ~ IdleBackdoor.Activity; Animator: TYPE ~ IdleBackdoor.Animator; AnimatorPrivate: TYPE ~ IdleBackdoor.AnimatorPrivate; FullIdleHandler: TYPE ~ IdleBackdoor.FullIdleHandler; KeyFilter: TYPE ~ IdleBackdoor.KeyFilter; IdleRegistration: TYPE ~ Idle.IdleRegistration; IdleHandler: TYPE ~ Idle.IdleHandler; ImageProc: TYPE ~ Idle.ImageProc; KeyCode: TYPE ~ KeyTypes.KeyCode; NotifyProc: TYPE ~ ViewerClasses.NotifyProc; ROPE: TYPE ~ Rope.ROPE; AnimatorList: TYPE ~ LIST OF Animator; Bug: ERROR ~ CODE; idleWorld: ViewersWorldTypes.Ref ฌ ViewersWorldInstance.GetWorld[]; becomeIdle, outOfIdle: CONDITION; idleState: Activity ฌ unidle; newState: Activity ฌ unidle; -- just to initialize to something changeComing: BOOL ฌ FALSE; enabled: BOOL ฌ TRUE; fullRegistry: FullIdleHandlerList ฌ NIL; animatorStack: AnimatorList ฌ NIL; FullIdleHandlerList: TYPE ~ LIST OF FullIdleHandlerRecord; FullIdleHandlerRecord: TYPE ~ RECORD [proc: FullIdleHandler, data: REF ANY]; RegisterFullIdleHandler: PUBLIC ENTRY PROC [handler: FullIdleHandler, data: REF ฌ NIL] RETURNS [IdleRegistration] ~ { fullRegistry ฌ CONS[[handler, data], fullRegistry]; RETURN [fullRegistry]; }; UnregisterFullIdleHandler: PUBLIC ENTRY PROC [registration: IdleRegistration] = { ENABLE UNWIND => NULL; lag: FullIdleHandlerList ฌ NIL; FOR each: FullIdleHandlerList ฌ fullRegistry, each.rest WHILE each # NIL DO IF each = registration THEN { IF lag = NIL THEN fullRegistry ฌ each.rest ELSE lag.rest ฌ each.rest; EXIT; }; lag ฌ each; ENDLOOP; }; CopyRegistry: INTERNAL PROC RETURNS [head: FullIdleHandlerList ฌ NIL] = { ENABLE UNWIND => NULL; tail: FullIdleHandlerList ฌ NIL; FOR each: FullIdleHandlerList ฌ fullRegistry, each.rest WHILE each # NIL DO new: FullIdleHandlerList = LIST[each.first]; IF tail = NIL THEN head ฌ new ELSE tail.rest ฌ new; tail ฌ new; ENDLOOP; }; GetAnimator: PUBLIC ENTRY PROC RETURNS [Animator] ~ { ENABLE UNWIND => NULL; RETURN [animatorStack.first]; }; SetAnimator: PUBLIC ENTRY PROC [a: Animator] ~ { ENABLE UNWIND => NULL; WHILE idleState#unidle DO WAIT outOfIdle ENDLOOP; animatorStack.first ฌ a; }; PushAnimator: PUBLIC ENTRY PROC [a: Animator] ~ { ENABLE UNWIND => NULL; WHILE idleState#unidle DO WAIT outOfIdle ENDLOOP; animatorStack ฌ CONS[a, animatorStack]; }; PopAnimator: PUBLIC ENTRY PROC ~ { ENABLE UNWIND => NULL; WHILE idleState#unidle DO WAIT outOfIdle ENDLOOP; IF animatorStack.rest#NIL THEN animatorStack ฌ animatorStack.rest; }; FinishSet: PROC [changed: BOOL, reg: FullIdleHandlerList] ~ { FOR each: FullIdleHandlerList ฌ reg, each.rest WHILE each # NIL DO ENABLE UNWIND => LOOP; IF each.first.proc#NIL THEN each.first.proc[each.first.data, idleState, newState]; ENDLOOP; }; IsKeyDown: PROC [watch: KeyFilter] RETURNS [BOOL] = { IF ViewersWorldInstance.GetWorld[]#idleWorld THEN RETURN [FALSE]; FOR k: KeyCode IN [watch.first .. watch.last] DO IF UserInputOps.GetLatestKeyState[ViewersWorld.GetInputHandle[idleWorld], k] = down AND watch.pass[k] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; WaitForLogin: PROC ~ { SIGNAL NotYetImplemented; }; NotYetImplemented: SIGNAL = CODE; DoLogin: PROC RETURNS [wake: BOOL ฌ TRUE] = { }; defaultKeyFilter: PUBLIC KeyFilter ฌ [first: VAL[1], last: VAL[125], pass: ALL[TRUE]]; DefaultKeyFilter: PROC RETURNS [KeyFilter] ~ { FirstKeyCode: PROC [mapping: KeyMapping.Mapping, keySym: KeyTypes.KeySym] RETURNS [keyCode: KeyTypes.KeyCode ฌ keycode0] = { keyCodes: KeyMapping.KeyCodes ~ KeyMapping.KeyCodesFromKeySym[mapping, keySym]; IF keyCodes.n>0 THEN RETURN [keyCodes[0].keyCode] }; filter: KeyFilter ฌ [first: VAL[1], last: VAL[125], pass: ALL[TRUE]]; handle: UserInput.Handle ฌ ViewersWorld.GetInputHandle[idleWorld]; mapping: KeyMapping.Mapping ~ UserInputOps.GetMapping[handle]; lockCode1, lockCode2, controlCode, leftShiftCode, rightShiftCode, leftMouseCode, middleMouseCode, rightMouseCode: KeyCode; lockCode1 ฌ FirstKeyCode[mapping, KeySymsKB.ShiftLock].keyCode; lockCode2 ฌ FirstKeyCode[mapping, KeySymsKB.CapsLock].keyCode; controlCode ฌ FirstKeyCode[mapping, KeySymsKB.LeftControl].keyCode; leftShiftCode ฌ FirstKeyCode[mapping, KeySymsKB.LeftShift].keyCode; rightShiftCode ฌ FirstKeyCode[mapping, KeySymsKB.RightShift].keyCode; leftMouseCode ฌ FirstKeyCode[mapping, SpecialKeySyms.Button1].keyCode; middleMouseCode ฌ FirstKeyCode[mapping, SpecialKeySyms.Button2].keyCode; rightMouseCode ฌ FirstKeyCode[mapping, SpecialKeySyms.Button3].keyCode; filter.pass[lockCode1] ฌ FALSE; filter.pass[lockCode2] ฌ FALSE; filter.pass[controlCode] ฌ FALSE; filter.pass[leftShiftCode] ฌ FALSE; filter.pass[rightShiftCode] ฌ FALSE; filter.pass[leftMouseCode] ฌ FALSE; filter.pass[middleMouseCode] ฌ FALSE; filter.pass[rightMouseCode] ฌ FALSE; RETURN[filter]; }; SimpleReg: TYPE = REF SimpleRegPrivate; SimpleRegPrivate: TYPE = RECORD [ handler: IdleHandler, data: REF ANY ]; IsIdle: PUBLIC PROC RETURNS [BOOL] = { RETURN [idleState # unidle]; }; RegisterIdleHandler: PUBLIC PROC [handler: IdleHandler, data: REF ฌ NIL] RETURNS [IdleRegistration]= { sr: SimpleReg ฌ NEW [SimpleRegPrivate ฌ [handler, data]]; RETURN [RegisterFullIdleHandler[Simplify, sr]]; }; Simplify: PROC [data: REF ANY, old, new: Activity] --FullIdleHandler-- ~ { sr: SimpleReg ~ NARROW[data]; IF old=unidle AND new=idle THEN sr.handler[sr.data, becomingIdle] ELSE IF old=loggingIn AND new=unidle THEN sr.handler[sr.data, becomingBusy]; }; UnregisterIdleHandler: PUBLIC PROC [registration: IdleRegistration] = { UnregisterFullIdleHandler[registration]; }; sleepMillis: [10..2000] ฌ 150; xVel: INTEGER ฌ 2; yVel: INTEGER ฌ 1; sleepEraseOld: BOOL ฌ TRUE; sleepWaitFactor: [5..100] ฌ 20; ticksPerSecond: Process.Ticks = Process.SecondsToTicks[1]; WaitForIdle: PUBLIC ENTRY PROC [idle: BOOL] ~ { WHILE idleState # idle DO WAIT becomeIdle ENDLOOP; }; DoASleep: PUBLIC PROC ~ { an: Animator ฌ animatorStack.first; BecomeIdle[]; an.Animate[idleWorld, IsKeyDown, an.data]; OutOfIdle[]; ViewerOps.PaintEverything[]; }; Sleep: PUBLIC PROC [proc: Idle.ImageProc ฌ DefaultImageProc, powerOff: BasicTime.GMT ฌ BasicTime.nullGMT] = { IF proc=DefaultImageProc THEN DoASleep[] ELSE { an: Animator; TRUSTED {an ฌ NEW [AnimatorPrivate ฌ [Bounce, NEW [Idle.ImageProc ฌ proc]]]}; PushAnimator[an]; DoASleep[]; PopAnimator[]; }; }; StringEscapement: PROC [font: ImagerFont.Font, string: ImagerFont.XStringProc, amplifySpace: REAL] RETURNS [ImagerFont.VEC] = { sum: ImagerFont.VEC ฌ [0, 0]; charAction: ImagerFont.XCharProc ~ { width: ImagerFont.VEC; width ฌ ImagerFont.Escapement[font, char]; IF ImagerFont.Amplified[font, char] THEN { width.x ฌ width.x*amplifySpace; width.y ฌ width.y*amplifySpace; }; sum.x ฌ sum.x+width.x; sum.y ฌ sum.y+width.y; }; string[charAction]; RETURN[sum]; }; RopeEscapement: PROC [font: ImagerFont.Font, rope: Rope.ROPE, amplifySpace: REAL, start: INT ฌ 0, len: INT ฌ INT.LAST] RETURNS [ImagerFont.VEC] ~ { string: ImagerFont.XStringProc ~ { ImagerFont.MapRope[rope, start, len, charAction] }; RETURN[StringEscapement[font, string, amplifySpace]]; }; DoNothing: NotifyProc = {}; NullContextCreator: PROC [screenServerData: REF, screen: ViewerPrivate.Screen] RETURNS [Imager.Context] = { sm: ImagerSample.SampleMap = ImagerSample.NewSampleMap[box: [max: [1, 1]]]; RETURN [ImagerBackdoor.BitmapContext[sm]] }; BecomeIdle: ENTRY PROC = { idleState ฌ idle; idleContext ฌ ViewerPrivate.CreateContext[main]; InputFocus.CaptureButtons[DoNothing, TIPPrivate.DefaultTable[FALSE]]; oldContextCreatorProc ฌ ViewerPrivate.SetCreator[NullContextCreator]; BROADCAST becomeIdle; }; OutOfIdle: ENTRY PROC = { idleState ฌ unidle; idleContext ฌ NIL; InputFocus.ReleaseButtons[]; [] ฌ ViewerPrivate.SetCreator[oldContextCreatorProc]; BROADCAST outOfIdle; }; idleContext: Imager.Context; -- context for Idle to use oldContextCreatorProc: ViewerPrivate.ContextCreatorProc; ColorScreen: PROC [screen: ViewerPrivate.Screen, color: Imager.Color] = { colorAction: PROC [context: Imager.Context] ~ { Imager.SetColor[context, color]; Imager.MaskRectangleI[context, 0, 0, 9999, 9999]; }; PaintScreen[screen, colorAction]; }; PaintScreen: PROC [screen: ViewerPrivate.Screen, action: PROC [context: Imager.Context] ] = { IF idleContext=NIL THEN RETURN; action[idleContext ! UNWIND => CONTINUE;]; }; Bounce: PROC [world: ViewersWorld.Ref, ShouldReturn: PROC [watch: KeyFilter] RETURNS [BOOL], data: REF ANY ฌ NIL] = TRUSTED { proc: Idle.ImageProc ~ WITH data SELECT FROM x: REF Idle.ImageProc => xญ, ENDCASE => IF data=NIL THEN DefaultImageProc ELSE ERROR; width: NAT ฌ ViewersWorld.GetSize[world].width; height: NAT ฌ ViewersWorld.GetSize[world].height; x: NAT ฌ (width / 8)*3; y: NAT ฌ (height / 8)*3; image: Rope.ROPE ฌ "Type Key"; font: Imager.Font ฌ Imager.FindFontScaled["Xerox/XC1-2-2/Helvetica", 14.0]; vec: ImagerFont.VEC ฌ RopeEscapement[font, image, 1.0]; fontExtents: ImagerFont.Extents ฌ ImagerFont.RopeBoundingBox[font, image]; imageWidth: NAT ฌ Real.Ceiling[vec.x]; descent: INTEGER ฌ Real.Ceiling[fontExtents.descent]; imageHeight: NAT ฌ descent + Real.Ceiling[fontExtents.ascent]; termW: NAT = width; maxW: NAT = termW - termW/4; termH: NAT = height; maxH: NAT = termH - termH/4; <>ColorScreen[main, Imager.black]; DO mark: BasicTime.Pulses ฌ BasicTime.GetClockPulses[]; w: CARDINAL ฌ 0; h: CARDINAL ฌ 0; oldX: INTEGER ฌ x; oldY: INTEGER ฌ y; IF image # NIL THEN { newX: INTEGER ฌ x + xVel; newY: INTEGER ฌ y + yVel; xLim: INTEGER ฌ newX + (w ฌ MIN[imageWidth, maxW]); yLim: INTEGER ฌ newY + (h ฌ MIN[imageHeight, maxH]); SELECT TRUE FROM newX < 0 => { newX ฌ 0; xLim ฌ newX + w; xVel ฌ - xVel; }; xLim > termW => { xLim ฌ termW; newX ฌ xLim - w; xVel ฌ - xVel; }; ENDCASE; SELECT TRUE FROM newY < 0 => { newY ฌ 0; yLim ฌ newY + h; yVel ฌ - yVel; }; yLim > termH => { yLim ฌ termH; newY ฌ yLim - h; yVel ฌ - yVel; }; ENDCASE; x ฌ newX; y ฌ newY; }; IF proc # NIL THEN { image ฌ proc[w: w, h: h]; IF sleepEraseOld THEN { PaintRectangleBlack: SAFE PROC [context: Imager.Context] = CHECKED { Imager.SetColor[context, Imager.black]; Imager.MaskRectangleI[context, oldX, oldY-descent, w, h]; }; <>PaintScreen[main, PaintRectangleBlack]; }; IF image # NIL THEN { DrawRope: SAFE PROC [context: Imager.Context] = TRUSTED { Imager.SetXY[context, [x, y]]; Imager.SetFont[context, font]; Imager.SetColor[context, Imager.white]; Imager.ShowRope[context, image]; }; <>PaintScreen[main, DrawRope]; }; }; { limit: BasicTime.Pulses ฌ (BasicTime.GetClockPulses[] - mark)*sleepWaitFactor; DO IF ShouldReturn[defaultKeyFilter] THEN GO TO done; Process.Pause[2]; IF BasicTime.Pulses[BasicTime.GetClockPulses[] - mark] > limit THEN EXIT; ENDLOOP; EXITS done => EXIT; }; ENDLOOP; }; DefaultImageProc: PUBLIC Idle.ImageProc = {RETURN["Type Key"]}; defaultAnimator: PUBLIC Animator ~ NEW [AnimatorPrivate ฌ [Bounce, NIL]]; nRandoms: CARDINAL = 20; RandIndex: TYPE = [0..nRandoms); randTable: ARRAY RandIndex OF CARDINAL ฌ [ 30200, 27432, 62096, 39855, 17884, 58726, 55595, 20904, 28164, 27447, 34709, 35231, 33770, 31508, 40689, 1411, 20373, 3422, 62938, 40035]; startTime: BasicTime.GMT; randIndex: RandIndex ฌ 0; -- initialized by Start trap Random: PROC RETURNS [r: CARDINAL] = { i: RandIndex; randIndex ฌ IF randIndex = LAST[RandIndex] THEN FIRST[RandIndex] ELSE SUCC[randIndex]; i ฌ (randIndex + 3) MOD nRandoms; r ฌ randTable[i] ฌ randTable[randIndex] + randTable[i]; }; UpdateAndClip: PROC [v: CARDINAL, limit: CARDINAL, scale: CARDINAL ฌ 16] RETURNS [newV: CARDINAL ฌ 0] = INLINE { r: CARDINAL = Random[]; x: INTEGER ฌ v; x ฌ x + (SELECT TRUE FROM Basics.BITAND[r, 100000B] ~= 0 => 0, Basics.BITAND[r, 40000B] ~= 0 => scale, ENDCASE => -scale); RETURN [ SELECT x FROM < 0 => limit - scale, >= INTEGER[limit - scale] => 0, ENDCASE => x ] }; StartIdleProcesses: PUBLIC PROC [] = { idleWorld ฌ ViewersWorldInstance.GetWorld[]; defaultKeyFilter ฌ DefaultKeyFilter[]; startTime ฌ BasicTime.Now[ ! BasicTime.TimeNotKnown => { startTime ฌ BasicTime.earliestGMT; CONTINUE } ]; randIndex ฌ Basics.LowHalf[BasicTime.ToPupTime[startTime]] MOD nRandoms; MultiCursors.SetACursorOffset[-16, -16, TRUE, NIL]; animatorStack ฌ LIST[defaultAnimator]; }; END. 8 IdleImpl.mesa Copyright ำ 1985, 1986, 1988, 1989, 1991, 1992 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) April 16, 1987 2:08:09 am PDT Doug Wyatt, December 4, 1986 7:06:23 pm PST Last tweaked by Mike Spreitzer on October 7, 1987 3:00:44 pm PDT Willie-Sue (really bj), November 2, 1988 11:33:51 am PST Bier, March 5, 1991 6:22 pm PST Last edited by: Mik Lamming - January 26, 1989 11:39:00 am PST Michael Plass, September 29, 1989 2:03:30 pm PDT Kenneth A. Pier, March 14, 1991 5:42 pm PST Willie-s, October 14, 1991 1:00 pm PDT Christian Jacobi, March 3, 1992 12:33 pm PST Basic Stuff Global Variables (not exported) Monitored Data Exports to IdleBackdoor defaultKeyFilter: PUBLIC KeyFilter _ [first: 13, last: 111, pass: ALL[TRUE]]; Idle Registry (exported to Idle) Sleep stuff (exported to Idle) BecomeIdle will change the Viewers context creator to a Null creator and save the old creator in oldContextCreatorProc. OutOfIdle will restore the Viewers context creator from oldContextCreatorProc. ignores screen. Uses idle context. Color the entire screen with the given color. ignores screen. Uses idle context. Reflect off of the left or right Reflect off of the top or bottom unpaint old image ViewerPrivate.ColorScreen[main, Imager.black]; This is an adaptive loop intended to keep the overhead of the idle loop small. We don't get out until the elapsed time from the start is sleepWaitFactor times the elapsed time taken to do the screen update. IF (BasicTime.GetClockPulses[] - mark) > limit THEN EXIT; This algorithm is stolen from DMT. Initialization สˆ•NewlineDelimiter –(cedarcode) style™codešœ ™ Kšœ ฯeœO™ZK™1K™+K™@K™8K™K™>K™0K™+K™&K™,—K˜šฯk ˜ Kšœา˜าK˜—šฯnœžœž˜Kšžœั˜ุKšžœ+ž˜7K˜—™ K˜Kšœžœžœ˜,Kšœžœžœ%˜AKšœ žœ˜'Kšœ žœ˜'Kšœžœ ˜5Kšœžœ ˜5Kšœ žœ˜)Kšœžœ˜/Kšœ žœ˜%Kšœ žœ˜!Kšœ žœ˜!Kšœ žœ˜,Kšžœžœžœ˜K˜Kšœžœžœžœ ˜&K˜KšŸœžœžœ˜K˜—šœ™K˜K˜CK˜™Kšœž œ˜!Kšœ˜Kšœฯc"˜?Kšœžœžœ˜Kšœ žœžœ˜Kšœ$žœ˜(Kšœžœ˜"—K˜—šœ™K˜Kšœžœžœžœ˜:Kš œžœžœžœžœ˜LK˜šŸœžœžœžœ"žœžœžœ˜uKšœžœ ˜3Kšžœ˜Kšœ˜—K˜šŸœžœžœžœ%˜QKšžœžœžœ˜Kšœžœ˜šžœ5žœžœž˜Kšžœžœ˜Kšžœžœžœžœ˜EKšžœ˜Kšœ˜—Kšœ ˜ Kšžœ˜—Kšœ˜K˜—š Ÿ œžœžœžœžœ˜IKšžœžœžœ˜Kšœžœ˜ šžœ5žœžœž˜KKšœžœ ˜,Kšžœžœžœ žœ˜3K˜ Kšžœ˜—Kšœ˜K˜—š Ÿ œžœžœžœžœ˜5Kšžœžœžœ˜Kšžœ˜Kšœ˜K˜—šŸ œžœžœžœ˜0Kšžœžœžœ˜Kšžœžœžœ žœ˜1Kšœ˜Kšœ˜K˜—šŸ œžœžœžœ˜1Kšžœžœžœ˜Kšžœžœžœ žœ˜1Kšœžœ˜'Kšœ˜K˜—šŸ œžœžœžœ˜"Kšžœžœžœ˜Kšžœžœžœ žœ˜1Kšžœžœžœ$˜BKšœ˜K˜—šŸ œžœ žœ˜=šžœ,žœžœž˜BKšžœžœžœ˜Kšžœžœžœ7˜RKšžœ˜—Kšœ˜K˜—šŸ œžœžœžœ˜5Kšžœ+žœžœžœ˜Ašžœ žœž˜0šžœQ˜SKšžœžœžœžœ˜$—Kšžœ˜—Kšžœžœ˜K˜K˜—šŸ œžœ˜Kšžœ˜K˜K˜—KšŸœžœžœ˜!K˜š Ÿœžœžœžœžœ˜-K˜—K˜Kšœžœ*žœžœ™MKš œžœžœ žœ žœžœ˜VšŸœžœžœ˜.šŸ œžœ8žœ+˜|KšœP˜PKšžœžœžœ˜1K˜—Kš œžœ žœ žœžœ˜EKšœB˜BKšœ>˜>K˜zKšœ?˜?Kšœ>˜>KšœC˜CKšœC˜CKšœE˜EKšœF˜FKšœH˜HKšœG˜GKšœžœ˜Kšœžœ˜Kšœžœ˜!Kšœžœ˜#Kšœžœ˜$Kšœžœ˜#Kšœžœ˜%Kšœžœ˜$Kšžœ ˜K˜K˜——šœ ™ K˜Kšœ žœžœ˜'šœžœžœ˜!Kšœ˜Kšœžœž˜ K˜—K˜š Ÿœžœžœžœžœ˜&Kšžœ˜K˜K™—š Ÿœžœžœžœžœžœ˜fKšœžœ&˜9Kšžœ)˜/K˜K˜—š Ÿœžœžœžœ œ˜JKšœžœ˜Kšžœ žœ žœ"˜AKšžœžœžœ žœ#˜LK˜K˜—šŸœžœžœ%˜GKšœ(˜(K˜K˜——šœ™K˜Kšœ˜Kšœžœ˜Kšœžœ˜Kšœžœžœ˜Kšœ˜K˜:K˜š Ÿ œžœžœžœžœ˜/Kšžœžœžœ žœ˜2K˜K˜—šŸœžœžœ˜Kšœ#˜#K˜ Kšœ*˜*K˜ K˜K˜K˜—šŸœžœžœ?žœ˜mšžœžœ žœ˜/Kšœ ˜ Kšžœžœžœ˜MKšœ˜Kšœ ˜ K˜K˜—Kšœ˜K˜—š ŸœžœGžœžœ žœ˜Kšœžœ ˜šœ$˜$Kšœžœ˜Kšœ*˜*šžœ"žœ˜*Kšœ˜Kšœ˜K˜—K˜-K˜—Kšœ˜Kšžœ˜ K˜K˜—šŸœžœ$žœžœ žœ žœžœžœžœ žœ˜“KšœV˜VKšžœ/˜5K˜K˜—KšŸ œ˜K˜šŸœžœžœ žœ˜kKšœK˜KKšžœ#˜)Kšœ˜K˜—šŸ œžœžœ˜Kšœ˜Kšœ0˜0Kšœ=žœ˜EKšœE˜EKšž œ ˜K˜K˜—šŸ œžœžœ˜Kšœ˜Kšœžœ˜Kšœ˜Kšœ5˜5Kšž œ ˜K˜K˜—Kšœ ˜7šœ8˜8Kšœว™ว—K˜šŸ œžœ8˜IK™#K™-šœ žœ˜/Kšœ ˜ K˜1K˜—Kšœ!˜!K˜K˜—šŸ œžœ(žœ ˜]K™#Kšžœ žœžœžœ˜Kšœžœžœ˜*K˜—K˜šŸœžœŸ œžœžœžœ žœžœžœžœ˜}šœžœžœž˜,Kšœžœ˜Kš žœžœžœžœžœžœ˜8—Kšœžœ&˜0Kšœžœ&˜1Kšœžœ˜Kšœžœ˜Kšœ žœ˜KšœK˜KKšœžœ$˜7KšœJ˜JKšœ žœ˜&Kšœ žœ%˜5Kšœ žœ.˜>Kšœžœ ˜Kšœžœ˜Kšœžœ ˜Kšœžœ˜K˜Kšœ2˜2šž˜K˜4Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜šžœ žœžœ˜Kšœžœ ˜Kšœžœ ˜Kšœžœžœ˜3Kšœžœžœ˜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šœ˜šžœžœ˜šŸœžœžœžœ˜DK˜'Kšœ9˜9K˜—Kšœ™K˜9K™.K˜—šžœ žœžœ˜šŸœžœžœžœ˜9K˜K˜K˜'K˜ K˜—Kšœ.˜.K˜—K˜—˜KšœŠฯzœ6™ฯK˜Nšž˜Kšžœ žœžœžœ˜2Kšœ˜Kšžœ-žœžœ™9Kšžœ=žœžœ˜IKšžœ˜—Kšžœ žœ˜K˜—Kšžœ˜—K˜K˜—KšŸœžœžœ˜?Kšœžœ žœžœ˜IK˜Kšœ žœ˜Kšœ žœ˜ šœ žœ žœžœ˜*K˜EK˜D—K˜Kšœžœ˜Kšœ ˜6K˜šŸœžœžœžœ˜&Kšœ"™"K˜ Kš œ žœ žœ žœžœ žœžœ ˜VKšœžœ ˜!K˜7K˜—K˜šŸ œžœžœ žœ žœžœžœžœ˜pKšœžœ ˜Kšœžœ˜˜šœžœžœž˜Kšœžœ˜$Kšœžœ˜(Kšžœ ˜——šžœ˜šžœž˜ K˜Kšœžœ˜Kšžœ˜ —K˜—Kšœ˜—K˜—šœ™K˜—šŸœžœžœ˜&Kšœ,˜,Kšœ&˜&Kšœ\žœ˜iKšœ;žœ ˜HKšœ(žœžœ˜3Kšœžœ˜&K˜K˜—Kšžœ˜K˜K˜—…—2dI$