TipDoc.Tioga
Christian LeCocq September 24, 1986 3:16:40 pm PDT
Doug Wyatt, September 24, 1986 3:23:34 pm PDT
Rick Beach, March 13, 1987 11:41:29 am PST
Willie-Sue, November 25, 1987 4:16:51 pm PST
Bill Jackson (bj) February 3, 1988 5:25:51 pm PST
Bier, August 9, 1990 11:48 pm PDT
Spreitze, November 27, 1990 7:43 am PST
Christian Jacobi, March 3, 1992 1:32 pm PST
0. Executive Summary
Dear PCedar user, much of this document is out of date and I (Eric Bier) don't have time to rewrite it right now. However, if you are porting packages to PCedar or writing new applications with TIP tables, here is some information that you may wish to have.
Most of your old TIP tables should continue to at least load properly. Notice, I didn't say they would work. TIP depends on other routines (such as RawViewersImpl.KeySymFromScanCode, X11TIPSourceImpl.RemapKeys, and X11TIPSourceImpl.EnsureKeyTable) to deliver keystrokes to it. So, getting a keystroke to actually do what you want it to may require some coordination. Also, some TIP key names have been revoked, have changed capitalization, or have just been forgotten (let me know if you find a name that really ought to be defined but isn't).
We are trying to head towards an age where all names appearing as triggers or enablers in TIP tables are either the names of standard symbols that actually tend to appear on keyboards (e.g., A, $, Cut, Paste, F1) or are pseudo-symbols that you might imagine pasting onto a keycap if you only used your keyboard for Cedar (such as LOOK or NEXT). This will require removing from TIP tables words like Spare3 or FL4 that are neither symbols nor Cedar concepts. Hopefully, we can phase these out gradually.
In this section, I list those Symbols which currently will be accepted in a PCedar TIP table. I list them in the following format (the complete up-to-date truth about this list can be found in TIPKeyboardsImpl.BuildKeyTables). Not all names found in this table are actually bound to a key on a given keybaord.
<name(s) you should use> (alternate names, for compatibility) => <the ASCII character associated with this symbol, if any>
A () => A
...
Z () => Z
a () => a
...
z () => z
Button1 (LeftMouse, Red, Point)
Button2 (MiddleMouse, Yellow, Menu)
Button3 (RightMouse, Blue, Adjust)
Space () => Ascii.SP
ExclamationPoint () => !
Quote, QuotationMark () => "
NumberSign () => #
DollarSign () => $
PercentSign () => %
Ampersand () => &
Apostrophe () => '
LeftParen, LeftParenthesis () => (
RightParen, RightParenthesis () => )
Asterisk () => *
PlusSign () => +
Comma () => ,
Hyphen () => -
Period (FullStop) => .
Slash, Solidus () => /
Zero () => 0
One () => 1
Two () => 2
Three () => 3
Four () => 4
Five () => 5
Six () => 6
Seven () => 7
Eight () => 8
Nine () => 9
Colon () => :
SemiColon () => ;
LeftAngleBracket (LessThanSign) => <
Equal, EqualSign () => =
RightAngleBracket (GreaterThanSign) => >
QuestionMark () => ?
AtSign () => @
LeftBracket () => [
BackSlash, ReverseSolidus () => \
RightBracket () => ]
CircumflexAccent () => ^ (temporary, this character also available from UpArrow)
LowLine () => ← (temporary, this character also available from LeftArrow)
GraveAccent () => `
LeftCurly, LeftCurlyBracket
VerticalLine, VerticalBar
RightCurly, RightCurlyBracket
Tilde () => ~
Dash () => -
BackSpace (BS) => Ascii.BS
Tab (TAB) => Ascii.TAB
LineFeed (LF) => Ascii.LF
Return (CR, Enter) => \n
Pause (Hold, ScrollLock)
Esc (ESC, COMPLETE, Center)
Home
UpArrow (Up, MoveUp) => ^
RightArrow (Right, MoveRight)
DownArrow (Down, MoveDown) => ¯
Next (NEXT, STUFF, Keyboard, Spare2)
Print
Execute (Run, Do, DOIT)
Help (HELP)
Break (BREAK)
LeftShift
RightShift
LeftControl (Ctrl, CONTROL, Open, Control)
CapsLock (LOCK, Lock)
Delete (DEL, DELETE)
KeypadMultiplicationSign, KeypadAsterisk () => *
KeypadPlusSign () => +
KeypadComma, KeypadSeparator () => ,
KeypadMinusSign, KeypadHyphen () => -
KeypadDecimalPoint, KeypadFullStop () => .
KeypadDivisionSign, KeypadSolidus () => /
KeypadZero ()
KeypadOne ()
KeypadTwo ()
KeypadThree ()
KeypadFour ()
KeypadFive ()
KeypadSix ()
KeypadSeven ()
KeypadEight ()
KeypadNine ()
KeypadEqualSign () => =
LeftMeta () (bound to the left diamond key on the SPARCStation 1)
RightMeta () (bound to the right diamond key on the SPARCStation 1)
LeftAlt () (bound to the Alt key on the SPARCStation 1)
RightAlt () (unbound on the SPARCStation 1)
LeftSuper ()
RightSuper ()
LeftHyper ()
RightHyper ()
F1 ()
...
F12 ()
L1 ()
L2 ()
L3 (F13)
...
L10 (F20)
R1
...
R8
R9 (Look, LOOK, Spare1, BW, COMMAND)
R10 (LeftArrow, Arrow, Left, MoveLeft) => ←
R11 ()
...
R14 ()
R15 (FormerlySWAT, Spare3, USERABORT)
RightControl ()
Swat (SWAT)
Stop (Cancel, Abort, Exit)
Again (AGAIN)
Props ()
Undo (UNDO)
Front ()
Copy (COPY)
Open ()
Paste (PASTE)
Find (FIND)
Cut ()
Unused0
...
Unused6
Keyset1
...
Keyset5
<more to be written, Bier, December 15, 1989>
2. A quick disclaimer:
There is still some confusion about the
"names" of keys
Before you jump to the conclusion that you think you understand the concept of "a key on the keyboard", let me suggest that it's a little more complicated than you would think, and that you should be wary of what you think you know.
To start, there are basically four different "things" that you have to worry about. First of all, there are the physical objects that you can stare at on your keyboard, let me call them "keycaps". Then there is the hardware associated with those keycaps, which is a bit vector indicating whether the switch underneath a keycap is depressed or not (down/up), we'll call each of these things a "bit position". Then there are the programmer names for the bit positions in the KeyName item of the TerminalDefs interface, which we'll call these "KeyName values", and finally there are the symbols which belong to the TIP vocabulary, which we'll call "TIP names".
Now lets throw in a few distractions; TerminalDefs includes some extra "constants" which can be used in place of Keyname values by programmers. This seems to be a dubious practice and should be discouraged, but is required for backward compatibility. It you happen do discover old code that uses constants, consider changing them to Keyname values instead.
The next distraction is that there are some "synonyms" added to the TIP vocabulary, also primarily for backward compatibility, but some seem to have been added for convienence. Currently, most of these convienence synonyms are not mapped to the keycaps you would think that they should be mapped to.
To confuse things even further, there are the "keyName ropes" which are available thru TIPPrivate.keyNames[KeyName] which contain names (in a derogatory sense) for the keys. Currently, these keyName ropes are not the same as the symbolic KeyName values, but are a mix of representations for values and constants. If you're interested, look in TIPTableBuilder.Mesa for the definition point of keyNames.
Now, to get to the nitty gritty, TIPTableBuilder.Mesa contains a procedure GetWord, which uses ATOMS (yes, ATOMS!) to identify whether tokens in tip tables refer to reserved words, or to names of keys (in the TIP name vocabulary sense). Currently there are problems with this mapping in that some synonyms which historically refered to constants now use the actual KeyName values instead (this isn't a new bug!), and you can discover obvious conflicts between interpretatons. For example, you might want to look at "Move", and "MOVE"
Luckily, all the problems seem to be constrained to keys which are unavailable on the Dorado keyboard (DLion keys?); so, unless you've done something special to your tip tables for DLions (or Daybreaks) none of this matters to you. Hopefully everything can get straightened out, but it is unlikely that the constants in TerminalDefs can be corrected (since it requires a major Cedar bounce/release), hence the suggestion that you avoid these. It should also be the case that the standard tip tables should use only TIP names corresponding to actual KeyName values. This could cause novice tip table hackers to get confused since the mapping between KeyName values and keycaps is not obvious, but judicious use of comments should help out here. Also documenting that mapping should help...
4. 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];
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
5. Appendix
The Old Dorado Cedar Alto Keyboard KeyIdent definitions (Historical Interest Only)
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