The displayable records of |TOPIC keep their
numbers and commands in LinkData1 and their text in LinkData2.
Commands and strings take turns: a string (often empty), a command, a string, a command.
Compressed integers
Numbers in LinkData1 are shortened by a flag in the lowest bit of the first
byte. Clear, the value fits one byte (or word); set, it takes twice that.
| Name | Low bit clear | Low bit set |
|---|---|---|
cshort | 1 byte: value / 2 − 0x40 | 2 bytes: value / 2 − 0x4000 |
cushort | 1 byte: value / 2 | 2 bytes: value / 2 |
clong | 2 bytes: value / 2 − 0x4000 | 4 bytes: value / 2 − 0x40000000 |
culong | 2 bytes: value / 2 | 4 bytes: value / 2 |
Record layout
LinkData1 starts as follows, by record type.
- All types: a
clong, the topic size. - Types
0x20and0x23: acushort,TopicLength, the characters in this record. It is what the TOPICOFFSET count adds up. - Type
0x23: a table header (u8columns,u8table type; if the type is 0 or 2, ani16minimum width; then twoi16per column, the gap and the width).
Then paragraphs follow. Type 0x23 has a five-byte prefix for each cell
(i16 column, i16 unknown, one zero byte); a column of −1 ends
the table.
Paragraphs
Each paragraph starts with 4 bytes whose meaning is not known and a 16-bit bit field. For each bit that is set, one field follows, in this order:
| Bit | Field | Type |
|---|---|---|
0x0001 | Unknown | clong |
0x0002 | Space above | cshort |
0x0004 | Space below | cshort |
0x0008 | Line spacing | cshort |
0x0010 | Left indent | cshort |
0x0020 | Right indent | cshort |
0x0040 | First-line indent | cshort |
0x0100 | Border | 3 bytes: flags, then a 16-bit width |
0x0200 | Tab stops | A cshort count, then each stop as a cushort, followed by another cushort (the tab type) when bit 0x4000 of the stop is set |
Bits 0x0400 and 0x0800 right-align and centre the paragraph.
Metrics are in half-points or twips, depending on the font table’s type.
Formatting commands
After the paragraph fields the string and command stream begins. Reading stops at
0xFF; other commands are single bytes with these parameters.
| Code | Meaning | Parameters |
|---|---|---|
0x20 | {vfld} marker (Multimedia Viewer) | u32 number |
0x21 | {dtype} marker (Multimedia Viewer) | u16 number |
0x80 | Font change | u16 index into the descriptors |
0x81 | Line break | none |
0x82 | End of paragraph (or table cell) | none |
0x83 | Tab | none |
0x86, 0x87, 0x88 | Picture or embedded object: in line, left, right | see below |
0x89 | End of a hotspot | none |
0x8B | Non-breaking space | none |
0x8C | Non-breaking hyphen | none |
0xC8, 0xCC | Macro hotspot | u16 length, then the macro text |
0xE0–0xE3, 0xE6, 0xE7 | Popup (even) or jump (odd) to a topic. 0xE6 and 0xE7 have no underline | u32 target |
0xEA, 0xEB, 0xEE, 0xEF | Popup (even) or jump (odd) to another file or window | see below |
0xFF | End of the commands for this paragraph | none |
A jump’s target depends on the compiler. Windows 3.0 stores a topic number, which
|TOMAP turns into a position.
Windows 3.1 and later store the 32-bit hash of the context name, looked up in
|CONTEXT.
Jumps to other files
0xEA and its neighbours are followed by a u16 length, a
u8 type and a u32 hash of the context name, then, by type:
nothing (0), a one-byte window number (1), or a file name (4), or a file name and a
window name (6), each as a NUL-terminated string.
Pictures and embedded objects
0x86–0x88 are followed by a u8 type, then a
clong size. Type 0x22 has a cushort hotspot count
next. Then, for size bytes:
- Type 3 or
0x22: ani16that is 0 for a picture stored in|bmN, followed by au16number, or 1 when the picture is stored here. - Type 5: three
i16values, then a string. It starts!for a button (label, macro),*for sound or video, and is otherwise a window from a DLL.