Top Method Summary
Options Name Purpose
Append (character) Appends the given value to the output buffer
AppendEscaped (longchar) Appends the escaped form of the given value to the output
AppendLongchar (longchar) Appends the given longchar value to the output
INTEGER BigEndian (memptr, integer, integer) Returns the big endian integer the given bytes hold
INTEGER BlueOf (integer) Returns the blue part of the given RGB value
CloseOpenBlock (integer, integer, integer) Writes the terminator of the block that is still open, and the row terminator when that block was the last one of its row
CollectResources (TextDocument) Collects the font names, the colors and the stylesheet entries the document needs
INTEGER ColorNumFor (integer) Returns the color table number of the given RGB value
EnsureColor (integer) Adds the given color to the color table when it is not in it yet
EnsureFont (longchar) Adds the given font name to the font table when it is not in it yet
EnsureStyle (integer) Adds the given stylesheet number to the styles the document needs
LONGCHAR EscapeText (longchar) Escapes the given value for use in an RTF document
Flush () Flushes the output buffer into the longchar result
INTEGER FontNumFor (longchar) Returns the font table number of the given font name
INTEGER GreenOf (integer) Returns the green part of the given RGB value
LONGCHAR HexEncode (memptr) Returns the hex representation of the given bytes
LOGICAL ImageSize (memptr, character, integer, integer) Returns the pixel size of the given image
INTEGER ListNumOfItem (TextDocument) Returns the number of the list of the list table the list item the given document is positioned on belongs to
INTEGER NumberFormatOf (TextDocument) Returns the levelnfc value of the list item the given document is positioned on
OpenRowIfNeeded (TextDocument) Writes the row definition when the given block opens a new row
INTEGER PutAscii (memptr, integer, character) Writes the given ASCII value into the target
INTEGER PutEscapedAscii (memptr, integer, integer) Writes the escape of a single ASCII byte into the target
INTEGER RedOf (integer) Returns the red part of the given RGB value
ResetState () Resets the writer state so that an instance could be reused
CHARACTER RunControls (TextRunFormat) Returns the control words of the character formatting of a run
INTEGER RunFontNum (TextRunFormat) Returns the font table number a run has to select
CHARACTER UnderlineControl (UnderlineStyleEnum) Returns the control word of an underline style
CHARACTER UnicodeEscape (integer) Returns the unicode escape of the given code point
LONGCHAR Write (TextDocument) Writes the given TextDocument out as an RTF document
WriteBlock (TextDocument) Writes one block of the document
WriteBlockAlignment (BlockAlignmentEnum) Writes the alignment control word of the block that is being written
WriteBlockIndent (TextDocument) Writes the left indentation control word of the block that is being written
WriteHeader () Writes the header of the RTF document
WriteImageRun (TextDocument) Writes an embedded image as a picture group
WriteListPrefix (TextDocument) Writes the paragraph properties of a list item
WriteListTable () Writes the list table and the list override table
WriteRowDefinition (integer, integer, logical) Writes the definition of one table row
WriteRuns (TextDocument) Writes the runs of the block the given document is positioned on
WriteStyleEntry (integer) Writes one entry of the stylesheet
WriteTextRun (TextDocument) Writes a single text run

Top Constructor Summary
Options Name Purpose
RtfWriter () Creates a new RtfWriter instance


Method Detail
Top

Append (character)

Purpose: Appends the given value to the output buffer
Notes: Flushes the buffer into the result first when the value would
take it past the CHARACTER limit

Parameters:
pcValue CHARACTER
The value to append
Top

AppendEscaped (longchar)

Purpose: Appends the escaped form of the given value to the output
Notes:

Parameters:
plcValue LONGCHAR
The value to escape and append
Top

AppendLongchar (longchar)

Purpose: Appends the given longchar value to the output
Notes: The escaped text of a run and the hex data of an image can be
longer than the CHARACTER limit on their own, so the buffer is
flushed and the value is appended to the LONGCHAR result

Parameters:
plcValue LONGCHAR
The value to append
Top

INTEGER BigEndian (memptr, integer, integer)

Purpose: Returns the big endian integer the given bytes hold
Notes:

Parameters:
pmData MEMPTR
The bytes to read from
piFrom INTEGER
The position of the first byte
piCount INTEGER
The number of bytes the value occupies
Returns INTEGER
The integer value
Top

INTEGER BlueOf (integer)

Purpose: Returns the blue part of the given RGB value
Notes:

Parameters:
piRgb INTEGER
The RGB value
Returns INTEGER
The blue part, 0 to 255
Top

CloseOpenBlock (integer, integer, integer)

