DIRECTORY CD, CDApplications, CDCallSpecific, CDDirectory, CDEvents, CDExtras USING [MergeInObjects], CDImports, CDImportsExtras, CDBasics, CDIO, CDOps, CDOrient, CDProperties, CDValue, Rope, TerminalIO, CDInterestRects, TokenIO; CDImportsImpl: CEDAR PROGRAM IMPORTS CD, CDApplications, CDDirectory, CDEvents, CDExtras, CDBasics, CDIO, CDOps, CDOrient, CDProperties, CDValue, Rope, TerminalIO, TokenIO, CDInterestRects EXPORTS CDImports, CDImportsExtras SHARES CDDirectory = BEGIN BoolOrInteractive: TYPE = CDImports.BoolOrInteractive; ReferencePtr: TYPE = CDImports.ReferencePtr; ReferenceRep: TYPE = CDImports.ReferenceRep; ImportList: TYPE = CDImports.ImportList; Import: TYPE = CDImports.Import; importListKey: ATOM = $ImportList; -- for CDValue pForReference: REF CD.ObjectProcs = CD.RegisterObjectType[$Import]; EnumerateItsObjects: PROC [me: CD.ObPtr, p: CDDirectory.EnumerateObjectsProc, x: REF] = BEGIN END; ReplaceDirectChild: CDDirectory.ReplaceDChildsProc = BEGIN END; InternalCreateReference: PROC [design: CD.Design, size: CD.DesignPosition_[1, 1], --ignored if allowConflicts ir: CD.DesignRect _ [0, 0, -1, -1], objectName, importeeName: Rope.ROPE, autoImport: BoolOrInteractive_false, --creates an import if not already done autoCreateOb: BoolOrInteractive_false, --creates if not found but design available allowConflicts: BoolOrInteractive_false, --allow size conflicts of the object include: BOOL_TRUE] RETURNS [CD.ObPtr] = BEGIN ob: CD.ObPtr; rp: ReferencePtr; import: REF Import = GetImport[design, importeeName, autoImport]; probablySize: CD.DesignPosition _ CDBasics.MaxPoint[size, [1, 1]]; iR: CD.DesignRect; IF CDBasics.NonEmpty[ir] THEN iR _ ir ELSE iR _ CDBasics.RectAt[[0, 0], probablySize]; IF import=NIL THEN RETURN [NIL]; FOR list: LIST OF CD.ObPtr _ import.referenceList, list.rest WHILE list#NIL DO ob _ list.first; rp _ NARROW[ob.specificRef, ReferencePtr]; IF Rope.Equal[rp.objectName, objectName] AND Rope.Equal[rp.designName, importeeName] THEN { IF ob.size=size OR allowConflicts=true THEN RETURN [ob] ELSE IF allowConflicts=interactive AND TerminalIO.UserSaysYes[ text: "size conflict\n", label: "ignore?" ] THEN RETURN [ob] ELSE RETURN [NIL] }; ENDLOOP; IF import.importee#NIL THEN { found: BOOL; referedOb: CD.ObPtr; [found, referedOb] _ CDDirectory.Fetch[import.importee, objectName]; IF ~found THEN { IF autoCreateOb=false OR (autoCreateOb=interactive AND ~TerminalIO.UserSaysYes[ text: "object not found\n", label: "ignore?" ]) THEN RETURN [NIL]; } ELSE { IF allowConflicts=true THEN { probablySize _ referedOb.size; iR _ CD.InterestRect[referedOb]; }; } }; ob _ NEW[CD.ObjectDefinition_[ size: probablySize, p: pForReference, layer: CD.combined, specificRef: NEW[ReferenceRep _ [ objectName: objectName, ir: iR, designName: importeeName ]] ]]; import.referenceList _ CONS[ob, import.referenceList]; IF include THEN [] _ CDDirectory.Include[design: design, object: ob, alternateName: Rope.Cat[importeeName, ".", objectName]]; IF import.importee#NIL THEN [] _ BindReference[design, ob, import.importee, allowConflicts]; RETURN [ob] END; GetReference: PUBLIC PROC [design: CD.Design, objectName, importeeName: Rope.ROPE] RETURNS [ob: CD.ObPtr] = BEGIN ob _ InternalCreateReference[design: design, objectName: objectName, importeeName: importeeName, autoCreateOb: false, autoImport: false, allowConflicts: true, include: TRUE]; END; ReferenceName: PROC [me: CD.ObPtr] RETURNS [Rope.ROPE] = BEGIN n: Rope.ROPE = CDDirectory.Name[me]; IF Rope.IsEmpty[n] THEN { rp: ReferencePtr = NARROW[me.specificRef]; RETURN [Rope.Cat[rp.designName, ".", rp.objectName]] }; RETURN [n] END; ShortName: PROC [me: CD.ObPtr, rp: ReferencePtr] RETURNS [Rope.ROPE] = INLINE BEGIN n: Rope.ROPE = CDDirectory.Name[me]; IF Rope.IsEmpty[n] THEN { RETURN [rp.objectName] }; RETURN [n] END; DescribeReference: PROC[me: CD.ObPtr] RETURNS [Rope.ROPE] = BEGIN RETURN [Rope.Concat["reference to ", ReferenceName[me]]] END; DrawReference: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN ENABLE UNWIND => IF pr.nesting.table[pr.nestDepth-1]=aptr THEN pr.nestDepth _ pr.nestDepth-1; rp: ReferencePtr = NARROW[aptr.ob.specificRef]; IF rp.boundApp#NIL THEN { pr.nesting.table[pr.nestDepth] _ aptr; pr.nestDepth _ pr.nestDepth+1; pr.drawChild[rp.boundApp, pos, orient, pr]; pr.nestDepth _ pr.nestDepth-1; } ELSE { r: CD.DesignRect = IntRect[aptr.ob, pos, orient]; pr.drawRect[r, CD.highLightShade, pr]; pr.drawComment[r, ShortName[aptr.ob, rp], pr]; } END; IntRect: PROC [ob: CD.ObPtr, pos: CD.DesignPosition, orient: CD.Orientation] RETURNS [CD.DesignRect] = INLINE BEGIN RETURN [CDOrient.MapRect[ itemInCell: CD.InterestRect[ob], cellSize: ob.size, cellInstOrient: orient, cellInstPos: pos ]] END; QuickDrawReference: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN ENABLE UNWIND => IF pr.nesting.table[pr.nestDepth-1]=aptr THEN pr.nestDepth _ pr.nestDepth-1; rp: ReferencePtr = NARROW[aptr.ob.specificRef]; IF rp.boundApp#NIL THEN { pr.nesting.table[pr.nestDepth] _ aptr; pr.nestDepth _ pr.nestDepth+1; rp.boundApp.ob.p.quickDrawMe[rp.boundApp, pos, orient, pr]; pr.nestDepth _ pr.nestDepth-1; } ELSE { r: CD.DesignRect = IntRect[aptr.ob, pos, orient]; pr.drawRect[r, CD.highLightShade, pr]; pr.drawComment[r, ShortName[aptr.ob, rp], pr]; } END; DrawReferenceSelection: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN rp: ReferencePtr = NARROW[aptr.ob.specificRef]; IF rp.boundApp#NIL THEN rp.boundApp.ob.p.showMeSelected[rp.boundApp, pos, orient, pr] ELSE pr.outLineProc[IntRect[aptr.ob, pos, orient], pr] END; InterestRect: PROC [ob: CD.ObPtr] RETURNS [CD.DesignRect] = BEGIN RETURN [NARROW[ob.specificRef, ReferencePtr].ir] END; WriteRect: PROC[r: CD.Rect] = BEGIN TokenIO.WriteInt[r.x1]; TokenIO.WriteInt[r.y1]; TokenIO.WriteInt[r.x2]; TokenIO.WriteInt[r.y2]; END; ReadRect: PROC [] RETURNS [CD.Rect] = BEGIN r: CD.Rect; r.x1 _ TokenIO.ReadInt[]; r.y1 _ TokenIO.ReadInt[]; r.x2 _ TokenIO.ReadInt[]; r.y2 _ TokenIO.ReadInt[]; RETURN [r] END; WriteReference: CD.InternalWriteProc -- PROC [me: ObPtr] -- = BEGIN rp: ReferencePtr = NARROW[me.specificRef]; TokenIO.WriteInt[me.size.x]; TokenIO.WriteInt[me.size.y]; WriteRect[rp.ir]; TokenIO.WriteRope[rp.objectName]; TokenIO.WriteRope[rp.designName]; END; ReadReference: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- = BEGIN x: INT = TokenIO.ReadInt[]; y: INT = TokenIO.ReadInt[]; ir: CD.DesignRect; objectName: Rope.ROPE; importeeName: Rope.ROPE; ob: CD.ObPtr; IF CDIO.VersionKey[] >= 8 THEN ir _ ReadRect[] ELSE ir _ CDBasics.RectAt[[0, 0], [x, y]]; objectName _ TokenIO.ReadRope[]; importeeName _ TokenIO.ReadRope[]; ob _ InternalCreateReference[ design: CDIO.DesignInReadOperation[], ir: ir, size: [x, y], objectName: objectName, autoCreateOb: true, importeeName: importeeName, autoImport: true, allowConflicts: interactive, include: FALSE ]; RETURN [ob] END; GetImportList: PUBLIC PROC [design: CD.Design] RETURNS [imp: REF ImportList] = BEGIN WITH CDValue.Fetch[boundTo: design, key: importListKey, propagation: design] SELECT FROM imp: REF ImportList => RETURN[imp]; ENDCASE => { imp _ NEW[ImportList _ [list: NIL]]; CDValue.Store[boundTo: design, key: importListKey, value: imp]; }; END; GetImport: PUBLIC PROC [design: CD.Design, importeeName: Rope.ROPE_NIL, createIfNotFound: BoolOrInteractive _ true] RETURNS [REF Import] = BEGIN ToBool: PROC[b: BoolOrInteractive, r: Rope.ROPE, default: BOOL_TRUE, r2: Rope.ROPE_NIL] RETURNS [BOOL] = BEGIN SELECT b FROM true => RETURN [TRUE]; false => RETURN [FALSE]; ENDCASE => { TerminalIO.WriteRope[r]; TerminalIO.WriteRope[r2]; RETURN [TerminalIO.UserSaysYes[r,, default]] } END; mdata: REF Import _ NIL; impl: REF ImportList = GetImportList[design]; IF Rope.IsEmpty[importeeName] THEN ERROR CD.Error[ec: other, explanation: "design has empty name, but shouldn't" ]; IF impl#NIL THEN FOR l: LIST OF REF Import _ impl.list, l.rest WHILE l#NIL DO IF l.first#NIL AND Rope.Equal[l.first.importeeName, importeeName] THEN RETURN [l.first] ENDLOOP; IF ToBool[createIfNotFound, "create an import", TRUE, importeeName] THEN { mdata _ NEW[Import _ [importeeName: importeeName, importee: NIL, referenceList: NIL]]; impl.list _ CONS[mdata, impl.list]; --atomic-- }; RETURN [mdata] END; BindImportee: PROC [importer, importee: CD.Design, allowSizeConflicts, allowOverload: BoolOrInteractive _ true] = BEGIN ENABLE TerminalIO.UserAbort => GOTO UserAborted; done1: BOOL_TRUE; mdata: REF Import = GetImport[importer, importee.name]; IF mdata=NIL THEN ERROR; IF mdata.importee#NIL THEN { IF allowOverload=false THEN RETURN ELSE IF allowOverload=interactive THEN IF NOT TerminalIO.UserSaysYes[ text: "design already loaded; shall overload?\n", label: "overload?"] THEN { TerminalIO.WriteRope["dont overload; not done\n"]; RETURN } }; mdata.importee _ importee; FOR list: LIST OF CD.ObPtr _ mdata.referenceList, list.rest WHILE list#NIL DO done1 _ done1 AND BindReference[importer, list.first, mdata.importee, allowSizeConflicts].ok ENDLOOP; IF NOT done1 THEN TerminalIO.WriteRope["some import not bound\n"]; CDOps.DelayedRedraw[importer]; EXITS UserAborted => {TerminalIO.WriteRope["aborted, design not bound\n"]}; END; BindReference: PROC [design: CD.Design, reference: CD.ObPtr, importee: CD.Design, allowSizeConflicts: BoolOrInteractive _ true] RETURNS [ok: BOOL_FALSE] = BEGIN ENABLE TerminalIO.UserAbort => GOTO UserAborted; rp: ReferencePtr = NARROW[reference.specificRef, ReferencePtr]; found: BOOL; oldRect, newRect: CD.DesignRect; referedOb: CD.ObPtr; [found, referedOb] _ CDDirectory.Fetch[importee, rp.objectName]; IF NOT found THEN { TerminalIO.WriteRope["entry "]; TerminalIO.WriteRope[rp.objectName]; TerminalIO.WriteRope[" in "]; TerminalIO.WriteRope[importee.name]; TerminalIO.WriteRope[" not found\n"]; RETURN }; oldRect _ InterestRect[reference]; newRect _ CD.InterestRect[referedOb]; IF newRect#oldRect THEN { TerminalIO.WriteRope["object "]; TerminalIO.WriteRope[rp.objectName]; TerminalIO.WriteRope[" has different size; "]; IF CDBasics.SizeOfRect[oldRect]=CDBasics.SizeOfRect[newRect] THEN TerminalIO.WriteRope[" has different outer size; "] ELSE TerminalIO.WriteRope[" has different interest size; "]; IF allowSizeConflicts=false THEN { TerminalIO.WriteRope["not resolved\n"]; RETURN }; IF allowSizeConflicts=interactive THEN { IF ~TerminalIO.UserSaysYes[text: "import anyway? ", label: "import different sized ob?"] THEN { TerminalIO.WriteRope["no\n"]; RETURN }; TerminalIO.WriteRope["yes\n"]; }; }; rp.boundApp _ CDApplications.NewApplicationI[ob: referedOb]; rp.boundApp.location _ [0, 0]; BEGIN oldSize: CD.DesignPosition = reference.size; oldBase: CD.DesignPosition = CDBasics.BaseOfRect[oldRect]; newSize: CD.DesignPosition = referedOb.size; newBase: CD.DesignPosition = CDBasics.BaseOfRect[newRect]; IF oldSize#newSize OR oldRect#newRect THEN { reference.size _ newSize; rp.ir _ newRect; CDDirectory.RepositionObject[design: design, ob: reference, oldSize: oldSize, baseOff: CDBasics.SubPoints[oldBase, newBase] ]; }; END; ok _ TRUE; EXITS UserAborted => {TerminalIO.WriteRope["aborted, entry not replaced\n"]}; END; DoImport: PUBLIC PROC [design: CD.Design, importee: CD.Design, allowOverload, allowConflicts: BoolOrInteractive_true] RETURNS [done: BOOL_FALSE] = BEGIN indirectImport: REF ImportList ~ GetImportList[importee]; IF indirectImport^.list#NIL THEN TerminalIO.WriteRope["There are indirect imports\n"]; FOR list: LIST OF REF Import _ indirectImport^, list.rest WHILE list#NIL DO IF Rope.Equal[list.first.importeeName, design.name] THEN { TerminalIO.WriteRope["**creates circular imports\n"]; RETURN } ENDLOOP; BindImportee[importer: design, importee: importee, allowSizeConflicts: allowConflicts, allowOverload: allowOverload]; FOR list: LIST OF REF Import _ GetImportList[design]^, list.rest WHILE list#NIL DO IF list.first.importee#NIL THEN BindImportee[importer: list.first.importee, importee: importee, allowSizeConflicts: false, allowOverload: true]; ENDLOOP; FOR list: LIST OF REF Import _ indirectImport^, list.rest WHILE list#NIL DO IF list.first.importee=NIL THEN { imp: REF Import _ GetImport[design, list.first.importeeName, false]; IF imp#NIL AND imp.importee#NIL THEN BindImportee[importer: importee, importee: imp.importee, allowSizeConflicts: false, allowOverload: true]; } ENDLOOP; done _ TRUE; END; DesignHasBeenRenamed: CDEvents.EventProc --PROC [event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOL_FALSE]-- = BEGIN imp: REF Import ~ GetImport[design: design, importeeName: design.name, createIfNotFound: false]; IF imp#NIL THEN { dont _ TRUE; TerminalIO.WriteRope["rename causes circularities; not done\n"] }; END; ReplaceChildrenByImports: PROC[me: CD.ObPtr, design: CD.Design, importeeName: Rope.ROPE] = BEGIN replaceList: CDDirectory.ReplaceList_NIL; PerChild: CDDirectory.EnumerateObjectsProc --PROC [me: CD.ObPtr, x: REF] -- = BEGIN IF me.p.inDirectory THEN { impChild: CD.ObPtr; FOR list: CDDirectory.ReplaceList _ replaceList, list.rest WHILE list#NIL DO IF list.first.old=me THEN RETURN -- eliminate duplicates ENDLOOP; impChild _ InternalCreateReference[ design: design, objectName: CDDirectory.Name[me], importeeName: importeeName, size: me.size, autoImport: true, autoCreateOb: true, allowConflicts: true, include: TRUE ]; replaceList _ CONS[ NEW[CDDirectory.ReplaceRec_[ old: me, oldSize: me.size, new: impChild, newSize: impChild.size, off: [0, 0] ]], replaceList ]; } END; CDDirectory.EnumerateChildObjects[me: me, p: PerChild, x: NIL]; IF replaceList#NIL THEN [] _ CDDirectory.DoReplaceDirectChild[me: me, design: design, replace: replaceList]; END; OneLevelIncludedCopy: PUBLIC PROC [impObject: CD.ObPtr, design: CD.Design] RETURNS [CD.ObPtr] = BEGIN WITH impObject.specificRef SELECT FROM rp: ReferencePtr => { newOb: CD.ObPtr; import: REF Import = GetImport[design, rp.designName, false]; IF rp.boundApp=NIL OR import=NIL OR import.importee=NIL THEN ERROR CD.Error[callingError, "OneLevelIncludedCopy impObject not bound "]; newOb _ CDDirectory.Another[me: rp.boundApp.ob, from: import.importee, to: design]; ReplaceChildrenByImports[me: newOb, design: design, importeeName: import.importeeName]; RETURN [newOb] }; ENDCASE => ERROR CD.Error[callingError, "OneLevelIncludedCopy impObject not reference"] END; Another: PROC [me: CD.ObPtr, from, to: CD.Design] RETURNS [CD.ObPtr] = BEGIN rp: ReferencePtr = NARROW[me.specificRef]; newOb: CD.ObPtr = InternalCreateReference[design: to, objectName: rp.objectName, importeeName: rp.designName, autoCreateOb: true, autoImport: true, allowConflicts: true, include: TRUE, size: me.size]; newOb.properties _ CDProperties.AppendProps[looser: me.properties, winner: newOb.properties]; IF newOb=NIL THEN ERROR; RETURN [newOb]; END; MergeInImport: PUBLIC PROC [design: CD.Design, importeeName: Rope.ROPE] = BEGIN imp: REF Import _ GetImport[design, importeeName, false]; IF imp=NIL THEN { TerminalIO.WriteRope["MergeInImport not done; design "]; TerminalIO.WriteRope[importeeName]; TerminalIO.WriteRope[" is not imported\n"]; RETURN } ELSE IF imp.importee=NIL THEN { TerminalIO.WriteRope["MerginImport not done; design "]; TerminalIO.WriteRope[importeeName]; TerminalIO.WriteRope[" is not loaded\n"]; RETURN } ELSE { importee: CD.Design _ imp.importee; objectList: LIST OF CD.ObPtr _ NIL; doList: LIST OF CD.ObPtr _ NIL; dontList: LIST OF CD.ObPtr _ NIL; FOR list: LIST OF CD.ObPtr _ imp.referenceList, list.rest WHILE list#NIL DO IF NARROW[list.first.specificRef, ReferencePtr].boundApp#NIL THEN doList _ CONS[list.first, doList] ELSE dontList _ CONS[list.first, dontList]; ENDLOOP; imp.importee _ NIL; imp.referenceList _ dontList; FOR list: LIST OF CD.ObPtr _ doList, list.rest WHILE list#NIL DO pr: ReferencePtr = NARROW[list.first.specificRef]; objectList _ CONS[pr.boundApp.ob, objectList]; ENDLOOP; CDExtras.MergeInObjects[design: design, from: importee, objects: objectList]; FOR list: LIST OF CD.ObPtr _ doList, list.rest WHILE list#NIL DO [] _ CDDirectory.Remove[design: design, name: CDDirectory.Name[list.first], expectObject: list.first ] ENDLOOP; FOR list: LIST OF CD.ObPtr _ doList, list.rest WHILE list#NIL DO pr: ReferencePtr = NARROW[list.first.specificRef]; CDDirectory.ReplaceObject[design: design, old: list.first, new: pr.boundApp.ob] ENDLOOP; } END; HasUnloadedImports: PUBLIC PROC [design: CD.Design] RETURNS [yes: BOOL_FALSE] = BEGIN impList: REF CDImports.ImportList = GetImportList[design]; IF impList#NIL THEN FOR list: LIST OF REF CDImports.Import _ impList^, list.rest WHILE list#NIL DO IF list.first.importee=NIL THEN { RETURN [yes _ TRUE] } ENDLOOP; END; OldSetInterest: PROC [ob: CD.ObPtr, r: CD.DesignRect] = BEGIN cptr: ReferencePtr = NARROW[ob.specificRef]; cptr.ir _ r; END; Init: PROC [] = BEGIN rp: REF CDDirectory.DirectoryProcs ~ CDDirectory.InstallDirectoryProcs[pForReference]; rp.enumerateChildObjects _ EnumerateItsObjects; rp.replaceDirectChilds _ ReplaceDirectChild; rp.another _ Another; pForReference.drawMe _ DrawReference; pForReference.quickDrawMe _ QuickDrawReference; pForReference.showMeSelected _ DrawReferenceSelection; pForReference.internalRead _ ReadReference; pForReference.internalWrite _ WriteReference; pForReference.describe _ DescribeReference; pForReference.interestRect _ InterestRect; CDInterestRects.InstallOldSetInterest[pForReference, OldSetInterest]; CDValue.EnregisterKey[importListKey]; CDEvents.RegisterEventProc[$RenameDesign, DesignHasBeenRenamed]; END; Init[]; END. äCDImportsImpl.mesa (part of ChipNDale) Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. by Christian Jacobi, March 20, 1984 5:50:51 pm PST last edited Christian Jacobi, April 11, 1985 9:30:55 am PST dont !!! rp: ReferencePtr ~ NARROW[me.specificRef]; IF rp.boundApp#NIL THEN p[rp.boundApp.ob, x]; -- PROC[me: CD.ObPtr, design: CD.Design, replace: LIST OF REF ReplaceRec] -- dont, don't ERROR: don't ERROR, because the client doese not know that imports cannot be changed --search first for an already imported object object --already imported object has not been found; make import -- check for forbidden circular import -- no circular import --check already imported designs for importing the new design --check the new design for importing of already imported designs -- prevent a renaming which would cause circularity --build list of direct children --replace each direct child by an import --imp is an imported and bound object which will be made local to design --Includes all the imported and bound objects from importeeName (including --their transitive closure; but not indirect imports) into design. --split the reference list in doList and dontList --merge in objects from doList --now remove old references ʶ˜šœ(™(Jšœ Ïmœ7™BJšœ3™3Jšœ;™;J˜—šÏk ˜ Jšžœ˜J˜J˜J˜ J˜ Jšœ žœ˜ Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ ˜ J˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜J˜—šÏb œžœžœ˜Jšžœžœ=žœT˜ŸJšžœ˜"Jšžœ˜—Jšž˜J˜J˜Jšœžœ˜6Jšœžœ˜,Jšœžœ˜,J˜Jšœ žœ˜(Jšœžœ˜ J˜JšœžœÏc˜1J˜Jšœžœžœ˜CJ˜šÏnœžœžœ0žœ˜XJšž˜šœ ™ Jšœžœ™*Jšžœ žœžœ™-—Jšžœ˜—J˜šŸœ#˜5JšœL™LJšž˜Jšœ™JšœM™MJšžœ˜—J˜š¡œžœ žœ ˜2Jšœžœ œ%˜bJšœ žœ˜&Jšœ' '˜NJšœ) +˜TJšœ+ $˜OJš œ žœžœžœžœ ˜)Jšž˜Jšœžœ˜ Jšœ˜Jšœžœ6˜AJšœžœ2˜BJšœžœ ˜Jšžœžœ žœ-˜WJš žœžœžœžœžœ˜ Jšœ4™4š žœžœžœžœ)žœžœž˜NJšœ˜Jšœžœ˜*šžœ'˜)šžœ)žœ˜2Jšžœžœžœžœ˜7šžœžœžœ˜>Jšœ˜Jšœ˜Jšœžœžœ˜—Jšžœžœžœ˜—Jšœ˜—Jšžœ˜—Jšœ9™9šžœžœžœ˜Jšœžœ˜ Jšœ žœ˜JšœD˜Dšžœžœ˜šžœžœžœ˜OJšœ˜Jšœ˜Jšœžœžœžœ˜—J˜—šžœ˜šžœžœ˜Jšœ˜Jšœžœ˜ Jšœ˜—J˜—J˜—šœžœžœ˜Jšœ˜Jšœ˜Jšœžœ ˜šœ žœ˜!Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœ˜—Jšœžœ˜6Jšžœ žœn˜}JšžœžœžœA˜\Jšžœ˜ Jšžœ˜—J˜š¡ œžœžœ žœ(žœžœžœ ˜kJšž˜Jšœ¨žœ˜®Jšžœ˜—Jšœ˜š ¡ œžœžœžœžœ˜8Jšž˜Jšœžœ˜$šžœžœ˜Jšœžœ˜*Jšžœ.˜4J˜—Jšžœ˜ Jšžœ˜—J˜š ¡ œžœžœžœžœž˜MJšž˜Jšœžœ˜$šžœžœ˜Jšžœ˜J˜—Jšžœ˜ Jšžœ˜—J˜š ¡œžœžœžœžœ˜˜>šž˜Jšžœžœ ˜0—Jšœžœžœ˜Jšœžœ-˜7Jšžœžœžœžœ˜šžœžœžœ˜Jšžœžœž˜"šžœžœž˜&šžœžœ˜Jšœ2˜2šœžœ˜Jšœ2˜2Jšžœ˜J˜———J˜—Jšœ˜š žœžœžœžœ(žœžœž˜MJšœžœK˜\Jšžœ˜—Jšžœžœžœ1˜BJšœ˜šž˜JšœE˜E—Jšžœ˜—J˜š¡ œžœ žœžœžœ7žœžœžœ˜ššž˜Jšžœžœ ˜0—Jšœžœ&˜?Jšœžœ˜ Jšœžœ ˜ Jšœ žœ˜Jšœ@˜@šžœžœžœ˜Jšœ˜Jšœ$˜$Jšœ˜Jšœ$˜$Jšœ%˜%Jšž˜J˜—Jšœ"˜"Jšœ%˜%šžœžœ˜Jšœ ˜ Jšœ$˜$Jšœ.˜.šžœ;žœ˜BJšœ3˜3—šžœ˜Jšœ7˜7—šžœžœ˜"Jšœ'˜'Jšž˜J˜—šžœ žœ˜(šžœ2˜4šœ%žœ˜+Jšœ˜Jšž˜Jšœ˜——Jšœ˜Jšœ˜—J˜—Jšœ<˜Jšœ7žœžœžœ˜TJšž˜Jšœžœ'˜:Jšžœžœžœ6˜VJšœ&™&š žœžœžœžœ%žœžœž˜Kšžœ2žœ˜:Jšœ5˜5Jšž˜Jšœ˜—Jšžœ˜ —Jšœ™Jšœu˜uJšœ=™=š žœžœžœžœ,žœžœž˜Ršžœžœž˜Jšœp˜p—Jšžœ˜ —Jšœ@™@š žœžœžœžœ%žœžœž˜Kšžœžœžœ˜!Jšœžœ<˜Dš žœžœžœžœž˜$Jšœi˜i—J˜—Jšžœ˜ —Jšœžœ˜ Jšžœ˜—J˜šŸœ˜)Jš žœ žœ žœ žœžœžœžœ œ˜MJšœ3™3Jšž˜JšœžœX˜`šžœžœžœ˜Jšœžœ˜ Jšœ?˜?J˜—Jšžœ˜—J˜š ¡œžœžœžœžœ˜ZJšž˜Jšœ%žœ˜)J˜šŸœ#  œ˜MJšž˜šžœžœ˜Jšœ žœ˜šžœ8žœžœž˜LJšžœžœž ˜8Jšžœ˜ —šœ#˜#JšœM˜MJšœTž˜XJšœ˜—šœžœ˜šžœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜—Jšœ ˜ Jšœ˜—J˜—Jšžœ˜—J™Jšœ™Jšœ:žœ˜?Jšœ(™(šžœ žœžœ˜JšœT˜T—Jšžœ˜—J˜š¡œžœžœ žœžœ žœžœ ˜_JšœH™HJšž˜šžœžœž˜&šœ˜Jšœžœ˜Jšœžœ2˜=šžœ žœžœžœžœžœžœ˜=JšžœžœB˜J—JšœS˜SJšœW˜WJšžœ˜J˜—JšžœžœžœD˜W—Jšžœ˜—J˜š ¡œžœžœžœ žœžœ ˜FJšž˜Jšœžœ˜*Jšœžœªžœ˜ÈJšœ]˜]Jšžœžœžœž˜Jšžœ ˜Jšžœ˜—J˜š ¡ œžœžœ žœžœ˜IJšœL™LJšœB™BJšž˜Jšœžœ1˜9šžœžœžœ˜Jšœ8˜8Jšœ#˜#Jšœ+˜+Jšž˜J˜—šžœžœžœžœ˜Jšœ7˜7Jšœ#˜#Jšœ)˜)Jšž˜J˜—šžœ˜Jšœ žœ˜$Jš œ žœžœžœ žœ˜#Jš œžœžœžœ žœ˜Jš œ žœžœžœ žœ˜!Jšœ1™1š žœžœžœžœ&žœžœž˜Kšžœžœ0žœžœ˜BJšœ žœ˜!—Jšžœ žœ˜+Jšžœ˜—Jšœžœ˜Jšœ˜Jšœ™š žœžœžœžœžœžœž˜@Jšœžœ˜2Jšœ žœ˜.Jšžœ˜—JšœM˜MJšœ™š žœžœžœžœžœžœž˜@šœ(˜(Jšœ$˜$Jšœ˜Jšœ˜—Jšžœ˜—š žœžœžœžœžœžœž˜@Jšœžœ˜2JšœO˜OJšžœ˜—J˜—Jšžœ˜—J˜š ¡œž œ žœ žœžœžœ˜OJšž˜Jšœ žœ.˜:šžœ žœž˜š žœžœžœžœ(žœžœž˜Nšžœžœžœ˜!Jšžœžœ˜J˜—Jšžœ˜——Jšžœ˜—J˜š¡œžœžœ žœ˜7Jšž˜Jšœžœ˜,Jšœ ˜ Jšžœ˜J˜—š¡œžœ˜Jšž˜JšœžœO˜VJšœ/˜/Jšœ,˜,Jšœ˜Jšœ%˜%Jšœ/˜/Jšœ6˜6Jšœ+˜+Jšœ-˜-Jšœ+˜+Jšœ*˜*JšœE˜EJšœ%˜%J˜@Jšžœ˜—J˜J˜Jšžœ˜J˜—…—Dîaˆ