DIRECTORY Ascii, Basics, Feedback, FeedbackConcreteTypes, FeedbackClasses, FeedbackSignals, FeedbackTypes, IO, IOUtils, RefTab, Rope, SimpleFeedback; FeedbackImpl: CEDAR PROGRAM IMPORTS IO, IOUtils, RefTab, Rope EXPORTS FeedbackTypes, Feedback, FeedbackClasses, FeedbackSignals = BEGIN ROPE: TYPE = Rope.ROPE; MsgType: TYPE = SimpleFeedback.MsgType; MsgClass: TYPE = SimpleFeedback.MsgClass; MsgRouter: TYPE = REF MsgRouterObj; MsgRouterObj: PUBLIC TYPE = FeedbackConcreteTypes.MsgRouterObj; MsgHandler: TYPE ~ REF MsgHandlerObj; MsgHandlerObj: PUBLIC TYPE = FeedbackConcreteTypes.MsgHandlerObj; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] _ CODE; typeBreaksAt: PUBLIC ARRAY MsgType OF Feedback.Breaks _ [ oneLiner: [TRUE, TRUE], begin: [TRUE, FALSE], middle: [FALSE, FALSE], end: [FALSE, TRUE]]; breaksToType: PUBLIC ARRAY --begin:--BOOL OF ARRAY --end:--BOOL OF MsgType _ [ FALSE: [FALSE: middle, TRUE: end], TRUE: [FALSE: begin, TRUE: oneLiner]]; AppendByName: PUBLIC PROC [routerName: ATOM, msgType: MsgType, msgClass: MsgClass, msg: Rope.ROPE] = { router: MsgRouter _ EnsureRouter[routerName]; Append[router, msgType, msgClass, msg]; }; BlinkByName: PUBLIC PROC [routerName: ATOM, msgClass: MsgClass _ $All] = { router: MsgRouter _ EnsureRouter[routerName]; Blink[router, msgClass]; }; SetRouterOnByName: PUBLIC PROC [routerName: ATOM, on: BOOL] = { router: MsgRouter _ EnsureRouter[routerName]; SetRouterOn[router, on]; }; GetRouterOnByName: PUBLIC PROC [routerName: ATOM] RETURNS [on: BOOL] = { router: MsgRouter _ EnsureRouter[routerName]; RETURN GetRouterOn[router]}; PutFByName: PUBLIC PROC [routerName: ATOM, msgType: MsgType, msgClass: MsgClass, format: Rope.ROPE _ NIL, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] = { router: MsgRouter _ EnsureRouter[routerName]; PutF[router, msgType, msgClass, format, v1, v2, v3, v4, v5]; }; ClearHeraldByName: PUBLIC PROC [routerName: ATOM, msgClass: MsgClass _ $All] = { router: MsgRouter _ EnsureRouter[routerName]; ClearHerald[router, msgClass]; }; gRouters: RefTab.Ref _ RefTab.Create[]; -- all of the MsgRouters in the world CreateRouter: PUBLIC PROC RETURNS [router: MsgRouter] = { router _ NEW[MsgRouterObj _ [defaultHandler: defaultHandler]]; RETURN}; RegisterRouter: PUBLIC PROC [router: MsgRouter, routerName: ATOM] RETURNS [oldRouter: MsgRouter _ NIL] = { found: BOOL _ FALSE; val: REF; [found, val] _ gRouters.Fetch[routerName]; IF found THEN oldRouter _ NARROW[val]; [] _ gRouters.Store[routerName, router]; }; RouterFromName: PUBLIC PROC [routerName: ATOM] RETURNS [router: MsgRouter _ NIL] = { found: BOOL _ FALSE; val: REF; [found, val] _ gRouters.Fetch[routerName]; IF found THEN router _ NARROW[val]; }; EnsureRouter: PUBLIC PROC [routerName: ATOM] RETURNS [router: MsgRouter] = { router _ RouterFromName[routerName]; IF router = NIL THEN { router _ CreateRouter[]; [] _ RegisterRouter[router, routerName]; }; }; ScanRouters: PUBLIC PROC [foreach: PROC [ATOM, MsgRouter] RETURNS [stop: BOOL _ FALSE]] RETURNS [result: Feedback.RouterScanResult _ []] ~ { Pass: PROC [key, val: REF ANY] RETURNS [stop: BOOL _ FALSE] --RefTab.EachPairAction-- ~ { routerName: ATOM ~ NARROW[key]; router: MsgRouter ~ NARROW[val]; IF foreach[routerName, router] THEN result _ [TRUE, routerName, router]; RETURN [result.stopped]}; [] _ gRouters.Pairs[Pass]; RETURN}; Append: PUBLIC PROC [router: MsgRouter, msgType: MsgType, msgClass: MsgClass, msg: ROPE] = { mh: MsgHandler ~ GetEffectiveHandler[router, msgClass]; mh.PutF[mh, msgType, msgClass, "%g", [rope[msg]]]; RETURN}; PutF: PUBLIC PROC [router: MsgRouter, msgType: MsgType, msgClass: MsgClass, format: ROPE _ NIL, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] = { mh: MsgHandler ~ GetEffectiveHandler[router, msgClass]; mh.PutF[mh, msgType, msgClass, format, v1, v2, v3, v4, v5]; RETURN}; Blink: PUBLIC PROC [router: MsgRouter, msgClass: MsgClass] = { mh: MsgHandler ~ GetEffectiveHandler[router, msgClass]; mh.Blink[mh, msgClass]; }; SetRouterOn: PUBLIC PROC [router: MsgRouter, on: BOOL] = { router.on _ on; }; GetRouterOn: PUBLIC PROC [router: MsgRouter] RETURNS [on: BOOL] = { on _ router.on; }; ClearHerald: PUBLIC PROC [router: MsgRouter, msgClass: MsgClass] = { mh: MsgHandler ~ GetEffectiveHandler[router, msgClass]; mh.ClearHerald[mh, msgClass]; RETURN}; CreateHandler: PUBLIC PROC [ PutF: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]] ], ClearHerald: PROC [mh: MsgHandler, msgClass: MsgClass], Blink: PROC [mh: MsgHandler, msgClass: MsgClass], data: REF ANY _ NIL] RETURNS [MsgHandler] ~ {RETURN [NEW [MsgHandlerObj _ [PutF, ClearHerald, Blink, data]]]}; GetHandlerData: PUBLIC PROC [mh: MsgHandler] RETURNS [REF ANY] ~ {RETURN [mh.data]}; SetHandler: PUBLIC PROC [router: MsgRouter, msgClass: MsgClass, mh: MsgHandler] RETURNS [previous: MsgHandler] ~ { SELECT msgClass FROM $Default, $Every => { varying: BOOL ~ msgClass=$Every AND router.c2h#NIL AND router.c2h.GetSize[]#0; IF mh=NIL THEN mh _ defaultHandler; IF varying THEN {router.c2h.Erase[]; previous _ NIL} ELSE IF router.defaultHandler=defaultHandler THEN previous _ NIL ELSE previous _ router.defaultHandler; router.defaultHandler _ mh; }; ENDCASE => { IF router.c2h=NIL THEN router.c2h _ RefTab.Create[]; previous _ NARROW[router.c2h.Fetch[msgClass].val]; IF mh=NIL THEN [] _ router.c2h.Delete[msgClass] ELSE [] _ router.c2h.Store[msgClass, mh]; }; RETURN}; SetMultiHandler: PUBLIC PROC [router: MsgRouter, msgClasses: LIST OF MsgClass, mh: MsgHandler] ~ { FOR msgClasses _ msgClasses, msgClasses.rest WHILE msgClasses#NIL DO [] _ SetHandler[router, msgClasses.first, mh]; ENDLOOP; RETURN}; GetHandler: PUBLIC PROC [router: MsgRouter, msgClass: MsgClass] RETURNS [mh: MsgHandler] ~ { SELECT msgClass FROM $Default, $Every => { IF msgClass=$Every AND router.c2h#NIL AND router.c2h.GetSize[]#0 THEN RETURN [NIL]; IF router.defaultHandler=defaultHandler THEN RETURN [NIL]; RETURN [router.defaultHandler]}; ENDCASE => { IF router.c2h=NIL THEN RETURN [NIL]; mh _ NARROW[router.c2h.Fetch[msgClass].val]; RETURN}}; GetEffectiveHandler: PUBLIC PROC [router: MsgRouter, msgClass: MsgClass] RETURNS [mh: MsgHandler] ~ { IF router=NIL OR NOT router.on THEN RETURN [doNothing]; IF msgClass=$Default OR msgClass=$Every THEN RETURN [router.defaultHandler]; IF router.c2h=NIL THEN RETURN [router.defaultHandler]; mh _ NARROW[router.c2h.Fetch[msgClass].val]; IF mh=NIL THEN mh _ router.defaultHandler; RETURN}; ScanHandlers: PUBLIC PROC [router: MsgRouter, foreach: PROC [MsgClass, MsgHandler] RETURNS [stop: BOOL _ FALSE]] RETURNS [result: Feedback.HandlerScanResult _ []] ~ { Pass: PROC [key, val: REF ANY] RETURNS [stop: BOOL _ FALSE] ~ { msgClass: MsgClass ~ NARROW[key]; mh: MsgHandler ~ NARROW[val]; IF foreach[msgClass, mh] THEN result _ [TRUE, msgClass, mh]; RETURN [result.stopped]}; IF router.c2h#NIL THEN [] _ router.c2h.Pairs[Pass]; IF router.defaultHandler#defaultHandler AND NOT result.stopped THEN [] _ Pass[$Default, router.defaultHandler]; RETURN}; GetHandledClasses: PUBLIC PROC [router: MsgRouter] RETURNS [classes: LIST OF MsgClass _ NIL] ~ { Note: PROC [msgClass: MsgClass, mh: MsgHandler] RETURNS [stop: BOOL _ FALSE] ~ {classes _ CONS[msgClass, classes]}; [] _ ScanHandlers[router, Note]; RETURN}; defaultHandler: PUBLIC MsgHandler ~ NEW [MsgHandlerObj _ [DefaultPutF, DefaultClearHerald, DefaultBlink, NIL]]; dh: MsgHandler _ NIL; SetGlobalDefaultHandlersBehavior: PUBLIC PROC [newDH: Feedback.MsgHandler] RETURNS [previous: Feedback.MsgHandler] ~ { previous _ dh; dh _ newDH}; DefaultPutF: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: Rope.ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] ~ { dh.PutF[dh, msgType, msgClass, format, v1, v2, v3, v4, v5]; RETURN}; DefaultClearHerald: PROC [mh: MsgHandler, msgClass: MsgClass] ~ { dh.ClearHerald[dh, msgClass]; RETURN}; DefaultBlink: PROC [mh: MsgHandler, msgClass: MsgClass] ~ { dh.Blink[dh, msgClass]; RETURN}; doNothing: PUBLIC MsgHandler ~ NEW [MsgHandlerObj _ [ PutF: DontPutF, ClearHerald: DontClearHerald, Blink: DontBlink, data: NIL]]; DontPutF: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: Rope.ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] ~ {RETURN}; DontClearHerald: PROC [mh: MsgHandler, msgClass: MsgClass] ~ {RETURN}; DontBlink: PROC [mh: MsgHandler, msgClass: MsgClass] ~ {RETURN}; handleByProblem: PUBLIC MsgHandler ~ NEW [MsgHandlerObj _ [ PutF: ProblemPutF, ClearHerald: DontClearHerald, Blink: DontBlink, data: NIL]]; ProblemPutF: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: Rope.ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] ~ { asRope: ROPE ~ IO.PutFR[format, v1, v2, v3, v4, v5]; SIGNAL Problem[asRope]; RETURN}; Splitter: TYPE ~ REF SplitterPrivate; SplitterPrivate: TYPE ~ RECORD [h1, h2: MsgHandler]; CreateSplittingHandler: PUBLIC PROC [h1, h2: MsgHandler] RETURNS [MsgHandler] ~ { sr: Splitter ~ NEW [SplitterPrivate _ [h1, h2]]; RETURN [NEW [MsgHandlerObj _ [SplitPutF, SplitClearHerald, SplitBlink, sr]]]}; IsSplittingHandler: PUBLIC PROC [mh: MsgHandler] RETURNS [is: BOOL, h1, h2: MsgHandler] ~ { WITH mh.data SELECT FROM sr: Splitter => RETURN [TRUE, sr.h1, sr.h2]; ENDCASE => RETURN [FALSE, NIL, NIL]}; SplitPutF: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: Rope.ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] ~ { sr: Splitter ~ NARROW[mh.data]; sr.h1.PutF[sr.h1, msgType, msgClass, format, v1, v2, v3, v4, v5]; sr.h2.PutF[sr.h2, msgType, msgClass, format, v1, v2, v3, v4, v5]; RETURN}; SplitClearHerald: PROC [mh: MsgHandler, msgClass: MsgClass] ~ { sr: Splitter ~ NARROW[mh.data]; sr.h1.ClearHerald[sr.h1, msgClass]; sr.h2.ClearHerald[sr.h2, msgClass]; RETURN}; SplitBlink: PROC [mh: MsgHandler, msgClass: MsgClass] ~ { sr: Splitter ~ NARROW[mh.data]; sr.h1.Blink[sr.h1, msgClass]; sr.h2.Blink[sr.h2, msgClass]; RETURN}; CreateHandlerOnRouter: PUBLIC PROC [router: MsgRouter] RETURNS [MsgHandler] ~ { RETURN [NEW [MsgHandlerObj _ [HorPutF, HorClearHerald, HorBlink, router]]]}; IsHandlerOnRouter: PUBLIC PROC [mh: MsgHandler] RETURNS [is: BOOL, router: MsgRouter] ~ { WITH mh.data SELECT FROM router: MsgRouter => RETURN [TRUE, router]; ENDCASE => RETURN [FALSE, NIL]}; HorPutF: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: Rope.ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] ~ { router: MsgRouter ~ NARROW[mh.data]; PutF[router, msgType, msgClass, format, v1, v2, v3, v4, v5]; RETURN}; HorClearHerald: PROC [mh: MsgHandler, msgClass: MsgClass] ~ { router: MsgRouter ~ NARROW[mh.data]; ClearHerald[router, msgClass]; RETURN}; HorBlink: PROC [mh: MsgHandler, msgClass: MsgClass] ~ { router: MsgRouter ~ NARROW[mh.data]; Blink[router, msgClass]; RETURN}; HandlerOnStream: TYPE ~ REF HandlerOnStreamPrivate; HandlerOnStreamPrivate: TYPE ~ RECORD [ to: IO.STREAM, nlAsap: BOOL, Blink: PROC [IO.STREAM, MsgClass] _ NIL, state: {before, after, chars} _ after ]; CreateHandlerOnStream: PUBLIC PROC [to: IO.STREAM, nlAsap: BOOL, Blink: PROC [IO.STREAM, MsgClass] _ NIL] RETURNS [MsgHandler] ~ { hos: HandlerOnStream ~ NEW [HandlerOnStreamPrivate _ [to, nlAsap, Blink]]; RETURN [NEW [MsgHandlerObj _ [StreamPutF, DontClearHerald, StreamBlink, hos]]]}; IsHandlerOnStream: PUBLIC PROC [mh: MsgHandler] RETURNS [is: BOOL, to: IO.STREAM, nlAsap: BOOL, Blink: PROC [IO.STREAM, MsgClass]] ~ { WITH mh.data SELECT FROM hos: HandlerOnStream => RETURN [TRUE, hos.to, hos.nlAsap, hos.Blink]; ENDCASE => RETURN [FALSE, NIL, FALSE, NIL]}; StreamPutF: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: Rope.ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] ~ { hos: HandlerOnStream ~ NARROW[mh.data]; IF hos.state=before OR (typeBreaksAt[msgType].begin AND hos.state#after) THEN hos.to.PutChar['\n]; hos.to.PutF[format, v1, v2, v3, v4, v5]; IF NOT typeBreaksAt[msgType].end THEN hos.state _ chars ELSE IF hos.nlAsap THEN {hos.to.PutChar['\n]; hos.state _ after} ELSE hos.state _ before; RETURN}; StreamBlink: PROC [mh: MsgHandler, msgClass: MsgClass] ~ { hos: HandlerOnStream ~ NARROW[mh.data]; IF hos.Blink#NIL THEN hos.Blink[hos.to, msgClass]; RETURN}; SendAsciiBell: PUBLIC PROC [to: IO.STREAM, msgClass: MsgClass] ~ {to.PutChar[Ascii.BEL]}; StoringHandler: TYPE ~ REF StoringHandlerPrivate; StoringHandlerPrivate: TYPE ~ RECORD [ buffsize, avail: INT, lastIsComplete: BOOL _ TRUE, head, tail: LIST OF ROPE ]; CreateStoringHandler: PUBLIC PROC [buffsize: INT _ INT.LAST] RETURNS [MsgHandler] ~ { head: LIST OF ROPE ~ LIST[NIL]; sh: StoringHandler ~ NEW [StoringHandlerPrivate _ [buffsize, buffsize, TRUE, head, head]]; RETURN [NEW [MsgHandlerObj _ [StoringPutF, DontClearHerald, DontBlink, sh]]]}; IsStoringHandler: PUBLIC PROC [mh: MsgHandler] RETURNS [is: BOOL, buffsize: INT] ~ { WITH mh.data SELECT FROM sh: StoringHandler => RETURN [TRUE, sh.buffsize]; ENDCASE => RETURN [FALSE, 0]}; StoringPutF: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: Rope.ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] ~ { sh: StoringHandler ~ NARROW[mh.data]; rope: ROPE ~ IO.PutFR[format, v1, v2, v3, v4, v5]; len: INT ~ rope.Length[]; IF len > sh.avail THEN RETURN; sh.avail _ sh.avail - len; IF sh.lastIsComplete OR typeBreaksAt[msgType].begin THEN sh.tail _ sh.tail.rest _ LIST[rope] ELSE sh.tail.first _ Rope.Concat[sh.tail.first, rope]; sh.lastIsComplete _ typeBreaksAt[msgType].end; RETURN}; GetStore: PUBLIC PROC [from: MsgHandler] RETURNS [msgs: LIST OF ROPE, lastIsComplete: BOOL] ~ { sh: StoringHandler ~ NARROW[from.data]; RETURN [sh.head.rest, sh.lastIsComplete]}; PlayStore: PUBLIC PROC [from, to: MsgHandler, withClass: MsgClass, thenClear: BOOL] ~ { sh: StoringHandler ~ NARROW[from.data]; FOR ml: LIST OF ROPE _ sh.head.rest, ml.rest WHILE ml#NIL DO to.PutF[to, IF ml.rest#NIL OR sh.lastIsComplete THEN oneLiner ELSE begin, withClass, ml.first]; ENDLOOP; IF thenClear THEN {sh.head.rest _ NIL; sh.lastIsComplete _ TRUE}; RETURN}; StreamOnRouter: TYPE ~ REF StreamOnRouterPrivate; StreamOnRouterPrivate: TYPE ~ RECORD [r: MsgRouter, c: MsgClass]; sorProcs: REF IO.StreamProcs ~ IO.CreateStreamProcs[ variety: output, class: $StreamOnRouter, putChar: SorPutChar, putBlock: SorPutBlock, unsafePutBlock: SorUnsafePutBlock, close: SorClose]; sorPfProcs: IOUtils.PFProcs ~ IOUtils.CopyPFProcs[NIL]; CreateStreamOnRouter: PUBLIC PROC [msgRouter: MsgRouter, msgClass: MsgClass] RETURNS [s: IO.STREAM] ~ { sor: StreamOnRouter ~ NEW [StreamOnRouterPrivate _ [msgRouter, msgClass]]; s _ IO.CreateStream[streamProcs: sorProcs, streamData: sor]; [] _ IOUtils.SetPFProcs[s, sorPfProcs]; RETURN}; IsStreamOnRouter: PUBLIC PROC [s: IO.STREAM] RETURNS [is: BOOL, msgRouter: MsgRouter, msgClass: MsgClass] ~ { WITH s.streamData SELECT FROM sor: StreamOnRouter => RETURN [TRUE, sor.r, sor.c]; ENDCASE => RETURN [FALSE, NIL, NIL]}; SorPutChar: PROC [self: IO.STREAM, char: CHAR] ~ { sor: StreamOnRouter ~ NARROW[self.streamData]; IF char='\r OR char='\l THEN Append[sor.r, end, sor.c, NIL] ELSE Append[sor.r, middle, sor.c, Rope.FromChar[char]]; RETURN}; SorPutBlock: PROC [self: IO.STREAM, block: REF READONLY TEXT, startIndex, count: NAT] ~ { sor: StreamOnRouter ~ NARROW[self.streamData]; IF startIndex >= block.length THEN RETURN; {limit: NAT ~ MIN[block.length - startIndex, count] + startIndex; WHILE startIndex < limit DO after: NAT _ startIndex; c: CHAR; WHILE afterstartIndex THEN Append[sor.r, middle, sor.c, Rope.FromRefText[block, startIndex, after-startIndex]]; WHILE afterstartIndex THEN Append[sor.r, middle, sor.c, Rope.FromProc[after-startIndex, GiveChar]]; WHILE after—K™šΟk œbœ(˜•K˜—šΟn œœ˜Jšœœ˜!Kšœ:˜AKšœ˜—Ihead™Kšœœœ˜Kšœ œ˜'Kšœ œ˜)Kšœ œœ˜#Kšœœœ&˜?Kšœ œœ˜%Kšœœœ'˜AL™ Kš žœœœ œœ˜/L™šœœœ œ˜9Kšœ œœ˜Kšœœœ˜Kšœ œœ˜Kšœœœ˜—K˜šœœœΟc œœœŸœœ ˜NKšœœ œ˜"Kšœœ œ ˜&—K˜š ž œœœœ2œ˜fKšœ-˜-Kšœ'˜'K˜—K˜šž œœœœ ˜JKšœ-˜-Kšœ˜K˜—K˜š žœœœœœ˜?Kšœ-˜-Kšœ˜K˜—K˜š žœœœœœœ˜HKšœ-˜-Kšœ˜—K˜šž œœœœ5œœœ˜—Kšœ-˜-Kšœ<˜Kšœ˜K˜—š žœœœ!œœœ˜jKšœœœ˜Jšœœ˜ Jšœ*˜*Kšœœ œ˜&Kšœ(˜(K˜K˜—š žœœœœœœ˜TKšœœœ˜Jšœœ˜ Jšœ*˜*Kšœœ œ˜#K˜—K˜š ž œœœœœ˜LKšœ$˜$šœ œœ˜Kšœ˜Kšœ(˜(K˜—K˜—K˜šž œœœ œœ œœœœ-˜Œšžœœ œœœœœŸœ˜YKšœ œœ˜Kšœœ˜ Kšœœ œ˜HKšœ˜—Kšœ˜Kšœ˜—Lšœ™šžœœœ@œ˜\Kšœ7˜7Kšœ2˜2Kšœ˜K˜—š žœœœCœœœ˜Kšœ7˜7Kšœ;˜;Kšœ˜—K˜šžœœœ,˜>Kšœ7˜7Kšœ˜K˜K˜—šž œœœœ˜:Kšœ˜K˜—K˜š ž œœœœœ˜CKšœ˜K˜—K˜šž œœœ,˜DKšœ7˜7Kšœ˜Kšœ˜—L™šž œœ˜šœ˜Kšžœœ@œœ˜zKšž œœ&˜7Kšžœœ&˜1Kšœœœœ˜—Kšœ ˜Kšœœœ6˜DK˜—š žœœœœœœ˜>Kšœœ ˜—K˜šž œœœ9œ˜ršœ ˜šœ˜Kš œ œœ œœ˜NKšœœœ˜#Kšœ œ!œ˜4Kšœœ&œ ˜@Kšœ"˜&Kšœ˜Kšœ˜—šœ˜ Kšœ œœ˜4Kšœ œ!˜2Kšœœœ!˜/Kšœ%˜)Kšœ˜——Kšœ˜—K˜š žœœœ!œœ˜bšœ*œ œ˜DK˜.Kšœ˜—Kšœ˜—K˜šž œœœ)œ˜\šœ ˜šœ˜Kšœœ œœœœœ˜SKšœ&œœœ˜:Kšœ˜ —šœ˜ Kš œ œœœœ˜$Kšœœ!˜,Kšœ˜ ———K˜šžœœœ)œ˜eKš œœœœ œœ ˜7Kšœœœœ˜LKšœ œœœ˜6Kšœœ!˜,Kšœœœ˜*Kšœ˜—K˜šž œœœœœœœœ.˜¦šžœœ œœœœœ˜?Kšœœ˜!Kšœœ˜Kšœœ œ˜