Dynamic HTML has enabled the presentation of user interfaces as documents the user can interact with. None of the traditional GUI components can deal with the mixture of properly formatted text with (interactive) graphics. XPCE provides support using a set of primitive classes that realise a box-model based on TeX . This basic model is enhanced using a Prolog library providing HTML-based primitives. First we will introduce the basics.
<->width, 
realise alignment and adjustment and can place text around floating 
objects.
Before discussing the library we show a small example using the primitives directly.
parbox :-
        send(new(W, window), open),
        send(W, display, new(P, parbox(W?width)), point(10,10)),
        send(W, resize_message, message(P, width, @arg2?width-20)),
        
        send(P, alignment, justify),
        send_list(P,
                  [ append(grbox(box(40,40), left)),
                    cdata('This is the central class of the '),
                    cdata('document-rendering support.  It is '),
                    cdata('a subclass of '),
                    cdata('device', style(underline := @on)),
                    cdata(', placing '),
                    cdata('hbox', style(underline := @on)),
                    cdata(' objects as words within a paragraph. '),
                    cdata('Parbox devices have a <->width, realise '),
                    cdata('alignment and adjustment and can place text '),
                    cdata('around '),
                    cdata('floating ', style(font := italic)),
                    cdata(' objects.')
                  ]).
 
