DIRECTORY Buttons USING [Button, ButtonProc, SetDisplayStyle], EditToolBuilder USING [BuildButton, BuildDataFieldPair, BuildLabel, BuildPair, BuildTriple, DataFieldButton, GetDataNode, HGap, ToMiddle, ToNext], EditToolPrivate USING [anywhere, ChangeState, CycleTriple, DoButton, FixPSel, Info, mainToolInfo, nodes, Register, ReportPatternError, SavePSel, words], EditSpanSupport USING [CopySpan], Labels USING [Set], Menus USING [MenuProc], MessageWindow USING [Append, Blink, Clear], NodeProps USING [DoSpecs], Rope USING [Concat, ROPE], RunReader USING [Backwards, FreeRunReader, Get, GetRunReader, Ref, SetPosition], TEditDocument USING [Selection], TEditInput USING [CloseEvent, CommandProc], TEditOps USING [GetSelData, SetTextContents], TEditSelection USING [LockSel, UnlockSel], TextEdit USING [ChangeFormat, PutProp, Size], TextFind USING [Finder, MalformedPattern], TextLooks USING [Looks, noLooks, Runs], TextLooksSupport USING [LooksAND], TextNode USING [Ref, RefTextNode, Root, MakeNodeSpan], TiogaOps USING [CreateGeneralPattern, Finder, MalformedPattern, Pattern, Ref, SearchDir, SelectionSearch], TreeFind USING [Finder], ViewerClasses USING [Viewer], ViewerOps USING [AddProp, BlinkDisplay, CreateViewer], ViewerSpecs USING [openRightWidth], ViewerTools USING [InhibitUserEdits]; EditToolSearchImpl: CEDAR PROGRAM IMPORTS Buttons, EditSpanSupport, EditToolBuilder, EditToolPrivate, Labels, MessageWindow, NodeProps, Rope, RunReader, TEditOps, TextEdit, TextFind, TextLooksSupport, TextNode, TEditInput, TEditSelection, TiogaOps, ViewerOps, ViewerSpecs, ViewerTools EXPORTS EditToolPrivate = { OPEN EditToolPrivate, EditToolBuilder; searchForwardAtom: LIST OF REF = Register[$SearchForward,SearchForwardOp]; SearchForwardOp: TEditInput.CommandProc = { Search[forwards,mainToolInfo] }; searchAnywhereAtom: LIST OF REF = Register[$SearchAnywhere,SearchAnywhereOp]; SearchAnywhereOp: TEditInput.CommandProc = { Search[anywhere,mainToolInfo] }; searchBackwardsAtom: LIST OF REF = Register[$SearchBackwards,SearchBackwardsOp]; SearchBackwardsOp: TEditInput.CommandProc = { Search[backwards,mainToolInfo] }; DoSearchMenuButton: PUBLIC Menus.MenuProc = { SELECT mouseButton FROM red => DoButton[searchForwardAtom]; yellow => DoButton[searchAnywhereAtom]; blue => DoButton[searchBackwardsAtom]; ENDCASE => ERROR; }; CheckPSel: PUBLIC PROC [pSel: TEditDocument.Selection, typescriptOK: BOOL _ TRUE] RETURNS [ok: BOOL] = { OPEN MessageWindow; IF pSel#NIL AND pSel.viewer#NIL AND (pSel.viewer.class.flavor=$Text OR (typescriptOK AND pSel.viewer.class.flavor=$Typescript)) THEN RETURN [TRUE]; Append["Please make a text selection.",TRUE]; Blink[]; RETURN [FALSE]; }; GetPatternNode: PUBLIC PROC [info: Info] RETURNS [pattern: TextNode.RefTextNode] = { OPEN info; IF ((pattern _ GetDataNode[targetArg])=NIL OR TextEdit.Size[pattern]=0) AND (~ignoreLooks OR ~ignoreText) THEN { OPEN MessageWindow; Append["Please enter a search pattern in the \"target\" field.",TRUE]; Blink[]; RETURN [NIL]; }; }; Search: PUBLIC PROC [whichDir: TiogaOps.SearchDir, info: Info] = TRUSTED { IF ~TrySearch[whichDir, info] THEN { MessageWindow.Append["Not found.", TRUE]; ViewerOps.BlinkDisplay[]; } ELSE MessageWindow.Clear[]; }; TrySearch: PUBLIC PROC [whichDir: TiogaOps.SearchDir, info: Info] RETURNS [found: BOOL] = { OPEN info; pattern: TextNode.RefTextNode; pSel: TEditDocument.Selection; searchPattern: TiogaOps.Pattern; IF ignoreText AND ignoreLooks AND ignoreFormat AND ignoreStyle AND ignoreComment THEN { OPEN MessageWindow; Append["Pick one or more of text/looks/format/style/comment to match.", TRUE]; Blink[]; RETURN; }; TEditSelection.LockSel[primary, "TrySearch"]; { ENABLE UNWIND => TEditSelection.UnlockSel[primary]; FixPSel; pSel _ TEditOps.GetSelData[]; IF ~CheckPSel[pSel] OR (pattern _ GetPatternNode[info])=NIL THEN { TEditSelection.UnlockSel[primary]; RETURN; }; TRUSTED { searchPattern _ TiogaOps.CreateGeneralPattern[LOOPHOLE[pattern], ~ignoreText, ~ignoreLooks, ~ignoreFormat, ~ignoreStyle, ~ignoreComment, ~ignoreCase, literal, searchWhere=words, ~looksExact, searchWhere=nodes ! TextFind.MalformedPattern => { ReportPatternError[ec]; GOTO Quit }; TiogaOps.MalformedPattern => { msg: Rope.ROPE = SELECT ec FROM toobig => "Pattern too long", endquote => "Pattern ends with quote (')", endtilda => "Pattern ends with tilde (~)", boundary => "Pattern has | inside rather than at beginning or end", missingNameEnd => "Pattern has < without matching >", unmatchedNameEnd => "Pattern has > without previous <", ENDCASE => "Pattern error (consult CedarSupport^)"; MessageWindow.Append[msg, TRUE]; MessageWindow.Blink[]; GOTO Quit}; ]}; TRUSTED { finder _ LOOPHOLE[searchPattern.finder, TreeFind.Finder]; }; found _ TiogaOps.SelectionSearch[searchPattern, whichDir, interrupt]; IF NOT found THEN GOTO Quit; TEditInput.CloseEvent[]; IF info.varNode # NIL THEN info.varNode.next _ NIL; info.varNode _ IF info.literal THEN NIL ELSE EditSpanSupport.CopySpan[TextNode.MakeNodeSpan[pSel.start.pos.node, pSel.start.pos.node]].start.node; EXITS Quit => {}; }; TEditSelection.UnlockSel[primary]; }; Extend: PUBLIC PROC [info: Info, forward: BOOL, searchLooks: TextLooks.Looks, where: TextNode.RefTextNode, at, atEnd: INT, last: TextNode.Ref _ NIL, lastLen: INT _ INT.LAST] RETURNS [newAt, newAtEnd: INT] = { OPEN info; runrdr: RunReader.Ref _ RunReader.GetRunReader[]; looks: TextLooks.Looks; runLen: INT; runs: TextLooks.Runs _ where.runs; IF forward THEN { -- extend toward end of node size: INT _ TextEdit.Size[where]; IF atEnd=size OR size=0 THEN RETURN [at,atEnd]; lastLen _ IF where=last THEN MIN[size,lastLen] ELSE size; RunReader.SetPosition[runrdr,runs,atEnd]; WHILE atEnd < lastLen DO IF runs=NIL THEN { runLen _ size-atEnd; looks _ TextLooks.noLooks } ELSE [runLen,looks] _ RunReader.Get[runrdr]; IF ~looksExact THEN looks _ TextLooksSupport.LooksAND[looks,searchLooks]; IF searchLooks # looks THEN EXIT; atEnd _ atEnd+runLen; ENDLOOP; RunReader.FreeRunReader[runrdr]; RETURN [at,MIN[atEnd,lastLen]] }; IF at=0 THEN RETURN [at,atEnd]; RunReader.SetPosition[runrdr,runs,at]; WHILE at > 0 DO IF runs=NIL THEN { runLen _ at; looks _ TextLooks.noLooks } ELSE [runLen,looks] _ RunReader.Backwards[runrdr]; IF ~looksExact THEN looks _ TextLooksSupport.LooksAND[looks,searchLooks]; IF searchLooks # looks THEN EXIT; at _ at-runLen; ENDLOOP; RunReader.FreeRunReader[runrdr]; RETURN [at,atEnd]; }; BuildSearchButtons: PUBLIC PROC [info: Info] = { BuildSearchChoiceEntries[info]; ToNext[info.layout]; BuildCaseEntry[info]; ToMiddle[info.layout]; BuildWhereEntry[info]; ToNext[info.layout]; BuildLitOrPatternEntry[info]; ToMiddle[info.layout]; BuildLooksMatchEntry[info]; }; equalLooks: Rope.ROPE = "Equal as Looks Test"; subsetLooks: Rope.ROPE = "Subset as Looks Test"; equalLooksAtom: LIST OF REF = Register[$EqualLooksTest,EqualLooksTestOp]; subsetLooksAtom: LIST OF REF = Register[$SubsetLooksTest,SubsetLooksTestOp]; LooksMatchButton: Buttons.ButtonProc = { ChangeState[mainToolInfo.looksExact, equalLooksAtom,subsetLooksAtom]; }; EqualLooksTestOp: TEditInput.CommandProc = { EqualLooksTest[mainToolInfo]; }; EqualLooksTest: PROC [info: Info] = { OPEN info; looksExact _ TRUE; Labels.Set[looksMatchLabel,equalLooks]; }; SubsetLooksTestOp: TEditInput.CommandProc = { SubsetLooksTest[mainToolInfo]; }; SubsetLooksTest: PROC [info: Info] = { OPEN info; looksExact _ FALSE; Labels.Set[looksMatchLabel,subsetLooks]; }; BuildLooksMatchEntry: PROC [info: Info] = { OPEN info; looksExact _ FALSE; [looksMatchLabel,] _ BuildPair[layout,LooksMatchButton,looksExact,equalLooks,subsetLooks,info]; }; BuildSearchChoiceEntries: PROC [info: Info] = { OPEN info; BuildEntry: PROC [name: Rope.ROPE, proc: Buttons.ButtonProc, state: BOOL] RETURNS [new: Buttons.Button] = { new _ BuildButton[layout, name, proc, info, FALSE, FALSE]; ViewerOps.AddProp[new, $DisableMBFeedback, $DisableMBFeedback]; SetButton[new, state, FALSE]; }; [] _ BuildLabel[layout, "Pick one or more: "]; HGap[layout]; textButton _ BuildEntry["Text", MatchTextButton, ignoreText _ FALSE]; looksButton _ BuildEntry["Looks", MatchLooksButton, ignoreLooks _ TRUE]; formatButton _ BuildEntry["Format", MatchFormatButton, ignoreFormat _ TRUE]; styleButton _ BuildEntry["Style", MatchStyleButton, ignoreStyle _ TRUE]; commentButton _ BuildEntry["Comment", MatchCommentButton, ignoreComment _ TRUE]; }; SetButton: PROC [viewer: Buttons.Button, ignore: BOOL, paint: BOOL _ TRUE] = { Buttons.SetDisplayStyle[viewer, IF ignore THEN $BlackOnWhite ELSE $WhiteOnBlack, paint]; }; matchTextAtom: LIST OF REF = Register[$MatchText,MatchTextOp]; ignoreTextAtom: LIST OF REF = Register[$IgnoreText,IgnoreTextOp]; MatchTextButton: Buttons.ButtonProc = { ChangeState[mainToolInfo.ignoreText, ignoreTextAtom, matchTextAtom]; }; MatchTextOp: TEditInput.CommandProc = { MatchText[mainToolInfo] }; MatchText: PROC [info: Info] = { OPEN info; SetButton[textButton, ignoreText _ FALSE]; }; IgnoreTextOp: TEditInput.CommandProc = { IgnoreText[mainToolInfo] }; IgnoreText: PROC [info: Info] = { OPEN info; SetButton[textButton, ignoreText _ TRUE]; }; matchLooksAtom: LIST OF REF = Register[$MatchLooks,MatchLooksOp]; ignoreLooksAtom: LIST OF REF = Register[$IgnoreLooks,IgnoreLooksOp]; MatchLooksButton: Buttons.ButtonProc = { ChangeState[mainToolInfo.ignoreLooks, ignoreLooksAtom, matchLooksAtom]; }; MatchLooksOp: TEditInput.CommandProc = { MatchLooks[mainToolInfo]; }; MatchLooks: PROC [info: Info] = { OPEN info; SetButton[looksButton, ignoreLooks _ FALSE]; }; IgnoreLooksOp: TEditInput.CommandProc = { IgnoreLooks[mainToolInfo]; }; IgnoreLooks: PROC [info: Info] = { OPEN info; SetButton[looksButton, ignoreLooks _ TRUE]; }; matchFormatAtom: LIST OF REF = Register[$MatchFormat,MatchFormatOp]; ignoreFormatAtom: LIST OF REF = Register[$IgnoreFormat,IgnoreFormatOp]; MatchFormatButton: Buttons.ButtonProc = { ChangeState[mainToolInfo.ignoreFormat, ignoreFormatAtom,matchFormatAtom] }; MatchFormatOp: TEditInput.CommandProc = { MatchFormat[mainToolInfo]; }; MatchFormat: PROC [info: Info] = { OPEN info; SetButton[formatButton, ignoreFormat _ FALSE]; }; IgnoreFormatOp: TEditInput.CommandProc = { IgnoreFormat[mainToolInfo]; }; IgnoreFormat: PROC [info: Info] = { OPEN info; SetButton[formatButton, ignoreFormat _ TRUE]; }; matchStyleAtom: LIST OF REF = Register[$MatchStyle,MatchStyleOp]; ignoreStyleAtom: LIST OF REF = Register[$IgnoreStyle,IgnoreStyleOp]; MatchStyleButton: Buttons.ButtonProc = { ChangeState[mainToolInfo.ignoreStyle, ignoreStyleAtom,matchStyleAtom] }; MatchStyleOp: TEditInput.CommandProc = { MatchStyle[mainToolInfo] }; MatchStyle: PROC [info: Info] = { OPEN info; SetButton[styleButton, ignoreStyle _ FALSE] }; IgnoreStyleOp: TEditInput.CommandProc = { IgnoreStyle[mainToolInfo] }; IgnoreStyle: PROC [info: Info] = { OPEN info; SetButton[styleButton, ignoreStyle _ TRUE] }; matchCommentAtom: LIST OF REF = Register[$MatchComment,MatchCommentOp]; ignoreCommentAtom: LIST OF REF = Register[$IgnoreComment,IgnoreCommentOp]; MatchCommentButton: Buttons.ButtonProc = { ChangeState[mainToolInfo.ignoreComment, ignoreCommentAtom,matchCommentAtom] }; MatchCommentOp: TEditInput.CommandProc = { MatchComment[mainToolInfo] }; MatchComment: PROC [info: Info] = { OPEN info; SetButton[commentButton, ignoreComment _ FALSE] }; IgnoreCommentOp: TEditInput.CommandProc = { IgnoreComment[mainToolInfo] }; IgnoreComment: PROC [info: Info] = { OPEN info; SetButton[commentButton, ignoreComment _ TRUE] }; matchingLiterally: Rope.ROPE = "Match Literally"; matchingAsPattern: Rope.ROPE = "Match as Pattern"; matchLitAtom: LIST OF REF = Register[$MatchLiterally,MatchLitOp]; matchPatternAtom: LIST OF REF = Register[$MatchPattern,MatchPatternOp]; LiteralButton: Buttons.ButtonProc = { ChangeState[mainToolInfo.literal, matchLitAtom,matchPatternAtom]; }; MatchLitOp: TEditInput.CommandProc = { MatchLit[mainToolInfo]; }; MatchLit: PROC [info: Info] = { OPEN info; literal _ TRUE; Labels.Set[literalLabel,matchingLiterally]; }; MatchPatternOp: TEditInput.CommandProc = { MatchPattern[mainToolInfo]; }; MatchPattern: PROC [info: Info] = { OPEN info; literal _ FALSE; Labels.Set[literalLabel,matchingAsPattern]; }; BuildLitOrPatternEntry: PROC [info: Info] = { OPEN info; literal _ TRUE; [literalLabel,] _ BuildPair[layout,LiteralButton,literal,matchingLiterally,matchingAsPattern,info]; }; numDocRopes: NAT = 18; docRopes: REF ARRAY [0..numDocRopes) OF Rope.ROPE _ NEW[ARRAY [0..numDocRopes) OF Rope.ROPE]; BuildPatternDocEntry: PUBLIC PROC [info: Info] = { OPEN info.layout; lines: CARDINAL = 25; rope: Rope.ROPE; arg: ViewerClasses.Viewer _ ViewerOps.CreateViewer[flavor: $Text, info: [parent: container, border: FALSE, scrollable: TRUE, wx: entryLeft, wy: heightSoFar, ww: ViewerSpecs.openRightWidth-entryLeft-5, wh: entryHeight*lines], paint: FALSE]; heightSoFar _ heightSoFar + entryHeight*lines; FOR i:NAT IN [0..numDocRopes) DO rope _ Rope.Concat[rope, docRopes[i]]; ENDLOOP; TEditOps.SetTextContents[arg, rope]; }; numMiniDocRopes: NAT = 4; miniDocRopes: REF ARRAY [0..numMiniDocRopes) OF Rope.ROPE _ NEW[ARRAY [0..numMiniDocRopes) OF Rope.ROPE]; miniDocStyle: Rope.ROPE ~ " BeginStyle (mini) \"for small comment\" { \"TimesRoman\" family 8 pt size 9 pt leading 10 pt topIndent 0 pt bottomIndent 0 leftIndent 5 pt rightIndent } StyleRule EndStyle "; BuildMiniPatternDocEntry: PUBLIC PROC [info: Info] = { OPEN info.layout; lines: CARDINAL = 3; rope: Rope.ROPE; where: TextNode.RefTextNode; height: CARDINAL = numMiniDocRopes*10+3; arg: ViewerClasses.Viewer _ ViewerOps.CreateViewer[flavor: $Text, info: [parent: container, wx: entryLeft, wy: heightSoFar, ww: ViewerSpecs.openRightWidth-entryLeft-5, wh: height, border: FALSE, scrollable: FALSE], paint: FALSE]; heightSoFar _ heightSoFar + height; FOR i:NAT IN [0..numMiniDocRopes) DO rope _ Rope.Concat[rope, miniDocRopes[i]]; ENDLOOP; TEditOps.SetTextContents[arg, rope]; where _ GetDataNode[arg]; TextEdit.PutProp[node: TextNode.Root[where], name: $StyleDef, value: NodeProps.DoSpecs[$StyleDef, miniDocStyle]]; TextEdit.ChangeFormat[where, $mini]; ViewerTools.InhibitUserEdits[arg]; }; ignoringCase: Rope.ROPE = "Ignore Case"; matchingCase: Rope.ROPE = "Match Case"; ignoreCaseAtom: LIST OF REF = Register[$IgnoreCase,IgnoreCaseOp]; matchCaseAtom: LIST OF REF = Register[$MatchCase,MatchCaseOp]; CaseButton: Buttons.ButtonProc = { ChangeState[mainToolInfo.ignoreCase, ignoreCaseAtom,matchCaseAtom]; }; IgnoreCaseOp: TEditInput.CommandProc = { IgnoreCase[mainToolInfo]; }; IgnoreCase: PROC [info: Info] = { OPEN info; ignoreCase _ TRUE; Labels.Set[caseLabel,ignoringCase]; }; MatchCaseOp: TEditInput.CommandProc = { MatchCase[mainToolInfo]; }; MatchCase: PROC [info: Info] = { OPEN info; ignoreCase _ FALSE; Labels.Set[caseLabel,matchingCase]; }; BuildCaseEntry: PROC [info: Info] = { OPEN info; ignoreCase _ FALSE; [caseLabel,] _ BuildPair[layout,CaseButton,ignoreCase,ignoringCase,matchingCase,info]; }; matchingWords: Rope.ROPE = "Match Words Only"; matchingAnywhere: Rope.ROPE = "Match Anywhere"; matchingNodes: Rope.ROPE = "Match Entire Nodes Only"; matchWordsAtom: LIST OF REF = Register[$MatchWords,MatchWordsOp]; matchAnywhereAtom: LIST OF REF = Register[$MatchAnywhere,MatchAnywhereOp]; matchNodesAtom: LIST OF REF = Register[$MatchNodes,MatchNodesOp]; WhereButton: Buttons.ButtonProc = { CycleTriple[mainToolInfo.searchWhere, matchAnywhereAtom,matchWordsAtom,matchNodesAtom] }; MatchWordsOp: TEditInput.CommandProc = { MatchWords[mainToolInfo] }; MatchWords: PROC [info: Info] = { OPEN info; searchWhere _ words; Labels.Set[wordLabel,matchingWords]; }; MatchNodesOp: TEditInput.CommandProc = { MatchNodes[mainToolInfo] }; MatchNodes: PROC [info: Info] = { OPEN info; searchWhere _ nodes; Labels.Set[wordLabel,matchingNodes]; }; MatchAnywhereOp: TEditInput.CommandProc = { MatchAnywhere[mainToolInfo]; }; MatchAnywhere: PROC [info: Info] = { OPEN info; searchWhere _ anywhere; Labels.Set[wordLabel,matchingAnywhere]; }; BuildWhereEntry: PROC [info: Info] = { OPEN info; searchWhere _ anywhere; [wordLabel,] _ BuildTriple[layout, WhereButton, searchWhere, matchingAnywhere, matchingWords, matchingNodes, info]; }; targetArgAtom: LIST OF REF = Register[$SearchFor,TargetArgOp]; clearTargetArgAtom: LIST OF REF = Register[$ClearSearchFor,ClearTargetArgOp]; TargetButton: Buttons.ButtonProc = { DoButton[targetArgAtom, clearTargetArgAtom, mouseButton=red]; }; TargetArgOp: TEditInput.CommandProc = { TargetArg[mainToolInfo]; }; TargetArg: PROC [info: Info] = { SavePSel; DataFieldButton[info.targetArg,FALSE]; }; ClearTargetArgOp: TEditInput.CommandProc = { ClearTargetArg[mainToolInfo]; }; ClearTargetArg: PROC [info: Info] = { SavePSel; DataFieldButton[info.targetArg,TRUE]; }; BuildTargetEntry: PUBLIC PROC [info: Info] = { OPEN info; [,targetArg] _ BuildDataFieldPair[layout, "Target:", TargetButton, info, 2]; }; docRopes[0] _ "The following special symbols may be used in search patterns: "; docRopes[1] _ " ' Match the next character in the pattern exactly. "; docRopes[2] _ " ~ Match any character except the next one in the pattern. "; docRopes[3] _ " # Match any single character. "; docRopes[4] _ " * Match any sequence of characters. "; docRopes[5] _ " @ Match any single alphanumeric character (letter or digit). "; docRopes[6] _ " & Match any sequence of alphanumeric characters. "; docRopes[7] _ " ~@ Match any single non-alphanumeric character. "; docRopes[8] _ " ~& Match any sequence of non-alphanumeric characters. "; docRopes[9] _ " % Match any single blank character. "; docRopes[10] _ " $ Match any sequence of blank characters. "; docRopes[11] _ " ~% Match any single non-blank character. "; docRopes[12] _ " ~$ Match any sequence of non-blank characters. "; docRopes[13] _ " | Match start or end of node. "; docRopes[14] _ " { Mark start of resulting selection. "; docRopes[15] _ " } Mark end of resulting selection. "; docRopes[16] _ " < Mark start of named subpattern. "; docRopes[17] _ " > Mark end of named subpattern. "; miniDocRopes[0] _ "single character: # any; @ alpha; ~@ nonalpha; % blank; ~% nonblank; "; miniDocRopes[1] _ "min sequence: * any; & alpha; ~& nonalpha; $ blank; ~$ nonblank; "; miniDocRopes[2] _ "max sequence: ** any; && alpha; ~&~& nonalpha; $$ blank; ~$~$ nonblank; "; miniDocRopes[3] _ "miscellaneous: 'x = use \"x\"; ~x = not x; { } bounds selection; < > named subpattern "; }... ΈEditToolSearchImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Michael Plass, March 28, 1985 9:01:55 am PST Doug Wyatt, May 3, 1985 11:46:50 am PDT Russ Atkinson (RRA) January 23, 1986 0:57:33 am PST RRA: This stuff is cloned from EditToolMiscImpl.ReportPatternError. Unfortunately, the types are real close, but not exactly the same. need to save this for named subpatterns Break circularity with root node, assuming this is just one node. Saved in case of named subpatterns. -------------------------- -------------------------- -------------------------- -------------------------- -------------------------- -------------------------- -------------------------- Κπ˜codešœ™Kšœ Οmœ1™žœ˜EKšœBžœ˜HKšœFžœ˜LKšœBžœ˜HKšœJžœ˜PK˜K˜—š Ÿ œžœ"žœ žœžœ˜N˜Kšžœžœžœ˜8—šœ˜K˜——Kšœ™Kšœžœžœžœ$˜>Kšœžœžœžœ&˜AK˜˜'K˜D˜K˜——K˜BK˜šŸ œžœžœ˜+Kšœ#žœ˜*Kšœ˜K˜—K˜DK˜šŸ œžœžœ˜,Kšœ#žœ˜)Kšœ˜K˜—Kšœ™Kšœžœžœžœ&˜AKšœžœžœžœ(˜DK˜˜(K˜G˜K˜——˜(K˜K˜—K˜šŸ œžœ˜!Kšžœ˜ Kšœ%žœ˜,Kšœ˜K˜—˜)K˜K˜—˜K˜—šŸ œžœ˜"Kšžœ˜ Kšœ%žœ˜+Kšœ˜K˜—Kšœ™Kšœžœžœžœ(˜DKšœžœžœžœ*˜GK˜˜)K˜H˜K˜——˜)K˜K˜—K˜šŸ œžœ˜"Kšžœ˜ Kšœ'žœ˜.Kšœ˜K˜—˜*K˜K˜—K˜šŸ œžœ˜#Kšžœ˜ Kšœ'žœ˜-Kšœ˜K˜—Kšœžœžœžœ&˜AKšœžœžœžœ(˜DK˜˜(˜%K˜"K˜——˜(K˜—K˜šŸ œžœ˜!Kšžœ˜ Kšœ%žœ˜.K˜—˜)K˜—K˜šŸ œžœ˜"Kšžœ˜ Kšœ%žœ˜-K˜—Kšœžœžœžœ*˜GKšœžœžœžœ,˜JK˜˜*˜'K˜&K˜——˜*K˜—K˜šŸ œžœ˜#Kšžœ˜ Kšœ)žœ˜2K˜—˜+K˜—K˜šŸ œžœ˜$Kšžœ˜ Kšœ)žœ˜1K˜—Kšœžœ˜1Kšœžœ˜2K˜Kšœžœžœžœ(˜AKšœžœžœžœ*˜GK˜˜%K˜A˜K˜——˜&K˜K˜—K˜šŸœžœ˜Kšžœ˜ Kšœ žœ˜K˜+K˜K˜—˜*K˜K˜—K˜šŸ œžœ˜#Kšžœ˜ Kšœ žœ˜K˜+K˜K˜—šŸœžœ˜-Kšžœ˜ Kšœ žœ˜K˜c˜K˜——Kšœ žœ˜š œ žœžœžœžœ˜4Kšžœžœžœžœ˜)K˜—šŸœžœžœ˜2Kšžœ ˜Kšœžœ˜Kšœ žœ˜˜[Kšœžœžœ˜ K˜K˜+Kšœžœ˜&—K˜.šžœžœžœž˜ K˜&Kšžœ˜—K˜$K˜K˜—Kšœžœ˜š œžœžœžœžœ˜K˜˜"K˜C˜K˜——˜(K˜K˜—K˜šŸ œžœ˜!Kšžœ˜ Kšœ žœ˜K˜#K˜K˜—˜'K˜K˜—K˜šŸ œžœ˜ Kšžœ˜ Kšœ žœ˜K˜#K˜K˜—šŸœžœ˜%Kšžœ˜ Kšœ žœ˜K˜V˜K˜——Kšœžœ˜.Kšœžœ˜/Kšœžœ˜5K˜Kšœžœžœžœ&˜AKšœžœžœžœ,˜JKšœžœžœžœ&˜AK˜˜#˜%K˜3K˜——K˜DK˜šŸ œžœ˜!Kšžœ˜ K˜K˜$K˜K˜—K˜DK˜šŸ œžœ˜!Kšžœ˜ K˜K˜$K˜K˜—˜+K˜K˜—K˜šŸ œžœ˜$Kšžœ˜ K˜K˜'K˜K˜—šŸœžœ˜&Kšžœ˜ K˜K˜s˜K˜——Kšœ™Kšœžœžœžœ$˜>Kšœžœžœžœ.˜MK˜˜$K˜=K˜K˜—˜'K˜K˜—K˜šŸ œžœ˜ Kšœ)žœ˜0Kšœ˜—K˜˜,K˜K˜—K˜šŸœžœ˜%Kšœ)žœ˜/Kšœ˜—K˜šŸœžœžœ˜.Kšžœ˜ K˜LK˜K˜—Kšœ™K˜LK˜K˜K˜BK˜K˜IK˜K˜-K˜K˜3K˜K˜LK˜K˜@K˜K˜?K˜K˜EK˜K˜3K˜K˜:K˜K˜9K˜K˜?K˜K˜.K˜K˜5K˜K˜3K˜K˜2K˜K˜0K˜K˜K˜WK˜K˜SK˜K˜ZK˜K˜hK˜K˜K˜K˜—…—H\Ό