DIRECTORY Atom USING [DottedPairNode, GetPName, MakeAtom, PropList], Basics USING [BoundsCheckHighHalf, DoubleShiftLeft, NonNegative], List USING [Length, Sort], NodeProps USING [CopyInfoProc, MapPropsAction, ReadSpecsProc, WriteSpecsProc], RefTab USING [Create, Fetch, Ref, Store], Rope USING [Concat, Equal, Fetch, FromChar, FromRefText, IsEmpty, ROPE, Size, Substr], Rosary USING [FromProcProc, MapRuns, ROSARY], TextNode USING [NodeProps, NodePropsBody, Ref]; NodePropsImpl: CEDAR MONITOR IMPORTS Atom, Basics, List, RefTab, Rope, Rosary EXPORTS TextNode, NodeProps ~ BEGIN ROSARY: TYPE = Rosary.ROSARY; ROPE: TYPE = Rope.ROPE; Object: TYPE = REF; CopyInfoProc: TYPE = NodeProps.CopyInfoProc; MapPropsAction: TYPE = NodeProps.MapPropsAction; ReadSpecsProc: TYPE = NodeProps.ReadSpecsProc; WriteSpecsProc: TYPE = NodeProps.WriteSpecsProc; Prop, Props: TYPE = REF NodePropsBody; NodePropsBody: PUBLIC TYPE = RECORD [ name: ATOM, -- name of the property value: REF, next: Props -- points to next property ]; artworkAtom: ATOM = $Artwork; activeAtom: ATOM = $Active; commentAtom: ATOM = $Comment; formatAtom: ATOM = $Format; styleDefAtom: ATOM = $StyleDef; prefixAtom: ATOM = $Prefix; postfixAtom: ATOM = $Postfix; true: PUBLIC REF BOOL _ NEW[BOOL _ TRUE]; false: PUBLIC REF BOOL _ NEW[BOOL _ FALSE]; ReadComment: PROC [name: ATOM, specs: ROPE] RETURNS [value: REF] ~ { RETURN [IF Rope.Equal[specs, "TRUE", FALSE] THEN true ELSE false] }; WriteComment: PROC [name: ATOM, value: REF] RETURNS [specs: ROPE] ~ { comment: BOOL _ FALSE; WITH value SELECT FROM x: REF BOOL => comment _ x^; ENDCASE => NULL; specs _ IF comment THEN "TRUE" ELSE "FALSE"; }; ReadFormat: PROC [name: ATOM, specs: ROPE] RETURNS [value: REF _ NIL] ~ { IF NOT Rope.IsEmpty[specs] THEN value _ Atom.MakeAtom[specs]; }; WriteFormat: PROC [name: ATOM, value: REF] RETURNS [specs: ROPE _ NIL] ~ { WITH value SELECT FROM atom: ATOM => specs _ Atom.GetPName[NARROW[atom]]; ENDCASE => IF value = NIL THEN specs _ ""; }; ReadPfix: PROC [name: ATOM, specs: ROPE] RETURNS [value: REF] ~ { RETURN [specs] }; WritePfix: PROC [name: ATOM, value: REF] RETURNS [specs: ROPE _ NIL] ~ { WITH value SELECT FROM rope: ROPE => specs _ rope; ENDCASE; }; ReadCharSets: PROC [name: ATOM, specs: ROPE] RETURNS [value: REF] ~ { p: PROC [q: PROC [REF, INT]] ~ { i: INT _ 0; size: INT _ Rope.Size[specs]; GetByte: PROC RETURNS [b: [0..256)] ~ {b _ Rope.Fetch[specs, i]-'\000; i _ i + 1}; Combine: PROC [a: INT, b: [0..128)] RETURNS [INT] ~ { bnd: NAT ~ LAST[NAT]/128+1; RETURN [Basics.DoubleShiftLeft[[li[Basics.BoundsCheckHighHalf[a, bnd]]], 7].li + b]; }; GetInt: PROC RETURNS [int: INT _ 0] ~ { b: [0..256) _ GetByte[]; WHILE b > 127 DO int _ Combine[int, b-128]; b _ GetByte[]; ENDLOOP; int _ Combine[int, b]; }; UNTIL i = size DO repeat: INT ~ GetInt[]; charSet: [0..256) ~ GetByte[]; IF charSet=0 THEN q[NIL, repeat] ELSE q[NEW[[0..256) _ charSet], repeat]; ENDLOOP; }; RETURN [Rosary.FromProcProc[p]]; }; WriteCharSets: PROC [name: ATOM, value: REF] RETURNS [specs: ROPE _ NIL] ~ { text: REF TEXT ~ NEW[TEXT[48]]; Fold: PROC ~ {specs _ Rope.Concat[specs, Rope.FromRefText[text]]; text.length _ 0}; PutByte: PROC [b: [0..256)] ~ { IF text.length = text.maxLength THEN Fold[]; text[text.length] _ VAL[b]; text.length _ text.length + 1; }; PutInt: PROC [int: INT, more: BOOLEAN _ FALSE] ~ { IF int > 127 THEN {PutInt[int/128, TRUE]; int _ int MOD 128}; IF more THEN int _ int + 128; PutByte[int]; }; charSet: [0..256) _ 0; charSetRepeat: INT _ 0; FlushRun: PROC ~ { IF charSetRepeat > 0 THEN {PutInt[charSetRepeat]; PutByte[charSet]; charSetRepeat _ 0}; }; Action: PROC [item: REF, repeat: INT] RETURNS [quit: BOOL _ FALSE] ~ { new: [0..256) _ WITH item SELECT FROM r: REF [0..256) => r^, ENDCASE => 0; IF charSetRepeat > 0 AND new#charSet THEN FlushRun[]; charSet _ new; charSetRepeat _ charSetRepeat + repeat; }; [] _ Rosary.MapRuns[[NARROW[value]], Action]; FlushRun[]; Fold[]; IF Rope.Size[specs] = 0 THEN specs _ NIL; }; ReadCharProps: PROC [name: ATOM, specs: ROPE] RETURNS [value: REF] ~ { p: PROC [q: PROC [REF, INT]] ~ { i: INT _ 0; size: INT _ Rope.Size[specs]; GetByte: PROC RETURNS [b: [0..256)] ~ {b _ Rope.Fetch[specs, i]-'\000; i _ i + 1}; Combine: PROC [a: INT, b: [0..128)] RETURNS [INT] ~ { bnd: NAT ~ LAST[NAT]/128+1; RETURN [Basics.DoubleShiftLeft[[li[Basics.BoundsCheckHighHalf[a, bnd]]], 7].li + b]; }; GetInt: PROC RETURNS [int: INT _ 0] ~ { b: [0..256) _ GetByte[]; WHILE b > 127 DO int _ Combine[int, b-128]; b _ GetByte[]; ENDLOOP; int _ Combine[int, b]; }; GetRope: PROC RETURNS [rope: ROPE _ NIL] ~ { len: INT ~ GetInt[]; rope _ Rope.Substr[specs, i, len]; i _ i + len; [] _ Basics.NonNegative[size-i]; }; UNTIL i = size DO repeatCount: INT ~ GetInt[]; propsCount: INT ~ GetInt[]; propList: Atom.PropList _ NIL; THROUGH [0..propsCount) DO atom: ATOM ~ Atom.MakeAtom[GetRope[]]; valueSpecs: ROPE ~ GetRope[]; value: REF ~ DoSpecs[atom, valueSpecs]; propList _ CONS[NEW[Atom.DottedPairNode _ [key: atom, val: value]], propList]; ENDLOOP; q[propList, repeatCount]; ENDLOOP; }; RETURN [Rosary.FromProcProc[p]]; }; WriteCharProps: PROC [name: ATOM, value: REF] RETURNS [specs: ROPE _ NIL] ~ { curRope: ROPE _ NIL; Grab: PROC RETURNS [rope: ROPE] ~ {rope _ curRope; curRope _ NIL}; PutByte: PROC [b: [0..256)] ~ {curRope _ Rope.Concat[curRope, Rope.FromChar[VAL[b]]]}; PutRope: PROC [rope: ROPE] ~ {curRope _ Rope.Concat[curRope, rope]}; PutInt: PROC [int: INT, more: BOOLEAN _ FALSE] ~ { IF int > 127 THEN {PutInt[int/128, TRUE]; int _ int MOD 128}; IF more THEN int _ int + 128; PutByte[int]; }; rept: INT _ 0; itemSpecs: ROPE _ NIL; FlushRun: PROC ~ { IF rept > 0 THEN {PutInt[rept]; PutRope[itemSpecs]; rept _ 0} }; PutItem: PROC [newItemSpecs: ROPE, repeat: INT] ~ { IF NOT Rope.Equal[newItemSpecs, itemSpecs] THEN FlushRun[]; itemSpecs _ newItemSpecs; rept _ rept + repeat; }; Action: PROC [item: REF, repeat: INT] RETURNS [quit: BOOL _ FALSE] ~ { save: ROPE ~ Grab[]; SpecsList: PROC [propList: Atom.PropList] RETURNS [s: LIST OF REF _ NIL] ~ { FOR p: Atom.PropList _ propList, p.rest UNTIL p = NIL DO atom: ATOM ~ NARROW[p.first.key]; v: ROPE ~ GetSpecs[atom, p.first.val]; IF v # NIL THEN { a: ROPE ~ Atom.GetPName[atom]; PutInt[Rope.Size[a]]; PutRope[a]; PutInt[Rope.Size[v]]; PutRope[v]; s _ CONS[Grab[], s]; }; ENDLOOP; }; specList: LIST OF REF _ List.Sort[SpecsList[NARROW[item]]]; newItemSpecs: ROPE; PutInt[List.Length[specList]]; UNTIL specList = NIL DO t: LIST OF REF _ specList; PutRope[NARROW[t.first]]; specList _ t.rest; t.rest _ NIL; ENDLOOP; newItemSpecs _ Grab[]; curRope _ save; PutItem[newItemSpecs, repeat]; }; [] _ Rosary.MapRuns[[NARROW[value]], Action]; FlushRun[]; specs _ Grab[]; IF Rope.Size[specs] = 0 THEN specs _ NIL; }; FindName: PROC [n: TextNode.Ref, name: ATOM, remove: BOOL] RETURNS [prop: Prop] ~ { lst, prev: Props; IF n=NIL THEN RETURN [NIL]; lst _ n.props; prop _ NIL; prev _ NIL; WHILE lst#NIL DO IF lst.name = name THEN { prop _ lst; EXIT }; prev _ lst; lst _ lst.next; ENDLOOP; IF prop#NIL AND remove THEN IF prev#NIL THEN prev.next _ prop.next ELSE n.props _ prop.next }; PutProp: PUBLIC PROC [n: TextNode.Ref, name: ATOM, value: REF] ~ { prop: Prop _ FindName[n, name, FALSE]; IF value = NIL THEN { IF prop#NIL THEN prop.value _ NIL; SELECT name FROM styleDefAtom => n.hasstyledef _ FALSE; prefixAtom => n.hasprefix _ FALSE; postfixAtom => n.haspostfix _ FALSE; formatAtom => n.formatName _ NIL; commentAtom => n.comment _ FALSE; artworkAtom => n.hasartwork _ FALSE; activeAtom => n.hasactive _ FALSE; ENDCASE; RETURN }; SELECT name FROM styleDefAtom => n.hasstyledef _ TRUE; prefixAtom => { n.hasprefix _ TRUE }; postfixAtom => { n.haspostfix _ TRUE }; formatAtom => { n.formatName _ NARROW[value]; RETURN; }; commentAtom => { -- simply set the bit in the node n.comment _ NARROW[value, REF BOOL]^; RETURN; }; artworkAtom => n.hasartwork _ TRUE; activeAtom => n.hasactive _ TRUE; ENDCASE; IF prop#NIL THEN { prop.value _ value; RETURN }; n.props _ NEW[NodePropsBody _ [name: name, value: value, next: n.props]]; }; GetProp: PUBLIC PROC [n: TextNode.Ref, name: ATOM] RETURNS [value: REF] ~ { prop: Prop _ FindName[n, name, FALSE]; IF prop # NIL THEN value _ prop.value ELSE IF name = commentAtom THEN value _ IF n # NIL AND n.comment THEN true ELSE false ELSE IF name = formatAtom THEN value _ IF n.formatName = NIL THEN NIL ELSE n.formatName; }; RemProp: PUBLIC PROC [n: TextNode.Ref, name: ATOM] ~ { [] _ FindName[n, name, TRUE]; -- removes the value SELECT name FROM styleDefAtom => n.hasstyledef _ FALSE; prefixAtom => n.hasprefix _ FALSE; postfixAtom => n.haspostfix _ FALSE; formatAtom => n.formatName _ NIL; commentAtom => n.comment _ FALSE; artworkAtom => n.hasartwork _ FALSE; activeAtom => n.hasactive _ FALSE; ENDCASE; }; MapProps: PUBLIC PROC [n: TextNode.Ref, action: MapPropsAction, formatFlag, commentFlag: BOOL _ TRUE] RETURNS [quit: BOOL] ~ { IF n#NIL THEN { props: Props _ n.props; IF formatFlag AND n.formatName#NIL AND action[formatAtom, n.formatName] THEN RETURN [TRUE]; IF commentFlag AND action[commentAtom, IF n.comment THEN true ELSE false] THEN RETURN [TRUE]; WHILE props#NIL DO next: Props _ props.next; -- get it now in case action deletes current prop IF props.value # NIL AND action[props.name, props.value] THEN RETURN [TRUE]; props _ next; ENDLOOP; }; RETURN [FALSE] }; ReaderProcRef: TYPE = REF ReaderProcRec; ReaderProcRec: TYPE = RECORD [proc: ReadSpecsProc]; WriterProcRef: TYPE = REF WriterProcRec; WriterProcRec: TYPE = RECORD [proc: WriteSpecsProc]; CopierProcRef: TYPE = REF CopierProcRec; CopierProcRec: TYPE = RECORD [proc: CopyInfoProc]; readerTable: RefTab.Ref _ RefTab.Create[]; writerTable: RefTab.Ref _ RefTab.Create[]; copierTable: RefTab.Ref _ RefTab.Create[]; Register: PUBLIC PROC [name: ATOM, reader: ReadSpecsProc, writer: WriteSpecsProc, copier: CopyInfoProc] ~ { IF name=NIL THEN RETURN; [] _ RefTab.Store[readerTable, name, NEW[ReaderProcRec _ [reader]]]; [] _ RefTab.Store[writerTable, name, NEW[WriterProcRec _ [writer]]]; [] _ RefTab.Store[copierTable, name, NEW[CopierProcRec _ [copier]]] }; NullRead: PUBLIC PROC [name: ATOM, specs: ROPE] RETURNS [value: REF] ~ { RETURN [NIL] }; NullWrite: PUBLIC PROC [name: ATOM, value: REF] RETURNS [specs: ROPE] ~ { RETURN [NIL] }; NullCopy: PUBLIC PROC [name: ATOM, value: REF] RETURNS [new: REF] ~ { RETURN [NIL] }; RefCopy: PUBLIC PROC [name: ATOM, value: REF] RETURNS [new: REF] ~ { RETURN [value] }; DoSpecs: PUBLIC PROC [name: ATOM, specs: ROPE] RETURNS [value: REF] ~ { procRef: ReaderProcRef; proc: ReadSpecsProc; value _ ( IF name=NIL OR (procRef _ NARROW[RefTab.Fetch[readerTable, name].val])=NIL OR (proc _ procRef.proc)=NIL THEN specs ELSE proc[name,specs] ); }; GetSpecs: PUBLIC PROC [name: ATOM, value: REF] RETURNS [specs: ROPE] ~ { procRef: WriterProcRef; proc: WriteSpecsProc; IF name=NIL OR (procRef _ NARROW[RefTab.Fetch[writerTable, name].val])=NIL OR (proc _ procRef.proc)=NIL THEN { IF value=NIL THEN specs _ NIL ELSE { WITH value SELECT FROM rope: ROPE => specs _ rope; ENDCASE => specs _ NIL; }; } ELSE specs _ proc[name, value]; }; CopyInfo: PUBLIC PROC [name: ATOM, value: REF] RETURNS [new: REF] ~ { procRef: CopierProcRef; proc: CopyInfoProc; new _ IF name=NIL OR (procRef _ NARROW[RefTab.Fetch[copierTable, name].val])=NIL OR (proc _ procRef.proc)=NIL THEN value ELSE proc[name, value] }; attributeTable: LIST OF LIST OF ATOM _ NIL; DeclarePropertyAttribute: PUBLIC ENTRY PROC [name: ATOM, attribute: ATOM] ~ { FOR a: LIST OF LIST OF ATOM _ attributeTable, a.rest UNTIL a=NIL DO IF a.first.first = name THEN { FOR p: LIST OF ATOM _ a.first.rest, p.rest UNTIL p=NIL DO IF p.first = attribute THEN RETURN; ENDLOOP; a.first.rest _ CONS[attribute, a.first.rest]; RETURN; }; ENDLOOP; attributeTable _ CONS[LIST[name, attribute], attributeTable]; }; Is: PUBLIC ENTRY PROC [name: ATOM, attribute: ATOM] RETURNS [BOOL] ~ { FOR a: LIST OF LIST OF ATOM _ attributeTable, a.rest UNTIL a=NIL DO IF a.first.first = name THEN { FOR p: LIST OF ATOM _ a.first.rest, p.rest UNTIL p=NIL DO IF p.first = attribute THEN RETURN [TRUE]; ENDLOOP; RETURN [FALSE]; }; ENDLOOP; RETURN [FALSE]; }; GetPropertyAttributes: PUBLIC ENTRY PROC [name: ATOM] RETURNS [LIST OF ATOM] ~ { FOR a: LIST OF LIST OF ATOM _ attributeTable, a.rest UNTIL a=NIL DO IF a.first.first = name THEN RETURN [a.first.rest]; ENDLOOP; RETURN [NIL]; }; SetPropertyAttributes: PUBLIC ENTRY PROC [name: ATOM, attributes: LIST OF ATOM] ~ { FOR a: LIST OF LIST OF ATOM _ attributeTable, a.rest UNTIL a=NIL DO IF a.first.first = name THEN {a.first.rest _ attributes; RETURN}; ENDLOOP; attributeTable _ CONS[CONS[name, attributes], attributeTable]; }; Init: PROC ~ { visible: LIST OF ATOM ~ LIST[$Visible]; visAndInherit: LIST OF ATOM ~ CONS[$Inheritable, visible]; visAndClient: LIST OF ATOM ~ CONS[$ClientOnly, visible]; Register[prefixAtom, ReadPfix, WritePfix, RefCopy]; SetPropertyAttributes[prefixAtom, visAndInherit]; Register[postfixAtom, ReadPfix, WritePfix, RefCopy]; SetPropertyAttributes[postfixAtom, visAndInherit]; Register[formatAtom, ReadFormat, WriteFormat, RefCopy]; SetPropertyAttributes[formatAtom, visAndInherit]; Register[commentAtom, ReadComment, WriteComment, RefCopy]; SetPropertyAttributes[commentAtom, visAndInherit]; Register[$CharSets, ReadCharSets, WriteCharSets, RefCopy]; SetPropertyAttributes[$CharSets, visAndClient]; Register[$CharProps, ReadCharProps, WriteCharProps, RefCopy]; SetPropertyAttributes[$CharProps, visAndClient]; SetPropertyAttributes[$StyleDef, visAndInherit]; SetPropertyAttributes[$Artwork, visible]; SetPropertyAttributes[$Interpress, CONS[$ClientOnly, visible]]; SetPropertyAttributes[$Bounds, visible]; }; Init[]; END. ˜NodePropsImpl.mesa Copyright Σ 1985, 1986, 1987, 1988 by Xerox Corporation. All rights reserved. written by Paxton. January 1981 Michael Plass, November 25, 1987 2:23:18 pm PST Rick Beach, March 28, 1985 9:57:47 am PST Russ Atkinson (RRA) August 19, 1985 4:17:41 pm PDT Doug Wyatt, February 16, 1988 5:20:32 pm PST Raises a bounds fault if invalid specs are provided. Encoding is ()*, where is encoded with the variable-length integer encoding scheme described in FileOps, and is just encoded as a byte. Raises a bounds fault if invalid specs are provided. Encoding is (()*)*, where the counts and lengths are encoded with the variable-length integer encoding scheme described in FileOps. apply the action to each name & value pair for the node returns true if&when an action returns true Read, Write, Copy Props registers these procs for this variety of node they will be called by DoSpecs, GetSpecs, and CopyInfo used when reading files calls the registered reader for this property name returns specs if no reader is registered used when writing files calls the registered writer for this property name if no writer is registered, returns value if it is a rope, NIL otherwise used when copying nodes calls the registered copier for this property name if no copier is registered, returns value Property Attributes Property Attribute Documentation $Visible says whether property affects appearance $Inheritable says whether property may be inherited when a new node is inserted $ClientOnly asserts EditTool interface should not change the value Initialization Κ)˜codešœ™KšœN™NKšœ ™ Kšœ/™/K™)K™2Kšœ,™,K™—šΟk ˜ Kšœœ0˜:Kšœœ5˜AKšœœ˜Kšœ œ?˜NKšœœ˜)Kšœœ8œ˜VKšœœœ˜-Kšœ œ!˜/—K˜KšΠbl œœ˜Kšœ)˜0Kšœ˜šœ˜K˜Kšœœ œ˜Kšœœœ˜Kšœœœ˜K˜Kšœœ˜,Kšœœ˜0Kšœœ˜.šœœ˜0K˜—Kšœ œœ˜&šœœœœ˜%KšœœΟc˜#Kšœœ˜ Kšœ Ÿ˜&K˜——˜Kšœ œ ˜Kšœ œ ˜K˜Kšœ œ ˜Kšœ œ ˜Kšœœ ˜Kšœ œ ˜Kšœ œ ˜Kš œœœœœœœ˜)š œœœœœœœ˜+K˜—š Οn œœœ œœ œ˜DKš œœœœœ˜BK˜—K˜š   œœœ œœ œ˜EKšœ œœ˜šœœ˜Kšœœœ˜Kšœœ˜—Kšœœ œœ ˜,K˜—K˜š  œœœ œœ œœ˜IKšœœœ˜=K˜—K˜š   œœœ œœ  œ˜Jšœœ˜Kšœœœ˜2Kšœœ œœ ˜*—K˜K˜—š  œœœ œœ œ˜AKšœ ˜K˜—K˜š  œœœ œœ œœ˜Hšœœ˜Kšœœ˜Kšœ˜—K˜—K˜š   œœœ œœ œ˜EKšœ4™4Kšœ΅™΅š œœœœœ˜ Kšœœ˜ Kšœœ˜Kš œœœ=˜Rš  œœœœœ˜5Kšœœœœ˜KšœN˜TK˜—š œœœœ ˜'K˜šœ ˜K˜K˜Kšœ˜—K˜K˜—šœ ˜Kšœœ ˜K˜Kš œ œœ œœ˜IKšœ˜—K˜—Kšœ˜ K˜—K˜š  œœœ œœ œœ˜LKš œœœœœ˜Kš œœI˜Sš œœ˜Kšœœ˜,Kšœœ˜K˜K˜—š  œœœœœ˜2Kšœ œœ œ˜=Kšœœ˜K˜ K˜—K˜Kšœœ˜š œœ˜Kšœœ>˜WK˜—š œœœ œœœœ˜Fšœœœ˜%Kšœœ˜Kšœ˜ —Kšœœ œ ˜5K˜K˜'K˜—Kšœœ˜-K˜ K˜Kšœœ œ˜)K˜—K˜š   œœœ œœ œ˜FKšœ4™4šœ ™ KšœJ™J—Kšœo™oš œœœœœ˜ Kšœœ˜ Kšœœ˜Kš œœœ=˜Rš  œœœœœ˜5Kšœœœœ˜KšœN˜TK˜—š œœœœ ˜'K˜šœ ˜K˜K˜Kšœ˜—K˜K˜—š  œœœœœ˜,Kšœœ ˜Kšœ"˜"K˜ Kšœ ˜ K˜—šœ ˜Kšœ œ ˜Kšœ œ ˜Kšœœ˜šœ˜Kšœœ˜&Kšœ œ ˜Kšœœ˜'Kšœ œœ;˜NKšœ˜—Kšœ˜Kšœ˜—K˜—Kšœ˜ K˜K˜—š œœœ œœ œœ˜MKšœ œœ˜Kš  œœœœœ˜BKš œœ?œ˜VKš œœœ+˜Dš  œœœœœ˜2Kšœ œœ œ˜=Kšœœ˜K˜ K˜—Kšœœ˜Kšœ œœ˜Kš œœœ œ0˜Sš œœœ œ˜3Kšœœ%œ ˜;Kšœ˜Kšœ˜Kšœ˜—š œœœ œœœœ˜FKšœœ ˜š  œœœœœœœ˜Lšœ%œœ˜8Kšœœœ˜!Kšœœ˜&šœœœ˜Kšœœ˜KšœC˜CKšœœ ˜Kšœ˜—Kšœ˜—Kšœ˜—Kš œ œœœœ ˜;Kšœœ˜Kšœ˜šœ œ˜Kšœœœœ ˜Kšœœ ˜Kšœ˜Kšœ œ˜ Kšœ˜—Kšœ˜Kšœ˜Kšœ˜K˜—Kšœœ˜-K˜ Kšœ˜Kšœœ œ˜)K˜K˜—š  œœœ œœ˜SK˜Kš œœœœœ˜K˜Kšœœ œ˜šœœ˜Kšœœœ˜-K˜Kšœ˜—Kšœœœ˜šœœœ˜&Kšœ˜—K˜—K˜š  œœœœ œ˜BKšœœ˜&šœ œœ˜Kšœœœœ˜"šœ˜Kšœ œ˜&Kšœœ˜"Kšœœ˜$Kšœœ˜!Kšœœ˜!Kšœœ˜$Kšœœ˜"Kšœ˜—Kšœ˜K˜—šœ˜Kšœ œ˜%Kšœœ˜%Kšœ œ˜'˜Kšœœ˜Kšœ˜K˜—šœŸ!˜2Kšœ œœœ˜%Kšœ˜K˜—Kšœœ˜#Kšœœ˜!Kšœ˜—Kšœœœœ˜0Kšœ œ<˜IK˜—K˜š  œœœœœ œ˜KKšœœ˜&šœœ˜Kšœ˜—šœœ˜Kš œœœœ œœ˜5—šœœ˜Kš œœœœœœ˜9—K˜—K˜š œœœœ˜6KšœœŸ˜2šœ˜Kšœ œ˜&Kšœœ˜"Kšœœ˜$Kšœœ˜!Kšœœ˜!Kšœœ˜$Kšœœ˜"Kšœ˜—K˜—K˜š  œœœDœœ˜eKšœœ˜Kšœ7™7Kšœ+™+šœœœ˜Kšœ˜Kšœ œœœ"œœœ˜[Kšœ œœ œœœœœ˜]šœœ˜KšœŸ1˜KKš œœœ!œœœ˜LK˜ Kšœ˜—Jšœ˜—Kšœœ˜K˜K˜——headšœ™Kšœœœ˜(Kšœœœ˜3Kšœœœ˜(Kšœœœ˜4Kšœœœ˜(Kšœœœ˜2K˜*K˜*˜*K˜—š œœœœJ˜kKšœ.™.Kšœ7™7Kšœœœœ˜Kšœ$œ˜DKšœ$œ˜DKšœ$œ˜DK˜—K˜š œœœœ œœ œ˜HKšœœ˜ K˜—K˜š  œœœœ œœ œ˜IKšœœ˜ K˜—K˜š œœœœ œœœ˜EKšœœ˜ K˜—K˜š œœœœ œœœ˜DKšœ ˜K˜—K˜š œœœœ œœ œ˜GKšœ™Kšœ2™2Kšœ(™(K˜K˜šœ ˜ Kšœ˜ Kšœ œ'˜>Kšœ˜Kšœ˜ Kšœ˜Kšœ˜—K˜—K˜š œœœœ œœ œ˜HKšœ™Kšœ2™2KšœH™HK˜K˜Kšœ˜ Kšœ œ'˜>Kšœ˜šœ˜Kšœœœ ˜šœ˜šœœ˜Kšœœ˜Kšœ œ˜—Kšœ˜—Kšœ˜—Kšœ˜K˜—K˜š œœœœ œœœ˜EKšœ™Kšœ2™2Kšœ)™)K˜K˜Kšœœœœ œ'œœœœ˜K˜——™K˜Kš œœœœœœœ˜+š  œœœœœ œ˜Mšœœœœœœœœ˜Cšœœ˜š œœœœœœ˜9Kšœœœ˜#Kšœ˜—Kšœœ˜-Kšœ˜Kšœ˜—Kšœ˜—Kšœœœ#˜=Kšœ˜K˜—š œœœœœ œœœ˜Fšœœœœœœœœ˜Cšœœ˜š œœœœœœ˜9Kšœœœœ˜*Kšœ˜—Kšœœ˜Kšœ˜—Kšœ˜—Kšœœ˜Kšœ˜K˜—š œœœœœœœœœ˜Pšœœœœœœœœ˜CKšœœœ˜3Kšœ˜—Kšœœ˜ Kšœ˜K˜—š œœœœœœœœ˜Sšœœœœœœœœ˜CKšœœœ˜AKšœ˜—Kšœœœ$˜>Kšœ˜—K˜—™ K™4KšœO™OKšœB™B—šœ™š œœ˜Kš œ œœœœ ˜'Kš œœœœœ˜:š œœœœœ˜8K˜—šœ3˜3Kšœ1˜1K˜—šœ4˜4Kšœ2˜2K˜—˜7Kšœ1˜1K˜—˜:Kšœ2˜2K˜—˜:Kšœ/˜/K˜—˜=Kšœ0˜0K˜—Kšœ0˜0Kšœ)˜)Kšœ#œ˜?Kšœ(˜(Kšœ˜K˜—K˜—K˜Kšœ˜K˜—…—5˜RY