WordPerfect for the Macintosh used two document layouts: version 1.x writes a
headerless stream close to WordPerfect 4.2 for DOS, and versions 2.x, 3.0–3.5 and
3.5e write a WPC header (file type 0x2C) and a stream with their own
codes. Neither layout has a public specification. This page follows libwpd’s
reader; numbers inside the Macintosh streams are big-endian (high byte first). A
manual for the 3.5e (“4.0”) format circulates, but its cover marks it confidential,
and it was not used here.
Version 1.x
The file is the document from its first byte. Its byte ranges are the same as in
WordPerfect 4.2: control
characters below 0x20 (0x09 tab, 0x0A hard
return, 0x0B soft page break, 0x0C hard page break,
0x0D soft return), text 0x20–0x7F,
single-byte functions 0x80–0xBF and multiple-byte
functions 0xC0–0xFE. A protected file starts
FE FF 61 61, then the password checksum (big-endian), and is scrambled
from offset 6.
| Byte | Function | Byte | Function |
|---|---|---|---|
90, 91 | Redline on, off | B4, B5 | Shadow on, off |
92, 93 | Strikeout on, off | B6, B7 | Outline on, off |
94, 95 | Underline on, off | BC, B9 | Superscript on, off |
9D, 9C | Bold on, off | BD, B8 | Subscript on, off |
B2, B3 | Italics on, off |
Other single-byte codes are not named by libwpd.
A fixed-length function is its code, data and the code again. A variable-length function is its code, a 32-bit length, that many data bytes, the length again and the code again:
code length(4) data… length(4) code
Function lengths, both codes included (−1 variable):
| Code | Length | Code | Length | Code | Length | Code | Length |
|---|---|---|---|---|---|---|---|
C0 | 10 | D0 | 6 | E0 | 4 | F0 | 6 |
C1 | 4 | D1 | −1 | E1 | 3 | F1 | 106 |
C2 | 4 | D2 | −1 | E2 | −1 | F2 | −1 |
C3 | 7 | D3 | 4 | E3 | 150 | F3 | 196 |
C4 | 7 | D4 | 4 | E4 | 6 | F4 | 4 |
C5 | 6 | D5 | 4 | E5 | 23 | F5 | −1 |
C6 | 4 | D6 | 6 | E6 | 11 | F6 | 5 |
C7 | 6 | D7 | −1 | E7 | 3 | F7 | 4 |
C8 | 8 | D8 | 4 | E8 | 3 | F8 | 4 |
C9 | −1 | D9 | 4 | E9 | −1 | F9 | 8 |
CA | 4 | DA | 4 | EA | −1 | FA | −1 |
CB | 6 | DB | 4 | EB | 32 | FB | 4 |
CC | 6 | DC | −1 | EC | 5 | FC | −1 |
CD | 3 | DD | 24 | ED | −1 | FD | −1 |
CE | 6 | DE | 6 | EE | 44 | FE | −1 |
CF | 3 | DF | −1 | EF | 18 |
The functions libwpd reads (measurements in points, 1/72 inch, unless stated):
| Code | Function | Data |
|---|---|---|
C0 | Margin reset | 4 bytes skipped, new left margin (16-bit), new right margin (16-bit) |
C1 | Spacing reset | 1 byte skipped, new spacing |
C2 | Margin release | 16-bit amount moved left |
C3 | Centre text | not read |
C4 | Flush right | not read |
C9 | Set tabs (variable) | an old condensed tab table of 3-byte entries ending FF, then the new table: entries of a type byte and a 16-bit position, ending FF. Type bits 0–1: 0 left, 1 centre, 2 right, 3 decimal; bit 2: dot leader. A negative type −n repeats the position step n times |
CB | Font | old font ID, new font ID (16-bit each); see font IDs |
CC | Left indent | old and new left margin (16-bit); the indent is their difference |
CE | Top margin | 2 bytes skipped, 16-bit top margin |
CF | Suppress page features | flags: 0x01 all headers and footers, 0x10 header A, 0x20 header B, 0x40 footer A, 0x80 footer B |
D0 | Bottom margin | 2 bytes skipped, 16-bit bottom margin |
D1 | Header or footer (variable) | definition byte (bits 0–1: 0 header A, 1 header B, 2 footer A, 3 footer B; bits 2–4: 1 all pages, 2 odd, 4 even), 18 bytes skipped, then the text (length − 19 bytes) |
E0 | Left and right indent | 16-bit offset |
E1 | Extended character | one byte, a Mac OS Roman character (bytes up to 0x20 read as a space) |
E2 | Footnote or endnote (variable) | definition byte (bit 1: endnote), 16-bit note number, then the note text, which is the last (length − 29) bytes for a footnote and (length − 27) for an endnote |
F4 | Point size | 1 byte skipped, size in points |
F5 | Picture (variable) | a byte (if not 0 another byte follows), 16-bit width and height, 6 bytes skipped, 16-bit data size, then a Macintosh PICT picture |
FB | Justification | 1 byte skipped, then 0 left, 1 centre, 2 right, 3 full |
The other codes are skipped by their lengths; their contents are not known. Many share their numbers and lengths with WordPerfect 4.2’s codes, which suggests the same meanings, but that is not confirmed.
Version 1.x font IDs
The 16-bit IDs libwpd maps to names (each of the first group also appears with
0xFF as its high byte): 2 New York, 3 Geneva, 4 Monaco, 5 Venice,
6 London, 7 Athens, 8 San Francisco, 9 Toronto, 11 Cairo, 12 Los Angeles,
13 Zapf Dingbats, 16 Palatino, 20 Times, 21 Helvetica, 22 Courier, 23 Symbol,
24 Mobile; also 0x07D2 Charcoal, 0x3FFF Chicago, and a
list of Bitstream typefaces (0x0B07, 0x0B48,
0x0DB0, 0x0DBF, 0x0DC0,
0x0EC8–0x0ECD, 0x0F7C,
0x12ED–0x12EF, 0x3275, 0x3B98,
0x3BA2, 0x3BCF, 0x3BF4, 0x3C86,
0x3C3F, 0x3C4A, 0x3C4C). libwpd shows any
other ID as Geneva.
Versions 2.x and 3.x
These files have the WPC header (file type 0x2C; major version 2 for
2.x, 3 for 3.0–3.5, 4 for 3.5e). From offset 16 to the document pointer the file
holds a Macintosh resource fork: at 16 come its data offset, map offset, data length
and map length (32-bit each), and libwpd reads the
pictures for graphics boxes from it (resources PICT and
WBOX). Some 2.x files have no resource fork (document pointer 16 or
less). A protected file is scrambled from the document pointer on, with the resource
data scrambled separately.
| Bytes | Meaning |
|---|---|
0x00, 0x7F, 0xFF | Ignored. |
0x01–0x1F | Control characters; meanings not known. |
0x20–0x7E | ASCII text. |
0x80–0xBF | Single-byte functions. |
0xC0–0xCF | Fixed-length groups. |
0xD0–0xEF | Variable-length groups. |
| Byte | Function | Byte | Function |
|---|---|---|---|
80 | Condensed hard return | 85 | Condensed left and right indent |
81 | Condensed hard page | 96 | Hard hyphen |
82 | Condensed tab | 97 | Soft hyphen |
83 | Condensed back tab | A0 | Hard space |
84 | Condensed indent |
The other single-byte functions are not named by libwpd.
2.x and 3.x fixed-length groups
Code, data, code. Positions are 16.16 fixed-point numbers in points.
| Code | Length | Group | Data |
|---|---|---|---|
C0 | 5 | Extended character | Mac OS Roman character, character set, character: a Mac character from 0x20 is used; otherwise the set and character are a WordPerfect character as in 5.x |
C1 | 8 | Tab | sub-code (0 tab, 1 centre, 2 flush right, 3 back tab, 4 character kerning, 5 bar tab, 6 fixed tab), mode, 32-bit position |
C2 | 7 | Indent | sub-code (0 left indent, 1 left and right indent), 32-bit offset |
C3 | 4 | Attribute | attribute, state (bit 0: on) |
C4–C7 | 4, 7, 10, 7 | Not known | |
C8 | 4 | Double-byte script character | 16-bit character in an Apple WorldScript encoding |
C9–CC | 5, 6, 6, 7 | Not known | |
CD | 9 | Undo | type (0 start of invalid text, 1 end), 16-bit level |
CE, CF | 7, 4 | Not known |
Attributes: 0 bold, 1 italics, 2 underline, 3 outline, 4 shadow, 8 redline, 9 strikeout, 10 subscript, 11 superscript, 12 double underline, 13 extra large, 14 very large, 15 large, 16 small print, 17 fine print, 18 small caps; 5 to 7 are not known.
2.x and 3.x variable-length groups
code subcode length(2) data… length(2) subcode code
The 16-bit length is the number of data bytes plus 3. Offsets in the table count from the first data byte.
| Code | Group | Sub-codes and data |
|---|---|---|
D0 | Page format | 1 left and right margins (8 bytes old, new left and right, 32-bit fixed; 0x80000000 means unchanged); 2 line spacing (4 bytes old, then 16.16 spacing); 4 tab set (old condensed table, a flag byte with bit 0 relative tabs, then entries of a type byte and a 32-bit position ending FF: type bits 0–3 0 left, 1 centre, 2 right, 3 decimal, 4 bar; bits 4–6 leader 0 none, 1 dots with spaces, 2 dots, 3 hyphens, 4 underscores; negative types repeat); 5 top and bottom margins (as sub-code 1); 6 justification (1 byte old, then 0 left, 1 centre, 2 right, 3 full, 4 full including the last line, 5 decimal-aligned); 7 suppress page features (2 bytes old, then 16-bit flags: 0x01 page number, 0x02 page number at bottom, 0x04 header A, 0x08 header B, 0x10 footer A, 0x20 footer B, 0x40 watermark A, 0x80 watermark B); 12 first-line indent (4 bytes old, then 32-bit fixed) |
D1 | Font | 0 text colour (6 bytes skipped, then 16-bit red, green, blue); 1 font (12 bytes skipped, then a Pascal string with the font name); 2 font size (2 bytes skipped, then size in points) |
D2 | Definition | 1 set columns: old type and count with old widths, then new type (0 off, 1 newspaper, 2 parallel, 3 extended), count, then alternating 16-bit column sizes (fractions of 65,536) and 32-bit gaps (fixed-point) |
D5 | Header, footer, watermark | sub-code 0 header A, 1 header B, 2 footer A, 3 footer B, 4 watermark A, 5 watermark B; 14 bytes skipped, the old text’s 16-bit length and text, a definition byte (bit 0 even pages, bit 1 odd pages, both all), 4 bytes, the new text’s 16-bit length and text |
D6 | Footnote or endnote | 0 footnote, 1 endnote: 25 bytes skipped, a 16-bit page count and 4 bytes per page, a 16-bit break-table count and 6 bytes per entry, then the note text |
D8 | Display | 0 date/time, 1 paragraph number, 2 overstrike, 3 search character, 4 box number, 5 chapter number, 6 page number, 7 footnote number, 8 endnote number; for 6, 7 and 8, 4 bytes skipped and then the number as shown, a Pascal string |
D9 | Miscellaneous | 4 page size: 20 bytes of old values, 16-bit orientation (bit 0: landscape), 32-bit width and height (fixed-point) |
DA | Window (boxes) | 0 figure, 1 table box, 2 text box, 3 user box, 4 equation, 5 HTML image box, 6 horizontal line. For 0–5: 14 bytes, 16-bit flags, 2 bytes, left and right column, 28 bytes, box content type (0 text, 1 and 3 picture from a PICT resource, 2 picture from a WBOX resource, 4 and 5 table), 1 byte, 16-bit resource ID, 32-bit vertical offset, horizontal offset, width and height (fixed-point), 9 bytes, a count of sub-rectangles and 8 bytes each, the caption’s 16-bit length and text, the box text’s 16-bit length and text |
DB | Style | not described |
DC | End of line or page | sub-code only: 0 soft end of line, 1 soft end of page or column, 2 hard end of line, 3 hard EOL and soft EOP, 4 temporary EOL, 5 temporary end of page or column, 6 dormant hard return, 7 hard end of page, 8 hard end of column, 9 hard EOC and soft EOP, 10 hard EOL (hard EOC outside columns), 11 hard EOL/soft EOP, 12 hard hyphen at EOL, 13 hard hyphen at EOP, 14 soft hyphen at EOL, 15 soft hyphen at EOP, 16 auto hyphen at EOL, 17 auto hyphen at EOP, 18 reserved, 19 hard beginning of file, 20 temporary hard end of column, 21 temporary hard EOC/soft EOP, 22 end of table cell, 23 reserved, 24 end of row and cell, 25 the same at a soft page break, 26 end of row and of table, 27 the same at a soft page break, 28 end of row and cell and of header rows, 29 end of row and cell at a soft page break and start of header rows, 30 and 31 reserved |
E2 | Tables | 1 table definition (71 bytes skipped, table mode, 32-bit offset from left edge, top, left, bottom and right gutters, 3 bytes, column count up to 32, then per column: mode, number format, 32-bit width, 32-bit offset for decimal alignment); 2 cell span (16-bit columns and rows, each one less than the span); 3–6 top, left, bottom, right cell line; 7–10 their colours; 11 fill colour and pattern (16-bit red, green, blue); 12 vertical alignment; 13 cell mode; 14 row mode |
Groups D3, D4, D7, DD to
E1 and E3 to EF, and the sub-codes whose data
is not listed, are skipped by libwpd using the length; their contents are not
public.
Sources
- libwpd source –
WP1FileStructure,WP1Parser,WP1Heuristics,WP1*Group,WP1ContentListener;WP3FileStructure,WP3Parser,WP3Part,WP3SingleByteFunction,WP3*Group,WP3ResourceFork,WP3ContentListener,WP3StylesListener;WPXHeader,WPDocument - WordPerfect for DOS Updated: software and file formats – lists the surviving format documents, including the confidential Macintosh 3.5e manual that is not used here