Skip to content

WGML Common File Blocks

Jiri Malak edited this page Feb 20, 2021 · 6 revisions
Table of Contents

Introduction

This page is used to describe elements of :DEVICE, :DRIVER and :FONT blocks that are common to two or more of them.

This section exists to force the Wiki to provide a Table of Contents (which requires more than three sections).

Common Attributes

The attributes defined_name and member_name are found in :DEVICE blocks, :DRIVER blocks, and :FONT blocks, and are treated identically in each case.

These attributes are used to identify the specific block they are in to wgml and gendev. They do not appear in the same binary member file as the rest of that block's entries (although the attribute member_name is used as the name of that file): they appear instead in the directory file entry created when the source file is processed. They are both character strings.

These attributes are required in the sense that, if they are missing, gendev produces this error message:

AT--001: Required attribute not found.

gendev does not, however, object if either or both are given as empty strings.

If the attribute defined_name is an empty string, then the field defined_name in the directory file consists in the single byte "0x00" which wgml will match with an empty string used in either of two contexts:

  • as the value of the command-line option DEVICE; and
  • as the value of the attribute driver_name in a :DEVICE block.

The restrictions imposed by gendev on the attributes font and fontname in all cases except the :UNDERSCORE block made it impossible to verify that an empty string for these attributes would match a font with an empty string for the value of attribute defined_name (see the discussion at the end of The :UNDERSCORE Block for further speculation on the effect of an empty string as the value of attribute font in an :UNDERSCORE block).

If the attribute member_name is empty, then a gendev error occurs, so an empty field member_name should never be found.

The functions in "copdir.c" accept an empty string for field defined_name but treat an empty string for member_name as an error condition.

The attribute defined_name has a documented limit of 78 characters.

The attribute member_name has some interesting properties when used with the DOS version of gendev 4.1 (and so when used with the FAT file system):

  • if it does not contain a ., then the first eight characters are taken as the file name and ".cop" is used as the extension; the directory file entry, however, will show all the characters given as the file name (and no extension).
  • if it does contain a ., then the first eight characters before the . are taken as the file name and the first three characters after the . are taken as the extension; the directory file entry, however, will show all the characters given.
  • if it contains more than one ., then this error is produced:
IO--004: Output operation failed.

If an empty string was given for the attribute member_name, then error IO--004 occurs. This indicates that gendev does not check the value of the attribute to screen out an empty string but rather that the file system rejects a nonexistent filename.

When gendev and wgml are implemented, it will be necessary to further explore the file-naming behavior associated with the attribute member_name.

The :INTRANS Block

The description of the :INTRANS block given in the WGML 4 Reference is still correct:

:INTRANS.
   font-character input-translation
:eINTRANS.

This block does not have attributes. Both font-character and input-translation are character values.

An empty :INTRANS block (one with no entries) is the same as no :INTRANS block at all: gendev ignores it.

gendev 3.33 enforces a limit of "$ff" on the character values with this message:

SN--001: Number is too large or contains invalid characters

gendev 4.1 will accept, for example "$feff" but treats it as if it were "$ff". There is, then, no point in using values larger than $ff.

If an :INTRANS block with more than two characters on a line is input, that is, one like this:

:INTRANS.
   b c d
:eINTRANS.

then gendev accepts the input but produces exactly the same encoding that

:INTRANS.
   b c
:eINTRANS.

produces. The :INTRANS block, then, cannot be written on one line, at least if it has more than one entry.

Multiple :INTRANS blocks, whether identical or different, are allowed in the source file. They are merged into a single entry in the binary file. If the same character is given for translation in more than one block, the translation in the last block will be used:

:INTRANS.
   b c
:eINTRANS.

:INTRANS.
   b c
:eINTRANS.

maps 'b' to 'c' and

:INTRANS.
   b c
:eINTRANS.

:INTRANS.
   d c
:eINTRANS.

maps both 'b' and 'd' to 'c' but

:INTRANS.
   b c
:eINTRANS.

:INTRANS.
   b d
:eINTRANS.

maps 'b' to 'd' in the binary file.

The corresponding struct in the binary file is:

IntransBlock {
   uint8_t designator = 0x81;
   uint8_t count = 0x00;
   uint8_t table[0x100];
};

The value of the field designator is always "0x81".

The value of the field count is always "0x00".

If the field table is treated as an array, then, given the first mapping above, table['b'] would be 'c', as would table['c']. The effect is to create an array of 0x100 byte values, each entry in which is equal to its index, and then, for each font-character, to place the input-translation character into table[font-character]. No instances of any other form are known.

