Menu, Topic, Help (MTH)
Each application can have a set of 'topics' associated with it. These topics appear in the topic window on the left hand edge of the screen, below the application name. Normally all the topics are in grey but when the menu key is pressed a topic name is highlighted and a menu display is brought up. The menu consists of up to three columns of commands, which may be selected with a highlight bar or by using a special keyboard sequence also shown on the menu. Each topic and each command may have a page of help text associated with it and in addition the application itself may have a page of help text, perhaps for a general description of its function. An extra information topic, not displayed in the topic window, may be added to provide access to a series of help pages which are not directly associated with keyboard commands. This is useful to explain general features of the application or tips of command usage.
Limitations and conventions
There are some limitations and conventions regarding menu topics and help; the limitations are:
- Diamond sequences should consist of no more than 5 characters, although these may be special characters like arrow keys and Delete.
- The first possible match will be selected, so if a diamond sequence 'AB' exists, there is no point having 'ABC' as it cannot be selected.
- No command code should be zero, as two zeroes from 'OS_In' are used to represent NUL. Note also that the <SPACE>, <TAB>, <ENTER> and the arrow keys all return command codes and you must make sure you do not clash with these. See "Input and the Keyboard Decoder" for details of these codes.
- There should be no more than 7 topics per application and no more than 24 commands per topic. Each command name should consist of no more than 25 characters.
- If any commands in a topic have help, then it is strongly recommended that all the topics have help, even if this is just a blank page (set the help pointer to point to a NUL) and the topic itself must have help.
The conventions, we recommend you subscribe to, are:
- Make the first letter of a diamond sequence the first letter of the topic name (eg. PipeDream has BNEW in the Blocks topic).
- If topic names coincide with the internal ones, then the order should be the same, eg. 'CURSOR' before 'FILES'.
- Commands associated with the arrow keys should be in the order: Right, Left, Up and Down.
Topic information
The 'pointer to topics' is of the form of a 2 byte offset in a bank, followed by a bank number. The pointer should point to a series of topic definitions arranged like this:
1 byte 0 Start marker
x bytes <first definition>
x bytes <second definition>
...
...
x bytes <last definition>
1 byte 0 End marker
Where each definition has the following form:
a 1 byte b-a length byte
n bytes 'xxxxx' topic name
1 byte 0 optional null-terminator (see below)
2 bytes x x Optional pointer to topic help page, if
any. This is a 2-byte pointer relative to
the start of the help text. NOTE: it is
stored as high byte, low byte sequence
(reverse of the conventional order).
1 byte x topic attribute byte
1 byte b-a length byte
b
The topic attribute byte:
bit 0 set for an 'An' topic eg. 'An Edit topic' - default is 'A'
bit 1 set for an information topic - see below
bits 2-3 should be 0
bit 4 set if topic entry has a pointer to a help page
bits 5-7 should be 0
The topic name terminator can simply be a null, but in fact any control character (ie. $00-$1F) will serve perfectly well. Therefore it is possible to use the attribute byte, or the high byte of the help pointer (hence the high byte, low byte ordering - although this won't apply if the help text length is more than 8K - the high byte becoming $80) to terminate the name. The system looks at the attribute and help pointers by counting back from the end of the topic entry, so there is no confusion between a term inator and an attribute byte or help pointer.
NOTE: Due to a bug in OZ it is necessary when creating information topics (bit 1), that the definitions must be placed before any command topics otherwise they are not recognized by the system.
Command Information
The 'pointer to commands' is of the form of a 2 byte offset in a bank, followed by a bank number. The pointer should point to a series of command definitions arranged like this:
1 byte 0 Start marker
x bytes def(1,1) first command of first topic
x bytes def(1,2) second command of first topic
...
x bytes def(1,x) last command of first topic
1 byte 1 End of this topic
x bytes def(2,1) first command of second topic
...
x bytes def(2,x) last command of second topic
1 byte 1 End of this topic
x bytes def(x,1) first command of last topic
x bytes def(x,y) last command of last topic
1 byte 0 End of all topics
Each of these definitions should have the following form:
a 1 byte b-a length byte
1 byte x command code (see below)
x bytes 'xxx',0 null-terminated keyboard sequence for
command.
x bytes 'xxxxx' Command name. The total length of the name
and keyboard sequence must be 25 characters
or less. Any control characters which you
need to use must be brought in via tokens.
1 byte 0 optional null-terminator (see below)
2 bytes x x Optional pointer to command help page, if
any. This is a 2-byte pointer relative to
the start of the help text. NOTE: it is
stored as high byte, low byte sequence
(reverse of the conventional order).
1 byte x command attribute byte
1 byte b-a length byte
b
The command attribute byte:
bit 0 set to make this entry the first in a new column. Note: the last
entry in a column has no special attribute. Set this bit even
though the previous column is used up, otherwise the system gets
confused in displaying the entries.
bit 1 should be set to 0
bit 2 set to make a hidden entry. The command name and key sequence will
not appear on the menu display. This is useful for commands which
need to key sequences. eg. in PipeDream <>TAB is a hidden entry
which does the same thing as <>CFC, by having the same command
code. Hidden entries may have Help text, but this text will never
be displayed. Note: A hidden entry must never be the last in a
topic. If it is the Help system will not be fully traversable and
the system will crash if the user moves through help in a certain
way.
bit 3 set to make safe. Setting this bit forces to use the user to use
the keyboard sequence rather than selecting the command with the
highlight bar in the menu display. This is used by the system for
the Index commands <>KILL and <>PURGE. An attempt to access these
commands through the highlight bar results in a double bleep. These
entries should have their command name in tiny text, by convention.
This has to be done using a token, since control characters will
terminate a command name.
bit 4 set if command entry has a pointer to a help page.
bit 5-7 should be set to 0
NOTE: The same trick of treating the attribute byte, or high byte of the help pointer as a terminator, can be used in menu entries. The command name terminator simply needs to be in the range ($00 - $1F).
The format of the keyboard sequence is as follows:
For a conventional diamond sequence, simply use the upper case letters of the sequence, eg. for the PipeDream New command the entry would be the following bytes "BNEW" & 0 . For commands using other keys the keyboard decoder codes are used. For example <SHIFT><UP><ARROW> is represented by a key sequence consisting of one byte. IN_SUP ($FB) and the terminator, $00. The system automatically generates the graphic sequence from this code. The menu exceptions, which correspond to the screen driver codes, are:
Key Symbol Code
<SPACE> MU_SPC $E0
<ENTER> MU_ENT $E1
<TAB> MU_TAB $E2
<DEL> MU_DEL $E3
When an application reads the keyboard then valid keyboard sequences are intercepted so instead of returning the raw characters, the routine will return a zero, indicating a command - note this means the NUL can never be read in as a normal character. The next keyboard read will then return the relevant command code as specified in the above definition. One way of dealing with this behaviour is for the user to set up a 'read character' routine which will return normal characters without change, but intercept and obey command sequences. The following code fragment indicates a possible arrangement, although you will need to have read "Error handling and related issues" and "Input and the keyboard decoder" to follow it properly.
.rdch call_oz(OS_In) ; perform OS_In
jr nc, rdch2 ; if no error, continue
cp RC_SUSP ; check RC_SUSP
jr z, rdch ; and ignore if it occurs
SCF
RET ; return with system error enabled
.rdch2 or a ; reflect on input
ret nz ; return if character is not NUL
call_oz(OS_In) ; read command code
or a ; set flags
ret z ; return if a NUL has been read
<deal with command code in A>
Help Information
The 'pointer to commands' is of the form of a 2 byte offset in a bank, followed by a bank number. The pointer should point to a series of help page definitions arranged like this:
x bytes help page for the application (or 0 for a blank page)
x bytes help entry (see below)
...
...
x bytes last help entry
Each help entry will produce one page of help text. It consists of a series of lines, where DEL ($7F) is used for newline, terminated by a NUL ($00). The DEL character is used for newline to facilitate embedding screen driver codes into the help text. For example you can use special keyboard icons, arrow symbols or box characters, eg. for the 'ENTER' icon use the sequence 1 & SD_ENT. The help page is displayed with centred justfification switched on, but you could include a command to switch off centering in your help strings. This should only be done where necessary, to avoid disrupting the overall style of the help pages. The pointer to the help text, which is an offset from the base of the help text, defined in the application DOR, in topic and command entries, should point to the first character of the first line. A help entry might look like this:
.helppage defm "This is a simple help page" & $7F
defm "and this is the second line" & 0
Token information
The 'pointer to token base' is of the form of a 2 byte offset in a bank, followed by a bank number. The token table format is shown below.
base 1 byte Recursive token boundary (1 - 127)
1 byte Number of tokens (1 - 127)
2 bytes first-base pointer to first token
2 bytes second-base pointer to second token
...
...
2 bytes last-base pointer to last token
2 bytes end-base pointer to byte after nth token
.first x bytes defm "xxx" first string (no terminators)
.second x bytes defm "yyy" second string
...
.last x bytes defm "zzz" last string
.end
NOTE: the token table must not be allowed to cross a bank boundary (16K).
Tokens may be embedded in the help text or within the text for topic and command names. The first token has a code of $80 and subsequent tokens count up from here. Recursive tokens may contain tokens in their text. Tokens above the boundary level set by the 'first recursive token' may contain tokens themselves, providing those tokens are below the boundary. The example below is in assembly format to improve clarity:
.tok_base defb $04 ; recursive token boundary
defb $05 ; number of tokens
defw tok0 - tok_base
defw tok1 - tok_base
defw tok2 - tok_base
defw tok3 - tok_base
defw tok4 - tok_base
defw end - tok_base
.tok0 defm "file"
.tok1 defm " the "
.tok2 defm "EPROM"
.tok3 defb $01, 'T' ; Tiny text token
.tok4 defm ' ', $80, "s "
.end
Information topics
The information topic is selected by pressing <HELP> from within the application. If the topic is present then a menu of commands will be brought up. In an application with no other topics, pressing <MENU> will bring up the information topic name in the topic window. The command entries for an information topic topic differ from ordinary commands in that there is no keyboard sequence associated with them. The command entries should look like this:
a 1 byte b-a length byte
1 byte 0 NULL command code
1 byte 0 NULL keyboard sequence
x bytes 'xxxxx' Command name. The total length of the name
must be 25 characters
1 byte 0 optional null-terminator
2 bytes x x pointer to help page
1 byte x command attribute byte
1 byte b-a length byte
b
The attribute byte should always be $10 (help page) or $11 (help page and first entry in a new column).