DIRECTORY BasicTime USING [Now], IO USING [PutR], Rope USING [Fetch, Index, ROPE, Size], RopeEdit USING [AlphaNumericChar, BlankChar, Concat, Substr], RopeReader USING [Create, Get, GetIndex, Backwards, ReadOffEnd, Ref, SetPosition], TextEdit USING [DeleteText, FetchChar, FetchLooks, InsertChar, InsertRope, Size], TextLooks USING [Look, Looks, noLooks], TextNode USING [Backward, FirstChild, LastLocWithin, Location, Node, NodeItself, Parent, StepForward, StepBackward], TEditDocument USING [BeforeAfter, Selection, SelectionPoint], TEditInput USING [CloseEvent, currentEvent], TEditInputOps USING [CallWithLocks, DoPendingDelete, EditFailed], TEditOps USING [RememberCurrentPosition], TEditRefresh USING [ScrollToEndOfSel], TEditSelection USING [CaretVisible, Copy, Deselect, InsertionPoint, LockSel, MakePointSelection, MakeSelection, pSel, SetSelLooks, UnlockSel], TreeFind USING [Finder, CreateFromRope, Try, TryBackwards], ViewerClasses USING [Viewer], ViewerTools USING [SetSelection]; TEditMiscOpsImpl: CEDAR PROGRAM IMPORTS BasicTime, IO, Rope, RopeEdit, RopeReader, TextEdit, TextNode, TEditInput, TEditInputOps, TEditOps, TEditRefresh, TEditSelection, TreeFind, ViewerTools EXPORTS TEditInputOps = BEGIN OPEN TEditDocument, TEditSelection, TEditOps, TEditInputOps; InsertChar: PUBLIC PROC [char: CHAR] = { DoInsertChar: PROC [root: TextNode.Node, tSel: Selection] = { pos: TextNode.Location; looks: TextLooks.Looks _ tSel.looks; IF tSel.pendingDelete THEN { DoPendingDelete[]; TEditSelection.Copy[source: pSel, dest: tSel] }; pos _ InsertionPoint[pSel]; -- need to get insertion point after pending delete Deselect[primary]; [] _ TextEdit.InsertChar[root: root, dest: pos.node, char: char, destLoc: pos.where, inherit: FALSE, looks: looks, event: TEditInput.currentEvent]; pos.where _ pos.where+1; MakePointSelection[tSel, pos]; IF CaretVisible[] THEN TEditRefresh.ScrollToEndOfSel[tSel.viewer, TRUE] }; CallWithLocks[DoInsertChar]; }; InsertRope: PUBLIC PROC [rope: Rope.ROPE] = { DoInsertRope: PROC [root: TextNode.Node, tSel: Selection] = { pos: TextNode.Location; len: INT _ Rope.Size[rope]; looks: TextLooks.Looks; IF tSel.pendingDelete THEN { DoPendingDelete[]; TEditSelection.Copy[source: pSel, dest: tSel] }; pos _ InsertionPoint[pSel]; -- need to get insertion point after pending delete looks _ tSel.looks; Deselect[primary]; [] _ TextEdit.InsertRope[root: root, dest: pos.node, rope: rope, destLoc: pos.where, inherit: FALSE, looks: looks, event: TEditInput.currentEvent]; pos.where _ pos.where+len; MakePointSelection[tSel, pos]; IF CaretVisible[] THEN TEditRefresh.ScrollToEndOfSel[tSel.viewer, TRUE] }; CallWithLocks[DoInsertRope]; }; InsertLineBreak: PUBLIC PROC = { DoInsertLineBreak: PROC [root: TextNode.Node, tSel: Selection] = { pos: TextNode.Location; node: TextNode.Node; start, end, lim: INT _ 0; rope: Rope.ROPE; IF tSel.pendingDelete THEN { DoPendingDelete[]; TEditSelection.Copy[source: pSel, dest: tSel] }; pos _ InsertionPoint[pSel]; -- need to get insertion point after pending delete IF (node _ pos.node) = NIL THEN { EditFailed[]; RETURN }; rope _ node.rope; start _ lim _ MAX[0, MIN[pos.where, Rope.Size[rope]]]; WHILE start > 0 AND Rope.Fetch[rope,start-1] # 15C DO start _ start-1; ENDLOOP; end _ start; WHILE end < lim AND RopeEdit.BlankChar[Rope.Fetch[rope,end]] DO end _ end+1; ENDLOOP; InsertRope[RopeEdit.Concat["\n",RopeEdit.Substr[rope,start,end-start]]]; }; CallWithLocks[DoInsertLineBreak]; }; DeleteNextChar: PUBLIC PROC [count: INT _ 1] = { DoDeleteNextChar: PROC [root: TextNode.Node, tSel: Selection] = { flush: TextNode.Location _ InsertionPoint[tSel]; node: TextNode.Node _ flush.node; IF node = NIL THEN GOTO Bad; IF flush.where=TextNode.NodeItself THEN GOTO Bad; IF (count _ MIN[count,TextEdit.Size[node]-flush.where]) <= 0 THEN GOTO Bad; Deselect[primary]; TextEdit.DeleteText[root, node, flush.where, count, TEditInput.currentEvent]; MakePointSelection[tSel,flush]; TEditRefresh.ScrollToEndOfSel[tSel.viewer, TRUE]; EXITS Bad => EditFailed[] }; IF count > 0 THEN CallWithLocks[DoDeleteNextChar]; }; GoToNextChar: PUBLIC PROC [count: INT _ 1] = { DoGoToNextChar: PROC [root: TextNode.Node, tSel: Selection] = { loc: TextNode.Location _ InsertionPoint[tSel]; node: TextNode.Node _ loc.node; IF node = NIL OR loc.where=TextNode.NodeItself OR (count _ MIN[count,TextEdit.Size[node]-loc.where]) <= 0 THEN { -- try next node GoToNextNode; RETURN }; MakePointSelection[tSel,[node,loc.where+count]]; TEditRefresh.ScrollToEndOfSel[tSel.viewer, TRUE]; }; IF count > 0 THEN CallWithLocks[DoGoToNextChar, read]; }; GoToPreviousChar: PUBLIC PROC [count: INT _ 1] = { DoGoToPreviousChar: PROC [root: TextNode.Node, tSel: Selection] = { loc: TextNode.Location _ InsertionPoint[tSel]; node: TextNode.Node _ loc.node; IF node = NIL OR loc.where=TextNode.NodeItself OR loc.where < count THEN { GoToPreviousNode; RETURN }; -- try previous node MakePointSelection[tSel,[node,loc.where-count]]; TEditRefresh.ScrollToEndOfSel[tSel.viewer, TRUE]; }; IF count > 0 THEN CallWithLocks[DoGoToPreviousChar, read]; }; FindNextWord: PUBLIC PROC [node: TextNode.Node, start: INT] RETURNS [nChars: CARDINAL] = { offset: INT _ start; size: INT _ TextEdit.Size[node]; Alpha: PROC [index: INT] RETURNS [BOOL] ~ { set: NAT; char: CHAR; [set, char] _ TextEdit.FetchChar[node, index]; RETURN [set=0 AND RopeEdit.AlphaNumericChar[char]]; }; nChars _ 1; WHILE offset EditFailed[]; }; IF count > 0 THEN CallWithLocks[DoDeleteNextWord]; }; GoToNextWord: PUBLIC PROC [count: INT _ 1] = { DoGoToNextWord: PROC [root: TextNode.Node, tSel: Selection] = { pos: TextNode.Location _ InsertionPoint[tSel]; node: TextNode.Node _ pos.node; size, next: INT _ 0; IF node=NIL OR (next _ pos.where)=TextNode.NodeItself THEN { -- try next node GoToNextNode; RETURN }; size _ TextEdit.Size[node]; FOR garbage:INT IN [0..count) DO IF next >= size THEN { GoToNextNode; RETURN }; next _ next+FindNextWord[node,next]; ENDLOOP; MakePointSelection[tSel,[node,next]]; TEditRefresh.ScrollToEndOfSel[tSel.viewer, TRUE]; }; IF count > 0 THEN CallWithLocks[DoGoToNextWord, read]; }; GoToNextNode: PUBLIC PROC [count: INT _ 1] = { DoGoToNextNode: PROC [root: TextNode.Node, tSel: Selection] = { pos: TextNode.Location _ InsertionPoint[tSel]; node: TextNode.Node _ pos.node; FOR garbage:INT IN [0..count) DO IF (node _ TextNode.StepForward[node])=NIL THEN { EditFailed[]; RETURN }; ENDLOOP; MakePointSelection[tSel,[node,0]]; TEditRefresh.ScrollToEndOfSel[tSel.viewer, TRUE]; }; IF count > 0 THEN CallWithLocks[DoGoToNextNode, read]; }; GoToPreviousNode: PUBLIC PROC [count: INT _ 1] = { DoGoToPreviousNode: PROC [root: TextNode.Node, tSel: Selection] = { pos: TextNode.Location _ InsertionPoint[tSel]; node: TextNode.Node _ pos.node; FOR garbage:INT IN [0..count) DO IF (node _ TextNode.StepBackward[node])=NIL OR TextNode.Parent[node]=NIL THEN GOTO Bad; ENDLOOP; IF node=NIL THEN GOTO Bad; MakePointSelection[tSel,[node,TextEdit.Size[node]]]; TEditRefresh.ScrollToEndOfSel[tSel.viewer, TRUE]; EXITS Bad => EditFailed[]; }; IF count > 0 THEN CallWithLocks[DoGoToPreviousNode, read]; }; AppendDecimal: PROC [text: REF TEXT, number: NAT] = { pos: NAT _ text.length; skipZeros: BOOL _ TRUE; div: NAT _ 1000; DO c: CHAR _ '0 + (number / div); number _ number MOD div; IF c # '0 THEN skipZeros _ FALSE; IF NOT skipZeros THEN {text[pos] _ c; pos _ pos + 1}; IF div = 10 THEN EXIT; div _ div / 10; ENDLOOP; text[pos] _ '0 + (number / div); text.length _ pos + 1; }; InsertTime: PUBLIC PROC = { DoInsertTime: PROC [root: TextNode.Node, tSel: Selection] = { resLen: INT _ 0; caret: TextNode.Location; dest: TextNode.Node; looks: TextLooks.Looks _ pSel.looks; date: Rope.ROPE _ IO.PutR[[time[BasicTime.Now[]]]]; dateLen: INT _ Rope.Index[date, 0, ", "]; IF dateLen < date.Size[] THEN dateLen _ Rope.Index[date, dateLen+2, " "]; IF pSel.pendingDelete THEN DoPendingDelete[]; caret _ InsertionPoint[pSel]; IF (dest _ caret.node)=NIL THEN GOTO Bad; Deselect[primary]; [----, resLen] _ TextEdit.InsertRope[ root: root, dest: dest, rope: date, destLoc: caret.where, inherit: FALSE, looks: looks, event: TEditInput.currentEvent]; tSel.end.pos.node _ tSel.start.pos.node _ caret.node; tSel.end.pos.where _ caret.where+resLen-1; tSel.start.pos.where _ caret.where+dateLen; tSel.insertion _ after; tSel.granularity _ char; tSel.pendingDelete _ FALSE; MakeSelection[selection: primary, new: tSel]; EXITS Bad => EditFailed[]; }; CallWithLocks[DoInsertTime]; }; MakeLook: PROC [c: CHAR] RETURNS [looks: TextLooks.Looks] ~ INLINE { looks _ ALL[FALSE]; looks[c] _ TRUE; }; InsertBrackets: PUBLIC PROC [left, right: CHAR] = { DoInsertBrackets: PROC [root: TextNode.Node, tSel: Selection] = { leftEnd, rightEnd: TextNode.Location; leftNode, rightNode: TextNode.Node; l, r: INT _ 0; bracketLooks: TextLooks.Looks ~ IF left = 1C THEN MakeLook['t] ELSE tSel.looks; leftEnd _ tSel.start.pos; rightEnd _ tSel.end.pos; IF (leftNode _ leftEnd.node)=NIL THEN GOTO Bad; IF (rightNode _ rightEnd.node)=NIL THEN GOTO Bad; IF (r _ rightEnd.where) = TextNode.NodeItself THEN r _ TextEdit.Size[rightNode] ELSE IF tSel.granularity # point THEN r _ r+1; IF (l _ leftEnd.where) = TextNode.NodeItself THEN l _ 0; Deselect[primary]; [----, ----] _ TextEdit.InsertChar[ root: root, dest: rightNode, char: right, destLoc: r, inherit: FALSE, looks: bracketLooks, event: TEditInput.currentEvent]; [----, ----] _ TextEdit.InsertChar[ root: root, dest: leftNode, char: left, destLoc: l, inherit: FALSE, looks: bracketLooks, event: TEditInput.currentEvent]; tSel.start.pos.where _ l+1; IF tSel.granularity = point THEN tSel.end.pos.where _ l+1 ELSE { tSel.granularity _ char; IF leftNode=rightNode THEN tSel.end.pos.where _ r}; tSel.pendingDelete _ FALSE; MakeSelection[selection: primary, new: tSel]; EXITS Bad => EditFailed[]; }; CallWithLocks[DoInsertBrackets]; }; End: ERROR = CODE; -- private; for use in SelectMatchingBrackets SelectMatchingBrackets: PUBLIC PROC [left, right: CHAR] = { IF NOT DoSelectMatchingBrackets[left, right] THEN EditFailed["No match."]; }; DoSelectMatchingBrackets: PUBLIC PROC [left, right: CHAR] RETURNS [found: BOOL] = { rdr: RopeReader.Ref _ RopeReader.Create[]; ref, parent: TextNode.Node; node: TextNode.Node; GetPreviousNode: PROC RETURNS [n: TextNode.Node] = { DO -- search for previous text node [back: ref, backparent: parent] _ TextNode.Backward[ref, parent]; IF ref=NIL THEN ERROR End; IF ref # NIL THEN RETURN [ref]; ENDLOOP }; GetLeftChar: PROC RETURNS [CHAR] = { c: CHAR; c _ RopeReader.Backwards[rdr ! RopeReader.ReadOffEnd => { node _ GetPreviousNode[]; RopeReader.SetPosition[rdr, node.rope, Rope.Size[node.rope]]; RETRY } ]; RETURN [c]; }; GetNextNode: PROC RETURNS [n: TextNode.Node] = { DO -- search for next text node IF (ref _ TextNode.StepForward[ref])=NIL THEN ERROR End; IF ref # NIL THEN RETURN [ref]; ENDLOOP; }; GetRightChar: PROC RETURNS [CHAR] = { c: CHAR; c _ RopeReader.Get[rdr ! RopeReader.ReadOffEnd => { node _ GetNextNode[]; RopeReader.SetPosition[rdr, node.rope]; RETRY } ]; RETURN [c] }; DoSelect: PROC [root: TextNode.Node, tSel: Selection] = { leftEnd, rightEnd: TextNode.Location; nest: CARDINAL _ 0; loc: INT _ 0; leftEnd _ tSel.start.pos; rightEnd _ tSel.end.pos; ref _ leftEnd.node; IF (node _ ref)=NIL THEN { IF (node _ GetPreviousNode[])=NIL THEN GOTO NoMatch; loc _ Rope.Size[node.rope] } ELSE IF (loc _ leftEnd.where) = TextNode.NodeItself THEN loc _ 0; RopeReader.SetPosition[rdr, node.rope, loc]; DO -- left end SELECT GetLeftChar[ ! End => GOTO NoMatch] FROM left => IF nest=0 THEN EXIT ELSE nest _ nest-1; right => nest _ nest+1; ENDCASE; ENDLOOP; leftEnd.node _ node; leftEnd.where _ RopeReader.GetIndex[rdr]; ref _ rightEnd.node; IF (node _ ref)=NIL THEN { IF (node _ GetNextNode[])=NIL THEN GOTO NoMatch; loc _ 0 } ELSE IF (loc _ rightEnd.where) = TextNode.NodeItself THEN loc _ Rope.Size[node.rope] ELSE IF pSel.granularity # point THEN loc _ loc+1; RopeReader.SetPosition[rdr, node.rope, loc]; DO -- right end SELECT GetRightChar[ ! End => GOTO NoMatch] FROM right => IF nest=0 THEN EXIT ELSE nest _ nest-1; left => nest _ nest+1; ENDCASE; ENDLOOP; rightEnd.node _ node; rightEnd.where _ RopeReader.GetIndex[rdr]-1; tSel.start.pos _ leftEnd; tSel.end.pos _ rightEnd; tSel.granularity _ char; SetSelLooks[tSel]; MakeSelection[selection: primary, new: tSel]; found _ TRUE; EXITS NoMatch => found _ FALSE; }; CallWithLocks[DoSelect, read]; }; CallWithPrimarySelectionLocked: PROC [who: Rope.ROPE, action: PROC [Selection]] ~ { TEditSelection.LockSel[primary, who]; action[TEditSelection.pSel ! UNWIND => TEditSelection.UnlockSel[primary]]; TEditSelection.UnlockSel[primary]; }; NextViewer: PUBLIC PROC [forward: BOOL] = { IF NOT DoNextViewer[forward] THEN EditFailed["No next viewer."]; }; DoNextViewer: PUBLIC PROC [forward: BOOL] RETURNS [found: BOOL _ FALSE] = { Viewer: TYPE ~ ViewerClasses.Viewer; DoNextViewerAction: PROC [pSel: Selection] ~ { thisViewer: Viewer ~ pSel.viewer; nextViewer: Viewer _ NIL; Enumerate: PROC [enum: PROC [Viewer]] = { FOR v: Viewer _ thisViewer.parent.child, v.sibling UNTIL v=NIL DO enum[v]; ENDLOOP; }; ConvergeForward: PROC [v: Viewer] = { IF v.class.flavor=$Text AND (v.wy > thisViewer.wy OR (v.wy = thisViewer.wy AND v.wx > thisViewer.wx)) THEN { IF nextViewer=NIL OR v.wy < nextViewer.wy THEN {nextViewer _ v; RETURN}; IF v.wy > nextViewer.wy THEN RETURN; IF (v.wy > thisViewer.wy OR v.wx > thisViewer.wx) AND v.wx < nextViewer.wx THEN nextViewer _ v; }; }; ConvergeBackward: PROC [v: Viewer] = { IF v.class.flavor=$Text AND (v.wy < thisViewer.wy OR (v.wy = thisViewer.wy AND v.wx < thisViewer.wx)) THEN { IF nextViewer=NIL OR v.wy > nextViewer.wy THEN {nextViewer _ v; RETURN}; IF v.wy < nextViewer.wy THEN RETURN; IF (v.wy < thisViewer.wy OR v.wx < thisViewer.wx) AND v.wx > nextViewer.wx THEN nextViewer _ v; }; }; IF thisViewer=NIL OR thisViewer.parent=NIL THEN RETURN; Enumerate[IF forward THEN ConvergeForward ELSE ConvergeBackward]; IF nextViewer # NIL THEN { ViewerTools.SetSelection[nextViewer, NIL]; found _ TRUE }; }; CallWithPrimarySelectionLocked["DoNextViewer", DoNextViewerAction]; }; FindPlaceholders: PUBLIC PROC [next: BOOL] = { found, wenttoend: BOOL; [found, wenttoend] _ DoFindPlaceholders[next, TRUE]; IF ~found AND ~wenttoend THEN NextViewer[next]; }; DoFindPlaceholders: PUBLIC PROC [next, gotoend: BOOL, startBoundaryNode, endBoundaryNode: TextNode.Node _ NIL, startBoundaryOffset: INT _ 0, endBoundaryOffset: INT _ LAST[INT]] RETURNS [found, wenttoend: BOOL] = { DoFind: PROC [root: TextNode.Node, tSel: Selection] = { finder: TreeFind.Finder _ TreeFind.CreateFromRope[IF next THEN "" ELSE ""]; from: TextNode.Location; where: TextNode.Node; at, atEnd, start: INT _ 0; Failed: PROC = { IF gotoend THEN { loc: TextNode.Location = IF next THEN TextNode.LastLocWithin[root] ELSE [TextNode.FirstChild[root],0]; IF loc # from OR tSel.granularity # point THEN { wenttoend _ TRUE; RememberCurrentPosition[tSel.viewer]; MakePointSelection[tSel, loc]; TEditRefresh.ScrollToEndOfSel[tSel.viewer, FALSE] }}; }; from _ InsertionPoint[tSel]; start _ from.where; IF next AND tSel.insertion=before AND tSel.granularity#point THEN start _ start+1 ELSE IF NOT next AND tSel.insertion=after THEN start _ MAX[start-1,0]; [found,where,at,atEnd,,] _ IF next THEN TreeFind.Try[finder: finder, first: from.node, start: start, last: endBoundaryNode, lastLen: endBoundaryOffset] ELSE TreeFind.TryBackwards[finder: finder, first: from.node, len: start, last: startBoundaryNode, lastStart: startBoundaryOffset]; wenttoend _ FALSE; IF NOT found THEN { Failed[]; RETURN }; MakePointSelection[tSel, [where,IF next THEN at+1 ELSE MAX[at,0]]]; IF NOT DoSelectMatchingBrackets[','] THEN { Failed[]; RETURN }; TEditSelection.Copy[source: pSel, dest: tSel]; tSel.insertion _ before; tSel.pendingDelete _ TRUE; RememberCurrentPosition[tSel.viewer]; tSel.looks _ TextEdit.FetchLooks[ -- take looks from first char after the  tSel.start.pos.node, tSel.start.pos.where+1]; MakeSelection[tSel, primary]; TEditInput.CloseEvent[]; TEditRefresh.ScrollToEndOfSel[tSel.viewer, FALSE]; }; CallWithLocks[DoFind, read]; }; END. TEditMiscOpsImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Paxton on June 6, 1983 4:09 pm Maxwell, January 6, 1983 11:33 am Russ Atkinson, September 28, 1983 2:57 pm Michael Plass, April 7, 1986 9:09:08 am PST Russ Atkinson (RRA) January 23, 1986 0:10:22 am PST Doug Wyatt, September 2, 1986 4:49:33 pm PDT copy leading blanks from previous line RRA wrote this -- insert left char at start of selection, right char after selection -- extend selection until includes matching left and right brackets Κ˜codešœ™Kšœ Οmœ7™BKšœ™Kšœ!™!K™)K™+K™3K™,—K™šΟk ˜ Kšœ žœ˜Kšžœžœ˜Kšœžœžœ˜&Kšœ žœ/˜=Kšœ žœB˜RKšœ žœC˜QKšœ žœ˜'Kšœ žœf˜tKšœžœ*˜=Kšœ žœ˜,Kšœžœ.˜AKšœ žœ˜)Kšœ žœ˜&Kšœžœz˜ŽKšœ žœ-˜;Kšœžœ ˜Kšœ žœ˜!—K˜KšΠblœžœž˜Kšžœ žœŠ˜ŸKšžœ˜Kšœžœžœ8˜DK˜šΟn œžœžœžœ˜(š  œžœ+˜=K˜Kšœ$˜$šžœžœ˜Kšœ˜K˜0—KšœΟc3˜OK˜˜$K˜K˜Kšœ žœ˜K˜ —K˜Kšœ˜Kšžœžœ,žœ˜J—Kšœ˜Kšœ˜K˜—š  œžœžœ žœ˜-š  œžœ+˜=K˜Kšœžœ˜K˜šžœžœ˜Kšœ˜K˜0—Kšœ‘3˜OKšœ˜K˜˜$K˜K˜Kšœ žœ˜K˜ —K˜Kšœ˜Kšžœžœ,žœ˜J—Kšœ˜Kšœ˜K˜—š œžœžœ˜ Kšœ&™&š œžœ+˜BK˜K˜Kšœžœ˜Kšœ žœ˜šžœžœ˜Kšœ˜K˜0—Kšœ‘3˜OKšžœžœžœžœ˜9K˜Kšœžœžœ˜6Kšžœ žœ žœžœ˜OK˜ šžœ žœ*ž˜?Kšœ ˜ Kšžœ˜—K˜HK˜—Kšœ!˜!šœ˜K˜——š œžœžœ žœ ˜0š œžœ+˜AKšœ0˜0Kšœ!˜!Kšžœžœžœžœ˜Kšžœ!žœžœ˜1Kšžœ žœ.žœžœ˜KK˜K˜MKšœ˜Kšœ+žœ˜1Kšžœ˜—Kšžœ žœ!˜2Kšœ˜K˜—š  œžœžœ žœ ˜.š œžœ+˜?Kšœ.˜.Kšœ˜šžœžœž˜Kšœž˜ Kšœ žœ,žœ‘˜OKšœžœ˜—Kšœ0˜0Kšœ+žœ˜1Kšœ˜—Kšžœ žœ%˜6Kšœ˜K˜—š œžœžœ žœ ˜2š œžœ+˜CKšœ.˜.Kšœ˜šžœžœž˜Kšœžœ˜3Kšžœžœ‘˜7—Kšœ0˜0Kšœ+žœ˜1Kšœ˜—Kšžœ žœ)˜:Kšœ˜K˜—š  œžœžœžœ˜;Kšžœ žœ˜Kšœžœ ˜Kšœžœ˜ š  œžœ žœžœžœ˜+Kšœžœžœ˜Kšœ.˜.Kšžœžœ"˜3Kšœ˜—K˜ šžœ žœžœž˜*K˜K˜Kšžœ˜—šžœ žœž˜&K˜K˜Kšžœ˜—Kšœ‘#˜8K˜K˜—š œžœžœ žœ ˜0š œžœ+˜AKšœ.˜.Kšœ˜Kšœžœ˜Kšžœ+žœžœ˜;Kšžœžœžœžœ˜K˜ Kš žœ žœžœ žœ&žœ˜NK˜K˜KšœH˜HKšœ˜Kšœ+žœ˜1Kšžœ˜Kšœ˜—Kšžœ žœ!˜2Kšœ˜K˜—š  œžœžœ žœ ˜.š œžœ+˜?Kšœ.˜.Kšœ˜Kšœ žœ˜šžœžœž˜Kšœ'žœ‘˜>Kšœžœ˜—K˜šžœ žœžœ ž˜ Kšžœžœžœ˜.K˜$Kšžœ˜—Kšœ%˜%Kšœ+žœ˜1Kšœ˜—Kšžœ žœ%˜6Kšœ˜K˜—š  œžœžœ žœ ˜.š œžœ+˜?Kšœ.˜.K˜šžœ žœžœ ž˜ Kšžœ%žœžœžœ˜IKšžœ˜—Kšœ"˜"Kšœ+žœ˜1Kšœ˜—Kšžœ žœ%˜6Kšœ˜K˜—š œžœžœ žœ ˜2š œžœ+˜CKšœ.˜.K˜šžœ žœžœ ž˜ šžœ&žœž˜.Kšœžœžœžœ˜(—Kšžœ˜—Kšžœžœžœžœ˜Kšœ4˜4Kšœ+žœ˜1Kšžœ˜Kšœ˜—Kšžœ žœ)˜:Kšœ˜K˜—š   œžœžœžœ žœ˜5Kšœ™Kšœžœ˜Kšœ žœžœ˜Kšœžœ˜šž˜Kšœžœ˜Kšœžœ˜Kšžœžœ žœ˜!Kšžœžœ žœ ˜5Kšžœ žœžœ˜Kšœ˜Kšžœ˜—Kšœ ˜ Kšœ˜K˜K˜—š  œžœžœ˜š  œžœ+˜=Kšœžœ˜K˜K˜K˜$Kšœ žœžœ˜3Kšœ žœ˜)Kšžœžœ,˜IKšžœžœ˜-K˜Kšžœžœžœžœ˜)K˜šœ‘œ ˜%Kšœ#˜#Kšœžœ0˜T—K˜5K˜*K˜+K˜K˜Kšœžœ˜K˜-Kšžœ˜Kšœ˜—Kšœ˜Kšœ˜K˜—š  œžœžœžœžœ˜DKšœžœžœ˜Kšœ žœ˜Kšœ˜K˜—š œžœžœžœ˜3KšœE™Eš œžœ+˜AK˜%K˜#Kšœžœ˜Kšœ žœ žœžœ ˜OKšœ˜Kšœ˜Kšžœžœžœžœ˜/Kšžœžœžœžœ˜2Kšžœ,žœ˜OKšžœžœžœ ˜.Kšžœ+žœ˜8K˜šœ‘œ‘œ˜#K˜ K˜K˜ K˜ Kšœ žœ˜$K˜ —šœ‘œ‘œ˜#K˜ K˜K˜ K˜ Kšœ žœ˜$K˜ —K˜Kšžœžœ˜9šžœ˜K˜Kšžœžœ˜3—Kšœžœ˜K˜-Kšžœ˜Kšœ˜—Kšœ ˜ šœ˜K˜——K˜šœžœžœ‘-˜@K˜—š œžœžœžœ˜;Kšžœžœ'žœ˜JKšœ˜K˜—š  œžœžœžœžœ žœ˜SKšœC™CK˜*K˜K˜š œžœžœ˜4šžœ‘ ˜#KšœA˜AKšžœžœžœžœ˜Kšžœžœžœžœ˜Kšž˜—Kšœ˜—š  œžœžœžœ˜$Kšœžœ˜šœ˜šœ˜K˜K˜=Kšžœ˜—K˜—Kšžœ˜ Kšœ˜—š  œžœžœ˜0šžœ‘˜Kšžœ#žœžœžœ˜8Kšžœžœžœžœ˜Kšžœ˜—Kšœ˜—š  œžœžœžœ˜%Kšœžœ˜šœ˜šœ˜K˜K˜'Kšžœ˜—Kšœ˜—Kšžœ˜ Kšœ˜—š œžœ+˜9K˜%Kšœžœ˜Kšœžœ˜ Kšœ˜Kšœ˜K˜šžœžœžœ˜Kšžœžœžœžœ ˜4K˜—Kšžœžœ-žœ ˜AK˜,šžœ‘ ˜šžœžœ ž˜/Kš œžœžœžœžœ˜/K˜Kšžœ˜—Kšžœ˜—K˜K˜)K˜šžœžœžœ˜Kšžœžœžœžœ ˜0K˜ —šžœžœ.žœ˜TKšžœžœžœ ˜2—K˜,šžœ‘ ˜šžœžœ ž˜0Kš œ žœžœžœžœ˜0K˜Kšžœ˜—Kšžœ˜—K˜K˜,K˜K˜K˜K˜K˜K˜-Kšœžœ˜ Kšžœžœ˜Kšœ˜—Kšœ˜Kšœ˜K˜—K˜š œžœ žœ žœ˜SKšœ%˜%Kšœžœ'˜JKšœ"˜"K˜K˜—š  œžœžœ žœ˜+Kšžœžœžœ˜@Kšœ˜K˜—š  œžœžœ žœžœ žœžœ˜KKšœžœ˜$š œžœ˜.K˜!Kšœžœ˜š  œžœžœ˜)šžœ0žœžœž˜AK˜Kšžœ˜—Kšœ˜—š œžœ˜%Kšžœžœ˜1šžœžœžœ˜:Kš žœ žœžœžœžœ˜HKšžœžœžœ˜$šžœžœžœž˜OK˜—Kšœ˜—Kšœ˜—š œžœ˜&Kšžœžœ˜1šžœžœžœ˜:Kš žœ žœžœžœžœ˜HKšžœžœžœ˜$šžœžœžœž˜OK˜—Kšœ˜—Kšœ˜—Kš žœ žœžœžœžœžœ˜7Kšœ žœ žœžœ˜AKš žœžœžœ(žœ žœ˜UK˜—KšœC˜CKšœ˜—K˜š œžœžœžœ˜.Kšœžœ˜Kšœ.žœ˜4Kšžœžœ žœ˜/šœ˜K˜——š œžœžœžœ˜5Kšœ4žœ˜8Kšœžœ˜Kšœžœžœžœ˜#Kšžœžœ˜$š œžœ+˜7Kšœ2žœžœ˜MK˜K˜Kšœžœ˜š œžœ˜šžœ žœ˜šœžœžœ˜BKšžœ˜#—šžœ žœžœ˜0Kšœ žœ˜Kšœ%˜%K˜Kšœ+žœ˜5——Kšœ˜—Kšœ˜K˜Kšžœžœžœžœ˜QKš žœžœžœžœžœ žœ ˜Fšœžœž˜'šœ<˜Xl