DIRECTORY ClassIncreek USING [Acceptance, ActionBody, ActionKind, CopyIncreek, GetAction, GetPositionFrom, GetTime, Increek, NewStdIncreek, SetMouseGrain, ViewPosition], RefTab USING [Fetch], Inline USING [BITAND], Interminal USING [KeyName, KeyState, MousePosition, updown], Process USING [Abort], TIPPrivate USING [predTable], TIPTables USING [IgnoreBits, IgnoreEverything, TIPScreenCoords, TIPScreenCoordsRec, TIPChoiceSeries, TIPChoice, TIPKeyState], TIPUser USING [stdChar, stdCoords, stdTime, TIPClient, TIPNotifyProc, TIPParseInfo, TIPPredicate, TIPTable]; TIPMatcher: PROGRAM IMPORTS ClassIncreek, Inline, Process, RefTab, TIPPrivate, TIPUser EXPORTS TIPUser SHARES TIPUser = BEGIN OPEN TIPTables, TIPUser, TIPPrivate; mouseGrainCreek: ClassIncreek.Increek _ ClassIncreek.NewStdIncreek[]; -- only for setting recording grain TransparentTIPTable: PUBLIC SAFE PROC RETURNS [table: TIPTable] = CHECKED {RETURN[transparentTIPTable]}; transparentTIPTable: TIPTable = LOOPHOLE[$transparentTIPTable]; ResetTIPContext: PUBLIC SAFE PROC [user: TIPClient, table: TIPTable, notify: TIPNotifyProc, interrupt: BOOLEAN _ FALSE] = TRUSTED BEGIN user.parseInfo.tableHead _ table; user.notifyProc _ notify; ClassIncreek.SetMouseGrain[mouseGrainCreek, IF table=NIL THEN 50 ELSE table.mouseTicks, 1]; IF interrupt THEN Process.Abort[user.matcher]; END; MatchProcess: PUBLIC SAFE PROCEDURE [user: TIPClient] = TRUSTED BEGIN creekAction: ClassIncreek.ActionBody; results: LIST OF REF ANY; privateTSC: TIPScreenCoords _ NEW[TIPScreenCoordsRec _ [0, FALSE, 0]]; userTSC: TIPScreenCoords _ NEW[TIPScreenCoordsRec]; UNTIL user.matcher=NIL DO -- until TIP client instance is flushed... ENABLE ABORTED => LOOP; ClassIncreek.CopyIncreek[user.parseInfo.localCreek, user.parseInfo.inCreek]; creekAction _ ClassIncreek.GetAction[self: user.parseInfo.inCreek, waitMode: forever, acceptance: clicksAndMotion]; IF user.buttonProc#NIL THEN WITH action: creekAction SELECT FROM mousePosition, deltaMouse => BEGIN userTSC^ _ privateTSC^ _ ClassIncreek.GetPositionFrom[user.parseInfo.inCreek].mousePosition; IF user.buttonProc[userTSC, motion, user.parseInfo.localCreek] THEN BEGIN [] _ ClassIncreek.CopyIncreek[user.parseInfo.inCreek, user.parseInfo.localCreek]; LOOP; END; END; keyUp => SELECT action.value FROM Red, Yellow, Blue => BEGIN userTSC^ _ privateTSC^; IF user.buttonProc[userTSC, buttonUp, user.parseInfo.localCreek] THEN BEGIN [] _ ClassIncreek.CopyIncreek[user.parseInfo.inCreek, user.parseInfo.localCreek]; LOOP; END; END; ENDCASE; keyDown => SELECT action.value FROM Red, Yellow, Blue => BEGIN userTSC^ _ privateTSC^; IF user.buttonProc[userTSC, buttonDown, user.parseInfo.localCreek] THEN BEGIN [] _ ClassIncreek.CopyIncreek[user.parseInfo.inCreek, user.parseInfo.localCreek]; LOOP; END; END; ENDCASE; ENDCASE; IF user.parseInfo.tableHead#NIL THEN WITH action: creekAction SELECT FROM mousePosition, deltaMouse, keyUp, keyDown => results _ MatchEvent[user.parseInfo, creekAction]; ENDCASE => ERROR; -- unexpected ActionKind IF results#NIL THEN user.notifyProc[results]; ENDLOOP; END; ParseOneEvent: PUBLIC SAFE PROC [parseInfo: TIPParseInfo] RETURNS [result: LIST OF REF ANY] = TRUSTED {RETURN[MatchEvent[parseInfo, ClassIncreek.GetAction[self: parseInfo.inCreek, waitMode: forever, acceptance: clicksAndMotion]]]}; MatchEvent: PROCEDURE [parseInfo: TIPParseInfo, creekAction: ClassIncreek.ActionBody] RETURNS [result: LIST OF REF ANY _ NIL] = BEGIN OPEN ClassIncreek; increek: Increek; increekAction: ActionBody; firstAccess, copied: BOOLEAN; advanced: BOOLEAN; stackPointer: CARDINAL; ClearIncreekStack: PROC[] = INLINE BEGIN stackPointer _ 0; END; PushIncreek: PROC[] = INLINE BEGIN CopyIncreek[parseInfo.creekStack[stackPointer], increek]; stackPointer _ stackPointer + 1; advanced _ FALSE; END; CopyTopIncreek: PROC = INLINE BEGIN IF advanced THEN BEGIN CopyIncreek[increek, parseInfo.creekStack[stackPointer]]; advanced _ FALSE; END; END; PopIncreek: PROC = INLINE BEGIN stackPointer _ stackPointer - 1; END; GetIncreekAction: PROC [acceptance: ClassIncreek.Acceptance _ clicks] = INLINE BEGIN IF firstAccess THEN BEGIN firstAccess _ FALSE; increek _ parseInfo.inCreek; increekAction _ creekAction; -- the parameter of MatchEvent copied _ FALSE; END ELSE BEGIN IF ~copied THEN BEGIN copied _ TRUE; CopyIncreek[parseInfo.localCreek, parseInfo.inCreek]; increek _ parseInfo.localCreek; END; increekAction _ GetAction[self: increek, waitMode: forever, acceptance: acceptance]; advanced _ TRUE; END; END; MatchChoice: PROCEDURE [choice: TIPChoice] RETURNS [result: LIST OF REF ANY _ NIL] = BEGIN valid: BOOLEAN _ TRUE; -- go ahead, you're about to match an event FOR terms: TIPChoice _ choice, terms.rest UNTIL ~valid OR terms=NIL DO WITH term: terms.first SELECT FROM keyTrigger => BEGIN GetIncreekAction[clicks]; valid _ WITH ca: increekAction SELECT FROM keyDown => (term.keyState.key=ca.value AND term.keyState.state=down), keyUp => (term.keyState.key=ca.value AND term.keyState.state=up), ENDCASE => FALSE; -- suprise action from Increek END; mouseTrigger => BEGIN GetIncreekAction[clicksAndMotion]; valid _ WITH increekAction SELECT FROM mousePosition => TRUE, deltaMouse => TRUE, ENDCASE => FALSE; END; timeTrigger => BEGIN IF firstAccess THEN ERROR; -- time events can't be first CopyIncreek[parseInfo.timeCreek, increek]; increekAction _ GetAction[self: parseInfo.timeCreek, waitMode: timed, waitInterval: term.mSecs, acceptance: clicks]; valid _ WITH ca: increekAction SELECT FROM timedOut => term.flavor=gt, ENDCASE => term.flavor=lt; END; keyEnable => BEGIN creekKeyState: Interminal.KeyState _ GetPositionFrom[increek].keyState; valid _ (term.keyState.state = creekKeyState.bits[term.keyState.key]); END; key2Enable => BEGIN creekKeyState: Interminal.KeyState _ GetPositionFrom[increek].keyState; valid _ (term.keyState1.state = creekKeyState.bits[term.keyState1.key]) OR (term.keyState2.state = creekKeyState.bits[term.keyState2.key]); END; keyEnableList => BEGIN creekKeyState: Interminal.KeyState _ GetPositionFrom[increek].keyState; valid _ FALSE; FOR lst: LIST OF TIPKeyState _ term.lst, lst.rest UNTIL lst=NIL DO IF lst.first.state = creekKeyState.bits[lst.first.key] THEN { valid _ TRUE; EXIT }; ENDLOOP; END; predEnable => BEGIN predRef: REF; found: BOOLEAN; predicate: REF TIPUser.TIPPredicate; [found, predRef] _ RefTab.Fetch[predTable, term.predicate]; IF found THEN { predicate _ NARROW[predRef]; valid _ predicate^[] } ELSE { valid _ FALSE }; END; char => stdChar^ _ AsciiAction[increek, increekAction]; coords => BEGIN stdCoords^ _ GetPositionFrom[increek].mousePosition; END; time => BEGIN stdTime^ _ GetTime[increek]; END; nested => BEGIN PushIncreek[]; FOR choices: TIPChoiceSeries _ term.statement, choices.rest UNTIL choices=NIL DO result _ MatchChoice[choices.first]; IF result#NIL THEN RETURN[result]; CopyTopIncreek[]; ENDLOOP; PopIncreek[]; valid _ FALSE; END; result => BEGIN IF copied THEN CopyIncreek[parseInfo.inCreek, increek]; RETURN[term.list]; END; ENDCASE => ERROR; ENDLOOP; END; -- MatchChoice actionKind: ActionKind _ creekAction.kind; IF parseInfo.tableHead=transparentTIPTable THEN BEGIN -- just pass creek and action through result _ LIST[parseInfo.inCreek, NEW[ClassIncreek.ActionBody _ creekAction]]; RETURN; END; FOR table: TIPTable _ parseInfo.tableHead, IF table.opaque THEN NIL ELSE table.link UNTIL table=NIL DO SELECT actionKind FROM -- for efficiency mousePosition => IF table.ignore.move THEN LOOP; deltaMouse => IF table.ignore.move THEN LOOP; keyDown => IF table.ignore.down THEN LOOP; keyUp => IF table.ignore.up THEN LOOP; ENDCASE; firstAccess _ TRUE; ClearIncreekStack[]; WITH t: table SELECT FROM fast => BEGIN GetIncreekAction[]; WITH action: increekAction SELECT FROM mousePosition => result _ MatchChoice[t.mouse]; deltaMouse => result _ MatchChoice[t.mouse]; keyUp => result _ MatchChoice[t.keyUp[action.value]]; keyDown => result _ MatchChoice[t.keyDown[action.value]]; ENDCASE; IF result#NIL THEN RETURN[result]; END; small => BEGIN FOR choices: TIPChoiceSeries _ t.all, choices.rest UNTIL choices=NIL DO result _ MatchChoice[choices.first]; IF result#NIL THEN RETURN[result]; firstAccess _ TRUE; ClearIncreekStack[]; ENDLOOP; END; ENDCASE; ENDLOOP; END; AsciiAction: PROCEDURE [inCreek: ClassIncreek.Increek, creekAction: ClassIncreek.ActionBody] RETURNS [c: CHARACTER] = BEGIN p: ClassIncreek.ViewPosition = ClassIncreek.GetPositionFrom[inCreek]; WITH action: creekAction SELECT FROM keyDown => BEGIN OPEN keyNames: p.keyState.keyNames; kI: KeyItem = KeyTable[action.value]; cC: CARDINAL _ kI.NormalCode; IF cC = 0 THEN ERROR; -- not a character SELECT Interminal.updown[down] FROM keyNames.Ctrl => cC _ Inline.BITAND[cC, 37B]; keyNames.LeftShift, keyNames.RightShift => cC _ kI.ShiftCode; keyNames.Lock => IF kI.Letter THEN cC _ kI.ShiftCode; ENDCASE; IF kI.extendedCharSet THEN cC _ cC+200B; RETURN[LOOPHOLE[cC, CHARACTER]]; END; ENDCASE => ERROR; -- why are they asking for a char? END; KeyItem: TYPE = RECORD [ Letter: BOOLEAN, extendedCharSet: BOOLEAN, ShiftCode: [0..177B], NormalCode: [0..177B]]; KeyTable: ARRAY Interminal.KeyName OF KeyItem = [ -- MEMORY[177033B] Index [0..15] KeyItem[FALSE, FALSE, 0, 0], -- UNUSED KeyItem[FALSE, FALSE, 0, 0], -- UNUSED KeyItem[FALSE, FALSE, 0, 0], -- UNUSED KeyItem[FALSE, FALSE, 0, 0], -- UNUSED KeyItem[FALSE, FALSE, 0, 0], -- UNUSED KeyItem[FALSE, FALSE, 0, 0], -- UNUSED KeyItem[FALSE, FALSE, 0, 0], -- UNUSED KeyItem[FALSE, FALSE, 0, 0], -- UNUSED KeyItem[FALSE, FALSE, 0, 0], -- KeyItemset1 KeyItem[FALSE, FALSE, 0, 0], -- KeyItemset2 KeyItem[FALSE, FALSE, 0, 0], -- KeyItemset3 KeyItem[FALSE, FALSE, 0, 0], -- KeyItemset4 KeyItem[FALSE, FALSE, 0, 0], -- KeyItemset5 KeyItem[FALSE, FALSE, 0, 0], -- Red KeyItem[FALSE, FALSE, 0, 0], -- Blue KeyItem[FALSE, FALSE, 0, 0], -- Yellow KeyItem[FALSE, FALSE, 45B, 65B], -- %,5 KeyItem[FALSE, FALSE, 44B, 64B], -- $,4 KeyItem[FALSE, FALSE, 176B, 66B], -- ~,6 KeyItem[TRUE, FALSE, 105B, 145B], -- E KeyItem[FALSE, FALSE, 46B, 67B], -- &,7 KeyItem[TRUE, FALSE, 104B, 144B], -- D KeyItem[TRUE, FALSE, 125B, 165B], -- U KeyItem[TRUE, FALSE, 126B, 166B], -- V KeyItem[FALSE, FALSE, 51B, 60B], -- ),0 KeyItem[TRUE, FALSE, 113B, 153B], -- K KeyItem[FALSE, FALSE, 30B, 55B], -- `,- KeyItem[TRUE, FALSE, 120B, 160B], -- P KeyItem[FALSE, FALSE, 77B, 57B], -- ?,/ KeyItem[FALSE, FALSE, 174B, 134B], -- |,\ KeyItem[FALSE, FALSE, 12B, 12B], -- LF KeyItem[FALSE, FALSE, 10B, 10B], -- BS KeyItem[FALSE, FALSE, 43B, 63B], -- #,3 KeyItem[FALSE, FALSE, 100B, 62B], -- @,2 KeyItem[TRUE, FALSE, 127B, 167B], -- W KeyItem[TRUE, FALSE, 121B, 161B], -- Q KeyItem[TRUE, FALSE, 123B, 163B], -- S KeyItem[TRUE, FALSE, 101B, 141B], -- A KeyItem[FALSE, FALSE, 50B, 71B], -- (,9 KeyItem[TRUE, FALSE, 111B, 151B], -- I KeyItem[TRUE, FALSE, 130B, 170B], -- X KeyItem[TRUE, FALSE, 117B, 157B], -- O KeyItem[TRUE, FALSE, 114B, 154B], -- L KeyItem[FALSE, FALSE, 74B, 54B], -- <,, KeyItem[FALSE, FALSE, 42B, 47B], -- ",' KeyItem[FALSE, FALSE, 175B, 135B], -- },] KeyItem[FALSE, TRUE, 5B, 2B], -- SPARE2 KeyItem[FALSE, TRUE, 4B, 1B], -- SPARE1 KeyItem[FALSE, FALSE, 41B, 61B], -- !,1 KeyItem[FALSE, FALSE, 33B, 33B], -- ESCAPE KeyItem[FALSE, FALSE, 11B, 11B], -- TAB KeyItem[TRUE, FALSE, 106B, 146B], -- F KeyItem[FALSE, FALSE, 0B, 0B], -- CONTROL KeyItem[TRUE, FALSE, 103B, 143B], -- C KeyItem[TRUE, FALSE, 112B, 152B], -- J KeyItem[TRUE, FALSE, 102B, 142B], -- B KeyItem[TRUE, FALSE, 132B, 172B], -- Z KeyItem[FALSE, FALSE, 0B, 0B], -- SHIFT KeyItem[FALSE, FALSE, 76B, 56B], -- >,. KeyItem[FALSE, FALSE, 72B, 73B], -- :,; KeyItem[FALSE, FALSE, 15B, 15B], -- CR KeyItem[FALSE, FALSE, 136B, 137B], -- ^,_ KeyItem[FALSE, FALSE, 177B, 177B], -- DEL KeyItem[FALSE, FALSE, 0B, 0B], -- NOT USED (FL3) KeyItem[TRUE, FALSE, 122B, 162B], -- R KeyItem[TRUE, FALSE, 124B, 164B], -- T KeyItem[TRUE, FALSE, 107B, 147B], -- G KeyItem[TRUE, FALSE, 131B, 171B], -- Y KeyItem[TRUE, FALSE, 110B, 150B], -- H KeyItem[FALSE, FALSE, 52B, 70B], -- *,8 KeyItem[TRUE, FALSE, 116B, 156B], -- N KeyItem[TRUE, FALSE, 115B, 155B], -- M KeyItem[FALSE, FALSE, 0B, 0B], -- LOCK KeyItem[FALSE, FALSE, 40B, 40B], -- SPACE KeyItem[FALSE, FALSE, 173B, 133B], -- {,[ KeyItem[FALSE, FALSE, 53B, 75B], -- +,= KeyItem[FALSE, FALSE, 0B, 0B], -- SHIFT KeyItem[FALSE, TRUE, 6B, 3B], -- SPARE3 KeyItem[FALSE, FALSE, 0B, 0B], -- NOT USED (FL4) KeyItem[FALSE, FALSE, 0B, 0B]]; -- allUp, synthesized Start: PUBLIC SAFE PROC = CHECKED {}; ClassIncreek.SetMouseGrain[mouseGrainCreek, 100, 1]; END. ²TIPMatcher.mesa; Last Edited by McGregor, June 3, 1983 11:16 am Last Edited by: Maxwell, January 3, 1983 12:06 pm keep two copies of screen coords so that client can overwrite passed copy Aborted is expected to be caught in these two situations: 1) when DestroyClient is called to flush the tip process (inCreek=NIL) 2) InterruptTIP is called to change the table and flush pending state someday should also catch ClassIncreek.IncreekError => flush type-ahead in case ring buffer wraps save away our state for the buttonProc below mouse moves also depend on this! get a top-level action trigger The following special test and dispatch is for Cedar window management. The parseInfo.localCreek contains the Inscript state at the start of the mouse event and is passed to the buttonProc. The buttonProc is required to adjust the passed Increek to reflect the event that gets parsed. If no event was successfully parsed, the buttonProc should return FALSE. the top level parser goes through the list of TIPTables, picks up the relevant ones (the ones not to be ignored), and parses the appropriate entry: tells whether the increek on top of the stack has been changed at all used to eliminate unnecessary copying of increeks unless a second access to the increek actions, MatchEvent deals with parseInfo.inCreek later, parseInfo.localCreek is the increek which to be considered PushIncreek and CopyTopIncreek use parseInfo.localCreek as implicit parameter, assuming that increek, the pointer to the 'interesting' increek, equals localCreek copy local creek for checking time since no "putback" term.ch^ _ AsciiAction[increek, increekAction]; - for the general case - term.xy^ _ [mp.mouseX, mp.mouseY]; - for the general case - term.time^ _ Intime.ReadEventTime[]; - for the general case - MEMORY[177034B] Index [16..31] MEMORY[177035B] Index [32..47] MEMORY[177036B] Index [48..63] MEMORY[177037B] Index [64..79] KeyItem[FALSE, FALSE, 0B, 0B], -- -- NOT USED (FR5) Κ1– "Mesa" style˜JšΟc™Jš.™.J™1J˜šΟk ˜ šœ žœ=˜OJ˜O—Jšœžœ ˜Jšœžœžœ˜Jšœ žœ,˜J˜šžœAž˜GJšž˜˜5J˜—Jšžœ˜Jšžœ˜—Jšžœžœ˜ —Jšžœ˜J˜—š žœžœžœžœžœž˜IJ˜J˜J˜>Jšžœžœ˜*J˜—Jšžœ žœžœ˜-Jšžœ˜—Jšžœ˜J˜—šŸ œžœž œžœ žœžœžœžœ˜]šžœžœF˜UJ˜3J˜——JšS™SJš?™?J˜šŸ œž œ@˜UJšžœ žœžœžœžœžœžœžœ˜BJ˜J˜J˜J˜ Jšœžœ˜J˜Jšœ žœ˜JšE™EJš1™1J˜Jšœžœ˜J˜šŸœžœžœž˜(J˜Jšžœ˜J˜—šŸ œžœžœž˜"˜9J˜ Jšœ žœ˜Jšžœ˜J˜——šŸœžœžœž˜#šžœ žœž˜J˜9Jšœ žœ˜Jšžœ˜—Jšžœ˜J˜—šŸ œžœžœž˜˜ Jšžœ˜J˜———JšV™VJšA™AJšN™NJšR™R˜šŸœžœ2žœž˜Tšžœ žœž˜Jšœžœ˜J˜Jšœ˜;Jšœ žœ˜Jšž˜—šžœžœ˜ šžœ žœž˜Jšœ žœ˜J˜5J˜Jšžœ˜—˜(J˜J˜—Jšœ žœ˜Jšžœ˜—Jšžœ˜J˜—šŸ œž œ˜*Jš žœ žœžœžœžœžœž˜/J˜Jšœžœžœ+˜BJ˜Jš žœ'žœžœžœž˜F˜Jšžœžœž˜"˜šœž˜J˜šœžœžœž˜*šœ'ž˜*J˜—šœ%ž˜(J˜—Jšžœžœ˜0—Jšžœ˜J˜—šœž˜J˜"šœžœžœž˜&Jšœžœ˜Jšœžœ˜Jšžœžœ˜—Jšžœ˜J˜—šœž˜Jšžœ žœžœ˜8Jš5™5J˜*˜4J˜*J˜—šœžœžœž˜*J˜Jšžœ˜—Jšžœ˜J˜—šœ ž˜J˜GJ˜FJšžœ˜J˜—šœž˜J˜G˜GJšžœA˜C—Jšžœ˜J˜—šœž˜J˜GJšœžœ˜š žœžœžœ"žœžœž˜Bšžœ5žœ˜=Jšœžœžœ˜—Jšžœ˜—Jšžœ˜J˜—šœž˜Jšœ žœ˜ Jšœžœ˜Jšœ žœ˜$J˜;šžœžœ˜Jšœ žœ ˜J˜—Jšžœ žœ˜Jšžœ˜J˜—J˜7————JšH™H˜šœ ž˜J˜4——š;™;Jšžœ˜J˜šœž˜ J˜——š=™=Jšžœ˜J˜šœ ž˜J˜Jšžœ8˜;šžœ žœž˜J˜$Jšžœžœžœžœ ˜"J˜Jšžœ˜—J˜ Jšœžœ˜Jšžœ˜J˜—šœ ž˜Jšžœžœ)˜7Jšžœ ˜Jšžœ˜—Jšžœžœ˜J˜Jšžœ˜Jšžœ˜J˜J˜*J˜šžœ)žœžœ%˜[Jšœ žœžœ)˜MJšžœ˜Jšžœ˜J˜—Jš žœ(žœžœžœžœ ˜SJšžœžœž˜˜šžœ žœ˜(Jšœžœžœžœ˜0Jšœžœžœžœ˜.Jšœ žœžœžœ˜+Jšœ žœžœžœ˜'Jšžœ˜J˜—Jšœžœ˜J˜J˜šžœ žœž˜šœž˜ J˜šžœžœž˜&J˜/J˜/J˜=J˜?Jšžœ˜—Jšžœžœžœžœ ˜"Jšžœ˜—šœ ž˜Jšžœ0˜3šžœ žœž˜J˜$Jšžœžœžœžœ ˜"Jšœžœ˜J˜Jšžœ˜—Jšžœ˜—Jšžœ˜—Jšžœ˜—Jšžœ˜J˜—šŸ œž œF˜\Jšžœž œž˜J˜Ešžœžœž˜$šœ žœžœ˜5J˜%Jšœžœ˜Jšžœžœžœ˜(šžœž˜#Jšœžœ ˜-J˜=Jšœžœ žœ˜5Jšžœ˜—Jšžœžœ˜(Jšžœžœž œ˜ Jšžœ˜—Jšžœžœ"˜5—Jšžœ˜J˜—šœ žœžœ˜Jšœžœ˜Jšœžœ˜J˜J˜J˜—šœ žœžœ ˜0Jšœ ˜"Jšœžœžœ  ˜&Jšœžœžœ  ˜&Jšœžœžœ  ˜&Jšœžœžœ  ˜&Jšœžœžœ  ˜&Jšœžœžœ  ˜&Jšœžœžœ  ˜&Jšœžœžœ  ˜&Jšœžœžœ ˜+Jšœžœžœ ˜+Jšœžœžœ ˜+Jšœžœžœ ˜+Jšœžœžœ ˜+Jšœžœžœ ˜#Jšœžœžœ ˜$Jšœžœžœ  ˜&Jš™Jšœžœžœ ˜'Jšœžœžœ ˜'Jšœžœžœ˜(Jšœžœžœ˜&Jšœžœžœ ˜'Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ ˜'Jšœžœžœ˜&Jšœžœžœ ˜'Jšœžœžœ˜&Jšœžœžœ ˜'Jšœžœžœ˜)Jšœžœžœ ˜&Jšœžœžœ ˜&Jš™Jšœžœžœ ˜'Jšœžœžœ˜(Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ ˜'Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ ˜'Jšœžœžœ ˜'Jšœžœžœ˜)Jšœžœžœ  ˜'Jšœžœžœ  ˜'Jš™Jšœžœžœ ˜'Jšœžœžœ  ˜*Jšœžœžœ ˜'Jšœžœžœ˜&Jšœžœžœ  ˜)Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ ˜'Jšœžœžœ ˜'Jšœžœžœ ˜'Jšœžœžœ ˜&Jšœžœžœ˜)Jšœžœžœ˜)Jšœžœžœ ˜0Jš™Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ ˜'Jšœžœžœ˜&Jšœžœžœ˜&Jšœžœžœ ˜&Jšœžœžœ ˜)Jšœžœžœ˜)Jšœžœžœ ˜'Jšœžœžœ ˜'Jšœžœžœ  ˜'Jšœžœžœ ˜0Jš!œ™3Jšœžœžœ ˜5J˜—Jš Ÿœžœžœžœžœ˜%J˜J˜4J˜Jšžœ˜J˜J˜J˜—…—1Jχ