Purpose: Writes the terminator of the block that is still open, and the
row terminator when that block was the last one of its row
Notes: The last paragraph of a cell is terminated by cell rather than
by par - a par in front of the cell would give the cell an
empty paragraph it never had. Which paragraph of a cell is the
last one is only known once the next block is there, which is
why the terminator lags one block behind.

Parameters:
piTableId INTEGER
The table of the block that follows, 0 at the end of the document
piRowIndex INTEGER
The row of the block that follows, 0 at the end of the document
piCellIndex INTEGER
The cell of the block that follows, 0 at the end of the document
Top

CollectResources (TextDocument)

Purpose: Collects the font names, the colors and the stylesheet entries
the document needs
Notes: Walks the whole document once before anything is written, so
that the tables of the header are complete and in the order of
first use

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument to collect the resources of
Top

INTEGER ColorNumFor (integer)

Purpose: Returns the color table number of the given RGB value
Notes:

Parameters:
piRgb INTEGER
The RGB value to look up
Returns INTEGER
The color table number, or 0 when the value is not in the table
Top

EnsureColor (integer)

Purpose: Adds the given color to the color table when it is not in it yet
Notes:

Parameters:
piRgb INTEGER
The RGB value of a run
Top

EnsureFont (longchar)

Purpose: Adds the given font name to the font table when it is not in it yet
Notes: The names are compared through TextRunFormat:IsSameText, which
works on the bytes - an ABL comparison would collate them
through -cpinternal and raise for a name the session code page
does not know

Parameters:
plcFontName LONGCHAR
The font name of a run
Top

EnsureStyle (integer)

Purpose: Adds the given stylesheet number to the styles the document needs
Notes:

Parameters:
piStyleNum INTEGER
The stylesheet number to add
Top

LONGCHAR EscapeText (longchar)

Purpose: Escapes the given value for use in an RTF document
Notes: The backslash and the two braces are escaped, a tab and a line
feed become their control word, the remaining control
characters are dropped, and every character outside the ASCII
range becomes a \uN? escape - N as a signed 16 bit value, a
character above the Basic Multilingual Plane as its two
surrogates. No code page can lose a character that way, which
is why the writer does not emit \'hh escapes at all.
The single question mark behind an escape is its fallback
character; the header declares \uc1, so a reader that does not
understand \u skips exactly that one character.

Parameters:
plcValue LONGCHAR
The value to escape
Returns LONGCHAR
The longchar with the escaped value, fixed to UTF-8
Top

Flush ()

Purpose: Flushes the output buffer into the longchar result
Notes:

Top

INTEGER FontNumFor (longchar)

Purpose: Returns the font table number of the given font name
Notes:

Parameters:
plcFontName LONGCHAR
The font name to look up
Returns INTEGER
The font table number, or -1 when the name is not in the table
Top

INTEGER GreenOf (integer)

Purpose: Returns the green part of the given RGB value
Notes:

Parameters:
piRgb INTEGER
The RGB value
Returns INTEGER
The green part, 0 to 255
Top

LONGCHAR HexEncode (memptr)

Purpose: Returns the hex representation of the given bytes
Notes: Consultingwerk.Util.MathHelper:Int2Hex is deliberately not
used here - it strips leading zeros, so it would not produce
the fixed two digits per byte a picture group needs, and its
bit loop would run once per byte of an image

Parameters:
pmData MEMPTR
The bytes to encode
Returns LONGCHAR
The longchar with the hex data, fixed to UTF-8
Top

LOGICAL ImageSize (memptr, character, integer, integer)

Purpose: Returns the pixel size of the given image
Notes: The PNG size is the IHDR chunk, which always sits at a fixed
offset; the JPEG size is the first start of frame marker,
which has to be found by walking the segment headers

Parameters:
pmData MEMPTR
The image bytes
pcMimeType CHARACTER
The MIME type of the image
piWidth INTEGER
The width of the image in pixels
piHeight INTEGER
The height of the image in pixels
Returns LOGICAL
TRUE when the size could be read
Top

INTEGER ListNumOfItem (TextDocument)

Purpose: Returns the number of the list of the list table the list item
the given document is positioned on belongs to
Notes: One list per list of the model - a list starts where
TextDocument:StartsNewList StartsNewList says so, and a sublist is a list of
its own. Word and the Telerik editor number the items of one
ls per level from the levelstartat of the list, so a sublist
that shared the ls of its parent would restart at the same
number under every parent item, whatever the model says; with
a list of its own it starts at the number of its own first item
(SCL-5863).
Called for every list item by both passes over the document,
which is what makes the numbers of the list table
CollectResources builds the ones WriteListPrefix writes: the
numbers are handed out in the order of the lists in the
document, and the state is reset in front of each pass.
The first pass records the list in ttList.

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument positioned on the list item
Returns INTEGER
The ls number of the list
Top

