Qs: Quickscript

Quickscript Layout Mechanism

If you want to tailor Quickscript, modifying how existing layout marks work or creating new layout marks, you will need to understand how the Quickscript machinery processes layout marks.

Quickscript contains a table


an array of arrays. Each array within Kwrd contains three items:

First element in a Kwrd item The keyword string, eg. (FN), identifying the keyword.
The second element in a Kwrd item The keyword procedure, which will be run to implement the keyword.
The text following the keyword string is put on top of the stack before the procedure is run. That is, a layout mark %FN,Cou% will match a keyword string of (FN), and (,Cou) will be put on the stack to be available to the procedure. A layout mark %FN% will also match (FN), and the empty string () will be put on the stack before running the procedure.
The third element in a Kwrd item The keyword flags, indicating how the keyword is to be processed and when the procedure is to be run. The flags are built as bitwise-OR of the following codes:
1 = line-breaking This indicates that the text already received should be output immediately, as following text will not influence its layout. Obvious examples include %L% or %P%; more subtle would be %PS, which could have any type of effect on the output; because the effect of PostScript code is unpredictable as far as Quickscript is concerned, we are forced to assume the worst. Keywords that move the current point to a defined place will always be line-breaking.
2 = output-producing This keyword will itself put output on the page which will have to be measured. The implication of setting this bit is firstly that the procedure can only be executed when Quickscript is ready to put it on the page, and secondly, that there will be an entry in the MeasureK procedure to determine the amount of space on the page that output of this keyword will occupy. An example of this will be %C,code% or %_%. However, %VL would not be classed as output-producing, even though it will cause a line to be drawn eventually, because the line produced will not affect the placement of preceding or following text.

"Output-producing" and "line-breaking" are mutually exclusive.
4 = start-recording This keyword turns off normal processing of the input stream, instead recording the incoming text in a buffer (RecBuf). Any layout marks in the input stream will be written to RecBuf without being processed, unless they are of type "end-recording".
8 = end-recording This keyword will process the text in RecBuf in some way, and will decrement the count of the number of "start-recording" keywords so far met. If this count reaches zero, normal processing of the input stream will resume.

"End-recording" and "start-recording" are mutually exclusive.
It is possible for a keyword to have none of these flags set. Such keywords must be capable of being executed when text is being measured and again when it is being output without risk of side-effects from either the premature or second execution.

Quickscript processes all layout marks until

  1. text to be output is encountered, or
  2. an output-producing keyword is encountered, or
  3. a "start-recording" keyword is encountered.

In cases 1) or 2), the input stream is now processed word at a time, each word being measured to see if it will fit on the current line. The accumulated text is output when the output line is filled, or when a "line-breaking" or "start-recording" layout mark is encountered. A "line-breaking" mark will cause the input text to be processed again keyword by keyword.

In case 3), the input stream is recorded to RecBuf, being checked for layout marks that have "start-recording" or "end-recording" status. Any other layout marks are simply included with the text in RecBuf. RecBuf is cleared when an "end-recording" layout mark causes the count of recording marks to be decremented to zero. It is possible by this scheme to record text for multiple purposes, but only one buffer is used and the text is recorded from the first "start-recording" mark, for use when an "end-recording" mark is found.

At the start of Quickscript execution, it places a number and a mark on the stack. At various stages during its execution, other information is put on the stack beneath the mark, with the number changed accordingly. This means of recording internal state information should not be interfered with in any PostScript included within a Quickscript document, for the effects will be unpredictable.

When embedded PostScript is executed, the current point is recorded beneath the mark, so if the embedded PostScript finishes with no current point existing, it can be recovered from the stack.

Graham Freeman