The IntransBlock, when present, is part of the TranslationBlock (for binary device files) or the CharacterDescriptionBlock (for binary font files). It has the structure shown above in either case.

The :OUTTRANS Block

The description of the :OUTTRANS block given in WGML 4 Reference is still correct:

:OUTTRANS.
   font-character output-translation
:eOUTTRANS.

This block does not have attributes. Both the font-character and the output-translation are character values.

The output-translation can be either a single character value or a sequence of single character values separated by spaces.

An empty :OUTTRANS block (one with no entries) is the same as no :OUTTRANS block at all: gendev ignores it.

gendev 3.33 enforces a limit of "$ff" on each character value with this message:

SN--001: Number is too large or contains invalid characters

gendev 4.1 behaves differently when, for example, "$feff" is used as the font-character and when it is used as one of the characters in the output-translation:

  1. If the value of the font-character is "$feff", a GP-fault results.
  2. If the value of one of the characters in the output-translation is "$feff", it is treated as if it were "$ff".

So there is no point to using character values higher than "$ff".

Multiple :OUTTRANS blocks, whether identical or different, are allowed in the source file. They are merged into a single entry in the binary file. If the same character is given for translation in more than one block, the translation in the last block will be used:

:OUTTRANS.
   ( \ (
:eOUTTRANS.

:OUTTRANS.
  ( \ (
:eOUTTRANS.

maps '(' to '\(' and

:OUTTRANS.
   ( \ (
:eOUTTRANS.

:OUTTRANS.
   { \ (
:eOUTTRANS.

maps both '(' and '{' to '\(' but

:OUTTRANS.
   ( \ (
:eOUTTRANS.

:OUTTRANS.
   ( \ {
:eOUTTRANS.

maps '(' to '\{' in the binary file.

Since gendev takes all but the first character to be the output-translation for the first character, it follows that the :OUTTRANS block cannot be written on one line, at least, not if it contains more than one entry.

When no line of the :OUTTRANS block contains more than one character in the output-translation, then the corresponding struct in the binary file is:

OuttransBlock {
   uint8_t designator = 0x81;
   uint8_t count = 0x00;
   uint8_t table[0x100];
};

The value of the field designator is always "0x81".

The value of the field count is always "0x00".

If the field table is treated as an array, then, given the first mapping above, table['b'] would be 'c', as would table['c']. The effect is to create an array of 0x100 byte values, each entry in which is equal to its index, and then, for each font-character, to place the input-translation character into table[font-character].

This is identical to the struct used for the IntransBlock.

If at least one line of the :OUTTRANS block contains more than one character in the output-translation, then the corresponding struct in the binary file is:

OuttransBlock {
    uint8_t      designator = 0x82;
    uint8_t      count;
    uint16_t     table[0x100];
    OuttransData translations[count]
};

The value of the field designator is always 0x82.

The field count is an 8-bit unsigned integer and its value is always identical to the value of the field TranslationBlock.data_count. The value of the field count is the number of bytes in the field data. Although the upper bound of field count has not been determined, the size of translations is almost certainly limited to $FF at most.

The field table consists of 0x100 two-byte entries:

  1. If a character is not being translated, then the first byte is the character itself (the value of the index if the table is regarded as an array) and the second byte is "0x00".
  2. If a character is being translated to a single character, then the first byte is the character it is to be translated to and the second byte is "0x00".
  3. If a character is being translated to more than one character, the first byte is the offset into the data to the beginning of the output characters to be used. The second byte is "0x82".

The field translations is an array of these structs:

OuttransData {
   uint8_t  count;
   uint8_t  data[length];
}

The fields count and data together encode the output-translation.

Something odd happens when these conditions are satisfied:

  • More than one :OUTTRANS block exists.
  • The same font-character appears in more than one :OUTTRANS block with a translation to more than one character.

What happens is that all entries in field translations but the last entry for that font-character contain the bytes "0x03 0x50 0x0c 0xff" (which is an OuttransData struct with a count of "0x03" and a translation value of "0x50 0x0c 0xff"). This happens whether the output-translations for the font-character are the same or different. In the field table, an offset to this sort of entry is never found.

It is unclear why this sort of entry is needed. Since it is four bytes in length, the data area and all affected offsets must be adjusted if the former output-translation had either more or less than 4 bytes, so why not just replace it with the new value? Or remove it entirely and put the new one at the end of the table?

The OuttransBlock, when present, is part of the TranslationBlock (for binary device files) or the CharacterDescriptionBlock (for binary font files). It has the structure shown above in either case.

Clone this wiki locally