DIRECTORY Buttons USING [Button, Create, ReLabel, SetDisplayStyle], Containers USING [ChildXBound, ChildYBound, Container, Create], GVPDefs, IO USING [PutF, PutText, SetIndex, STREAM, UnsafeGetBlock], ObjectDirDefs USING [ObjectNumber], Rope USING [Concat, Equal, Fetch, Length, Substr], ViewerIO USING [CreateViewerStreams], ViewerOps USING [CreateViewer, MoveViewer, PaintViewer], ViewerTools USING [GetContents, MakeNewTextViewer, SetSelection, SetContents]; GVPBrowser: CEDAR MONITOR LOCKS lock IMPORTS Buttons, Containers, GVPDefs, IO, Rope, ViewerIO, ViewerOps, ViewerTools EXPORTS GVPDefs SHARES ObjectDirDefs = BEGIN OPEN GVPDefs; browserButtons, browserText, setInput, repeatInput, patternInput: Viewer; repeatPending, stopScan, stoppable, autoShow: BOOLEAN _ FALSE; showFull: BOOLEAN _ TRUE; pageBuffer: REF PageWordVec _ NIL; objects: ARRAY objRange OF ROPE = -- used for printing and lookup ["Gap ", "Body ", "SLinp ", "SLpend", "SLfwd ", "RSobj ", "RSmail", "temp ", "RSname", "MSname", "test-M", "TOC ", "Arch ", "s15 ", "s16 ", "s17 " ]; MakeBrowserButtons: PUBLIC PROC[h: GVPRef] = BEGIN browserText _ ViewerOps.CreateViewer[flavor: $Typescript, info: [parent: h.root, border: TRUE, iconic: FALSE, wy: offScreen]]; h.browserStream _ ViewerIO.CreateViewerStreams[viewer: browserText, name: NIL].out; browserButtons _ Containers.Create[[name: NIL, parent: h.root, wx: 0, wy: offScreen, wh: 4*rowSize, border: FALSE, scrollable: FALSE]]; setInput _ ViewerTools.MakeNewTextViewer[[parent: browserButtons, wx: col6, wy: row1+2, ww: 30*char, wh: rowHeight, scrollable: FALSE, border: FALSE, data: "0"]]; patternInput _ ViewerTools.MakeNewTextViewer[[parent: browserButtons, wx: col6, wy: row3+2, ww: 30*char, wh: rowHeight, scrollable: FALSE, border: FALSE, data: "/ / /"]]; repeatInput _ ViewerTools.MakeNewTextViewer[[parent: browserButtons, wx: col6, wy: row2+2, ww: 30*char, wh: rowHeight, scrollable: FALSE, border: FALSE, data: "1"]]; [] _ Buttons.Create[info: [name: "SERVER", wx: col1, wy: row1, wh: rowSize+rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: ServerButton]; [] _ Buttons.Create[info: [name: "EDITOR", wx: col1, wy: row3, wh: rowSize+rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: EditorButton]; [] _ Buttons.Create[info: [name: "position #", wx: col3, wy: row1, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: SetLogicalButton]; [] _ Buttons.Create[info: [name: "page #", wx: col2, wy: row1, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: SetPhysicalButton]; [] _ Buttons.Create[info: [name: "number >", wx: col5, wy: row1, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: ValueButton]; [] _ Buttons.Create[info: [name: "FULL", wx: col2, wy: row2, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: ShowModeButton]; [] _ Buttons.Create[info: [name: "REPEAT", wx: col3, wy: row2, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: RepeatButton]; [] _ Buttons.Create[info: [name: "AUTO", wx: col4, wy: row2, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: AutoShowButton]; [] _ Buttons.Create[info: [name: "next", wx: col2, wy: row3, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: NextButton]; [] _ Buttons.Create[info: [name: "prev", wx: col3, wy: row3, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: PrevButton]; [] _ Buttons.Create[info: [name: "pattern >", wx: col5, wy: row3, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: PatternButton]; [] _ Buttons.Create[info: [name: "scan error", wx: col2, wy: row4, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: ScanErrorButton]; [] _ Buttons.Create[info: [name: "scan match", wx: col3, wy: row4, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: ScanMatchButton]; [] _ Buttons.Create[info: [name: " ! STOP !", wx: col4, wy: row4, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: StopButton]; [] _ Buttons.Create[info: [name: "show", wx: col4, wy: row3, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: ShowButton]; [] _ Buttons.Create[info: [name: "repeat >", wx: col5, wy: row2, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: RptCountButton]; [] _ Buttons.Create[info: [name: "reset", wx: col4, wy: row1, wh: rowHeight, ww: buttonSize, parent: browserButtons], clientData: h, proc: ResetButton] END; BrowserButton: PUBLIC ENTRY ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; r: ROPE = CheckStructure[h]; IF r#NIL THEN {Flash[r]; RETURN}; ToFocus[]; ViewerOps.MoveViewer[viewer: h.currentButtons, x:0, y: offScreen, w: 0, h: 0, paint: FALSE]; ViewerOps.MoveViewer[viewer: browserButtons, x:0, y: 0, w: 0, h: 4*rowSize, paint: FALSE]; ViewerOps.MoveViewer[viewer: h.currentText, x:0, y: offScreen, w: 0, h: 0, paint: FALSE]; ViewerOps.MoveViewer[viewer: browserText, x:0, y: row6, w: 0, h: 0, paint: FALSE]; Containers.ChildXBound[h.root, browserText]; Containers.ChildXBound[h.root, browserButtons]; Containers.ChildYBound[h.root, browserText]; ViewerOps.PaintViewer[h.root, all]; h.currentButtons _ browserButtons; h.currentText _ browserText END; ShowAuto: PROC[h: GVPRef] RETURNS[r: ROPE] = BEGIN IF autoShow THEN ShowItem[h, showFull]; r _ PlaceRope[h] END; PlaceRope: PROC[h: GVPRef] RETURNS[r:ROPE] ={r _ Rope.Concat["Current ", PositionRope[h]]}; SetLogicalButton: ENTRY ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; a: CARDINAL; [num: a] _ NumFromRope[octal: FALSE, r: ViewerTools.GetContents[setInput], start: 0]; IF SetLogical[h, a] THEN Set[ShowAuto[h]] ELSE Flash["Couldn't"] END; SetPhysicalButton: ENTRY ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; a: CARDINAL; [num: a] _ NumFromRope[octal: FALSE, r: ViewerTools.GetContents[setInput], start: 0]; IF SetPhysical[h, a] THEN Set[ShowAuto[h]] ELSE Flash["Couldn't"] END; ResetButton: ENTRY ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; IF SetLogical[h, 0] THEN Set[ShowAuto[h]] ELSE Flash["Couldn't"] END; PrevButton: ENTRY ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; stoppable _ TRUE; THROUGH [0..GetRepeatCount[]) DO IF NOT PrevPage[h] THEN {Flash["No more pages"]; EXIT}; [] _ ShowAuto[h]; IF StopRequested[] THEN EXIT ENDLOOP; stoppable _ FALSE; Set[PlaceRope[h]] END; NextButton: ENTRY ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; stoppable _ TRUE; THROUGH [0..GetRepeatCount[]) DO IF NOT NextPage[h] THEN {Flash["No more pages"]; EXIT}; [] _ ShowAuto[h]; IF StopRequested[] THEN EXIT ENDLOOP; stoppable _ FALSE; Set[PlaceRope[h]] END; ShowButton: ENTRY ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; ShowItem[h, showFull]; Set[PlaceRope[h]] END; ShowModeButton: ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; me: Viewer = NARROW[parent]; showFull _ NOT showFull; Buttons.ReLabel[me, IF showFull THEN "FULL" ELSE "BRIEF"] END; RepeatButton: ButtonProc = TRUSTED BEGIN me: Viewer = NARROW[parent]; repeatPending _ NOT repeatPending; Buttons.SetDisplayStyle[me, IF repeatPending THEN $WhiteOnBlack ELSE $BlackOnWhite] END; AutoShowButton: ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; me: Viewer = NARROW[parent]; autoShow _ NOT autoShow; Buttons.SetDisplayStyle[me, IF autoShow THEN $WhiteOnBlack ELSE $BlackOnWhite] END; ScanErrorButton: ENTRY ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; stoppable _ TRUE; [] _ Failed[ ScanHeap[h, TRUE] ]; stoppable _ FALSE END; ScanMatchButton: ENTRY ButtonProc = TRUSTED BEGIN h: GVPRef = NARROW[clientData]; stoppable _ TRUE; [] _ Failed[ ScanHeap[h, FALSE] ]; stoppable _ FALSE END; StopButton: ButtonProc = TRUSTED BEGIN IF stoppable THEN stopScan _ TRUE END; StopRequested: PUBLIC PROC RETURNS[stop: BOOLEAN] = BEGIN IF stopScan THEN {stop _ TRUE; stopScan _ FALSE} ELSE stop _ FALSE END; ValueButton: ButtonProc = TRUSTED BEGIN ViewerTools.SetSelection[setInput] END; PatternButton: ButtonProc = TRUSTED BEGIN ViewerTools.SetContents[patternInput, "/ / /"]; Set["Input page, index(octal) and type(string). '/' means don't care"]; ViewerTools.SetSelection[patternInput] END; RptCountButton: ButtonProc = TRUSTED BEGIN ViewerTools.SetContents[repeatInput, "1"]; ViewerTools.SetSelection[repeatInput] END; GetRepeatCount: PROC RETURNS [c: CARDINAL _ 1] = BEGIN IF NOT repeatPending THEN RETURN; [num: c] _ NumFromRope[octal: FALSE, r: ViewerTools.GetContents[repeatInput], start: 0]; IF c=lastCard THEN c _ 1; END; GetSearchPattern: PUBLIC PROC RETURNS[page, index, type: CARDINAL] = BEGIN pos: CARDINAL; rope: ROPE = ViewerTools.GetContents[patternInput]; [num: page, end: pos] _ NumFromRope[octal: TRUE, r: rope, start: 0]; [num: index, end: pos] _ NumFromRope[octal: TRUE, r: rope, start: pos]; type _ ObjectIndex[rope, pos] END; ObjectRope: PUBLIC PROC[index: CARDINAL, brief: BOOLEAN] RETURNS[r: ROPE _ NIL] = BEGIN IF NOT index IN objRange THEN RETURN; IF brief AND (index IN [firstObj..firstObj+5] OR index IN [firstObj+11..firstObj+12]) THEN r _ Rope.Substr[objects[index], 0, 1] ELSE r _ objects[index] END; ObjectIndex: PROC[r: ROPE, start: CARDINAL] RETURNS[index: CARDINAL] = BEGIN len: CARDINAL = Rope.Length[r]; chars: CARDINAL; index _ lastObj+1; IF start=len THEN RETURN; WHILE Rope.Fetch[r, start]=' AND start#len DO start _ start+1 ENDLOOP; chars _ len-start; IF chars=0 THEN RETURN; IF Rope.Fetch[r, start]='/ THEN {index _ lastCard; RETURN}; IF chars<3 THEN RETURN; IF chars>3 THEN chars _ 3; index _ firstObj; WHILE index <= lastObj DO IF Rope.Equal[Rope.Substr[r, start, chars], Rope.Substr[objects[index], 0, chars], FALSE] THEN EXIT; index _ index + 1 ENDLOOP; END; ShowItem: PROC[h: GVPRef, full: BOOLEAN] = BEGIN IF full THEN PrintPageFull[h] ELSE PrintPageBrief[h] END; PrintPageFull: PROC[h: GVPRef] = TRUSTED BEGIN out: IO.STREAM = h.browserStream; page: INT = h.pPage; byte: INT = page*pageByteSize; word: [0..256] _ pageHdrSize; header: LONG POINTER TO PageHeader = LOOPHOLE[pageBuffer]; cont: BOOLEAN; h.heapStream.SetIndex[byte]; [] _ h.heapStream.UnsafeGetBlock[[LOOPHOLE[pageBuffer], 0, bytesPerPage]]; cont _ header.offset#0; out.PutText["\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"]; out.PutF["Page at %g\n\n", [rope[PositionRope[h]]]]; DO objH: LONG POINTER TO ObjectHeader = LOOPHOLE[header + word]; out.PutF["Object Number=[page:%3bB, index:%3bB, %g]", [cardinal[objH.number.page]], [cardinal[objH.number.index]], [rope[ObjectRope[LOOPHOLE[objH.number.type, CARDINAL], FALSE]]] ]; out.PutF[", size=%d, word=%d.", [cardinal[objH.size]], [cardinal[word]] ]; IF cont THEN {out.PutF[" Cont, offset=%d", [cardinal[header.offset]]]; cont _ FALSE }; IF objH.number.page>maxObjNumPage OR objH.number.index>maxObjNumIndex OR objH.number.fill#0 THEN out.PutText[" **Illegal**"]; out.PutText["\n"]; word _ word + objHdrSize + objH.size; IF word + objHdrSize > 255 THEN EXIT ENDLOOP; out.PutText["\n"] END; PrintPageBrief: PROC[h: GVPRef] = TRUSTED BEGIN out: IO.STREAM = h.browserStream; page: INT = h.pPage; byte: INT = page*pageByteSize; word: [0..256] _ pageHdrSize; header: LONG POINTER TO PageHeader = LOOPHOLE[pageBuffer]; cont: BOOLEAN; h.heapStream.SetIndex[byte]; [] _ h.heapStream.UnsafeGetBlock[[LOOPHOLE[pageBuffer], 0, bytesPerPage]]; cont _ header.offset#0; IF h.pPage MOD segSize = 0 THEN out.PutF["\n(pos: %d, page: %d) ", [cardinal[h.lPage]], [cardinal[h.pPage]]]; DO objH: LONG POINTER TO ObjectHeader = LOOPHOLE[header + word]; IF cont THEN {out.PutText["-"]; cont _ FALSE} ELSE out.PutF["%g", [rope[ObjectRope[LOOPHOLE[objH.number.type, CARDINAL], TRUE]]]]; IF objH.number.page>maxObjNumPage OR objH.number.index>maxObjNumIndex OR objH.number.fill#0 THEN out.PutText["(_**Illegal**)"]; word _ word + objHdrSize + objH.size; IF word + objHdrSize > 255 THEN EXIT ENDLOOP; out.PutText[" "] END; BrowserInit: PUBLIC PROC = BEGIN pageBuffer _ NEW[PageWordVec]; autoShow _ FALSE; showFull _ TRUE; repeatPending _ FALSE; stopScan _ FALSE; stoppable _ FALSE END; BrowserTidyUp: PUBLIC PROC = BEGIN pageBuffer _ NIL; END; END. pGVPBrowser.mesa HGM. May 23, 1984 11:01:01 pm PDT Steve Temple. November 5, 1982 1:34 pm Schroeder on March 31, 1983 9:51 am This module implements the browser mode of the GVPatch system. The monitor lock for this module is in GVPMain. This module contains all the browser mode button procedures and relies on procedures in GVPProcs for many of its operations. Note that we must SHARE ObjectDirDefs to get at the internals of object numbers (machine dependent records) The viewers here are for the obvious thing. The BOOLs are used to control repeating operations or the style of printing objects. The buffer "pageBuffer" holds a disk page while we are printing its contents. MakeBrowserButtons makes a container for the browser buttons and (three) input viewers and also makes a typescript and attaches an output stream to it. See MakeServerButtons in GVPMain for more details. BrowserButton is called by clicking the BROWSER button in server or editor modes. It just shifts the current mode's viewer off the screen and puts up the browser mode viewer. Note that we call CheckStructure to make the data strucures necessary for browsing. If this fails we can't get to brower mode. ShowAuto consults the auto display BOOLEAN and if set prints the current page. It returns the current position as a rope. PlaceRope is the proc which does just that. SetLogicalButton and SetPhysicalButton get a number from the input viewer and attempt to make that the current position or page. The procs that do the work are in GVPProcs. If OK then call ShowAuto to show where we are and maybe print the page. ResetButton is just a special case of SetLogicalButton PrevButton and NextButton call the appropriate proc in GVPProcs to work out the new position. They may both repeat and the auto show facility may be enabled. We must also check to see if the STOP button has been clicked. ShowButton just calls ShowItem (this module) with the print mode flag as an argument. ShowModeButton just flips the printing mode flag (showFull) and relabels itself accordingly. RepeatButton is much the same, the flag is repeatPending and reverse video is used to show the flag is set. AutoShowButton is similar. ScanError and ScanMatch both use the ScanHeap proc (from GVPProcs) to scan thro the heap. They are both stoppable and the only difference is the BOOLEAN argument which says whether to scan only for errors or for pattern matches also. StopButton sets a stop flag if the currently running command is stoppable. StopRequested tests and clears this flag returning its old value. ValueButton, PatternButton and RptCountButton just direct the selection to the right viewer and may impose a default content while they're about it. GetRepeatCount checks the repeat flag and returns 1 if it's not set. Otherwise it reads the count from the input viewer and returns that. Empty viewer or / means 1. GetSearchPattern reads 2 numbers (octal) and a string from the input viewer and returns 3 numbers the last being the object type derived from the string. ObjectRope and ObjectIndex convert between strings representing object types and numbers. Valid object type indices are [0..15]. ObjectRope returns a rope when presented with a number in this range. A BOOLEAN says only give a single char for commonly occurring object types. ObjectIndex does the reverse operation, starting at a given position in a rope. The char / returns LAST[CARDINAL] while a bad rope returns 16. Only the first 3 chars are matched. ShowItem prints the current page according to the print mode flag PrintPageFull and PrintPageBrief both print the objects on the current page in various levels of detail. The page in question is read into the buffer (pageBuffer) and the objects are picked out for printing. Bad object numbers and continuation sub-objects are noted. BrowserInit just gets storage for the page buffer and sets up all the flags. BrowserTidyUp frees the page buffer. ÊÞ˜šœ™Jšœ!™!Jšœ&™&Jšœ#™#—J˜JšœX™XJšœU™UJšœT™TJšœS™SJ˜J˜šÏk ˜ Jšœœ,˜9Jšœ œ/˜?J˜Jšœœœ˜;Jšœœ˜#Jšœœ(˜2Jšœ œ˜%Jšœ œ)˜8Jšœ œ=˜NJ˜—Jšœ œ˜J˜Jšœ˜ J˜šœœ(˜QJ˜—Jšœ˜J˜Jšœ˜Jšœœ ˜J˜J˜JšœS™SJšœW™WJšœ.™.J˜J˜IJšœ.œœ˜>Jšœ œœ˜Jšœ œœ˜"J˜J˜šœ œ œœÏc˜A˜PJ˜QJ˜J˜J˜——JšœW™WJšœZ™ZJšœ™J˜JšÏnœœœ˜2˜˜9Jšœœ œ˜DJ˜—JšœJœ˜SJ˜šœ*œ'˜TJšœœœ˜2J˜—˜KJšœ4œ œ˜VJ˜—˜OJšœ4œ œ˜ZJ˜—˜NJšœ4œ œ˜VJ˜—˜VJ˜LJ˜—˜UJ˜LJ˜—˜QJ˜QJ˜—˜MJ˜QJ˜—˜QJ˜LJ˜—˜KJ˜NJ˜—˜MJ˜LJ˜—˜KJ˜NJ˜—˜KJ˜JJ˜—˜KJ˜JJ˜—˜RJ˜MJ˜—˜QJ˜OJ˜—˜QJ˜OJ˜—˜RJ˜JJ˜—˜KJ˜JJ˜—˜RJ˜NJ˜—˜LJ˜J—Jšœ˜J˜J˜—JšœY™YJšœT™TJšœ[™[Jšœ"™"J˜šœœœœ˜6Jšœ œ ˜Jšœœ˜Jšœœœ œ˜!J˜ JšœUœ˜\JšœSœ˜ZJšœRœ˜YJšœLœ˜SJ˜J˜,J˜/J˜,J˜#J˜J˜"J˜Jšœ˜J˜J˜—JšœN™NJšœV™VJ˜š Ÿœœ œœ˜2Jšœ œ˜'J˜Jšœ˜J˜—JšŸ œœ œœ2˜[J˜J˜JšœU™UJšœV™VJšœH™HJšœ6™6J˜šœœœ˜2Jšœ œ ˜Jšœœ˜ Jšœœ2˜UJšœœœ˜@Jšœ˜J˜—šœœœ˜3Jšœ œ ˜Jšœœ˜ Jšœœ2˜UJšœœœ˜AJšœ˜J˜—šœ œœ˜-Jšœ œ ˜Jšœœœ˜@Jšœ˜J˜J˜—JšœS™SJšœW™WJšœ1™1JšœU™UJ˜šœ œœ˜,Jšœ œ ˜Jšœ œ˜šœ˜ Jšœœ œœ˜7J˜Jšœœ˜Jšœ˜—Jšœ œ˜J˜Jšœ˜J˜—šœ œœ˜,Jšœ œ ˜Jšœ œ˜šœ˜ Jšœœ œœ˜7J˜Jšœœ˜Jšœ˜—Jšœ œ˜J˜Jšœ˜J˜—šœ œœ˜,Jšœ œ ˜J˜J˜Jšœ˜J˜J˜—JšœO™OJšœQ™QJšœA™AJ˜šœœ˜*Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœœ œœ ˜9Jšœ˜J˜—šœœ˜(Jšœ œ ˜Jšœœ˜"Jšœœœœ˜TJšœ˜J˜—šœœ˜*Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœœ œœ˜NJšœ˜J˜J˜—JšœS™SJšœS™SJšœA™AJ˜šœœœ˜1Jšœ œ ˜Jšœ œ˜Jšœœ˜!Jšœ ˜Jšœ˜J˜—šœœœ˜1Jšœ œ ˜Jšœ œ˜Jšœœ˜"Jšœ ˜Jšœ˜J˜J˜—JšœJ™JJšœA™AJ˜šœœ˜&Jšœ œ ˜!Jšœ˜J˜—š Ÿ œœœœœ˜9Jšœ ˜ Jšœ œ œ˜$Jšœ˜Jšœ˜J˜J˜—JšœT™TJšœ?™?J˜šœœ˜'J˜"Jšœ˜J˜—šœœ˜)J˜/J˜GJ˜&Jšœ˜J˜—šœœ˜*J˜*J˜%Jšœ˜J˜J˜—JšœW™WJšœL™LJ˜š Ÿœœœœ˜6Jšœœœœ˜!Jšœœ5˜XJšœ œ˜Jšœ˜J˜J˜—JšœW™WJšœA™AJ˜š Ÿœœœœœœ˜KJšœœ˜Jšœœ)˜3Jšœ+œ˜DJšœ,œ˜GJ˜Jšœ˜J˜J˜—JšœY™YJšœ]™]JšœZ™ZJšœ[™[JšœW™WJ˜š Ÿ œœœœ œ˜9Jšœœœ˜J˜Jš œœœ œœ˜%J˜š œœœœœ˜UJšœ'˜+Jšœ˜—Jšœ˜J˜—š Ÿ œœœ œœœ˜LJšœœ˜Jšœœ˜J˜J˜J˜Jšœ œœ˜Jšœœ œœ˜GJ˜Jšœ œœ˜Jšœœœ˜;Jšœ œœ˜Jšœ œ ˜J˜J˜šœ˜šœQœ˜ZJšœœ˜ —J˜Jšœ˜—Jšœ˜J˜J˜—JšœA™AJ˜šŸœœœ˜0šœ˜Jšœ˜Jšœ˜—Jšœ˜J˜J˜—Jšœ]™]Jšœ_™_JšœL™LJ˜JšŸ œœ ˜.˜Jšœœœ˜!Jšœœ ˜Jšœœ˜J˜J˜Jšœœœ ˜:Jšœœ˜J˜J˜Jšœ"œ ˜JJ˜J˜J˜@J˜4J˜š˜Jšœ œœœ˜=J˜˜5J˜J˜Jšœœœœ˜BJ˜—˜J˜J˜J˜—šœ˜ JšœAœ˜IJ˜—šœ ˜$Jšœ!˜#Jšœœ˜4J˜—J˜%J˜J˜%Jšœœ˜$Jšœ˜J˜—J˜Jšœ˜J˜J˜—JšŸœœœ˜/˜Jšœœœ˜!Jšœœ ˜Jšœœ˜J˜J˜Jšœœœ ˜:Jšœœ˜J˜J˜Jšœ"œ ˜JJ˜J˜šœ œ ˜JšœN˜RJ˜—š˜Jšœ œœœ˜=J˜šœ˜Jšœœ˜%Jšœ!œœœ˜TJ˜—šœ œ˜%Jšœ!œ˜$Jšœœ˜6J˜—J˜%Jšœœ˜$Jšœ˜J˜—J˜Jšœ˜J˜J˜—JšœL™LJšœ$™$J˜šŸ œœœ˜ Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœœ˜Jšœ œ˜Jšœ ˜Jšœ˜J˜—šŸ œœœ˜"Jšœ œ˜Jšœ˜J˜—Jšœ˜J˜J˜J˜—…—0ŽNÜ