TipTablesDoc.tioga
Christian LeCocq September 24, 1986 3:16:40 pm PDT
Doug Wyatt, September 24, 1986 3:23:34 pm PDT
TIP TABLES
CEDAR 6.1 — FOR INTERNAL XEROX USE ONLY
Tip Tables
User Input Parser
Werner Winiger, updated by Christian Le Cocq
© Copyright 1986 Xerox Corporation. All rights reserved.
Abstract: TIP (Terminal Interface Package) is a package built on top of Dan Swinehart's Inscript software that parses hardware-level actions from the keyboard, mouse, and keyset, into higher-level user actions. The input to TIP is a Mesa-like program (called here a TIP table) describing the parsing algorithm. i.e. the set of events to be recognised, and the output to be passed through a client supplied procedure, which is called once per event parsed. TIP runs as a separate process from the client and is reentrant, allowing several instances to run at once. There are public interfaces to create a new TIP client and to change the parse table by which TIP recognises events. Users should be aware of the InputFocus interface that allows input events to arbitrarily directed to a single Cedar document.
Created by: Winiger & Paxton
Maintained by: CedarSupport^.pa
Keywords: TIP, Input, Mouse, Keyboard
XEROX  Xerox Corporation
   Palo Alto Research Center
   3333 Coyote Hill Road
   Palo Alto, California 94304

For Internal Xerox Use Only
1. Basic Overview
How to use it
In order to get started, you need to create a TIP client. A user is expected to provide a procedure (a TIPNotifyProc) that TIP can call for recognised events. In your start code, you should call CreateClient, passing in your TIPNotifyProc. TIP will fork a process and begin looking for input events. You next need to give TIP a table from which to parse events. Most applications find the default table to be sufficient, but you can read the section on TIP Tables below in order to "roll your own". You can create your own TIPTable from its disk representation using InstantiateNewTIPTable, or simply pass NIL into InstantiateNewTIPTable. The "Compiled" versions of the TIP Table are stored in []<>TipC>*.tipC.
A Macro preprocessor has been added to the TIP language to improve its generality.
How it works
When TIP recognises an event, the TIPNotifyProc is called with the parameter 'results', which is a list of values collected from the TIP Table while parsing an event. The default table provides a REF CHAR for normal keys. In order to receive events from the keyboard you have to acquire first the "Input Focus" (see the InputFocus interface). If not you will only be notified for mouse events when the cursor is in your Viewer (Unless you use InputFocus.CaptureButtons).
2. TIP Tables
Some applications
For a detailed example, see [Cedar]<Cedar#>Tioga>Tioga.tip, and remember that you can always default the table by passing NIL to InstantiateTIPTable. In general, most people will want to use the default mechanisms.
A much simpler table can be found in [Cedar]<Cedar#>Viewers>MessageWindow.tip for instance.
Syntax
Here is the BNF description for a valid TIP table: (terminals are the quoted symbols and the special characters besides the metasymbols ::= and | )
TIPTable ::= Options Macros TriggerStmt .
Options ::= empty | "OPTIONS" OptionList ;
OptionList ::= SmallOrFast | SmallOrFast , PrintOrDefaultKeys | PrintOrDefaultKeys
SmallOrFast ::= "Small" | "Fast"
PrintOrDefaultKeys ::= "PrintKeys" | "DefaultKeys"
Macros ::= empty | MacroList
MacroList ::= Macro ; MacroList
Macro ::= "[DEF,", MacroName, "(", MacroBody, ")]"
A precise definition could probably be found in Strachey: General Purpose Macrogenerator described in Computer Journal, Oct. 1965. pp. 225-241. See below.
TriggerStmt ::= "SELECT" "TRIGGER" "FROM" TriggerChoiceSeries
EnableStmt ::= "SELECT" "ENABLE" "FROM" EnableChoiceSeries
TriggerChoiceSeries ::= TriggerChoice ;
TriggerChoiceSeries | TriggerChoice "ENDCASE" FinalChoice
EnableChoiceSeries ::= EnableChoice ;
EnableChoiceSeries | EnableChoice "ENDCASE" FinalChoice
TriggerChoice ::= TriggerTerm Expression
EnableChoice ::= EnableTerm Expression
TriggerTerm ::= Key TimeOut | "Mouse" TimeOut
EnableTerm ::= Key | PredicateIdent
Key ::= KeyIdent "Up" | KeyIdent "Down"
TimeOut ::= "BEFORE" Number | "AFTER" Number
Expression ::= "AND" TriggerChoice | "WHILE" EnableChoice | => Statement
Results ::= ResultItem | ResultItem , Results | ResultItem Expression
ResultItem ::= "Coords" | "Char" | String | Number | ResultIdent
FinalChoice ::= empty | => Statement
Statement ::= TriggerStmt | EnableStmt | Results
Blanks, tabs and CRs are allowed between symbols, comments are handled as in Mesa.
The meaning of the options is as follows:

