summaryrefslogtreecommitdiff
path: root/devdoc
diff options
context:
space:
mode:
authorSebastian Geerken <devnull@localhost>2015-06-03 22:34:03 +0200
committerSebastian Geerken <devnull@localhost>2015-06-03 22:34:03 +0200
commitda88ede8c401449729ae9c4b78f4c9914d81fa09 (patch)
treea66a438f5523269bf470b087d1f38410a688bb1a /devdoc
parentd03e77b0aa3f1f70dcc1d1377b2262ad674ad87e (diff)
parent59b76c75b64578edac35d19c914067a0bd7791e9 (diff)
Merge with main repo.
Diffstat (limited to 'devdoc')
-rw-r--r--devdoc/CCCwork.txt153
-rw-r--r--devdoc/Cache.txt166
-rw-r--r--devdoc/Dillo.txt96
-rw-r--r--devdoc/Dpid.txt331
-rw-r--r--devdoc/HtmlParser.txt124
-rw-r--r--devdoc/IO.txt468
-rw-r--r--devdoc/Images.txt129
-rw-r--r--devdoc/NC_design.txt127
-rw-r--r--devdoc/README51
-rw-r--r--devdoc/dw-changes.doc105
-rw-r--r--devdoc/dw-example-screenshot.pngbin0 -> 2264 bytes
-rw-r--r--devdoc/dw-floats-01.pngbin0 -> 3410 bytes
-rw-r--r--devdoc/dw-grows.doc208
-rw-r--r--devdoc/dw-images-and-backgrounds.doc235
-rw-r--r--devdoc/dw-layout-views.doc256
-rw-r--r--devdoc/dw-layout-widgets.doc267
-rw-r--r--devdoc/dw-line-breaking.doc470
-rw-r--r--devdoc/dw-map.doc59
-rw-r--r--devdoc/dw-out-of-flow-2.doc69
-rw-r--r--devdoc/dw-out-of-flow-floats.doc121
-rw-r--r--devdoc/dw-out-of-flow.doc252
-rw-r--r--devdoc/dw-overview.doc158
-rw-r--r--devdoc/dw-size-of-widget.pngbin0 -> 1749 bytes
-rw-r--r--devdoc/dw-style-box-model.pngbin0 -> 3889 bytes
-rw-r--r--devdoc/dw-style-length-absolute.pngbin0 -> 575 bytes
-rw-r--r--devdoc/dw-style-length-percentage.pngbin0 -> 890 bytes
-rw-r--r--devdoc/dw-style-length-relative.pngbin0 -> 868 bytes
-rw-r--r--devdoc/dw-textblock-collapsing-spaces-1-1.pngbin0 -> 641 bytes
-rw-r--r--devdoc/dw-textblock-collapsing-spaces-1-2.pngbin0 -> 521 bytes
-rw-r--r--devdoc/dw-textblock-collapsing-spaces-2-1.pngbin0 -> 802 bytes
-rw-r--r--devdoc/dw-textblock-collapsing-spaces-2-2.pngbin0 -> 586 bytes
-rw-r--r--devdoc/dw-usage.doc375
-rw-r--r--devdoc/dw-viewport-with-scrollbar.pngbin0 -> 755 bytes
-rw-r--r--devdoc/dw-viewport-without-scrollbar.pngbin0 -> 542 bytes
-rw-r--r--devdoc/dw-widget-sizes.doc277
-rw-r--r--devdoc/fltk-problems.doc180
-rw-r--r--devdoc/index.doc48
-rw-r--r--devdoc/lout.doc95
-rw-r--r--devdoc/not-so-simple-container.pngbin0 -> 19319 bytes
-rw-r--r--devdoc/not-so-simple-container.svg785
-rw-r--r--devdoc/rounding-errors.doc35
-rw-r--r--devdoc/uml-legend.doc195
42 files changed, 5835 insertions, 0 deletions
diff --git a/devdoc/CCCwork.txt b/devdoc/CCCwork.txt
new file mode 100644
index 00000000..1ea5d20e
--- /dev/null
+++ b/devdoc/CCCwork.txt
@@ -0,0 +1,153 @@
+Last review: August 04, 2009 --jcid
+
+
+----------------------------
+Internal working for the CCC
+----------------------------
+
+
+HTTP protocol
+-------------
+
+
+ Query: |
+ .
+ 1B --> 1B 1B --> 1B --> | -------------.
+ .----. .----. .----. . |
+I |Capi| |http| | IO | | |
+ '----' '----' '----' . |
+ 1F <-- 1F 1F <-- 1F | V
+ .
+ | [Server]
+ Answer: .
+
+ 2B --> 2B 2B --> 2B | |
+ .----. .----. .----. . |
+II |Capi| |Dpi | | IO | | |
+ '----' '----' '----' . |
+ 2F <-- 2F 2F <-- 2F <-- | <------------'
+ .
+ |
+
+* a_Capi_open_url() builds both the Answer and Query chains at
+once (Answer first then Query), to ensure a uniform structure
+that avoids complexity (e.g. race conditions).
+
+* Http_get() sets a callback for the DNS hostname resolve.
+Normally it comes later, but may also by issued immediately if
+the hostname is cached.
+
+* The socket FD is passed by means of OpSend by the http module
+once the remote IP is known and the socket is connected.
+
+
+
+Function calls for HTTP CCC
+---------------------------
+
+ a_Capi_open_url
+ if (reload)
+ Capi OpStart 2B (answer) [Capi] --> [dpi] --> [IO]
+ Capi OpStart 1B (query) [Capi] --> [http] --> [IO]
+ Http_get
+ a_Cache_open_url
+ if URL_E2EReload -> prepare reload
+ if cached
+ client enqueue
+ delayed process queue
+ else
+ Cache_entry_add
+ client enqueue
+
+ -//->
+ a_Http_dns_cb
+ Http_connect_socket
+ OpSend FD, BCK
+ OpSend FD, FWD
+ Http_send_query
+ a_Http_make_query_str
+ OpSend, BCK
+ IO_submit
+ a_IOwatch_add_fd (DIO_WRITE, ...)
+
+
+ Note about 'web' structures. They're created using a_Web_new().
+The web.c module keeps a list of valid webs, so anytime you're
+unsure of a weak reference to 'web', it can be checked with
+a_Web_valid(web).
+
+
+
+------------
+Dpi protocol
+------------
+
+
+ Query: |
+ .
+ 1B --> 1B 1B --> 1B --> | -------------.
+ .----. .----. .----. . |
+I |Capi| |Dpi | | IO | | |
+ '----' '----' '----' . |
+ 1F <-- 1F 1F <-- 1F | V
+ .
+ | [Server]
+ .
+ Answer (same as HTTP): | |
+ . |
+ 2B --> 2B 2B --> 2B | |
+ .----. .----. .----. . |
+II |Capi| |Dpi | | IO | | |
+ '----' '----' '----' . |
+ 2F <-- 2F 2F <-- 2F <-- | <------------'
+ .
+ |
+
+
+CCC Construction:
+
+ a_Capi_open_url() calls a_Capi_dpi_send_cmd() when the URL
+belongs to a dpi and it is not cached.
+
+ a_Capi_dpi_send_cmd() builds both the Answer and Query chains
+at once (Answer first then Query), in the same way as HTTP does.
+Note that the answer chain is the same for both, and the query
+chain only differs in the module in the middle ([http] or [dpi]).
+
+
+Function calls for DPI CCC
+--------------------------
+
+ a_Capi_open_url
+ a_Capi_dpi_send_cmd
+ Capi OpStart 2B (answer) [Capi] --> [dpi] --> [IO]
+ Capi OpStart 1B (query) [Capi] --> [http] --> [IO]
+ a_Cache_open_url
+ [...]
+
+
+Normal termination:
+
+ When the dpi server is done, it closes the FD, and OpEnd flows
+from IO to Capi (answer branch). When in Capi, capi propagates
+OpEnd to the query branch.
+
+Abnormal termination:
+
+ The transfer may be aborted by a_Capi_conn_abort_by_url(). The
+OpAbort is not yet standardized and has an ad-hoc implementation.
+One idea is to have OpAbort always propagate BCK and then FWD and
+to jump into the other chain when it gets to [Capi].
+
+
+Debugging CCC
+-------------
+
+ A simple way to "look" inside it, is to "#define VERBOSE 1" in
+chain.c, and then to follow its work with a printed copy of the
+diagrams in this document.
+
+ Each new data request generates a CCC, so if you want to debug,
+it's good to refine the testcase to the minimum possible number
+of connections.
+
diff --git a/devdoc/Cache.txt b/devdoc/Cache.txt
new file mode 100644
index 00000000..4e885df2
--- /dev/null
+++ b/devdoc/Cache.txt
@@ -0,0 +1,166 @@
+ June 2000, --Jcid
+ Last update: Jul 09
+
+ -------
+ CACHE
+ -------
+
+ The cache module is the main abstraction layer between
+rendering and networking.
+
+ The capi module acts as a discriminating wrapper which either
+calls the cache or the dpi routines depending on the type of
+request.
+
+ Every URL must be requested using a_Capi_open_url, which
+sends the request to the cache if the data is cached, to dillo's
+http module for http: URLs, and through dillo's DPI system for
+other URLs.
+
+ Here we'll document non dpi requests.
+
+
+ ----------------
+ CACHE PHILOSOPHY
+ ----------------
+
+ Dillo's cache is very simple; every single resource that's
+retrieved (URL) is kept in memory. NOTHING is saved to disk.
+This is mainly for three reasons:
+
+ - Dillo encourages personal privacy and it assures there'll be
+no recorded tracks of the sites you visited.
+
+ - The Network is full of intermediate transparent proxys that
+serve as caches.
+
+ - If you still want to have cached stuff, you can install an
+external cache server (such as WWWOFFLE), and benefit from it.
+
+
+ ---------------
+ CACHE STRUCTURE
+ ---------------
+
+ Currently, dillo's cache code is spread in different sources:
+mainly in cache.[ch], dicache.[ch] and it uses some other
+functions from mime.c and web.cc.
+
+ Cache.c is the principal source, and it also is the one
+responsible for processing cache-clients (held in a queue).
+Dicache.c is the interface to the decompressed RGB representations
+of currently-displayed images held in DW's imgbuf.
+
+ mime.c and web.cc are used for secondary tasks such as
+assigning the right "viewer" or "decoder" for a given URL.
+
+
+----------------
+A bit of history
+----------------
+
+ Some time ago, the cache functions, URL retrieval and
+external protocols were a whole mess of mixed code, and it was
+getting REALLY hard to fix, improve or extend the functionality.
+The main idea of this "layering" is to make code-portions as
+independent as possible so they can be understood, fixed,
+improved or replaced without affecting the rest of the browser.
+
+ An interesting part of the process is that, as resources are
+retrieved, the client (dillo in this case) doesn't know the
+Content-Type of the resource at request-time. It only becomes known
+when the resource header is retrieved (think of http). This
+happens when the cache has control, so the cache sets the
+proper viewer for it (unless the Callback function was already
+specified with the URL request).
+
+ You'll find a good example in http.c.
+
+ Note: All resources received by the cache have HTTP-style headers.
+ The file/data/ftp DPIs generate these headers when sending their
+ non-HTTP resources. Most importantly, a Content-Type header is
+ generated based on file extension or file contents.
+
+
+-------------
+Cache clients
+-------------
+
+ Cache clients MUST use a_Capi_open_url to request an URL. The
+client structure and the callback-function prototype are defined,
+in cache.h, as follows:
+
+struct _CacheClient {
+ int Key; /* Primary Key for this client */
+ const DilloUrl *Url; /* Pointer to a cache entry Url */
+ int Version; /* Dicache version of this Url (0 if not used) */
+ void *Buf; /* Pointer to cache-data */
+ uint_t BufSize; /* Valid size of cache-data */
+ CA_Callback_t Callback; /* Client function */
+ void *CbData; /* Client function data */
+ void *Web; /* Pointer to the Web structure of our client */
+};
+
+typedef void (*CA_Callback_t)(int Op, CacheClient_t *Client);
+
+
+ Notes:
+
+ * Op is the operation that the callback is asked to perform
+ by the cache. { CA_Send | CA_Close | CA_Abort }.
+
+ * Client: The Client structure that originated the request.
+
+
+
+--------------------------
+Key-functions descriptions
+--------------------------
+
+································································
+int a_Cache_open_url(void *Web, CA_Callback_t Call, void *CbData)
+
+ if Web->url is not cached
+ Create a cache-entry for that URL
+ Send client to cache queue
+ else
+ Feed our client with cached data
+
+································································
+
+----------------------
+Redirections mechanism
+ (HTTP 30x answers)
+----------------------
+
+ This is by no means complete. It's a work in progress.
+
+ Whenever an URL is served under an HTTP 30x header, its cache
+entry is flagged with 'CA_Redirect'. If it's a 301 answer, the
+additional 'CA_ForceRedirect' flag is also set, if it's a 302
+answer, 'CA_TempRedirect' is also set (this happens inside the
+Cache_parse_header() function).
+
+ Later on, in Cache_process_queue(), when the entry is flagged
+with 'CA_Redirect' Cache_redirect() is called.
+
+
+
+
+
+
+
+-----------
+Notes
+-----------
+
+ The whole process is asynchronous and very complex. I'll try
+to document it in more detail later (source is commented).
+ Currently I have a drawing to understand it; hope the ASCII
+translation serves the same as the original.
+ If you're planning to understand the cache process thoroughly,
+write me a note and I will assign higher priority to further
+improvement of this doc.
+ Hope this helps!
+
+
diff --git a/devdoc/Dillo.txt b/devdoc/Dillo.txt
new file mode 100644
index 00000000..a63c9588
--- /dev/null
+++ b/devdoc/Dillo.txt
@@ -0,0 +1,96 @@
+"Eliminate the guesswork and quality goes up."
+
+
+ -------
+ DILLO
+ -------
+
+ These notes are written with a view to make it less hard, not
+easier yet ;), to get into Dillo development.
+ When I first got into it, I was totally unaware of the browser
+internals. Now that I've made my way deep into the core of it,
+(we rewrote it 90% and modified the rest), is time to write some
+documentation, just to make a less steep learning curve for new
+developers.
+
+ --Jcid
+
+
+
+ --------
+ OVERVIEW
+ --------
+
+ Dillo can be viewed as the sum of five main parts:
+
+ 1.- Dillo Widget: A custom widget, FLTK-based, that holds the
+necessary data structures and mechanisms for graphical rendering.
+(Described in Dw*.txt, dw*.c files among the sources.)
+
+ 2.- Dillo Cache: Integrated with a signal driven Input/Output
+engine that handles file descriptor activity, the cache acts as
+the main abstraction layer between rendering and networking.
+ Every URL, whether cached or not, must be retrieved using
+a_Capi_open_url (Described briefly in Cache.txt, source
+contained in capi.c).
+ IO is described in IO.txt (recommended), source in src/IO/.
+
+ 3.- The HTML parser: A streamed parser that joins the Dillo
+Widget and the Cache functionality to make browsing possible
+(Described in HtmlParser.txt, source mainly inside html.cc).
+
+ 4.- Image processing code: The part that handles image
+retrieval, decoding, caching and displaying. (Described in
+Images.txt. Sources: image.c, dw/image.cc, dicache.c, gif.c,
+jpeg.c and png.c)
+
+ 5.- The dpi framework: a gateway to interface the browser with
+external programs (Example: the bookmarks server plugin).
+Dpi spec: http://www.dillo.org/dpi1.html
+
+
+ -------------------------
+ HOW IS THE PAGE RENDERED?
+ -------------------------
+
+(A short description of the internal function calling process)
+
+ When the user requests a new URL, a_UIcmd_open_url
+is queried to do the job; it calls a_Nav_push (The highest level
+URL dispatcher); a_Nav_push updates current browsing history and
+calls Nav_open_url. Nav_open_url closes all open connections by
+calling a_Bw_stop_clients, and then calls
+a_Capi_open_url which calls a_Cache_open_url (or the dpi module if
+this gateway is used).
+
+ If Cache_entry_search hits (due to a cached url :), the client is
+fed with cached data, but if the URL isn't cached yet, a new CCC
+(Concomitant Control Chain) is created and committed to fetch the
+URL.
+
+ The next CCC link is dynamically assigned by examining the
+URL's protocol. It can be a_Http_ccc or a_Dpi_ccc.
+
+ If we have an HTTP URL, a_Http_ccc will succeed, and the http
+module will be linked; it will create the proper HTTP query and
+link the IO module to submit and deliver the answer.
+
+ Note that as the Content-Type of the URL is not always known
+in advance, the answering branch decides where to dispatch it to
+upon HTTP header arrival.
+
+
+ What happens then?
+
+ Well, the html parser gets fed, and proper functions are
+called for each tag (to parse and call the appropriate methods)
+and the whole page is contructed in a streamed way.
+ Somewhere in the middle of it, resize and repaint functions
+are activated and idle functions draw to screen what has been
+processed.
+
+ (The process for images is described in Images.txt)
+
+
+
+
diff --git a/devdoc/Dpid.txt b/devdoc/Dpid.txt
new file mode 100644
index 00000000..6c418f57
--- /dev/null
+++ b/devdoc/Dpid.txt
@@ -0,0 +1,331 @@
+Aug 2003, Jorge Arellano Cid,
+ Ferdi Franceschini --
+Last update: Nov 2009
+
+
+ ------
+ dpid
+ ------
+
+-------------
+Nomenclature:
+-------------
+
+ dpi:
+ generic term referring to dillo's plugin system (version1).
+
+ dpi1:
+ specific term for dillo's plugin spec version 1.
+ at: http://www.dillo.org/dpi1.html
+
+ dpi program:
+ any plugin program itself.
+
+ dpi framework:
+ the code base inside and outside dillo that makes dpi1
+ working possible (it doesn't include dpi programs).
+
+ dpip:
+ dillo plugin protocol. The HTML/XML like set of command tags
+ and information that goes inside the communication sockets.
+ Note: not yet fully defined, but functional.
+ Note2: it was designed to be extensible.
+
+ dpid:
+ dillo plugin daemon.
+
+ server plugin:
+ A plugin that is capable of accepting connections on a socket. Dpid will
+ never run more than one instance of a server plugin at a time.
+
+ filter plugin:
+ A dpi program that reads from stdin and writes to stdout, and that
+ exits after its task is done (they don't remain as server plugins).
+ Warning, dpid will run multiple instances of filter plugins if requested.
+
+-----------
+About dpid:
+-----------
+
+ * dpid is a program which manages dpi connections.
+ * dpid is a daemon that serves dillo using IDS sockets.
+ * dpid launches dpi programs and arranges socket communication
+ between the dpi program and dillo.
+
+ The concept and motivation is similar to that of inetd. The
+plugin manager (dpid) listens for a service request on a socket
+and returns the socket/port pair of a plugin that handles the
+service. It also watches sockets of inactive plugins and starts
+them when a connection is requested.
+
+
+-----------------------------------------------------------
+What's the problem with managing dpi programs inside dillo?
+-----------------------------------------------------------
+
+ That's the other way to handle it, but it started to show some
+problems (briefly outlined here):
+
+ * When having two or more running instances of Dillo, one
+ should prevail, and take control of dpi managing (but all
+ dillos carry the managing code).
+ * If the managing-dillo exits, it must pass control to another
+ instance, or leave it void if there's no other dillo running!
+ * The need to synchronize all the running instances of
+ dillo arises.
+ * If the controlling instance finishes and quits, all the
+ dpi-program PIDs are lost.
+ * Terminating hanged dpis is hard if it's not done with signals
+ (PIDs)
+ * Forks can be expensive (Dillo had to fork its dpis).
+ * When a managing dillo exits, the new one is no longer the
+ parent of the forked dpis.
+ * If Unix domain sockets for the dpis were to be named
+ randomly, it gets very hard to recover their names if the
+ controlling instance of dillo exits and another must "take
+ over" the managing.
+ * It increments dillo's core size.
+ * If dillo hangs/crashes, dpi activity is lost (e.g. downloads)
+ * ...
+
+ That's why the managing daemon scheme was chosen.
+
+
+----------------------
+What does dpid handle?
+----------------------
+
+ It solves all the above mentioned shortcomings and also can do:
+
+ * Multiple dillos:
+ dpid can communicate and serve more than one instance
+ of dillo.
+
+ * Multiple dillo windows:
+ two or more windows of the same dillo instance accessing dpis
+ at the same time.
+
+ * Different implementations of the same service
+ dpi programs ("dpis") are just an implementation of a
+ service. There's no problem in implementing a different one
+ for the same service (e.g. downloads).
+
+ * Upgrading a service:
+ to a new version or implementation without requiring
+ patching dillo's core or even bringing down the dpid.
+
+
+ And finally, being aware that this design can support the
+following functions is very helpful:
+
+ SCHEME Example
+ ------------------------------------------------------------
+ * "one demand/one response" man, preferences, ...
+ * "resident while working" downloads, mp3, ...
+ * "resident until exit request" bookmarks, ...
+
+ * "one client only" cd burner, ...
+ * "one client per instance" man, ...
+ * "multiple clients/one instance" downloads, cookies ...
+
+
+--------
+Features
+--------
+ * Dpi programs go in: "EPREFIX/dillo/dpi" or "~/.dillo/dpi". The binaries
+ are named <name>.dpi as "bookmarks.dpi" and <name>.filter.dpi as in
+ "hello.filter.dpi". The ".filter" plugins simply read from stdin
+ and write to stdout.
+ * Register/update/remove dpis from list of available dpis when a
+ 'register_all' command is received.
+ * dpid terminates when it receives a 'DpiBye' command.
+ * dpis can be terminated with a 'DpiBye' command.
+ * dpidc control program for dpid, currently allows register and stop.
+
+
+-----
+todo:
+-----
+
+ These features are already designed, waiting for implementation:
+
+ * dpidc remove // May be not necessary after all...
+
+
+-----------------
+How does it work?
+-----------------
+
+o on startup dpid reads dpidrc for the path to the dpi directory
+ (usually EPREFIX/lib/dillo/dpi). ~/.dillo/dpi is scanned first.
+
+o both directories are scanned for the list of available plugins.
+ ~/.dillo/dpi overrides system-wide dpis.
+
+o next it creates internet domain sockets for the available plugins and
+ then listens for service requests on its own socket,
+ and for connections to the sockets of inactive plugins.
+
+o dpid returns the port of a plugin's socket when a client (dillo)
+ requests a service.
+
+o if the requested plugin is a 'server' then
+ 1) dpid stops watching the socket for activity
+ 2) forks and starts the plugin
+ 3) resumes watching the socket when the plugin exits
+
+o if the requested plugin is a 'filter' then
+ 1) dpid accepts the connection
+ 2) maps the socket fd to stdin/stdout (with dup2)
+ 3) forks and starts the plugin
+ 4) continues to watch the socket for new connections
+
+
+
+
+---------------------------
+dpi service process diagram
+---------------------------
+
+ These drawings should be worth a thousand words! :)
+
+
+(I)
+ .--- s1 s2 s3 ... sn
+ |
+ [dpid] [dillo]
+ |
+ '--- srs
+
+ The dpid is running listening on several sockets.
+
+
+(II)
+ .--- s1 s2 s3 ... sn
+ |
+ [dpid] [dillo]
+ | |
+ '--- srs ------------------'
+
+ dillo needs a service so it connects to the service request
+ socket of the dpid (srs) and asks for the socket name of the
+ required plugin (using dpip).
+
+
+(III)
+ .--- s1 s2 s3 ... sn
+ | |
+ [dpid] | [dillo]
+ | | |
+ '--- srs '---------------'
+
+ then it connects to that socket (s3, still serviced by dpid!)
+
+
+(IV)
+ .--- s1 s2 s3 ... sn
+ | |
+ .[dpid] | [dillo]
+ . | | |
+ . '--- srs '---------------'
+ .
+ .............[dpi program]
+
+ when s3 has activity (incoming data), dpid forks the dpi
+ program for it...
+
+
+(V)
+ .--- s1 s2 (s3) ... sn
+ |
+ [dpid] [dillo]
+ | |
+ '--- srs .---------------'
+ |
+ [dpi program]
+
+ ... and lets it "to take over" the socket.
+
+ Once there's a socket channel for dpi and dillo, the whole
+communication process takes place until the task is done. When
+the dpi program exits, dpid resumes listening on the socket (s3).
+
+
+--------------------------------
+So, how do I make my own plugin?
+--------------------------------
+
+ Maybe the simplest way to get started is to understand a few
+concepts and then to use the hands-on method by using/modifying
+the hello dpi. It's designed as an example to get developers
+started.
+
+ ---------
+ Concepts:
+ ---------
+
+ * Dillo plugins work by communicating two processes: dillo
+ and the dpi.
+ * The underlying protocol (DPIP) has a uniform API which is
+ powerful enough for both blocking and nonblocking IO, and
+ filter or server dpis.
+ * The simplest example is one-request one-answer (for example
+ dillo asks for a URL and the dpi sends it). You'll find
+ this and more complex examples in hello.c
+
+ First, you should get familiar with the hello dpi as a user:
+
+ $dillo dpi:/hello/
+
+ Once you've played enough with it, start reading the well
+commented code in hello.c and start making changes!
+
+
+ ---------------
+ Debugging a dpi
+ ---------------
+
+ The simplest way is to add printf-like feedback using the MSG*
+macros. You can start the dpid by hand on a terminal to force
+messages to go there. Filter dpis use sdterr and server dpis
+stdout.
+
+ Sometimes more complex dpis need more than MSG*. In this case
+you can use gdb like this.
+
+ 1.- Add an sleep(20) statement just after the dpi starts.
+ 2.- Start dillo and issue a request for your dpi. This will
+ get your dpi started.
+ 3.- Standing in the dpi source directory:
+ ps aux|grep dpi
+ 4.- Take note of the dpi's PID and start gdb, then:
+ (gdb) attach <PID>
+ 5.- Continue from there...
+
+
+ ------------
+ Final Notes:
+ ------------
+
+ 1.- If you already understand the hello dpi and want to try
+something more advanced:
+
+ * bookmarks.c is a good example of a blocking server
+ * file.c is an advanced example of a server handling multiple
+ non-blocking connections with select().
+
+ 2.- Multiple instances of a filter plugin may be run
+concurrently, this could be a problem if your plugin records data
+in a file, however it is safe if you simply write to stdout.
+Alternatively you could write a 'server' plugin instead as they
+are guaranteed not to run concurrently.
+
+ 3.- The hardest part is to try to modify the dpi framework code
+inside dillo; you have been warned! It already supports a lot of
+functionality, but if you need to do some very custom stuff, try
+extending the "chat" command, or asking in dillo-dev.
+
+
+
+ >>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<
+
diff --git a/devdoc/HtmlParser.txt b/devdoc/HtmlParser.txt
new file mode 100644
index 00000000..2eb8be63
--- /dev/null
+++ b/devdoc/HtmlParser.txt
@@ -0,0 +1,124 @@
+ October 2001, --Jcid
+ Last update: Jul 2009
+
+ ---------------
+ THE HTML PARSER
+ ---------------
+
+
+ Dillo's parser is more than just a HTML parser, it does XHTML
+and plain text also. It has parsing 'modes' that define its
+behaviour while working:
+
+ typedef enum {
+ DILLO_HTML_PARSE_MODE_INIT = 0,
+ DILLO_HTML_PARSE_MODE_STASH,
+ DILLO_HTML_PARSE_MODE_STASH_AND_BODY,
+ DILLO_HTML_PARSE_MODE_BODY,
+ DILLO_HTML_PARSE_MODE_VERBATIM,
+ DILLO_HTML_PARSE_MODE_PRE
+ } DilloHtmlParseMode;
+
+
+ The parser works upon a token-grained basis, i.e., the data
+stream is parsed into tokens and the parser is fed with them. The
+process is simple: whenever the cache has new data, it is
+passed to Html_write, which groups data into tokens and calls the
+appropriate functions for the token type (tag, space, or word).
+
+ Note: when in DILLO_HTML_PARSE_MODE_VERBATIM, the parser
+doesn't try to split the data stream into tokens anymore; it
+simply collects until the closing tag.
+
+------
+TOKENS
+------
+
+ * A chunk of WHITE SPACE --> Html_process_space
+
+
+ * TAG --> Html_process_tag
+
+ The tag-start is defined by two adjacent characters:
+
+ first : '<'
+ second: ALPHA | '/' | '!' | '?'
+
+ Note: comments are discarded ( <!-- ... --> )
+
+
+ The tag's end is not as easy to find, nor to deal with!:
+
+ 1) The HTML 4.01 sec. 3.2.2 states that "Attribute/value
+ pairs appear before the final '>' of an element's start tag",
+ but it doesn't define how to discriminate the "final" '>'.
+
+ 2) '<' and '>' should be escaped as '&lt;' and '&gt;' inside
+ attribute values.
+
+ 3) The XML SPEC for XHTML states:
+ AttrValue ::== '"' ([^<&"] | Reference)* '"' |
+ "'" ([^<&'] | Reference)* "'"
+
+ Current parser honors the XML SPEC.
+
+ As it's a common mistake for human authors to mistype or
+ forget one of the quote marks of an attribute value; the
+ parser solves the problem with a look-ahead technique
+ (otherwise the parser could skip significant amounts of
+ properly-written HTML).
+
+
+
+ * WORD --> Html_process_word
+
+ A word is anything that doesn't start with SPACE, that's
+ outside of a tag, up to the first SPACE or tag start.
+
+ SPACE = ' ' | \n | \r | \t | \f | \v
+
+
+-----------------
+THE PARSING STACK
+-----------------
+
+ The parsing state of the document is kept in a stack:
+
+ class DilloHtml {
+ [...]
+ lout::misc::SimpleVector<DilloHtmlState> *stack;
+ [...]
+ };
+
+ struct _DilloHtmlState {
+ CssPropertyList *table_cell_props;
+ DilloHtmlParseMode parse_mode;
+ DilloHtmlTableMode table_mode;
+ bool cell_text_align_set;
+ DilloHtmlListMode list_type;
+ int list_number;
+
+ /* TagInfo index for the tag that's being processed */
+ int tag_idx;
+
+ dw::core::Widget *textblock, *table;
+
+ /* This is used to align list items (especially in enumerated lists) */
+ dw::core::Widget *ref_list_item;
+
+ /* This is used for list items etc; if it is set to TRUE, breaks
+ have to be "handed over" (see Html_add_indented and
+ Html_eventually_pop_dw). */
+ bool hand_over_break;
+ };
+
+ Basically, when a TAG is processed, a new state is pushed into
+the 'stack' and its 'style' is set to reflect the desired
+appearance (details in DwStyle.txt).
+
+ That way, when a word is processed later (added to the Dw), all
+the information is within the top state.
+
+ Closing TAGs just pop the stack.
+
+
diff --git a/devdoc/IO.txt b/devdoc/IO.txt
new file mode 100644
index 00000000..cd62a4f5
--- /dev/null
+++ b/devdoc/IO.txt
@@ -0,0 +1,468 @@
+
+This is the updated base of a paper I wrote with Horst.
+It provides a good introduction to Dillo's internals.
+(Highly recommended if you plan to patch or develop in Dillo)
+
+It may not be exactly accurate (it's quite old), but it explains
+the theory behind in some detail, so it's more than recommended
+reading material.
+--Jcid
+
+
+-----------------------------------------------------
+Parallel network programming of the Dillo web browser
+-----------------------------------------------------
+
+ Jorge Arellano-Cid <jcid@dillo.org>
+ Horst H. von Brand <vonbrand@inf.utfsm.cl>
+
+
+--------
+Abstract
+--------
+
+ Network programs face several delay sources when sending or
+retrieving data. This is particularly problematic in programs
+which interact directly with the user, most notably web browsers.
+We present a hybrid approach using threads communicated through
+pipes and signal driven I/O, which allows a non-blocking main
+thread and overlapping waiting times.
+
+
+------------
+Introduction
+------------
+
+ The Dillo project didn't start from scratch but mainly working
+on the code base of gzilla (a light web browser written by Raph
+Levien). As the project went by, the code of the whole source was
+standardized, and the networking engine was replaced with a new,
+faster design. Later, the parser was changed, the streamed
+handling of data and its error control was put under the control
+of the CCC (Concomitant Control Chain), and the old widget system
+was replaced with a new one (Dw). The source code is currently
+regarded as "very stable beta", and is available at
+<http://www.dillo.org>. Dillo is a project licensed under the GNU
+General Public License.
+
+ This paper covers basic design aspects of the hybrid approach
+that the Dillo web browser uses to solve several latency
+problems. After introducing the main delay-sources, the main
+points of the hybrid design will be addressed.
+
+
+-------------
+Delay sources
+-------------
+
+ Network programs face several delay-sources while sending or
+retrieving data. In the particular case of a web browser, they
+are found in:
+
+ DNS querying:
+ The time required to solve a name.
+
+ Initiating the TCP connection:
+ The three way handshake of the TCP protocol.
+
+ Sending the query:
+ The time spent uploading queries to the remote server.
+
+ Retrieving data:
+ The time spent expecting and receiving the query answer.
+
+ Closing the TCP connection:
+ The four packet-sending closing sequence of the TCP protocol.
+
+ In a WAN context, every single item of this list has an
+associated delay that is non deterministic and often measured in
+seconds. If we add several connections per browsed page (each one
+requiring at least the 4 last steps), the total latency can be
+considerable.
+
+
+-----------------------------------
+The traditional (blocking) approach
+-----------------------------------
+
+ The main problems with the blocking approach are:
+
+ When issuing an operation that can't be completed
+ immediately, the process is put to sleep waiting for
+ completion, and the program doesn't do any other
+ processing in the meantime.
+
+ When waiting for a specific socket operation to complete,
+ packets that belong to other connections may be arriving,
+ and have to wait for service.
+
+ Web browsers handle many small transactions,
+ if waiting times are not overlapped
+ the latency perceived by the user can be very annoying.
+
+ If the user interface is just put to sleep during network
+ operations, the program becomes unresponsive, confusing
+ and perhaps alarming the user.
+
+ Not overlapping waiting times and processing makes
+ graphical rendering (which is arguably the central function
+ of a browser) unnecessarily slow.
+
+
+---------------------
+Dillo's hybrid design
+---------------------
+
+ Dillo uses threads and signal driven I/O extensively to
+overlap waiting times and computation. Handling the user
+interface in a thread that never blocks gives a good interactive
+``feel.'' The use of GTK+, a sophisticated widget framework for
+graphical user interfaces, helped very much to accomplish this
+goal. All the interface, rendering and I/O engine was built upon
+its facilities.
+
+ The design is said to be ``hybrid'' because it uses threads
+for DNS querying and reading local files, and signal driven I/O
+for TCP connections. The threaded DNS scheme is potentially
+concurrent (this depends on underlying hardware), while the I/O
+handling (both local files and remote connections) is
+definitively parallel.
+
+ To simplify the structure of the browser, local files are
+encapsulated into HTTP streams and presented to the rest of the
+browser as such, in exactly the same way a remote connection is
+handled. To create this illusion, a thread is launched. This
+thread opens a pipe to the browser, it then synthesizes an
+appropriate HTTP header, sends it together with the file to the
+browser proper. In this way, all the browser sees is a handle,
+the data on it can come from a remote connection or from a local
+file.
+
+ To handle a remote connection is more complex. In this case,
+the browser asks the cache manager for the URL. The name in the
+URL has to be resolved through the DNS engine, a socket TCP
+connection must be established, the HTTP request has to be sent,
+and finally the result retrieved. Each of the steps mentioned
+could give rise to errors, which have to be handled and somehow
+communicated to the rest of the program. For performance reasons,
+it is critical that responses are cached locally, so the remote
+connection doesn't directly hand over the data to the browser;
+the response is passed to the cache manager which then relays it
+to the rest of the browser. The DNS engine caches DNS responses,
+and either answers them from the cache or by querying the DNS.
+Querying is done in a separate thread, so that the rest of the
+browser isn't blocked by long waits here.
+
+ The activities mentioned do not happen strictly in the order
+stated above. It is even possible that several URLs are being
+handled at the same time, in order to overlap waiting and
+downloading. The functions called directly from the user
+interface have to return quickly to maintain interactive
+response. Sometimes they return connection handlers that haven't
+been completely set up yet. As stated, I/O is signal-driven, when
+one of the descriptors is ready for data transfer (reading or
+writing), it wakes up the I/O engine.
+
+ Data transfer between threads inside the browser is handled by
+pipes, shared memory is little used. This almost obviates the
+need for explicit synchronization, which is one of the main areas
+of complexity and bugs in concurrent programs. Dillo handles its
+threads in a way that its developers can think of it as running
+on a single thread of control. This is accomplished by making the
+DNS engine call-backs happen within the main thread, and by
+isolating file loading with pipes.
+
+ Using threads in this way has three big advantages:
+
+ The browser doesn't block when one of its child threads
+ blocks. In particular, the user interface is responsive
+ even while resolving a name or downloading a file.
+
+ Developers don't need to deal with complex concurrent
+ concerns. Concurrency is hard to handle, and few developers
+ are adept at this. This gives access a much larger pool of
+ potential developers, something which can be critical
+ in an open-source development project.
+
+ By making the code mostly sequential, debugging the code
+ with traditional tools like gdb is possible. Debugging
+ parallel programs is very hard, and appropriate tools are
+ hard to come by.
+
+ Because of simplicity and portability concerns, DNS querying
+is done in a separate thread. The standard C library doesn't
+provide a function for making DNS queries that don't block. The
+alternative is to implement a new, custom DNS querying function
+that doesn't block. This is certainly a complex task, integrating
+this mechanism into the thread structure of the program is much
+simpler.
+
+ Using a thread and a pipe to read a local file adds a
+buffering step to the process (and a certain latency), but it has
+a couple of significative advantages:
+
+ By handling local files in the same way as remote
+ connections, a significant amount of code is reused.
+
+ A preprocessing step of the file data can be added easily,
+ if needed. In fact, the file is encapsulated into an HTTP
+ data stream.
+
+
+-----------
+DNS queries
+-----------
+
+ Dillo handles DNS queries with threads, letting a child thread
+wait until the DNS server answers the request. When the answer
+arrives, a call-back function is called, and the program resumes
+what it was doing at DNS-request time. The interesting thing is
+that the call-back happens in the main thread, while the child
+thread simply exits when done. This is implemented through a
+server-channel design.
+
+
+The server channel
+------------------
+
+ There is one thread for each channel, and each channel can
+have multiple clients. When the program requests an IP address,
+the server first looks for a cached match; if it hits, the client
+call-back is invoked immediately, but if not, the client is put
+into a queue, a thread is spawned to query the DNS, and a GTK+
+idle client is set to poll the channel 5~times per second for
+completion, and when it finally succeeds, every client of that
+channel is serviced.
+
+ This scheme allows all the further processing to continue on
+the same thread it began: the main thread.
+
+
+------------------------
+Handling TCP connections
+------------------------
+
+ Establishing a TCP connection requires the well known
+three-way handshake packet-sending sequence. Depending on network
+traffic and several other issues, significant delay can occur at
+this phase.
+
+ Dillo handles the connection by a non blocking socket scheme.
+Basically, a socket file descriptor of AF_INET type is requested
+and set to non-blocking I/O. When the DNS server has resolved the
+name, the socket connection process begins by calling connect(2);
+ {We use the Unix convention of identifying the manual section
+ where the concept is described, in this case
+ section 2 (system calls).}
+which returns immediately with an EINPROGRESS error.
+
+ After the connection reaches the EINPROGRESS ``state,'' the
+socket waits in background until connection succeeds (or fails),
+when that happens, a callback function is awaked to perform the
+following steps: set the I/O engine to send the query and expect
+its answer (both in background).
+
+ The advantage of this scheme is that every required step is
+quickly done without blocking the browser. Finally, the socket
+will generate a signal whenever I/O is possible.
+
+
+----------------
+Handling queries
+----------------
+
+ In the case of a HTTP URL, queries typically translate into a
+short transmission (the HTTP query) and a lengthy retrieval
+process. Queries are not always short though, specially when
+requesting forms (all the form data is attached within the
+query), and also when requesting CGI programs.
+
+ Regardless of query length, query sending is handled in
+background. The thread that was initiated at TCP connecting time
+has all the transmission framework already set up; at this point,
+packet sending is just a matter of waiting for the
+write signal (G_IO_OUT) to come and then sending the data. When
+the socket gets ready for transmission, the data is sent using
+IO_write.
+
+
+--------------
+Receiving data
+--------------
+
+ Although conceptually similar to sending queries, retrieving
+data is very different as the data received can easily exceed the
+size of the query by many orders of magnitude (for example when
+downloading images or files). This is one of the main sources of
+latency, the retrieval can take several seconds or even minutes
+when downloading large files.
+
+ The data retrieving process for a single file, that began by
+setting up the expecting framework at TCP connecting time, simply
+waits for the read signal (G_IO_IN). When it happens, the
+low-level I/O engine gets called, the data is read into
+pre-allocated buffers and the appropriate call-backs are
+performed. Technically, whenever a G_IO_IN event is generated,
+data is received from the socket file descriptor, by using the
+IO_read function. This iterative process finishes upon EOF (or on
+an error condition).
+
+
+----------------------
+Closing the connection
+----------------------
+
+ Closing a TCP connection requires four data segments, not an
+impressive amount but twice the round trip time, which can be
+substantial. When data retrieval finishes, socket closing is
+triggered. There's nothing but a IO_close_fd call on the socket's
+file descriptor. This process was originally designed to split
+the four segment close into two partial closes, one when query
+sending is done and the other when all data is in. This scheme is
+not currently used because the write close also stops the reading
+part.
+
+
+The low-level I/O engine
+------------------------
+
+ Dillo I/O is carried out in the background. This is achieved
+by using low level file descriptors and signals. Anytime a file
+descriptor shows activity, a signal is raised and the signal
+handler takes care of the I/O.
+
+ The low-level I/O engine ("I/O engine" from here on) was
+designed as an internal abstraction layer for background file
+descriptor activity. It is intended to be used by the cache
+module only; higher level routines should ask the cache for its
+URLs. Every operation that is meant to be carried out in
+background should be handled by the I/O engine. In the case of
+TCP sockets, they are created and submitted to the I/O engine for
+any further processing.
+
+ The submitting process (client) must fill a request structure
+and let the I/O engine handle the file descriptor activity, until
+it receives a call-back for finally processing the data. This is
+better understood by examining the request structure:
+
+ typedef struct {
+ gint Key; /* Primary Key (for klist) */
+ gint Op; /* IORead | IOWrite | IOWrites */
+ gint FD; /* Current File Descriptor */
+ gint Flags; /* Flag array */
+ glong Status; /* Number of bytes read, or -errno code */
+
+ void *Buf; /* Buffer place */
+ size_t BufSize; /* Buffer length */
+ void *BufStart; /* PRIVATE: only used inside IO.c! */
+
+ void *ExtData; /* External data reference (not used by IO.c) */
+ void *Info; /* CCC Info structure for this IO */
+ GIOChannel *GioCh; /* IO channel */
+ guint watch_id; /* glib's event source id */
+ } IOData_t;
+
+ To request an I/O operation, this structure must be filled and
+passed to the I/O engine.
+
+ 'Op' and 'Buf' and 'BufSize' MUST be provided.
+
+ 'ExtData' MAY be provided.
+
+ 'Status', 'FD' and 'GioCh' are set by I/O engine internal
+routines.
+
+ When there is new data in the file descriptor, 'IO_callback'
+gets called (by glib). Only after the I/O engine finishes
+processing the data are the upper layers notified.
+
+
+The I/O engine transfer buffer
+------------------------------
+
+ The 'Buf' and 'BufSize' fields of the request structure
+provide the transfer buffer for each operation. This buffer must
+be set by the client (to increase performance by avoiding copying
+data).
+
+ On reads, the client specifies the amount and where to place
+the retrieved data; on writes, it specifies the amount and source
+of the data segment that is to be sent. Although this scheme
+increases complexity, it has proven very fast and powerful. For
+instance, when the size of a document is known in advance, a
+buffer for all the data can be allocated at once, eliminating the
+need for multiple memory reallocations. Even more, if the size is
+known and the data transfer is taking the form of multiple small
+chunks of data, the client only needs to update 'Buf' and
+BufSize' to point to the next byte in its large preallocated
+reception buffer (by adding the chunk size to 'Buf'). On the
+other hand, if the size of the transfer isn't known in advance,
+the reception buffer can remain untouched until the connection
+closes, but the client must then accomplish the usual buffer
+copying and reallocation.
+
+ The I/O engine also lets the client specify a full length
+transfer buffer when sending data. It doesn't matter (from the
+client's point of view) if the data fits in a single packet or
+not, it's the I/O engine's job to divide it into smaller chunks
+if needed and to perform the operation accordingly.
+
+
+------------------------------------------
+Handling multiple simultaneous connections
+------------------------------------------
+
+ The previous sections describe the internal work for a single
+connection, the I/O engine handles several of them in parallel.
+This is the normal downloading behavior of a web page. Normally,
+after retrieving the main document (HTML code), several
+references to other files (typically images) and sometimes even
+to other sites (mostly advertising today) are found inside the
+page. In order to parse and complete the page rendering, those
+other documents must be fetched and displayed, so it is not
+uncommon to have multiple downloading connections (every one
+requiring the whole fetching process) happening at the same time.
+
+ Even though socket activity can reach a hectic pace, the
+browser never blocks. Note also that the I/O engine is the one
+that directs the execution flow of the program by triggering a
+call-back chain whenever a file descriptor operation succeeds or
+fails.
+
+ A key point for this multiple call-back chained I/O engine is
+that every single function in the chain must be guaranteed to
+return quickly. Otherwise, the whole system blocks until it
+returns.
+
+
+-----------
+Conclusions
+-----------
+
+ Dillo is currently in very stable beta state. It already shows
+impressive performance, and its interactive ``feel'' is much
+better than that of other web browsers.
+
+ The modular structure of Dillo, and its reliance on GTK1 allow
+it to be very small. Not every feature of HTML-4.01 has been
+implemented yet, but no significant problems are foreseen in
+doing this.
+
+ The fact that Dillo's central I/O engine is written using
+advanced features of POSIX and TCP/IP networking makes its
+performance possible, but on the other hand this also means that
+only a fraction of the interested hackers are able to work on it.
+
+ A simple code base is critical when trying to attract hackers
+to work on a project like this one. Using the GTK+ framework
+helped both in creating the graphical user interface and in
+handling the concurrency inside the browser. By having threads
+communicate through pipes the need for explicit synchronization
+is almost completely eliminated, and with it most of the
+complexity of concurrent programming disappears.
+
+ A clean, strictly applied layering approach based on clear
+abstractions is vital in each programming project. A good,
+supportive framework is of much help here.
+
+
diff --git a/devdoc/Images.txt b/devdoc/Images.txt
new file mode 100644
index 00000000..62082e48
--- /dev/null
+++ b/devdoc/Images.txt
@@ -0,0 +1,129 @@
+ January 2009, --Jcid
+
+Update June 2015: See also doc/dw-images-and-backgrounds.doc, or
+../html/dw-images-and-backgrounds.html (generated by doxygen).
+
+ ------
+ IMAGES
+ ------
+
+* When a image tag is found within a HTML page, Html_tag_open_img
+handles it by:
+
+ - Parsing & getting attribute values.
+ - Creating a new image structure (DilloImage) and its
+ associated widget (DwImage).
+ i.e. If 'Image' is the var for the structure, then
+ 'Image->dw' is the widget.
+ - Requesting the image to be feeded by the cache.
+ - Sending some info to the browser interface.
+
+* The cache can either request the image data from the net, or
+feed it directly from the dicache (decompressed image cache).
+
+* Both processes are somewhat different because the first one
+requires to decode the image data into RGB format, and the second
+one has the whole data already decoded.
+
+* Regardless of the RGB-data feeding method, the decoded data is
+passed to the widget (DwImage) and drawn in a streamed way.
+ Note that INDEXED images are also decoded into RGB format.
+
+ Html_tag_open_img // IMG element processing
+ Html_add_new_image // Read attributes, create image, add to HTML page
+ a_Image_new // Create a 'DilloImage' data structure, to coordinate
+ // decoded image-data transfer to an 'Imgbuf'.
+ Html_add_widget // Adds the dw::Image to the page
+ Html_load_image // Tells cache to retrieve image
+
+
+---------------------
+Fetching from the net
+---------------------
+
+* a_Capi_open_url initiates the resource request, and when
+finally the answer arrives, the HTTP header is examined for MIME
+type and either the GIF or PNG or JPEG decoder is set to handle
+the incoming data stream.
+
+ Decoding functions:
+ a_Gif_callback, a_Jpeg_callback and a_Png_callback.
+
+* The decoding function calls the following dicache methods as
+the data is processed (listed in order):
+
+ a_Dicache_set_parms
+ a_Dicache_set_cmap (only for indexed-GIF images)
+ a_Dicache_write
+ a_Dicache_new_scan (MAY be called here or after set_cmap)
+ a_Dicache_close
+
+
+* The dicache methods call the necessary functions to connect
+with the widget code. This is done by calling image.c functions:
+
+ a_Image_set_parms
+ a_Image_set_cmap
+ a_Image_write
+ a_Image_new_scan
+ a_Image_close
+
+* The functions in image.c make the required Dw calls.
+
+
+-------------------------
+Fetching from the dicache
+-------------------------
+
+* a_Capi_open_url() tests the cache for the image, and the cache,
+via a_Cache_open_url(), enqueues a client for it, without asking
+the network for the data. When the client queue is processed (a
+bit later), Dicache_image() is set as the callback.
+
+* When Dicache_image() is called, it sets the proper image data
+decoder (RGB) and its data structure based on the entry's Type.
+Then it substitutes itself with a_Dicache_callback() as the
+handling function, and gets out of the way.
+
+* Thenceforth the rest of the functions calls is driven by
+a_Dicache_callback().
+
+
+-----------
+Misc. notes
+-----------
+
+* Repeated images generate new cache clients, but they may share
+the imgbuf.
+ Note: Currently there's no proper support for transparent
+images (i.e. decode to RGBA), but most of the time they render
+the background color OK. This is: when first loaded, repeated
+images share a background color, but when cached they render
+correctly ;-). There's no point in trying to fix this because the
+correct solution is to decode to RGBA and let the toolkit (FLTK)
+handle the transparency.
+
+* The first cache-client callback (Dicache_image()) is set when
+the Content-type of the image is got.
+
+* Later on, when there's a shared imgbuf, the dicache's logic
+avoids decoding it multiple times and reuses what's already done.
+
+* The dicache-entry and the Image structure hold bit arrays that
+represent which rows have been decoded.
+
+* The image processing can be found in the following sources:
+
+ - image.{cc,hh}
+ - dicache.[ch]
+ - gif.[ch], png.[ch], jpeg.[ch]
+ - dw/image.{cc,hh}
+
+* Bear in mind that there are four data structures for image
+code:
+
+ - DilloImage (image.hh)
+ - DICacheEntry (dicache.h)
+ - dw::Image (class Image in dw/image.hh)
+ - core::Imgbuf (imgbuf.hh)
+
diff --git a/devdoc/NC_design.txt b/devdoc/NC_design.txt
new file mode 100644
index 00000000..380787f6
--- /dev/null
+++ b/devdoc/NC_design.txt
@@ -0,0 +1,127 @@
+
+ _________________________________________________________________
+
+ Naming&Coding design
+ _________________________________________________________________
+
+ Dillo's code is divided into modules. For instance: bookmark, cache,
+ dicache, gif.
+
+ Let's think of a module named "menu", then:
+ * Every internal routine of the module, should start with "Menu_"
+ prefix.
+ * "Menu_" prefixed functions are not meant to be called from outside
+ the module.
+ * If the function is to be exported to other modules (i.e. it will
+ be called from the outside), it should be wrapped with an "a_"
+ prefix.
+
+ For instance: if the function name is "Menu_create", then it's an
+ internal function, but if we need to call it from the outside, then it
+ should be renamed to "a_Menu_create".
+
+ Why the "a_" prefix?
+ Because of historical reasons.
+ And "a_Menu_create" reads better than "d_Menu_create" because the
+ first one suggests "a Menu create" function!
+
+ Another way of understanding this is thinking of "a_" prefixed
+ functions as Dillo's internal library, and the rest ("Menu_" prefixed
+ in our example) as a private module-library.
+
+ Indentation:
+
+ Source code must be indented with 3 blank spaces, no Tabs.
+ Why?
+ Because different editors expand or treat tabs in several ways; 8
+ spaces being the most common, but that makes code really wide and
+ we'll try to keep it within the 80 columns bounds (printer friendly).
+
+ You can use: indent -kr -sc -i3 -bad -nbbo -nut -l79 myfile.c
+
+ Function commenting:
+
+ Every single function of the module should start with a short comment
+ that explains its purpose; three lines must be enough, but if you
+ think it requires more, enlarge it.
+
+ /*
+ * Try finding the url in the cache. If it hits, send the contents
+ * to the caller. If it misses, set up a new connection.
+ */
+ int a_Cache_open_url(const char *url, void *Data)
+ {
+ ...
+ ...
+ ...
+ }
+
+ We also have the BUG:, TODO:, and WORKAROUND: tags.
+ Use them within source code comments to spot hidden issues. For
+ instance:
+
+ /* BUG: this counter is not accurate */
+ ++i;
+
+ /* TODO: get color from the right place */
+ a = color;
+
+ /* WORKAROUND: the canonical way of doing it doesn't work yet. */
+ ++a; ++a; ++a;
+
+ Function length:
+
+ Let's try to keep functions within the 45 lines boundary. This eases
+ code reading, following, understanding and maintenance.
+
+ Functions with a single exit:
+
+ It's much easier to follow and maintain functions with a single exit
+ point at the bottom (instead of multiple returns). The exception to
+ the rule are calls like dReturn_if_fail() at its head.
+
+ dlib functions:
+
+ * Dillo uses dlib extensively in its C sources. Before starting
+ to code something new, a good starting point is to check what
+ this library has to offer (check dlib/dlib.h).
+ * Memory management must be done using dNew, dNew0, dMalloc, dFree
+ and their relatives.
+ * For debugging purposes and error catching (not for normal flow):
+ dReturn_if_fail, dReturn_val_if_fail etc. are encouraged.
+ * The MSG macro is extensively used to output additional information
+ to the calling terminal.
+
+ _________________________________________________________________
+
+ C++
+
+ Source code in C++ should follow the same rules with these exceptions:
+
+ * Class method names are camel-cased and start with lowercase
+ e.g. appendInputMultipart
+ * Classes and types start uppercased
+ e.g. class DilloHtmlReceiver
+ * Class methods don't need to prefix its module name
+ e.g. links->get()
+
+ We also try to keep the C++ relatively simple. Dillo does use
+ inheritance and templates, but that's about all.
+
+ _________________________________________________________________
+
+ What do we get with this?
+
+ * A clear module API for Dillo; every function prefixed "a_" is to
+ be used outside the module.
+ * A way to identify where the function came from (the
+ capitalized word is the module name).
+ * An inner ADT (Abstract data type) for the module that can be
+ isolated, tested and replaced independently.
+ * A two stage instance for bug-fixing. You can change the exported
+ function algorithms while someone else fixes the internal
+ module-ADT!
+ * A coding standard ;)
+ _________________________________________________________________
+
+ Naming&Coding design by Jorge Arellano Cid
diff --git a/devdoc/README b/devdoc/README
new file mode 100644
index 00000000..9736a32b
--- /dev/null
+++ b/devdoc/README
@@ -0,0 +1,51 @@
+README: Last update Jul 2009
+
+These documents cover dillo's internals.
+For user help, see http://www.dillo.org/dillo3-help.html
+
+--------------------------------------------------------------------------
+
+These documents need a review.
+*.txt were current with Dillo1, but many have since become more or
+ less out-of-date.
+*.doc are doxygen source for the Dillo Widget (dw) component, and
+ were written for Dillo2.
+
+They will give you an overview of what's going on, but take them
+with a pinch of salt.
+
+ Of course I'd like to have *.txt as doxygen files too!
+If somebody wants to make this conversion, please let me know
+to assign higher priority to updating these docs.
+
+--
+Jorge.-
+
+ --------------------------------------------------------------------------
+ FILE DESCRIPTION STATE
+ --------------------------------------------------------------------------
+ NC_design.txt Naming&Coding design (Be sure to Current
+ read it before any other doc)
+ Dillo.txt General overview of the program Current
+ IO.txt Extensive introduction Current
+ Cache.txt Informative description Current
+ Images.txt Image handling and processing Current
+ HtmlParser.txt A versatile parser Current
+ Dw.txt The New Dillo Widget (Overview) Current
+ Imgbuf.txt Image buffers Pending
+ Selection.txt Selections, and link activation Current (?)
+ Cookies.txt Explains how to enable cookies Current
+ Dpid.txt Dillo plugin daemon Current
+ --------------------------------------------------------------------------
+
+
+ * BTW, there's a small program (srch) within the src/ dir. It searches
+ tokens within the whole code (*.[ch]). It has proven very useful.
+ Ex: ./srch a_Image_write
+ ./srch todo:
+
+ * Please submit your patches with 'hg diff'.
+
+
+ Happy coding!
+ --Jcid
diff --git a/devdoc/dw-changes.doc b/devdoc/dw-changes.doc
new file mode 100644
index 00000000..7050df9a
--- /dev/null
+++ b/devdoc/dw-changes.doc
@@ -0,0 +1,105 @@
+/** \page dw-changes Changes to the GTK+-based Release Version
+
+<h2>Changes in Dw</h2>
+
+Related to the FLTK port, there have been many changes, this is a
+(hopefully complete) list:
+
+<ul>
+<li> Rendering abstraction, read \ref dw-overview and \ref dw-layout-views
+ for details. Some important changes:
+
+ <ul>
+ <li> The underlying platform (e.g. the UI toolkit) is fully abstract,
+ there are several platform independent structures replacing
+ GTK+ structures, e.g. dw::core::Event.
+
+ <li> The central class managing the widget tree is not anymore
+ GtkDwViewport, but dw::core::Layout.
+
+ <li> Drawing is done via dw::core::View, a pointer is passed to
+ dw::core::Widget::draw.
+
+ <li> The distinction between viewport coordinates and canvas
+ coordinates (formerly world coordinates) has been mostly
+ removed. (Only for views, it sometimes plays a role, see
+ \ref dw-layout-views).
+</ul>
+
+<li> Cursors have been moved to dw::core::style, see
+ dw::core::style::Style::cursor. dw::core::Widget::setCursor is now
+ protected (and so only called by widget implementations).
+
+<li> World coordinates are now called canvas coordinates.
+
+<li> There is now a distinction between dw::core::style::StyleAttrs and
+ dw::core::style::Style.
+
+<li> There is no base class for container widgets anymore. The former
+ DwContainer::for_all has been removed, instead this functionality
+ is now done via iterators (dw::core::Widget::iterator,
+ dw::core::Iterator).
+
+<li> DwPage is now called dw::Textblock, and DwAlignedPage
+ dw::AlignedTextblock.
+
+<li> dw::Textblock, all sub classes of it, and dw::Table do not read
+ "limit_text_width" from the preferences, but get it as an argument.
+ (May change again.)
+
+<li> dw::Table has been rewritten.
+
+<li> Instead of border_spacing in the old DwStyle, there are two attributes,
+ dw::core::style::Style::hBorderSpacing and
+ dw::core::style::Style::vBorderSpacing, since CSS allowes to specify
+ two values. Without CSS, both attributes should have the same value.
+
+<li> Images are handled differently, see \ref dw-images-and-backgrounds.
+
+<li> Embedded UI widgets (formerly GtkWidget's) are handled differently,
+ see dw::core::ui.
+
+<li> DwButton has been removed, instead, embedded UI widgets are used. See
+ dw::core::ui and dw::core::ui::ComplexButtonResource.
+</ul>
+
+Dw is now written C++, the transition should be obvious. All "Dw"
+prefixes have been removed, instead, namespaces are used now:
+
+<ul>
+<li>dw::core contains the core,
+<li>dw::core::style styles,
+<li>dw::core::ui embedded UI resources,
+<li>dw::fltk classes related to FLTK, and
+<li>::dw the widgets.
+</ul>
+
+<h2>Documentation</h2>
+
+The old documentation has been moved to:
+
+<table>
+<tr><th colspan="2">Old <th>New
+<tr><td rowspan="2">Dw.txt
+ <td>general part <td>\ref dw-overview, \ref dw-usage,
+ \ref dw-layout-widgets,
+ \ref dw-widget-sizes
+<tr><td>remarks on specific widgets <td>respective source files: dw::Bullet,
+ dw::core::ui::Embed
+<tr><td rowspan="2">DwImage.txt
+ <td>signals <td>dw::core::Layout::LinkReceiver
+<tr><td>rest <td>dw::Image,
+ \ref dw-images-and-backgrounds
+<tr><td colspan="2">Imgbuf.txt <td>dw::core::Imgbuf,
+ \ref dw-images-and-backgrounds
+<tr><td colspan="2">DwPage.txt <td>dw::Textblock
+<tr><td colspan="2">DwRender.txt <td>\ref dw-overview, \ref dw-layout-views,
+ dw::core::ui
+<tr><td colspan="2">DwStyle.txt <td>dw::core::style
+<tr><td colspan="2">DwTable.txt <td>dw::Table
+<tr><td colspan="2">DwWidget.txt <td>dw::core::Widget, \ref dw-layout-widgets,
+ \ref dw-widget-sizes
+<tr><td colspan="2">Selection.txt <td>dw::core::SelectionState
+</table>
+
+*/
diff --git a/devdoc/dw-example-screenshot.png b/devdoc/dw-example-screenshot.png
new file mode 100644
index 00000000..94f272ab
--- /dev/null
+++ b/devdoc/dw-example-screenshot.png
Binary files differ
diff --git a/devdoc/dw-floats-01.png b/devdoc/dw-floats-01.png
new file mode 100644
index 00000000..116d36b3
--- /dev/null
+++ b/devdoc/dw-floats-01.png
Binary files differ
diff --git a/devdoc/dw-grows.doc b/devdoc/dw-grows.doc
new file mode 100644
index 00000000..c255419f
--- /dev/null
+++ b/devdoc/dw-grows.doc
@@ -0,0 +1,208 @@
+/** \page dw-grows GROWS - Grand Redesign Of Widget Sizes
+
+<div style="border: 2px solid #ffff00; margin: 1em 0;
+ padding: 0.5em 1em; background-color: #ffffe0">The complex "widget
+ sizes" is currently divided into three documents: \ref
+ dw-widget-sizes, **Grand Redesign Of Widget Sizes** (this document),
+ and \ref dw-size-request-pos. </div>
+
+This paper describes (will describe) some design changes to
+calculating widget sizes. Goals are:
+
+- Simplification of widget size calculation by the parent widget;
+ dw::Textblock::calcWidgetSize, dw::OutOfFlowMgr::ensureFloatSize
+ etc. should become simpler or perhaps even obsolete.
+
+- Making the implementation of some features possible:
+
+ - *max-width*, *max-height*, *min-width*, *min-height*;
+ - correct aspect ratio for images with only one percentage size defined;
+ - *display: inline-block*;
+ - &lt;button&gt;.
+
+
+A short sketch
+==============
+
+**dw::core::Widget::sizeRequest and dw::core::Widget::getExtremes will
+return final results.** The caller does not have to correct the size,
+e.&nbsp;g. when percentages are defined. As an example,
+dw::Textblock::calcWidgetSize has already become much simpler.
+
+**A new hierarchy, *container*:** Aside from dw::core::Widget::parent
+and dw::core::Widget::generator, there is a third hierarchy
+dw::core::Widget::container, which is (unlike *generator*) always a
+direct ancestor, and represents what in CSS is called *containing
+block*. Containers are important to define the "context size", which
+is (not solely) used for percentage sizes.
+
+(There is another "containing block", dw::Textblock::containingBlock;
+these may be consolidated some day.)
+
+**The process of size calculation is split between the widget itself
+and its container:**
+
+- The container provides some abstract methods:
+ dw::core::Widget::getAvailWidthOfChild,
+ dw::core::Widget::getAvailHeightOfChild,
+ dw::core::Widget::correctRequisitionOfChild, and
+ dw::core::Widget::correctExtremesOfChild, which can be used in the
+ actual implementation of dw::core::Widget::sizeRequestImpl;
+ different containers with different ways how to arrange their
+ children will implement these methods in a different way. (Simple
+ example: the *available width* for children within a textblock is
+ the *available width* for the textblock itself, minus
+ margin/border/padding; on the other hand, it is completely different
+ for children of tables, for which a complex column width calculation
+ is used.)
+
+- The actual size calculation is, however, controlled by the widget
+ itself, which only *uses* these methods above.
+
+<div style="border: 2px solid #ffff00; margin-top: 0.5em;
+ margin-bottom: 0.5em; padding: 0.5em 1em; background-color: #ffffe0">
+ <b>Update:</b> This is not fully correct; the parents are also involved
+ for calculating available widths and heights, at least when CSS 'width'
+ and 'height' are not set.</div>
+
+**Size hints are removed.** Instead, the container methods in the
+previous paragraph are used. Changes of container sizes (especially
+viewport the size) are handled in a different way.
+
+**Extremes are extended by intrinsic values.** In some cases (see
+dw::Table::forceCalcCellSizes, case *minWidth* > *totalWidth*, for an
+example) it is useful to know about minimal and maximal width of a
+widget independent of CSS attributes. For this, dw::core::Extremes is
+extended by:
+
+- dw::core::Extremes::minWidthIntrinsic and
+- dw::core::Extremes::maxWidthIntrinsic.
+
+The rules for the calculation:
+
+1. If a widget has no children, it calculates *minWidthIntrinsic* and
+ *maxWidthIntrinsic* as those values not affected by CSS hints.
+ (dw::core::Widget::correctExtremes will not change these values.)
+2. A widget must calculate *minWidthIntrinsic* and *maxWidthIntrinsic*
+ from *minWidthIntrinsic* and *maxWidthIntrinsic* of its children,
+ and *minWidth* and *maxWidth* from *minWidth* and *maxWidth* of its
+ children.
+3. At the end, *minWidth* and *maxWidth* of a widget are corrected by
+ CSS attributes. (dw::core::Widget::correctExtremes will do this.)
+
+<div style="border: 2px solid #ffff00; margin-top: 0.5em;
+ margin-bottom: 0.5em; padding: 0.5em 1em; background-color: #ffffe0">
+ <b>Notice:</b> Currently, dw::core::Widget::getExtremesImpl must
+ set all four members in dw::core::Extremes; this may change.</div>
+
+Another **extension of extremes: *adjustmentWidth*.** This is used as
+minimum for the width, when "adjust_min_width" (or,
+"adjust_table_min_width", respectively) is set.
+
+The rules for the calculation:
+
+1. If a widget has no children, it can choose a suitable value,
+ typically based on dw::core::Extremes::minWidth and
+ dw::core::Extremes::minWidthIntrinsic.
+2. A widget must calculate *adjustmentWidth* from *adjustmentWidth* of
+ its children.
+
+*Note:* An implementation of dw::core::Widget::getExtremesImpl may set
+this value *after* calling dw::core::Widget::correctExtremesOfChild,
+so that it cannot be used for the correction of extremes. In this case
+*useAdjustmentWidth = false* should be passed to
+dw::core::Widget::correctExtremesOfChild. On the other hand, if known
+before, *useAdjustmentWidth* should be set to *true*.
+
+Rules for *new* methods related to resizing
+===========================================
+
+- Of course, *sizeRequestImpl* may (should) call *correctRequisition*,
+ and *getExtremesImpl* may (should) call *correctExtremes*.
+
+- *sizeRequestImpl* (and *correctRequisition*) is allowed to call
+ *getAvailWidth* and *getAvailHeight* with *forceValue* set, but
+ *getExtremesImpl* (and *correctExtremes*) is allowed to call these
+ only with *forceValue* unset.
+
+- For this reason, *sizeRequestImpl* is indeed allowed to call
+ *getExtremes* (dw::Table does so), but the opposite
+ (*getExtremesImpl* calling *sizeRequest*) is not allowed
+ anymore. (Before GROWS, the standard implementation
+ dw::core::Widget::getExtremesImpl did so.)
+
+- Finally, *getAvailWidth* and *getAvailHeight* may call
+ *getExtremes*, if and only if *forceValue* is set.
+
+Here is a diagram showing all permitted dependencies:
+
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10, color="#c0c0c0"];
+ edge [arrowhead="open", arrowtail="none", color="#404040"];
+
+ "sizeRequest[Impl]" -> "getExtremes[Impl]";
+ "sizeRequest[Impl]" -> correctRequisition;
+ "getExtremes[Impl]" -> correctExtremes;
+ "sizeRequest[Impl]" -> "getAvail[Width|Height] (true)";
+ "getExtremes[Impl]" -> "getAvail[Width|Height] (false)";
+ correctRequisition -> "getAvail[Width|Height] (true)";
+ correctExtremes -> "getAvail[Width|Height] (false)";
+ "getAvail[Width|Height] (true)" -> "getExtremes[Impl]";
+}
+\enddot
+
+Open issues
+===========
+
+**Do CSS size dimensions override intrinsic sizes in all cases?** If a
+textblock needs at least, say, 100 pixels width so that the text can
+be read, but has a specification "width: 50px", should half of the
+text be invisible? Or should the width be corrected again to 100
+pixels?
+
+Currently, in the CSS size specification is honoured in all cases,
+with one exception: see dw::Textblock::sizeRequestImpl and see
+dw::Textblock::getExtremesImpl (the time when
+dw::core::Widget::correctRequisition and
+dw::core::Widget::correctExtremes, respectively, is called).
+
+*Not* honouring the CSS size specification in all cases could improve
+readability in some cases, so this could depend on a user preference.
+
+**Update:** There is now a dillorc option <tt>adjust_min_width</tt>,
+which is implemented for widths, but not heights (since it is based on
+width extremes, but there are currently no height extremes).
+
+Another problem is that in most cases, there is no clippping, so that
+contents may exceed the allocation of the widget, but redrawing is not
+necessarily triggered.
+
+**Percentage values for margins and paddings, as well as negative
+margins** are interesting applications, but have not been considered
+yet. For negative margins, a new attribute
+dw::core::Widget::extraSpace could solve the problem of widgets
+sticking out of the allocation of parent.
+
+**Clarify percentage heights.** Search in widget.cc, and compare
+section 10.5 ('height') of the CSS 2.1 specification to section 10.2
+('width').
+
+**Fast queue resize does not work fully.** Example: run
+*test/dw-simple-container-test* (dw_simple_container_test.cc), resize
+(best maximize) the window and follow (e.&nbsp;g. by using RTFL) what
+happens in consequence of dw::core::Layout::viewportSizeChanged. The
+dw::SimpleContainer in the middle is not affected, so only the two
+dw::Textblock's (at the top and at the bottom) call queueResize with
+*fast = true*, and so get *NEEDS_RESIZE* set; but since it is not set
+for the dw::SimpleContainer, *sizeRequest* is never called for the
+bottom dw::Textblock.
+
+There does not seem to be a real case for this problem in dillo, since
+all widgets which may contain other widgets (except
+dw::SimpleContainer, which is not used outside tests) use the
+available width and height (dw::core::Widget::usesAvailWidth and
+dw::core::Widget::usesAvailHeight), and so are always affected by
+viewport size changes.
+
+*/
diff --git a/devdoc/dw-images-and-backgrounds.doc b/devdoc/dw-images-and-backgrounds.doc
new file mode 100644
index 00000000..8f07766a
--- /dev/null
+++ b/devdoc/dw-images-and-backgrounds.doc
@@ -0,0 +1,235 @@
+/** \page dw-images-and-backgrounds Images and Backgrounds in Dw
+
+Image Buffers
+=============
+
+Representation of the image data is done by dw::core::Imgbuf, see
+there for details. Drawing is done by dw::core::View
+(dw::core::View::drawImage).
+
+Since dw::core::Imgbuf provides memory management based on reference
+counting, there may be an 1-to-n relation from image renderers (image
+widgets or backgrounds, see below) and dw::core::Imgbuf. Since
+dw::core::Imgbuf does not know about renderers, but just provides
+rendering functionality, the caller must (typically after calling
+dw::core::Imgbuf::copyRow) notify all renderers connected to the
+buffer.
+
+
+Image Renderer
+==============
+
+Generally, there are no restrictions on how to manage
+dw::core::Imgbuf; but to handle image data from web resources, the
+interface dw::core::ImgRenderer should be implemented. It is again
+wrapped by DilloImage (to make access from the C part possible, since
+dw::core::ImgRenderer is written in C++), which is referenced by
+DilloWeb. There are two positions where retrieving image data is
+initiated:
+
+- Html_load_image: for embedded images (implemented by dw::Image,
+ which implements dw::core::ImgRenderer);
+- StyleEngine::apply (search for "case
+ CSS_PROPERTY_BACKGROUND_IMAGE"): for backgrond images; there are
+ some implementations of dw::core::ImgRenderer within the context of
+ dw::core::style::StyleImage.
+
+Both are described in detail below. Notice that the code is quite
+similar; only the implementation of dw::core::ImgRenderer differs.
+
+At this time, dw::core::ImgRenderer has got two methods (see more
+documentation there):
+
+- dw::core::ImgRenderer::setBuffer,
+- dw::core::ImgRenderer::drawRow,
+- dw::core::ImgRenderer::finish, and
+- dw::core::ImgRenderer::fatal.
+
+
+Images
+======
+
+This is the simplest renderer, displaying an image. For each row to be
+drawn,
+
+- first dw::core::Imgbuf::copyRow, and then
+- for each dw::Image, dw::Image::drawRow must be called, with the same
+ argument (no scaling is necessary).
+
+dw::Image automatically scales the dw::core::Imgbuf, the root buffer
+should be passed to dw::Image::setBuffer.
+
+\see dw::Image for more details.
+
+
+Background Images
+=================
+
+Since background images are style resources, they are associated with
+dw::core::style::Style, as dw::core::style::StyleImage, which is
+handled in a similar way (reference counting etc.) as
+dw::core::style::Color and dw::core::style::Font, although it is
+concrete and not platform-dependant.
+
+The actual renderer (passed to Web) is an instance of
+dw::core::ImgRendererDist (distributes all calls to a set of other
+instances of dw::core::ImgRenderer), which contains two kinds of
+renderers:
+
+- one instance of dw::core::style::StyleImage::StyleImgRenderer, which
+ does everything needed for dw::core::style::StyleImage, and
+- other renderers, used externally (widgets etc.), which are added by
+ dw::core::style::StyleImage::putExternalImgRenderer (and removed by
+ dw::core::style::StyleImage::removeExternalImgRenderer).
+
+This diagram gives an comprehensive overview:
+
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10];
+ edge [arrowhead="open", dir="both", arrowtail="none",
+ labelfontname=Helvetica, labelfontsize=10, color="#404040",
+ labelfontcolor="#000080"];
+ fontname=Helvetica; fontsize=10;
+
+ subgraph cluster_dw_style {
+ style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+
+ Style [URL="\ref dw::core::style::Style"];
+ StyleImage [URL="\ref dw::core::style::StyleImage"];
+ Imgbuf [URL="\ref dw::core::Imgbuf", color="#a0a0a0"];
+ StyleImgRenderer
+ [URL="\ref dw::core::style::StyleImage::StyleImgRenderer"];
+ ImgRenderer [URL="\ref dw::core::ImgRenderer", color="#ff8080"];
+ ImgRendererDist [URL="\ref dw::core::ImgRendererDist"];
+ ExternalImgRenderer
+ [URL="\ref dw::core::style::StyleImage::ExternalImgRenderer",
+ color="#a0a0a0"];
+ ExternalWidgetImgRenderer
+ [URL="\ref dw::core::style::StyleImage::ExternalWidgetImgRenderer",
+ color="#a0a0a0"];
+ }
+
+ subgraph cluster_dw_layout {
+ style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+
+ Layout [URL="\ref dw::core::Layout"];
+ LayoutImgRenderer [URL="\ref dw::core::Layout::LayoutImgRenderer"];
+ }
+
+ subgraph cluster_dw_widget {
+ style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+
+ Widget [URL="\ref dw::core::Widget", color="#a0a0a0"];
+ WidgetImgRenderer [URL="\ref dw::core::Widget::WidgetImgRenderer"];
+ }
+
+ subgraph cluster_dw_textblock {
+ style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+
+ Textblock [URL="\ref dw::Textblock"];
+ Word [URL="\ref dw::Textblock::Word"];
+ WordImgRenderer [URL="\ref dw::Textblock::WordImgRenderer"];
+ SpaceImgRenderer [URL="\ref dw::Textblock::SpaceImgRenderer"];
+ }
+
+ Style -> StyleImage [headlabel="*", taillabel="1"];
+ StyleImage -> Imgbuf [headlabel="*", taillabel="1"];
+ StyleImage -> StyleImgRenderer [headlabel="1", taillabel="1"];
+ StyleImage -> ImgRendererDist [headlabel="1", taillabel="1"];
+ ImgRendererDist -> StyleImgRenderer [headlabel="1", taillabel="1"];
+ ImgRendererDist -> ImgRenderer [headlabel="1", taillabel="*"];
+
+ ImgRenderer -> ImgRendererDist [arrowhead="none", arrowtail="empty",
+ dir="both", style="dashed"];
+ ImgRenderer -> StyleImgRenderer [arrowhead="none", arrowtail="empty",
+ dir="both", style="dashed"];
+ ImgRenderer -> ExternalImgRenderer [arrowhead="none", arrowtail="empty",
+ dir="both", style="dashed"];
+ ExternalImgRenderer -> ExternalWidgetImgRenderer [arrowhead="none",
+ arrowtail="empty", dir="both", style="dashed"];
+
+ Layout -> LayoutImgRenderer [headlabel="1", taillabel="0..1"];
+ ExternalImgRenderer -> LayoutImgRenderer [arrowhead="none",
+ arrowtail="empty", dir="both", style="dashed"];
+
+ Widget -> WidgetImgRenderer [headlabel="1", taillabel="0..1"];
+ ExternalWidgetImgRenderer -> WidgetImgRenderer [arrowhead="none",
+ arrowtail="empty", dir="both", style="dashed"];
+
+ Textblock -> Word [headlabel="1", taillabel="*"];
+ Word -> WordImgRenderer [headlabel="1", taillabel="0..1"];
+ Word -> SpaceImgRenderer [headlabel="1", taillabel="0..1"];
+ ExternalWidgetImgRenderer -> WordImgRenderer [arrowhead="none",
+ arrowtail="empty", dir="both", style="dashed"];
+ WordImgRenderer -> SpaceImgRenderer [arrowhead="none", arrowtail="empty",
+ dir="both", style="dashed"];
+}
+\enddot
+
+<center>[\ref uml-legend "legend"]</center>
+
+
+Memory management
+-----------------
+
+dw::core::style::StyleImage extends lout::signal::ObservedObject, so
+that deleting this instance can be connected to code dealing with
+cache clients etc. See StyleImageDeletionReceiver and how it is
+attached in StyleEngine::apply ("case CSS_PROPERTY_BACKGROUND_IMAGE").
+
+
+Bugs and Things Needing Improvement
+===================================
+
+(Mostly related to image backgrounds, when not otherwise mentioned.)
+
+High Priority
+-------------
+
+**Configurability, security/privacy aspects, etc.,** which are
+currently available for image widgets, should be adopted. Perhaps some
+more configuration options specially for background images.
+
+
+Medium Priority
+---------------
+
+**Background-attachment** is not yet implemented, and will be postponed.
+
+**Calls to dw::core::ImgRenderer::fatal** are incomplete. As an
+example, it is not called, when connecting to a server fails. (And so,
+as far as I see, no cache client is started.)
+
+
+Low Priority
+------------
+
+**Alpha support:** (not related to image backgrounds) currently alpha
+support (and also colormap management) is done in dicache, while
+dw::Image is only created with type RGB. This leads to several problems:
+
+- One dicache entry (representing an image related to the same URL),
+ which has only one background color, may refer to different images
+ with different background colors.
+- The dicache only handles background colors, not background images.
+
+The solution is basicly simple: keep alpha support out of dicache;
+instead implement RGBA in dw::Image. As it seems, the main problem is
+alpha support in FLTK/X11.
+
+
+Solved (Must Be Documented)
+---------------------------
+
+*Drawing background images row by row may become slow. As an
+alternative, dw::core::ImgRenderer::finish could be used. However,
+drawing row by row could become an option.* There is now
+dw::core::style::drawBackgroundLineByLine, which can be changed in the
+code, and is set to *false*. The old code still exists, so changing
+this to *true* activates again drawing line by line.
+
+(For image widgets, this could also become an option: in contexts,
+when image data is retrieved in a very fast way.)
+
+*/
diff --git a/devdoc/dw-layout-views.doc b/devdoc/dw-layout-views.doc
new file mode 100644
index 00000000..d1118489
--- /dev/null
+++ b/devdoc/dw-layout-views.doc
@@ -0,0 +1,256 @@
+/** \page dw-layout-views Layout and Views
+
+Rendering of Dw is done in a way resembling the model-view pattern, at
+least formally. Actually, the counterpart of the model, the layout
+(dw::core::Layout), does a bit more than a typical model, namely the
+layouting (delegated to the widget tree, see \ref dw-layout-widgets),
+and the view does a bit less than a typical view, i.e. only the actual
+drawing.
+
+Additionally, there is a structure representing common properties of
+the platform. A platform is typically related to the underlying UI
+toolkit, but other uses may be thought of.
+
+This design helps to archieve two important goals:
+
+<ul>
+<li> Abstraction of the actual drawing, by different implementations
+ of dw::core::View.
+
+<li> It makes portability simple.
+</ul>
+
+
+<h2>Viewports</h2>
+
+Although the design implies that the usage of viewports should be
+fully transparent to the layout module, this cannot be fully achieved,
+for the following reasons:
+
+<ul>
+<li> Some features, which are used on the level of dw::core::Widget,
+ e.g. anchors, refer to scrolling positions.
+
+<li> Size hints (see \ref dw-layout-widgets) depend on the viewport
+ sizes, e.g. when the user changes the window size, and so also
+ the size of a viewport, the text within should be rewrapped.
+</ul>
+
+Therefore, dw::core::Layout keeps track of the viewport size, the
+viewport position, and even the thickness of the scrollbars, they are
+relevant, see below for more details.
+If a viewport is not used, however, the size is not defined.
+
+Whether a given dw::core::View implementation is a viewport or not, is
+defined by the return value of dw::core::View::usesViewport. If this
+method returns false, the following methods need not to be implemented
+at all:
+
+<ul>
+<li> dw::core::View::getHScrollbarThickness,
+<li> dw::core::View::getVScrollbarThickness,
+<li> dw::core::View::scrollTo, and
+<li> dw::core::View::setViewportSize.
+</ul>
+
+<h3>Scrolling Positions</h3>
+
+The scrolling position is the canvas position at the upper left corner
+of the viewport. Views using viewports must
+
+<ol>
+<li> change this value on request (dw::core::View::scrollTo), and
+<li> tell other changes to the layout, e.g. caused by user events
+ (dw::core::Layout::scrollPosChanged).
+</ol>
+
+Applications of scrolling positions (anchors, test search etc.) are
+handled by the layout, in a way fully transparent to the view.
+
+<h3>Scrollbars</h3>
+
+A feature of the viewport size model are scrollbars. There may be a
+vertical scrollbar and a horizontal scrollbar, displaying the
+relationship between canvas and viewport height or width,
+respectively. If they are not needed, they are hidden, to save screen
+space.
+
+Since scrollbars decrease the usable space of a view, dw::core::Layout
+must know how much space they take. The view returns, via
+dw::core::View::getHScrollbarThickness and
+dw::core::View::getVScrollbarThickness, how thick they will be, when
+visible.
+
+Viewport sizes, which denote the size of the viewport widgets, include
+scrollbar thicknesses. When referring to the viewport \em excluding
+the scrollbars space, we will call it "usable viewport size", this is
+the area, which is used to display the canvas.
+
+<h2>Drawing</h2>
+
+A view must implement several drawing methods, which work on the whole
+canvas. If it is necessary to convert them (e.g. into
+dw::fltk::FltkViewport), this is done in a way fully transparent to
+dw::core::Widget and dw::core::Layout, instead, this is done by the
+view implementation.
+
+There exist following situations:
+
+<ul>
+<li> A view gets an expose event: It will delegate this to the
+ layout (dw::core::Layout::draw), which will then pass it to the
+ widgets (dw::core::Widget::draw), with the view as a parameter.
+ Eventually, the widgets will call drawing methods of the view.
+
+<li> A widget requests a redraw: In this case, the widget will
+ delegate this to the layout (dw::core::Layout::queueDraw), which
+ delegates it to the view (dw::core::View::queueDraw).
+ Typically, the view will queue these requests for efficiency.
+
+<li> A widget requests a resize: This case is described below, in short,
+ dw::core::View::queueDrawTotal is called for the view.
+</ul>
+
+If the draw method of a widget is implemented in a way that it may
+draw outside of the widget's allocation, it should draw into a
+<i>clipping view.</i> A clipping view is a view related to the actual
+view, which guarantees that the parts drawn outside are discarded. At
+the end, the clipping view is merged into the actual view. Sample
+code:
+
+\code
+void Foo::draw (dw::core::View *view, dw::core::Rectangle *area)
+{
+ // 1. Create a clipping view.
+ dw::core::View clipView =
+ view->getClippingView (allocation.x, allocation.y,
+ allocation.width, getHeight ());
+
+ // 2. Draw into clip_view
+ clipView->doSomeDrawing (...);
+
+ // 3. Draw the children, they receive the clipping view as argument.
+ dw::core::Rectangle *childArea
+ for (<all relevant children>) {
+ if (child->intersects (area, &childArea))
+ child->draw (clipView, childArea);
+ }
+
+ // 4. Merge
+ view->mergeClippingView (clipView);
+}
+\endcode
+
+A drawing process is always embedded into calls of
+dw::core::View::startDrawing and dw::core::View::finishDrawing. An
+implementation of this may e.g. use backing pixmaps, to prevent
+flickering.
+
+
+<h2>Sizes</h2>
+
+In the simplest case, the view does not have any influence on
+the canvas size, so it is told about changes of the
+canvas size by a call to dw::core::View::setCanvasSize. This happens
+in the following situations:
+
+<ul>
+<li> dw::core::Layout::addWidget,
+<li> dw::core::Layout::removeWidget (called by dw::core::Widget::~Widget),
+ and
+<li> dw::core::Layout::queueResize (called by
+ dw::core::Widget::queueResize, when a widget itself requests a size
+ change).
+</ul>
+
+<h3>Viewports</h3>
+
+There are two cases where the viewport size changes:
+
+<ul>
+<li> As an reaction on a user event, e.g. when the user changes the
+ window size. In this case, the view delegates this
+ change to the layout, by calling
+ dw::core::Layout::viewportSizeChanged.
+
+<li> The viewport size may also depend on the visibility of UI
+ widgets, which depend on the world size, e.g scrollbars,
+ generally called "viewport markers". This is described in a separate
+ section.
+</ul>
+
+After the creation of the layout, the viewport size is undefined. When
+a view is attached to a layout, and this view can already specify
+its viewport size, it may call
+dw::core::Layout::viewportSizeChanged within the implementation of
+dw::core::Layout::setLayout. If not, it may do this as soon as the
+viewport size is known.
+
+Generally, the scrollbars have to be considered. If e.g. an HTML page
+is rather small, it looks like this:
+
+\image html dw-viewport-without-scrollbar.png
+
+If some more data is retrieved, so that the height exceeds the
+viewport size, the text has to be rewrapped, since the available width
+gets smaller, due to the vertical scrollbar:
+
+\image html dw-viewport-with-scrollbar.png
+
+Notice the different line breaks.
+
+This means circular dependencies between these different sizes:
+
+<ol>
+<li> Whether the scrollbars are visible or not, determines the
+ usable space of the viewport.
+
+<li> From the usable space of the viewport, the size hints for the
+ toplevel are calculated.
+
+<li> The size hints for the toplevel widgets may have an effect on its
+ size, which is actually the canvas size.
+
+<li> The canvas size determines the visibility of the scrollbarss.
+</ol>
+
+To make an implementation simpler, we simplify the model:
+
+<ol>
+<li> For the calls to dw::core::Widget::setAscent and
+ dw::core::Widget::setDescent, we will always exclude the
+ horizontal scrollbar thickness (i.e. assume the horizontal
+ scrollbar is used, although the visibility is determined correctly).
+
+<li> For the calls to dw::core::Widget::setWidth, we will calculate
+ the usable viewport width, but with the general assumption, that
+ the widget generally gets higher.
+</ol>
+
+This results in the following rules:
+
+<ol>
+<li> Send always (when it changes) dw::core::Layout::viewportHeight
+ minus the maximal value of dw::core::View::getHScrollbarThickness as
+ argument to dw::core::Widget::setAscent, and 0 as argument to
+ dw::core::Widget::setDescent.
+
+<li> There is a flag, dw::core::Layout::canvasHeightGreater, which is set
+ to false in the following cases:
+
+ <ul>
+ <li> dw::core::Layout::addWidget,
+ <li> dw::core::Layout::removeWidget (called by dw::core::Widget::~Widget),
+ and
+ <li> dw::core::Layout::viewportSizeChanged.
+ </ul>
+
+ Whenever the canvas size is calculated (dw::core::Layout::resizeIdle),
+ and dw::core::Layout::canvasHeightGreater is false, a test is made,
+ whether the widget has in the meantime grown that high, that the second
+ argument should be set to true (i.e. the vertical scrollbar gets visible).
+ As soon as and dw::core::Layout::canvasHeightGreater is true, no such test
+ is done anymore.
+</ol>
+
+*/
diff --git a/devdoc/dw-layout-widgets.doc b/devdoc/dw-layout-widgets.doc
new file mode 100644
index 00000000..e0215562
--- /dev/null
+++ b/devdoc/dw-layout-widgets.doc
@@ -0,0 +1,267 @@
+/** \page dw-layout-widgets Layout and Widgets
+
+Both, the layouting and the drawing is delegated to a tree of
+widgets. A widget represents a given part of the document, e.g. a text
+block, a table, or an image. Widgets may be nested, so layouting and
+drawing may be delegated by one widget to its child widgets.
+
+Where to define the borders of a widget, whether to combine different
+widgets to one, or to split one widget into multiple ones, should be
+considered based on different concerns:
+
+<ul>
+<li> First, there are some restrictions of Dw:
+
+ <ul>
+ <li> The allocation (this is the space a widget allocates at
+ a time) of a dillo widget is always rectangular, and
+ <li> the allocation of a child widget must be a within the allocation
+ of the parent widget.
+ </ul>
+
+<li> Since some widgets are already rather complex, an important goal
+ is to keep the implementation of the widget simple.
+
+<li> Furthermore, the granularity should not be too fine, because of the
+ overhead each single widget adds.
+</ul>
+
+For CSS, there will be a document tree on top of Dw, this will be
+flexible enough when mapping the document structure on the widget
+structure, so you should not have the document structure in mind.
+
+<h2>Sizes</h2>
+
+\ref dw-widget-sizes
+
+
+<h2>Styles</h2>
+
+Each widget is assigned a style, see dw::core::style for more
+informations.
+
+
+<h2>Iterators</h2>
+
+Widgets must implement dw::core::Widget::iterator. There are several
+common iterators:
+
+<ul>
+<li>dw::core::EmptyIterator, and
+<li>dw::core::TextIterator.
+</ul>
+
+Both hide the constructor, use the \em create method.
+
+These simple iterators only iterate through one widget, it does not
+have to iterate recursively through child widgets. Instead, the type
+dw::core::Content::WIDGET is returned, and the next call of
+dw::core::Iterator::next will return the piece of contents \em after
+(not within) this child widget.
+
+This makes implementation much simpler, for recursive iteration, there
+is dw::core::DeepIterator.
+
+
+<h2>Anchors and Scrolling</h2>
+
+\todo This section is not implemented yet, after the implementation,
+ the documentation should be reviewed.
+
+Here is a description, what is to be done for a widget
+implementation. How to jump to anchors, set scrolling positions
+etc. is described in \ref dw-usage.
+
+<h3>Anchors</h3>
+
+Anchors are position markers, which are identified by a name, which is
+unique in the widget tree. The widget must care about anchors in three
+different situations:
+
+<ol>
+<li> Adding an anchor is inititiated by a specific widget method, e.g.
+ dw::Textblock::addAnchor. Here, dw::core::Widget::addAnchor must be
+ called,
+
+<li> Whenever the position of an anchor is changed,
+ dw::core::Widget::changeAnchor is called (typically, this is done
+ in the implementation of dw::core::Widget::sizeAllocateImpl).
+
+<li> When a widget is destroyed, the anchor must be removed, by calling
+ dw::core::Widget::removeAnchor.
+</ol>
+
+All these methods are delegated to dw::core::Layout, which manages
+anchors centrally. If the anchor in question has been set to jump to,
+the viewport position is automatically adjusted, see \ref
+dw-usage.
+
+
+<h2>Drawing</h2>
+
+In two cases, a widget has to be drawn:
+
+<ol>
+<li> as a reaction on an expose event,
+<li> if the widget content has changed and it needs to be redrawn.
+</ol>
+
+In both cases, drawing is done by the implementation of
+dw::core::Widget::draw, which draws into the view.
+
+
+Each view provides some primitive methods for drawing, most should be
+obvious. Note that the views do not know anything about dillo
+widgets, and so coordinates have to be passed as canvas coordinates.
+
+A widget may only draw in its own allocation. If this cannot be
+achieved, a <i>clipping view</i> can be used, this is described in
+\ref dw-layout-views. Generally, drawing should then look like:
+
+\code
+void Foo::draw (dw::core::View *view, dw::core::Rectangle *area)
+{
+ // 1. Create a clipping view.
+ dw::core::View clipView =
+ view->getClippingView (allocation.x, allocation.y,
+ allocation.width, getHeight ());
+
+ // 2. Draw into clip_view
+ clipView->doSomeDrawing (...);
+
+ // 3. Draw the children, they receive the clipping view as argument.
+ dw::core::Rectangle *childArea
+ for (<all relevant children>) {
+ if (child->intersects (area, &childArea))
+ child->draw (clipView, childArea);
+ }
+
+ // 4. Merge
+ view->mergeClippingView (clipView);
+}
+\endcode
+
+Clipping views are expensive, so they should be avoided when possible.
+
+The second argument to dw::core::Widget::draw is the region, which has
+to be drawn. This may (but needs not) be used for optimization.
+
+If a widget contains child widgets, it must explicitly draw these
+children (see also code example above). For this, there is the useful
+method dw::core::Widget::intersects, which returns, which area of the
+child must be drawn.
+
+<h3>Explicit Redrawing</h3>
+
+If a widget changes its contents, so that it must be redrawn, it must
+call dw::core::Widget::queueDrawArea or
+dw::core::Widget::queueDraw. The first variant expects a region within
+the widget, the second will cause the whole widget to be redrawn. This
+will cause an asynchronous call of dw::core::Widget::draw.
+
+If only the size changes, a call to dw::core::Widget::queueResize is
+sufficient, this will also queue a complete redraw (see \ref
+dw-widget-sizes.)
+
+
+<h2>Mouse Events</h2>
+
+A widget may process mouse events. The view (\ref dw-layout-views)
+passes mouse events to the layout, which then passes them to the
+widgets. There are two kinds of mouse events:
+
+<ul>
+<li>events returning bool, and
+<li>events returning nothing (void).
+</ul>
+
+The first group consists of:
+
+<ul>
+<li>dw::core::Widget::buttonPressImpl,
+<li>dw::core::Widget::buttonReleaseImpl, and
+<li>dw::core::Widget::motionNotifyImpl.
+</ul>
+
+For these events, a widget returns a boolean value, which denotes,
+whether the widget has processed this event (true) or not (false). In
+the latter case, the event is delegated according to the following
+rules:
+
+<ol>
+<li> First, this event is passed to the bottom-most widget, in which
+ allocation the mouse position is in.
+<li> If the widget does not process this event (returning false), it is
+ passed to the parent, and so on.
+<li> The final result (whether \em any widget has processed this event) is
+ returned to the view.
+</ol>
+
+The view may return this to the UI toolkit, which then interprets this
+in a similar way (whether the viewport, a UI widget, has processed
+this event).
+
+These events return nothing:
+
+<ul>
+<li>dw::core::Widget::enterNotifyImpl and
+<li>dw::core::Widget::leaveNotifyImpl.
+</ul>
+
+since they are bound to a widget.
+
+When processing mouse events, the layout always deals with two
+widgets: the widget, the mouse pointer was in, when the previous mouse
+event was processed, (below called the "old widget") and the widget,
+in which the mouse pointer is now ("new widget").
+
+The following paths are calculated:
+
+<ol>
+<li> the path from the old widget to the nearest common ancestor of the old
+ and the new widget, and
+<li> the path from this ancestor to the new widget.
+</ol>
+
+For the widgets along these paths, dw::core::Widget::enterNotifyImpl
+and dw::core::Widget::leaveNotifyImpl are called.
+
+<h3>Signals</h3>
+
+If a caller outside of the widget is interested in these events, he
+can connect a dw::core::Layout::LinkReceiver. For those events with a
+boolean return value, the results of the signal emission is regarded,
+i.e. the delegation of an event to the parent of the widget can be
+stopped by a signal receiver returning true, even if the widget method
+returns false.
+
+First, the widget method is called, then (in any case) the signal is
+emitted.
+
+<h3>Selection</h3>
+
+If your widget has selectable contents, it should delegate the events
+to dw::core::SelectionState (dw::core::Layout::selectionState).
+
+
+<h2>Miscellaneous</h2>
+
+<h3>Cursors</h3>
+
+Each widget has a cursor, which is set by
+dw::core::Widget::setCursor. If a cursor is assigned to a part of a
+widget, this widget must process mouse events, and call
+dw::core::Widget::setCursor explicitly.
+
+(This will change, cursors should become part of
+dw::core::style::Style.)
+
+<h3>Background</h3>
+
+Backgrounds are part of styles
+(dw::core::style::Style::backgroundColor). If a widget assigns
+background colors to parts of a widget (as dw::Table does for rows),
+it must call dw::core::Widget::setBgColor for the children inside this
+part.
+
+*/
diff --git a/devdoc/dw-line-breaking.doc b/devdoc/dw-line-breaking.doc
new file mode 100644
index 00000000..14ab97c4
--- /dev/null
+++ b/devdoc/dw-line-breaking.doc
@@ -0,0 +1,470 @@
+/** \page dw-line-breaking Changes in Line-Breaking and Hyphenation
+
+<div style="border: 2px solid #ffff00; margin-bottom: 0.5em;
+padding: 0.5em 1em; background-color: #ffffe0"><b>Info:</b>
+Should be incorporated into dw::Textblock.</div>
+
+Introduction
+============
+
+For the implementation of hyphenation in dillo, not only a
+hyphenation algorithm was implemented, but also, the line breaking was
+changed to a simple optimization per line. Aside from the improvement
+by this change per se, an important aspect is the introduction of
+"penalties". Before this change, dillo put all words into a line which
+fitted into it; now, a "badness" is calculated for a possible
+breakpoint, and the best breakpoint, i.&nbsp;e. the breakpoint with the
+smallest value for "badness", is chosen. This can be simply refined
+to define "good" and "bad" breakpoints by assigning a "penalty"; the
+best breakpoint is then the one with the smallest value of "badness +
+penalty". Details can be found below.
+
+Example: Normal spaces have a penalty of 0, while hyphenation points
+get a penalty of, say, 1, since hyphenation is generally considered as
+a bit "ugly" and should rather be avoided. Consider a situation where
+the word "dillo" could be hyphenated, with the following badnesses:
+
+- before "dillo": 0.6;
+- between "dil-" and "lo": 0.2;
+- after "dillo": 0.5.
+
+Since the penalty is added, the last value is the best one, so "dillo"
+is put at the end of the line, without hyphenation.
+
+Under other circumstances (e.&nbsp;g. narrower lines), the values
+might be different:
+
+- before "dillo": infinite;
+- between "dil-" and "lo": 0.3;
+- after "dillo": 1.5.
+
+In this case, even the addition of the penalty makes hyphenation the
+best choice.
+
+
+Literature
+==========
+
+Breaking Paragraphs Into Lines
+------------------------------
+
+Although dillo does not (yet?) implement the algorithm T<sub>E</sub>X
+uses for line breaking, this document shares much of the notation used
+by the article *Breaking Paragraphs Into Lines* by Donald E. Knuth and
+Michael F. Plass; originally published in: Software -- Practice and
+Experience **11** (1981), 1119-1184; reprinted in: *Digital
+Typography* by Donalt E. Knuth, CSLI Publications 1999. Anyway an
+interesting reading.
+
+Hyphenation
+-----------
+
+Dillo uses the algorithm by Frank Liang, which is described in his
+doctoral dissertation found at http://www.tug.org/docs/liang/. There
+is also a description in chapter H ("Hyphenation") of *The
+T<sub>E</sub>Xbook* by Donald E. Knuth, Addison-Wesley 1984.
+
+Pattern files can be found at
+http://www.ctan.org/tex-archive/language/hyphenation.
+
+
+Overview of Changes
+===================
+
+Starting with this change, dw/textblock.cc has been split up; anything
+related to line breaking has been moved into
+dw/textblock_linebreaking.cc. This will also be done for other aspects
+like floats. (Better, however, would be a clean logical split.)
+
+An important change relates to the way that lines are added: before,
+dillo would add a line as soon as a new word for this line was
+added. Now, a line is added not before the *last* word of this line is
+known. This has two important implications:
+
+- Some values in dw::Textblock::Line, which represented values
+ accumulated within the line, could be removed, since now, these
+ values can be calculated simply in a loop.
+- On the other hand, this means that some words may not belong to any
+ line. For this reason, in some cases (e.&nbsp;g. in
+ dw::Textblock::sizeRequestImpl) dw::Textblock::showMissingLines is
+ called, which creates temporary lines, which must, under other
+ circumstances, be removed again by
+ dw::Textblock::removeTemporaryLines, since they have been created
+ based on limited information, and so possibly in a wrong way. (See
+ below for details.)
+
+When a word can be hyphenated, an instance of dw::Textblock::Word is
+used for each part. Notice that soft hyphens are evaluated
+immediately, but automatic hyphenation is done in a lazy way (details
+below), so the number of instances may change. There are some new
+attributes: only when dw::Textblock::Word::canBeHyphenated is set to
+*true*, automatic hyphenation is allowed; it is set to false when soft
+hyphens are used for a word, and (of course) by the automatic
+hyphenation itself. Furthermore, dw::Textblock::Word::hyphenWidth
+(more details in the comment there) has to be included when
+calculating line widths.
+
+Some values should be configurable: dw::Textblock::HYPHEN_BREAK, the
+penalty for hyphens. Also dw::Textblock::Word::stretchability,
+dw::Textblock::Word::shrinkability, which are both set in
+dw::Textblock::addSpace.
+
+
+Criteria for Line-Breaking
+==========================
+
+Before these changes to line breaking, a word (represented by
+dw::Textblock::Word) had the following attributes related to
+line-breaking:
+
+- the width of the word itself, represented by
+ dw::Textblock::Word::size;
+- the width of the space following the word, represented by
+ dw::Textblock::Word::origSpace.
+
+In a more mathematical notation, the \f$i\f$th word has a width
+\f$w_i\f$ and a space \f$s_i\f$.
+
+A break was possible, when there was a space between the two words,
+and the first possible break was chosen.
+
+With hyphenation, the criteria are refined. Hyphenation should only be
+used when otherwise line breaking results in very large spaces. We
+define:
+
+- the badness \f$\beta\f$ of a line, which is greater the more the
+ spaces between the words differ from the ideal space;
+- a penalty \f$p\f$ for any possible break point.
+
+The goal is to find those break points, where \f$\beta + p\f$ is
+minimal.
+
+Examples for the penalty \f$p\f$:
+
+- 0 for normal line breaks (between words);
+- \f$\infty\f$ to prevent a line break at all costs;
+- \f$-\infty\f$ to force a line
+- a positive, but finite, value for hyphenation points.
+
+So we need the following values:
+
+- \f$w_i\f$ (the width of the word \f$i\f$ itself);
+- \f$s_i\f$ (the width of the space following the word \f$i\f$);
+- the stretchability \f$y_i\f$, a value denoting how much the space
+ after word\f$i\f$ can be stretched (typically \f${1\over 2} s_i\f$
+ for justified text; otherwise 0, since the spaces are not
+ stretched);
+- the shrinkability \f$y_i\f$, a value denoting how much the space
+ after word\f$i\f$ can be shrunken (typically \f${1\over 3} s_i\f$
+ for justified text; otherwise 0, since the spaces are not shrinked);
+- the penalty \f$p_i\f$, if the line is broken after word \f$i\f$;
+- a width \f$h_i\f$, which is added, when the line is broken after
+ word \f$i\f$.
+
+\f$h_i\f$ is the width of the hyphen, if the word \f$i\f$ is a part of
+the hyphenated word (except the last part); otherwise 0.
+
+Let \f$l\f$ be the (ideal) width (length) of the line, which is
+e.&nbsp;at the top given by the browser window width. Furthermore, all words
+from \f$a\f$ to \f$b\f$ are added to the line. \f$a\f$ is fixed: we do
+not modify the previous lines anymore; but our task is to find a
+suitable \f$b\f$.
+
+We define:
+
+\f[W_a^b = \sum_{i=a}^{b} w_i + \sum_{i=a}^{b-1} s_i + h_b\f]
+
+\f[Y_a^b = {Y_0}_a^b + \sum_{i=a}^{b-1} y_i\f]
+
+\f[Z_a^b = {Z_0}_a^b + \sum_{i=a}^{b-1} z_i\f]
+
+
+\f$W_a^b\f$ is the total width, \f$Y_a^b\f$ the total stretchability,
+and \f$Z_a^b\f$ the total shrinkability. \f${Y_0}_a^b\f$ and
+\f${Z_0}_a^b\f$ are the stretchability and shrinkability defined per
+line, and applied at the borders; they are 0 for justified text, but
+\f${Y_0}_a^b\f$ has a positive value otherwise, see below for details.
+
+Furthermore the *adjustment ratio* \f$r_a^b\f$:
+
+- in the ideal case that \f$W_a^b = l\f$: \f$r_a^b = 0\f$;
+- if \f$W_a^b < l\f$: \f$r_a^b = (l - W_a^b) / Y_a^b\f$
+ (\f$r_a^b < 0\f$ in this case);
+- if \f$W_a^b > l\f$: \f$r_a^b = (l - W_a^b) / Z_a^b\f$
+ (\f$r_a^b < 0\f$ in this case).
+
+The badness \f$\beta_a^b\f$ is defined as follows:
+
+- if \f$r_a^b\f$ is undefined or \f$r_a^b < -1\f$: \f$\beta_a^b = \infty\f$;
+- otherwise: \f$\beta_a^b = |r_a^b|^3\f$
+
+The goal is to find the value of \f$b\f$ where \f$\beta_a^b + p_b\f$
+is minimal. (\f$a\f$ is given, since we do not modify the previous
+lines.)
+
+After a couple of words, it is not predictable whether this minimum
+has already been reached. There are two cases where this is possible
+for a given \f$b'\f$:
+
+- \f$\beta_{b'}^a = \infty\f$ (line gets too tight):
+ \f$a \le b < b'\f$, the minimum has to be searched between these two
+ values;
+- \f$p_{b'} = -\infty\f$ (forced line break):
+ \f$a \le b \le b'\f$ (there may be another minimum of
+ \f$\beta_a^b\f$ before; note the \f$\le\f$ instead of \f$<\f$).
+
+This leads to a problem that the last words of a text block are not
+displayed this way, since they do not fulfill these rules for being
+added to a line. For this reason, there are "temporary" lines already
+described above.
+
+(Note that the actual calculation differs from this description, since
+integer arithmetic is used for performance, which make the actual
+code more complicated. See dw::Textblock::BadnessAndPenalty for
+details.)
+
+Ragged Borders
+--------------
+
+For other than justified text (left-, right-aligned and centered), the
+spaces between the words are not shrinked or stretched (so \f$y_i\f$
+and \f$z_i\f$ are 0), but additional space is added to the left or
+right border or to both. For this reason, an additional stretchability
+\f${Y_0}_a^b\f$ is added (see definition above). Since this space at
+the border is 0 in an ideal case (\f$W_a^b = l\f$), it cannot be
+shrunken, so \f${Z_0}_a^b\f$ is 0.
+
+This is not equivalent to the calculation of the total stretchability
+as done for justified text, since in this case, the stretchability
+depends on the number of words: consider the typical case that all
+spaces and stretchabilities are equal (\f$y_a = y_{a + 1} = \ldots =
+y_b\f$). With \f$n\f$ words, the total strechability would be \f$n
+\cdot y_a\f$, so increase with an increasing number of words
+(\f$y_a\f$ is constant). This is correct for justified text, but for
+other alignments, where only one space (or two, for centered text) is
+changed, this would mean that a line with many narrow words is more
+stretchable than a line with few wide words.
+
+It is obvious that left-aligned text can be handled in the same way as
+right-aligned text. [... Centered text? ...]
+
+The default value for the stretchability is the line height without
+the space between the lines (more precisely: the maximum of all word
+heights). The exact value not so important when comparing different
+possible values for the badness \f$\beta_a^b\f$, when \f${Y_0}_a^b\f$
+is nearly constant for different \f$b\f$ (which is the case for the
+actual value), but it is important for the comparison with penalties,
+which are constant. To be considered is also that for non-justified
+text, hyphenation is differently (less) desirable; this effect can be
+achieved by enlarging the stretchability, which will lead to a smaller
+badness, and so make hyphenation less likely. The user can configure
+the stretchability by changing the preference value
+*stretchability_factor* (default: 1.0).
+
+(Comparison to T<sub>E</sub>X: Knuth and Plass describe a method for
+ragged borders, which is effectively the same as described here (Knuth
+1999, pp.&nbsp;93--94). The value for the stretchability of the line
+is slightly less, 1&nbsp;em (ibid., see also p.&nbsp;72 for the
+definition of the units). However, this article suggests a value for
+the hyphenation penalty, which is ten times larger than the value for
+justified text; this would suggest a larger value for
+*stretchability_factor*.)
+
+
+Hyphens
+=======
+
+Words (instances of dw::Textblock::Word), which are actually part of a
+hyphenated word, are always drawn as a whole, not seperately. This
+way, the underlying platform is able to apply kerning, ligatures, etc.
+
+Calculating the width of such words causes some problems, since it is
+not required that the width of text "AB" is identical to the width of
+"A" plus the width of "B", just for the reasons mentioned above. It
+gets even a bit more complicated, since it is required that a word
+part (instance of dw::Textblock::Word) has always the same length,
+independent of whether hyphenation is applied or not. Furthermore, the
+hyphen length is fixed for a word; for practical reasons, it is always
+the width of a hyphen, in the given font.
+
+For calculating the widths, consider a word of four syllables:
+A-B-C-D. There are 3 hyphenation points, and so 2<sup>3</sup> = 8
+possible ways of hyphenation: ABCD, ABC-D, AB-CD, AB-C-D, A-BCD,
+A-BC-D, A-B-CD, A-B-C-D. (Some of them, like the last one, are only
+probable for very narrow lines.)
+
+Let w(A), w(B), w(C), w(D) be the word widths (part of
+dw::Textblock::Word::size), which have to be calculated, and l be a
+shorthand for dw::core::Platform::textWidth. Without considering
+this problem, the calculation would be simple: w(A) = l(A)
+etc. However, it gets a bit more complicated. Since all
+non-hyphenations are drawn as a whole, the following conditions can be
+concluded:
+
+- from drawing "ABCD" (not hyphenated at all): w(A) + w(B) + w(C) +
+ w(D) = l(ABCD);
+- from drawing "BCD", when hyphenated as "A-BCD" ("A-" is not
+ considered here): w(B) + w(C) + w(D) = l(BCD);
+- likewise, from drawing "CD" (cases "AB-CD" and "A-B-CD"): w(C) +
+ w(D) = l(CD);
+- finally, for the cases "ABC-D", "AB-C-D", "A-BC-D", and "A-B-C-D":
+ w(D) = l(D).
+
+So, the calculation is simple:
+
+- w(D) = l(D)
+- w(C) = l(CD) - w(D)
+- w(B) = l(BCD) - (w(C) + w(D))
+- w(A) = l(ABCD) - (w(B) + w(C) + w(D))
+
+For calculation the hyphen widths, the exact conditions would be
+over-determined, even when the possibility for individual hyphen
+widths (instead of simply the text width of a hyphen character) would
+be used. However, a simple approach of fixed hyphen widths will have
+near-perfect results, so this is kept simple.
+
+
+Automatic Hyphenation
+=====================
+
+When soft hyphens are used, words are immediately divided into
+different parts, and so different instances of
+dw::Textblock::Word. Automatic hyphenation (using Liang's algorithm)
+is, however, not applied always, but only when possibly needed, after
+calculating a line without hyphenation:
+
+- When the line is tight, the last word of the line is hyphenated;
+ possibly this will result in a line with less parts of this word,
+ and so a less tight line.
+- When the line is loose, and there is another word (for the next
+ line) available, this word is hyphenated; possibly, some parts of
+ this word are taken into this line, making it less loose.
+
+After this, the line is re-calculated.
+
+A problem arrises when the textblock is rewrapped, e.&nbsp;g. when the
+user changes the window width. In this case, some new instances of
+dw::Textblock::Word must be inserted into the word list,
+dw::Textblock::words. This word list is implemented as an array, which
+is dynamically increased; a simple approach would involve moving all
+of the <i>n</i> elements after position <i>i</i>, so
+<i>n</i>&nbsp;-&nbsp;<i>i</i> steps are necessary. This would not be a
+problem, since O(n) steps are necessary; however, this will be
+necessary again for the next hyphenated word (at the end of a
+following line), and so on, so that
+(<i>n</i>&nbsp;-&nbsp;<i>i</i><sub>1</sub>) +
+(<i>n</i>&nbsp;-&nbsp;<i>i</i><sub>2</sub>) + ..., with
+<i>i</i><sub>1</sub>&nbsp;&lt;&nbsp;<i>i</i><sub>2</sub>&nbsp;&lt;&nbsp;...,
+which results in O(n<sup>2</sup>) steps. For this reason, the word
+list is managed by the class lout::misc::NotSoSimpleVector, which uses
+a trick (a second array) to deal with exactly this problem. See there
+for more details.
+
+
+Tests
+=====
+
+There are test HTML files in the <i>test</i> directory. Also, there is
+a program testing automatic hyphenation, <i>test/liang</i>, which can
+be easily extended.
+
+
+Bugs and Things Needing Improvement
+===================================
+
+High Priority
+-------------
+
+None.
+
+Medium Priority
+---------------
+
+None.
+
+Low Priority
+------------
+
+**Mark the end of a paragraph:** Should dw::core::Content::BREAK still
+be used? Currently, this is redundant to
+dw::Textblock::BadnessAndPenalty.
+
+Solved (Must Be Documented)
+---------------------------
+
+These have been solved recently and should be documented above.
+
+*Bugs in hyphenation:* There seem to be problems when breaking words
+containing hyphens already. Example: "Abtei-Stadt", which is divided
+into "Abtei-" and "Stadt", resulting possibly in
+&quot;Abtei-<span></span>-[new line]Stadt&quot;. See also below under
+"Medium Priority", on how to deal with hyphens and dashes.
+
+**Solution:** See next.
+
+*Break hyphens and dashes:* The following rules seem to be relevant:
+
+- In English, an em-dash is used with no spaces around. Breaking
+ before and after the dash should be possible, perhaps with a
+ penalty > 0. (In German, an en-dash (Halbgeviert) with spaces around
+ is used instead.)
+- After a hyphen, which is part of a compound word, a break should be
+ possible. As described above ("Abtei-Stadt"), this collides with
+ hyphenation.
+
+Where to implement? In the same dynamic, lazy way like hyphenation? As
+part of hyphenation?
+
+Notice that Liang's algorithm may behave different regarding hyphens:
+"Abtei-Stadt" is (using the patterns from CTAN) divided into "Abtei-"
+and "Stadt", but "Nordrhein-Westfalen" is divided into "Nord",
+"rhein-West", "fa", "len": the part containing the hyphen
+("rhein-West") is untouched. (Sorry for the German words; if you have
+got English examples, send them me.)
+
+**Solution for both:** This has been implemented in
+dw::Textblock::addText, in a similar way to soft hyphens. Liang's
+algorithm now only operates on the parts: "Abtei" and "Stadt";
+"Nordrhein" and "Westfalen".
+
+*Hyphens in adjacent lines:* It should be simple to assign a larger
+penalty for hyphens, when the line before is already hyphenated. This
+way, hyphens in adjacent lines are penalized further.
+
+**Solved:** There are always two penalties. Must be documented in
+detail.
+
+*Incorrect calculation of extremes:* The minimal width of a text block
+(as part of the width extremes, which are mainly used for tables) is
+defined by everything between two possible breaks. A possible break
+may also be a hyphenation point; however, hyphenation points are
+calculated in a lazy way, when the lines are broken, and not when
+extremes are calculated. So, it is a matter of chance whether the
+calculation of the minimal width will take the two parts "dil-" and
+"lo" into account (when "dillo" has already been hyphenated), or only
+one part, "dillo" (when "dillo" has not yet been hyphenated),
+resulting possibly in a different value for the minimal width.
+
+Possible strategies to deal with this problem:
+
+- Ignore. The implications should be minimal.
+- Any solution will make it neccessary to hyphenate at least some
+ words when calculating extremes. Since the minimal widths of all
+ words are used to calculate the minimal width of the text block, the
+ simplest approach will hyphenate all words. This would, of course,
+ eliminate the performance gains of the current lazy approach.
+- The latter approach could be optimized in some ways. Examples: (i)
+ If a word is already narrower than the current accumulated value for
+ the minimal width, it makes no sense to hyphenate it. (ii) In other
+ cases, heuristics may be used to estimate the number of syllables,
+ the width of the widest of them etc.
+
+**Solved:** Hyphenated parts of a word are not considered anymore for
+width extremes, but only whole words. This is also one reason for the
+introduction of the paragraphs list.
+
+**Also:**
+
+- Configuration of penalties.
+
+*/
diff --git a/devdoc/dw-map.doc b/devdoc/dw-map.doc
new file mode 100644
index 00000000..aebeb7da
--- /dev/null
+++ b/devdoc/dw-map.doc
@@ -0,0 +1,59 @@
+/** \page dw-map Dillo Widget Documentation Map
+
+This maps includes special documentations as well as longer comments
+in the sources. Arrows denote references between the documents.
+
+\dot
+digraph G {
+ rankdir=LR;
+ node [shape=record, fontname=Helvetica, fontsize=8];
+ fontname=Helvetica; fontsize=8;
+
+ dw_overview [label="Dillo Widget Overview", URL="\ref dw-overview"];
+ dw_usage [label="Dillo Widget Usage", URL="\ref dw-usage"];
+ dw_layout_views [label="Layout and Views", URL="\ref dw-layout-views"];
+ dw_layout_widgets [label="Layout and Widgets",
+ URL="\ref dw-layout-widgets"];
+ dw_widget_sizes [label="Sizes of Dillo Widgets",
+ URL="\ref dw-widget-sizes"];
+ dw_changes [label="Changes to the GTK+-based Release Version",
+ URL="\ref dw-changes"];
+ dw_images_and_backgrounds [label="Images and Backgrounds in Dw",
+ URL="\ref dw-images-and-backgrounds"];
+ dw_Image [label="dw::Image", URL="\ref dw::Image"];
+ dw_core_Imgbuf [label="dw::core::Imgbuf", URL="\ref dw::core::Imgbuf"];
+ dw_core_SelectionState [label="dw::core::SelectionState",
+ URL="\ref dw::core::SelectionState"];
+ dw_core_style [label="dw::core::style", URL="\ref dw::core::style"];
+ dw_Table [label="dw::Table", URL="\ref dw::Table"];
+ dw_Textblock [label="dw::Textblock", URL="\ref dw::Textblock"];
+ dw_core_ui [label="dw::core::ui", URL="\ref dw::core::ui"];
+
+ dw_overview -> dw_changes;
+ dw_overview -> dw_usage;
+ dw_overview -> dw_core_style;
+ dw_overview -> dw_core_ui;
+ dw_overview -> dw_images_and_backgrounds;
+ dw_overview -> dw_layout_widgets;
+ dw_overview -> dw_widget_sizes;
+ dw_overview -> dw_layout_views;
+
+ dw_usage -> dw_Table;
+ dw_usage -> dw_Textblock;
+ dw_usage -> dw_core_style;
+ dw_usage -> dw_core_ui;
+ dw_usage -> dw_images_and_backgrounds;
+
+ dw_layout_widgets -> dw_widget_sizes;
+ dw_layout_widgets -> dw_core_SelectionState;
+
+ dw_widget_sizes -> dw_Table;
+ dw_widget_sizes -> dw_Textblock;
+
+ dw_images_and_backgrounds -> dw_core_Imgbuf;
+ dw_images_and_backgrounds -> dw_Image;
+
+ dw_core_style -> dw_Textblock;
+}
+\enddot
+*/ \ No newline at end of file
diff --git a/devdoc/dw-out-of-flow-2.doc b/devdoc/dw-out-of-flow-2.doc
new file mode 100644
index 00000000..d9d70565
--- /dev/null
+++ b/devdoc/dw-out-of-flow-2.doc
@@ -0,0 +1,69 @@
+/** \page dw-out-of-flow-2 Handling Elements Out Of Flow (notes 2)
+
+This has to be integrated into \ref dw-out-of-flow.
+
+Constructing a page with floats
+-------------------------------
+When a page is constructed (dw::Textblock::addWord), the *generating*
+block tells the positions of floats (or, generally, widgets out of
+flow) via dw::OutOfFlowMgr::tellPosition. This method considers
+already collisions with other floats (only previous floats; floats
+following this float are not considered); after the call,
+dw::OutOfFlowMgr::getBorder will return correct values.
+
+dw::OutOfFlowMgr::tellPosition also checks for overlaps of this float
+with other textblocks, except this textblock (the *generator*, which
+is just constructed, so nothing has to be done). The fact that the
+position of the float is the top, and so the float has only an
+allocation below this position, leads to the effect that only the
+textblocks following the generator are affected. (**Check:** Can the
+search be limited here?) When a page is constructed, no textblocks
+should be following the generating block, so no textblocks are
+affected.
+
+**Todo:** Clarify details of line breaking (\ref dw-line-breaking).
+
+Float changes its size
+----------------------
+The float itself will call queueResize, which will result in a call of
+markSizeChange for the *containing* block, which will then call
+dw::OutOfFlowMgr::markSizeChange. Here, the vloat is only *marked* as
+dirty; the size will be calculated later (in
+dw::OutOfFlowMgr::ensureFloatSize).
+
+This will trigger the resize idle function, so sizeRequest and
+sizeAllocate for all floats and textblocks. In this run,
+dw::OutOfFlowMgr::hasRelationChanged will return *true*, and so result
+in a call of dw::Textblock::borderChanged, and trigger a second run of
+the resize idle function, dealing correctly with the new size.
+
+(This case is handles in a not perfectly optimal way, since two runs
+of the resize idle function are neccessary; but size changes of floats
+is not a very common case.
+
+When a page is constructed (see above), a changing size of a float
+currently constructed typically only affects the most bottom
+textblock; the other textblocks are not covered by this float.)
+
+**Error:** In this case, new collisions are not yet considered.
+
+
+Changing the width of the page
+------------------------------
+
+When the page width is changed, this will result in a reconstruction
+of the page; see *Constructing a page with floats*. Anyway, checking
+for overlaps will play a more important role. This is handled in an
+optimal way by dw::OutOfFlowMgr::hasRelationChanged.
+
+**Check:** Are "cascades" avoided, like this:
+
+1. All textblocks are constructed. A float in textblock 1 overlaps
+ with textblock 2, so dw::Textblock::borderChanged is called for
+ textblock 2.
+2. In another resize idle run, textblock 2 is constructed again. A
+ float in textblock 2 overlaps with textblock 3, so that
+ dw::Textblock::borderChanged is called for textblock 3.
+3. Etc.
+
+*/ \ No newline at end of file
diff --git a/devdoc/dw-out-of-flow-floats.doc b/devdoc/dw-out-of-flow-floats.doc
new file mode 100644
index 00000000..53c6b220
--- /dev/null
+++ b/devdoc/dw-out-of-flow-floats.doc
@@ -0,0 +1,121 @@
+/** \page dw-out-of-flow-floats Handling Elements Out Of Flow: Floats
+
+(Note: Bases on work at <http://flpsed.org/hgweb/dillo_grows>, I plan
+to split the documentation on elements out of flow into different
+parts: general part, floats, positioned elements. In this document,
+informations about floats are collected.)
+
+
+GB lists and CB lists
+=====================
+
+Floats generated by a block which is not yet allocated are initially
+put into a list related to the *generator*:
+
+- dw::OutOfFlowMgr::TBInfo::leftFloatsGB or
+- dw::OutOfFlowMgr::TBInfo::rightFloatsGB.
+
+These lists are also called GB lists.
+
+Floats of allocated generators are put into lists related to the
+*container* (called CB lists):
+
+- dw::OutOfFlowMgr::leftFloatsCB or
+- dw::OutOfFlowMgr::rightFloatsCB.
+
+As soon as the container is allocated, all floats are moved from the
+GB lists to the CB lists (dw::OutOfFlowMgr::sizeAllocateStart →
+dw::OutOfFlowMgr::moveFromGBToCB).
+
+Here, it is important to preserve the *generation order* (for reasons,
+see below: *Sorting floats*), i. e. the order in which floats have
+been added (dw::OutOfFlowMgr::addWidgetOOF). This may become a bit
+more complicated in a case like this:
+
+ <head>
+ <style>
+ \#fl-1, \#fl-2, \#fl-3 { float: right }
+ </style>
+ </head>
+ <body>
+ <div id="bl-1">
+ <div id="fl-1">float 1</div>
+ <div id="bl-2">
+ <div id="fl-2">float 2</div>
+ </div>
+ <div id="fl-3">float 3</div>
+ </div>
+ </body>
+
+The floats are generated in this order:
+
+- \#fl-1 (generated by \#bl-1),
+- \#fl-2 (generated by \#bl-2),
+- \#fl-3 (generated by \#bl-1).
+
+Since the floats must be moved into the CB list in this order, it
+becomes clear that the floats from one GB list cannot be moved at
+once. For this reason, each float is assigned a "mark", which is
+different from the last one as soon as the generator is *before* the
+generator of the float added before. In the example above, there are
+three generators: body, \#bl-1, and \#bl-2 (in this order), and floats
+are assigned these marks:
+
+- \#fl-1: 0,
+- \#fl-2: also 0,
+- \#fl-3 is assigned 1, since its generator (\#bl-1) lies before the
+ last generator (\#bl-2).
+
+dw::OutOfFlowMgr::moveFromGBToCB will then iterate over all marks, so
+that the generation order is preserved.
+
+
+Sorting floats
+==============
+
+Floats are sorted, to make binary search possible, in these lists:
+
+- for each generator: dw::OutOfFlowMgr::TBInfo::leftFloatsGB and
+ dw::OutOfFlowMgr::TBInfo::rightFloatsGB;
+- for the container: dw::OutOfFlowMgr::leftFloatsCB and
+ dw::OutOfFlowMgr::rightFloatsCB.
+
+The other two lists, dw::OutOfFlowMgr::leftFloatsAll and
+dw::OutOfFlowMgr::rightFloatsAll are not sorted at all.
+
+New floats are always added to the end of either list; this order is
+called *generation order*. See also above: *GB lists and CB lists*.
+
+On the other hand, there are different sorting criteria, implemented
+by different comparators, so that different kinds of keys may be used
+for searching. These sorting criteria are equivalent to the generation
+order.
+
+dw::OutOfFlowMgr::Float::CompareSideSpanningIndex compares
+*sideSpanningIndex* (used to compare floats to those on the respective
+other side); if you look at the definition
+(dw::OutOfFlowMgr::addWidgetOOF) it becomes clear that this order is
+equivalent to the generation order.
+
+dw::OutOfFlowMgr::Float::CompareGBAndExtIndex compares *externalIndex*
+for floats with same generators, otherwise: (i) if one generator (T1)
+is a direct anchestor of the other generator (T2), the child of T1,
+which is an anchestor of, or identical to, T2 is compared to the float
+generated by T1, using *externalIndex*, as in this example:
+
+ T1 -+-> child --> ... -> T2 -> Float
+ `-> Float
+
+Otherwise, the two blocks are compared, according to their position in
+dw::OutOfFlowMgr::tbInfos:
+
+ common anchestor -+-> ... --> T1 -> Float
+ `-> ... --> T2 -> Float
+
+This is equivalent to the generation order, as long it is ensured that
+*externalIndex* reflects the generation order within a generating
+block, for both floats and child blocks.
+
+dw::OutOfFlowMgr::Float::ComparePosition ...
+
+*/
diff --git a/devdoc/dw-out-of-flow.doc b/devdoc/dw-out-of-flow.doc
new file mode 100644
index 00000000..eda6994a
--- /dev/null
+++ b/devdoc/dw-out-of-flow.doc
@@ -0,0 +1,252 @@
+/** \page dw-out-of-flow Handling Elements Out Of Flow
+
+<div style="border: 2px solid #ff4040; margin-bottom: 0.5em;
+padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b>
+Not up to date; incorporate these two changes: (i) there are different
+containing blocks for floats and absolutely (furthermore also fixedly)
+positioned elements; (ii) dw::oof::OutOfFlowMgr is now only the base
+class; floats and absolutely positioned elements are seperated:
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10];
+ edge [arrowhead="none", arrowtail="empty", dir="both"];
+ fontname=Helvetica; fontsize=8;
+
+ OutOfFlowMgr [URL="\ref dw::oof::OutOfFlowMgr"; color="#a0a0a0"];
+ OOFFloatsMgr [URL="\ref dw::oof::OOFFloatsMgr"];
+ OOFPositionedMgr [URL="\ref dw::oof::OOFPositionedMgr"; color="#a0a0a0"];
+ OOFPosAbsLikeMgr [URL="\ref dw::oof::OOFPosAbsLikeMgr"; color="#a0a0a0"];
+ OOFPosAbsMgr [URL="\ref dw::oof::OOFPosAbsMgr"];
+ OOFPosFixedMgr [URL="\ref dw::oof::OOFPosFixedMgr"];
+ OOFPosRelMgr [URL="\ref dw::oof::OOFPosRelMgr"];
+
+ OutOfFlowMgr -> OOFFloatsMgr;
+ OutOfFlowMgr -> OOFPositionedMgr;
+ OOFPositionedMgr -> OOFPosAbsLikeMgr;
+ OOFPosAbsLikeMgr -> OOFPosAbsMgr;
+ OOFPosAbsLikeMgr -> OOFPosFixedMgr;
+ OOFPositionedMgr -> OOFPosRelMgr;
+}
+\enddot
+</div>
+
+<div style="border: 2px solid #ffff00; margin: 1em 0;
+padding: 0.5em 1em; background-color: #ffffe0"><b>Info:</b>
+A simplification is ongoing, see \ref dw-size-request-pos.
+</div>
+
+Introduction
+============
+
+This texts deals with both floats and absolute positions, which have
+in common that there is a distinction between generating block and
+containing block (we are here using the same notation as in the
+CSS&nbsp;2 specification). Consider this snippet (regarding floats):
+
+
+ <ul>
+ <li>Some text.</li>
+ <li>
+ <div style="float:right; width=50%">Some longer text, so
+ that the effect described in this passage can be
+ demonstrated.
+ </div>
+ Some more and longer text.</li>
+ <li>Final text. Plus some more to demonstrate how text flows
+ around the float on the right side.</li>
+ </ul>
+
+which may be rendered like this
+
+\image html dw-floats-01.png
+
+The float (the DIV section, yellow in the image) is defined
+("generated") within the list item (blue), so, in CSS 2 terms, the
+list item is the generating block of the float. However, as the image
+shows, the float is not contained by the list item, but another block,
+several levels above (not shown here). In terms of ::dw, this means
+that the dw::Textblock representing the float cannot be a child of the
+dw::Textblock representing the generating block, the list item, since
+the allocation of a child widget must be within the allocation of the
+parent widget. Instead, to each dw::Textblock, another dw::Textblock
+is assigned as the containing box.
+
+(Notice also that other text blocks must regard floats to calculate
+their borders, and so their size. In this example, the following list
+item (green) must consider the position of the float. This is
+discussed in detail in the next section.)
+
+Both in this text and the code, generating and containing block are
+abbreviated with **GB** and **CB**, respectively.
+
+
+Implementation overview
+=======================
+
+Widget level
+------------
+The terms *generating block* and *containing block* have been raised
+to a higher level, the one of dw::core::Widget, and are here called
+*generating widget* and *containing widget*. To represent the
+distinction, the type of dw::core::Content has been split into three
+parts:
+
+- If a widget is out of flow, the generating widget keeps a reference
+ with the type dw::core::Content::WIDGET_OOF_REF, while the
+ containing block refers to it as dw::core::Content::WIDGET_OOF_CONT.
+- For widgets within flow, dw::core::Content::WIDGET_IN_FLOW is used.
+
+Notice that in the first case, there are two pieces of content
+referring to the same widget.
+
+An application of this distinction is iterators. [TODO: more. And
+still missing: DeepIterator may need the generating parent widget in
+some cases.]
+
+
+Textblock level
+---------------
+Both dw::Textblock::notifySetAsTopLevel and
+dw::Textblock::notifySetParent set the member
+dw::Textblock::containingBlock appropriately, (according to rules
+which should be defined in this document).
+
+Handling widgets out of flow is partly the task of the new class
+dw::oof::OutOfFlowMgr, which is stored by dw::Textblock::outOfFlowMgr,
+but only for containing blocks. Generating blocks should refer to
+*containingBlock->outOfFlowMgr*. (Perhaps dw::oof::OutOfFlowMgr may
+become independent of dw::Textblock.)
+
+dw::Textblock::addWidget is extended, so that floats and absolutely
+positioned elements can be added. Notice that not *this* widget, but
+the containing block becomes the parent of the newly added child, if
+it is out of flow. dw::Textblock::addWidget decides this by calling
+dw::oof::OutOfFlowMgr::isOutOfFlow. (See new content types above.)
+
+dw::core::Widget::parentRef has become a new representation. Before,
+it represented the line numer. Now (least signifant bit left):
+
+ +---+ - - - +---+---+- - - - - -+---+---+---+---+
+ | line number | 0 |
+ +---+ - - - +---+---+- - - - - -+---+---+---+---+
+
+ +---+ - - - +---+---+- - - - - -+---+---+---+---+
+ | left float index | 0 | 0 | 1 |
+ +---+ - - - +---+---+- - - - - -+---+---+---+---+
+
+ +---+ - - - +---+---+- - - - - -+---+---+---+---+
+ | right float index | 1 | 0 | 1 |
+ +---+ - - - +---+---+- - - - - -+---+---+---+---+
+
+ +---+ - - - +---+---+- - - - - -+---+---+---+---+
+ | absolutely positioned index | 1 | 1 |
+ +---+ - - - +---+---+- - - - - -+---+---+---+---+
+
+Details are hidden by static inline methods of dw::oof::OutOfFlowMgr.
+
+
+The sizeRequest/sizeAllocate problem
+====================================
+
+*See also:* \ref dw-widget-sizes, especially the section *Rules for
+Methods Related to Resizing*.
+
+The size/position model of ::dw consists mainly of the following two
+steps:
+
+1. First, the size of the toplevel widget is calculated. Size
+ calculation typically depends on the sizes of the widgets, which
+ are calculated recursively, but not more.
+2. After this, the toplevel widget is allocated at position (0, 0),
+ with the previosly calculated size. Each widget must allocate its
+ children; here, the condition for the toplevel widget (allocated
+ size equals requested size) is not necessary; instead, each widget
+ may be allocated at every size.
+
+Especially for floats, this model becomes a bit difficult, for reasons
+described below. For the solutions, much is centralized at the level
+of the containing block, which delegates most to an instance of
+dw::oof::OutOfFlowMgr (details below).
+
+**The size of a widget depends on the size not only of the children.**
+In the example above, the last list item (green, following the
+generating list item) must know the size of the the float (which is
+not a child or, generally, descendant) to determine the borders, which
+is done in dw::Textblock::sizeRequestImpl.
+
+For this, the size model has been extended (see \ref dw-widget-sizes,
+section *Rules for Methods Related to Resizing*): *sizeRequest* can be
+called within *sizeRequestImpl* for other widgets that children (with
+some caution). Namely, dw::Textblock::sizeRequestImpl calls
+dw::core::Widget::sizeRequest for the float, via
+dw::oof::OutOfFlowMgr::getBorder and
+dw::oof::OutOfFlowMgr::ensureFloatSize.
+
+**The size of a widget depends on the allocation of another widget.**
+In the example above, both list items (blue and green) must know the
+position of the float widget, within dw::Textblock::sizeRequestImpl,
+to calculate the borders. The position, however, is stored in the
+allocation, which is typically calculated later.
+
+Here, two cases must be distinguished. The position of a float is
+always **relative to its generating block**, so for calculating the
+borders for the generating block, the allocation needs not to be
+know. For other textblocks, it needs to be known, so the calculation
+of the borders will ignore floats generated by other textblocks, until
+all widgets are allocated. The latter will call (when neccessary)
+dw::core::Widget::queueResize, so that all border calculations are
+repeated. See below (*hasRelationChanged*) for details.
+
+Generally, this pattern (distinguishing between GB and CB) can be
+found everywhere in dw::oof::OutOfFlowMgr.
+
+For details see:
+
+- dw::oof::OutOfFlowMgr::getLeftBorder,
+ dw::oof::OutOfFlowMgr::getRightBorder,
+ dw::oof::OutOfFlowMgr::getBorder (called by the first two), and
+ especially, dw::oof::OutOfFlowMgr::getFloatsListForTextblock (called
+ by the latter), where these three cases are distinguished;
+- dw::oof::OutOfFlowMgr::sizeAllocateStart,
+ dw::oof::OutOfFlowMgr::sizeAllocateEnd which are called by the
+ containing block.
+
+(This could be solved in a more simple, elegant way, when
+*sizeRequest* would depend on the position. This is, however, only a
+vague idea, perhaps not even feasible, and for which there are no
+concrete plans, certainly not in \ref dw-grows.)
+
+
+Implementation details
+======================
+
+- CB and GB lists (general pattern) (see previous section)
+- binary search; different search criteria, how they accord
+- lastLeftTBIndex, lastRightTBIndex etc.
+- limitiation of search; extIndex etc.
+
+
+How *hasRelationChanged* works
+==============================
+
+...
+
+
+Integration of line breaking and floats
+=======================================
+
+(Positioning of floats, loop, recent works.)
+
+
+Absolute and fixed positiones
+=============================
+
+To be documented.
+
+
+See also
+========
+
+→ \ref dw-miscellaneous.
+
+*/
diff --git a/devdoc/dw-overview.doc b/devdoc/dw-overview.doc
new file mode 100644
index 00000000..0c4ffb53
--- /dev/null
+++ b/devdoc/dw-overview.doc
@@ -0,0 +1,158 @@
+/** \page dw-overview Dillo Widget Overview
+
+Note: If you are already familiar with the Gtk+-based version of Dw,
+read \ref dw-changes.
+
+
+The module Dw (Dillo Widget) is responsible for the low-level rendering of
+all resources, e.g. images, plain text, and HTML pages (this is the
+most complex type). Dw is \em not responsible for parsing HTML, or
+decoding image data. Furthermore, the document tree, which is planned
+for CSS, is neither a part of Dw, instead, it is a new module on top
+of Dw.
+
+The rendering, as done by Dw, is split into two phases:
+
+<ul>
+<li> the \em layouting, this means calculating the exact positions of
+ words, lines, etc. (in pixel position), and
+<li> the \em drawing, i.e. making the result of the layouting visible
+ on the screen.
+</ul>
+
+The result of the layouting allocates an area, which is called
+\em canvas.
+
+<h2>Structure</h2>
+
+The whole Dw module can be split into the following parts:
+
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10];
+ edge [arrowhead="open", fontname=Helvetica, fontsize=10,
+ labelfontname=Helvetica, labelfontsize=10,
+ color="#404040", labelfontcolor="#000080"];
+
+ subgraph cluster_core {
+ style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ label="Platform independent core";
+
+ Layout [URL="\ref dw::core::Layout"];
+ Platform [URL="\ref dw::core::Platform", color="#ff8080"];
+ View [URL="\ref dw::core::View", color="#ff8080"];
+ Widget [URL="\ref dw::core::Widget", color="#a0a0a0"];
+ }
+
+ subgraph cluster_fltk {
+ style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ label="FLTK specific part (as an\nexample for the platform specific\n\
+implementations)";
+
+ subgraph cluster_fltkcore {
+ style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ label="FLTK core";
+
+ FltkPlatform [URL="\ref dw::fltk::FltkPlatform"];
+ FltkView [URL="\ref dw::fltk::FltkView", color="#ff8080"];
+ }
+
+ FltkViewport [URL="\ref dw::fltk::FltkViewport"];
+ FltkPreview [URL="\ref dw::fltk::FltkPreview"];
+ }
+
+ subgraph cluster_widgets {
+ style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ label="Platform independent widgets";
+
+ Textblock [URL="\ref dw::Textblock"];
+ AlignedTextblock [URL="\ref dw::AlignedTextblock", color="#a0a0a0"];
+ Table [URL="\ref dw::Table"];
+ Image [URL="\ref dw::Image"];
+ etc1 [label="..."];
+ etc2 [label="..."];
+ }
+
+ Layout -> Platform [headlabel="1", taillabel="1"];
+ Layout -> View [headlabel="*", taillabel="1"];
+
+ Layout -> Widget [headlabel="1", taillabel="1", label="topLevel"];
+ Widget -> Widget [headlabel="*", taillabel="1", label="children"];
+
+ Widget -> Textblock [arrowhead="none", arrowtail="empty", dir="both"];
+ Widget -> Table [arrowhead="none", arrowtail="empty", dir="both"];
+ Widget -> Image [arrowhead="none", arrowtail="empty", dir="both"];
+ Widget -> etc1 [arrowhead="none", arrowtail="empty", dir="both"];
+ Textblock -> AlignedTextblock [arrowhead="none", arrowtail="empty",
+ dir="both"];
+ AlignedTextblock -> etc2 [arrowhead="none", arrowtail="empty", dir="both"];
+
+ Platform -> FltkPlatform [arrowhead="none", arrowtail="empty", dir="both",
+ style="dashed"];
+ FltkPlatform -> FltkView [headlabel="*", taillabel="1"];
+
+ View -> FltkView [arrowhead="none", arrowtail="empty", dir="both"];
+ FltkView -> FltkViewport [arrowhead="none", arrowtail="empty", dir="both",
+ style="dashed"];
+ FltkView -> FltkPreview [arrowhead="none", arrowtail="empty", dir="both",
+ style="dashed"];
+}
+\enddot
+
+<center>[\ref uml-legend "legend"]</center>
+
+\em Platform means in most cases the underlying UI toolkit
+(e.g. FLTK). A layout is bound to a specific platform, but multiple
+platforms may be handled in one program.
+
+A short overview:
+
+<ul>
+<li> dw::core::Layout is the central class, it manages the widgets and the
+ view, and provides delegation methods for the platform.
+
+<li> The layouting is done by a tree of widgets (details are described in
+ \ref dw-layout-widgets), also the drawing, which is finally delegated
+ to the view.
+
+<li> The view (implementation of dw::core::View) provides primitive methods
+ for drawing, but also have an influence on
+ the canvas size (via size hints). See \ref dw-layout-views for details.
+
+<li> Some platform dependencies are handled by implementations
+ of dw::core::Platform.
+</ul>
+
+
+<h3>Header Files</h3>
+
+The structures mentioned above can be found in the following header
+files:
+
+<ul>
+<li> Anything from the Dw core in core.hh. Do not include the single files.
+
+<li> The single widgets can be found in the respective header files, e.g.
+ image.hh for dw::Image.
+
+<li> The core of the FLTK implementation is defined in fltkcore.hh. This
+ includes dw::fltk::FltkPlatform, dw::fltk::FltkView, but not the concrete
+ view implementations.
+
+<li> The views can be found in single header files, e.g fltkviewport.hh for
+ dw::fltk::FltkViewport.
+</ul>
+
+
+<h2>Further Documentations</h2>
+
+A complete map can be found at \ref dw-map.
+
+<ul>
+<li> For learning, how to use Dw, read \ref dw-usage and related documents,
+ dw::core::style, dw::core::ui and \ref dw-images-and-backgrounds.
+<li> Advanced topics are described in \ref dw-layout-widgets,
+ \ref dw-widget-sizes and \ref dw-layout-views.
+</ul>
+
+*/
diff --git a/devdoc/dw-size-of-widget.png b/devdoc/dw-size-of-widget.png
new file mode 100644
index 00000000..dbdbe0c4
--- /dev/null
+++ b/devdoc/dw-size-of-widget.png
Binary files differ
diff --git a/devdoc/dw-style-box-model.png b/devdoc/dw-style-box-model.png
new file mode 100644
index 00000000..bf2fb1f1
--- /dev/null
+++ b/devdoc/dw-style-box-model.png
Binary files differ
diff --git a/devdoc/dw-style-length-absolute.png b/devdoc/dw-style-length-absolute.png
new file mode 100644
index 00000000..9ea28cad
--- /dev/null
+++ b/devdoc/dw-style-length-absolute.png
Binary files differ
diff --git a/devdoc/dw-style-length-percentage.png b/devdoc/dw-style-length-percentage.png
new file mode 100644
index 00000000..b1ad79c9
--- /dev/null
+++ b/devdoc/dw-style-length-percentage.png
Binary files differ
diff --git a/devdoc/dw-style-length-relative.png b/devdoc/dw-style-length-relative.png
new file mode 100644
index 00000000..ee79b1a9
--- /dev/null
+++ b/devdoc/dw-style-length-relative.png
Binary files differ
diff --git a/devdoc/dw-textblock-collapsing-spaces-1-1.png b/devdoc/dw-textblock-collapsing-spaces-1-1.png
new file mode 100644
index 00000000..d528dfb2
--- /dev/null
+++ b/devdoc/dw-textblock-collapsing-spaces-1-1.png
Binary files differ
diff --git a/devdoc/dw-textblock-collapsing-spaces-1-2.png b/devdoc/dw-textblock-collapsing-spaces-1-2.png
new file mode 100644
index 00000000..483e79d1
--- /dev/null
+++ b/devdoc/dw-textblock-collapsing-spaces-1-2.png
Binary files differ
diff --git a/devdoc/dw-textblock-collapsing-spaces-2-1.png b/devdoc/dw-textblock-collapsing-spaces-2-1.png
new file mode 100644
index 00000000..0a03ea80
--- /dev/null
+++ b/devdoc/dw-textblock-collapsing-spaces-2-1.png
Binary files differ
diff --git a/devdoc/dw-textblock-collapsing-spaces-2-2.png b/devdoc/dw-textblock-collapsing-spaces-2-2.png
new file mode 100644
index 00000000..b89c6254
--- /dev/null
+++ b/devdoc/dw-textblock-collapsing-spaces-2-2.png
Binary files differ
diff --git a/devdoc/dw-usage.doc b/devdoc/dw-usage.doc
new file mode 100644
index 00000000..a23920b8
--- /dev/null
+++ b/devdoc/dw-usage.doc
@@ -0,0 +1,375 @@
+/** \page dw-usage Dillo Widget Usage
+
+This document describes the usage of Dw, without going too much into
+detail.
+
+
+<h2>Getting Started</h2>
+
+In this section, a small runnable example is described, based on the
+FLTK implementation.
+
+As described in \ref dw-overview, the following objects are needed:
+
+<ul>
+<li> dw::core::Layout,
+<li> an implementation of dw::core::Platform (we will use
+ dw::fltk::FltkPlatform),
+<li> at least one implementation of dw::core::View (dw::fltk::FltkViewport),
+ and
+<li> some widgets (for this example, only a simple dw::Textblock).
+</ul>
+
+First of all, the necessary \#include's:
+
+\code
+#include <FL/Fl_Window.H>
+#include <FL/Fl.H>
+
+#include "dw/core.hh"
+#include "dw/fltkcore.hh"
+#include "dw/fltkviewport.hh"
+#include "dw/textblock.hh"
+\endcode
+
+Everything is put into one function:
+
+\code
+int main(int argc, char **argv)
+{
+\endcode
+
+As the first object, the platform is instantiated:
+
+\code
+ dw::fltk::FltkPlatform *platform = new dw::fltk::FltkPlatform ();
+\endcode
+
+Then, the layout is created, with the platform attached:
+
+\code
+ dw::core::Layout *layout = new dw::core::Layout (platform);
+\endcode
+
+For the view, we first need a FLTK window:
+
+\code
+ Fl_Window *window = new Fl_Window(200, 300, "Dw Example");
+ window->begin();
+\endcode
+
+After this, we can create a viewport, and attach it to the layout:
+
+\code
+ dw::fltk::FltkViewport *viewport =
+ new dw::fltk::FltkViewport (0, 0, 200, 300);
+ layout->attachView (viewport);
+\endcode
+
+Each widget needs a style (dw::core::style::Style, see dw::core::style),
+so we construct it here. For this, we need to fill a
+dw::core::style::StyleAttrs structure with values, and call
+dw::core::style::Style::create (latter is done further below):
+
+\code
+ dw::core::style::StyleAttrs styleAttrs;
+ styleAttrs.initValues ();
+ styleAttrs.margin.setVal (5);
+\endcode
+
+dw::core::style::StyleAttrs::initValues sets several default
+values. The last line sets a margin of 5 pixels. Next, we need a
+font. Fonts are created in a similar way, first, the attributes are
+defined:
+
+\code
+ dw::core::style::FontAttrs fontAttrs;
+ fontAttrs.name = "Bitstream Charter";
+ fontAttrs.size = 14;
+ fontAttrs.weight = 400;
+ fontAttrs.style = dw::core::style::FONT_STYLE_NORMAL;
+ fontAttrs.letterSpacing = 0;
+ fontAttrs.fontVariant = dw::core::style::FONT_VARIANT_NORMAL;
+\endcode
+
+Now, the font can be created:
+
+\code
+ styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs);
+\endcode
+
+As the last attributes, the background and forground colors are
+defined, here dw::core::style::Color::createSimple must be called:
+
+\code
+ styleAttrs.color =
+ dw::core::style::Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor =
+ dw::core::style::Color::create (layout, 0xffffff);
+\endcode
+
+Finally, the style for the widget is created:
+
+\code
+ dw::core::style::Style *widgetStyle =
+ dw::core::style::Style::create (layout, &styleAttrs);
+\endcode
+
+Now, we create a widget, assign a style to it, and set it as the
+toplevel widget of the layout:
+
+\code
+ dw::Textblock *textblock = new dw::Textblock (false);
+ textblock->setStyle (widgetStyle);
+ layout->setWidget (textblock);
+\endcode
+
+The style is not needed anymore (a reference is added in
+dw::core::Widget::setStyle), so it should be unreferred:
+
+\code
+ widgetStyle->unref();
+\endcode
+
+Now, some text should be added to the textblock. For this, we first
+need another style. \em styleAttrs can still be used for this. We set
+the margin to 0, and the background color to "transparent":
+
+\code
+ styleAttrs.margin.setVal (0);
+ styleAttrs.backgroundColor = NULL;
+
+ dw::core::style::Style *wordStyle =
+ dw::core::style::Style::create (layout, &styleAttrs);
+\endcode
+
+This loop adds some paragraphs:
+
+\code
+ for(int i = 1; i <= 10; i++) {
+ char buf[4];
+ sprintf(buf, "%d.", i);
+
+ char *words[] = { "This", "is", "the", buf, "paragraph.",
+ "Here", "comes", "some", "more", "text",
+ "to", "demonstrate", "word", "wrapping.",
+ NULL };
+
+ for(int j = 0; words[j]; j++) {
+ textblock->addText(strdup(words[j]), wordStyle);
+\endcode
+
+Notice the \em strdup, dw::Textblock::addText will feel responsible
+for the string, and free the text at the end. (This has been done to
+avoid some overhead in the HTML parser.)
+
+The rest is simple, it also includes spaces (which also have styles):
+
+\code
+ textblock->addSpace(wordStyle);
+ }
+\endcode
+
+Finally, a paragraph break is added, which is 10 pixels high:
+
+\code
+ textblock->addParbreak(10, wordStyle);
+ }
+\endcode
+
+Again, this style should be unreferred:
+
+\code
+ wordStyle->unref();
+\endcode
+
+After adding text, this method should always be called (for faster
+adding large text blocks):
+
+\code
+ textblock->flush ();
+\endcode
+
+Some FLTK stuff to finally show the window:
+
+\code
+ window->resizable(viewport);
+ window->show();
+ int errorCode = Fl::run();
+\endcode
+
+For cleaning up, it is sufficient to destroy the layout:
+
+\code
+ delete layout;
+\endcode
+
+And the rest
+
+\code
+ return errorCode;
+}
+\endcode
+
+If you compile and start the program, you should see the following:
+
+\image html dw-example-screenshot.png
+
+Try to scroll, or to resize the window, you will see, that everything
+is done automatically.
+
+Of course, creating new widgets, adding text to widgets etc. can also
+be done while the program is running, i.e. after fltk::run has been
+called, within timeouts, idles, I/O functions etc. Notice that Dw is
+not thread safe, so that everything should be done within one thread.
+
+With the exception, that you have to call dw::Textblock::flush,
+everything gets immediately visible, within reasonable times; Dw has
+been optimized for frequent updates.
+
+
+<h2>List of all Widgets</h2>
+
+These widgets are used within dillo:
+
+<ul>
+<li>dw::core::ui::Embed
+<li>dw::AlignedTextblock
+<li>dw::Bullet
+<li>dw::Ruler
+<li>dw::Image
+<li>dw::ListItem
+<li>dw::Table
+<li>dw::TableCell
+<li>dw::Textblock
+</ul>
+
+If you want to create a new widget, refer to \ref dw-layout-widgets.
+
+
+<h2>List of Views</h2>
+
+There are three dw::core::View implementations for FLTK:
+
+<ul>
+<li> dw::fltk::FltkViewport implements a viewport, which is used in the
+ example above.
+
+<li> dw::fltk::FltkPreview implements a preview window, together with
+ dw::fltk::FltkPreviewButton, it is possible to have a scaled down
+ overview of the whole canvas.
+
+<li> dw::fltk::FltkFlatView is a "flat" view, i.e. it does not support
+ scrolling. It is used for HTML buttons, see
+ dw::fltk::ui::FltkComplexButtonResource and especially
+ dw::fltk::ui::FltkComplexButtonResource::createNewWidget for details.
+</ul>
+
+More informations about views in general can be found in \ref
+dw-layout-views.
+
+
+<h2>Iterators</h2>
+
+For examining generally the contents of widgets, there are iterators
+(dw::core::Iterator), created by the method
+dw::core::Widget::iterator (see there for more details).
+
+These simple iterators only iterate through one widget, and return
+child widgets as dw::core::Content::WIDGET. The next call of
+dw::core::Iterator::next will return the piece of contents \em after
+(not within) this child widget.
+
+If you want to iterate through the whole widget trees, there are two
+possibilities:
+
+<ol>
+<li> Use a recursive function. Of course, with this approach, you are
+ limited by the program flow.
+
+<li> Maintain a stack of iterators, so you can freely pass this stack
+ around. This is already implemented, as dw::core::DeepIterator.
+</ol>
+
+As an example, dw::core::SelectionState represents the selected region
+as two instances of dw::core::DeepIterator.
+
+
+<h2>Finding Text</h2>
+
+See dw::core::Layout::findtextState and dw::core::FindtextState
+(details in the latter). There are delegation methods:
+
+<ul>
+<li> dw::core::Layout::search and
+<li> dw::core::Layout::resetSearch.
+</ul>
+
+
+<h2>Anchors and Scrolling</h2>
+
+In some cases, it is necessary to scroll to a given position, or to
+an anchor, programmatically.
+
+<h3>Anchors</h3>
+
+Anchors are defined by widgets, e.g. dw::Textblock defines them, when
+dw::Textblock::addAnchor is called. To jump to a specific anchor
+within the current widget tree, use dw::core::Layout::setAnchor.
+
+This can be done immediately after assignig a toplevel widget, even
+when the anchor has not yet been defined. The layout will remember the
+anchor, and jump to the respective position, as soon as possible. Even
+if the anchor position changes (e.g., when an anchor is moved
+downwards, since some space is needed for an image in the text above),
+the position is corrected.
+
+As soon as the user scrolls the viewport, this correction is not done
+anymore. If in dillo, the user request a page with an anchor, which is
+quite at the bottom of the page, he may be get interested in the text
+at the beginning of the page, and so scrolling down. If then, after
+the anchor has been read and added to the dw::Textblock, this anchor
+would be jumped at, the user would become confused.
+
+The anchor is dismissed, too, when the toplevel widget is removed
+again.
+
+\todo Currently, anchors only define vertical positions.
+
+<h3>Scrolling</h3>
+
+To scroll to a given position, use the method
+dw::core::Layout::scrollTo. It expects several parameters:
+
+<ul>
+<li>a horizontal adjustment parameter, defined by dw::core::HPosition,
+<li>a vertical adjustment parameter, defined by dw::core::VPosition, and
+<li>a rectangle (\em x, \em y, \em width and \em heigh) of the region
+ to be adjusted.
+</ul>
+
+If you just want to move the canvas coordinate (\em x, \em y) into the
+upper left corner of the viewport, you can call:
+
+\code
+dw::core::Layout *layout;
+// ...
+layout->scrollTo(dw::core::HPOS_LEFT, dw::core::VPOS_TOP, 0, 0, 0, 0);
+\endcode
+
+By using dw::core::HPOS_NO_CHANGE or dw::core::VPOS_NO_CHANGE, you can
+change only one dimension. dw::core::HPOS_INTO_VIEW and
+dw::core::VPOS_INTO_VIEW will cause the viewport to move as much as
+necessary, that the region is visible in the viewport (this is
+e.g. used for finding text).
+
+
+<h2>Further Documentations</h2>
+
+<ul>
+<li> dw::core::style
+<li> dw::core::ui
+<li> \ref dw-images-and-backgrounds
+</ul>
+
+*/
diff --git a/devdoc/dw-viewport-with-scrollbar.png b/devdoc/dw-viewport-with-scrollbar.png
new file mode 100644
index 00000000..7ac62de3
--- /dev/null
+++ b/devdoc/dw-viewport-with-scrollbar.png
Binary files differ
diff --git a/devdoc/dw-viewport-without-scrollbar.png b/devdoc/dw-viewport-without-scrollbar.png
new file mode 100644
index 00000000..8aa20fec
--- /dev/null
+++ b/devdoc/dw-viewport-without-scrollbar.png
Binary files differ
diff --git a/devdoc/dw-widget-sizes.doc b/devdoc/dw-widget-sizes.doc
new file mode 100644
index 00000000..ffc7fb5d
--- /dev/null
+++ b/devdoc/dw-widget-sizes.doc
@@ -0,0 +1,277 @@
+/** \page dw-widget-sizes Sizes of Dillo Widgets
+
+<div style="border: 2px solid #ffff00; margin: 1em 0;
+ padding: 0.5em 1em; background-color: #ffffe0">The complex "widget
+ sizes" is currently divided into three documents: **Sizes of Dillo
+ Widgets** (this document), \ref dw-grows, and \ref
+ dw-size-request-pos. </div>
+
+<div style="border: 2px solid #ff4040; margin: 1em 0;
+ padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b>
+ Not up to date, see other documents.</div>
+
+Allocation
+==========
+
+Each widget has an \em allocation at a given time, this includes
+
+- the position (\em x, \em y) relative to the upper left corner of the
+ canvas, and
+- the size (\em width, \em ascent, \em descent).
+
+The \em canvas is the whole area available for the widgets, in most
+cases, only a part is seen in a viewport. The allocation of the
+toplevel widget is exactly the allocation of the canvas, i.e.
+
+- the position of the toplevel widget is always (0, 0), and
+- the canvas size is defined by the size of the toplevel widget.
+
+The size of a widget is not simply defined by the width and the
+height, instead, widgets may have a base line, and so are vertically
+divided into an ascender (which height is called \em ascent), and a
+descender (which height is called \em descent). The total height is so
+the sum of \em ascent and \em descent.
+
+Sizes of zero are allowed. The upper limit for the size of a widget is
+defined by the limits of the C++ type \em int.
+
+\image html dw-size-of-widget.png Allocation of a Widget
+
+In the example in the image, the widget has the following allocation:
+
+- \em x = 50
+- \em y = 50
+- \em width = 150
+- \em ascent = 150
+- \em descent = 100
+
+The current allocation of a widget is hold in
+dw::core::Widget::allocation. It can be set from outside by
+calling dw::core::Widget::sizeAllocate. This is a concrete method,
+which will call dw::core::Widget::sizeAllocateImpl (see code of
+dw::core::Widget::sizeAllocate for details).
+
+For trivial widgets (like dw::Bullet),
+dw::core::Widget::sizeAllocateImpl does not need to be
+implemented. For more complex widgets, the implementation should call
+dw::core::Widget::sizeAllocate (not
+dw::core::Widget::sizeAllocateImpl) on all child widgets, with
+appropriate child allocations. dw::core::Widget::allocation should not
+be changed here, this is already done in
+dw::core::Widget::sizeAllocate.
+
+
+Requisitions
+============
+
+A widget may prefer a given size for the allocation. This size, the
+\em requisition, should be returned by the method
+dw::core::Widget::sizeRequestImpl. In the simplest case, this is
+independent of the context, e.g. for an
+image. dw::Image::sizeRequestImpl returns the following size:
+
+- If no buffer has yet been assigned (see dw::Image for more details),
+ the size necessary for the alternative text is returned. If no
+ alternative text has been set, zero is returned.
+
+- If a buffer has been assigned (by dw::Image::setBuffer), the root
+ size is returned (i.e. the original size of the image to display).
+
+This is a bit simplified, dw::Image::sizeRequestImpl should also deal
+with margins, borders and paddings, see dw::core::style.
+
+From the outside, dw::Image::sizeRequest should be called, which does
+a bit of optimization. Notice that in dw::Image::sizeRequestImpl, no
+optimization like lazy evaluation is necessary, this is already done
+in dw::Image::sizeRequest.
+
+A widget, which has children, will likely call dw::Image::sizeRequest
+on its children, to calculate the total requisition.
+
+The caller (this is either the dw::core::Layout, or the parent
+widget), may, but also may not consider the requisition. Instead, a
+widget must deal with any allocation. (For example, dw::Image scales
+the image buffer when allocated at another size.)
+
+
+Size Hints
+==========
+
+<div style="border: 2px solid #ff4040; margin-bottom: 0.5em;
+padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b>
+Size hints have been removed, see \ref dw-grows.</div>
+
+
+Width Extremes
+==============
+
+dw::Table uses width extremes for fast calculation of column
+widths. The structure dw::core::Extremes represents the minimal and
+maximal width of a widget, as defined by:
+
+- the minimal width is the smallest width, at which a widget can still
+ display contents, and
+- the maximal width is the largest width, above which increasing the
+ width- does not make any sense.
+
+Especially the latter is vaguely defined, here are some examples:
+
+- For those widgets, which do not depend on size hints, the minimal
+ and the maximal width is the inherent width (the one returned by
+ dw::core::Widget::sizeRequest).
+
+- For a textblock, the minimal width is the width of the widest
+ (unbreakable) word, the maximal width is the width of the total
+ paragraph (stretching a paragraph further would only waste space).
+ Actually, the implementation of dw::Textblock::getExtremesImpl is a
+ bit more complex.
+
+- dw::Table is an example, where the width extremes are calculated
+ from the width extremes of the children.
+
+Handling width extremes is similar to handling requisitions, a widget
+must implement dw::core::Widget::getExtremesImpl, but a caller will
+use dw::core::Widget::getExtremes.
+
+
+Resizing
+========
+
+When the widget changes its size (requisition), it should call
+dw::core::Widget::queueResize. The next call of
+dw::core::Widget::sizeRequestImpl should then return the new
+size. See dw::Image::setBuffer as an example.
+
+Interna are described in the code of dw::core::Widget::queueResize.
+
+<h3>Incremental Resizing</h3>
+
+A widget may calculate its size based on size calculations already
+done before. In this case, a widget must exactly know the reasons, why
+a call of dw::core::Widget::sizeRequestImpl is necessary. To make use
+of this, a widget must implement the following:
+
+1. There is a member dw::core::Widget::parentRef, which is totally
+ under control of the parent widget (and so sometimes not used at
+ all). It is necessary to define how parentRef is used by a specific
+ parent widget, and it has to be set to the correct value whenever
+ necessary.
+2. The widget must implement dw::core::Widget::markSizeChange and
+ dw::core::Widget::markExtremesChange, these methods are called in
+ two cases:
+ 1. directly after dw::core::Widget::queueResize, with the
+ argument ref was passed to dw::core::Widget::queueResize,
+ and
+ 2. if a child widget has called dw::core::Widget::queueResize,
+ with the value of the parent_ref member of this child.
+
+This way, a widget can exactly keep track on size changes, and so
+implement resizing in a faster way. A good example on how to use this
+is dw::Textblock.
+
+
+Rules for Methods Related to Resizing
+=====================================
+
+Which method can be called, when the call of another method is not
+finished? These rules are important in two circumstances:
+
+1. To know which method can be called, and, especially, which methods
+ *must not* be called, within the implementation of
+ *sizeRequestImpl* (called by *sizeRequest*), *markSizeChange*, and
+ *markExtremesChange* (the latter two are called by *queueResize*).
+2. On the other hand, to make sure that the calls, which are allowed,
+ are handled correctly, especially in implementations of
+ *sizeRequestImpl*, *markSizeChange*, *markExtremesChange*
+
+Generally, the rules defined below are, in case of doubt, rather
+strict; when changing the rules, loosening is simpler than to tighten
+them, since this will make it neccessary to review old code for calls
+previously allowed but now forbidden.
+
+Short recap:
+
+- *QueueResize* directly calls *markSizeChange* and
+ *markExtremesChanges*, and queues an idle function for the actual
+ resizing (dw::core::Layout::resizeIdle). (The idle function is
+ called some time after *queueResize* is finished.)
+- The resize idle function first calls *sizeRequest*, then
+ *sizeAllocate*, for the toplevel widget.
+
+In the following table, the rules are defined in detail. "Within call
+of ..." includes all methods called from the original method: the
+first row (*queueResize*) defines also the rules for
+*markExtremesChanges* and *markExtremesChanges*, and in the second row
+(*sizeAllocate*), even *sizeRequest* has to be considered.
+
+<div style="border: 2px solid #ff4040; margin-bottom: 0.5em;
+padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b>
+Not up to date: *queueResize* can now be called recursively (so to
+speak). See code there.</div>
+
+<table>
+ <tr>
+ <th>Within call of ... ↓
+ <th>... is call allowed of ... ? →
+ <th>queueResize
+ <th>sizeAllocate
+ <th>sizeRequest
+ <th>getExtremes
+ <tr>
+ <th colspan=2>queueResize
+ <td>No
+ <td>No<sup>1</sup>
+ <td>No<sup>1</sup>
+ <td>No<sup>1</sup>
+ <tr>
+ <th colspan=2>sizeAllocate
+ <td>Yes
+ <td>Only for children<sup>2</sup>
+ <td>Yes(?)
+ <td>Yes(?)
+ <tr>
+ <th colspan=2>sizeRequest
+ <td>Yes<sup>3</sup>
+ <td>No
+ <td>Limited<sup>4</sup>
+ <td>Limited<sup>4</sup>
+ <tr>
+ <th colspan=2>getExtremes
+ <td>Yes<sup>3</sup>
+ <td>No
+ <td>Limited<sup>4</sup>
+ <td>Limited<sup>4</sup>
+ <tr>
+ <td colspan=6><sup>1</sup>) Otherwise, since these other methods
+may be call *queueResize*, the limitation that *queueResize* must not
+call *queueResize* can be violated.
+
+<sup>2</sup>) Could perhaps be loosened as for *sizeRequest* and
+*getExtremes*, but there is probably no need.
+
+<sup>3</sup>) Therefore the distinction between *RESIZE_QUEUED* and
+*NEEDS_RESIZE*, and *EXTREMES_QUEUED* and *EXTREMES_CHANGED*,
+respectively.
+
+<sup>4</sup>) Calls only for children are safe. In other cases, you
+take a large responsibility to prevent endless recursions by
+(typically indirectly) calling *sizeRequest* / *getExtremes* for
+direct ancestors.
+</table>
+
+Furthermore, *sizeAllocate* can only be called within a call of
+dw::core::Layout::resizeIdleId, so (if you do not touch dw::core) do
+not call it outside of *sizeAllocateImpl*. The other methods can be
+called outsize; e.&nbsp;g. *sizeRequest* is called in
+dw::Textblock::addWidget.
+
+To avoid painful debugging, there are some tests for the cases that
+one method call is strictly forbidden while another method is called.
+
+This could be done furthermore:
+
+- The tests could be refined.
+- Is it possible to define exacter rules, along with a proof that no
+ problems (like endless recursion) can occur?
+
+*/
diff --git a/devdoc/fltk-problems.doc b/devdoc/fltk-problems.doc
new file mode 100644
index 00000000..df4f1f14
--- /dev/null
+++ b/devdoc/fltk-problems.doc
@@ -0,0 +1,180 @@
+/** \page fltk-problems Problems with FLTK
+
+<h2>dw::fltk::FltkViewport</h2>
+
+Current problems:
+
+<ul>
+<li> How should dw::fltk::FltkViewport::cancelQueueDraw be implemented?
+
+<li> If the value of a scrollbar is changed by the program, not the user,
+ the callback seems not to be called. Can this be assured?
+
+<li> The same for dw::fltk::FltkViewport::layout?
+
+<li> Also, the problems with the widgets seems to work. Also sure?
+
+<li> When drawing, clipping of 32 bit values is not working properly.
+
+<li> The item group within a selection widget (menu) should not be selectable.
+</ul>
+
+
+<h2>dw::fltk::FltkPlatform</h2>
+
+<ul>
+<li> There is the problem, that fltk::font always returns a font, the
+ required one, or a replacements. The latter is not wanted in all
+ cases, e.g. when several fonts are tested. Perhaps, this could be
+ solved by searching in the font list. <i>[This was true of fltk2.
+ What is the state of font handling now with fltk-1.3?]</i>
+
+<li> Distinction between italics and oblique would be nice
+ (dw::fltk::FltkFont::FltkFont).
+</ul>
+
+
+<h2>dw::fltk::ui::FltkCheckButtonResource</h2>
+
+Groups of Fl_Radio_Button must be added to one Fl_Group, which is
+not possible in this context. There are two alternatives:
+
+<ol>
+<li>there is a more flexible way to group radio buttons, or
+<li>radio buttons are not grouped, instead, grouping (especially
+ unchecking other buttons) is done by the application.
+</ol>
+
+(This is mostly solved.)
+
+<h2>dw::fltk::FltkImgbuf</h2>
+
+Alpha transparency should be best abstracted by FLTK itself. If not,
+perhaps different implementations for different window systems could
+be used. Then, it is for X necessary to use GCs with clipping masks.
+
+
+<h2>dw::fltk::ui::ComplexButton</h2>
+
+Unfortunately, FLTK does not provide a button with Fl_Group as parent, so
+that children may be added to the button. dw::fltk::ui::ComplexButton does
+exactly this, and is, in an ugly way, a modified copy of the FLTK
+button.
+
+It would be nice, if this is merged with the standard FLTK
+button. Furthermore, setting the type is strange.
+
+If the files do not compile, it may be useful to create a new one from
+the FLTK source:
+
+<ol>
+<li> Copy Fl_Button.H from FLTK to dw/fltkcomplexbutton.hh and
+ src/Button.cxx to dw/fltkcomplexbutton.cc.
+
+<li> In both files, rename "Button" to "ComplexButton". Automatic replacing
+ should work.
+
+<li> Apply the changes below.
+</ol>
+
+The following changes should be applied manually.
+
+<h3>Changes in fltkcomplexbutton.hh</h3>
+
+First of all, the \#define's for avoiding multiple includes:
+
+\code
+-#ifndef fltk_ComplexButton_h // fltk_Button_h formerly
+-#define fltk_ComplexButton_h
++#ifndef __FLTK_COMPLEX_BUTTON_HH__
++#define __FLTK_COMPLEX_BUTTON_HH__
+\endcode
+
+at the beginning and
+
+\code
+-#endif
++#endif // __FLTK_COMPLEX_BUTTON_HH__
+\endcode
+
+at the end. Then, the namespace is changed:
+
+\code
+-namespace fltk {
++namespace dw {
++namespace fltk {
++namespace ui {
+\endcode
+
+at the beginning and
+
+\code
+-}
++} // namespace ui
++} // namespace fltk
++} // namespace dw
+\endcode
+
+at the end. Most important, the base class is changed:
+
+\code
+-#include "FL/Fl_Widget.H"
++#include <FL/Fl_Group.H>
+\endcode
+
+and
+
+\code
+-class FL_API ComplexButton : public Fl_Widget {
++class ComplexButton: public Fl_Group
++{
+\endcode
+
+Finally, for dw::fltk::ui::ComplexButton::default_style, there is a
+namespace conflict:
+
+\code
+- static NamedStyle* default_style;
++ static ::fltk::NamedStyle* default_style;
+\endcode
+
+<h3>Changes in fltkcomplexbutton.cc</h3>
+
+First, \#include's:
+
+\code
+
+ #include <FL/Fl.H>
+-#include <FL/ComplexButton.h> // <FL/Fl_Button.H> formerly
+ #include <FL/Fl_Group.H>
+ #include <FL/Fl_Window.H>
++
++#include "fltkcomplexbutton.hh"
+\endcode
+
+Second, namespaces:
+
+\code
++using namespace dw::fltk::ui;
+\endcode
+
+Since the base class is now Fl_Group, the constructor must be changed:
+
+\code
+-ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) : Fl_Widget(x,y,w,h,l) {
++ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) :
++ Fl_Group(x,y,w,h,l)
++{
+\endcode
+
+Finally, the button must draw its children (end of
+dw::fltk::ui::ComplexButton::draw()):
+
+\code
++
++ for (int i = children () - 1; i >= 0; i--)
++ draw_child (*child (i));
+ }
+\endcode
+
+*/
diff --git a/devdoc/index.doc b/devdoc/index.doc
new file mode 100644
index 00000000..59de8cd8
--- /dev/null
+++ b/devdoc/index.doc
@@ -0,0 +1,48 @@
+/** \mainpage
+
+<h2>Overview</h2>
+
+This is a list of documents to start with:
+
+<ul>
+<li> \ref lout
+<li> \ref dw-overview (map at \ref dw-map)
+</ul>
+
+Currently, a document \ref fltk-problems is maintained, ideally, it
+will be removed soon.
+
+<h2>Historical</h2>
+
+<h3>Replacements for GTK+ and GLib</h3>
+
+There are several classes etc., which are used for tasks formerly (in the GTK+
+version of dillo) achieved by GtkObject (in 1.2.x, this is part of Gtk+) and
+GLib. For an overview on all this, take a look at \ref lout.
+
+GtkObject is replaced by the following:
+
+<ul>
+<li> lout::object::Object is a common base class for many classes used
+ dillo. In the namespace lout::object, there are also some more common
+ classes and interfaces.
+
+<li> A sub class of lout::object::Object is
+ lout::identity::IdentifiableObject, which allows to determine the
+ class at run-time (equivalent to GTK_CHECK_CAST in GtkObject).
+
+<li> For signals, there is the namespace lout::signal.
+</ul>
+
+Hash tables, linked lists etc. can be found in the lout::container namespace,
+several useful macros from GLib have been implemented as inline functions
+in the lout::misc namespace.
+
+As an alternative to the macros defined in list.h, there is also a template
+class, lout::misc::SimpleVector, which does the same.
+
+<h3>Changes in Dw</h3>
+
+If you have been familiar with Dw before, take a look at \ref dw-changes.
+
+*/
diff --git a/devdoc/lout.doc b/devdoc/lout.doc
new file mode 100644
index 00000000..4e1503c6
--- /dev/null
+++ b/devdoc/lout.doc
@@ -0,0 +1,95 @@
+/** \page lout Lots of Useful Tools
+
+In the "lout" directory, there are some common base functionality for
+C++. Most is described as doxygen comments, this text gives an
+overview.
+
+<h2>Common Base Class</h2>
+
+Many classes are derived from lout::object::Object, which defines some
+general methods. See there for more information.
+
+For the case, that you need primitive C++ types, there are some
+wrappers:
+
+<table>
+<tr><th>C++ Type <th>Wrapper Class
+<tr><td>void* <td>lout::object::Pointer
+<tr><td>specific pointer <td>lout::object::TypedPointer (template class)
+<tr><td>int <td>lout::object::Integer
+<tr><td>const char* <td>lout::object::ConstString
+<tr><td>char* <td>lout::object::String
+</table>
+
+
+<h2>Containers</h2>
+
+In the namespace lout::container, several container classes are defined,
+which all deal with instances of lout::object::Object.
+
+<h3>Untyped Containers</h3>
+
+In lout::container::untyped, there are the following containers:
+
+<ul>
+<li>lout::container::untyped::Vector, a dynamically increases array,
+<li>lout::container::untyped::List, a linked list,
+<li>lout::container::untyped::HashTable, a hash table, and
+<li>lout::container::untyped::Stack, a stack.
+</ul>
+
+All provide specific methods, but since they have a common base class,
+lout::container::untyped::Collection, they all provide iterators, by the
+method lout::container::untyped::Collection::iterator.
+
+<h3>Typed Containers</h3>
+
+lout::container::typed provides wrappers for the container classes defined
+in lout::container::untyped, which are more type safe, by using C++
+templates.
+
+
+<h2>Signals</h2>
+
+For how to connect objects at run-time (to reduce dependencies), take a
+look at the lout::signal namespace.
+
+There is also a base class lout::signal::ObservedObject, which implements
+signals for deletion.
+
+
+<h2>Debugging</h2>
+
+In debug.hh, there are some some useful macros for debugging messages,
+see the file for mor informations.
+
+
+<h2>Identifying Classes at Runtime</h2>
+
+If the class of an object must be identified at runtime,
+lout::identity::IdentifiableObject should be used as the base class,
+see there for more details.
+
+
+<h2>Miscellaneous</h2>
+
+The lout::misc namespace provides several miscellaneous stuff:
+
+<ul>
+<li> In some contexts, it is necessary to compare objects
+ (less/greater), for this, also lout::misc::Comparable must be
+ implemented. For example., lout::container::untyped::Vector::sort and
+ lout::container::typed::Vector::sort cast the elements to
+ lout::misc::Comparable. This can be mixed with lout::object::Object.
+<li> lout::misc::SimpleVector, a simple, template based vector class
+ (not depending on lout::object::Object) (a variant for handling a
+ special case in an efficient way is lout::misc::NotSoSimpleVector),
+<li> lout::misc::StringBuffer, class for fast concatenation of a large number
+ of strings,
+<li> lout::misc::BitSet implements a bitset.
+<li> useful (template) functions (lout::misc::min, lout::misc::max), and
+<li> some functions useful for runtime checks (lout::misc::assert,
+ lout::misc::assertNotReached).
+</ul>
+
+*/
diff --git a/devdoc/not-so-simple-container.png b/devdoc/not-so-simple-container.png
new file mode 100644
index 00000000..f3e2c039
--- /dev/null
+++ b/devdoc/not-so-simple-container.png
Binary files differ
diff --git a/devdoc/not-so-simple-container.svg b/devdoc/not-so-simple-container.svg
new file mode 100644
index 00000000..ce00510e
--- /dev/null
+++ b/devdoc/not-so-simple-container.svg
@@ -0,0 +1,785 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.3.1 r9886"
+ sodipodi:docname="not-so-simple-container.svg"
+ inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/not-so-simple-container.png"
+ inkscape:export-xdpi="69"
+ inkscape:export-ydpi="69">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path3998"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path4004"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lend"
+ style="overflow:visible;">
+ <path
+ id="path3992"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+ transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend-5"
+ style="overflow:visible">
+ <path
+ inkscape:connector-curvature="0"
+ id="path3998-5"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend-3"
+ style="overflow:visible">
+ <path
+ inkscape:connector-curvature="0"
+ id="path3998-2"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend-2"
+ style="overflow:visible">
+ <path
+ inkscape:connector-curvature="0"
+ id="path3998-22"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="marker4917"
+ style="overflow:visible">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4919"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="marker4921"
+ style="overflow:visible">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4923"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend-9"
+ style="overflow:visible">
+ <path
+ inkscape:connector-curvature="0"
+ id="path3998-7"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend-6"
+ style="overflow:visible">
+ <path
+ inkscape:connector-curvature="0"
+ id="path3998-6"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend-51"
+ style="overflow:visible">
+ <path
+ inkscape:connector-curvature="0"
+ id="path3998-3"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="226.09436"
+ inkscape:cy="741.31258"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:window-width="1598"
+ inkscape:window-height="876"
+ inkscape:window-x="0"
+ inkscape:window-y="22"
+ inkscape:window-maximized="1">
+ <inkscape:grid
+ type="xygrid"
+ id="grid2985" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Ebene 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3010"
+ width="35.433071"
+ height="17.716536"
+ x="442.91339"
+ y="25.611128" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L"
+ x="496.06299"
+ y="38.581394"
+ id="text3012"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3014"
+ x="496.06299"
+ y="38.581394"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L">unaffected (in main array)</tspan></text>
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot3800"
+ style="fill:black;stroke:none;stroke-opacity:1;stroke-width:1px;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:1;font-family:Nimbus Mono L;font-style:normal;font-weight:normal;font-size:20px;line-height:125%;letter-spacing:0px;word-spacing:0px;-inkscape-font-specification:Nimbus Mono L;font-stretch:normal;font-variant:normal"><flowRegion
+ id="flowRegion3802"><rect
+ id="rect3804"
+ width="276.7818"
+ height="34.345188"
+ x="424.26407"
+ y="20.996433" /></flowRegion><flowPara
+ id="flowPara3806" /></flowRoot> <rect
+ style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3812"
+ width="70.866142"
+ height="17.716536"
+ x="17.716558"
+ y="60.236198" />
+ <rect
+ style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3814"
+ width="35.433071"
+ height="17.716536"
+ x="442.91339"
+ y="61.480198" />
+ <rect
+ style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816"
+ width="35.433071"
+ height="17.716536"
+ x="442.91339"
+ y="96.913269" />
+ <rect
+ style="fill:#ffff40;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3818"
+ width="35.433071"
+ height="17.716536"
+ x="442.91339"
+ y="131.10234" />
+ <rect
+ style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-2"
+ width="88.58268"
+ height="17.716536"
+ x="124.01577"
+ y="60.236198" />
+ <rect
+ style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3812-5"
+ width="88.582687"
+ height="17.716536"
+ x="301.18112"
+ y="60.236198" />
+ <rect
+ style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-4"
+ width="35.433071"
+ height="17.716536"
+ x="442.91339"
+ y="96.913269" />
+ <rect
+ style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-4-2"
+ width="35.433071"
+ height="17.716536"
+ x="88.582703"
+ y="95.669266" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 17.716558,60.236198 70.866142,0 0,17.716536 -70.866142,0"
+ id="path3939"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 389.7638,60.236198 -88.58268,0 0,17.716536 88.58268,0"
+ id="path3941"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <rect
+ style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3812-3"
+ width="70.866142"
+ height="17.716536"
+ x="17.71656"
+ y="148.81888" />
+ <rect
+ style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3812-5-7"
+ width="88.582687"
+ height="17.716537"
+ x="301.18112"
+ y="148.81888" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 17.716558,148.81888 70.86614,0 0,17.71653 -70.86614,0"
+ id="path3939-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 389.7638,148.81887 -88.58268,1e-5 0,17.71653 88.58268,0"
+ id="path3941-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <rect
+ style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-4-2-6"
+ width="35.433071"
+ height="17.716536"
+ x="124.01577"
+ y="148.81888" />
+ <rect
+ style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-2-5"
+ width="53.149605"
+ height="17.716537"
+ x="159.44885"
+ y="148.81888" />
+ <rect
+ style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-2-50"
+ width="35.433067"
+ height="17.716537"
+ x="212.59845"
+ y="184.25195" />
+ <rect
+ style="fill:#ffff40;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3818-4"
+ width="53.149609"
+ height="17.716534"
+ x="248.03152"
+ y="184.25195" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 88.5827,148.81887 35.43307,0"
+ id="path4078-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 88.5827,166.53541 35.43307,0"
+ id="path4078-4-7"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 212.59845,60.236198 88.58267,0"
+ id="path4078-66"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 212.59845,77.952734 88.58267,0"
+ id="path4078-4-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:2, 4;stroke-dashoffset:0"
+ d="m 88.5827,77.952734 0,17.716535"
+ id="path4156"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 88.5827,77.952734 0,17.716535"
+ id="path4176"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 124.01577,95.669269 0,-17.716535"
+ id="path4178"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 212.59845,166.53541 0,17.71654"
+ id="path4180"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 301.18112,184.25195 0,-17.71654"
+ id="path4182"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 88.5827,77.952734 0,17.716535"
+ id="path4186"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png"
+ inkscape:export-xdpi="69"
+ inkscape:export-ydpi="69" />
+ <path
+ style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 124.01577,95.669269 0,-17.716535"
+ id="path4188"
+ inkscape:connector-curvature="0"
+ inkscape:export-xdpi="69"
+ inkscape:export-ydpi="69" />
+ <path
+ style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 212.59845,166.53541 0,17.71654"
+ id="path4190"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png"
+ inkscape:export-xdpi="69"
+ inkscape:export-ydpi="69" />
+ <path
+ style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 301.18112,184.25195 0,-17.71654"
+ id="path4192"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png"
+ inkscape:export-xdpi="69"
+ inkscape:export-ydpi="69" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 88.5827,77.952734 0,17.716535"
+ id="path4078-6-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 124.01577,77.952734 0,17.716535"
+ id="path4078-6-0-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 212.59845,166.53541 0,17.71654"
+ id="path4078-6-0-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 301.18112,166.53541 0,17.71654"
+ id="path4078-6-0-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)"
+ d="m 106.29923,116.92911 c 35.43307,28.34646 0,0 35.43307,28.34646"
+ id="path3803"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)"
+ d="m 148.81892,81.496041 c 35.43307,63.779529 0,0 35.43307,63.779529"
+ id="path3803-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 177.16537,60.236198 0,17.716535"
+ id="path4078-6-0-9-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)"
+ d="m 194.88191,81.496038 c 35.43307,99.212602 0,3e-6 35.43307,99.212602"
+ id="path3803-7-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L"
+ x="496.06299"
+ y="74.426468"
+ id="text3012-5"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3014-0"
+ x="496.06299"
+ y="74.426468"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L">main array (moved)</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
+ x="496.06299"
+ y="109.85954"
+ id="text4897"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan4899"
+ x="496.06299"
+ y="109.85954"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L">original extra array</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L"
+ x="496.06299"
+ y="145.60861"
+ id="text4901"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan4903"
+ x="496.06299"
+ y="145.60861"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L">new inserted area</tspan></text>
+ <rect
+ style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3812-37"
+ width="53.149609"
+ height="17.716536"
+ x="17.716558"
+ y="272.83463" />
+ <rect
+ style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-2-1"
+ width="35.433067"
+ height="17.716537"
+ x="159.44884"
+ y="272.83463" />
+ <rect
+ style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3812-5-5"
+ width="53.149582"
+ height="17.716537"
+ x="336.61423"
+ y="272.83463" />
+ <rect
+ style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-4-2-3"
+ width="88.582664"
+ height="17.716534"
+ x="70.866173"
+ y="308.2677" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 17.716558,272.83462 53.149615,0 0,17.71654 -53.149615,0"
+ id="path3939-43"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 389.7638,272.83462 -53.14961,0 0,17.71654 53.14961,0"
+ id="path3941-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <rect
+ style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3812-3-3"
+ width="53.149624"
+ height="17.716515"
+ x="17.716558"
+ y="361.4173" />
+ <rect
+ style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3812-5-7-9"
+ width="53.149582"
+ height="17.716543"
+ x="336.61423"
+ y="361.4173" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 17.716559,361.4173 53.149604,0 0,17.71653 -53.149604,1e-5"
+ id="path3939-4-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 389.7638,361.4173 -53.14961,0 0,17.71653 53.14961,1e-5"
+ id="path3941-8-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <rect
+ style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-4-2-6-7"
+ width="35.433071"
+ height="17.716536"
+ x="159.44884"
+ y="361.4173" />
+ <rect
+ style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-2-50-6"
+ width="35.433067"
+ height="17.716537"
+ x="248.03151"
+ y="396.85037" />
+ <rect
+ style="fill:#ffff40;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3818-4-9"
+ width="53.149609"
+ height="17.716534"
+ x="283.4646"
+ y="396.85037" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 70.866173,361.41729 88.582667,1e-5"
+ id="path4078-6-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 70.866173,379.13383 88.582667,1e-5"
+ id="path4078-4-7-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 194.88192,272.83462 141.73227,0"
+ id="path4078-66-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 194.88192,290.55116 141.73227,0"
+ id="path4078-4-0-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:2, 4;stroke-dashoffset:0"
+ d="m 70.866173,290.55116 0,17.71653"
+ id="path4156-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 70.866173,290.55116 0,17.71653"
+ id="path4176-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 106.29924,308.26769 0,-17.71653"
+ id="path4178-9"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 194.88192,379.13383 0,17.71654"
+ id="path4180-3"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 336.61419,396.85037 0,-17.71654"
+ id="path4182-8"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 70.866173,290.55116 0,17.71653"
+ id="path4186-1"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png"
+ inkscape:export-xdpi="69"
+ inkscape:export-ydpi="69"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 106.29924,308.26769 0,-17.71653"
+ id="path4188-2"
+ inkscape:connector-curvature="0"
+ inkscape:export-xdpi="69"
+ inkscape:export-ydpi="69" />
+ <path
+ style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 194.88192,379.13383 0,17.71654"
+ id="path4190-8"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png"
+ inkscape:export-xdpi="69"
+ inkscape:export-ydpi="69" />
+ <path
+ style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 336.61419,396.85037 0,-17.71654"
+ id="path4192-4"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png"
+ inkscape:export-xdpi="69"
+ inkscape:export-ydpi="69" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 70.866173,290.55116 0,17.71653"
+ id="path4078-6-0-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 159.44883,290.55116 0,17.71653"
+ id="path4078-6-0-9-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 194.88192,379.13383 0,17.71654"
+ id="path4078-6-0-0-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 336.61419,379.13383 0,17.71654"
+ id="path4078-6-0-6-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect3816-4-2-6-7-8"
+ width="53.149616"
+ height="17.716539"
+ x="194.88191"
+ y="396.85037" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0"
+ d="m 106.29924,308.26769 0,17.71654"
+ id="path4078-6-0-9-5-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)"
+ d="m 88.5827,329.52754 c 88.58267,28.34645 0,0 88.58267,28.34645"
+ id="path3803-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)"
+ d="m 131.10238,329.52754 c 70.86614,24.80315 53.14961,3.5433 88.58268,63.77952"
+ id="path3803-4-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)"
+ d="m 177.16537,294.09447 c 88.58268,99.21259 0,0 88.58268,99.21259"
+ id="path3803-4-01"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L"
+ x="17.716536"
+ y="42.519665"
+ id="text3012-5-7"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3014-0-2"
+ x="17.716536"
+ y="42.519665"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L">Example 1:</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L"
+ x="528"
+ y="389.36218"
+ id="text5205"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan5207"
+ x="528"
+ y="389.36218" /></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L"
+ x="17.716536"
+ y="255.11809"
+ id="text3012-5-7-9"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ x="17.716536"
+ y="255.11809"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
+ id="tspan5230">Example 2:</tspan></text>
+ </g>
+</svg>
diff --git a/devdoc/rounding-errors.doc b/devdoc/rounding-errors.doc
new file mode 100644
index 00000000..a442033e
--- /dev/null
+++ b/devdoc/rounding-errors.doc
@@ -0,0 +1,35 @@
+/** \page rounding-errors How to Avoid Rounding Errors
+
+(Probably, this is a standard algorithm, so if someone knows the name,
+drop me a note.)
+
+If something like
+
+\f[y_i = {x_i a \over b}\f]
+
+is to be calculated, and all numbers are integers, a naive
+implementation would result in something, for which
+
+\f[\sum y_i \ne {(\sum x_i) a \over b}\f]
+
+because of rounding errors, due to the integer division. This can be
+avoided by transforming the formula into
+
+\f[y_i = {(\sum_{j=0}^{j=i} x_j) a \over b} - \sum_{j=0}^{j=i-1} y_j\f]
+
+Of corse, when all \f$y_i\f$ are calculated in a sequence,
+\f$\sum_{j=0}^{j=i} x_j\f$ and \f$\sum_{j=0}^{j=i-1} y_j\f$ can be
+accumulated in the same loop. Regard this as sample:
+
+\code
+int n, x[n], a, b; // Should all be initialized.
+int y[n], cumX = 0, cumY = 0;
+
+for (int i = 0; i < n; i++) {
+ cumX += x[i]
+ y[i] = (cumX * a) / b - cumY;
+ cumY += y[i];
+}
+\endcode
+
+*/
diff --git a/devdoc/uml-legend.doc b/devdoc/uml-legend.doc
new file mode 100644
index 00000000..54004ccd
--- /dev/null
+++ b/devdoc/uml-legend.doc
@@ -0,0 +1,195 @@
+/** \page uml-legend UML Legend
+
+This page describes the notation for several diagrams used in the
+documentation, which is a slight variation of UML.
+
+
+<h2>Classes</h2>
+
+Classes are represented by boxes, containing there names:
+
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10];
+ fontname=Helvetica; fontsize=8;
+ "Concrete Class";
+ "Abstract Class" [color="#a0a0a0"];
+ Interface [color="#ff8080"];
+}
+\enddot
+
+(In most cases, the attributes and operations are left away, for
+better readibility. Just click on it, to get to the detailed
+description.)
+
+Of course, in C++, there are no interfaces, but here, we call a class,
+which has only virtual abstract methods, and so does not provide any
+functionality, an interface.
+
+Templates get a yellow background color:
+
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10,
+ fillcolor="#ffffc0", style="filled"];
+ fontname=Helvetica; fontsize=8;
+ "Concrete Class Template";
+ "Abstract Class Template" [color="#a0a0a0"];
+ "Interface Template" [color="#ff8080"];
+}
+\enddot
+
+
+<h2>Objects</h2>
+
+In some cases, an examle for a concrete constellation of objects is
+shown. An object is represented by a box containing a name and the
+class, separated by a colon.
+
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10];
+ edge [arrowhead="open", labelfontname=Helvetica, labelfontsize=10,
+ color="#404040", labelfontcolor="#000080"];
+ fontname=Helvetica; fontsize=10;
+
+ "x: A" -> "y1: B";
+ "x: A" -> "y2: B";
+}
+\enddot
+
+The names (\em x, \em y, and \em z) are only meant within the context
+of the diagram, there needs not to be a relation to the actual names
+in the program. They should be unique within the diagram.
+
+Classes and objects may be mixed in one diagram.
+
+
+<h2>Associations</h2>
+
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10];
+ edge [arrowhead="open", labelfontname=Helvetica, labelfontsize=10,
+ color="#404040", labelfontcolor="#000080",
+ fontname=Helvetica, fontsize=10, fontcolor="#000080"];
+ fontname=Helvetica; fontsize=10;
+ A -> B [headlabel="*", taillabel="1", label="x"];
+}
+\enddot
+
+In this example, one instance of A refers to an arbitrary number of B
+instances (denoted by the "*"), and each instance of B is referred by
+exactly one ("1") A. The label \em x is the name of the association,
+in most cases the name of the field, e.g. A::x.
+
+Possible other values for the \em multiplicity:
+
+<ul>
+<li> a concrete number, in most cases "1",
+<li> a range, e.g. "0..1",
+<li> "*", denoting an arbitrary number.
+</ul>
+
+
+<h2>Implementations and Inheritance</h2>
+
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10];
+ edge [arrowhead="none", dir="both", arrowtail="empty",
+ labelfontname=Helvetica, labelfontsize=10, color="#404040",
+ labelfontcolor="#000080"];
+ fontname=Helvetica; fontsize=10;
+ A[color="#ff8080"];
+ B[color="#ff8080"];
+ C;
+ D;
+ A -> B;
+ A -> C [style="dashed"];
+ C -> D;
+}
+\enddot
+
+In this example,
+
+<ul>
+<li> the interface B extends the interface A,
+<li> the class C implements the interface A, and
+<li> the class D extends the class C.
+</ul>
+
+
+<h2>Template Instantiations</h2>
+
+Template instantiations are shown as own classes/interfaces, the
+instantiation by the template is shown by a yellow dashed arrow:
+
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10];
+ edge [arrowhead="none", arrowtail="empty", dir="both",
+ labelfontname=Helvetica, labelfontsize=10, color="#404040",
+ labelfontcolor="#000080"];
+ fontname=Helvetica; fontsize=10;
+
+ A[color="#ff8080"];
+ B[color="#ff8080"];
+ C[color="#ff8080", fillcolor="#ffffc0", style="filled"];
+ C_A[color="#ff8080", label="C \<A\>"];
+ C_B[color="#ff8080", label="C \<A\>"];
+ D;
+
+ C -> C_A [arrowhead="open", arrowtail="none", style="dashed",
+ color="#808000"];
+ C -> C_B [arrowhead="open", arrowtail="none", style="dashed",
+ color="#808000"];
+ A -> C_A;
+ B -> C_B;
+ C_A -> D [style="dashed"];
+}
+\enddot
+
+In this example, the interface template C uses the template argument
+as super interface.
+
+
+<h2>Packages</h2>
+
+Packages are presented by dashed rectangles:
+
+\dot
+digraph G {
+ node [shape=record, fontname=Helvetica, fontsize=10];
+ edge [arrowhead="none", arrowtail="empty", dir="both",
+ labelfontname=Helvetica, labelfontsize=10, color="#404040",
+ labelfontcolor="#000080"];
+ fontname=Helvetica; fontsize=10;
+
+ subgraph cluster_1 {
+ style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ label="package 1";
+
+ A;
+ B [color="#a0a0a0"];
+ }
+
+ subgraph cluster_2 {
+ style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ label="package 2";
+
+ C;
+ D [color="#a0a0a0"];
+ E
+ }
+
+ A -> C;
+ B -> D;
+ D -> E;
+ E -> A [arrowhead="open", arrowtail="none"];
+}
+\enddot
+
+Packages may be nested.
+
+*/ \ No newline at end of file