Oberon/Text

Confusingly for a novice, three forms of line ending can be found in text files in contemporary computer systems.
 * In Oberon and some other systems (most prominently Classic MacOS), a line of text ends with the carriage return character, denoted CR.
 * In Unix-like and some other systems, a line of text ends with the line feed character denoted LF.
 * In DOS, Microsoft Windows and some other systems, a line of text ends with the two characters, CR and LF.

This multiplicity poses no difficulty in Oberon; most Oberon systems allow convenient editing with any of these line endings.

Also confusing for a novice, an Oberon Text can appear at the first sight to be no more than a plain text comprising a sequence of ASCII characters. Nevertheless Text in Oberon is a type defined in the Text module. A Text of this type is a sequence of characters including non-printing characters. A character in a Text can have attributes including typeface, size and color. Furthermore a Text can include non-character objects; an image or a hyperlink for example. Consequently two displayed documents, one an Oberon Text and the other an HTML text, can have the same appearance and the same behavior of links.

Editing a Text
Each Oberon system has an Edit module. If  appears almost anywhere on the screen, a MM on   will open a viewer. If a file named Example.Text exists, it's content will appear in the viewer. If no file with the name exists, the viewer will be empty. The caret can be set by ML and characters can be inserted using a keyboard. In addition to Edit, ETH Oberon has ET and the Gadgets subsystem. Commands  and   are available. ETH Oberon also has the Hex module providing a hexadecimal editor with command.

Programmatical Access to a Text
A Text can be manipulated using procedures in the Texts module; for ETH Oberon and for V5. Also summarized for ETH Oberon in DEFINITION Texts.

To read a Text programmatically, a RECORD termed a Reader is opened on the Text at a specified offset. (A Reader is a RECORD; not a procedure.) With reader open, the Read(reader, ch) procedure retrieves a character each time it is executed as in this fragment from ETH Oberon. VAR T: Texts.Text; R: Texts.Reader; ch: CHAR; BEGIN NEW(T); Texts.Open(T, “Texts.Mod“); Texts.OpenReader(R, T, 0); Texts.Read(R, ch); WHILE ~R.eot DO     Out.Char(ch); Texts.Read(R, ch) END END The font of a character is referenced in the Objects.Library of the Reader. The Reader also has fields, col, the color of the character and voff, vertical offset of the character. After an execution of Read(reader, ch), the freshly read character is available in ch and attributes are in the components of reader. This assumes that the object read was a character as evidenced by (reader.lib IS Fonts.Font) being TRUE. Each execution of Read advances reader through the Text by one character until the end is reached and reader.eot becomes TRUE.

How Text Works ...
These tables show the structure of records in memory representing a Text. When Texts.Store records a Text in a file for a storage medium, the information in the record structure is serialized. In the inverse process, Texts.Load deserializes the information to the record structure of the Text in memory.

Click on a hyperlink to see the module where a type is defined.

Texts.FindPiece and the cache
For a given Text, T, and offset pos in [0, T.len), procedure Texts.FindPiece has the task of locating the piece containing pos. At each execution, FindPiece could begin at offset 0 and add lengths of pieces until the piece containing pos is located. A cache based upon T.pce and T.org allows better efficiency. When FindPiece completes a search, the pointer to the found piece is recorded in T.pce; the offset of the first character of that piece is recorded in T.org. The next execution of FindPiece begins at that cached location. With a result from FindPiece often being near the preceeding result, this strategy avoids repeated summation of lengths from the beginning of the first piece.