DIRECTORY Ascii USING [ Letter ], Basics USING [BYTE, LongNumber], BasicTime USING [GMT, ToPupTime], Convert USING [CardFromRope], GVBasics USING [Timestamp], IO, Menus, Nut USING [SetNutInfo, CopyNutInfo], PopUpSelection USING [Request], RefText USING[line, AppendChar, ObtainScratch, ReleaseScratch], Rope, WalnutDocumentRope USING [Create], TEditSplit USING[ Split ], TEditDocument USING [TEditDocumentData, maxClip], TiogaOps USING [CancelSelection, GetSelection, RestoreSelB, SaveSelB, SelectDocument, SetStyle, ViewerDoc], TiogaMenuOps USING[ tiogaMenu, AllLevels ], UserProfile USING [Token], ViewerClasses USING [Viewer], ViewerEvents USING [ EventRegistration, EventProc, ViewerEvent, RegisterEventProc, UnRegisterEventProc ], ViewerLocks USING[ CallUnderWriteLock ], ViewerOps USING [AddProp, CreateViewer, DestroyViewer, FetchProp, GrowViewer, OpenIcon, PaintViewer, SetMenu], ViewerTools USING [TiogaContents, InhibitUserEdits, SetTiogaContents], WalnutOps USING [MsgSet, GetCategories, GetMsgShortName, GetMsg, MsgExists], WalnutOpsExtras USING [GetMsgSize], WalnutViewer USING [CreateMenuEntry], WalnutSendOps USING [Answer, Forward, WalnutSendProc], WalnutSendOpsExtras USING [ReSend], WalnutControlInternal USING [DoWaitCall], WalnutDisplayerInternal, WalnutPrintOps USING [MsgPrintProc], WalnutWindowInternal USING [msgIcon, walnutQueue, Report, ReportRope], WalnutWindow USING [EnumWalnutViewers]; WalnutMsgDisplayerImpl: CEDAR MONITOR IMPORTS Ascii, BasicTime, Convert, IO, Nut, PopUpSelection, RefText, Rope, WalnutDocumentRope, TiogaMenuOps, TiogaOps, TEditSplit, Menus, UserProfile, ViewerEvents, ViewerLocks, ViewerOps, ViewerTools, WalnutOps, WalnutOpsExtras, WalnutSendOps, WalnutSendOpsExtras, WalnutControlInternal, WalnutPrintOps, WalnutViewer, WalnutWindow, WalnutWindowInternal EXPORTS WalnutDisplayerInternal, WalnutWindow SHARES Menus = BEGIN ROPE: TYPE = Rope.ROPE; TiogaContents: TYPE = ViewerTools.TiogaContents; Viewer: TYPE = ViewerClasses.Viewer; MsgSet: TYPE = WalnutOps.MsgSet; msgMenu: PUBLIC Menus.Menu _ Menus.CreateMenu[]; frozenMsgMenu: Menus.Menu _ Menus.CreateMenu[]; nilMenu: Menus.Menu _ Menus.CreateMenu[]; GetMsgName: PUBLIC PROC[v: Viewer] RETURNS[mName: ROPE] = { mName _ NARROW[ViewerOps.FetchProp[v, $WalnutMsgName]]; IF mName = NIL THEN WalnutWindowInternal.Report[" Not a Walnut Msg viewer"]; }; InternalAddToMsgMenu: PUBLIC PROC[label: ROPE, proc: Menus.MenuProc, clientData: REF ANY _ NIL, onQueue: BOOL] = { frozenList: LIST OF Viewer; new: Menus.MenuEntry = IF onQueue THEN WalnutViewer.CreateMenuEntry[ WalnutWindowInternal.walnutQueue, label, proc, clientData] ELSE Menus.CreateEntry[label, proc, clientData]; Menus.AppendMenuEntry[msgMenu, new]; frozenList _ ChangeAllMsgMenus[]; FOR fL: LIST OF Viewer _ frozenList, fL.rest UNTIL fL = NIL DO v: Viewer = fL.first; Menus.AppendMenuEntry[v.menu, new]; ViewerOps.PaintViewer[v, menu]; ENDLOOP; }; RemoveFromMsgMenu: PUBLIC PROC[name: ROPE] = { old: Menus.MenuEntry = Menus.FindEntry[msgMenu, name]; notFound: BOOL _ FALSE; frozenList: LIST OF Viewer; IF old = NIL THEN RETURN; Menus.ReplaceMenuEntry[msgMenu, old ! Menus.targetNotFound => { notFound _ TRUE; CONTINUE}]; IF notFound THEN RETURN; frozenList _ ChangeAllMsgMenus[]; FOR fL: LIST OF Viewer _ frozenList, fL.rest UNTIL fL = NIL DO v: Viewer = fL.first; Menus.ReplaceMenuEntry[v.menu, old ! Menus.targetNotFound => CONTINUE]; ViewerOps.PaintViewer[v, menu]; ENDLOOP; }; onlyInTextViewer: ROPE = "Can only display msgs in Text viewers"; noSplitsAllowed: ROPE = "Can't display msg in a split viewer"; QDisplayMsg: PUBLIC PROC[msg: ROPE, oldV: Viewer, shift: BOOL, openIfIconic: BOOL _ TRUE] RETURNS[v: Viewer] = { contents: TiogaContents; herald, shortName: ROPE; iconName, date: ROPE; LockedSetMenu: PROC = {ViewerOps.SetMenu[v, msgMenu]}; IF ~WalnutOps.MsgExists[msg] THEN RETURN[NIL]; [contents, herald, shortName] _ WalnutOps.GetMsg[msg]; iconName _ Rope.Substr[shortName, 0, shortName.Length[] - 9]; date _ Rope.Substr[shortName, shortName.Length[] - 9]; IF oldV # NIL AND ~oldV.destroyed THEN { oldV.name _ herald; ViewerOps.PaintViewer[oldV, caption]; v _ oldV; } ELSE { v _ ViewerOps.CreateViewer[flavor: $Text, paint: ~shift, info: [name: herald, icon: WalnutWindowInternal.msgIcon, scrollable: TRUE, iconic: FALSE] ]; ViewerLocks.CallUnderWriteLock[LockedSetMenu, v]; IF shift THEN ViewerOps.GrowViewer[v]; shift _ FALSE; -- so don't end up toggling the Grow ViewerOps.AddProp[v, $DestroyMsgDisplayer, ViewerEvents.RegisterEventProc[DestroyMsgDisplayer, destroy, v]]; }; Nut.SetNutInfo[v, $Walnut, "Msg", msg]; ViewerOps.AddProp[v, $WalnutMsgName, msg]; ViewerOps.AddProp[v, $IconLabel, Rope.Cat[StripForIcon[iconName], " .", date]]; ShowMsgInMsgViewer[v, contents, shift, openIfIconic]; }; FixUpMsgViewer: PUBLIC PROC[msg: ROPE, v: Viewer] = { IF (msg.Length[] = 0) OR v.destroyed THEN RETURN; IF QDisplayMsg[msg, v, FALSE].v = NIL THEN { WalnutWindowInternal.Report["Msg: ", msg, " doesn't exist; destroying viewer"]; ViewerOps.DestroyViewer[v]; }; }; DisplayMsgFromMsgSet: PUBLIC PROC[msg: ROPE, msViewer: Viewer, shift: BOOL] = { v: Viewer = NARROW[ViewerOps.FetchProp[msViewer, $LastSpawned]]; newV: Viewer; newV _ QDisplayMsg[msg, v, shift]; IF newV = v THEN RETURN; ViewerOps.AddProp[newV, $WhoSpawnedMe, msViewer]; ViewerOps.AddProp[msViewer, $LastSpawned, newV]; }; MsgForwardProc: Menus.MenuProc = { self: Viewer _ NARROW[parent]; self.inhibitDestroy_ TRUE; []_ WalnutSendOps.Forward[self, self]; self.inhibitDestroy_ FALSE; }; MsgReSendProc: Menus.MenuProc = { self: Viewer _ NARROW[parent]; self.inhibitDestroy_ TRUE; []_ WalnutSendOpsExtras.ReSend[self, self]; self.inhibitDestroy_ FALSE; }; MsgAnswerProc: Menus.MenuProc = { OPEN TiogaOps; self: Viewer _ NARROW[parent]; msgR: ROPE; self.inhibitDestroy _ TRUE; TRUSTED { msgR _ WalnutDocumentRope.Create[LOOPHOLE[ViewerDoc[self]]]}; [] _ WalnutSendOps.Answer[msgR, self]; self.inhibitDestroy _ FALSE; }; MsgOpsProc: Menus.MenuProc = { self: Viewer = NARROW[parent]; msg: ROPE = NARROW[ViewerOps.FetchProp[self, $WalnutMsgName]]; which: INT = PopUpSelection.Request["MsgOps", LIST["Sender", "Categories", "SizeOf", "gvID", "PressPrint", "Interpress3.0Print"] ]; SELECT which FROM 1 => WalnutSendOps.WalnutSendProc[fromExec: FALSE]; 2 => MsgCategoriesProc[self, msg]; 3 => { textLen, formatLen: INT; [textLen, formatLen] _ WalnutOpsExtras.GetMsgSize[msg]; IF formatLen # 0 THEN WalnutWindowInternal.Report[IO.PutFR["Formatted Msg \" %g\" has %g bytes of text", IO.rope[msg], IO.int[textLen] ]] ELSE WalnutWindowInternal.Report[IO.PutFR["Msg \"%g\" has %g bytes of text", IO.rope[msg], IO.int[textLen] ]]; }; 4 => MsgGvId[msg, mouseButton # red]; 5 => MsgPrint[self: self, usePress: TRUE]; 6 => MsgPrint[self: self, usePress: FALSE]; ENDCASE => NULL; }; MsgCategoriesProc: PROC[self: Viewer, msg: ROPE] = { IF ViewerOps.FetchProp[self, $Frozen] # NIL AND ~WalnutOps.MsgExists[msg] THEN WalnutWindowInternal.Report[ "Msg ", msg, " in a frozen viewer doesn't exist in this database"] ELSE MsgCategories[msg]; }; MsgFreezeProc: Menus.MenuProc = { self: Viewer = NARROW[parent]; msViewer: Viewer = NARROW[ViewerOps.FetchProp[self, $WhoSpawnedMe]]; frozen: Menus.MenuEntry = Menus.FindEntry[self.menu, "Freeze"]; IF frozen # NIL THEN FreezeViewer[self]; IF self.link # NIL THEN -- you are part of a split viewer FOR newV: Viewer _ self.link, newV.link UNTIL newV = self DO FreezeViewer[newV] ENDLOOP; IF msViewer # NIL THEN ViewerOps.AddProp[msViewer, $LastSpawned, NIL] }; FreezeViewer: PROC[ v: Viewer ] = { ViewerOps.AddProp[ v, $Frozen, v ]; ViewerOps.SetMenu[v, frozenMsgMenu]; }; MsgSplitProc: Menus.MenuProc = { self: Viewer = NARROW[parent]; newV: Viewer; frozen: REF ANY = ViewerOps.FetchProp[self, $Frozen]; TEditSplit.Split[self]; FOR newV _ self.link, newV.link UNTIL newV.link = self DO ENDLOOP; Nut.CopyNutInfo[from: self, to: newV]; ViewerOps.AddProp[ newV, $WalnutMsgName, ViewerOps.FetchProp[self, $WalnutMsgName] ]; ViewerOps.AddProp[ newV, $WhoSpawnedMe, ViewerOps.FetchProp[ self, $WhoSpawnedMe ] ]; IF frozen # NIL THEN FreezeViewer[newV] ELSE ViewerOps.AddProp[ newV, $DestroyMsgDisplayer, ViewerEvents.RegisterEventProc[DestroyMsgDisplayer, destroy, newV] ]; newV.icon _ WalnutWindowInternal.msgIcon }; DestroyMsgDisplayer: ViewerEvents.EventProc = { eventProc: ViewerEvents.EventRegistration; next: Viewer = viewer.link; spawner: Viewer = NARROW[ ViewerOps.FetchProp[viewer, $WhoSpawnedMe] ]; IF ViewerOps.FetchProp[viewer, $Frozen] # NIL THEN RETURN; -- you're not involved IF spawner # NIL THEN ViewerOps.AddProp[ spawner, $LastSpawned, next ]; eventProc_ NARROW[ ViewerOps.FetchProp[viewer, $DestroyMsgDisplayer]]; ViewerEvents.UnRegisterEventProc[ eventProc, destroy]; }; MsgPlacesProc: Menus.MenuProc = Menus.CopyEntry[ Menus.FindEntry[ TiogaMenuOps.tiogaMenu, "Places" ] ].proc; MsgLevelsProc: Menus.MenuProc = Menus.CopyEntry[ Menus.FindEntry[ TiogaMenuOps.tiogaMenu, "Levels" ] ].proc; MsgCategories: PUBLIC PROC[msg: ROPE] = { Mc: PROC = { msL: LIST OF ROPE _ WalnutOps.GetCategories[msg]; first: BOOL _ TRUE; shortName: ROPE = WalnutOps.GetMsgShortName[msg]; WalnutWindowInternal.ReportRope[IO.PutFR[" %g is in: ", IO.rope[shortName]]]; IF msL = NIL THEN {WalnutWindowInternal.Report["no MsgSets! This is a bug."]; RETURN}; FOR mL: LIST OF ROPE _ msL, mL.rest UNTIL mL=NIL DO IF first THEN first _ FALSE ELSE WalnutWindowInternal.ReportRope[", "]; WalnutWindowInternal.ReportRope[mL.first]; ENDLOOP; WalnutWindowInternal.ReportRope["\n"]; }; [] _ WalnutControlInternal.DoWaitCall[Mc]; }; MsgGvId: PUBLIC PROC[msg: ROPE, all: BOOL] = { Mg: PROC = { gID, other: ROPE; WalnutWindowInternal.Report["gvID for msg is: ", msg]; IF ~all THEN RETURN; [gID, other] _ OtherIDFormats[msg]; WalnutWindowInternal.Report[gID]; WalnutWindowInternal.Report[other]; }; [] _ WalnutControlInternal.DoWaitCall[Mg]; }; MsgPrint: PROC[self: Viewer, usePress: BOOL] = { Mp: PROC = { WalnutPrintOps.MsgPrintProc[self, usePress] }; [] _ WalnutControlInternal.DoWaitCall[Mp]; }; OtherIDFormats: PROC[msg: ROPE] RETURNS[gID, other: ROPE] = { OPEN IO; ts: GVBasics.Timestamp; h: IO.STREAM _ IO.RIS[msg]; netAsRope, hostAsRope: ROPE; netAsLC, hostAsLC: LONG CARDINAL; tyme: BasicTime.GMT; net, host: Basics.BYTE; sender, gvTimeStamp: ROPE; BEGIN temp: REF TEXT = RefText.ObtainScratch[RefText.line]; ch: CHAR; temp.length _ 0; UNTIL (ch _ h.GetChar[]) = '$ DO [] _ RefText.AppendChar[temp, ch]; ENDLOOP; temp.length _ temp.length - 1; -- delete trailing SP sender _ Rope.FromRefText[temp]; RefText.ReleaseScratch[temp]; END; [] _ h.GetChar[]; -- space netAsRope _ h.GetCedarTokenRope[].token; [] _ h.GetChar[]; -- # hostAsRope _ h.GetCedarTokenRope[].token; [] _ h.GetChar[]; -- @ tyme _ h.GetTime[]; netAsLC _ Convert.CardFromRope[netAsRope, 8]; hostAsLC _ Convert.CardFromRope[hostAsRope, 8]; net _ LOOPHOLE[netAsLC, Basics.LongNumber].ll; host _ LOOPHOLE[hostAsLC, Basics.LongNumber].ll; ts _ [net: net, host: host, time: BasicTime.ToPupTime[tyme]]; gvTimeStamp _ RopeFromTimestamp[ts]; gID _ PutFR["[sender: %g, gvTimeStamp: %g]", rope[sender], rope[gvTimeStamp]]; }; RopeFromTimestamp: PROC[stamp: GVBasics.Timestamp] RETURNS[Rope.ROPE] = { RETURN[ IO.PutFR["%b#%b@%g", [integer[stamp.net]], [integer[stamp.host]], [cardinal[stamp.time]] ] ] }; ChangeAllMsgMenus: PROC RETURNS[fL: LIST OF Viewer] = { vL: LIST OF Viewer _ WalnutWindow.EnumWalnutViewers[keepSeparate: TRUE].msgList; FOR vL2: LIST OF Viewer _ vL, vL2.rest UNTIL vL2 = NIL DO IF ViewerOps.FetchProp[vL2.first, $Frozen] # NIL THEN fL _ CONS[vL2.first, fL] ELSE ViewerOps.SetMenu[vL2.first, msgMenu]; ENDLOOP; }; plainTextStyle: PUBLIC ROPE _ UserProfile.Token[key: "Walnut.PlainTextStyle", default: "cedar"]; ShowMsgInMsgViewer: PROC[v: Viewer, contents: TiogaContents, shift: BOOL, open: BOOL _ TRUE] = { painted: BOOL _ FALSE; KillFeedbackSel[v]; IF v.link # NIL THEN DestroySplitMsgDisplayers[v]; BEGIN WITH v.data SELECT FROM tdd: TEditDocument.TEditDocumentData => IF tdd.clipLevel # TEditDocument.maxClip THEN painted _ TRUE ENDCASE; END; IF contents.formatting.IsEmpty[] AND NOT Rope.Equal[plainTextStyle, "cedar"] THEN { -- Plain Text ViewerTools.SetTiogaContents[v, contents, FALSE]; TiogaOps.SaveSelB[]; TiogaOps.SelectDocument[viewer: v, level: point]; TiogaOps.SetStyle[plainTextStyle, root]; v.newVersion _ FALSE; -- Is there a ``better'' way to do this? ViewerOps.PaintViewer[v, all]; TiogaOps.RestoreSelB[]; } ELSE { -- Tioga formatted; needn't reset the style ViewerTools.SetTiogaContents[v, contents, NOT painted]; TiogaMenuOps.AllLevels[v]; }; ViewerTools.InhibitUserEdits[v]; IF v.iconic THEN { IF ~open THEN RETURN; ViewerOps.OpenIcon[v, shift] } ELSE IF shift THEN ViewerOps.GrowViewer[v] }; KillFeedbackSel: PROC[v: Viewer] = { OPEN TiogaOps; who: Viewer _ GetSelection[feedback].viewer; IF who = v THEN CancelSelection[feedback]; }; DestroySplitMsgDisplayers: ENTRY PROC[keepThisOne: Viewer] = { ENABLE UNWIND => NULL; next: Viewer_ keepThisOne.link; next2: Viewer; event: ViewerEvents.EventRegistration; DO IF next = keepThisOne THEN EXIT; IF (event _ NARROW[ViewerOps.FetchProp[next, $DestroyMsgDisplayer]]) = NIL THEN LOOP; ViewerEvents.UnRegisterEventProc[event, destroy]; next2 _ next.link; ViewerOps.DestroyViewer[next]; -- DON'T FORK here next _ next2; ENDLOOP; }; StripForIcon: PROC[name: ROPE] RETURNS[ iconLabel: ROPE ] = { start: INT; dot: INT; suffixLength: NAT; start _ 0; WHILE (dot _ Rope.Find[Rope.Substr[name, start], "."]) # -1 DO length: INT = Rope.Length[name]; dot _ dot+start; IF length - dot < 2 THEN EXIT; suffixLength _ 0; WHILE dot+1+suffixLength < length AND Ascii.Letter[Rope.Fetch[name, dot+1+suffixLength]] DO suffixLength _ suffixLength+1 ENDLOOP; IF suffixLength >= 0 THEN { name _ Rope.Replace[name, dot, suffixLength+1]; start _ dot } ELSE start _ dot+suffixLength+1 ENDLOOP; iconLabel _ Rope.Substr[name, 0, Rope.Length[name]-1] }; { OPEN Menus, WalnutWindowInternal; AppendMenuEntry[ msgMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "Freeze", MsgFreezeProc]]; AppendMenuEntry[ msgMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "Answer", MsgAnswerProc]]; AppendMenuEntry[msgMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "Forward", MsgForwardProc]]; AppendMenuEntry[msgMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "ReSend", MsgReSendProc]]; AppendMenuEntry[msgMenu, Menus.CreateEntry["MsgOps", MsgOpsProc]]; AppendMenuEntry[ msgMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "Split", MsgSplitProc]]; AppendMenuEntry[ msgMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "Places", MsgPlacesProc]]; AppendMenuEntry[ msgMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "Levels", MsgLevelsProc]]; AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["Answer", MsgAnswerProc]]; AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["Forward", MsgForwardProc]]; AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["ReSend", MsgReSendProc]]; AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["MsgOps", MsgOpsProc]]; AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["Split", MsgSplitProc]]; AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["Places", MsgPlacesProc]]; AppendMenuEntry[ frozenMsgMenu, Menus.CreateEntry["Levels", MsgLevelsProc]]; }; END. Change Log. WSH on March 4, 1983: take out all DBText stuff ΜWalnutMsgDisplayerImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last Edited by: Willie-Sue, September 29, 1986 11:07:08 am PDT Pavel, February 6, 1986 3:33:33 pm PST Donahue, June 17, 1985 4:53:34 pm PDT Contents: Implementation of the Walnut Msg Display windows. Status: complete. Created by: Rick Cattell & Willie-Sue Haugeland, 17-Feb-82 Last Edited by: Donahue, December 27, 1984 11:41:54 am PST (Added Nut connection) (Changed StripForIcon to remove all registry information from icon labels) Rick on: April 13, 1982 11:50 am Willie-Sue on: January 3, 1985 4:27:53 pm PST -------------------------- exported to WalnutWindow of v is a Viewer for a Walnut Entity, then return its name else NIL * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Note how we cleverly put in a "." here to get the date to appear on a new line *********************************************************** menu command procs: now freeze everyone linked to you only need to do this once now find the newest link in the chain to copy properties * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * the one from GVBasics gets a bound fault * * * * * * * * * * * * * * * * * * * * * * * * * * * * -- a menu entry was added or removed - update all msg viewers check to see whether AllLevels will cause a paint bug in SetTiogaContents necessitates this Remove all registry information from the icon label -- where registry information is taken to be any sequence of letters following a period * * * * * * * * * * * * * * * * * * * * * * * * * * * * initialize menues: AppendMenuEntry[msgMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "Print", WalnutPrintOps.MsgPrintProc]]; Κ˜šΟn™Icodešœ Οmœ1™™>K™&K™%—J™Jšœ;™;J˜Jšœ™Jšœ:™:Jšœ:™:J™™JJšœ ™ Jšœ-™-J˜—šΟk ˜ JšœŸœ ˜JšœŸœŸœ˜ Jšœ ŸœŸœ ˜!JšœŸœ˜Jšœ Ÿœ ˜JšŸœ˜J˜JšœŸœ˜$JšœŸœ ˜JšœŸœ2˜?J˜JšœŸœ ˜"Jšœ Ÿœ ˜JšœŸœ˜1Jšœ Ÿœ]˜kJšœ Ÿœ˜+Kšœ Ÿœ ˜JšœŸœ ˜šœ Ÿœ-˜?J˜)—Jšœ Ÿœ˜(šœ ŸœH˜WJ˜—Jšœ Ÿœ5˜FJ˜Jšœ Ÿœ=˜LJšœŸœ˜#J˜Jšœ Ÿœ˜%JšœŸœ#˜6JšœŸœ ˜#JšœŸœ˜)J˜JšœŸœ˜$JšœŸœ,˜FJšœ Ÿœ˜'J˜—šœŸœŸ˜%šŸ˜JšœŸœ%˜BJ˜7J˜FJšœ˜JšœJ˜JJšœ0˜0—šŸ˜Jšœ%˜%—JšŸœ˜J˜—JšŸ˜J˜JšŸœŸœŸœ˜JšœŸœ˜0JšœŸœ˜$JšœŸœ˜ J˜Jšœ Ÿœ!˜0Jšœ/˜/J˜J˜)J˜Jšœ™J™˜š  œŸœŸœ ŸœŸœ˜;JšœC™CJšœŸœ)˜7JšŸœ ŸœŸœ9˜LJšœ˜J˜—šœŸœŸœŸœ˜DJš œ ŸœŸœŸœ Ÿœ˜.Jšœ ŸœŸœ˜šœŸœ Ÿ˜&šœ˜Jšœ;˜;—JšŸœ,˜0—Jšœ$˜$Jšœ!˜!š ŸœŸœŸœŸœŸœŸ˜?Jšœ˜Jšœ#˜#Jšœ˜JšŸœ˜—J˜Jšœ˜——˜šœŸœŸœŸœ˜.Jšœ6˜6Jšœ ŸœŸœ˜Jšœ ŸœŸœ˜JšŸœŸœŸœŸœ˜šœ=˜=Jšœ ŸœŸœ˜—JšŸœ ŸœŸœ˜Jšœ!˜!š ŸœŸœŸœŸœŸœŸ˜?Jšœ˜Jšœ=Ÿœ˜GJšœ˜JšŸœ˜—J˜——˜JšœŸœ+˜AJšœŸœ)˜>—˜J™O—™š œŸœŸœŸœŸœŸœŸœ˜YJšœŸœ˜J˜JšœŸœ˜JšœŸœ˜J˜Jš œŸœ#˜6J˜JšŸœŸœŸœŸœ˜.J˜Jšœ6˜6Jšœ=˜=Jšœ6˜6J˜šŸœŸœŸœŸ˜&šœ˜Jšœ%˜%J˜ J˜—šŸœ˜˜:šœ9˜9JšœŸœ Ÿœ˜%—J˜J˜1JšŸœŸœ˜&JšœŸœΟc$˜4˜*J˜A——J˜J˜——Jšœ'˜'Jšœ*˜*JšœN™NJšœO˜OJ˜Jšœ5˜5Jšœ˜J˜—šœŸœŸœŸœ˜5JšŸœŸœ ŸœŸœ˜1šŸœŸœŸœŸœ˜,JšœO˜OJ˜J˜—Jšœ˜—J˜š œŸœŸœŸœŸœ˜OJšœ Ÿœ.˜@Jšœ ˜ Jšœ"˜"JšŸœ ŸœŸœ˜Jšœ1˜1Jšœ0˜0J˜—J˜Jšœ;™;—˜Jšœ™—˜šœ˜"JšœŸœ ˜JšœŸœ˜J˜&JšœŸœ˜˜J˜——š œ˜!JšœŸœ ˜JšœŸœ˜J˜+JšœŸœ˜˜J˜——š œ˜!JšŸœ ˜JšœŸœ ˜JšœŸœ˜ JšœŸœ˜JšŸœ$Ÿœ˜GJ˜&JšœŸœ˜J˜—J˜š œ˜JšœŸœ ˜JšœŸœŸœ,˜>šœŸœ#˜-JšŸœN˜RJ˜—J˜šŸœŸ˜Jšœ,Ÿœ˜3Jšœ"˜"šœ˜JšœŸœ˜Jšœ7˜7šŸœŸ˜šœŸœ4˜RJšœŸœ Ÿœ˜"—šŸœŸœ)˜LJšœŸœ Ÿœ˜"——J˜—Jšœ%˜%Jšœ$Ÿœ˜*Jšœ$Ÿœ˜+JšŸœŸœ˜—J˜J˜—šœŸœŸœ˜4šŸœ&ŸœŸœŸ˜N˜J˜B—JšŸœ˜—Jšœ˜J˜—š œ˜!JšœŸœ ˜JšœŸœ+˜DJ˜?JšŸœ ŸœŸœ˜(Jšœ!™!šŸœ ŸœŸœ !˜9šŸœ%Ÿœ Ÿ˜Kšœ˜Kšœ˜K˜—šŸœ +˜2Jšœ*Ÿœ ˜7J˜J˜J˜—J˜ J˜šŸœ Ÿœ˜šŸœŸ˜ JšŸœ˜—Jšœ˜Jšœ˜—šŸœŸœŸ˜Jšœ˜—Jšœ˜J˜—Jšœ)™)šœŸœ˜$šŸœ ˜J˜,JšŸœ Ÿœ˜*—Jšœ˜J˜—šœŸœŸœ˜>JšŸœŸœŸœ˜J˜J˜J˜&šŸ˜JšŸœŸœŸœ˜ Jš Ÿœ Ÿœ5ŸœŸœŸœ˜UJ˜1J˜Jšœ  ˜2J˜ JšŸœ˜—Jšœ˜J˜—š  œŸœŸœŸœ Ÿœ˜=JšœŸœ˜ JšœŸœ˜ JšœŸœ˜J™‹J˜ šŸœ7Ÿ˜>JšœŸœ˜ J˜JšŸœŸœŸœ˜J˜šŸœŸ˜%šœ3Ÿ˜5J˜JšŸœ˜——šŸœŸ˜J˜?—JšŸœ˜JšŸœ˜J˜5—J˜J˜—Jšœ7™7—˜Jšœ™šœŸœ˜#˜J˜D—˜J˜D—˜J˜F—˜J˜D—J˜B™J™Q—˜J˜B—˜J˜D—˜J˜D—J˜J˜LJ˜NJ˜LJ˜IJ˜JJ˜LJ˜LJ˜J˜——J˜JšŸœ˜J˜J˜ JšŸœ,˜/J˜J˜—…—;ώSα