INTEGER NumberFormatOf (TextDocument)

Purpose: Returns the levelnfc value of the list item the given document
is positioned on
Notes: 0 decimal, 1 upper case roman, 2 lower case roman, 3 upper case
letters, 4 lower case letters, 23 the bullet - the values the
RtfReader maps back (SCL-5863)

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument positioned on the list item
Returns INTEGER
The levelnfc value
Top

OpenRowIfNeeded (TextDocument)

Purpose: Writes the row definition when the given block opens a new row
Notes:

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument positioned on the block to write
Top

INTEGER PutAscii (memptr, integer, character)

Purpose: Writes the given ASCII value into the target
Notes: Used for the escapes only, which are ASCII by construction

Parameters:
pmTarget MEMPTR
The memptr to write to
piPos INTEGER
The position to write at
pcAscii CHARACTER
The ASCII value to write
Returns INTEGER
The position behind what was written
Top

INTEGER PutEscapedAscii (memptr, integer, integer)

Purpose: Writes the escape of a single ASCII byte into the target
Notes: A carriage return is dropped because the line feed of the pair
carries the break, and the remaining control characters have
no representation in RTF at all

Parameters:
pmTarget MEMPTR
The memptr to write to
piPos INTEGER
The position to write at
piByte INTEGER
The byte to escape
Returns INTEGER
The position behind what was written
Top

INTEGER RedOf (integer)

Purpose: Returns the red part of the given RGB value
Notes:

Parameters:
piRgb INTEGER
The RGB value
Returns INTEGER
The red part, 0 to 255
Top

ResetState ()

Purpose: Resets the writer state so that an instance could be reused
Notes:

Top

CHARACTER RunControls (TextRunFormat)

Purpose: Returns the control words of the character formatting of a run
Notes: The order is fixed, which is part of what makes the output
deterministic. The returned value never ends with a blank -
the caller adds the one that delimits the last control word
from the text.

Parameters:
poFormat Consultingwerk.Util.DocumentConverter.TextRunFormat
The character formatting of the run
Returns CHARACTER
The character with the control words, empty when the run carries no formatting
Top

INTEGER RunFontNum (TextRunFormat)

Purpose: Returns the font table number a run has to select
Notes: A run marked as Code takes the monospace slot of the font
table - that slot is how RTF expresses the flag - and since a
run cannot select two fonts, a font name on a Code run is
dropped. HTML expresses both and does not lose it.

Parameters:
poFormat Consultingwerk.Util.DocumentConverter.TextRunFormat
The character formatting of the run
Returns INTEGER
The font table number, or -1 when the run selects no font at all
Top

CHARACTER UnderlineControl (UnderlineStyleEnum)

Purpose: Returns the control word of an underline style
Notes: One control word per style of the model, which the RtfReader
maps back to that style (SCL-5859). Single is the plain ul, so
that a plain underline writes what it always wrote.

Parameters:
poStyle Consultingwerk.Util.DocumentConverter.UnderlineStyleEnum
The underline style of the run
Returns CHARACTER
The character with the control word
Top

CHARACTER UnicodeEscape (integer)

Purpose: Returns the unicode escape of the given code point
Notes: A code point above the Basic Multilingual Plane is written as
its two UTF-16 surrogates, which is how every editor writes an
emoji; the parameter is the signed 16 bit value the RTF
specification asks for

Parameters:
piCodePoint INTEGER
The Unicode code point to escape
Returns CHARACTER
The character with the escape
Top

LONGCHAR Write (TextDocument)

Purpose: Writes the given TextDocument out as an RTF document
Notes: An empty document yields an empty value, never the unknown
value and not an empty RTF document either - an empty value is
what the converter short circuits on

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument to write out
Returns LONGCHAR
The longchar with the RTF document
Top

WriteBlock (TextDocument)

Purpose: Writes one block of the document
Notes: Every block begins with pard, so that the paragraph properties
of the preceding block cannot leak into it. The terminator of
the block is not written here - see CloseOpenBlock.

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument positioned on the block to write
Top

WriteBlockAlignment (BlockAlignmentEnum)

Purpose: Writes the alignment control word of the block that is being
written
Notes: Nothing is written for the unset alignment - see WriteBlock

Parameters:
poAlignment Consultingwerk.Util.DocumentConverter.BlockAlignmentEnum
The alignment of the block
Top

WriteBlockIndent (TextDocument)

