DIRECTORY IO USING [atom, BreakProc, EndOfStream, Error, GetChar, GetLineRope, GetRopeLiteral, GetTokenRope, IDProc, PeekChar, PutFR, RIS, rope, STREAM], LoganBerry USING [Cursor, Entry, GenerateEntries, Open, NextEntry], LoganBerryBrowser USING [AttributePatterns, ReadAttributePatterns, SyntaxError], NodeProps USING [GetProp, PutProp], Rope USING [Concat, ROPE, Size], TextLooks USING [Runs], TextNode USING [Body, Location, MaxLen, NodeItself, NodeProps, Ref, RefTextNode, Span]; QueryTextNodeImpl: CEDAR PROGRAM IMPORTS IO, LoganBerry, LoganBerryBrowser, NP: NodeProps, Rope EXPORTS TextNode = BEGIN OPEN TextNode; ROPE: TYPE ~ Rope.ROPE; MakeNodeLoc: PUBLIC PROC [n: Ref] RETURNS [Location] = { RETURN [[node: n, where: NodeItself]] }; MakeNodeSpan: PUBLIC PROC [first, last: Ref] RETURNS [Span] = { RETURN [[MakeNodeLoc[first], MakeNodeLoc[last]]] }; NarrowToTextNode: PUBLIC PROC [n: Ref] RETURNS [txt: RefTextNode] ~ {RETURN [n]}; NewTextNode: PUBLIC PROC RETURNS [txt: RefTextNode] = { txt _ NEW[Body]; txt.last _ TRUE }; Parent: PUBLIC PROC [n: Ref] RETURNS [Ref] = { RETURN [InlineParent[n]] }; InlineParent: PROC [n: Ref] RETURNS [Ref] = INLINE { DO IF n=NIL OR n.deleted THEN RETURN [NIL]; IF n.last THEN RETURN [QueryToText[n.next]]; n _ n.next; ENDLOOP; }; Root: PUBLIC PROC [n: Ref] RETURNS [Ref] = { p: Ref; DO IF (p _ InlineParent[n])=NIL THEN RETURN [IF n=NIL OR n.deleted THEN NIL ELSE n]; n _ p; ENDLOOP; }; Next: PUBLIC PROC [n: Ref] RETURNS [Ref] = { RETURN[IF n=NIL OR n.last OR n.deleted THEN NIL ELSE QueryToText[n.next]]; }; Previous: PUBLIC PROC [n: Ref, parent: Ref _ NIL] RETURNS [nx: Ref] = { nx2: Ref; IF parent=NIL THEN parent _ InlineParent[n]; IF n=NIL OR parent=NIL OR (nx _ parent.child)=n THEN RETURN [NIL]; DO IF (nx2_nx.next)=n THEN RETURN [QueryToLastText[nx]]; nx _ nx2; ENDLOOP; }; Forward: PUBLIC PROC [node: Ref] RETURNS [nx: Ref, levelDelta: INTEGER] = { [nx, levelDelta] _ InlineForward[node]; }; InlineForward: PROC [node: Ref] RETURNS [nx: Ref, levelDelta: INTEGER] = INLINE { child: Ref; IF node=NIL THEN RETURN [NIL, 0]; IF (child _ node.child) # NIL THEN RETURN [QueryToText[child, node], 1]; -- descend in the tree levelDelta _ 0; DO -- move to next node, sibling or up* then sibling IF NOT node.last THEN RETURN [QueryToText[node.next], levelDelta]; -- the sibling IF (node _ node.next) = NIL THEN RETURN [NIL, levelDelta]; -- the parent levelDelta _ levelDelta-1; ENDLOOP; }; Backward: PUBLIC PROC [node: Ref, parent: Ref _ NIL] RETURNS [back, backparent: Ref, levelDelta: INTEGER] = { child, child2: Ref; IF parent = NIL THEN parent _ InlineParent[node]; IF parent = NIL OR node = NIL THEN RETURN [NIL, NIL, 0]; IF (child _ parent.child) = node THEN RETURN [parent, Parent[parent], -1]; DO IF child.last THEN ERROR; -- incorrect value supplied for parent IF (child2 _ child.next)=node THEN EXIT; child _ child2; ENDLOOP; levelDelta _ 0; DO IF (child2 _ LastChild[child]) = NIL THEN RETURN [QueryToLastText[child], parent, levelDelta]; levelDelta _ levelDelta+1; parent _ child; child _ child2; ENDLOOP; }; StepForward: PUBLIC PROC [node: Ref] RETURNS [Ref] = { RETURN[Forward[node].nx] }; StepBackward: PUBLIC PROC [node: Ref, parent: Ref _ NIL] RETURNS [Ref] = { RETURN[Backward[node, parent].back] }; Level: PUBLIC PROC [node: Ref] RETURNS [level: INTEGER] = { level _ 0; UNTIL (node _ InlineParent[node])=NIL DO level _ level+1 ENDLOOP; }; ForwardClipped: PUBLIC PROC [ node: Ref, maxLevel: INTEGER, nodeLevel: INTEGER _ 0] RETURNS [nx: Ref, nxLevel: INTEGER] = { child: Ref; IF node=NIL THEN RETURN [NIL, 0]; IF nodeLevel <= 0 THEN nodeLevel _ Level[node]; IF nodeLevel < maxLevel AND (child _ node.child) # NIL THEN RETURN [QueryToText[child, node], nodeLevel+1]; -- return the child DO -- move to next node, sibling or up* then sibling IF NOT node.last THEN RETURN [QueryToText[node.next], nodeLevel]; -- return the sibling IF (node _ node.next) = NIL THEN RETURN [NIL, 0]; -- go to the parent nodeLevel _ nodeLevel-1; ENDLOOP; }; BackwardClipped: PUBLIC PROC [ node: Ref, maxLevel: INTEGER, parent: Ref _ NIL, nodeLevel: INTEGER _ 0] RETURNS [back, backparent: Ref, backLevel: INTEGER] = { child, child2: Ref; IF parent = NIL THEN parent _ InlineParent[node]; IF parent = NIL OR node = NIL THEN RETURN [NIL, NIL, 0]; IF nodeLevel <= 0 THEN nodeLevel _ Level[node]; IF (child _ parent.child) = node THEN RETURN [parent, InlineParent[parent], nodeLevel-1]; DO -- search for sibling just before node IF child.last THEN ERROR; -- incorrect value supplied for parent IF (child2 _ child.next)=node THEN EXIT; child _ child2; ENDLOOP; DO -- go deeper in tree until reach maxLevel IF nodeLevel >= maxLevel OR (child2 _ LastChild[child]) = NIL THEN RETURN [QueryToLastText[child], parent, nodeLevel]; nodeLevel _ nodeLevel+1; parent _ child; child _ child2; ENDLOOP; }; LocRelative: PUBLIC PROC [location: Location, count: INT _ 0, break: NAT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [Location] = { n: Ref _ location.node; size, lastSize, where: INT _ 0; init: Ref _ n; lastTxt: RefTextNode; IF count=0 AND InlineParent[n]=NIL THEN RETURN [[FirstChild[n], 0]]; -- avoid returning root node where _ MAX[location.where, 0]; -- where we are in the current node WHILE n # NIL DO IF n # NIL AND (NOT skipCommentNodes OR NOT n.comment) THEN { lastSize _ size _ Rope.Size[n.rope]; IF (count _ count-(size-where)) <= 0 THEN RETURN [[n, MAX[0, count+size]]]; lastTxt _ n; count _ count-break; }; [n, ] _ InlineForward[n]; where _ 0; ENDLOOP; IF lastTxt # NIL THEN RETURN [[lastTxt, lastSize]]; -- end of last text node RETURN [[init, 0]]; }; LocWithin: PUBLIC PROC [n: Ref, count: INT, break: NAT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [Location] = { RETURN[LocRelative[[n, 0], count, break, skipCommentNodes]] }; BadArgs: PUBLIC ERROR = CODE; LocOffset: PUBLIC PROC [loc1, loc2: Location, break: NAT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [count: INT _ 0] = { node: Ref _ loc2.node; n: Ref _ loc1.node; count _ IF loc2.where # NodeItself THEN loc2.where ELSE 0; count _ count - MAX[loc1.where, 0]; DO -- add in counts for text nodes before location SELECT n FROM node => RETURN; NIL => ERROR BadArgs; ENDCASE; IF n # NIL AND (NOT skipCommentNodes OR NOT n.comment) THEN count _ count+Rope.Size[n.rope]+break; [n, ] _ InlineForward[n]; ENDLOOP; }; LocNumber: PUBLIC PROC [at: Location, break: NAT _ 1, skipCommentNodes: BOOL _ FALSE] RETURNS [count: INT] = { RETURN[LocOffset[[Root[at.node], 0], at, break, skipCommentNodes]] }; FirstSibling: PUBLIC PROC [n: Ref] RETURNS [Ref] = { RETURN[FirstChild[Parent[n]]]; }; LastSibling: PUBLIC PROC [n: Ref] RETURNS [Ref] = { IF n=NIL THEN RETURN [NIL]; UNTIL n.last DO n _ n.next ENDLOOP; RETURN[QueryToLastText[n]]; }; FirstChild: PUBLIC PROC [n: Ref] RETURNS [Ref] = { RETURN[IF n=NIL THEN NIL ELSE QueryToText[n.child, n]]; }; LastChild: PUBLIC PROC [n: Ref] RETURNS [Ref] = { RETURN[LastSibling[FirstChild[n]]]; }; LastWithin: PUBLIC PROC [n: Ref] RETURNS [Ref] = { nxt: Ref; IF n=NIL THEN RETURN [NIL]; IF (nxt _ n.child)=NIL THEN RETURN [n]; n _ nxt; DO -- keep going to child of last sibling IF n.last THEN { IF (nxt _ n.child)=NIL THEN RETURN [QueryToLastText[n]]; n _ nxt } ELSE n _ n.next; ENDLOOP; }; LastLocWithin: PUBLIC PROC [n: Ref] RETURNS [Location] = { last: Ref _ LastWithin[n]; where: INT _ IF last # NIL THEN Rope.Size[last.rope] ELSE NodeItself; RETURN [[last, where]]; }; NthChild: PUBLIC PROC [n: Ref, location: INT _ 0] RETURNS [child: Ref] = { IF n=NIL OR (child _ n.child)=NIL THEN RETURN; DO IF location=0 THEN RETURN [QueryToText[child]]; child _ QueryToText[child]; IF child.last THEN RETURN [NIL]; child _ child.next; location _ location-1; ENDLOOP; }; NthSibling: PUBLIC PROC [n: Ref, cnt: INT _ 0] RETURNS [Ref] = { IF n=NIL THEN RETURN [NIL]; DO IF cnt=0 THEN RETURN [QueryToText[n]]; n _ QueryToText[n]; IF n.last THEN RETURN [NIL]; n _ n.next; cnt _ cnt-1; ENDLOOP; }; CountChildren: PUBLIC PROC [n: Ref] RETURNS [count: INT _ 0] = { child: Ref; IF (child _ FirstChild[n])=NIL THEN RETURN; DO count _ count+1; child _ QueryToText[child]; IF child.last THEN RETURN; child _ child.next; ENDLOOP; }; CountFollowing: PUBLIC PROC [n: Ref] RETURNS [count: INT _ 0] = { IF n=NIL THEN RETURN; UNTIL n.last DO n _ n.next; count _ count+1; n _ QueryToText[n]; ENDLOOP; }; CountToParent: PUBLIC PROC [n: Ref] RETURNS [count: INT _ 0, parent: Ref] = { IF n=NIL THEN RETURN; UNTIL n.last DO n _ n.next; count _ count+1; n _ QueryToText[n]; ENDLOOP; parent _ n.next; parent _ QueryToText[parent]; }; CountToChild: PUBLIC PROC [parent, child: Ref] RETURNS [count: INT _ 0] = { n: Ref; IF parent=NIL OR child=NIL THEN RETURN; n _ parent.child; DO SELECT n FROM child => RETURN [count]; NIL => RETURN [MaxLen]; ENDCASE; n _ Next[n]; count _ count+1; ENDLOOP; }; NodeRope: PUBLIC PROC [n: RefTextNode] RETURNS [ROPE] = { RETURN[IF n=NIL THEN NIL ELSE n.rope]; }; NodeRuns: PUBLIC PROC [n: RefTextNode] RETURNS [TextLooks.Runs] = { RETURN[IF n=NIL THEN NIL ELSE n.runs]; }; Props: PUBLIC PROC [n: Ref] RETURNS [NodeProps] = { RETURN[IF n=NIL THEN NIL ELSE n.props]; }; NodeFormat: PUBLIC PROC [n: Ref] RETURNS [ATOM] = { RETURN[IF n=NIL THEN NIL ELSE n.formatName]; }; IsLastSibling: PUBLIC PROC [n: Ref] RETURNS [BOOL] = { RETURN[IF n=NIL THEN FALSE ELSE n.last]; }; EndPos: PUBLIC PROC [n: Ref] RETURNS [INT] = { IF n=NIL THEN RETURN [0]; RETURN [MAX[Rope.Size[n.rope], 1]-1]; }; -- remember last query and its cursor to improve performance lastq: Ref _ NIL; cursor: REF LoganBerry.Cursor _ NIL; QueryToText: PROC [q, p: Ref _ NIL] RETURNS [t: Ref] ~ { entry: LoganBerry.Entry; IF q=NIL OR q.formatName # $query THEN RETURN[t: q]; IF q # lastq THEN { -- get new cursor lastq _ q; cursor _ NARROW[NP.GetProp[q, $LBCursor]]; IF cursor = NIL THEN { cursor _ InitiateQuery[q.rope]; IF cursor = NIL THEN { -- bad query specification q.formatName _ $block; q.rope _ Rope.Concat["Bad Query: ", q.rope]; RETURN[q]; }; NP.PutProp[q, $LBCursor, cursor]; }; }; entry _ LoganBerry.NextEntry[cursor: cursor^]; IF entry = NIL THEN { -- query completed q.formatName _ $block; q.rope _ NIL; RETURN[q]; }; t _ NEW[Body _ q^]; -- t inherits q's properties t.child _ NIL; t.formatName _ $block; t.last _ FALSE; t.rope _ EntryToRope[entry]; IF p=NIL THEN { p _ q; WHILE NOT p.last DO p _ p.next; ENDLOOP; p _ p.next; -- p is now q's parent IF p.child#q THEN { p _ p.child; -- get to first sibling WHILE p.next # q DO p _ p.next; ENDLOOP; }; }; t.next _ q; IF p.child=q THEN p.child _ t; IF p.next=q THEN p.next _ t; }; QueryToLastText: PROC [q: Ref] RETURNS [t: Ref] ~ { IF q=NIL OR q.formatName # $query THEN RETURN[t: q]; t _ QueryToText[q]; WHILE t.rope # NIL DO t _ QueryToText[t.next, t]; ENDLOOP; }; InitiateQuery: PROC [rope: Rope.ROPE] RETURNS [c: REF LoganBerry.Cursor] ~ { ParseSubrange: PROC [r: ROPE] RETURNS [start, end: ROPE] ~ { ENABLE IO.EndOfStream, IO.Error => GOTO Bad; ToDash: IO.BreakProc = { RETURN[SELECT char FROM '- => sepr, ENDCASE => other]; }; s: IO.STREAM; s _ IO.RIS[r]; start _ IF IO.PeekChar[s] = '" THEN IO.GetRopeLiteral[s] ELSE IO.GetTokenRope[s, ToDash].token; IF IO.GetChar[s] # '- THEN RETURN[r, NIL]; end _ IF IO.PeekChar[s] = '" THEN IO.GetRopeLiteral[s] ELSE IO.GetLineRope[s]; EXITS Bad => RETURN[r, NIL]; }; dbname, start, end: Rope.ROPE; ap: LoganBerryBrowser.AttributePatterns; s: IO.STREAM _ IO.RIS[rope]; dbname _ IO.GetTokenRope[s, IO.IDProc ! IO.EndOfStream => GOTO End].token; ap _ LoganBerryBrowser.ReadAttributePatterns[s ! LoganBerryBrowser.SyntaxError => GOTO End]; [start, end] _ ParseSubrange[ap.first.attr.value]; c _ NEW[LoganBerry.Cursor _ LoganBerry.GenerateEntries[db: LoganBerry.Open[dbName: dbname], key: ap.first.attr.type, start: start, end: end]]; EXITS End => RETURN[NIL]; }; EntryToRope: PROC [e: LoganBerry.Entry] RETURNS [r: Rope.ROPE] ~ { r _ NIL; FOR l: LoganBerry.Entry _ e, l.rest WHILE l # NIL DO r _ IO.PutFR["%g%g: %g\n", IO.rope[r], IO.atom[l.first.type], IO.rope[l.first.value]]; ENDLOOP; }; END. &QueryTextNodeImpl.mesa Copyright Σ 1985, 1986 by Xerox Corporation. All rights reserved. written by Bill Paxton, March 1981 last edit by Bill Paxton, August 11, 1982 9:51 am Doug Wyatt, March 3, 1985 3:01:39 pm PST Michael Plass, March 27, 1985 3:50:32 pm PST Rick Beach, March 27, 1985 10:13:12 am PST Doug Terry, April 9, 1987 6:16:18 pm PDT This is a modified version of TextNodeImpl.mesa that retrieves nodes from a LoganBerry database as they are requested. Nodes with format="Query" are dynamically replaced with the results obtained from running the query specified by the node's contents. The query need not always be run in its entirety; in many cases the query node can be replaced by two nodes: the first being the first database entry returned by the query and the second being a new query (specifcally a database cursor) to generate the remaining entries. Note: All of the procedures in this module assume that any nodes passed as inputs are regular text nodes (format#$query) and ensure that any nodes returned as results are regular text nodes. For backwards compatability. applies Parent repeatedly until reaches root returns next node in standard tree walk order returns preceeding node in standard tree walk order returns next node in standard tree walk order returns preceding node in standard tree walk order Level[Root[x]] == 0; Level[FirstChild[n]]=Level[n]+1 like Forward, but limits how deep will go in tree if pass nodeLevel=0, correct value will be computed nxLevel = Level[nx] <= MAX[maxLevel, Level[node]] like Backward, but limits how deep will go in tree backLevel = Level[back] <= MAX[maxLevel, Level[node]] returns character offset of location2 relative to location1 returns character offset of location relative to root note: NthChild[n, 0]==FirstChild[n]; NthChild[n, k+1]==Next[NthChild[n, k]] note: NthSibling[n, 0]==n; NthSibling[n, k+1]==Next[NthSibling[n, k]] note: CountToChild[parent, FirstChild[parent]]==0 New routines for operating on $query nodes On input: q should be a node with format $query, p (if not NIL) should be the q's parent (if q is a first child) or q's preceeding sibling, Note that p can be determined given q so its input is only for performance improvement. Upon completion: t is a text node containing the first database entry obtained by running the query specified in q (t=q if q is not a $query node), t.next is a $query node representing the rest of the query that remains to be run. Get next entry returned by query Create new node t for returned entry Link t before q in tree On input: q should be a node with format $query. Upon completion: the query specified in q has been completely processed and t is the last node in the list of retrieved database entries (t=q if q is not a $query node). r should be of the form "start-end". [char: CHAR] RETURNS [IO.CharClass] Κ›˜codešœ™KšœB™BKšœ"™"Kšœ1™1Kšœ(™(Kšœ,™,K™*K™(—K™šœŽ™ŽK™K™Ώ—K™šΟk ˜ Kš œœkœœœ˜Kšœ œ3˜CKšœœ9˜PKšœ œ˜#Kšœœœ ˜!Kšœ œ ˜Kšœ œI˜W—K˜KšΠblœœ˜ Kšœ7˜>Kšœ ˜šœœœ ˜K˜šœœœ˜K˜—šΟn œœœ œ ˜4Kšœœ"˜,K˜—šŸ œœœœ˜;Kšœœ-˜7K˜—š Ÿœœœ œœ˜QK™K˜—šŸ œœœœ˜7Kšœœœ˜!K˜—K˜Kš Ÿœœœ œ œ˜JšŸ œœ œ œ˜5šœœœœ œœœ˜+Kšœœœ˜,K˜ Kšœ˜—K˜—K˜šŸœœœ œ ˜-Kšœ,™,K˜šœœœœœœœœ œœœ˜TK˜Kšœ˜—K˜—K˜šŸœœœ œ ˜,Kšœœœœœ œœœ˜JK˜—K˜š Ÿœœœœœ˜GK˜ Kšœœœ˜,Kšœœœœœœœœ˜BKš œœœœ"œ˜KK˜—K˜š Ÿœœœ œœ˜KK˜'K˜—K˜š Ÿ œœ œœœ˜QKšœ-™-K˜ Kš œœœœœ˜!Kš œœœœ Οc˜_K˜šœ œ ˜4Kš œœ œœ' ˜QKš œœœœœ  ˜HK˜Kšœ˜—K˜—K˜šŸœœœœ˜4Kšœ%œ˜8Kšœ3™3K˜Kšœ œœ˜1Kšœ œœœœœœœ˜8Kšœœœ˜Jš œœ œœ &˜CKšœœœ˜(K˜Kšœ˜—K˜š œœœœœ.˜aK˜Kšœ˜Kšœ˜—K˜—K˜šŸ œœœ œ˜2Kšœœ˜Kšœ-™-K˜—š Ÿ œœœœœ˜FKšœœ ˜*Kšœ2™2K˜—š Ÿœœœ œ œ˜;Kšœ4™4Kšœ ˜ Kšœœœœ˜AK˜—K˜šŸœœœ˜Kšœœ œ˜5Kšœœ˜'Kšœ1™1Kšœ4™4Kšœ1™1K˜ Kš œœœœœ˜!Kšœœ˜/šœœœ˜;Kšœ* ˜C—šœ œ ˜4Kš œœ œœ& ˜WKš œœœœœ ˜EK˜Kšœ˜—K˜—K˜šŸœœœ˜Kšœœœ œ˜HKšœ$œ˜7Kšœ2™2Kšœ5™5K˜Kšœ œœ˜1Kšœ œœœœœœœ˜8Kšœœ˜/Kšœœœ-˜Yšœ &˜)Kšœ œœ &˜@Kšœœœ˜(K˜Kšœ˜—šœ )˜,Kšœœœ˜BKšœ-˜3K˜K˜K˜Kšœ˜—K˜—K˜šŸ œœœœ˜>Kš œœœœœ˜FK˜Kšœœ˜K˜K˜Kšœ œœ˜'Kšœ ˜9Kšœœ #˜Cšœœ˜šœœœœœœ œ˜=Kšœ$˜$Kšœ#œœœ˜KK˜ K˜K˜—K˜K˜ Kšœ˜—Kš œ œœœ ˜LKšœ ˜K˜—K˜šŸ œœœœ œœœœ ˜nKšœœ8˜BK˜—Kšœ œœœ˜šŸ œœœœœœœ œ ˜zKšœ;™;K˜K˜Kšœœœ œ˜:Kšœœ˜#šœ /˜2šœ˜ Kšœœ˜Kšœœ ˜Kšœ˜ —Kš œœœœœœ ˜;Kšœ&˜&K˜Kšœ˜—K˜—K˜šŸ œœœœœœœ œ˜jKšœœ?˜IKšœ5™5K˜—šŸ œœœ œ ˜4Kšœ˜K˜—K˜šŸ œœœ œ ˜3Kš œœœœœ˜Kšœœ œ˜#Kšœ˜K˜—K˜šŸ œœœ œ ˜2Kš œœœœœœ˜7K˜—K˜šŸ œœœ œ ˜1Kšœ˜#K˜—K˜šŸ œœœ œ ˜2K˜ Kš œœœœœ˜Kšœœœœ˜'K˜šœ &˜)šœœ˜Kšœœœœ˜8K˜K˜—Kšœ ˜Kšœ˜—K˜—K˜šŸ œœœ œ˜:K˜Kš œœœœœœ ˜EKšœ˜K˜—K˜š Ÿœœœœœ˜JKšœK™KKš œœœœœœ˜.šœœ œœ˜2Kšœ˜Kšœ œœœ˜ K˜Kšœ˜Kšœ˜—K˜—K˜š Ÿ œœœœœ ˜@KšœE™EKš œœœœœ˜šœœœœ˜)Kšœ˜Kšœœœœ˜K˜ Kšœ ˜ Kšœ˜—K˜—K˜š Ÿ œœœ œ œ ˜@K˜ Kšœœœœ˜+šœ˜K˜Kšœ œœ˜K˜Kšœ˜—K˜—K˜š Ÿœœœ œ œ ˜AKšœœœœ˜šœ˜K˜ K˜K˜Kšœ˜—K˜—K˜š Ÿ œœœ œ œ˜MKšœœœœ˜šœ˜K˜ K˜K˜Kšœ˜—K˜K˜K˜—K˜š Ÿ œœœœ œ ˜KKšœ1™1K˜Kš œœœœœœ˜'K˜šœœ˜Kšœ œ ˜Kšœœ ˜Kšœ˜K˜ K˜Kšœ˜—K˜—K˜š Ÿœœœœœ˜9Kš œœœœœœ ˜&K˜—K˜šŸœœœœ˜CKš œœœœœœ ˜&K˜—K˜šŸœœœ œ˜3Kš œœœœœœ ˜'K˜—K˜š Ÿ œœœ œœ˜3Kš œœœœœœ˜,K˜—K˜š Ÿ œœœ œœ˜6Kš œœœœœœ ˜(K˜—K˜š Ÿœœœ œœ˜.Kšœœœœ˜Kšœœ˜%K˜—K˜—™*K™Kš <˜