<> <> <> 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; <> <<1) when DestroyClient is called to flush the tip process (inCreek=NIL)>> <<2) InterruptTIP is called to change the table and flush pending state>> < flush type-ahead>> <> <> <> 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]]]}; <> <<(the ones not to be ignored), and parses the appropriate entry:>> 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.