DefaultKeys Adds all normal keyboard events
PrintKeys As above, but only printing keys (e.g. not 'Return' or mouse stuff)
Fast  Indicates to table builder that you favor lookup speed over storage
Small  Indicates you favor storage over lookup speed (default)
The whole match process is viewed as a SELECT statement, which is continuously executed reading key transitions, mouse movements, or key states from the input stream. A trigger statement has the effect of looking at the next action recorded in the input stream and branching to the appropriate choice. An enable statement implies selection between the different choices according to the 'current' state of the keyboard or the mouse keys. Trigger terms may appear in sequence, separated by AND. They might be mixed with enable terms which in turn are characterized by the keyword WHILE. A timeout following a trigger indicates a timing condition which has to hold between this trigger and its predecessor. The number associated with the timeout expresses a time intervall in msecs. An enable term consisting of a predicate identifier is interpreted by calling the 'TIPPredicate' with the same name, a boolean procedure registered in TIP by the user. Events starting with the same sequence of trigger and/or enable terms are expressed as nested statements. As result items you may specify names, numbers, strings, or the keywords Char or Coords. The results of a successfully parsed event are passed to the user as a LIST OF REF ANY. Where names appear as atoms, numbers as REF INT, and strings as REF TEXT. Char comes as a REF CHAR pointing to the ASCII interpretation of the key involved with the event, Coords results in a 'TIPScreenCoords' which is a REF to the RECORD [x, y: REAL]; x and y containing the mouse coordinates of the event.
For example, the DefaultKeys entry for the letter "A" might be represented as:

SELECT TRIGGER FROM
A Down WHILE Ctrl Up => Char;
...

This event will be triggered when the A key goes down, only if the Ctrl key is up and will pass a REF to the character A as a result.
A more elaborate example may look like this:

SELECT TRIGGER FROM
Red Down =>
SELECT TRIGGER FROM
Red Up BEFORE 200 AND Red Down BEFORE 200 =>
SELECT ENABLE FROM
  LeftShift Down => Coords, ShiftedDoubleClick
