DIRECTORY Ascii USING [BS, ControlA, ControlW, ControlQ, ControlS, CR, DEL, ESC], BiScrollers USING [BiScroller, ClientCoords, ClientDataOf, QuaBiScroller, QuaViewer], Geom2D USING [Vec], ImagerTransformation USING [Transform], InputFocus USING [SetInputFocus], Interminal USING [GetCursorOffset, SetCursorOffset], MessageWindow USING [Append], Real USING [RoundI], Rope USING [ROPE], Terminal USING [Current, Position, SetBWCursorPosition, SetColorCursorPosition, Virtual], TIPUser USING [TIPTable, TIPScreenCoords], ViewerClasses USING [ModifyProc, NotifyProc, Viewer], ViewerOps USING [UserToScreenCoords], Cursors USING [SetCursor, CursorType], SilUserInput, SilKernel, SilFile ; SilUserInputImpl: CEDAR MONITOR LOCKS uiData USING uiData: SilUIData IMPORTS BiScrollers, MessageWindow, ImagerTransformation, InputFocus, Real, ViewerOps, Interminal, Terminal, Cursors EXPORTS SilUserInput, SilKernel = BEGIN ROPE: TYPE = Rope.ROPE; SilData: TYPE = SilKernel.SilData; UInput: TYPE = SilUserInput.UInput; UInputRec: TYPE = SilUserInput.UInputRec; TIPScreenCoords: TYPE = TIPUser.TIPScreenCoords; SilUIData: TYPE = REF SilUIDataRec; SilUIDataRec: PUBLIC TYPE = MONITORED RECORD [ queue: UInput _ NIL, gotInput: CONDITION, innerViewer: ViewerClasses.Viewer, --two viewers to use BiScrollers properly outerViewer: ViewerClasses.Viewer, bs: BiScrollers.BiScroller, gotInputFocus: BOOL _ FALSE, caretsShouldChangeNow: BOOL _ FALSE, gridSpacing: NAT _ SilUserInput.defaultGridSpacing, gridding: BOOL _ FALSE, --is cursor gridding in this viewer at this moment? hotX: INTEGER _ 0, hotY: INTEGER _ 0, xOffset, yOffset: REAL _ 0.0, xPostOffset, yPostOffset: INTEGER _ 0, gridMagnification: NAT _ 1, mode: SilUserInput.InputCharMode _ NotInputingRope, InputWaitingForArg: UInput _ NIL ]; silTipTable: TIPUser.TIPTable; terminal: Terminal.Virtual; SilHasInputFocus: BOOL; silCursorHasBitmap: BOOL _ FALSE; -- set by ControlS restoreCursor: BOOL _ TRUE; -- set by move or copy commands savedCursor: Cursors.CursorType _ textPointer; --restored after ControlS, move, copy InitTipTable: PUBLIC PROC [tipTable: TIPUser.TIPTable] = { silTipTable _ tipTable; terminal _ Terminal.Current[]; }; InitUserInput: PUBLIC PROC [data: SilData, viewer: ViewerClasses.Viewer] = { uiData: SilUIData _ data.uiData _ NEW[SilUIDataRec]; uiData.bs _ BiScrollers.QuaBiScroller[viewer]; uiData.innerViewer _ BiScrollers.QuaViewer[bs: uiData.bs, inner: TRUE]; uiData.outerViewer _ BiScrollers.QuaViewer[bs: uiData.bs, inner: FALSE]; savedCursor _ uiData.innerViewer.class.cursor; }; DestroyUserInput: PUBLIC ENTRY PROC [uiData: SilUIData] = { QuitGridding[uiData]; uiData.innerViewer _ NIL; uiData.outerViewer _ NIL; }; SilNotify: PUBLIC ViewerClasses.NotifyProc = { mx, my: INTEGER _ 0; --for saving mouse coordinates. data: SilData _ NARROW[BiScrollers.QuaBiScroller[self].ClientDataOf[]]; uiData: SilUIData _ data.uiData; FOR list: LIST OF REF ANY _ input, list.rest WHILE list # NIL DO WITH list.first SELECT FROM z: BiScrollers.ClientCoords => { [mx, my] _ GridTheCursor[self, uiData, z]; }; C: REF CHAR => RouteInputChars[C^, uiData]; A: ATOM => { SELECT A FROM $Exit => QuitGridding[uiData]; $TrackMouse => Enque[ [TrackMouse[x: mx, y: my] ], uiData]; $MoveMark => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [SetCaret[caret: mark, mode: absolute, x: mx, y: my] ], uiData]; Enque[ [TrackMouse[x: mx, y: my] ], uiData]; }; $MoveStretch => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [OperateOnSelected[op: IF silCursorHasBitmap THEN moveNoStretch ELSE moveStretch, rel: absolute, x: mx, y: my] ], uiData]; Enque[ [TrackMouse[x: mx, y: my] ], uiData]; }; $MoveNoStretch => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [OperateOnSelected[op: moveNoStretch, rel: absolute, x: mx, y: my] ], uiData]; Enque[ [TrackMouse[x: mx, y: my] ], uiData]; }; $MoveOrigin => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [SetCaret[caret: origin, mode: absolute, x: mx, y: my] ], uiData]; Enque[ [TrackMouse[x: mx, y: my] ], uiData]; }; $DrawLine => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [DrawBox[markRel: absolute, originRel: relative, x: mx, y: my] ], uiData]; }; $DeleteObject => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [SelectWithPos[x: mx, y: my, mode: delete] ], uiData]; }; $Copy => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [OperateOnSelected[op: copy, rel: absolute, x: mx, y: my] ], uiData]; }; $Undelete => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [Undelete[] ], uiData]; }; $SelectObject => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [SelectWithPos[x: mx, y: my] ], uiData]; }; $AddSelected => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [SelectWithPos[x: mx, y: my, mode: add] ], uiData]; }; $SelectArea => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [SelectWithPos[x: mx, y: my, mode: relative] ], uiData]; }; $DeselectObject => { IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ESC, uiData]; Enque[ [SelectWithPos[x: mx, y: my, mode: remove] ], uiData]; }; $DrawBox => Enque[ [DrawBox[markRel: absolute, originRel: absolute] ], uiData]; $DrawBackBox => Enque[ [DrawBox[markRel: absolute, originRel: absolute, background: TRUE] ], uiData]; $CopySelected => Enque[ [OperateOnSelected[op: copy, rel: relative] ], uiData]; $DeleteSelected => Enque[ [OperateOnSelected[op: delete] ], uiData]; $CenterOnMark => Enque[ [CenterOnMark[] ], uiData]; $ComplimentMagnify => Enque[ [Compliment[mode: magnification] ], uiData]; $SetDefault => { uiData.mode _ waitingFor1CharArg; uiData.InputWaitingForArg _ LIST[ [SetDefaultAttribs[]] ]; MessageWindow.Append["Attribute which is to be default: ", TRUE]; }; $SetGrid => { uiData.mode _ waitingFor1CharArg; uiData.InputWaitingForArg _ LIST[ [SetDetails[detail: gridSize]] ]; MessageWindow.Append["Exponent for new grid size (0-9): ", TRUE]; }; $InputFile => Enque[ [InputFile[mode: absolute] ], uiData]; $InputFileRelative => Enque[ [InputFile[mode: relative] ], uiData]; $Jam => { uiData.mode _ waitingFor1CharArg; uiData.InputWaitingForArg _ LIST[ [ChangeSelected[]] ]; MessageWindow.Append["Attribute by which to change selection: ", TRUE]; }; $Kill => Enque[ [KillPicture[] ], uiData]; $DefineMacro => { uiData.mode _ waitingFor1CharArg; uiData.InputWaitingForArg _ LIST[ [ManipulateMacro[mode: define]] ]; MessageWindow.Append["Name for new macro: ", TRUE]; }; $ComplimentOneLevel => Enque[ [Compliment[mode: oneLevel] ], uiData]; $OutputFile => Enque[ [StoreFile[clip: TRUE, large: FALSE] ], uiData]; $OutputFileUnclipped => Enque[ [StoreFile[clip: FALSE, large: FALSE] ], uiData]; $PutFile => Enque[ [StoreFile[clip: FALSE, large: TRUE] ], uiData]; $DeleteMacros => Enque[ [ManipulateMacro[mode: clear] ], uiData]; $ShowTics => Enque[ [Compliment[mode: tics] ], uiData]; $ShowFrames => Enque[ [Compliment[mode: frames] ], uiData]; $View => { uiData.mode _ waitingFor1CharArg; uiData.InputWaitingForArg _ LIST[ [ShowMacros[]] ]; MessageWindow.Append["Font for macro description or attribute for selection: ", TRUE]; }; $ReduceSelection => { uiData.mode _ waitingFor1CharArg; uiData.InputWaitingForArg _ LIST[ [SelectForAttrib[mode: reduce]] ]; MessageWindow.Append["Attribute to which to reduce selection: ", TRUE]; }; $MoveRelativeStretch => { Enque[ [OperateOnSelected[op: IF silCursorHasBitmap THEN moveNoStretch ELSE moveStretch, rel: relative, x: mx, y: my] ], uiData]; }; $MoveRelativeNoStretch => { Enque[ [OperateOnSelected[op: moveNoStretch, rel: relative, x: mx, y: my] ], uiData]; }; $Ylock => Enque[ [Compliment[mode: yInc] ], uiData]; $Hardcopy => { uiData.mode _ waitingFor1CharArg; uiData.InputWaitingForArg _ LIST[ [HardCopy[]] ]; MessageWindow.Append["Hardcopy Device: Type ", TRUE]; MessageWindow.Append["R,H,M,U,C for IP file (H for Stinger); P for Press file)", FALSE]; }; $ControlA => IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ControlA, uiData] ELSE Enque[ [SwapFonts[] ], uiData]; $ControlH => IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ControlA, uiData] ELSE { uiData.mode _ waitingFor1CharArg; uiData.InputWaitingForArg _ LIST[ [ManipulateMacro[mode: expand]] ]; MessageWindow.Append["Name for macro to be expanded: ", TRUE]; }; $ControlQ => IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ControlQ, uiData] ELSE MessageWindow.Append["Use viewer Destroy button to Quit", TRUE]; $ControlW => IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ControlW, uiData] ELSE { uiData.mode _ waitingFor1CharArg; uiData.InputWaitingForArg _ LIST[ [SetDetails[detail: boxWidth]] ]; MessageWindow.Append["New line width (1-9): ", TRUE]; }; $ControlS => IF uiData.mode = InputingRope THEN RouteInputChars[Ascii.ControlS, uiData] ELSE { Enque[ [SetCursor[caret: origin] ], uiData]; silCursorHasBitmap _ TRUE; }; $Del => RouteInputChars[Ascii.DEL, uiData]; $Escape => RouteInputChars[Ascii.ESC, uiData]; $Return => SELECT uiData.mode FROM InputingRope => RouteInputChars[Ascii.CR, uiData] ENDCASE => Enque[ [SetCaret[caret: mark, mode: relative] ], uiData]; $Backspace => RouteInputChars[Ascii.BS, uiData]; ENDCASE => NULL; restoreCursor _ SELECT A FROM $TrackMouse, $ControlS, $MoveMark, $MoveStretch, $MoveNoStretch, $MoveOrigin, $Copy, $CopySelected, $ShowTics, $MoveRelativeStretch, $MoveRelativeNoStretch => FALSE, ENDCASE => TRUE; }; ENDCASE => ERROR; IF silCursorHasBitmap AND restoreCursor THEN TRUSTED { Cursors.SetCursor[blank]; -- clear special cursor bits Cursors.SetCursor[savedCursor]; -- restore normal cursor Interminal.SetCursorOffset[deltaX: 0, deltaY: 0, enableTracking: FALSE]; -- and disable automatic tracking !!!! silCursorHasBitmap _ FALSE; }; ENDLOOP; }; SilModifyInputFocus: PUBLIC ViewerClasses.ModifyProc = { data: SilData _ NARROW[BiScrollers.QuaBiScroller[self].ClientDataOf[]]; uiData: SilUIData _ data.uiData; SELECT change FROM kill, push => { uiData.gotInputFocus _ FALSE; SilHasInputFocus _ FALSE; }; set, pop => { uiData.gotInputFocus _ TRUE; SilHasInputFocus _ TRUE; }; ENDCASE; }; GetInputFocus: PUBLIC ENTRY PROC[uiData: SilUIData] = { IF NOT uiData.gotInputFocus THEN InputFocus.SetInputFocus[uiData.innerViewer]; }; HasInputFocus: PUBLIC PROC[] RETURNS [hasIt: BOOL] = { RETURN[SilHasInputFocus]; }; Enque: PUBLIC PROC [UI: UInputRec, uiData: SilUIData] = { EnqueWithList[LIST[UI], uiData]; }; EnqueWithList: ENTRY PROC [UIL: UInput, uiData: SilUIData] = { ENABLE UNWIND => NULL; IF uiData.queue = NIL THEN uiData.queue _ UIL ELSE FOR q: UInput _ uiData.queue, q.rest WHILE q # NIL DO IF q.rest = NIL THEN { q.rest _ UIL; EXIT; }; ENDLOOP; NOTIFY uiData.gotInput; }; Deque: PUBLIC ENTRY PROC [uiData: SilUIData] RETURNS [UInputRec] = { ENABLE UNWIND => NULL; UI: UInputRec _ uiData.queue.first; uiData.queue _ uiData.queue.rest; RETURN [UI]; }; InputAvailable: PUBLIC ENTRY PROC [uiData: SilUIData] RETURNS [yes: BOOL] = { ENABLE UNWIND => NULL; RETURN[uiData.queue # NIL]; }; SetCaretChange: PUBLIC ENTRY PROC [uiData: SilUIData] = { ENABLE UNWIND => NULL; uiData.caretsShouldChangeNow _ TRUE; NOTIFY uiData.gotInput; }; CaretHasChanged: PUBLIC ENTRY PROC [uiData: SilUIData] = { ENABLE UNWIND => NULL; uiData.caretsShouldChangeNow _ FALSE; }; ShouldChangeCaret: PUBLIC ENTRY PROC [uiData: SilUIData] RETURNS [changeIt: BOOL] = { ENABLE UNWIND => NULL; RETURN[uiData.caretsShouldChangeNow]; }; AwaitUserInput: PUBLIC ENTRY PROC [uiData: SilUIData] = { ENABLE UNWIND => NULL; WAIT uiData.gotInput; }; GridTheCursor: PROC [innerViewer: ViewerClasses.Viewer, uiData: SilUIData, cc: BiScrollers.ClientCoords] RETURNS [mx, my: INTEGER _ 0] = TRUSTED { Grid: PROC [raw, grid: INTEGER] RETURNS [gridded: INTEGER] = CHECKED { rem: INTEGER _ raw MOD grid; IF rem >= grid/2 THEN rem _ rem - grid; gridded _ raw - rem}; gridSpacing: NAT _ uiData.gridSpacing * uiData.gridMagnification; viewerPos: Geom2D.Vec; sx, sy: INTEGER; mx _ Real.RoundI[cc.x]; my _ Real.RoundI[cc.y]; IF NOT uiData.gridding THEN { [uiData.hotX, uiData.hotY, ] _ Interminal.GetCursorOffset[]; uiData.gridding _ TRUE; uiData.bs.style.SetButtonsCapturedness[uiData.bs, TRUE]; Interminal.SetCursorOffset[0, 0, FALSE]; }; mx _ Grid[mx - uiData.xPostOffset, gridSpacing] + uiData.xPostOffset; my _ Grid[my - uiData.yPostOffset, gridSpacing] + uiData.yPostOffset; viewerPos _ uiData.bs.style.GetTransforms[uiData.bs].clientToViewer.Transform[[mx, my]]; [sx, sy] _ ViewerOps.UserToScreenCoords[innerViewer, Real.RoundI[viewerPos.x], Real.RoundI[viewerPos.y]]; IF innerViewer.column#color THEN { sy _ terminal.bwHeight - sy; Terminal.SetBWCursorPosition[terminal, [sx + uiData.hotX, sy + uiData.hotY]]; } ELSE { sy _ terminal.colorHeight - sy; Terminal.SetColorCursorPosition[terminal, [sx + uiData.hotX, sy + uiData.hotY]]; }; }; QuitGridding: PROC [uiData: SilUIData] = TRUSTED { uiData.gridding _ FALSE; uiData.bs.style.SetButtonsCapturedness[uiData.bs, FALSE]; Interminal.SetCursorOffset[uiData.hotX, uiData.hotY, TRUE]; --reset remembered offset }; ChangeGridInterval: PUBLIC ENTRY PROC [uiData: SilUIData, gridSpacing: NAT] = { ENABLE UNWIND => NULL; uiData.gridSpacing _ gridSpacing; }; MagnifyGrid: PUBLIC ENTRY PROC [uiData: SilUIData, xOffset, yOffset: REAL, magnification: NAT] = { ENABLE UNWIND => NULL; uiData.xOffset _ xOffset; uiData.yOffset _ yOffset; uiData.gridMagnification _ magnification; uiData.xPostOffset _ Real.RoundI[xOffset * magnification]; uiData.yPostOffset _ Real.RoundI[yOffset * -magnification]; }; NotInputingRope: PUBLIC ENTRY PROC [uiData: SilUIData] = { ENABLE UNWIND => NULL; uiData.mode _ NotInputingRope; }; InputingRope: PUBLIC ENTRY PROC [uiData: SilUIData] = { ENABLE UNWIND => NULL; uiData.mode _ InputingRope; }; RouteInputChars: PROC [c: CHAR, uiData: SilUIData] = { SELECT uiData.mode FROM NotInputingRope, InputingRope => Enque[ [UserChar[c] ], uiData]; waitingFor1CharArg => { TRUSTED { WITH temp: uiData.InputWaitingForArg.first SELECT FROM ChangeSelected => temp.char _ c; HardCopy => temp.char _ c; ManipulateMacro => temp.char _ c; SelectForAttrib => temp.char _ c; SetDefaultAttribs => temp.char _ c; SetDetails => temp.char _ c; ShowMacros => SELECT c FROM '4, '5, '6, '7, '8, '9 => temp.char _ c; ENDCASE => uiData.InputWaitingForArg _ LIST[ [SelectForAttrib[mode: change, char: c]] ]; ENDCASE; }; uiData.mode _ NotInputingRope; IF c IN SilFile.PrintingChars THEN EnqueWithList[uiData.InputWaitingForArg, uiData]; uiData.InputWaitingForArg _ NIL; }; waitingForConfirmation => NULL; ENDCASE; }; GetBiScroller: PUBLIC PROC [uiData: SilUIData] RETURNS [bs: BiScrollers.BiScroller] = {bs _ uiData.bs}; END. ΊSilUserInputImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Tracy Larrabee, April 23, 1984 5:43:05 pm PST Last Edited by: Ken Pier, May 7, 1986 10:14:59 am PDT This module implements procedures needed for User Input retreival and inventory: things that handle input from Viewers (including placement of the input focus), deal with TIPTables, query and append to the Sil UserAction queue, and grid the cursor. The way that user input works: Actions by the user will cause one or more User Input Records (UInputRec - defined below) to be placed on the User Input Queue (UInput - defined below). The display module will take the records off, whenever it has an opportunity to do so, and process them. This is the concrete representation of an opaque type defined in SilKernel. The SilUIDataRec contains all the state that the User Input module needs to operate (the input queue, the cursor gridding details, the current mode). Information about the state of this viewer and its input Information for gridding the cursor: see GridTheCursor for explanation of the need for each field. Transform from Sil coordinates to Client coordinates: Client Coords = (Sil Coords + offset) * scale xScale = gridMagnification, yScale = - gridMagnification, Client Coords = Sil Coords * scale + postOffset Information for correctly interpretting control characters: in text input mode ^W is backup word - else it is change line width. GLOBAL VARIABLES: only 1 tip table for all sil instances Only 1 virtual terminal for all sil instances Only1 input focus for all sil instances Only1 sil cursor for all sil instances Set the tip table so it can be referenced later on. Also set up the virtual terminal Initialize all the state needed to process user input Perform necessary actions for the destruction of this user input. [self: Viewer, input: LIST OF REF ANY] The notify proc which the viewers package will be asked to call. This process will be placing user input records on the user input queue. IF NOT uiData.gridding THEN RETURN; What happens when mouse leaves BiScroller client TIPtable: Tracking the mouse for the command line: Sil MARK buttons (they cause the mouse to track for the command line) Sil DRAW buttons Sil SELECT buttons Sil Control characters $Help => -- HELP FEATURE DISABLED. SIL Help.sil gets desired effect. data.createHelpWindow _ TRUE; [self: Viewer, change: ModifyAction] Call me when the user input focus changes. Make sure that we have the input Focus. Do we have the input Focus? Enque the user input so that it can be processed sequentially with all the other user inputs. Does a notify on gotInput. Enque the user input so that it can be processed sequentially with all the other user inputs. Does a notify on gotInput. Deque a user input so that it can be processed. True if there is user input available, else false. Set the information which will tell the display process to blink the caret. doesn't really matter whether or not it was already on Make uiData reflect the fact that the caret has been blinked. doesn't really matter whether or not it was already on True if the caret should be blinked. Wait until somebody typed something. Make the cursor Grid. This is a pretty low level routine. Modification of this routine is potentially hazardous to your peace of mind. 1st mouse input for viewer: coords will be viewer relative; save Cursor Offset so can reset when we release buttons. Steal input events & keep the cursor from tracking. . . InputFocus.CaptureButtons[SilNotify, silTipTable, viewer]; Perform necessary actions for the destruction of this user input. Change the cursor grid spacing Change the cursor grid spacing Make the cursor gridding reflect the current magnification. Tell the userinput module that Sil is no longer in Rope Editing Mode. Tell the userinput module that Sil is now in Rope Editing Mode. Only show macros if char was macro font ELSE select all items of given attribute Only printing characters are appropriate here. Κ‘˜code™Kšœ Οmœ1™<—K™-K™5K™K™ωK™K™’K™šΟk ˜ šœž˜ Kš œžœ*žœžœžœ˜;—Kšœ žœD˜Ušœž˜ K˜—šœž˜Kšœ ˜ —šœ ž˜K˜—šœ ž˜K˜#—šœž˜Kšœ ˜ —Kšœžœ ˜šœž˜ Kšœžœ˜—šœ ž˜K˜J—šœžœ˜Kšœ˜—šœžœ˜Kšœ!˜!—šœ žœ˜Kšœ˜—šœž˜ K˜—K˜ K˜ K˜Kšœ˜—K˜š œžœžœžœžœ˜DKšžœn˜uKšžœž˜'—K˜Kšžœžœžœ˜Kšœ žœ˜"Kšœžœ˜#Kšœ žœ˜)Kšœžœ˜0˜K™β—Kšœ žœžœ˜#š œžœžœž œžœ˜.K™8Kšœžœ˜Kšœ ž œ˜Kšœ#Οc)˜LKšœ"˜"K˜Kšœžœžœ˜Kšœžœžœ˜$Kšœc™cKšœ žœ#˜3Kšœ žœžœŸ3˜KKšœžœ˜Kšœžœ˜™5K™-Kšœ™Kšœ™—šœžœ˜K™/—Kšœžœ˜&Kšœžœ˜K™;K™DKšœ3˜3Kšœž˜ Kšœ˜K˜—K˜šΟb™Kš &™&—šœ˜Kš -™-—˜Kš '™'—šœžœ˜Kš &™&—KšœžœžœŸ˜4KšœžœžœŸ˜;Kšœ/Ÿ%˜TK˜šΟn œžœžœ!˜:K™TK™K˜K˜K˜K˜—š‘ œžœžœ3˜MK™5K™Kšœ"žœ˜4Kšœ.˜.KšœAžœ˜GKšœAžœ˜HKšœ.˜.K˜K˜—š‘œžœžœžœ˜;K™AK™Kšœ˜Kšœžœ˜Kšœžœ˜K˜K˜—š‘ œžœ˜.KšΟi±™±K™Kšœž œŸ˜4Kšœžœ1˜GKšœ ˜ K˜šžœžœžœžœžœžœžœž˜@šžœ žœž˜˜!K˜*Kšžœžœžœžœ™#K˜—Kšžœžœžœžœ ˜,šžœžœ˜ Kšžœžœž˜ —™:šœ˜Kšœ˜——šœ(™(šœ˜Kšœ,˜,——šœΠblœ=™E˜šžœž˜"Kšœžœ ˜#—KšœG˜GKšœ,˜,K˜—šœ˜šžœž˜"Kšœžœ ˜#—Kšœžœžœžœ6˜Kšœ,˜,K˜—šœ˜šžœž˜"Kšœžœ ˜#—KšœU˜UKšœ,˜,K˜—šœ˜šžœž˜"Kšœžœ ˜#—KšœI˜IKšœ,˜,K˜—Kšœ£œ™šœ˜šžœž˜"Kšœžœ ˜#—KšœQ˜QK˜—šœ˜šžœž˜"Kšœžœ ˜#—Kšœ=˜=K˜—šœ ˜ šžœž˜"Kšœžœ ˜#—KšœL˜LK˜—šœ˜šžœž˜"Kšœžœ ˜#—Kšœ˜K˜—Kšœ£œ™šœ˜šžœž˜"Kšœžœ ˜#—Kšœ/˜/K˜—šœ˜šžœž˜"Kšœžœ ˜#—Kšœ:˜:K˜—šœ˜šžœž˜"Kšœžœ ˜#—Kšœ?˜?K˜—šœ˜šžœž˜"Kšœžœ ˜#—Kšœ=˜=K˜Kšœ£ œ ™—˜ KšœC˜C—˜KšœDžœ ˜U—˜Kšœ>˜>—˜Kšœ1˜1—šœ˜Kšœ"˜"—˜Kšœ œ˜3—šœ˜Kšœ!˜!Kšœžœ˜:Kšœ;žœ˜AK˜—šœ ˜ Kšœ!˜!Kšœžœ#˜CKšœ;žœ˜AK˜—šœ ˜ Kšœ-˜-—šœ˜Kšœ-˜-—šœ ˜ Kšœ!˜!Kšœžœ˜7KšœAžœ˜GK˜—˜Kšœ!˜!—šœ˜Kšœ!˜!Kšœžœ$˜DKšœ-žœ˜3K˜—˜Kšœ œ˜.—šœ˜Kšœžœ žœ ˜7—šœ˜Kšœžœ žœ ˜8—šœ ˜ Kšœžœ žœ ˜7—˜Kšœ0˜0—˜ Kšœ œ˜*—˜Kšœ œ˜,—šœ ˜ Kšœ!˜!Kšœžœ˜3KšœPžœ˜VK˜—šœ˜Kšœ!˜!Kšœžœ$˜DKšœAžœ˜GK˜—˜Kšœžœžœžœ6˜K˜—˜KšœU˜UK˜—˜ Kšœ œ˜*—šœ˜Kšœ!˜!Kšœžœ˜1Kšœ/žœ˜5KšœQžœ˜XK˜—šœE™EKšœžœ™—šœ ˜ šžœž˜"Kšœ'˜'—Kšžœ ˜$—šœ ˜ šžœž˜"Kšœ'˜'—šžœ˜Kšœ!˜!Kšœžœ$˜DKšœ8žœ˜>K˜——šœ ˜ šžœž˜"Kšœ'˜'—Kšžœ<žœ˜F—šœ ˜ šžœž˜"Kšœ'˜'—šžœ˜Kšœ!˜!Kšœžœ#˜CKšœ/žœ˜5K˜——šœ ˜ šžœž˜"Kšœ'˜'—šžœ˜Kšœ,˜,Kšœžœ˜K˜——šœ˜Kšœžœ ˜#—šœ ˜ Kšœžœ ˜#—šœ žœ ž˜"šœ˜Kšœžœ ˜!—šžœ˜ Kšœ9˜9——šœ ˜ Kšœžœ ˜"—Kšžœžœ˜šœžœžœž˜KšœŸžœ˜₯Kšžœžœ˜—K˜—Kšžœžœ˜—šžœžœžœžœ˜6KšœŸ˜6Kšœ Ÿ˜8KšœAžœŸ&˜oKšœžœ˜K˜—Kšžœ˜—K˜K™—š‘œžœ˜8Kšœ%™%K™*K™Kšœžœ1˜GKšœ ˜ šžœž˜šœ˜Kšœžœ˜Kšœžœ˜K˜—šœ ˜ Kšœžœ˜Kšœžœ˜K˜—Kšžœ˜—Kšœ˜K˜—š‘ œžœž œ˜7K™'Kšžœžœžœ.˜NKšœ˜K˜—š ‘ œžœžœžœ žœ˜6K™Kšžœ˜Kšœ˜K˜—š‘œžœžœžœ#˜9K™]K™Kšœžœžœ ˜ K˜K˜—š‘ œžœžœžœ ˜>K™]K™K™šžœžœžœ˜Kšžœžœžœž˜-šžœ˜šžœ"žœžœž˜5šžœ žœžœ˜Kšœ žœ˜ Kšžœ˜K˜—Kšžœ˜——Kšžœ˜—K˜K˜—š ‘œžœžœžœžœ˜DK™0K™šžœžœžœ˜Kšžœ!˜#Kšœ!˜!Kšžœžœ˜ —K˜K˜—š ‘œžœžœžœžœžœ˜MK™2šžœžœžœ˜Kšžœžœ˜—K˜K˜—š‘œžœžœžœ˜9K™KK™šžœžœžœ˜Kšœ6™6Kšœžœ˜$Kšžœ˜—Kšœ˜K˜—š‘œžœžœžœ˜:K™=šžœžœžœ˜Kšœ6™6Kšœžœ˜%—K˜K˜—š ‘œžœžœžœžœ žœ˜UK™$šžœžœžœ˜Kšžœ˜%—K˜K˜—š‘œžœžœžœ˜9K™$šžœžœžœ˜Kšžœ˜—K˜K˜—š ‘ œžœUžœ žœžœ˜’K™‡K™š ‘œžœ žœžœ žœžœ˜FKšœžœžœ˜Kšžœžœ˜'K˜—Kšœ žœ1˜AK˜Kšœžœ˜K˜K˜K™šžœžœžœ˜Kšœt™tKšœ<˜