
The hidden genie of the Writeln statement.
-----------------------------------------

If you use Turbo Pascal and need a formatted string for something else than
a text file you might think that your heading in to a lot of troublesome
assembler coding.

However, every opened text device in TP is associated with a text file
variable, a record structure with the size of 256 bytes. A type definition
for the record can be found in the Dos unit as "TextRec". The last item
of this record is an char array named "Buffer". Formatted output from the
Writeln statement is normally stored in this line buffer when control is
turned over to the text device for processing.

The size of a text file variable can not be changed, it is always 256
bytes, but you can change everything else in the variable and there is
a text device that doesn't change a bit about what ends up in it's buffer,
the "NUL" device. This is where the trickery and the fun comes in.

A predefined structure in a TP program such as the text type can be
accessed in any way you want, by combining two different methods for
looking at data structures. Those two methods are called variable
typecast and absolute variable declarations. You can superimpose a
logical structure over the memory area of a predefined variable of any
type. The "absolute" clause in the declaration of a variable creats an
identifier for such a logical structure. An variable typecast is done in
a code statement by using a type identifier as an prefix for a variable
identifier.

To get access to the sleeping "NUL" device line buffer we first need to
declare a file variable of type text and declare a data structure that
makes it as easy as possible to access the line buffer as an string variable.

      var   f      : text;
      type  pstr =  record
                       len : byte;  buf : array[1..200] of char;
                    end;
            TextInfo = record
                          handle : word;
                          mode   : word;
                          booboo : array[1..44] of byte;
                          name   : array[1..3]  of char;
                          zero   : byte;
                          str    : pstr;
                       end;

The TextInfo structure does not need to be the same size as a text variable,
however it must not exceed it's size. With that in mind we can declare an
identifier for the logical structure of type TextInfo at the location of the
text file variable 'f'.

      var  alias : TextInfo absolute f;

What we have now is a text variable 'f' with a line buffer of 128 bytes.
We have created 'f' with the only purpose of being associated to the
"NUL" device and directly before the line buffer is an 80 byte storage
place for the device name and an ending zero. The "NUL" device name and
the zero uses only four bytes, thus we can extended the line buffer with
76 extra bytes. The str record in the alias structure overlaps the 76 bytes
and the original line buffer area. We can make the extra space available
by using TP's procedure SetTextBuf.

      SetTextBuf(f,alias.str.buf);

Now we can access the line buffer of the text variable 'f' as an string
variable by doing an variable type cast on the alias.str identifier. The
variable type cast is contrary to the absolute clause, size sensitive.
The type used for the type cast and the variable has to be of the same byte
size. But that's easy, we just declare a string type of the same
size as the line buffer area.

      type  str200 = string[200];

      FmtStr := str200(alias.str);  or  with alias do str200(str) := #13;

That's it, the hidden genie of the Writeln statement is ready to serve you
formatted strings at your will.


/Boz,