| Figure 29 : A parbox floating text around a box | 
In line 4, we forward changes to the width of the window to the
parbox to force 
reformatting the text if the width of the window changes. Line 6 asks 
for a straight right-margin. Line 8 appends a box 
that is left aligned, the text floating around it. The remaining lines 
append text. The method `parbox->cdata' 
breaks the argument into words and adds instances of tbox 
for each word, separated by instances of hbox 
with appropriate
rubber for each 
sequence of white-space, doing much the same as an HTML browser 
processing CDATA text.
Defining a document from Prolog text using these primitives is not attractive. This is the motivation for using a library.
The directory \bnfmeta{pcehome}/prolog/lib/doc contains 
the document-rendering library, providing HTML-oriented primitives for 
document rendering. The translation process can be extended by defining 
predicates for two multifile predicates.
The central library is library(doc/emit). This library 
defines the predicate emit/3:
ListOfTerm consists of the following instructions:
<-space_mode' 
equals preserve, spaces are preserved. Otherwise space is 
canonised, smashing multiple consecutive banks into a single (rubber) 
space.
\Action
Before handed to the above, emit/3 calls the multifile predicate doc:emit/3 passing the whole list as you can see from the definition below. This allows the user-hook to process sequences of instructions.
emit(Term, PB, Mode) :-
        doc:emit(Term, PB, Mode), !.
The file library(doc/objects) defines a number of 
globally named instances of the box classes. Appending these objects is 
like executing an action. These objects are:
| @br | Nul-dimension hbox with rubber to force a line-break. | 
| @nbsp | Non-breaking space. | 
| @hfill | Rubber hbox for alignment and centering. | 
| @space_rubber | Rubber used for hbox objects representing a space. This rubber allows for a line-break. | 
| @h<n>_above | Space above HTML section-headers. | 
| @h<n>_below | Space below HTML section-headers. | 
This section provides a partial reference to the classes and methods defining the document-rendering library. For full information, please use the ClassBrowser and check the source-code.
<-content' 
vector that starts the named anchor (see section 
11.10.3.2.
| vfont | new(vfont) | The virtual font for text | 
| link_colour | dark_green | Text-colour while rendering buttons | 
| parsep | hbox(0,8) | Skip 8 pixels between paragraphs | 
| parindent | hbox(0,0) | Do not indent paragraphs | 
| space_mode | canonical | Collapse spaces | 
| alignment | justify | Make a right-margin | 
| base_url | '' | URL for HTML hyper-links | 
<-vfont and update <-style 
and <-space to reflect the new font-settings.<-style.<-style.
The class vfont realises virtual fonts, Microsoft 
also calls these logical fonts. XPCE font 
objects are read-only. When dealing with incremental font manipulation 
it is necessary to have a font that can be manipulated. Therefore,
vfont defines a number of slots to represent the font attributes 
regardless of the fonts existence. At any time the user can request the 
best matching font using `vfont<-font'. 
The mapping between virtual font attributes and physical fonts can be 
programmed by adding clauses to the multifile predicate 
vfont:font_map/7. This class is defined in
library(doc/vfont) where you find further programming 
details.
The action subsystem processes actions (\Action) from emit/3, 
providing a hook for adding new actions. Before doing anything else, the 
hook doc:action/3 is called:
The built-in actions are:
preserve white-space or render it
canonical. Default is canonical.parskip, 
followed by parsep.<-parsep from the current mode, 
surrounded by two line-breaks (@br).<-parindent from the current mode.<-clone of the doc_mode 
object. This is essentially the same as a TeX group, scoping changes to 
the mode such as font-changes, etc.family, encoding, slant, weight,
fixed and size. See
\bnfmeta{pcehome}/prolog/lib/doc/vfont.pl for details.class(Class) defines 
the subclass of lbox used 
to instantiate, default
bullet_list. The Content is passed to emit/3, 
using the created list-object as 2nd argument.
When using a bullet_list or enum_list Content 
must translated into a sequence of li commands. Using a
definition_list, a sequence of dt and dd 
commands is expected.
<-make_item', then emit Content 
to the new item.<-frame of the pbox and send it 
the given title using
`frame->label'.bgcolour(Colour), background(Image) and
text(Colour).<-link_colour' 
and underlining to @on.<-anchor'.left,center,right,justify) 
within the box.
top, center,
bottom.<-area 
is determined by the content rather than the specified width. Text may 
be formatted left-to-write without wrapping by defining a wide parbox 
and using this option.
tr, td, col, thead 
and
tbody. Defined options are:
left or right 
floating object or centered placement.
col element, specifying parameters for the 
next column. Defined Options are span(Span) to 
apply these settings to the next Span columns and width(Spec), 
where Spec is an integer (pixels) or a term *(N), 
defining the weight for shrinking and stretching relative to other 
columns using this notation. The following defines the second column to 
be twice as wide as the first:
        [ \col(*(1)),
          \col(*(2))
        ]
->end_group'. Options 
is currently ignored.center and font to bold.In section 11.10.1 and section 11.10.3.2 we have seen the definition of the basic rendering library infrastructure. It uses concepts from TeX and HTML-3, introducing primitives for grouping, attribute settings, lists, tables and whitespace-handling.
The emit/3 predicate as described above is not intended for direct use though. It is hard to imagine a good syntax for defining significant amounts of formatted text in a Prolog text-file. In some cases it is feasible to define a suitable set of new commands and use emit/3 directly from Prolog. In most cases you'll want to use tokens from an external source using an external markup language.
One option to arrive at a token-list is using the XML/SGML parser 
included in SWI-Prolog. It can be used either with a domain-specific 
DTD, in which case you need to define the translations by hand or using 
an HTML DTD, in which case the library library(doc/html) 
defines the required translations.
We will illustrate this in a small example. First the code to show 
HTML inside a window is below. In line 1 we load the always-needed 
document rendering infra-structure and register the doc 
search-path to reflect the \bnfmeta{pcehome}/prolog/lib/doc 
directory. Next we import emit/3 
and load the HTML-rendering extensions to doc:emit/3 and doc:action/3.
:- use_module(library('doc/load')).
:- use_module(doc(emit)).
:- use_module(doc(html)).
:- use_module(library(sgml)).
show_html(File) :-
        send(new(P, picture), open),
        send(P, display, new(PB, pbox), point(10,10)),
        send(P, resize_message, message(PB, width, @arg2?width - 20)),
        
        load_html_file(File, Tokens),
        send(PB, show, Tokens).
Here is the HTML code loaded and the visual result.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>  
  <head>  
    <title>Document rendering</title>
  </head>  
<body>
<h1>SWI-Prolog SGML-DOM</h1>
<p>
SWI-Prolog 4.0 provides a library for loading XML, SGML and
HTML files and convert them to a complex Prolog term.  This
term has the format
<p>
<pre>
element(Name,
        ListOfNameValue
        ListOfContent)
</pre>
<p>
Where <var/ListOfNameValue/ reflects the attribute-list of the
element and <var/ListOfContent/ is mixed list of atoms representing
<em/CDATA/ and <b>element/3</b> terms representing nested elements.
</body>
</html>
 
| Figure 30 : Rendering HTML code | 
In general you do not want to render plain HTML using XPCE/Prolog as it is far less flexible than real browsers dealing with errornous HTML, the implementation of HTML is incomplete and it supports Java nor Javascript.
It has proved to be worthwile using the extensibility of SGML and this layout to render domain-specific documents, often using HTML elements for the basic layout.