Purpose: Writes the left indentation control word of the block that is
being written
Notes: 720 twips per level, which is the step the RtfReader reads
back and the step Word, WordPad and the Telerik editor use.
Nothing is written for a block that is not indented - see
WriteBlock.
A list item is left alone: its indentation is the one of the
list, written by WriteListPrefix, and the model holds no
indentation of its own for it anyway (SCL-5856). The guard is
here so that the rule can be read off this writer as well as
off TextDocument:SetBlockIndentLevel.

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument positioned on the block to write
Top

WriteHeader ()

Purpose: Writes the header of the RTF document
Notes: The font table always declares the default and the monospace
font; the color table and the stylesheet are only written when
the document needs them. No character formatting is applied
here - see the notes of the class.

Top

WriteImageRun (TextDocument)

Purpose: Writes an embedded image as a picture group
Notes: Only PNG and JPEG are written - they are the two picture types
the reader keeps. The pixel size is taken from the image
header when it can be read; without it the size hints are
omitted, which the editors accept.

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument positioned on the image run to write
Top

WriteListPrefix (TextDocument)

Purpose: Writes the paragraph properties of a list item
Notes: ls names the list of the list table the item belongs to and
ilvl its nesting level; the indentation follows at 720 twips
per level, which is what Word, WordPad and the Telerik editor
use. The list table carries the numbering type and the start
number of the list - see WriteListTable. Ends with a control
word, so the delimiting blank is written here.
Neither a pn destination nor a label group is written
(SCL-5863), both deliberately, and both verified against the
engines themselves:
- The Telerik RadRichTextEditor reads the ls construct only; a
pn destination it ignores, so a list written as one showed as
indented paragraphs in the SmartCommentControl.
- Word follows a pn destination whenever a paragraph carries
one, ls notwithstanding - it then counts on across two
adjacent lists of the same numbering type and does not treat
a sublist as a level of its list. Written after the ls, the
pn destination breaks the numbering of Word altogether.
- WordPad prints a listtext group - with or without the
asterisk of an ignorable destination - as text of the item.
Word and the Telerik editor compute the label from the list
table and need none.
The price is WordPad: it reads the ls construct and shows the
numbers right, except that it counts on across two directly
adjacent lists of the same numbering type.

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument positioned on the list item to write
Top

WriteListTable ()

Purpose: Writes the list table and the list override table
Notes: One list per list of the document. A list holds the levels up
to the nesting level its items sit on, all carrying the
numbering type and the start number of the list - the items
only ever use the deepest one. Word and the Telerik editor
write nine levels per list; they, and WordPad, read a list
with fewer levels the same way (verified), and the nine would
make the list table of a document with a dozen lists several
times the size of its text. The listid and the ls of a list are
its number, so the output stays deterministic (SCL-5863).

Top

WriteRowDefinition (integer, integer, logical)

Purpose: Writes the definition of one table row
Notes: The cell count of the row has to be known before its first
cell is written, because the cellx boundaries are part of the
definition - that is what TextDocument:GetTableRowCellCount is
for, and it is the one lookup the flat cursor cannot answer

Parameters:
piTableId INTEGER
The table the row belongs to
piRowIndex INTEGER
The row within that table
plHeader LOGICAL
TRUE for a header row
Top

WriteRuns (TextDocument)

Purpose: Writes the runs of the block the given document is positioned on
Notes:

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument positioned on the block to write
Top

WriteStyleEntry (integer)

Purpose: Writes one entry of the stylesheet
Notes: The entry carries the visual formatting of the style, which is
how a heading keeps its appearance without that formatting
reaching the runs of the paragraph. The style name is what the
reader recognizes the style by.

Parameters:
piStyleNum INTEGER
The stylesheet number to write the entry of
Top

WriteTextRun (TextDocument)

Purpose: Writes a single text run
Notes: A run that carries formatting is written in a group of its
own, so that its control words end where the run ends. A
hyperlink is written as the HYPERLINK field the three editors
produce. Its quoted target never holds a double quote that
would end it early - TextRunFormat stores one as %22 (SCL-5864).

Parameters:
poDocument Consultingwerk.Util.DocumentConverter.TextDocument
The TextDocument positioned on the run to write


Constructor Detail
Top

RtfWriter ()

Purpose: Creates a new RtfWriter instance
Notes: The result is fixed to UTF-8 here rather than in Write,
because FIX-CODEPAGE can only be applied to a LONGCHAR that
has no value yet



©2006-2026 Consultingwerk Ltd.         info@consultingwerk.de         http://www.consultingwerk.de       19.09.2026 10:19:22