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]]; 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.PutFL[mh, msgType, msgClass, "%g", LIST[[rope[msg]]]]; RETURN}; PutFL: PUBLIC PROC [router: MsgRouter, msgType: MsgType, msgClass: MsgClass, format: ROPE ¬ NIL, list: LIST OF IO.Value ¬ NIL ] = { mh: MsgHandler ~ GetEffectiveHandler[router, msgClass]; mh.PutFL[mh, msgType, msgClass, format, list]; RETURN}; PutF: PUBLIC PROC [router: MsgRouter, msgType: MsgType, msgClass: MsgClass, format: ROPE ¬ NIL, v1: IO.Value ] = { mh: MsgHandler ~ GetEffectiveHandler[router, msgClass]; mh.PutFL[mh, msgType, msgClass, format, LIST[v1]]; 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 [ PutFL: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: ROPE, list: LIST OF IO.Value ¬ NIL ], ClearHerald: PROC [mh: MsgHandler, msgClass: MsgClass], Blink: PROC [mh: MsgHandler, msgClass: MsgClass], data: REF ANY ¬ NIL] RETURNS [MsgHandler] ~ {RETURN [NEW [MsgHandlerObj ¬ [PutFL, 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, list: LIST OF IO.Value ] ~ { dh.PutFL[dh, msgType, msgClass, format, list]; 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 ¬ [ PutFL: DontPutF, ClearHerald: DontClearHerald, Blink: DontBlink, data: NIL]]; DontPutF: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: Rope.ROPE, list: LIST OF IO.Value ¬ NIL ] ~ {RETURN}; DontClearHerald: PROC [mh: MsgHandler, msgClass: MsgClass] ~ {RETURN}; DontBlink: PROC [mh: MsgHandler, msgClass: MsgClass] ~ {RETURN}; handleByProblem: PUBLIC MsgHandler ~ NEW [MsgHandlerObj ¬ [ PutFL: ProblemPutF, ClearHerald: DontClearHerald, Blink: DontBlink, data: NIL]]; ProblemPutF: PROC [mh: MsgHandler, msgType: MsgType, msgClass: MsgClass, format: Rope.ROPE, list: LIST OF IO.Value ¬ NIL ] ~ { asRope: ROPE ~ IO.PutFLR[format, list]; 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, list: LIST OF IO.Value ¬ NIL ] ~ { sr: Splitter ~ NARROW[mh.data]; sr.h1.PutFL[sr.h1, msgType, msgClass, format, list]; sr.h2.PutFL[sr.h2, msgType, msgClass, format, list]; 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, list: LIST OF IO.Value ¬ NIL ] ~ { router: MsgRouter ~ NARROW[mh.data]; PutFL[router, msgType, msgClass, format, list]; 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, list: LIST OF IO.Value ¬ NIL ] ~ { hos: HandlerOnStream ~ NARROW[mh.data]; IF hos.state=before OR (typeBreaksAt[msgType].begin AND hos.state#after) THEN hos.to.PutChar['\n]; hos.to.PutFL[format, list]; 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, list: LIST OF IO.Value ¬ NIL ] ~ { sh: StoringHandler ~ NARROW[mh.data]; rope: ROPE ~ IO.PutFLR[format, list]; 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.PutFL[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 afterK™*K™—šΟk œbžœ(˜•K˜—šΟn œžœž˜Kšžœžœ˜!Kšžœ:˜AKšœž˜—Ihead™Kšžœžœžœ˜Kšœ žœ˜'Kšœ žœ˜)Kšœ žœžœ˜#Kšœžœžœ&˜?Kšœ žœžœ˜%Kšœžœžœ'˜AL™ Kš Ÿœžœžœ žœžœ˜/L™šœžœžœ žœ˜9Kšœ žœžœ˜Kšœžœžœ˜Kšœ žœžœ˜Kšœžœžœ˜—K˜šœžœžœΟc žœžœžœ žœžœ ˜NKšžœžœ žœ˜"Kšžœžœ žœ ˜&—K˜Lšœ ™ Kšœ( %˜MK˜šŸ œžœžœžœ˜9Kšœ žœ2˜>Kšžœ˜K˜—š Ÿœžœžœ!žœžœžœ˜jKšœžœžœ˜Kšœžœ˜ Kšœ*˜*Kšžœžœ žœ˜&Kšœ(˜(K˜K˜—š Ÿœžœžœžœžœžœ˜TKšœžœžœ˜Kšœžœ˜ Kšœ*˜*Kšžœžœ žœ˜#K˜—K˜š Ÿ œžœžœžœžœ˜LKšœ$˜$šžœ žœžœ˜Kšœ˜Kšœ(˜(K˜—K˜—K˜šŸ œžœžœ žœžœ žœžœžœžœ-˜ŒšŸœžœ žœžœžœžœžœ œ˜YKšœ žœžœ˜Kšœžœ˜ Kšžœžœ žœ˜HKšžœ˜—Kšœ˜Kšžœ˜—Lšœ™šŸœžœžœ@žœ˜\Kšœ7˜7Kšœ&žœ˜9Kšžœ˜K˜—šŸœžœžœCžœžœžœžœžœ žœ˜ƒKšœ7˜7Kšœ.˜.Kšžœ˜K˜—š ŸœžœžœCžœžœžœ ˜rKšœ7˜7Kšœ(žœ˜2Kšžœ˜—K˜šŸœžœžœ,˜>Kšœ7˜7Kšœ˜K˜K˜—šŸ œžœžœžœ˜:Kšœ˜K˜—K˜š Ÿ œžœžœžœžœ˜CKšœ˜K˜—K˜šŸ œžœžœ,˜DKšœ7˜7Kšœ˜Kšžœ˜—L™šŸ œžœž˜šœ˜KšŸœžœ@žœžœžœžœ žœ˜pKšŸ œžœ&˜7KšŸœžœ&˜1Kšœžœžœžœ˜—Kšžœ ˜Kšœžœžœ7˜EK˜—š Ÿœžœžœžœžœžœ˜>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šžœžœ žœ˜