DIRECTORY CedarProcess USING [SetPriority], Imager USING [black, Color, Context, MaskRectangleI, SetColor, SetFont, SetXRelI, SetXYI, ShowRope, white], ImagerFont USING [Extents, FontBoundingBox], ImagerBackdoor USING [MakeStipple], Menus USING [armedTime, armingTime, ClickProc, Menu, MenuEntry, MenuEntryRec, MenuRec, MenuLine, MouseButton], MessageWindow USING [Append], Process USING [Detach, Milliseconds, MsecToTicks, SetTimeout], Real USING [Round], Rope USING [Equal, FromRefText, ROPE], TIPUser USING [TIPScreenCoords], VFonts USING [defaultFont, Font, StringWidth], ViewerClasses USING [Viewer], ViewerOps USING [PaintViewer], ViewerPrivate USING [DrawCaptionMenu, InvertForMenus, menuHLeading, menuHSpace, windowMenu], ViewerSpecs USING [menuHeight], WindowManager USING [RestoreCursor]; MenusImpl: CEDAR MONITOR LOCKS entry USING entry: MenuEntry IMPORTS CedarProcess, Imager, ImagerBackdoor, ImagerFont, MessageWindow, Process, Real, Rope, VFonts, ViewerOps, ViewerPrivate, ViewerSpecs, WindowManager EXPORTS Menus, ViewerPrivate SHARES ViewerClasses, ViewerOps = BEGIN OPEN Menus; Viewer: TYPE ~ ViewerClasses.Viewer; menuFont: VFonts.Font ¬ VFonts.defaultFont; fontHeight: INTEGER ¬ 0; baselineOffset: INTEGER ¬ 0; margin: INTEGER = 3; CreateMenu: PUBLIC PROC [lines: MenuLine ¬ 1] RETURNS [menu: Menu] ~ { RETURN[NEW[MenuRec ¬ [linesUsed: lines]]] }; CopyMenu: PUBLIC PROC [old: Menu] RETURNS [new: Menu] = { new ¬ CreateMenu[old.linesUsed]; FOR l: MenuLine IN MenuLine UNTIL old.lines[l]=NIL DO new.lines[l] ¬ old.lines[l]; CopyLine[new, l]; ENDLOOP; }; CopyLine: PROC [menu: Menu, line: INTEGER] = { oldEntry: MenuEntry ¬ menu.lines[line]; newEntry: MenuEntry; menu.lines[line] ¬ NIL; FOR t: MenuEntry ¬ oldEntry, t.link UNTIL t=NIL DO IF menu.lines[line]=NIL THEN newEntry ¬ menu.lines[line] ¬ CopyEntry[t] ELSE newEntry ¬ newEntry.link ¬ CopyEntry[t]; newEntry.greyed ¬ FALSE; newEntry.guardState ¬ IF newEntry.guarded THEN guarded ELSE armed; ENDLOOP; }; CopyEntry: PUBLIC PROC [oldEntry: MenuEntry] RETURNS [newEntry: MenuEntry] = { newEntry ¬ NEW[MenuEntryRec]; newEntry.link ¬ oldEntry.link; newEntry.name ¬ oldEntry.name; newEntry.proc ¬ oldEntry.proc; newEntry.width ¬ oldEntry.width; newEntry.xPos ¬ oldEntry.xPos; newEntry.clientData ¬ oldEntry.clientData; newEntry.documentation ¬ oldEntry.documentation; newEntry.fork ¬ oldEntry.fork; newEntry.greyed ¬ oldEntry.greyed; newEntry.guarded ¬ oldEntry.guarded; newEntry.guardState ¬ oldEntry.guardState; }; CreateEntry: PUBLIC PROC [name: Rope.ROPE, proc: ClickProc, clientData: REF ANY ¬ NIL, documentation: REF ANY ¬ NIL, fork: BOOL ¬ TRUE, guarded: BOOL ¬ FALSE] RETURNS [entry: MenuEntry] = { entry ¬ NEW[MenuEntryRec ¬ [ name: name, proc: proc, clientData: clientData, documentation: documentation, fork: fork, guarded: guarded, guardState: IF guarded THEN guarded ELSE armed, width: VFonts.StringWidth[name, menuFont] ]]; }; SetGuarded: PUBLIC PROC [entry: MenuEntry, guard: BOOL] = { entry.guarded ¬ guard; entry.guardState ¬ IF guard THEN guarded ELSE armed; }; SetClientData: PUBLIC PROC [entry: MenuEntry, newData: REF ANY] RETURNS [oldData: REF ANY] = { oldData ¬ entry.clientData; entry.clientData ¬ newData; }; SetDocumentation: PUBLIC PROC [entry: MenuEntry, newDoc: REF ANY] RETURNS [oldDoc: REF ANY] = { oldDoc ¬ entry.documentation; entry.documentation ¬ newDoc; }; FindEntry: PUBLIC PROC [menu: Menu, entryName: Rope.ROPE] RETURNS [entry: MenuEntry] = { IF menu=NIL THEN RETURN[NIL]; FOR l: MenuLine IN MenuLine UNTIL menu.lines[l]=NIL DO FOR e: MenuEntry ¬ menu.lines[l], e.link UNTIL e=NIL DO IF Rope.Equal[e.name, entryName] THEN RETURN[e]; ENDLOOP; ENDLOOP; }; InsertMenuEntry: PUBLIC PROC [menu: Menu, entry: MenuEntry, line: MenuLine ¬ 0] = { entry.link ¬ menu.lines[line]; menu.lines[line] ¬ entry; entry.xPos ¬ ViewerPrivate.menuHLeading; FOR e: MenuEntry ¬ menu.lines[line].link, e.link UNTIL e=NIL DO e.xPos ¬ e.xPos + entry.width + ViewerPrivate.menuHSpace; ENDLOOP; }; AppendMenuEntry: PUBLIC PROC [menu: Menu, entry: MenuEntry, line: MenuLine ¬ 0] = { entry.link ¬ NIL; IF menu.lines[line]=NIL THEN {entry.xPos ¬ ViewerPrivate.menuHLeading; menu.lines[line] ¬ entry} ELSE FOR e: MenuEntry ¬ menu.lines[line], e.link UNTIL e.link=NIL DO REPEAT FINISHED => { entry.xPos ¬ e.xPos+e.width+ViewerPrivate.menuHSpace; e.link ¬ entry}; ENDLOOP; }; MenuFromMenuEntry: PUBLIC PROC[entryList: MenuEntry] RETURNS [Menu] ~ { menu: Menu ~ CreateMenu[lines: 1]; SetLine[menu: menu, line: 0, entryList: entryList]; RETURN [menu]; }; MenuEntryFind: PUBLIC PROC[entryName: Rope.ROPE, entryList: MenuEntry] RETURNS [MenuEntry] ~ { menu: Menu ~ MenuFromMenuEntry[entryList: entryList]; RETURN [FindEntry[menu: menu, entryName: entryName]]; }; MenuEntryAppend: PUBLIC PROC[entry: MenuEntry, entryList: MenuEntry] RETURNS [MenuEntry] ~ { menu: Menu ~ MenuFromMenuEntry[entryList: entryList]; AppendMenuEntry[menu: menu, entry: entry, line: 0]; RETURN [GetLine[menu: menu, line: 0]]; }; MenuEntryInsert: PUBLIC PROC[entry: MenuEntry, entryList: MenuEntry] RETURNS [MenuEntry] ~ { menu: Menu ~ MenuFromMenuEntry[entryList: entryList]; InsertMenuEntry[menu: menu, entry: entry, line: 0]; RETURN [GetLine[menu: menu, line: 0]]; }; MenuEntryReplace: PUBLIC PROC[entryList: MenuEntry, old: MenuEntry, new: MenuEntry] RETURNS [MenuEntry] ~ { menu: Menu ~ MenuFromMenuEntry[entryList: entryList]; ReplaceMenuEntry[menu: menu, oldEntry: old, newEntry: new]; RETURN [GetLine[menu: menu, line: 0]]; }; targetNotFound: PUBLIC SIGNAL = CODE; ReplaceMenuEntry: PUBLIC PROC [menu: Menu, oldEntry: MenuEntry, newEntry: MenuEntry ¬ NIL] = { l: MenuLine; x: INTEGER ¬ ViewerPrivate.menuHLeading; exit: BOOL ¬ FALSE; FOR l IN MenuLine UNTIL menu.lines[l]=NIL DO IF oldEntry=menu.lines[l] THEN { IF newEntry=NIL THEN menu.lines[l] ¬ menu.lines[l].link ELSE { newEntry.link ¬ oldEntry.link; menu.lines[l] ¬ newEntry; }; EXIT; } ELSE FOR e: MenuEntry ¬ menu.lines[l], e.link UNTIL e.link=NIL DO IF e.link=oldEntry THEN { IF newEntry=NIL THEN e.link ¬ e.link.link ELSE { newEntry.link ¬ oldEntry.link; e.link ¬ newEntry; }; exit ¬ TRUE; EXIT; }; ENDLOOP; IF exit THEN EXIT; REPEAT FINISHED => SIGNAL targetNotFound; ENDLOOP; IF menu.lines[l]#NIL THEN menu.lines[l].xPos ¬ ViewerPrivate.menuHLeading; FOR e: MenuEntry ¬ menu.lines[l], e.link UNTIL e=NIL DO e.xPos ¬ x; x ¬ x+e.width+ViewerPrivate.menuHSpace; ENDLOOP; }; ChangeNumberOfLines: PUBLIC PROC [menu: Menu, newLines: MenuLine] = { menu.linesUsed ¬ newLines; }; GetNumberOfLines: PUBLIC PROC [menu: Menu] RETURNS [lines: MenuLine] = { RETURN[menu.linesUsed]; }; SetLine: PUBLIC PROC [menu: Menu, line: MenuLine, entryList: MenuEntry] = { menu.lines[line] ¬ entryList; menu.linesUsed ¬ MAX[menu.linesUsed, line+1]; }; GetLine: PUBLIC PROC [menu: Menu, line: MenuLine] RETURNS [entryList: MenuEntry] = { RETURN[menu.lines[line]]; }; MarkMenu: PUBLIC PROC [menu: Menu, parent: ViewerClasses.Viewer, mousePos: TIPUser.TIPScreenCoords] = { delta: INTEGER ~ (menu.y-mousePos.mouseY); IF delta >= 0 THEN { row: NAT ~ NAT[delta]/ViewerSpecs.menuHeight; newEntry: MenuEntry ¬ ResolveEntry[menu, row, mousePos.mouseX]; SELECT TRUE FROM newEntry=NIL => { IF menu.inverted#NIL THEN InvertEntry[menu, parent]; menu.inverted ¬ NIL; }; newEntry#menu.inverted => { IF menu.inverted#NIL THEN InvertEntry[menu, parent]; menu.inverted ¬ newEntry; menu.lineInverted ¬ row; InvertEntry[menu, parent]; }; ENDCASE; }; }; HitMenu: PUBLIC PROC [menu: Menu, parent: ViewerClasses.Viewer, mousePos: TIPUser.TIPScreenCoords, button: MouseButton, shift, control: BOOL ¬ FALSE] = { delta: INTEGER ~ (menu.y-mousePos.mouseY); IF delta >= 0 THEN { row: NAT ~ NAT[delta]/ViewerSpecs.menuHeight; entry: MenuEntry ¬ ResolveEntry[menu, row, mousePos.mouseX]; hit: BOOL ¬ menu.inverted#NIL AND entry=menu.inverted; IF menu.inverted#NIL THEN InvertEntry[menu, parent]; -- take down menu.inverted ¬ NIL; IF hit THEN ProcessMenuHit[entry, menu, parent, button, shift, control]; }; }; ProcessMenuHit: ENTRY PROC [entry: MenuEntry, menu: Menu, parent: ViewerClasses.Viewer, button: MouseButton, shift, control: BOOL] = TRUSTED { SELECT entry.guardState FROM guarded => { entry.guardState ¬ arming; Process.Detach[FORK ArmMenuProc[entry, menu, parent]]; IF entry.documentation#NIL THEN Process.Detach[ FORK Document[entry.documentation, parent, entry.clientData, button, shift, control]]; }; arming=> NULL; -- no action armed => { IF entry.guarded THEN entry.guardState ¬ guarded; IF entry.fork THEN Process.Detach[FORK MenuPusher[entry, menu, parent, button, shift, control]] ELSE MenuPusher[entry, menu, parent, button, shift, control, FALSE]; }; ENDCASE; }; ArmMenuProc: ENTRY PROC [entry: MenuEntry, menu: Menu, parent: ViewerClasses.Viewer] = { menuWaitCondition: CONDITION; TRUSTED {Process.SetTimeout[@menuWaitCondition, Process.MsecToTicks[armingTime]]}; WAIT menuWaitCondition; IF entry.guardState = arming THEN { entry.guardState ¬ armed; RedrawMenu[parent, menu, entry]; TRUSTED {Process.SetTimeout[@menuWaitCondition, Process.MsecToTicks[armedTime]]}; WAIT menuWaitCondition; }; IF entry.guardState#guarded THEN { entry.guardState ¬ guarded; RedrawMenu[parent, menu, entry]; }; }; MenuPusher: PROC [entry: MenuEntry, menu: Menu, parent: ViewerClasses.Viewer, button: MouseButton, shift, control: BOOL ¬ FALSE, normalPriority: BOOL ¬ TRUE] = { entry.greyed ¬ TRUE; RedrawMenu[parent, menu, entry]; IF normalPriority THEN CedarProcess.SetPriority[normal]; entry.proc[parent, entry.clientData, button, shift, control ! ABORTED => CONTINUE]; entry.greyed ¬ FALSE; RedrawMenu[parent, menu, entry]; WindowManager.RestoreCursor[]; }; RedrawMenu: PROC [viewer: Viewer, menu: Menu, entry: MenuEntry] = { IF menu=ViewerPrivate.windowMenu THEN ViewerPrivate.DrawCaptionMenu[viewer, FALSE] ELSE ViewerOps.PaintViewer[viewer, menu, entry=NIL, entry]; }; Document: PUBLIC PROC [info: REF ANY, parent: Viewer, clientData: REF ANY ¬ NIL, mouseButton: MouseButton ¬ red, shift, control: BOOL ¬ FALSE] = { WITH info SELECT FROM doc: REF TEXT => MessageWindow.Append[Rope.FromRefText[doc], TRUE]; doc: REF ClickProc => doc­[parent, clientData, mouseButton, shift, control]; doc: Rope.ROPE => MessageWindow.Append[doc, TRUE]; ENDCASE => ERROR; -- not valid documentation }; ClearMenu: PUBLIC PROC [menu: Menu, parent: ViewerClasses.Viewer, paint: BOOL ¬ TRUE] = { IF menu#NIL AND menu.inverted#NIL THEN { IF paint THEN InvertEntry[menu, parent]; menu.inverted ¬ NIL; }; }; greyGuard: PUBLIC BOOL ¬ FALSE; -- grey text of guarded items else strikeout myGrey: Imager.Color ~ ImagerBackdoor.MakeStipple[001010B]; DrawMenu: PUBLIC PROC [menu: Menu, context: Imager.Context, x, y: INTEGER, whatChanged: REF ANY ¬ NIL] = { quitEarly: BOOL ¬ FALSE; ey: INTEGER ¬ y; menu.x ¬ x; menu.y ¬ y; Imager.SetFont[context, menuFont]; FOR row: NAT IN [0..menu.linesUsed) DO ey ¬ ey-ViewerSpecs.menuHeight; Imager.SetXYI[context, x+ViewerPrivate.menuHLeading, ey+baselineOffset]; FOR e: MenuEntry ¬ menu.lines[row], e.link UNTIL e=NIL DO ex: INTEGER ~ x+e.xPos; IF whatChanged#NIL THEN { IF e=whatChanged THEN { Imager.SetColor[context, Imager.white]; Imager.MaskRectangleI[context, ex-margin, ey, e.width+margin*2, fontHeight]; quitEarly ¬ TRUE; } ELSE { Imager.SetXRelI[context, e.width+ViewerPrivate.menuHSpace]; LOOP }; }; IF e.greyed THEN { Imager.SetColor[context, myGrey]; Imager.MaskRectangleI[context, ex-margin, ey, e.width+margin*2, fontHeight]; }; Imager.SetColor[context, Imager.black]; Imager.ShowRope[context, e.name]; IF e.guarded AND e.guardState#armed THEN { Imager.MaskRectangleI[context, ex-1, ey+baselineOffset+3, e.width+2, 1]; }; IF quitEarly THEN RETURN; Imager.SetXRelI[context, ViewerPrivate.menuHSpace]; ENDLOOP; ENDLOOP; menu.inverted ¬ NIL; }; ResolveEntry: PROC [menu: Menu, line, x: INTEGER] RETURNS [entry: MenuEntry] = { IF line NOT IN [0..menu.linesUsed) THEN RETURN[NIL]; FOR e: MenuEntry ¬ menu.lines[line], e.link UNTIL e=NIL OR e.xPos>x DO IF x IN [e.xPos..e.xPos+e.width) THEN RETURN[e]; ENDLOOP; RETURN[NIL]; }; InvertEntry: PROC [menu: Menu, parent: Viewer] = { IF ~parent.destroyed AND ~parent.iconic THEN { menuHeight: INTEGER ~ ViewerSpecs.menuHeight; x: INTEGER ~ menu.inverted.xPos-margin; w: INTEGER ~ menu.inverted.width+(2*margin); y: INTEGER ~ menu.y-menu.lineInverted*menuHeight; ViewerPrivate.InvertForMenus[parent, x, y, w, -menuHeight]; }; }; ComputeFontInfo: PROC = { extents: ImagerFont.Extents ~ ImagerFont.FontBoundingBox[menuFont]; fontHeight ¬ Real.Round[extents.descent+extents.ascent]; baselineOffset ¬ Real.Round[extents.descent]; }; ComputeFontInfo[]; END.  MenusImpl.mesa Copyright Σ 1985, 1986, 1987, 1991 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) June 11, 1985 4:15:15 pm PDT Doug Wyatt, January 20, 1987 0:09:42 am PST Bier, February 2, 1989 12:06:47 pm PST Willie-s, October 8, 1991 1:10 pm PDT CopyLine: PROC [menu: Menu, line: INTEGER] = { oldEntry: MenuEntry _ menu.lines[line]; newEntry: MenuEntry; menu.lines[line] _ NIL; FOR t: MenuEntry _ oldEntry, t.link UNTIL t=NIL DO newEntry _ CopyEntry[t]; newEntry.greyed _ FALSE; newEntry.guardState _ IF newEntry.guarded THEN guarded ELSE armed; IF menu.lines[line]=NIL THEN menu.lines[line] _ newEntry ELSE newEntry.link _ newEntry; ENDLOOP; }; Search for an entry given the name. Will return NIL if target name not found. Add the entry to the end of the list. Add the entry to the beginning of the list. Change an existing entry in a menu. If new is NIL then old will be deleted. Will raise targetNotFound if target entry not found. ! targetNotFound => RAISE targetNotFound assert: state=arming Initialization ΚA–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ ΟeœC™NK™0K™+K™&K™%K™—šΟk ˜ Kšœ žœ˜!Kšœžœ_˜kKšœ žœ˜,Kšœžœ˜#Kšœžœc˜nKšœžœ ˜Kšœžœ1˜>Kšœžœ ˜Kšœžœžœ˜&Kšœžœ˜ Kšœžœ"˜.Kšœžœ ˜Kšœ žœ˜KšœžœI˜\Kšœ žœ˜Kšœžœ˜$—K˜š Πbl œžœžœžœžœ˜;Kšžœ“˜šKšžœ˜Kšžœ˜Kšœžœžœ˜—K˜Kšœžœ˜$K˜K˜+Kšœ žœ˜Kšœžœ˜Kšœžœ˜K˜šΟn œžœžœžœ˜FKšžœžœ˜)Kšœ˜K˜—š œžœžœ žœ˜9K˜ š žœ žœ žœžœž˜5K˜K˜Kšžœ˜—Kšœ˜K˜—š œžœžœ™.K™'K™Kšœžœ™šžœ!žœžœž™2Kšœ™Kšœžœ™Kšœžœžœ žœ™Bšžœž™Kšžœ™ Kšžœ™—Kšžœ™—Kšœ™K™—š œžœžœ˜.K˜'K˜Kšœžœ˜šžœ!žœžœž˜2Kšžœžœžœ+˜GKšžœ)˜-Kšœžœ˜Kšœžœžœ žœ˜BKšžœ˜—Kšœ˜K˜—š  œžœžœžœ˜NKšœžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ*˜*Kšœ0˜0Kšœ˜Kšœ"˜"Kšœ$˜$Kšœ*˜*Kšœ˜K˜—š  œžœžœ žœžœžœžœžœžœžœžœžœ žœžœžœ˜½šœžœ˜K˜ K˜ K˜K˜K˜ K˜Kšœ žœ žœ žœ˜/K˜)K˜—šœ˜K˜——š  œžœžœžœ˜;Kšœ˜Kšœžœžœ žœ˜4Kšœ˜K˜—š  œžœžœžœžœžœ žœžœ˜^Kšœ˜Kšœ˜Kšœ˜K˜—š œžœžœžœžœžœ žœžœ˜_Kšœ˜Kšœ˜Kšœ˜K˜—š   œžœžœžœžœ˜YKš žœžœžœžœžœ˜š žœ žœ žœžœž˜6šžœ&žœžœž˜7Kšžœžœžœ˜0Kšžœ˜—Kšžœ˜—Kšœ˜K˜—š œžœžœ7˜SK˜K˜K˜(šžœ.žœžœž˜?Kšœ9˜9Kšžœ˜—Kšœ˜K˜—š œžœžœ7˜SKšœ žœ˜šžœž˜KšžœD˜Hš žœžœ)žœžœž˜Dšžœžœ˜Kšœ5˜5Kšœ˜—Kšžœ˜——Kšœ˜K˜—š œžœžœžœ ˜GK˜"K˜K˜3Kšžœ˜Kšœ˜K˜—š   œžœžœžœžœ˜^Kšœ1žœ™NKšœ5˜5K˜Kšžœ/˜5K˜K™—š œžœžœ)žœ˜\K™%Kšœ5˜5K˜Kšœ3˜3Kšžœ ˜&Kšœ˜K˜—š œžœžœ)žœ˜\K™+Kšœ5˜5K˜Kšœ3˜3Kšžœ ˜&Kšœ˜K™—š œžœžœ7žœ˜kKšœL™LKšœ4™4Kšœ5˜5K˜šœ;˜;Kšœ(™(—Kšžœ ˜&Kšœ˜K˜—Kšœžœžœžœ˜%K˜š œžœžœ9žœ˜^K˜ Kšœžœ˜(Kšœžœžœ˜š žœžœ žœžœž˜,šžœžœ˜ šžœ ž˜Kšžœ#˜'šžœ˜K˜K˜Kšœ˜——Kšžœ˜Kšœ˜—š žœžœ&žœžœž˜Ašžœžœ˜šžœ ž˜Kšžœ˜šžœ˜K˜K˜Kšœ˜——Kšœžœ˜ Kšžœ˜Kšœ˜—Kšžœ˜—Kšžœžœžœ˜Kšžœžœžœ˜)Kšžœ˜—Kšžœžœžœ1˜Jšžœ&žœžœž˜7K˜ Kšœ'˜'Kšžœ˜—Kšœ˜K˜—š œžœžœ%˜EKšœ˜Kšœ˜K˜—š œžœžœžœ˜HKšžœ˜Kšœ˜K˜—š œžœžœ7˜KKšœ/žœ˜KKšœ˜K˜—š œžœžœžœ˜TKšžœ˜Kšœ˜K˜—š œžœžœR˜gKšœžœ˜*šžœ žœ˜Kšœžœžœ˜-K˜?šžœžœž˜šœ žœ˜Kšžœžœžœ˜4Kšœžœ˜K˜—šœ˜Kšžœžœžœ˜4K˜K˜K˜K˜—Kšžœ˜—K˜—Kšœ˜K˜—š  œžœžœtžœžœ˜™Kšœžœ˜*šžœ žœ˜Kšœžœžœ˜-K˜žœžœ˜SKšœžœ˜K˜ K˜Kšœ˜K˜—š  œžœ3˜Cšžœ˜ Kšžœ'žœ˜1Kšžœ+žœ ˜;—Kšœ˜K˜—š œžœžœžœžœžœžœžœ2žœžœ˜’šžœžœž˜Kšœžœžœ0žœ˜CKšœžœD˜LKšœ žœžœ˜2Kšžœžœ‘˜,—Kšœ˜K˜—š   œžœžœ3žœžœ˜Yš žœžœžœžœžœ˜(Kšžœžœ˜(Kšœžœ˜Kšœ˜—Kšœ˜K˜—Kšœ žœžœžœ‘,˜LK˜Kšœ;˜;K˜š œžœžœ-žœžœžœžœ˜kKšœ žœžœ˜Kšœžœ˜K˜ K˜ K˜"šžœžœžœž˜&Kšœ˜KšœH˜Hšžœ(žœžœž˜9Kšœžœ ˜šžœ žœžœ˜šžœžœ˜K˜'KšœL˜LKšœ žœ˜Kšœ˜—Kšžœ?žœ˜JKšœ˜—šžœ žœ˜K˜!KšœL˜LKšœ˜—K˜'K˜!šžœ žœžœ˜*KšœH˜HKšœ˜—Kšžœ žœžœ˜Kšœ3˜3Kšžœ˜—Kšžœ˜—Kšœžœ˜Kšœ˜K˜—š  œžœžœžœ˜PKš žœžœžœžœžœžœ˜4š žœ)žœžœžœ ž˜FKšžœžœžœžœ˜0Kšžœ˜—Kšžœžœ˜ Kšœ˜K˜—š  œžœ!˜2šžœžœžœ˜.Kšœ žœ˜-Kšœžœ˜'Kšœžœ"˜,Kšœžœ'˜1Kšœ;˜;K˜—Kšœ˜K˜—š œžœ˜KšœC˜CKšœ8˜8Kšœ-˜-Kšœ˜—K˜K™K™K˜K˜Kšžœ˜—…—1JEŸ