ENDCASE => Coords, NormalDoubleClick;
Blue Down BEFORE 300 => RedAndBlue
ENDCASE => Coords, SimpleClick;
...
This table produces the result NormalDoubleClick along with the mouse coordinates if the red mouse button goes down, remains there not longer than 200 ms, and goes down again before another 200 ms elapse.
The result will be ShiftedDoubleClick if the same actions occur but also the left shift key is down.
If less than 300 ms after the initial 'Red Down' the blue mouse button also goes down then we get the result RedAndBlue.
And finaly the table specifies the result SimpleClick (with coordinates) for the case of red going down but none of the above described succeeding actions occuring.
Macro syntax
The macro package used in TIP is based on the "General Purpose Macrogenerator" described by Strachey in the October 1965 Computer Journal. The following summary is based on that article; see the real thing for more details.
A macro-call consists of a macro-name and a list of actual parameters, each separated by a comma. The name is preceded by a left square bracket ([) and the last parameter is followed by a right square bracket. A macro is defined by the special macro DEF which takes two arguments: the name of the macro to be defined and the defining string. The defining string may contain the special symbols ~1, ~2, etc., which stand for the first, second, etc., formal parameters. Enclosing any string in parentheses has the effect of preventing evaluation of any macro-calls inside; in place of evaluation, one "layer" of string quotes is removed. It is usual to enclose the defining string of a macro definition in string quotes in order to prevent any macro-calls or uses of formal parameters from being effective during the process of definition. The symbol  acts as a single character string quote (to enter this, type "d", then hit MakeControlCharacter). Use it in front of special macrogenerator characters in string literals. For example, if you want to insert "(", you need to write "(" to keep the macro scanner from treating the paren as a start of string quote.
Examples :
[DEF,WhileCTRLUp,(WHILE Ctrl Up WHILE Spare3 Up)]
[DEF,BothUp,(~1 Up WHILE ~2 Up)]
[DEF,IfShift,(SELECT ENABLE FROM
[SHIFT] => ~1;
ENDCASE => ~2)]
Which are later used as:
[BothUp,Red,Yellow] => SELECT TRIGGER FROM ...
ESC Down [WhileCTRLUp] => [IfShift,Undo,Repeat];
From Tioga.tip.
Compiled tables syntax
The syntax of "compiled" tip table files follows:
capital letters, numbers and parens are character literals
lower case id's are names of syntax equations
id* means 0 or more instances
<id> is a primitive of some sort such as text
file = TIPTABLE version opaque link ignore variant
version = <char>
opaque = flag
link = N --none-- | P --printKeys-- | D --defaultKeys--
ignore = up down move
up = flag
down = flag
move = flag
variant = S small | F fast
small = choiceseries
fast = choice U choicearray D choicearray time
time = choice
choicearray = ( choiceitem* )
choiceitem = ( key choice )
choiceseries = ( choice* )
choice = ( term* )
term = 1 keytrigger | 2 --mousetrigger-- | 3 timetrigger | 4 keyenable |
5 predenable | 6 --CHAR-- | 7 --COORDS-- | 8 choiceseries | 9 results |
A key2Enable | B keyEnableList | C --TIME--
keytrigger = key keystate
key = <byte>
keystate = U --up-- | D --down--
timetrigger = timeoutflavor msecs
timeoutflavor = G --gt-- | L --lt--
msecs = high low
high = <byte>
low = <byte>
keyenable = key keystate
key2Enable = keyenable keyenable
keyEnableList = ( keyenable* )
predenable = atom
results = ( result* )
result = 1 atom | 2 --TIPUser.stdChar-- | 3 <int> | 4 len <text> |
5 --TIPScreenCoords-- | 6 --TIPUser.stdTime--
flag = T | F -- true or false
atom = len pname
pname = <text>
len = <byte>
<text> stored as series of characters. length limited to 255 chars
<int> stored as 4 bytes
<char> and <byte> stored as themselves
3. Appendix
KeyIdent definitions
ESC: [Ascii.ESC, Ascii.ESC], -- Alto ESC (upper left), DLion CENTER (top row, left end)
One: ['1, '!], -- 1 and !
Two: ['2, '@], -- 2 and @
Three: ['3, '#], -- 3 and #
Four: ['4, '$], -- 4 and $
Five: ['5, '%], -- 5 and %
Six: ['6, '~], -- 6 and ~
Seven: ['7, '&], -- 7 and &
Eight: ['8, '*], -- 8 and *
Nine: ['9, '(], -- 9 and (
Zero: ['0, ')], -- 0 and )
Dash: ['-, '—], -- Alto - and —, DLion -
Equal: ['=, '+], -- = and +
BackSlash: ['\\, '|], -- Alto \ and |, DLion DEFAULTS (top row, right end)
LF: [Ascii.LF, Ascii.LF], -- Alto LF (upper right), DLion COPY (left group)
DEL: [Ascii.DEL, Ascii.DEL], -- Alto DEL, DLion DELETE (left group)
TAB: [Ascii.TAB, Ascii.TAB], -- Alto TAB, DLion <paratab> (large key left of Q)
Q: ['q, 'Q],
W: ['w, 'W],
E: ['e, 'E],
R: ['r, 'R],
T: ['t, 'T],
Y: ['y, 'Y],
U: ['u, 'U],
I: ['i, 'I],
O: ['o, 'O],
P: ['p, 'P],
LeftBracket: ['[, '{], -- [ and {
RightBracket: ['], '}], -- ] and }
Arrow: ['←, '^], -- Alto ← and ^, DLion open quotes
BS: [Ascii.BS, Ascii.BS], -- Alto BS (upper right), DLion ← (large key, upper right)
A: ['a, 'A],
S: ['s, 'S],
D: ['d, 'D],
F: ['f, 'F],
G: ['g, 'G],
H: ['h, 'H],
J: ['j, 'J],
K: ['k, 'K],
L: ['l, 'L],
SemiColon: [';, ':], --; and :
Quote: ['\', '\"], -- ' and " (close quotes on DLion)
Return: [Ascii.CR, Ascii.CR], -- Alto RETURN, DLion <newpara> (double-height key, right side)
Z: ['z, 'Z],
X: ['x, 'X],
C: ['c, 'C],
V: ['v, 'V],
B: ['b, 'B],
N: ['n, 'N],
M: ['m, 'M],
Comma: [',, '<], -- , and <
Period: ['., '>], -- . and >
Slash: ['/, '?], -- / and ?
Space: [Ascii.SP, Ascii.SP], -- the space bar
Spare1: ['\201, '\204],
Spare2: ['\202, '\205],
Spare3: ['\203, '\206]
Note that there are no names for shifted characters like left or right paren. Instead you must specify SHIFT plus the unshifted key name e.g.
Nine Down WHILE [SHIFT] instead of LeftParen Down