changeset 347:e5955ab8dafb

- Moved the dw2 tree into dillo2's tree.
author jcid
date Wed, 24 Sep 2008 18:44:40 +0200
parents 05228bc9f399
children 2e01d88e03be
files ChangeLog Doxyfile Makefile.am configure.in doc/Makefile.am doc/dw-changes.doc doc/dw-images-and-backgrounds.doc doc/dw-layout-views.doc doc/dw-layout-widgets.doc doc/dw-map.doc doc/dw-overview.doc doc/dw-usage.doc doc/dw-widget-sizes.doc doc/fltk-problems.doc doc/index.doc doc/lout.doc doc/rounding-errors.doc doc/uml-legend.doc dw/Makefile.am dw/alignedtextblock.cc dw/alignedtextblock.hh dw/bullet.cc dw/bullet.hh dw/core.hh dw/events.hh dw/findtext.cc dw/findtext.hh dw/fltkcomplexbutton.cc dw/fltkcomplexbutton.hh dw/fltkcore.hh dw/fltkflatview.cc dw/fltkflatview.hh dw/fltkimgbuf.cc dw/fltkimgbuf.hh dw/fltkmisc.cc dw/fltkmisc.hh dw/fltkplatform.cc dw/fltkplatform.hh dw/fltkpreview.cc dw/fltkpreview.hh dw/fltkui.cc dw/fltkui.hh dw/fltkviewbase.cc dw/fltkviewbase.hh dw/fltkviewport.cc dw/fltkviewport.hh dw/image.cc dw/image.hh dw/imgbuf.hh dw/iterator.cc dw/iterator.hh dw/layout.cc dw/layout.hh dw/listitem.cc dw/listitem.hh dw/platform.hh dw/preview.xbm dw/ruler.cc dw/ruler.hh dw/selection.cc dw/selection.hh dw/style.cc dw/style.hh dw/table.cc dw/table.hh dw/tablecell.cc dw/tablecell.hh dw/textblock.cc dw/textblock.hh dw/types.cc dw/types.hh dw/ui.cc dw/ui.hh dw/view.hh dw/widget.cc dw/widget.hh lout/Makefile.am lout/container.cc lout/container.hh lout/debug.hh lout/identity.cc lout/identity.hh lout/misc.cc lout/misc.hh lout/object.cc lout/object.hh lout/signal.cc lout/signal.hh src/Makefile.am test/Makefile.am test/dw_anchors_test.cc test/dw_border_test.cc test/dw_example.cc test/dw_find_test.cc test/dw_images_scaled.cc test/dw_images_scaled2.cc test/dw_images_simple.cc test/dw_imgbuf_mem_test.cc test/dw_links.cc test/dw_links2.cc test/dw_lists.cc test/dw_resource_test.cc test/dw_table.cc test/dw_table_aligned.cc test/dw_ui_test.cc test/fltk_browser.cc test/form.cc test/form.hh test/shapes.cc
diffstat 109 files changed, 27518 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Sep 24 16:20:42 2008 +0200
+++ b/ChangeLog	Wed Sep 24 18:44:40 2008 +0200
@@ -181,6 +181,135 @@
  - test no_proxy (set a list in dillorc).
 
 -----------------------------------------------------------------------------
+dw
+
+0.0.43
+        - Fixed bug in dw::core::ExtIterator (wrong mask, see also Jorge's
+          patch "createvar.diff" from Nov 08).
+        - Applied Jorge's patch for dw::core::AlignedTextblock
+          ("lists.diff" in mail from Nov 08).
+        - Applied Jorge's patch for dw::core::Textblock ("links.diff" in
+          mail from Nov 08).
+        - Applied Jorge's patch for configure.in ("conf.diff" in mail from
+          Nov 08).
+        - Renamed ExtIterator to DeepIterator.
+        - Implemented CharIterator (as an alternative to word iterators).
+        - Implemented text search (simple KMP based on CharIterator).
+        - Completed scrolling.
+          Patches: Sebastian Geerken
+
+        + Implemented drag scrolling with mouse's middle button.
+        - Enabled commented out partial image redraw, adding some checks.
+        - Enabled clipped redraws (avoids some flickering).
+        - Improvement: avoid complete redraws for child widget updates.
+        - Added code to really delete fltk2 widgets embedded in dw2.
+        - Fixed partial redraws and scrolling interference.
+        - Added combination of drawing rectangles into a larger one.
+        - Bug fix: a newly added rectangle may contain others.
+        - Made draw() check whether a rectangle is visible at drawing time.
+        - The background is now cleared properly on partial redraws.
+        - Made getWidgetAtPoint() a virtual method of widget and implemented a
+          custom one for TextBlock, reducing CPU usage on pages full of links.
+        - Added a style reference and an initialization to mustQueueResize.
+        - Replaced prepareCreateFltkWidget with an explicit call to add().
+        - Fixed an assertion-exit bug in DeepIterator.
+        - Fixed two viewport bugs: in drawing and scrolling.
+        - Made scrollbars really children of FltkViewport.
+        - Avoided multiple redraws when Layout::resizeIdle() queues itself.
+        - Set FltkViewBase::draw to intersect with view area for expose.
+        - Set cursor shape to CURSOR_MOVE on drag. Disabled drag over links.
+        - Added Layout::queueDrawExcept(), it reduces flickering by avoiding
+          a redraw when another rectangle is added.
+        - Fixed a scrollIdleId test to properly compare against -1.
+        - Set FltkPlatform::removeIdle to use removeRef() instead of remove().
+        - Cleaned up scroll code and moved updateCanvasWidgets() out of draw().
+        - Switched begin-end pairs with add() calls (fixes side-effect bugs!).
+        - Fixed checks in adjustScrollPos() to not allow wild values.
+        - Added double buffering for partial redraws!
+        - Implemented ComplexButton.
+        - Fixed find text so it works for phrases and PRE-wrapped text.
+        - Fixed a bug in DeepIterator::prev.
+        - Added the "lout" namespace.
+        - Reduced memory usage in 30% by reusing styles, reducing the size
+          of struct Content, and not preallocating in SimpleVector. !
+        - Made fontsTable and colorsTable static members of Font and Color.
+        - Moved highlighting information from struct Word into Textblock
+          to save memory.
+        - Reduced memory usage 10% with a custom memory handler in Textblock.
+        - Fixed a segfault when searching for single characters.
+        - Fixed memory leaks by s/delete/delete[]/ where necessary.
+        - Fixed three iterator memory leaks in Iterator::scrollTo().
+        - Changed DeepIterator to always clone its parameter (segfault bug).
+        - Implemented selection of multibyte glyphs (UTF-8).
+        - Removed the canvasWidgets list (fltk's children seem enough).
+        - Switched misc:assert() to the standard assert() call.
+          Patches: Johannes Hofmann
+        + Fixed a segfault-on-empty-strings bug in ConstString::hashValue.
+        - Fixed a segfault in reallocChildren (colspan/rowspan related).
+        - Fixed another assertion-exit bug in DeepIterator.
+        - Added the dw::fltk::ui::FltkMultiLineTextResource class.
+        - Implemented TEXTAREA using fltk::TextEditor.
+        - Bugfix: added the missing fltk::setfont calls before ::getwidth.
+        - Bugfix: initialized scrollIdleNotInterrupted variable.
+        - Commented out obsolete DEBUG_MSG lines in widget.cc.
+        - Fixed rowspan apportion when no single rowspan=1 row is found.
+        - Fixed allocateFltkWidget to handle and display FltkListResource.
+        - Fixed a slithery BUG in lout::misc::Stringbuffer.
+        - Implemented multiple item selection in FltkSelectionResource.
+          Patches: Jeremy Henty
+        + Added an extra argument in the link signals
+          (I recommended that instead of an array of image handlers --jcid)
+        - Aded an x_img camp to style (an image array index, like x_link).
+        - Added the same workaround in ui.cc for WHEN_ENTER_KEY_ALWAYS.
+        - Fixed shading (style.cc) and implemented FltkViewBase::drawPolygon().
+        - Implemented Circle and Disk bullet drawing.
+        - Fixed a bug in FltkViewBase::getClippingView.
+        - Made FltkColor::FltkColor use ::fltk::BLACK (bugfix).
+        - Fixed a bug with dissappearing widgets when scrolling with low CPU.
+        - Fixed a bug with the canvas offset of scrolling bars.
+        - Fixed a typo bug in scrollIdle() and a typo in processMouseEvent().
+        - Fixed an offset arithmetic bug with widgets inside textblock.
+        - Fixed RTFL debugging messages.
+        - Switched ComplexButton to use "Activate" instead of "Clicked" signal.
+        - Made the ComplexButton resource remember its click x,y.
+        - Added "enter" and "leave" signals into class Resource.
+          Patches: place
+        + Enabled mouse wheel scrolling. 
+          FltkViewport::setScrollStep() sets how many points at a time.
+        - Added setDeleteCallback(DW_Callback_t func, void *data) to widget.
+          This allows to hook a callback when the widget is destroyed.
+        - Implemented a weighted apportionment algorithm for table rowspan.
+        - Implemented a weighted apportionment algorithm for table colspan.
+        - Implemented percentage widths in tables (better rendering!).
+        - Fixed an initialization bug in hruler.
+        - Fixed a bug in the textblock's wrapping algorithm.
+        - Fixed a bug in table cellpadding.
+        - Fixed a bug in getContentHeight().
+        - Changed the table-apportion algorithms + bug fixes. Big work!
+        - Fixed a mistake in the CSS-box-model PNG image (style-box-model.png).
+        - Added initialization for scrollX and scrollY.
+        - Fixed a typo bug in adjustScrollPos().
+        - Fixed two typo bugs in Textblock::drawLine().
+        - Changed Textblock::addText() to internally allocate its text string,
+          making the memory handling opaque to the caller.
+          Patches: Jorge Arellano Cid
+        + Added actual text selection.
+          Patch: Sebastian Geerken, place
+        + Implemented dw::fltk::ui::FltkOptionMenuResource::isSelected(),
+          added Item::createNewGroupWidget(), Item::createNewWidget().
+          Patch: Jeremy Henty, Johannes Hofmann
+        + Implemented the necessary base for image maps.
+          Patch: Johannes Hofmann, place
+
+0.0.42
+        - Fixed event handling in FLTK views. (Fixes links and several
+          problems with UI resources.)
+        - Implemented clipping views. (dw::Image used this already in
+          version 0.0.41.)
+        - Added "activated" signals to UI resources.
+          Patches: Sebastian Geerken
+
+-----------------------------------------------------------------------------
 
 
 0.8.5-pre-dw-redesign-1 [internal]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Doxyfile	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,1143 @@
+# Doxyfile 1.3.7
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = Dillo
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 2 levels of 10 sub-directories under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of source 
+# files, where putting all generated files in the same directory would otherwise 
+# cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, 
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en 
+# (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, 
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is used 
+# as the annotated text. Otherwise, the brief description is used as-is. If left 
+# blank, the following values are used ("$name" is automatically replaced with the 
+# name of the entity): "The $name class" "The $name widget" "The $name file" 
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
+# members of a class in the documentation of that class as if those members were 
+# ordinary class members. Constructors, destructors and assignment operators of 
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
+# only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = NO
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  =
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS          = *.cc *.hh *.doc
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = dlib dpi dpid dpip src test
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = doc
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.
+
+INPUT_FILTER           = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 3
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse the 
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or 
+# super classes. Setting the tag to NO turns the diagrams off. Note that this 
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is 
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+#HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = NO
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = NO
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 20480
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes that 
+# lay further from the root node will be omitted. Note that setting this option to 
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also 
+# note that a graph may be further truncated if the graph's image dimensions are 
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). 
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+	
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
--- a/Makefile.am	Wed Sep 24 16:20:42 2008 +0200
+++ b/Makefile.am	Wed Sep 24 18:44:40 2008 +0200
@@ -1,5 +1,5 @@
-SUBDIRS = doc dlib dpip src dpid dpi
+SUBDIRS = lout dw dlib dpip src doc dpid dpi test
 
-EXTRA_DIST = ChangeLog.old dillo2rc install-dpi-local README-port
+EXTRA_DIST = ChangeLog.old Doxyfile dillo2rc install-dpi-local README-port
 
 sysconf_DATA = dillo2rc
--- a/configure.in	Wed Sep 24 16:20:42 2008 +0200
+++ b/configure.in	Wed Sep 24 18:44:40 2008 +0200
@@ -34,6 +34,8 @@
               enable_ssl=$enableval, enable_ssl=yes)
 AC_ARG_ENABLE(threaded-dns,[  --disable-threaded-dns  Disable the advantage of a reentrant resolver library],
               enable_threaded_dns=$enableval, enable_threaded_dns=yes)
+AC_ARG_ENABLE(rtfl,   [  --enable-rtfl           Build with rtfl messages])
+AC_ARG_ENABLE(doublebuffer,   [  --disable-doublebuffer           Disable double buffering for drawing], , enable_doublebuffer=yes)
               
 AC_PROG_CC
 AC_PROG_CXX
@@ -425,6 +427,12 @@
 if test "x$enable_threaded_dns" = "xyes" ; then
   CFLAGS="$CFLAGS -DD_DNS_THREADED"
 fi
+if test "x$enable_rtfl" = "xyes" ; then
+  CXXFLAGS="$CXXFLAGS -DDBG_RTFL"
+fi
+if test "x$enable_doublebuffer" = "xno" ; then
+  CXXFLAGS="$CXXFLAGS -DNO_DOUBLEBUFFER"
+fi
 
 dnl -----------------------
 dnl Checks for header files
@@ -487,5 +495,5 @@
 AC_SUBST(LIBICONV_LIBS)
 AC_SUBST(datadir)
 
-AC_OUTPUT(Makefile dlib/Makefile dpip/Makefile dpid/Makefile dpi/Makefile doc/Makefile src/Makefile src/IO/Makefile)
+AC_OUTPUT(Makefile dlib/Makefile dpip/Makefile dpid/Makefile dpi/Makefile doc/Makefile dw/Makefile lout/Makefile src/Makefile src/IO/Makefile test/Makefile)
 
--- a/doc/Makefile.am	Wed Sep 24 16:20:42 2008 +0200
+++ b/doc/Makefile.am	Wed Sep 24 18:44:40 2008 +0200
@@ -1,19 +1,44 @@
 EXTRA_DIST = \
-	Cache.txt \
-	Cookies.txt \
-	Dillo.txt \
-	Dw.txt \
-	DwImage.txt \
-	DwPage.txt \
-	DwRender.txt \
-	DwStyle.txt \
-	DwTable.txt \
-	DwWidget.txt \
-	HtmlParser.txt \
-	IO.txt \
-	Images.txt \
-	Imgbuf.txt \
-	NC_design.txt \
-	Selection.txt \
-	Dpid.txt \
-	README
+	index.doc \
+	lout.doc \
+	dw-map.doc \
+	dw-overview.doc \
+	dw-usage.doc \
+	dw-layout-views.doc \
+	dw-layout-widgets.doc \
+	dw-widget-sizes.doc \
+	dw-changes.doc \
+	dw-images-and-backgrounds.doc \
+	fltk-problems.doc \
+	rounding-errors.doc \
+	uml-legend.doc \
+	dw-example-screenshot.png \
+	dw-viewport-without-scrollbar.png \
+	dw-viewport-with-scrollbar.png \
+	dw-size-of-widget.png \
+	dw-style-box-model.png \
+	dw-style-length-absolute.png \
+	dw-style-length-percentage.png \
+	dw-style-length-relative.png \
+	dw-textblock-collapsing-spaces-1-1.png \
+	dw-textblock-collapsing-spaces-1-2.png \
+	dw-textblock-collapsing-spaces-2-1.png \
+	dw-textblock-collapsing-spaces-2-2.png \
+        Cache.txt \
+        Cookies.txt \
+        Dillo.txt \
+        Dw.txt \
+        DwImage.txt \
+        DwPage.txt \
+        DwRender.txt \
+        DwStyle.txt \
+        DwTable.txt \
+        DwWidget.txt \
+        HtmlParser.txt \
+        IO.txt \
+        Images.txt \
+        Imgbuf.txt \
+        NC_design.txt \
+        Selection.txt \
+        Dpid.txt \
+        README
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/dw-changes.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,109 @@
+/** \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> There are multiple views (implementations of dw::core::View).
+          Typically, you keep a reference on dw::core::Layout and a "main"
+          view (a viewport).
+
+     <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::Widget::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>
+
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/dw-images-and-backgrounds.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,146 @@
+/** \page dw-images-and-backgrounds Images and Backgrounds in Dw
+
+<h2>General</h2>
+
+Representation of the image data is delegated to dw::core::Imgbuf, see
+there for details. Drawing is delegated to dw::core::View
+(dw::core::View::drawImgbuf).
+
+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.
+
+
+<h2>Images</h2>
+
+This is the simplest renderer, displaying an image. For each row to be
+drawn,
+
+<ol>
+<li> first dw::core::Imgbuf::copyRow, and then
+<li> for each dw::Image, dw::Image::drawRow must be called, with the same
+     argument (no scaling is necessary).
+</ol>
+
+dw::Image automatically scales the dw::core::Imgbuf, the root buffer
+should be passed to dw::Image::setBuffer.
+
+\see dw::Image for more details.
+
+<h2>Future Extensions</h2>
+
+(This is not implemented yet.) Rendering itself (image widgets and
+background) will be abstracted, by a new interface
+dw::core::ImageRenderer.  In the current code for image decoding, this
+interface will replace references to dw::Image, which implements
+dw::core::ImageRenderer, in most cases.
+
+<h2>Backgrounds</h2>
+
+(This is based on future extensions described above.) Since background
+are style resources, they are associated with
+dw::core::style::Style. For backgrounds, another level is needed,
+because of the 1-to-n relation from dw::core::style::Style to
+dw::core::Widget:
+
+\dot
+digraph G {
+   node [shape=record, fontname=Helvetica, fontsize=10];
+   edge [arrowhead="open", arrowtail="none", labelfontname=Helvetica,
+         labelfontsize=10, color="#404040", labelfontcolor="#000080"];
+   fontname=Helvetica; fontsize=10;
+
+   "background renderer (as a part of style)" -> "image buffer" [headlabel="*",
+                                                                taillabel="1"];
+   "widget (or a part of it)" -> "background renderer (as a part of style)"
+      [headlabel="*", taillabel="1"];
+}
+\enddot
+
+Unlike dw::Image, dw::core::style::BgRenderer is not associated with a
+certain rectangle on the canvas. Instead, widgets, or parts of widgets
+take this role. This is generally represented by an implementation of
+the interface dw::core::style::BgAllocation, which is implemented by
+dw::core::Widget, but also by all parts of widget implementation,
+which may have an own background image.
+
+The following diagram gives a total overview:
+
+\dot
+digraph G {
+   node [shape=record, fontname=Helvetica, fontsize=10];
+   edge [arrowhead="open", arrowtail="none", labelfontname=Helvetica,
+         labelfontsize=10, color="#404040", labelfontcolor="#000080"];
+   fontname=Helvetica; fontsize=10;
+
+   "DICache Entry";
+
+   subgraph cluster_dw_images {
+      style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+      label="Dw Images";
+
+      ImageRenderer [URL="\ref dw::core::ImageRenderer", color="#ff8080"];
+      Imgbuf [URL="\ref dw::core::Imgbuf", color="#ff8080"];
+   }
+
+   subgraph cluster_widgets {
+      style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+      label="Widgets";
+
+      Widget [URL="\ref dw::core::Widget", color="#a0a0a0"];
+      Textblock [URL="\ref dw::Textblock"];
+      "Textblock::Word" [URL="\ref dw::Textblock::Word"];
+      Table [URL="\ref dw::Table"];
+      "Table::Row" [URL="\ref dw::Table::Row"];
+      Image [URL="\ref dw::Image"];
+   }
+
+   subgraph cluster_style {
+      style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+      label="dw::core::style";
+
+      Style [URL="\ref dw::core::style::Style"];
+      BgRenderer [URL="\ref dw::core::style::BgRenderer"];
+      BgAllocation [URL="\ref dw::core::style::BgAllocation", color="#ff8080"];
+   }
+
+   "DICache Entry" -> ImageRenderer [headlabel="*", taillabel="1"];
+   "DICache Entry" -> Imgbuf [headlabel="1", taillabel="1"]; 
+
+   BgRenderer -> Imgbuf [headlabel="1", taillabel="*"];
+   BgRenderer -> BgAllocation [headlabel="*", taillabel="1"];
+   ImageRenderer -> BgRenderer [arrowhead="none", arrowtail="empty",
+                                style="dashed"];
+   ImageRenderer -> Image [arrowhead="none", arrowtail="empty",
+                           style="dashed"];
+
+   Style -> BgRenderer [headlabel="0..1", taillabel="1"];
+
+   Widget -> Textblock [arrowhead="none", arrowtail="empty"];
+   Textblock -> "Textblock::Word" [headlabel="*", taillabel="1"];
+   Widget -> Table [arrowhead="none", arrowtail="empty"];
+   Table -> "Table::Row" [headlabel="*", taillabel="1"];
+   Widget -> Image [arrowhead="none", arrowtail="empty"];
+
+   BgAllocation -> Widget [arrowhead="none", arrowtail="empty",
+                           style="dashed"];
+   BgAllocation -> "Textblock::Word" [arrowhead="none", arrowtail="empty",
+                                      style="dashed"];
+   BgAllocation -> "Table::Row" [arrowhead="none", arrowtail="empty",
+                                 style="dashed"];
+}
+\enddot
+
+<center>[\ref uml-legend "legend"]</center>
+
+
+<h2>Integration into dillo</h2>
+
+\todo Add some references.
+
+
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/dw-layout-views.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,270 @@
+/** \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 views do a bit less than a typical view, i.e. only the actual
+drawing.
+
+Additionally, there is a structure representing common properties of
+the platform, views generally work only together with one specific
+platform. A platform is typically related to the underlying UI
+toolkit, but other uses may be thought of.
+
+This design helps to archieve three important goals:
+
+<ul>
+<li> It makes different views of the same document simple, e.g. the
+     normal viewport and the preview window.
+
+<li> Abstraction of the actual drawing, by different implementations
+     of dw::core::View. Most important, there must be a viewport, but
+     some other views are possible, e.g. a preview window.
+
+<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 archived,
+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>
+
+Therefor, 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. These sizes are always equal in
+all views. However, a given view may not use viewports at all, and
+there may be the case, that no view related to a layout uses
+viewports, in this case, the viewport size is not defined at all.
+
+(The case, that there is no viewport at all, is currently not well
+defined, but this case does not occur currently within dillo.)
+
+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 views.
+
+<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. Each view returns, via
+dw::core::View::getHScrollbarThickness and
+dw::core::View::getVScrollbarThickness, how thick they will be, when
+visible. The total space difference is then the maximum of all values,
+which the views return.
+
+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 neccesary 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 all views (dw::core::View::queueDraw).
+     Typically, the views 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>
+
+Generally, all views show the same layout, which has a given size
+(canvas size). In the simplest case, views do not have an influence on
+the canvas size, so that they are just 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>
+
+Furthermore, viewport sizes and scrollbar thicknesses are always the
+same. There are two cases, in which 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 affected view delegates this
+     change to the layout, by calling
+     dw::core::Layout::viewportSizeChanged. All other views are
+     told about this, by calling dw::core::Layout::setViewportSize.
+
+<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 an own
+     section.
+</ul>
+
+After the creation of the layout, the viewport size is undefined. When
+a view is attached to a layout, and this view is already to be able to
+define its viewport size, it may already 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 gets 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>
+
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/dw-layout-widgets.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,270 @@
+/** \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 do define the borders of a widget, wheather 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 to 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. Generally, a widget draws into different views
+(see \ref dw-layout-views), the view to draw into is passed as the
+first argument. In the first case, only the view, which causes the
+expose event, is passed, in the second case, dw::core::Widget::draw is
+called multiple times, once for each view connected to the layout.
+
+Each view provides some primitive methods for drawing, most should be
+obvious. Notice 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 views (\ref dw-layout-views)
+pass mouse events to the layout, which then passes them to the
+widgtes. 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 anchestor of the old
+     and the new widget, and
+<li> the path from this anchestor 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::Widget::EventReceiver. 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.
+
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/dw-map.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/dw-overview.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,157 @@
+/** \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"];
+   Widget -> Table [arrowhead="none", arrowtail="empty"];
+   Widget -> Image [arrowhead="none", arrowtail="empty"];
+   Widget -> etc1 [arrowhead="none", arrowtail="empty"];
+   Textblock -> AlignedTextblock [arrowhead="none", arrowtail="empty"];
+   AlignedTextblock -> etc2 [arrowhead="none", arrowtail="empty"];
+
+   Platform -> FltkPlatform [arrowhead="none", arrowtail="empty",
+                             style="dashed"];
+   FltkPlatform -> FltkView [headlabel="*", taillabel="1"];
+
+   View -> FltkView [arrowhead="none", arrowtail="empty"];
+   FltkView -> FltkViewport [arrowhead="none", arrowtail="empty",
+                             style="dashed"];
+   FltkView -> FltkPreview [arrowhead="none", arrowtail="empty",
+                            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
+     views, 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 views.
+
+<li> The views (implementations of dw::core::View) provide 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>
+
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/dw-usage.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,373 @@
+/** \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 <fltk/Window.h>
+#include <fltk/run.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 instanciated:
+
+\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
+   fltk::Window *window = new fltk::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;
+\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::createSimple (layout, 0x000000);
+   styleAttrs.backgroundColor =
+      dw::core::style::Color::createSimple (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 = fltk::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 imediately 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>
+
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/dw-widget-sizes.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,186 @@
+/** \page dw-widget-sizes Sizes of Dillo Widgets
+
+<h2>Allocation</h2>
+
+Each widget has an \em allocation at a given time, this includes
+
+<ul>
+<li> the position (\em x, \em y) relative to the upper left corner of the
+     canvas, and
+<li> the size (\em width, \em ascent, \em descent).
+</ul>
+
+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.
+
+<ul>
+<li> the position of the toplevel widget is always (0, 0), and
+<li> the canvas size is defined by the size of the toplevel widget.
+</ul>
+
+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:
+
+<ul>
+<li>\em x = 50
+<li>\em y = 50
+<li>\em width = 150
+<li>\em ascent = 150
+<li>\em descent = 100
+</ul>
+
+The current allocation of a widget is hold in
+dw::core::Widget::allocation. It can be set from outside by
+callcalling 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.
+
+<h2>Requisitions</h2>
+
+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:
+
+<ul>
+<li> 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.
+
+<li> 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).
+</ul>
+
+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.)
+
+<h2>Size Hints</h2>
+
+Some widgets do not have an inherent size, but depend on the context,
+e.g. the viewport size. These widgets should adhere to <i>size hints</i>,
+i.e. implement the methods dw::core::Widget::setWidth,
+dw::core::Widget::setAscent and dw::core::Widget::setDescent. The values
+passed to the calles are
+
+<ul>
+<li> the viewport size (ascent is the heigt here, while descent is 0) for
+     the toplevel widget, and
+<li> determined by the parent for its child widgets.
+</ul>
+
+Generally, the values should define the available space for the
+widget. 
+
+A widget, which depends on size hints, should call
+dw::core::Widget::queueResize, when apropriate.
+
+\todo There should be a definition of "available space".
+
+<h2>Width Extremes</h2>
+
+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:
+
+<ul>
+<li> the minimal width is the smallest width, at which a widget can still
+     display contents, and
+<li> the maximal width is the largest width, above which increasing the width
+     does not make any sense.
+</ul>
+
+Especially the latter is vaguely defined, here are some examples:
+
+<ul>
+<li> 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).
+
+<li> 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.
+
+<li> dw::Table is an example, where the width extremes are calculated
+     from the width extremes of the children.
+</ul>
+
+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.
+
+
+<h2>Resizing</h2>
+
+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:
+
+<ol>
+<li> 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.
+
+<li> The widget must implement dw::core::Widget::markSizeChange and
+     dw::core::Widget::markExtremesChange, these methods are called in
+     two cases:
+
+     <ol>
+     <li> directly after dw::core::Widget::queueResize, with the argument
+          ref was passed to dw::core::Widget::queueResize, and
+     <li> if a child widget has called dw::core::Widget::queueResize,
+          with the value of the parent_ref member of this child.
+     </ol>
+</ol>
+
+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.
+
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/fltk-problems.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,219 @@
+/** \page fltk-problems Problems with FLTK
+
+<h2>dw::fltk::FltkViewport</h2>
+
+Current problems:
+
+<ul>
+<li> dw::fltk::FltkViewport::draw should only draw the region, for which e.g.
+     an expose event was received.
+
+<li> dw::fltk::FltkViewport::queueDraw will collect data, which has to be
+     redrawn. Currently, it calls redraw (DAMAGE_EXPOSE), can this be changed,
+     so that dw::fltk::FltkViewport::draw will distinguish between the two
+     cases?
+
+<li> For Scrolling, something similar applies, only parts of the viewport
+     have to be redrawn.
+
+<li> Also for Scrolling, it is necessary to copy parts of the window.
+
+<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 seems to work.
+
+<li> Who is responsable for clearing before drawing?
+
+<li> The embedded buttons are not redrawn, when pressing the mouse button
+     on them.
+
+<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.
+
+<li> In dw::fltk::FltkFont::FltkFont, fltk::measure does not seem to work
+     for the calculation of dw::core::style::Font::xHeight.
+
+<li> Distinction between italics and oblique would be nice
+     (dw::fltk::FltkFont::FltkFont).
+</ul>
+
+
+<h2>dw::fltk::ui::FltkCheckButtonResource</h2>
+
+Groups of fltk::RadioButton must be added to one fltk::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>Lower Priority</h2>
+
+There needs to be an XEmbed implementation.
+
+
+<h2>dw::fltk::ui::ComplexButton</h2>
+
+Unfortunately, FLTK does not provide a button with 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 fltk/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
+-#ifndef fltk_Widget_h
+-#include "Widget.h"
+-#endif
++#include <fltk/Group.h>
+\endcode
+
+and
+
+\code 
+-class FL_API ComplexButton : public Widget {
++class ComplexButton: public ::fltk::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 <fltk/events.h>
+ #include <fltk/damage.h>
+-#include <fltk/ComplexButton.h> // <fltk/Button.h> formerly
+ #include <fltk/Group.h>
+ #include <fltk/Box.h>
+ #include <stdlib.h>
++
++#include "fltkcomplexbutton.hh"
+\endcode
+
+Second, namespaces:
+
+\code
++using namespace dw::fltk::ui;
+ using namespace fltk;
+\endcode
+
+Since the base class is now Group, the constructor must be changed:
+
+\code
+-ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) : Widget(x,y,w,h,l) {
++ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) :
++   Group(x,y,w,h,l)
++{
+\endcode
+
+At the end of the constructor,
+
+\code
++  type (NORMAL);
+ }
+\endcode
+
+must be added (I've forgotten, what this is for).
+
+Finally, the button must draw its children (end of
+dw::fltk::ui::ComplexButton::draw()):
+
+\code
++
++  for (int i = 0; i < children (); i++)
++     draw_child (*child (i));
+ }
+\endcode
+
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/index.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -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> object::Object is a common base class for many classes used dillo. In
+     the namespace ::object, there are also some more common classes and
+     interfaces.
+
+<li> A sub class of object::Object is 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 ::signal.
+</ul>
+
+Hash tables, linked lists etc. can be found in the ::container namespace,
+several useful macros from GLib have been implemented as inline functions
+in the ::misc namespace.
+
+As an alternative to the macros defined in list.h, there is also a template
+class, 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.
+
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/lout.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,94 @@
+/** \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 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>object::Pointer
+<tr><td>specific pointer <td>object::TypedPointer (template class)
+<tr><td>int              <td>object::Integer
+<tr><td>const char*      <td>object::ConstString
+<tr><td>char*            <td>object::String
+</table>
+
+
+<h2>Containers</h2>
+
+In the namespace ::container, several container classes are defined,
+which all deal with instances of object::Object.
+
+<h3>Untyped Containers</h3>
+
+In container::untyped, there are the following containers:
+
+<ul>
+<li>container::untyped::Vector, a dynamically increases array,
+<li>container::untyped::List, a linked list,
+<li>container::untyped::HashTable, a hash table, and
+<li>container::untyped::Stack, a stack.
+</ul>
+
+All provide specific methods, but since they have a common base class,
+container::untyped::Collection, they all provide iterators, by the
+method container::untyped::Collection::iterator.
+
+<h3>Typed Containers</h3>
+
+container::typed provides wrappers for the container classes defined
+in 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 ::signal namespace.
+
+There is also a base class 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,
+identity::IdentifiableObject should be used as the base class, see
+there for more details.
+
+
+<h2>Miscellaneous</h2>
+
+The ::misc namespace provides several miscellaneous stuff:
+
+<ul>
+<li> In some contexts, it is necessary to compare objects
+     (less/greater), for this, also misc::Comparable must be
+     implemented. For example., container::untyped::Vector::sort and
+     container::typed::Vector::sort cast the elements to
+     misc::Comparable. This can be mixed with object::Object.
+<li> misc::SimpleVector, a simple, template based vector class (not
+     depending on object::Object),
+<li> misc::StringBuffer, class for fast concatenation of a large number
+     of strings,
+<li> misc::BitSet implements a bitset.
+<li> useful (template) functions (misc::min, misc::max), and
+<li> some functions useful for runtime checks (misc::assert,
+     misc::assertNotReached).
+</ul>
+
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/rounding-errors.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,24 @@
+/** \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} 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} y_j\f$ can be
+accumulated in the same loop.
+
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/uml-legend.doc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,192 @@
+/** \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", 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 Instanciations</h2>
+
+Template instanciations are shown as own classes/interfaces, the
+instanciation 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", 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", 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/Makefile.am	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,70 @@
+noinst_LIBRARIES = \
+	libDw-core.a \
+	libDw-fltk.a \
+	libDw-widgets.a
+
+libDw_core_a_SOURCES = \
+	core.hh \
+	events.hh \
+	findtext.cc \
+	findtext.hh \
+	imgbuf.hh \
+	iterator.cc \
+	iterator.hh \
+	layout.cc \
+	layout.hh \
+	platform.hh \
+	selection.hh \
+	selection.cc \
+	style.cc \
+	style.hh \
+	types.cc \
+	types.hh \
+	ui.cc \
+	ui.hh \
+	view.hh \
+	widget.cc \
+	widget.hh
+
+libDw_fltk_a_SOURCES = \
+	fltkcomplexbutton.cc \
+	fltkcomplexbutton.hh \
+	fltkcore.hh \
+	fltkflatview.cc \
+	fltkflatview.hh \
+	fltkimgbuf.cc \
+	fltkimgbuf.hh \
+	fltkmisc.cc \
+	fltkmisc.hh \
+	fltkplatform.cc \
+	fltkplatform.hh \
+	fltkpreview.hh \
+	fltkpreview.cc \
+	fltkui.cc \
+	fltkui.hh \
+	fltkviewbase.cc \
+	fltkviewbase.hh \
+	fltkviewport.cc \
+	fltkviewport.hh
+
+libDw_fltk_a_CXXFLAGS = @LIBFLTK_CXXFLAGS@
+
+libDw_widgets_a_SOURCES = \
+	alignedtextblock.cc \
+	alignedtextblock.hh \
+	bullet.cc \
+	bullet.hh \
+	image.cc \
+	image.hh \
+	listitem.cc \
+	listitem.hh \
+	ruler.cc \
+	ruler.hh \
+	table.cc \
+	table.hh \
+	tablecell.cc \
+	tablecell.hh \
+	textblock.cc \
+	textblock.hh
+
+EXTRA_DIST = preview.xbm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/alignedtextblock.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,105 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "alignedtextblock.hh"
+#include <stdio.h>
+
+namespace dw {
+
+AlignedTextblock::List::List ()
+{
+   textblocks = new misc::SimpleVector <AlignedTextblock*> (4);
+   values = new misc::SimpleVector <int> (4);
+   maxValue = 0;
+   refCount = 0;
+}
+
+AlignedTextblock::List::~List ()
+{
+   delete textblocks;
+   delete values;
+}
+
+int AlignedTextblock::List::add(AlignedTextblock *textblock)
+{
+   textblocks->increase ();
+   values->increase ();
+   textblocks->set (textblocks->size () - 1, textblock);
+   refCount++;
+   return textblocks->size () - 1;
+}
+
+void AlignedTextblock::List::unref(int pos)
+{
+   assert (textblocks->get (pos) != NULL);
+   textblocks->set (pos, NULL);
+   refCount--;
+
+   if(refCount == 0)
+      delete this;
+}
+
+int AlignedTextblock::CLASS_ID = -1;
+
+AlignedTextblock::AlignedTextblock (bool limitTextWidth):
+   Textblock (limitTextWidth)
+{
+   registerName ("dw::AlignedTextblock", &CLASS_ID);  
+}
+
+void AlignedTextblock::setRefTextblock (AlignedTextblock *ref)
+{
+   if(ref == NULL)
+      list = new List();
+   else
+      list = ref->list;
+
+   listPos = list->add (this);
+   updateValue ();
+}
+                                    
+AlignedTextblock::~AlignedTextblock()
+{
+   list->unref (listPos);
+}
+
+void AlignedTextblock::updateValue ()
+{
+   if (list) {
+      list->setValue (listPos, getValue ());
+      
+      if (list->getValue (listPos) > list->getMaxValue ()) {
+         // New value greater than current maximum -> apply it to others.
+         list->setMaxValue (list->getValue (listPos));
+
+         for (int i = 0; i < list->size (); i++)
+            if (list->getTextblock (i))
+               list->getTextblock (i)->setMaxValue (list->getMaxValue (),
+                                                    list->getValue (i));
+      } else {
+         /* No change, apply old max_value only to this page. */
+         setMaxValue (list->getMaxValue (), list->getValue (listPos));
+      }
+   }
+}
+
+} // namespace dw
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/alignedtextblock.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,61 @@
+#ifndef __DW_ALIGNEDTEXTBLOCK_HH__
+#define __DW_ALIGNEDTEXTBLOCK_HH__
+
+#include "core.hh"
+#include "textblock.hh"
+
+namespace dw {
+
+/**
+ * \brief Base widget for all textblocks (sub classes of dw::Textblock), which
+ *    are positioned vertically and aligned horizontally.
+ */
+class AlignedTextblock: public Textblock
+{
+private:
+   class List
+   {
+   private:
+      misc::SimpleVector <AlignedTextblock*> *textblocks;
+      misc::SimpleVector <int> *values;
+      int maxValue, refCount;
+
+      ~List ();
+
+   public:
+      List ();
+      inline int add (AlignedTextblock *textblock);
+      void unref (int pos);
+
+      inline int getMaxValue () { return maxValue; }
+      inline void setMaxValue (int maxValue) { this->maxValue = maxValue; }
+
+      inline int size () { return textblocks->size (); }
+      inline AlignedTextblock *getTextblock (int pos) {
+         return textblocks->get (pos); }
+      inline int getValue (int pos) {return values->get (pos); }
+      inline void setValue (int pos, int value) {
+         return values->set (pos, value); }
+   };
+
+   List *list;
+   int listPos;
+
+protected:
+   AlignedTextblock(bool limitTextWidth);
+
+   virtual int getValue () = 0;
+   virtual void setMaxValue (int maxValue, int value) = 0;
+
+   void setRefTextblock (AlignedTextblock *ref);
+   void updateValue ();
+
+public:
+   static int CLASS_ID;
+
+   ~AlignedTextblock();
+};
+
+} // namespace dw
+
+#endif // __DW_ALIGNEDTEXTBLOCK_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/bullet.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,72 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "bullet.hh"
+   
+#include <stdio.h>
+
+namespace dw {
+
+Bullet::Bullet ()
+{
+}
+
+void Bullet::sizeRequestImpl (core::Requisition *requisition)
+{
+   requisition->width = lout::misc::max (getStyle()->font->xHeight * 4 / 5, 1);
+   requisition->ascent = lout::misc::max (getStyle()->font->xHeight, 1);
+   requisition->descent = 0;
+}
+
+void Bullet::draw (core::View *view, core::Rectangle *area)
+{
+   int x, y, l;
+   bool filled = true;
+
+   l = lout::misc::min (allocation.width, allocation.ascent);
+   x = allocation.x;
+   y = allocation.y + allocation.ascent - getStyle()->font->xHeight;
+
+   switch (getStyle()->listStyleType) {
+   case core::style::LIST_STYLE_TYPE_SQUARE:
+      view->drawRectangle (getStyle()->color,
+                           core::style::Color::SHADING_NORMAL,
+                           false, x, y, l, l);
+      break;
+   case core::style::LIST_STYLE_TYPE_CIRCLE:
+      filled = false;
+      // Fall Through
+   case core::style::LIST_STYLE_TYPE_DISC:
+   default:
+      view->drawArc (getStyle()->color, core::style::Color::SHADING_NORMAL,
+                     filled, x, y, l, l, 0, 360);
+   }
+}
+
+core::Iterator *Bullet::iterator (core::Content::Type mask, bool atEnd)
+{
+   //return new core::TextIterator (this, mask, atEnd, "*");
+   /** \bug Not implemented. */
+   return new core::EmptyIterator (this, mask, atEnd);
+}
+
+} // namespace dw
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/bullet.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,27 @@
+#ifndef __BULLET_HH__
+#define __BULLET_HH__
+
+#include "core.hh"
+
+namespace dw {
+
+/**
+ * \brief Displays different kind of bullets.
+ *
+ * Perhaps, in the future, Unicode characters are used for bullets, so this
+ * widget is not used anymore.
+ */
+class Bullet: public core::Widget
+{
+protected:
+   void sizeRequestImpl (core::Requisition *requisition);
+   void draw (core::View *view, core::Rectangle *area);  
+   core::Iterator *iterator (core::Content::Type mask, bool atEnd); 
+
+public:
+   Bullet ();
+};
+
+} // namespace dw
+
+#endif // __BULLET_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/core.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,58 @@
+#ifndef __DW_CORE_HH__
+#define __DW_CORE_HH__
+
+#define __INCLUDED_FROM_DW_CORE_HH__
+
+/**
+ * \brief Dw is in this namespace, or sub namespaces of this one.
+ *
+ * The core can be found in dw::core, widgets are defined directly here.
+ *
+ * \sa \ref dw-overview
+ */
+namespace dw {
+
+/**
+ * \brief The core of Dw is defined in this namespace.
+ *
+ * \sa \ref dw-overview
+ */
+namespace core {
+
+typedef unsigned char byte;
+
+class Layout;
+class View;
+class Widget;
+class Iterator;
+
+namespace ui {
+
+class ResourceFactory;
+
+} // namespace ui
+
+
+} // namespace dw
+} // namespace core
+
+#include "../lout/object.hh"
+#include "../lout/container.hh"
+#include "../lout/signal.hh"
+
+#include "types.hh"
+#include "events.hh"
+#include "imgbuf.hh"
+#include "style.hh"
+#include "view.hh"
+#include "platform.hh"
+#include "iterator.hh"
+#include "findtext.hh"
+#include "selection.hh"
+#include "layout.hh"
+#include "widget.hh"
+#include "ui.hh"
+
+#undef __INCLUDED_FROM_DW_CORE_HH__
+
+#endif // __DW_CORE_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/events.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,83 @@
+#ifndef __DW_EVENTS_HH__
+#define __DW_EVENTS_HH__
+
+#ifndef __INCLUDED_FROM_DW_CORE_HH__
+#   error Do not include this file directly, use "core.hh" instead.
+#endif
+
+namespace dw {
+namespace core {
+
+/**
+ * \brief Platform independant representation.
+ */
+enum ButtonState
+{
+   /* We won't use more than these ones. */
+   SHIFT_MASK    = 1 << 0,
+   CONTROL_MASK  = 1 << 1,
+   META_MASK     = 1 << 2,
+   BUTTON1_MASK  = 1 << 3,
+   BUTTON2_MASK  = 1 << 4,
+   BUTTON3_MASK  = 1 << 5
+};
+
+/**
+ * \brief Base class for all events.
+ *
+ * The dw::core::Event hierarchy describes events in a platform independant
+ * way.
+ */
+class Event: public object::Object
+{
+public:
+};
+
+/**
+ * \brief Base class for all mouse events.
+ */
+class MouseEvent: public Event
+{
+public:
+   ButtonState state;
+};
+
+/**
+ * \brief Base class for all mouse events related to a specific position.
+ */
+class MousePositionEvent: public MouseEvent
+{
+public:
+   int xCanvas, yCanvas, xWidget, yWidget;
+};
+
+/**
+ * \brief Represents a button press or release event.
+ */
+class EventButton: public MousePositionEvent
+{
+public:
+   int numPressed; /* 1 for simple click, 2 for double click, etc. */
+   int button;
+};
+
+/**
+ * \brief Represents a mouse motion event.
+ */
+class EventMotion: public MousePositionEvent
+{
+};
+
+/**
+ * \brief Represents a enter or leave notify event.
+ */
+class EventCrossing: public MouseEvent
+{
+public:
+   Widget *lastWidget, *currentWidget;
+};
+
+} // namespace dw
+} // namespace core
+
+#endif // __DW_EVENTS_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/findtext.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,209 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "core.hh"
+
+namespace dw {
+namespace core {
+
+FindtextState::FindtextState ()
+{
+   key = NULL;
+   nexttab = NULL;
+   widget = NULL;
+   iterator = NULL;
+   hlIterator = NULL;
+}
+
+FindtextState::~FindtextState ()
+{
+   if (key)
+      delete key;
+   if (nexttab)
+      delete[] nexttab;
+   if (iterator)
+      delete iterator;
+   if (hlIterator)
+      delete hlIterator;
+}
+
+void FindtextState::setWidget (Widget *widget)
+{
+   this->widget = widget;
+
+   // A widget change will restart the search.
+   if (key)
+      delete key;
+   key = NULL;
+   if (nexttab)
+      delete[] nexttab;
+   nexttab = NULL;
+
+   if (iterator)
+      delete iterator;
+   iterator = NULL;
+   if (hlIterator)
+      delete hlIterator;
+   hlIterator = NULL;
+}
+
+FindtextState::Result FindtextState::search (const char *key, bool caseSens)
+{
+   if (!widget || *key == 0) // empty keys are not found
+      return NOT_FOUND;
+
+   bool wasHighlighted = unhighlight ();
+   bool newKey;
+   
+   // If the key (or the widget) changes (including case sensitivity),
+   // the search is started from the beginning.
+   if (this->key == NULL || this->caseSens != caseSens ||
+       strcmp (this->key, key) != 0) {
+      newKey = true;
+      if (this->key)
+         delete this->key;
+      this->key = strdup (key);
+      this->caseSens = caseSens;
+
+      if (nexttab)
+         delete[] nexttab;
+      nexttab = createNexttab (key, caseSens);
+      
+      if (iterator)
+         delete iterator;
+      iterator = new CharIterator (widget);
+      iterator->next ();
+   } else
+      newKey = false;
+
+   bool firstTrial = !wasHighlighted || newKey;
+
+   if (search0 ()) {
+      // Highlighlighting is done with a clone.
+      hlIterator = iterator->cloneCharIterator ();
+      for (int i = 0; key[i]; i++)
+         hlIterator->next ();
+      CharIterator::highlight (iterator, hlIterator, HIGHLIGHT_FINDTEXT);
+      CharIterator::scrollTo (iterator, hlIterator,
+                              HPOS_INTO_VIEW, VPOS_CENTER);
+
+      // The search will continue from the word after the found position.
+      iterator->next ();
+      return SUCCESS;
+   } else {
+      if (firstTrial)
+         return NOT_FOUND;
+      else {
+         // Nothing found anymore, reset the state for the next trial.
+         delete iterator;
+         iterator = new CharIterator (widget);
+         iterator->next ();
+         
+         // We expect a success.
+         Result result2 = search (key, caseSens);
+         assert (result2 == SUCCESS);
+         return RESTART;
+      }
+   }
+}
+
+/**
+ * \brief This method is called when the user closes the "find text" dialog.
+ */
+void FindtextState::resetSearch ()
+{
+   unhighlight ();
+
+   if (key)
+      delete key;
+   key = NULL;  
+}
+
+int *FindtextState::createNexttab (const char *key, bool caseSens)
+{
+   int i = 0;
+   int j = -1;
+   int l = strlen (key);
+   int *nexttab = new int[l + 1]; // + 1 is necessary for l == 1 case
+   nexttab[0] = -1;
+
+   do {
+      if (j == -1 || charsEqual (key[i], key[j], caseSens)) {
+         i++;
+         j++;
+         nexttab[i] = j;
+         //_MSG ("nexttab[%d] = %d\n", i, j);
+      } else
+         j = nexttab[j];
+   } while (i < l - 1);
+
+   return nexttab;
+}
+
+/**
+ * \brief Unhighlight, and return whether a region was highlighted.
+ */
+bool FindtextState::unhighlight ()
+{
+   if (hlIterator) {
+      CharIterator *start = hlIterator->cloneCharIterator ();
+      for (int i = 0; key[i]; i++)
+         start->prev ();
+
+      CharIterator::unhighlight (start, hlIterator, HIGHLIGHT_FINDTEXT);
+      delete start;
+      delete hlIterator;
+      hlIterator = NULL;
+
+      return true;
+   } else
+      return false;
+}
+
+bool FindtextState::search0 ()
+{
+   if (iterator->getChar () == CharIterator::END)
+      return false;
+
+   int j = 0;
+   bool nextit = true;
+   int l = strlen (key);
+
+   do {
+      if (j == -1 || charsEqual (iterator->getChar (), key[j], caseSens)) {
+         j++;
+         nextit = iterator->next ();
+      } else
+         j = nexttab[j];
+   } while (nextit && j < l);
+   
+   if (j >= l) {
+      // Go back to where the word was found.
+      for (int i = 0; i < l; i++)
+         iterator->prev ();
+      return true;
+   } else
+      return false;
+}
+
+} // namespace dw
+} // namespace core
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/findtext.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,82 @@
+#ifndef __DW_FINDTEXT_STATE_H__
+#define __DW_FINDTEXT_STATE_H__
+
+#ifndef __INCLUDED_FROM_DW_CORE_HH__
+#   error Do not include this file directly, use "core.hh" instead.
+#endif
+
+#include <ctype.h>
+
+namespace dw {
+namespace core {
+
+class FindtextState
+{
+public:
+   typedef enum {
+      /** \brief The next occurance of the pattern has been found. */
+      SUCCESS,
+
+      /**
+       * \brief There is no further occurance of the pattern, instead, the
+       *    first occurance has been selected.
+       */
+      RESTART,
+
+      /** \brief The patten does not at all occur in the text. */
+      NOT_FOUND
+   } Result;
+
+private:
+   /**
+    * \brief The key used for the last search.
+    *
+    * If dw::core::Findtext::search is called with the same key, the search
+    * is continued, otherwise it is restarted.
+    */
+   char *key;
+
+   /** \brief Whether the last search was case sensitive. */
+   bool caseSens;
+
+   /** \brief The table used for KMP search. */
+   int *nexttab;
+
+   /** \brief The top of the widget tree, in which the search is done.
+    *
+    * From this, the iterator will be constructed. Set by
+    * dw::core::Findtext::widget
+    */
+   Widget *widget;
+   
+   /** \brief The position from where the next search will start. */
+   CharIterator *iterator;
+
+   /**
+    * \brief The position from where the characters are highlighted.
+    * 
+    * NULL, when no text is highlighted.
+    */
+   CharIterator *hlIterator;  
+
+   static int *createNexttab (const char *key, bool caseSens);
+   bool unhighlight ();
+   bool search0 ();
+
+   inline static bool charsEqual (char c1, char c2, bool caseSens)
+   { return caseSens ? c1 == c2 : tolower (c1) == tolower (c2) ||
+      isspace (c1) && isspace (c2); }
+
+public:
+   FindtextState ();
+   ~FindtextState ();
+
+   void setWidget (Widget *widget);
+   Result search (const char *key, bool caseSens);
+   void resetSearch ();
+};
+
+} // namespace dw
+} // namespace core
+
+#endif // __DW_FINDTEXT_STATE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkcomplexbutton.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,282 @@
+//
+//
+// Copyright 1998-2006 by Bill Spitzak and others.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+//
+// Please report all bugs and problems to "fltk-bugs@fltk.org".
+//
+
+#include <fltk/events.h>
+#include <fltk/damage.h>
+#include <fltk/Group.h>
+#include <fltk/Box.h>
+#include <stdlib.h>
+
+#include "fltkcomplexbutton.hh"
+
+using namespace fltk;
+using namespace dw::fltk::ui;
+
+/*! \class fltk::ComplexButton
+
+  ComplexButtons generate callbacks when they are clicked by the user. You
+  control exactly when and how by changing the values for when():
+  - fltk::WHEN_NEVER: The callback is not done, instead changed() is
+    turned on.
+  - fltk::WHEN_RELEASE: This is the default, the callback is done
+    after the user successfully clicks the button (i.e. they let it go
+    with the mouse still pointing at it), or when a shortcut is typed.
+  - fltk::WHEN_CHANGED : The callback is done each time the value()
+    changes (when the user pushes and releases the button, and as the
+    mouse is dragged around in and out of the button).
+
+  ComplexButtons can also generate callbacks in response to fltk::SHORTCUT
+  events. The button can either have an explicit shortcut() value or a
+  letter shortcut can be indicated in the label() with an '&'
+  character before it. For the label shortcut it does not matter if
+  Alt is held down, but if you have an input field in the same window,
+  the user will have to hold down the Alt key so that the input field
+  does not eat the event first as an fltk::KEY event.
+
+  \image html buttons.gif
+*/
+
+/*! \fn bool ComplexButton::value() const
+  The current value. True means it is pushed down, false means it is
+  not pushed down. The ToggleComplexButton subclass provides the ability for
+  the user to change this value permanently, otherwise it is just
+  temporary while the user is holding the button down.
+
+  This is the same as Widget::state().
+*/
+
+/*! \fn bool ComplexButton::value(bool)
+  Change the value(). Redraws the button and returns true if the new
+  value is different. This is the same function as Widget::state().
+  See also Widget::set(), Widget::clear(), and Widget::setonly().
+
+  If you turn it on, a normal button will draw pushed-in, until
+  the user clicks it and releases it.
+*/
+
+static bool initial_state;
+
+int ComplexButton::handle(int event) {
+  return handle(event, Rectangle(w(),h()));
+}
+
+int ComplexButton::handle(int event, const Rectangle& rectangle) {
+  switch (event) {
+  case ENTER:
+  case LEAVE:
+    redraw_highlight();
+  case MOVE:
+    return 1;
+  case PUSH:
+    if (pushed()) return 1; // ignore extra pushes on currently-pushed button
+    initial_state = state();
+    clear_flag(PUSHED);
+    do_callback();
+  case DRAG: {
+    bool inside = event_inside(rectangle);
+    if (inside) {
+      if (!flag(PUSHED)) {
+        set_flag(PUSHED);
+        redraw(DAMAGE_VALUE);
+      }
+    } else {
+      if (flag(PUSHED)) {
+        clear_flag(PUSHED);
+        redraw(DAMAGE_VALUE);
+      }
+    }
+    if (when() & WHEN_CHANGED) { // momentary button must record state()
+      if (state(inside ? !initial_state : initial_state))
+        do_callback();
+    }
+    return 1;}
+  case RELEASE:
+    if (!flag(PUSHED)) return 1;
+    clear_flag(PUSHED);
+    redraw(DAMAGE_VALUE);
+    if (type() == RADIO)
+      setonly();
+    else if (type()) // TOGGLE
+      state(!initial_state);
+    else {
+      state(initial_state);
+      if (when() & WHEN_CHANGED) {do_callback(); return 1;}
+    }
+    if (when() & WHEN_RELEASE) do_callback(); else set_changed();
+    return 1;
+  case FOCUS:
+    redraw(1); // minimal redraw to just add the focus box
+    // grab initial focus if we are an ReturnComplexButton:
+    return shortcut()==ReturnKey ? 2 : 1;
+  case UNFOCUS:
+    redraw(DAMAGE_HIGHLIGHT);
+    return 1;
+  case KEY:
+    if (event_key() == ' ' || event_key() == ReturnKey
+        || event_key() == KeypadEnter) goto EXECUTE;
+    return 0;
+  case SHORTCUT:
+    if (!test_shortcut()) return 0;
+  EXECUTE:
+    if (type() == RADIO) {
+      if (!state()) {
+        setonly();
+        if (when() & WHEN_CHANGED) do_callback(); else set_changed();
+      }
+    } else if (type()) { // TOGGLE
+      state(!state());
+      if (when() & WHEN_CHANGED) do_callback(); else set_changed();
+    }
+    if (when() & WHEN_RELEASE) do_callback();
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+////////////////////////////////////////////////////////////////
+
+#include <fltk/draw.h>
+
+extern Widget* fl_did_clipping;
+
+/*!
+  This function provides a mess of back-compatabilty and Windows
+  emulation to subclasses of ComplexButton to draw with. It will draw the
+  button according to the current state of being pushed and it's
+  state(). If non-zero is passed for \a glyph_width then the glyph()
+  is drawn in that space on the left (or on the right if negative),
+  and it assummes the glyph indicates the state(), so the box is only
+  used to indicate the pushed state.
+*/
+void ComplexButton::draw(int glyph_width) const
+{
+  // For back-compatability, setting color() or box() directly on a plain
+  // button will cause it to act like buttoncolor() or buttonbox() are
+  // set:
+  Style localstyle;
+  const Style* style = this->style();
+  if (!glyph_width) {
+    localstyle = *style;
+    if (localstyle.color_) localstyle.buttoncolor_ = localstyle.color_;
+    if (localstyle.box_) localstyle.buttonbox_ = localstyle.box_;
+    if (localstyle.labelcolor_) localstyle.textcolor_ = localstyle.labelcolor_;
+    style = &localstyle;
+  }
+
+  Box* box = style->buttonbox();
+
+  Flags box_flags = flags() | OUTPUT;
+  Flags glyph_flags = box_flags & ~(HIGHLIGHT|OUTPUT);
+  if (glyph_width) box_flags &= ~STATE;
+
+  // only draw "inside" labels:
+  Rectangle r(0,0,w(),h());
+
+  if (box == NO_BOX) {
+    Color bg;
+    if (box_flags & HIGHLIGHT && (bg = style->highlight_color())) {
+      setcolor(bg);
+      fillrect(r);
+    } else if (label() || (damage()&(DAMAGE_EXPOSE|DAMAGE_HIGHLIGHT))) {
+      // erase the background so we can redraw the label in the new color:
+      draw_background();
+    }
+    // this allows these buttons to be put into browser/menus:
+    //fg = fl_item_labelcolor(this);
+  } else {
+    if ((damage()&(DAMAGE_EXPOSE|DAMAGE_HIGHLIGHT))
+        && !box->fills_rectangle()) {
+      // Erase the area behind non-square boxes
+      draw_background();
+    }
+  }
+
+  // Draw the box:
+  drawstyle(style,box_flags);
+  // For back-compatability we use any directly-set selection_color()
+  // to color the box:
+  if (!glyph_width && state() && style->selection_color_) {
+    setbgcolor(style->selection_color_);
+    setcolor(contrast(style->selection_textcolor(),style->selection_color_));
+  }
+  box->draw(r);
+  Rectangle r1(r); box->inset(r1);
+
+  if (glyph_width) {
+    int g = abs(glyph_width);
+    Rectangle lr(r1);
+    Rectangle gr(r1, g, g);
+    if (glyph_width < 0) {
+      lr.w(lr.w()-g-3);
+      gr.x(r1.r()-g-3);
+    } else {
+      lr.set_x(g+3);
+      gr.x(r1.x()+3);
+    }
+    this->draw_label(lr, box_flags);
+    drawstyle(style,glyph_flags);
+    this->glyph()->draw(gr);
+    drawstyle(style,box_flags);
+  } else {
+    this->draw_label(r1, box_flags);
+  }
+  box->draw_symbol_overlay(r);
+}
+
+void ComplexButton::draw() {
+  if (type() == HIDDEN) {
+    fl_did_clipping = this;
+    return;
+  }
+  draw(0);
+
+  // ComplexButton is a Group, draw its children
+  for (int i = children () - 1; i >= 0; i--)
+     draw_child (*child (i));
+}
+
+////////////////////////////////////////////////////////////////
+
+static NamedStyle style("ComplexButton", 0, &ComplexButton::default_style);
+NamedStyle* ComplexButton::default_style = &::style;
+
+ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) :
+   Group(x,y,w,h,l)
+{
+  style(default_style);
+  highlight_color(GRAY20);
+  //set_click_to_focus();
+}
+
+////////////////////////////////////////////////////////////////
+
+/*! \class fltk::ToggleComplexButton
+  This button turns the state() on and off each release of a click
+  inside of it.
+
+  You can also convert a regular button into this by doing
+  type(ComplexButton::TOGGLE) to it.
+*/
+
+//
+//
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkcomplexbutton.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,59 @@
+//
+//
+// Push button widget
+//
+// Copyright 2002 by Bill Spitzak and others.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+//
+// Please report all bugs and problems to "fltk-bugs@fltk.org".
+//
+
+#ifndef __FLTK_COMPLEX_BUTTON_HH__
+#define __FLTK_COMPLEX_BUTTON_HH__
+
+#include <fltk/Group.h>
+
+namespace dw {
+namespace fltk {
+namespace ui {
+
+class ComplexButton: public ::fltk::Group
+{
+public:
+  enum {HIDDEN=3}; // back-comptability value to hide the button
+
+  bool  value() const { return state(); }
+  bool  value(bool v) { return state(v); }
+
+  int handle(int);
+  int handle(int event, const Rectangle&);
+  ComplexButton(int,int,int,int,const char * = 0);
+  ~ComplexButton() { remove_all ();};
+  static ::fltk::NamedStyle* default_style;
+
+  virtual void draw();
+  void draw(int glyph_width) const;
+};
+
+} // namespace ui
+} // namespace fltk
+} // namespace dw
+
+#endif // __FLTK_COMPLEX_BUTTON_HH__
+
+//
+//
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkcore.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,25 @@
+#ifndef __DW_FLTK_CORE_HH__
+#define __DW_FLTK_CORE_HH__
+
+#define __INCLUDED_FROM_DW_FLTK_CORE_HH__
+
+namespace dw {
+namespace fltk {
+namespace ui {
+
+class FltkResource;
+
+} // namespace ui
+} // namespace fltk
+} // namespace core
+
+#include <fltk/Widget.h>
+
+#include "core.hh"
+#include "fltkimgbuf.hh"
+#include "fltkplatform.hh"
+#include "fltkui.hh"
+
+#undef __INCLUDED_FROM_DW_FLTK_CORE_HH__
+
+#endif // __DW_FLTK_CORE_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkflatview.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,108 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "fltkflatview.hh"
+
+#include <fltk/draw.h>
+#include <fltk/events.h>
+
+#include <stdio.h>
+
+using namespace fltk;
+using namespace lout::container::typed;
+
+namespace dw {
+namespace fltk {
+
+FltkFlatView::FltkFlatView (int x, int y, int w, int h, const char *label):
+   FltkWidgetView (x, y, w, h, label)
+{
+}
+
+FltkFlatView::~FltkFlatView ()
+{
+}
+
+void FltkFlatView::setCanvasSize (int width, int ascent, int descent)
+{
+   /**
+    * \bug It has to be clarified, who is responsible for setting the
+    *      FLTK widget size. In the only used context (complex buttons),
+    *      it is done elsewhere.
+    */
+
+#if 0
+   FltkWidgetView::setCanvasSize (width, ascent, descent);
+   
+   w (width);
+   h (ascent + descent);
+#endif
+}
+
+bool FltkFlatView::usesViewport ()
+{
+   return false;
+}
+
+int FltkFlatView::getHScrollbarThickness ()
+{
+   return 0;
+}
+
+int FltkFlatView::getVScrollbarThickness ()
+{
+   return 0;
+}
+
+void FltkFlatView::scrollTo (int x, int y)
+{
+}
+
+void FltkFlatView::setViewportSize (int width, int height,
+                                    int hScrollbarThickness,
+                                    int vScrollbarThickness)
+{
+}
+
+int FltkFlatView::translateViewXToCanvasX (int x)
+{
+   return x;
+}
+
+int FltkFlatView::translateViewYToCanvasY (int y)
+{
+   return y;
+}
+
+int FltkFlatView::translateCanvasXToViewX (int x)
+{
+   return x;
+}
+
+int FltkFlatView::translateCanvasYToViewY (int y)
+{
+   return y;
+}
+
+
+} // namespace fltk
+} // namespace dw
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkflatview.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,40 @@
+#ifndef __DW_FLTKFLATVIEW_HH__
+#define __DW_FLTKFLATVIEW_HH__
+
+#include <fltk/Group.h>
+#include <fltk/Scrollbar.h>
+
+#include "core.hh"
+#include "fltkcore.hh"
+#include "fltkviewbase.hh"
+
+namespace dw {
+namespace fltk {
+
+class FltkFlatView: public FltkWidgetView
+{
+protected:
+   int translateViewXToCanvasX (int x);
+   int translateViewYToCanvasY (int y);
+   int translateCanvasXToViewX (int x);
+   int translateCanvasYToViewY (int y);
+
+public:
+   FltkFlatView (int x, int y, int w, int h, const char *label = 0);
+   ~FltkFlatView ();
+ 
+   void setCanvasSize (int width, int ascent, int descent);
+
+   bool usesViewport ();
+   int getHScrollbarThickness ();
+   int getVScrollbarThickness ();
+   void scrollTo (int x, int y);
+   void setViewportSize (int width, int height,
+                         int hScrollbarThickness, int vScrollbarThickness);
+};
+
+} // namespace fltk
+} // namespace dw
+
+#endif // __DW_FLTKFLATVIEW_HH__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkimgbuf.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,347 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "fltkcore.hh"
+#include "../lout/misc.hh"
+
+#include <fltk/draw.h>
+#include <fltk/Color.h>
+
+using namespace fltk;
+
+namespace dw {
+namespace fltk {
+
+using namespace container::typed;
+
+FltkImgbuf::FltkImgbuf (Type type, int width, int height)
+{
+   //printf("FltkImgbuf: new root %p\n", this);
+   init (type, width, height, NULL);
+}
+
+FltkImgbuf::FltkImgbuf (Type type, int width, int height, FltkImgbuf *root)
+{
+   //printf("FltkImgbuf: new scaled %p, root is %p\n", this, root);
+   init (type, width, height, root);
+}
+
+void FltkImgbuf::init (Type type, int width, int height, FltkImgbuf *root)
+{
+   this->root = root;
+   this->type = type;
+   this->width = width;
+   this->height = height;
+
+   // TODO: Maybe this is only for root buffers
+   switch (type) {
+      case RGBA: bpp = 4; break;
+      case RGB:  bpp = 3; break;
+      default:   bpp = 1; break;
+   }
+   //fprintf(stderr,"FltkImgbuf::init width=%d height=%d bpp=%d\n",
+   //        width, height, bpp);
+   rawdata = new uchar[bpp * width * height];
+   // Set light-gray as interim background color.
+   memset(rawdata, 222, width*height*bpp);
+
+   refCount = 1;
+   deleteOnUnref = true;
+   copiedRows = new misc::BitSet (height);
+
+   // The list is only used for root buffers.
+   if (isRoot())
+      scaledBuffers = new container::typed::List <FltkImgbuf> (true);
+   else
+      scaledBuffers = NULL;
+
+   if (!isRoot()) {
+      // Scaling
+      for (int row = 0; row < root->height; row++) {
+         if (root->copiedRows->get (row))
+            scaleRow (row, root->rawdata + row*root->width*root->bpp);
+      }
+   }
+}
+
+FltkImgbuf::~FltkImgbuf ()
+{
+   //printf ("FltkImgbuf::~FltkImgbuf (%s)\n", isRoot() ? "root" : "scaled");
+
+   //if (root)
+   //   printf("FltkImgbuf[scaled %p, root is %p]: deleted\n", this, root);
+   //else
+   //   printf("FltkImgbuf[root %p]: deleted\n", this);
+
+   if (!isRoot())
+      root->detachScaledBuf (this);
+
+   delete[] rawdata;
+   delete copiedRows;
+
+   if (scaledBuffers)
+      delete scaledBuffers;
+}
+
+/**
+ * \brief This method is called for the root buffer, when a scaled buffer
+ *    removed.
+ */
+void FltkImgbuf::detachScaledBuf (FltkImgbuf *scaledBuf)
+{
+   scaledBuffers->detachRef (scaledBuf);
+
+   //printf("FltkImgbuf[root %p]: scaled buffer %p is detached, %d left\n",
+   //       this, scaledBuf, scaledBuffers->size ());
+
+   if (refCount == 0 && scaledBuffers->isEmpty () && deleteOnUnref)
+      // If the root buffer is not used anymore, but this is the last scaled
+      // buffer.
+      // See also: FltkImgbuf::unref().
+      delete this;
+}
+
+void FltkImgbuf::setCMap (int *colors, int num_colors)
+{
+}
+
+inline void FltkImgbuf::scaleRow (int row, const core::byte *data)
+{
+   int sr1 = scaledY (row);
+   int sr2 = scaledY (row + 1);
+   
+   for(int sr = sr1; sr < sr2; sr++) {
+      // Avoid multiple passes.
+      if (copiedRows->get(sr)) continue;
+
+      copiedRows->set (sr, true);
+      if (sr == sr1) {
+         for(int px = 0; px < root->width; px++) {
+            int px1 = px * width / root->width;
+            int px2 = (px+1) * width / root->width;
+            for(int sp = px1; sp < px2; sp++) {
+               memcpy(rawdata + (sr*width + sp)*bpp, data + px*bpp, bpp);
+            }
+         }
+      } else {
+         memcpy(rawdata + sr*width*bpp, rawdata + sr1*width*bpp, width*bpp);
+      }
+   }
+}
+
+void FltkImgbuf::copyRow (int row, const core::byte *data)
+{
+   assert (isRoot());
+
+   // Flag the row done and copy its data.
+   copiedRows->set (row, true);
+   memcpy(rawdata + row * width * bpp, data, width * bpp);
+
+   // Update all the scaled buffers of this root image.
+   for (Iterator <FltkImgbuf> it = scaledBuffers->iterator(); it.hasNext(); ) {
+      FltkImgbuf *sb = it.getNext ();
+      sb->scaleRow(row, data);
+   }
+}
+
+void FltkImgbuf::newScan ()
+{
+   if (isRoot()) {
+      for (Iterator<FltkImgbuf> it = scaledBuffers->iterator(); it.hasNext();){
+         FltkImgbuf *sb = it.getNext ();
+         sb->copiedRows->clear();       
+      }
+   }
+}
+
+core::Imgbuf* FltkImgbuf::getScaledBuf (int width, int height)
+{
+   if (root)
+      return root->getScaledBuf (width, height);
+   
+   if (width == this->width && height == this->height) {
+      ref ();
+      return this;
+   }
+
+   for (Iterator <FltkImgbuf> it = scaledBuffers->iterator(); it.hasNext(); ) {
+      FltkImgbuf *sb = it.getNext ();
+      if (sb->width == width && sb->height == height) {
+         sb->ref ();
+         return sb;
+      }
+   }
+
+   /* This size is not yet used, so a new buffer has to be created. */
+   FltkImgbuf *sb = new FltkImgbuf (type, width, height, this);
+   scaledBuffers->append (sb);
+   return sb;
+}
+
+void FltkImgbuf::getRowArea (int row, dw::core::Rectangle *area)
+{
+   // TODO: May have to be adjusted.
+
+   if (isRoot()) {
+      /* root buffer */
+      area->x = 0;
+      area->y = row;
+      area->width = width;
+      area->height = 1;
+      //fprintf(stderr,"::getRowArea: area x=%d y=%d width=%d height=%d\n",
+      //        area->x, area->y, area->width, area->height);
+   } else {
+      // scaled buffer
+      int sr1 = scaledY (row);
+      int sr2 = scaledY (row + 1);
+
+      area->x = 0;
+      area->y = sr1;
+      area->width = width;
+      area->height = sr2 - sr1;
+      //fprintf(stderr,"::getRowArea: area x=%d y=%d width=%d height=%d\n",
+      //        area->x, area->y, area->width, area->height);
+   }
+}
+
+int  FltkImgbuf::getRootWidth ()
+{
+   return root ? root->width : width;
+}
+
+int  FltkImgbuf::getRootHeight ()
+{
+   return root ? root->height : height;
+}
+
+void FltkImgbuf::ref ()
+{
+   refCount++;
+
+   //if (root)
+   //   printf("FltkImgbuf[scaled %p, root is %p]: ref() => %d\n",
+   //          this, root, refCount);
+   //else
+   //   printf("FltkImgbuf[root %p]: ref() => %d\n", this, refCount);
+}
+
+void FltkImgbuf::unref ()
+{
+   //if (root)
+   //   printf("FltkImgbuf[scaled %p, root is %p]: ref() => %d\n",
+   //          this, root, refCount - 1);
+   //else
+   //   printf("FltkImgbuf[root %p]: ref() => %d\n", this, refCount - 1);
+
+   if (--refCount == 0) {
+      if (isRoot ()) {
+         // Root buffer, it must be ensured that no scaled buffers are left.
+         // See also FltkImgbuf::detachScaledBuf().
+         if (scaledBuffers->isEmpty () && deleteOnUnref)
+            delete this;
+         else
+            printf("FltkImgbuf[root %p]: not deleted\n", this);
+      } else
+         // Scaled buffer buffer, simply delete it.
+         delete this;
+   }
+}
+
+bool FltkImgbuf::lastReference ()
+{
+   return refCount == 1 && 
+      (scaledBuffers == NULL || scaledBuffers->isEmpty ());
+}
+
+void FltkImgbuf::setDeleteOnUnref (bool deleteOnUnref)
+{
+   assert (isRoot ());
+   this->deleteOnUnref = deleteOnUnref;
+}
+
+bool FltkImgbuf::isReferred ()
+{
+   return refCount != 0 ||
+      (scaledBuffers != NULL && !scaledBuffers->isEmpty ());
+}
+
+
+int FltkImgbuf::scaledY(int ySrc)
+{
+   // TODO: May have to be adjusted.
+   assert (root != NULL);
+   return ySrc * height / root->height;
+}
+
+void FltkImgbuf::draw (::fltk::Widget *target, int xRoot, int yRoot,
+                   int x, int y, int width, int height)
+{
+   // TODO (i):  Implementation.
+   // TODO (ii): Clarify the question, whether "target" is the current widget
+   //            (and so has not to be passed at all).
+
+/*
+   setcolor (0);
+
+   for (int row = y; row < y + height; row++) {
+      if (copiedRows->get (row)) {
+         ::fltk::Rectangle rect (x + xRoot, row + yRoot, width, 1);
+         fillrect (rect);
+      }
+   }
+*/
+
+   //fprintf(stderr,"::draw: xRoot=%d x=%d yRoot=%d y=%d width=%d height=%d\n"
+   //        "        this->width=%d this->height=%d\n",
+   //        xRoot, x, yRoot, y, width, height, this->width, this->height);
+
+//{
+#if 1
+   if (x > this->width || y > this->height) {
+      return;
+   }
+
+   if (x + width > this->width) {
+      width = this->width - x;
+   }
+
+   if (y + height > this->height) {
+      height = this->height - y;
+   }
+
+   // almost OK for rows. For some unknown reason it trims the bottom and 
+   // rightmost parts when scrolling.
+   ::fltk::Rectangle rect (xRoot + x, yRoot + y, width, height);
+   PixelType ptype = (type == RGBA) ? ::fltk::RGBA : ::fltk::RGB;
+   drawimage(rawdata+bpp*(y*this->width + x),ptype,rect,bpp*this->width);
+
+#else
+   // OK for full image.
+   ::fltk::Rectangle rect (xRoot, yRoot, this->width, this->height);
+   PixelType ptype = (type == RGBA) ? ::fltk::RGBA : ::fltk::RGB;
+   drawimage(rawdata,ptype,rect);
+#endif
+//}
+}
+
+} // namespace dw
+} // namespace fltk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkimgbuf.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,65 @@
+#ifndef __DW_FLTKIMGBUF_HH__
+#define __DW_FLTKIMGBUF_HH__
+
+#ifndef __INCLUDED_FROM_DW_FLTK_CORE_HH__
+#   error Do not include this file directly, use "fltkcore.hh" instead.
+#endif
+
+namespace dw {
+namespace fltk {
+
+class FltkImgbuf: public core::Imgbuf
+{
+private:
+   FltkImgbuf *root;
+   int refCount;
+   bool deleteOnUnref;
+   lout::container::typed::List <FltkImgbuf> *scaledBuffers;
+
+   int width, height;
+   Type type;
+
+//{
+   int bpp;
+   uchar *rawdata;
+//}
+
+   // This is just for testing drawing, it has to be replaced by
+   // the image buffer.
+   lout::misc::BitSet *copiedRows;
+
+   FltkImgbuf (Type type, int width, int height, FltkImgbuf *root);
+   void init (Type type, int width, int height, FltkImgbuf *root);
+   int scaledY(int ySrc);
+   int isRoot() { return (root == NULL); }
+   void detachScaledBuf (FltkImgbuf *scaledBuf);
+
+protected:
+   ~FltkImgbuf ();
+
+public:
+   FltkImgbuf (Type type, int width, int height);
+
+   void setCMap (int *colors, int num_colors);
+   inline void scaleRow (int row, const core::byte *data);
+   void newScan ();
+   void copyRow (int row, const core::byte *data);
+   core::Imgbuf* getScaledBuf (int width, int height);
+   void getRowArea (int row, dw::core::Rectangle *area);
+   int  getRootWidth ();
+   int  getRootHeight ();
+   void ref ();
+   void unref ();
+
+   bool lastReference ();
+   void setDeleteOnUnref (bool deleteOnUnref);
+   bool isReferred ();
+
+   void draw (::fltk::Widget *target, int xRoot, int yRoot,
+              int x, int y, int width, int height);
+};
+
+} // namespace dw
+} // namespace fltk
+
+#endif // __DW_FLTK_IMGBUF_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkmisc.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,50 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "fltkmisc.hh"
+
+#include <fltk/events.h>
+#include <fltk/Monitor.h>
+#include <stdio.h>
+
+namespace dw {
+namespace fltk {
+namespace misc {
+
+int screenWidth ()
+{
+   return ::fltk::Monitor::all ().w ();
+}
+
+int screenHeight ()
+{
+   return ::fltk::Monitor::all ().h ();
+}
+
+void warpPointer (int x, int y)
+{
+   ::fltk::warp_mouse (x, y);
+}
+
+} // namespace misc
+} // namespace fltk
+} // namespace dw
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkmisc.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,22 @@
+#ifndef __FLTKMISC_HH__
+#define __FLTKMISC_HH__
+
+namespace dw {
+namespace fltk {
+
+/**
+ * \brief Miscellaneous FLTK stuff.
+ */
+namespace misc {
+
+int screenWidth ();
+int screenHeight ();
+
+void warpPointer (int x, int y);
+
+} // namespace misc
+} // namespace fltk
+} // namespace dw
+
+
+#endif // __FLTKMISC_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkplatform.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,421 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "fltkcore.hh"
+
+#include <fltk/draw.h>
+#include <fltk/run.h>
+#include <fltk/events.h>
+#include <fltk/utf.h>
+#include <stdio.h>
+
+namespace dw {
+namespace fltk {
+
+using namespace ::fltk;
+
+/**
+ * \todo Distinction between italics and oblique would be nice.
+ */
+
+container::typed::HashTable <dw::core::style::FontAttrs,
+                             FltkFont> *FltkFont::fontsTable =
+   new container::typed::HashTable <dw::core::style::FontAttrs,
+                                    FltkFont> (false, false);
+
+FltkFont::FltkFont (core::style::FontAttrs *attrs)
+{
+   copyAttrs (attrs);
+
+   int fa = 0;
+   if(weight >= 500)
+      fa |= BOLD;
+   if(style != core::style::FONT_STYLE_NORMAL)
+      fa  |= ITALIC;
+
+   font = ::fltk::font(name, fa);
+   if(font == NULL) {
+      fprintf(stderr, "No font '%s', using default sans-serif font.\n", name);
+      /*
+       * If using xft, fltk::HELVETICA just means sans, fltk::COURIER
+       * means mono, and fltk::TIMES means serif.
+       */
+      font = HELVETICA;
+   }      
+
+   setfont(font, size);
+   spaceWidth = (int)getwidth(" ");
+   int xw, xh;
+   measure("x", xw, xh);
+   xHeight = xh;
+   ascent = (int)getascent();
+   descent = (int)getdescent();
+
+   /**
+    * \bug The code above does not seem to work, so this workaround.
+    */
+   xHeight = ascent * 3 / 5;
+}
+
+FltkFont::~FltkFont ()
+{
+   fontsTable->remove (this);
+}
+
+FltkFont*
+FltkFont::create (core::style::FontAttrs *attrs)
+{
+   FltkFont *font = fontsTable->get (attrs);
+
+   if (font == NULL) {
+      font = new FltkFont (attrs);
+      fontsTable->put (font, font);
+   }
+
+   return font;
+}
+
+container::typed::HashTable <dw::core::style::ColorAttrs,
+                             FltkColor>
+   *FltkColor::colorsTable =
+      new container::typed::HashTable <dw::core::style::ColorAttrs,
+                                       FltkColor> (false, false);
+
+FltkColor::FltkColor (int color, core::style::Color::Type type):
+   Color (color, type)
+{
+   this->color = color;
+   this->type = type;
+
+   /*
+    * fltk/setcolor.cxx:
+    * "A Color of zero (fltk::NO_COLOR) will draw black but is
+    * ambiguous. It is returned as an error value or to indicate portions
+    * of a Style that should be inherited, and it is also used as the
+    * default label color for everything so that changing color zero can
+    * be used by the -fg switch. You should use fltk::BLACK (56) to get
+    * black."
+    *
+    * i.e., zero only works sometimes.
+    */
+
+   if (!(colors[SHADING_NORMAL] = shadeColor (color, SHADING_NORMAL) << 8))
+      colors[SHADING_NORMAL] = ::fltk::BLACK;
+   if (!(colors[SHADING_INVERSE] = shadeColor (color, SHADING_INVERSE) << 8))
+      colors[SHADING_INVERSE] = ::fltk::BLACK;
+
+   if(type == core::style::Color::TYPE_SHADED) {
+      if (!(colors[SHADING_DARK] = shadeColor (color, SHADING_DARK) << 8))
+         colors[SHADING_DARK] = ::fltk::BLACK;
+      if (!(colors[SHADING_LIGHT] = shadeColor (color, SHADING_LIGHT) << 8))
+         colors[SHADING_LIGHT] = ::fltk::BLACK;
+   }
+}
+
+FltkColor::~FltkColor ()
+{
+   colorsTable->remove (this);
+}
+
+FltkColor * FltkColor::create (int col, core::style::Color::Type type)
+{
+   ColorAttrs attrs(col, type);
+   FltkColor *color = colorsTable->get (&attrs);
+
+   if (color == NULL) {
+      color = new FltkColor (col, type);
+      colorsTable->put (color, color);
+   }
+
+   return color; 
+}
+
+void FltkView::addFltkWidget (::fltk::Widget *widget,
+                              core::Allocation *allocation)
+{
+}
+
+void FltkView::removeFltkWidget (::fltk::Widget *widget)
+{
+}
+
+void FltkView::allocateFltkWidget (::fltk::Widget *widget,
+                                   core::Allocation *allocation)
+{
+}
+
+void FltkView::drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area)
+{
+}
+
+
+core::ui::LabelButtonResource *
+FltkPlatform::FltkResourceFactory::createLabelButtonResource (const char
+                                                              *label)
+{
+   return new ui::FltkLabelButtonResource (platform, label);
+}
+
+core::ui::ComplexButtonResource *
+FltkPlatform::FltkResourceFactory::createComplexButtonResource (core::Widget
+                                                                *widget,
+                                                                bool relief)
+{
+   return new ui::FltkComplexButtonResource (platform, widget, relief);
+}
+
+core::ui::ListResource *
+FltkPlatform::FltkResourceFactory::createListResource (core::ui
+                                                       ::ListResource
+                                                       ::SelectionMode
+                                                       selectionMode)
+{
+   return new ui::FltkListResource (platform, selectionMode);
+}
+
+core::ui::OptionMenuResource *
+FltkPlatform::FltkResourceFactory::createOptionMenuResource ()
+{
+   return new ui::FltkOptionMenuResource (platform);
+}
+
+core::ui::EntryResource *
+FltkPlatform::FltkResourceFactory::createEntryResource (int maxLength,
+                                                        bool password)
+{
+   return new ui::FltkEntryResource (platform, maxLength, password);
+}
+
+core::ui::MultiLineTextResource *
+FltkPlatform::FltkResourceFactory::createMultiLineTextResource (int cols,
+                                                                int rows)
+{
+   return new ui::FltkMultiLineTextResource (platform, cols, rows);
+}
+
+core::ui::CheckButtonResource *
+FltkPlatform::FltkResourceFactory::createCheckButtonResource (bool activated)
+{
+   return new ui::FltkCheckButtonResource (platform, activated);
+}
+
+core::ui::RadioButtonResource
+*FltkPlatform::FltkResourceFactory::createRadioButtonResource
+(core::ui::RadioButtonResource *groupedWith, bool activated)
+{
+   return
+      new ui::FltkRadioButtonResource (platform,
+                                       (ui::FltkRadioButtonResource*)
+                                       groupedWith,
+                                       activated);
+}
+
+// ----------------------------------------------------------------------
+
+FltkPlatform::FltkPlatform ()
+{
+   layout = NULL;
+   idleQueue = new container::typed::List <IdleFunc> (true);
+   idleFuncRunning = false;
+   idleFuncId = 0;
+
+   views = new container::typed::List <FltkView> (false);
+   resources = new container::typed::List <ui::FltkResource> (false);
+
+   resourceFactory.setPlatform (this);
+}
+
+FltkPlatform::~FltkPlatform ()
+{
+   if(idleFuncRunning)
+      remove_idle (generalStaticIdle, (void*)this);
+   delete idleQueue;
+   delete views;
+   delete resources;
+}
+
+void FltkPlatform::setLayout (core::Layout *layout)
+{
+   this->layout = layout;
+}
+
+
+void FltkPlatform::attachView (core::View *view)
+{
+   views->append ((FltkView*)view);
+
+   for (container::typed::Iterator <ui::FltkResource> it =
+           resources->iterator (); it.hasNext (); ) {
+      ui::FltkResource *resource = it.getNext ();
+      resource->attachView ((FltkView*)view);
+   }
+}
+
+
+void FltkPlatform::detachView  (core::View *view)
+{
+   views->removeRef ((FltkView*)view);
+
+   for (container::typed::Iterator <ui::FltkResource> it =
+           resources->iterator (); it.hasNext (); ) {
+      ui::FltkResource *resource = it.getNext ();
+      resource->detachView ((FltkView*)view);
+   }
+}
+
+
+int FltkPlatform::textWidth (core::style::Font *font, const char *text,
+                             int len)
+{
+   FltkFont *ff = (FltkFont*) font;
+   setfont (ff->font, ff->size);
+   return (int) getwidth (text, len);
+}
+
+int FltkPlatform::nextGlyph (const char *text, int idx)
+{
+   return utf8fwd (&text[idx + 1], text, &text[strlen (text)]) - text;
+}
+
+int FltkPlatform::prevGlyph (const char *text, int idx)
+{
+   return utf8back (&text[idx - 1], text, &text[strlen (text)]) - text;
+}
+
+void FltkPlatform::generalStaticIdle (void *data)
+{
+   ((FltkPlatform*)data)->generalIdle();
+}
+
+void FltkPlatform::generalIdle ()
+{
+   IdleFunc *idleFunc;
+
+   if (!idleQueue->isEmpty ()) {
+      /* Execute the first function in the list. */
+      idleFunc = idleQueue->getFirst ();
+      (layout->*(idleFunc->func)) ();
+  
+      /* Remove this function. */
+      idleQueue->removeRef(idleFunc);
+   }
+
+   if(idleQueue->isEmpty()) {
+      idleFuncRunning = false;
+      remove_idle (generalStaticIdle, (void*)this);
+   }
+}
+
+/**
+ * \todo Incomplete comments.
+ */
+int FltkPlatform::addIdle (void (core::Layout::*func) ())
+{
+   /*
+    * Since ... (todo) we have to wrap around fltk_add_idle. There is only one
+    * idle function, the passed idle function is put into a queue.
+    */
+   if(!idleFuncRunning) {
+      add_idle (generalStaticIdle, (void*)this);
+      idleFuncRunning = true;
+   }
+
+   idleFuncId++;
+
+   IdleFunc *idleFunc = new IdleFunc();
+   idleFunc->id = idleFuncId;
+   idleFunc->func = func;
+   idleQueue->append (idleFunc);
+
+   return idleFuncId;
+}
+
+void FltkPlatform::removeIdle (int idleId)
+{
+   bool found;
+   container::typed::Iterator <IdleFunc> it;
+   IdleFunc *idleFunc;
+
+   for(found = false, it = idleQueue->iterator(); !found && it.hasNext(); ) {
+      idleFunc = it.getNext();
+      if(idleFunc->id == idleId) {
+         idleQueue->removeRef (idleFunc);
+         found = true;
+      }
+   }
+
+   if(idleFuncRunning && idleQueue->isEmpty())
+      remove_idle (generalStaticIdle, (void*)this);
+}
+
+core::style::Font *FltkPlatform::createFont (core::style::FontAttrs
+                                             *attrs,
+                                             bool tryEverything)
+{
+   return FltkFont::create (attrs);
+}
+
+core::style::Color *FltkPlatform::createSimpleColor (int color)
+{
+   return FltkColor::create (color, core::style::Color::TYPE_SIMPLE);
+}
+
+core::style::Color *FltkPlatform::createShadedColor (int color)
+{
+   return FltkColor::create (color, core::style::Color::TYPE_SHADED);
+}
+
+void FltkPlatform::copySelection(const char *text)
+{
+   fltk::copy(text, strlen(text), false);
+}
+
+core::Imgbuf *FltkPlatform::createImgbuf (core::Imgbuf::Type type,
+                                          int width, int height)
+{
+   return new FltkImgbuf (type, width, height);
+}
+
+core::ui::ResourceFactory *FltkPlatform::getResourceFactory ()
+{
+   return &resourceFactory;
+}
+
+
+void FltkPlatform::attachResource (ui::FltkResource *resource)
+{
+   resources->append (resource);
+
+   for (container::typed::Iterator <FltkView> it = views->iterator ();
+        it.hasNext (); ) {
+      FltkView *view = it.getNext ();
+      resource->attachView (view);
+   }
+}
+
+void FltkPlatform::detachResource (ui::FltkResource *resource)
+{
+   resources->removeRef (resource);
+}
+
+} // namespace fltk
+} // namespace dw
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkplatform.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,150 @@
+#ifndef __DW_FLTKPLATFORM_HH__
+#define __DW_FLTKPLATFORM_HH__
+
+#ifndef __INCLUDED_FROM_DW_FLTK_CORE_HH__
+#   error Do not include this file directly, use "fltkcore.hh" instead.
+#endif
+
+#include <fltk/Font.h>
+
+namespace dw {
+
+/**
+ * \brief This namespace contains FLTK implementations of Dw interfaces.
+ */
+namespace fltk {
+
+class FltkFont: public core::style::Font
+{
+   static lout::container::typed::HashTable <dw::core::style::FontAttrs,
+                                       FltkFont> *fontsTable;
+
+   FltkFont (core::style::FontAttrs *attrs);
+   ~FltkFont ();
+
+public:
+   ::fltk::Font *font;
+  
+   static FltkFont *create (core::style::FontAttrs *attrs);
+};
+
+
+class FltkColor: public core::style::Color
+{
+   static lout::container::typed::HashTable <dw::core::style::ColorAttrs,
+                                       FltkColor> *colorsTable;
+
+   FltkColor (int color, core::style::Color::Type type);
+   ~FltkColor ();
+
+public:
+   int colors[SHADING_NUM];
+
+   static FltkColor *create(int color, core::style::Color::Type type);
+};
+
+
+/**
+ * \brief This interface adds some more methods for all flkt-based views.
+ */
+class FltkView: public core::View
+{
+public:
+   virtual bool usesFltkWidgets () = 0;
+
+   virtual void addFltkWidget (::fltk::Widget *widget,
+                               core::Allocation *allocation);
+   virtual void removeFltkWidget (::fltk::Widget *widget);
+   virtual void allocateFltkWidget (::fltk::Widget *widget,
+                                    core::Allocation *allocation);
+   virtual void drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area);
+};
+
+
+class FltkPlatform: public core::Platform
+{
+private:
+   class FltkResourceFactory: public core::ui::ResourceFactory
+   {
+   private:
+      FltkPlatform *platform;
+
+   public:
+      inline void setPlatform (FltkPlatform *platform) {
+         this->platform = platform; }
+
+      core::ui::LabelButtonResource *createLabelButtonResource (const char
+                                                                *label);
+      core::ui::ComplexButtonResource *
+      createComplexButtonResource (core::Widget *widget, bool relief);
+      core::ui::ListResource *
+      createListResource (core::ui::ListResource::SelectionMode selectionMode);
+      core::ui::OptionMenuResource *createOptionMenuResource ();
+      core::ui::EntryResource *createEntryResource (int maxLength,
+                                                    bool password);
+      core::ui::MultiLineTextResource *createMultiLineTextResource (int cols,
+                                                                    int rows);
+      core::ui::CheckButtonResource *createCheckButtonResource (bool
+                                                                activated);
+      core::ui::RadioButtonResource *
+      createRadioButtonResource (core::ui::RadioButtonResource
+                                  *groupedWith, bool activated);
+   };
+
+   FltkResourceFactory resourceFactory;
+
+   class IdleFunc: public lout::object::Object
+   {
+   public:
+      int id;
+      void (core::Layout::*func) ();
+   };
+
+   core::Layout *layout;
+
+   lout::container::typed::List <IdleFunc> *idleQueue;
+   bool idleFuncRunning;
+   int idleFuncId;
+
+   static void generalStaticIdle(void *data);
+   void generalIdle();
+
+   lout::container::typed::List <FltkView> *views;
+   lout::container::typed::List <ui::FltkResource> *resources;
+
+public:
+   FltkPlatform ();
+   ~FltkPlatform ();
+
+   void setLayout (core::Layout *layout);
+   
+   void attachView (core::View *view);
+
+   void detachView  (core::View *view);
+   
+   int textWidth (core::style::Font *font, const char *text, int len);
+   int nextGlyph (const char *text, int idx);
+   int prevGlyph (const char *text, int idx);
+   
+   int addIdle (void (core::Layout::*func) ());
+   void removeIdle (int idleId);
+   
+   core::style::Font *createFont (core::style::FontAttrs *attrs,
+                                      bool tryEverything);
+   core::style::Color *createSimpleColor (int color);
+   core::style::Color *createShadedColor (int color);
+   
+   core::Imgbuf *createImgbuf (core::Imgbuf::Type type, int width, int height);
+
+   void copySelection(const char *text);
+
+   core::ui::ResourceFactory *getResourceFactory ();
+
+   void attachResource (ui::FltkResource *resource);
+   void detachResource (ui::FltkResource *resource);
+};
+
+} // namespace fltk
+} // namespace dw
+
+#endif // __DW_FLTKPLATFORM_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkpreview.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,298 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "fltkpreview.hh"
+#include "fltkmisc.hh"
+
+#include <fltk/events.h>
+#include <fltk/xbmImage.h>
+#include <fltk/draw.h>
+#include <stdio.h>
+
+#include "preview.xbm"
+
+using namespace ::fltk;
+
+namespace dw {
+namespace fltk {
+
+FltkPreview::FltkPreview (int x, int y, int w, int h,
+                          dw::core::Layout *layout, const char *label):
+   FltkViewBase (x, y, w, h, label)
+{
+   layout->attachView (this);
+
+   scrollX = 0;
+   scrollY = 0;
+   scrollWidth = 1;
+   scrollHeight = 1;
+}
+
+FltkPreview::~FltkPreview ()
+{
+}
+
+int FltkPreview::handle (int event)
+{
+   return FltkViewBase::handle (event);
+}
+
+int FltkPreview::translateViewXToCanvasX (int x)
+{
+   return x * canvasWidth / w ();
+}
+
+int FltkPreview::translateViewYToCanvasY (int y)
+{
+   return y * canvasHeight / h ();
+}
+
+int FltkPreview::translateCanvasXToViewX (int x)
+{
+   return x * w () / canvasWidth;
+}
+
+int FltkPreview::translateCanvasYToViewY (int y)
+{
+   return y * h () / canvasHeight;
+}
+
+void FltkPreview::setCanvasSize (int width, int ascent, int descent)
+{
+   FltkViewBase::setCanvasSize (width, ascent, descent);
+   if (parent() && parent()->visible ())
+      ((FltkPreviewWindow*)parent())->reallocate ();
+}
+
+bool FltkPreview::usesViewport ()
+{
+   return true;
+}
+
+int FltkPreview::getHScrollbarThickness ()
+{
+   return 0;
+}
+
+int FltkPreview::getVScrollbarThickness ()
+{
+   return 0;
+}
+
+void FltkPreview::scrollTo (int x, int y)
+{
+   scrollX = x;
+   scrollY = y;
+}
+
+void FltkPreview::setViewportSize (int width, int height,
+                                   int hScrollbarThickness,
+                                   int vScrollbarThickness)
+{
+   scrollWidth = width - vScrollbarThickness;
+   scrollHeight = height - hScrollbarThickness;
+}
+
+void FltkPreview::drawText (core::style::Font *font,
+                            core::style::Color *color,
+                            core::style::Color::Shading shading,
+                            int x, int y, const char *text, int len)
+{
+   /*
+    * We must call setfont() before calling getwidth() (or anything
+    * else that measures text).
+    */
+   FltkFont *ff = (FltkFont*)font;
+   setfont(ff->font, translateCanvasXToViewX (ff->size));
+#if 0
+   /**
+    * \todo Normally, this should already be known, maybe it
+    * should be passed?
+    */
+   int width = (int)getwidth (text, len);
+   int height = font->ascent; // No descent, this would look to "bold".
+
+   int x1 = translateCanvasXToViewX (x);
+   int y1 = translateCanvasYToViewY (y);
+   int x2 = translateCanvasXToViewX (x + width);
+   int y2 = translateCanvasYToViewY (y + height);
+   Rectangle rect (x1, y1, x2 - x1, y2 - y1);
+
+   setcolor(((FltkColor*)color)->colors[shading]);
+   fillrect (rect);
+#endif
+   setcolor(((FltkColor*)color)->colors[shading]);
+   drawtext(text, len,
+            translateCanvasXToViewX (x), translateCanvasYToViewY (y));
+}
+
+void FltkPreview::drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot,
+                int x, int y, int width, int height)
+{
+}
+
+bool FltkPreview::usesFltkWidgets ()
+{
+   return false;
+}
+
+void FltkPreview::drawFltkWidget (Widget *widget,
+                                  core::Rectangle *area)
+{
+}
+
+// ----------------------------------------------------------------------
+
+FltkPreviewWindow::FltkPreviewWindow (dw::core::Layout *layout):
+   MenuWindow (1, 1)
+{
+   box (EMBOSSED_BOX);
+
+   begin ();
+   preview = new FltkPreview (BORDER_WIDTH, BORDER_WIDTH, 1, 1, layout);
+   end ();
+
+   hide ();
+}
+
+FltkPreviewWindow::~FltkPreviewWindow ()
+{
+}
+
+void FltkPreviewWindow::showWindow ()
+{
+   reallocate ();
+   show ();
+}
+
+void FltkPreviewWindow::reallocate ()
+{
+   int maxWidth = misc::screenWidth () / 2;
+   int maxHeight = misc::screenHeight () * 4 / 5;
+   int mx, my, width, height;
+   bool warp = false;
+
+   if(preview->canvasHeight * maxWidth > maxHeight * preview->canvasWidth) {
+      // Expand to maximal height (most likely case).
+      width = preview->canvasWidth * maxHeight / preview->canvasHeight;
+      height = maxHeight;
+   } else {
+      // Expand to maximal width.
+      width = maxWidth;
+      height = preview->canvasHeight * maxWidth / preview->canvasWidth;
+   }
+
+   get_mouse(mx, my);
+
+   posX = mx - preview->translateCanvasXToViewX (preview->scrollX
+                                                 + preview->scrollWidth / 2);
+   posY = my - preview->translateCanvasYToViewY (preview->scrollY
+                                                 + preview->scrollHeight / 2);
+
+   if (posX < 0) {
+      mx -= posX;
+      posX = 0;
+      warp = true;
+   } else if (posX + width > misc::screenWidth ()) {
+      mx -= (posX - (misc::screenWidth () - width));
+      posX = misc::screenWidth () - width;
+      warp = true;
+   }
+
+   if (posY < 0) {
+      my -= posY;
+      posY = 0;
+      warp = true;
+   } else if (posY + height > misc::screenHeight ()) {
+      my -= (posY - (misc::screenHeight () - height));
+      posY = misc::screenHeight () - height;
+      warp = true;
+   }
+
+   if (warp)
+      misc::warpPointer (mx, my);
+
+   resize (posX, posY, width, height);
+
+   preview->w (w () - 2 * BORDER_WIDTH);
+   preview->h (h () - 2 * BORDER_WIDTH);
+}
+
+void FltkPreviewWindow::hideWindow ()
+{
+   Window::hide ();
+}
+
+void FltkPreviewWindow::scrollTo (int mouseX, int mouseY)
+{
+   preview->scrollX =
+      preview->translateViewXToCanvasX (mouseX - posX - BORDER_WIDTH)
+      - preview->scrollWidth / 2;
+   preview->scrollY =
+      preview->translateViewYToCanvasY (mouseY - posY - BORDER_WIDTH)
+      - preview->scrollHeight / 2;
+   preview->theLayout->scrollPosChanged (preview,
+                                         preview->scrollX, preview->scrollY);
+}
+
+// ----------------------------------------------------------------------
+
+FltkPreviewButton::FltkPreviewButton (int x, int y, int w, int h,
+                                      dw::core::Layout *layout,
+                                      const char *label):
+   Button (x, y, w, h, label)
+{
+   image (new xbmImage (preview_bits, preview_width, preview_height));
+   window = new FltkPreviewWindow (layout);
+}
+
+FltkPreviewButton::~FltkPreviewButton ()
+{
+}
+
+int FltkPreviewButton::handle (int event)
+{
+   /** \bug Some parts are missing. */
+
+   switch (event) {
+   case PUSH:
+      window->showWindow ();
+      return Button::handle (event);
+
+   case DRAG:
+      if (window->visible ()) {
+         window->scrollTo (event_x_root (), event_y_root ());
+         return 1;
+      }
+      return Button::handle (event);
+
+   case RELEASE:
+      window->hideWindow ();
+      return Button::handle (event);
+    
+   default:
+      return Button::handle (event);
+   }
+}
+
+} // namespace fltk
+} // namespace dw
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkpreview.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,89 @@
+#ifndef __FlTKPREVIEW_HH__
+#define __FlTKPREVIEW_HH__
+
+#include <fltk/Button.h>
+#include <fltk/MenuWindow.h>
+#include "fltkviewbase.hh"
+
+namespace dw {
+namespace fltk {
+
+class FltkPreview: public FltkViewBase
+{
+   friend class FltkPreviewWindow;
+
+private:
+   int scrollX, scrollY, scrollWidth, scrollHeight;
+
+protected:
+   int translateViewXToCanvasX (int x);
+   int translateViewYToCanvasY (int y);
+   int translateCanvasXToViewX (int x);
+   int translateCanvasYToViewY (int y);
+
+public:
+   FltkPreview (int x, int y, int w, int h, dw::core::Layout *layout,
+                const char *label = 0);
+   ~FltkPreview ();
+
+   int handle (int event);
+
+   void setCanvasSize (int width, int ascent, int descent);
+
+   bool usesViewport ();
+   int getHScrollbarThickness ();
+   int getVScrollbarThickness ();
+   void scrollTo (int x, int y);
+   void setViewportSize (int width, int height,
+                         int hScrollbarThickness, int vScrollbarThickness);
+
+   void drawText (core::style::Font *font,
+                  core::style::Color *color,
+                  core::style::Color::Shading shading,
+                  int x, int y, const char *text, int len);
+   void drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot,
+                   int x, int y, int width, int height);
+
+   bool usesFltkWidgets ();
+   void drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area);
+};
+
+
+class FltkPreviewWindow: public ::fltk::MenuWindow
+{
+private:
+   enum { BORDER_WIDTH = 2 };
+
+   FltkPreview *preview;
+   int posX, posY;
+
+public:
+   FltkPreviewWindow (dw::core::Layout *layout);
+   ~FltkPreviewWindow ();
+
+   void reallocate ();
+
+   void showWindow ();
+   void hideWindow ();
+
+   void scrollTo (int mouseX, int mouseY);
+};
+
+
+class FltkPreviewButton: public  ::fltk::Button
+{
+private:
+   FltkPreviewWindow *window;
+
+public:
+   FltkPreviewButton (int x, int y, int w, int h,
+                      dw::core::Layout *layout, const char *label = 0);
+   ~FltkPreviewButton ();
+
+   int handle (int event);
+};
+
+} // namespace fltk
+} // namespace dw
+
+#endif // __FlTKPREVIEW_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkui.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,1202 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "fltkcore.hh"
+#include "fltkflatview.hh"
+#include "fltkcomplexbutton.hh"
+#include "../lout/misc.hh"
+
+#include <stdio.h>
+#include <fltk/Widget.h>
+#include <fltk/Group.h>
+#include <fltk/Input.h>
+#include <fltk/SecretInput.h>
+#include <fltk/TextEditor.h>
+#include <fltk/RadioButton.h>
+#include <fltk/CheckButton.h>
+#include <fltk/Choice.h>
+#include <fltk/Browser.h>
+#include <fltk/MultiBrowser.h>
+#include <fltk/Font.h>
+#include <fltk/draw.h>
+#include <fltk/Symbol.h>
+#include <fltk/Item.h>
+#include <fltk/ItemGroup.h>
+#include <fltk/events.h>
+
+namespace dw {
+namespace fltk {
+namespace ui {
+
+enum { RELIEF_X_THICKNESS = 5, RELIEF_Y_THICKNESS = 3 };
+
+using namespace object;
+using namespace container::typed;
+
+FltkResource::FltkResource (FltkPlatform *platform)
+{
+   this->platform = platform;
+
+   allocation.x = 0;
+   allocation.y = 0;
+   allocation.width = 1;
+   allocation.ascent = 1;
+   allocation.descent = 0;
+
+   style = NULL;
+}
+
+/**
+ * This is not a constructor, since it calls some virtual methods, which
+ * should not be done in a C++ base constructor.
+ */
+void FltkResource::init (FltkPlatform *platform)
+{
+   viewsAndWidgets = new container::typed::List <ViewAndWidget> (true);
+   platform->attachResource (this);
+}
+
+FltkResource::~FltkResource ()
+{
+   platform->detachResource (this);
+   for (Iterator <ViewAndWidget> it = viewsAndWidgets->iterator ();
+      it.hasNext(); ) {
+      ViewAndWidget *viewAndWidget = it.getNext ();
+
+      if (viewAndWidget->widget) {
+         if (viewAndWidget->view) {
+            viewAndWidget->view->removeFltkWidget(viewAndWidget->widget);
+         }
+         delete viewAndWidget->widget;
+      }
+
+   }
+   delete viewsAndWidgets;
+   if(style)
+      style->unref ();
+}
+
+void FltkResource::attachView (FltkView *view)
+{
+   if (view->usesFltkWidgets ()) {
+      ViewAndWidget *viewAndWidget = new ViewAndWidget();
+      viewAndWidget->view = view;
+      
+      viewAndWidget->widget = createNewWidget (&allocation);
+      viewAndWidget->view->addFltkWidget (viewAndWidget->widget, &allocation);
+      viewsAndWidgets->append (viewAndWidget);
+      if (style)
+         setWidgetStyle (viewAndWidget->widget, style);
+   }
+}
+
+void FltkResource::detachView (FltkView *view)
+{
+   for (Iterator <ViewAndWidget> it = viewsAndWidgets->iterator ();
+        it.hasNext(); ) {
+      ViewAndWidget *viewAndWidget = it.getNext ();
+      if (viewAndWidget->view == view) {
+         viewsAndWidgets->removeRef (viewAndWidget);
+         return;
+      }
+   }
+
+   fprintf (stderr, "FltkResource::detachView: View not found.");
+}
+
+void FltkResource::sizeAllocate (core::Allocation *allocation)
+{
+   this->allocation = *allocation;
+
+   for (Iterator <ViewAndWidget> it = viewsAndWidgets->iterator ();
+        it.hasNext(); ) {
+      ViewAndWidget *viewAndWidget = it.getNext ();
+      viewAndWidget->view->allocateFltkWidget (viewAndWidget->widget,
+                                               allocation);
+   }
+}
+
+void FltkResource::draw (core::View *view, core::Rectangle *area)
+{
+   FltkView *fltkView = (FltkView*)view;
+   if (fltkView->usesFltkWidgets ()) {
+      for (Iterator <ViewAndWidget> it = viewsAndWidgets->iterator ();
+           it.hasNext(); ) {
+         ViewAndWidget *viewAndWidget = it.getNext ();
+         if (viewAndWidget->view == fltkView) {
+            fltkView->drawFltkWidget (viewAndWidget->widget, area);
+            break;
+         }
+      }
+   }
+}
+
+void FltkResource::setStyle (core::style::Style *style)
+{
+   if(this->style)
+      this->style->unref ();
+
+   this->style = style;
+   style->ref ();
+
+   for (Iterator <ViewAndWidget> it = viewsAndWidgets->iterator ();
+        it.hasNext(); ) {
+      ViewAndWidget *viewAndWidget = it.getNext ();
+      setWidgetStyle (viewAndWidget->widget, style);
+   }
+}
+
+void FltkResource::setWidgetStyle (::fltk::Widget *widget,
+                                   core::style::Style *style)
+{
+   /** \bug label or text? */
+
+   FltkFont *font = (FltkFont*)style->font;
+   widget->labelsize (font->size);
+   widget->labelfont (font->font);
+   widget->textsize (font->size);
+   widget->textfont (font->font);
+
+   FltkColor *bg = (FltkColor*)style->backgroundColor;
+   if (bg) {
+      if (style->color) {
+         /*
+          * todo: if/when CSS is implemented, test whether style->color
+          * will consistently provide readable widgets.
+          */
+         int32_t c = bg->colors[FltkColor::SHADING_NORMAL];
+         int r = (c >> 24) & 0xff, g = (c >> 16) & 0xff, b = (c >> 8) & 0xff;
+         bool light =  (r + g >= 0x150) || (r + g + b >= 0x180);
+
+         widget->labelcolor(light? ::fltk::BLACK : ::fltk::WHITE);
+         widget->textcolor(light? ::fltk::BLACK : ::fltk::WHITE);
+         widget->selection_color(light? ::fltk::BLACK : ::fltk::WHITE);
+      }
+
+      widget->color(bg->colors[FltkColor::SHADING_NORMAL]);
+      widget->buttoncolor(bg->colors[FltkColor::SHADING_NORMAL]);
+      widget->highlight_color(bg->colors[FltkColor::SHADING_LIGHT]);
+      widget->selection_textcolor(bg->colors[FltkColor::SHADING_NORMAL]);
+   }
+}
+   
+bool FltkResource::isEnabled ()
+{
+   /** \bug Not implemented. */
+   return true;
+}
+
+void FltkResource::setEnabled (bool enabled)
+{
+   /** \bug Not implemented. */
+}
+
+// ----------------------------------------------------------------------
+
+template <class I> void FltkSpecificResource<I>::sizeAllocate (core::Allocation
+                                                               *allocation)
+{
+   FltkResource::sizeAllocate (allocation);
+}
+
+template <class I> void FltkSpecificResource<I>::draw (core::View *view,
+                                                       core::Rectangle *area)
+{
+   FltkResource::draw (view, area);
+}
+
+template <class I> void FltkSpecificResource<I>::setStyle (core::style::Style
+                                                           *style)
+{
+   FltkResource::setStyle (style);
+}
+
+template <class I> bool FltkSpecificResource<I>::isEnabled ()
+{
+   return FltkResource::isEnabled ();
+}
+
+template <class I> void FltkSpecificResource<I>::setEnabled (bool enabled)
+{
+   FltkResource::setEnabled (enabled);
+}
+
+// ----------------------------------------------------------------------
+
+FltkLabelButtonResource::FltkLabelButtonResource (FltkPlatform *platform,
+                                                  const char *label):
+   FltkSpecificResource <dw::core::ui::LabelButtonResource> (platform)
+{
+   this->label = strdup (label);
+   init (platform);
+}
+
+FltkLabelButtonResource::~FltkLabelButtonResource ()
+{
+   delete label;
+}
+
+::fltk::Widget *FltkLabelButtonResource::createNewWidget (core::Allocation
+                                                          *allocation)
+{
+   ::fltk::Button *button =
+        new ::fltk::Button (allocation->x, allocation->y, allocation->width,
+                            allocation->ascent + allocation->descent,
+                            label);
+   button->callback (widgetCallback, this);
+   button->when (::fltk::WHEN_RELEASE);
+   return button;
+}
+
+void FltkLabelButtonResource::sizeRequest (core::Requisition *requisition)
+{
+   if (style) {
+      FltkFont *font = (FltkFont*)style->font;
+      ::fltk::setfont(font->font,font->size);
+      requisition->width =
+         (int)::fltk::getwidth (label, strlen (label))
+         + 2 * RELIEF_X_THICKNESS;
+      requisition->ascent = font->ascent + RELIEF_Y_THICKNESS;
+      requisition->descent = font->descent + RELIEF_Y_THICKNESS;
+   } else {
+      requisition->width = 1;
+      requisition->ascent = 1;
+      requisition->descent = 0;
+   }
+}
+
+void FltkLabelButtonResource::widgetCallback (::fltk::Widget *widget,
+                                              void *data)
+{
+   if (widget->when () & ::fltk::WHEN_RELEASE)
+      ((FltkLabelButtonResource*)data)->emitActivate ();
+}
+
+const char *FltkLabelButtonResource::getLabel ()
+{
+   return label;
+}
+
+
+void FltkLabelButtonResource::setLabel (const char *label)
+{
+   delete this->label;
+   this->label = strdup (label);
+
+   for (Iterator <ViewAndWidget> it = viewsAndWidgets->iterator ();
+        it.hasNext(); ) {
+      ViewAndWidget *viewAndWidget = it.getNext ();
+      viewAndWidget->widget->label (this->label);
+   }
+
+   queueResize (true);
+}
+
+// ----------------------------------------------------------------------
+
+FltkComplexButtonResource::FltkComplexButtonResource (FltkPlatform *platform,
+                                                      dw::core::Widget
+                                                      *widget, bool relief):
+   FltkSpecificResource <dw::core::ui::ComplexButtonResource> (platform)
+{
+   viewsAndViews = new container::typed::List <ViewAndView> (true);
+   this->relief = relief;
+   FltkResource::init (platform);
+   ComplexButtonResource::init (widget);
+}
+
+FltkComplexButtonResource::~FltkComplexButtonResource ()
+{
+   delete viewsAndViews;
+}
+
+void FltkComplexButtonResource::widgetCallback (::fltk::Widget *widget,
+                                                void *data)
+{
+   FltkComplexButtonResource *res = (FltkComplexButtonResource*)data;
+
+   /* would be best not to send click pos. if the image could not be loaded */
+   if (::fltk::event() == ::fltk::RELEASE &&
+       ::fltk::event_button() == ::fltk::LeftButton) {
+      res->click_x = ::fltk::event_x();
+      res->click_y = ::fltk::event_y();
+      res->emitActivate ();
+   } else {
+      ((FltkViewBase*)res->lastFlatView)->handle(::fltk::event());
+   }
+}
+
+dw::core::Platform *FltkComplexButtonResource::createPlatform ()
+{
+   return new FltkPlatform ();
+}
+
+void FltkComplexButtonResource::attachView (FltkView *view)
+{
+   FltkResource::attachView (view);
+
+   if (view->usesFltkWidgets ()) {
+      ViewAndView *viewAndView = new ViewAndView();
+      viewAndView->topView = view;
+      viewAndView->flatView = lastFlatView;
+      viewsAndViews->append (viewAndView);
+   }
+}
+
+void FltkComplexButtonResource::detachView (FltkView *view)
+{
+   FltkResource::detachView (view);
+
+   for (Iterator <ViewAndView> it = viewsAndViews->iterator ();
+        it.hasNext(); ) {
+      ViewAndView *viewAndView = it.getNext ();
+      if (viewAndView->topView == view) {
+         viewsAndViews->removeRef (viewAndView);
+         return;
+      }
+   }
+
+   fprintf (stderr,
+            "FltkComplexButtonResourceResource::detachView: View not "
+            "found.\n");
+}
+
+void FltkComplexButtonResource::sizeAllocate (core::Allocation *allocation)
+{
+   FltkResource::sizeAllocate (allocation);
+
+   for (Iterator <ViewAndView> it = viewsAndViews->iterator ();
+        it.hasNext(); ) {
+      ViewAndView *viewAndView = it.getNext ();
+      ((FltkFlatView*)viewAndView->flatView)->resize (
+         reliefXThickness (),
+         reliefYThickness (),
+         allocation->width - 2 * reliefXThickness (),
+         allocation->ascent + allocation->descent - 2 * reliefYThickness ());
+
+      ((FltkFlatView*)viewAndView->flatView)->parent ()->init_sizes ();
+   }
+}
+
+void FltkComplexButtonResource::setLayout (dw::core::Layout *layout)
+{
+   for (Iterator <ViewAndView> it = viewsAndViews->iterator ();
+        it.hasNext(); ) {
+      ViewAndView *viewAndView = it.getNext ();
+      layout->attachView (viewAndView->flatView);
+   }
+}
+
+int FltkComplexButtonResource::reliefXThickness ()
+{
+   return relief ? RELIEF_X_THICKNESS : 0;
+}
+
+int FltkComplexButtonResource::reliefYThickness ()
+{
+   return relief ? RELIEF_Y_THICKNESS : 0;
+}
+
+
+::fltk::Widget *FltkComplexButtonResource::createNewWidget (core::Allocation
+                                                            *allocation)
+{
+   ComplexButton *button =
+      new ComplexButton (allocation->x, allocation->y, allocation->width,
+                         allocation->ascent + allocation->descent);
+   button->callback (widgetCallback, this);
+   button->when (::fltk::WHEN_RELEASE);
+   if (!relief)
+      button->box(::fltk::FLAT_BOX);
+
+   FltkFlatView *flatView = 
+      new FltkFlatView (allocation->x + reliefXThickness (),
+                        allocation->y + reliefYThickness (),
+                        allocation->width - 2 * reliefXThickness (),
+                        allocation->ascent + allocation->descent
+                        - 2 * reliefYThickness ());
+   button->add (flatView);
+
+   lastFlatView = flatView;
+
+   if (layout)
+      layout->attachView (lastFlatView);
+   return button;
+}
+
+// ----------------------------------------------------------------------
+
+FltkEntryResource::FltkEntryResource (FltkPlatform *platform, int maxLength,
+                                      bool password):  
+   FltkSpecificResource <dw::core::ui::EntryResource> (platform)
+{
+   this->maxLength = maxLength;
+   this->password = password;
+   
+   initText = NULL;
+   editable = false;
+
+   init (platform);
+}
+
+FltkEntryResource::~FltkEntryResource ()
+{
+   if (initText)
+      delete initText;
+}
+
+::fltk::Widget *FltkEntryResource::createNewWidget (core::Allocation
+                                                    *allocation)
+{
+   ::fltk::Input *input =
+        password ?
+        new ::fltk::SecretInput (allocation->x, allocation->y,
+                                 allocation->width,
+                                 allocation->ascent + allocation->descent) :
+        new ::fltk::Input (allocation->x, allocation->y, allocation->width,
+                           allocation->ascent + allocation->descent);
+   input->callback (widgetCallback, this);
+   input->when (::fltk::WHEN_ENTER_KEY_ALWAYS);
+
+   if (viewsAndWidgets->isEmpty ()) {
+      // First widget created, attach the set text.
+      if (initText)
+         input->value (initText);
+   } else
+      input->value
+         (((::fltk::Input*)viewsAndWidgets->getFirst()->widget)->value ());
+
+   return input;
+}
+
+void FltkEntryResource::sizeRequest (core::Requisition *requisition)
+{
+   if (style) {
+      FltkFont *font = (FltkFont*)style->font;
+      ::fltk::setfont(font->font,font->size);
+      requisition->width =
+         (int)::fltk::getwidth ("M", 1)
+         * (maxLength == UNLIMITED_MAX_LENGTH ? 10 : maxLength)
+         + 2 * RELIEF_X_THICKNESS;
+      requisition->ascent = font->ascent + RELIEF_Y_THICKNESS;
+      requisition->descent = font->descent + RELIEF_Y_THICKNESS;
+   } else {
+      requisition->width = 1;
+      requisition->ascent = 1;
+      requisition->descent = 0;
+   }
+}
+
+void FltkEntryResource::widgetCallback (::fltk::Widget *widget,
+                                        void *data)
+{
+   /* The (::fltk::event_key() == ::fltk::ReturnKey) test
+    * is necessary because WHEN_ENTER_KEY also includes
+    * other events we're not interested in. For instance pressing
+    * The Back or Forward, buttons, or the first click on a rendered
+    * page. BUG: this must be investigated and reported to FLTK2 team
+    */
+   printf ("when = %d\n", widget->when ());
+   if ((widget->when () & ::fltk::WHEN_ENTER_KEY_ALWAYS) &&
+       (::fltk::event_key() == ::fltk::ReturnKey))
+      ((FltkEntryResource*)data)->emitActivate ();
+}
+
+const char *FltkEntryResource::getText ()
+{
+   if (viewsAndWidgets->isEmpty ())
+      return initText;
+   else
+      return ((::fltk::Input*)viewsAndWidgets->getFirst()->widget)->value ();
+}
+
+void FltkEntryResource::setText (const char *text)
+{
+   if (initText)
+      delete initText;
+   initText = strdup (text);
+
+   for (Iterator <ViewAndWidget> it = viewsAndWidgets->iterator ();
+        it.hasNext(); ) {
+      ViewAndWidget *viewAndWidget = it.getNext ();
+      ((::fltk::Input*)viewAndWidget->widget)->value (initText);
+   }
+}
+
+bool FltkEntryResource::isEditable ()
+{
+   return editable;
+}
+
+void FltkEntryResource::setEditable (bool editable)
+{
+   this->editable = editable;
+}
+
+// ----------------------------------------------------------------------
+
+FltkMultiLineTextResource::FltkMultiLineTextResource (FltkPlatform *platform,
+                                                      int cols, int rows): 
+   FltkSpecificResource <dw::core::ui::MultiLineTextResource> (platform)
+{
+   buffer = new ::fltk::TextBuffer;
+   editable = false;
+
+   numCols = cols;
+   numRows = rows;
+
+   // Check values. Upper bound check is left to the caller.
+   if (numCols < 1) {
+      fprintf (stderr, "WARNING: numCols = %d is set to 1.\n", numCols);
+      numCols = 1;
+   }
+   if (numRows < 1) {
+      fprintf (stderr, "WARNING: numRows = %d is set to 1.\n", numRows);
+      numRows = 1;
+   }
+
+   init (platform);
+}
+
+FltkMultiLineTextResource::~FltkMultiLineTextResource ()
+{
+   /* Free memory avoiding a double-free of text buffers */
+   for (Iterator <ViewAndWidget> it = viewsAndWidgets->iterator ();
+        it.hasNext(); ) {
+      ViewAndWidget *viewAndWidget = it.getNext ();
+      ((::fltk::TextEditor *) viewAndWidget->widget)->buffer (0);
+   }
+   delete buffer;
+}
+
+::fltk::Widget *FltkMultiLineTextResource::createNewWidget (core::Allocation
+                                                            *allocation)
+{
+   ::fltk::TextEditor *text =
+      new ::fltk::TextEditor (allocation->x, allocation->y,
+                              allocation->width,
+                              allocation->ascent + allocation->descent);
+   text->buffer (buffer);
+   return text;
+}
+
+void FltkMultiLineTextResource::sizeRequest (core::Requisition *requisition)
+{
+   if (style) {
+      FltkFont *font = (FltkFont*)style->font;
+      ::fltk::setfont(font->font,font->size);
+      requisition->width =
+         (int)::fltk::getwidth ("X", 1) * numCols +
+         2 * RELIEF_X_THICKNESS;
+      requisition->ascent =
+         font->ascent + RELIEF_Y_THICKNESS;
+      requisition->descent =
+         font->descent +
+         (font->ascent + font->descent) * (numRows - 1) +
+         RELIEF_Y_THICKNESS;
+   } else {
+      requisition->width = 1;
+      requisition->ascent = 1;
+      requisition->descent = 0;
+   }
+}
+
+const char *FltkMultiLineTextResource::getText ()
+{
+   return buffer->text ();
+}
+
+void FltkMultiLineTextResource::setText (const char *text)
+{
+   buffer->text (text);
+}
+
+bool FltkMultiLineTextResource::isEditable ()
+{
+   return editable;
+}
+
+void FltkMultiLineTextResource::setEditable (bool editable)
+{
+   this->editable = editable;
+}
+
+// ----------------------------------------------------------------------
+
+template <class I>
+FltkToggleButtonResource<I>::FltkToggleButtonResource (FltkPlatform *platform,
+                                                       bool activated):
+   FltkSpecificResource <I> (platform)  
+{
+   initActivated = activated;
+}
+
+
+template <class I>
+FltkToggleButtonResource<I>::~FltkToggleButtonResource ()
+{
+}
+
+
+template <class I>
+::fltk::Widget *FltkToggleButtonResource<I>::createNewWidget (core::Allocation
+                                                              *allocation)
+{
+   ::fltk::Button *button = createNewButton (allocation);
+
+   if (this->viewsAndWidgets->isEmpty ())
+      button->value (initActivated);
+   else
+      button->value (((::fltk::Button*)this->viewsAndWidgets
+                      ->getFirst()->widget)->value ());
+
+   return button;
+}
+
+
+template <class I>
+void FltkToggleButtonResource<I>::sizeRequest (core::Requisition *requisition)
+{
+   /** \bug Random values. */
+   requisition->width = 20;
+   requisition->ascent = 18;
+   requisition->descent = 5;
+}
+
+
+template <class I>
+bool FltkToggleButtonResource<I>::FltkToggleButtonResource::isActivated ()
+{
+   if (this->viewsAndWidgets->isEmpty ())
+      return initActivated;
+   else
+      return
+         ((::fltk::Button*)this->viewsAndWidgets->getFirst()->widget)
+         ->value ();
+}
+
+
+template <class I>
+void FltkToggleButtonResource<I>::setActivated (bool activated)
+{
+   initActivated = activated;
+
+   for (Iterator <FltkResource::ViewAndWidget> it =
+           this->viewsAndWidgets->iterator ();
+        it.hasNext(); ) {
+      FltkResource::ViewAndWidget *viewAndWidget = it.getNext ();
+      ((::fltk::Button*)viewAndWidget->widget)->value (initActivated);
+   }
+}
+
+// ----------------------------------------------------------------------
+
+FltkCheckButtonResource::FltkCheckButtonResource (FltkPlatform *platform,
+                                                  bool activated):
+   FltkToggleButtonResource<dw::core::ui::CheckButtonResource> (platform,
+                                                                activated)
+{
+   init (platform);
+}
+
+
+FltkCheckButtonResource::~FltkCheckButtonResource ()
+{
+}
+
+
+::fltk::Button *FltkCheckButtonResource::createNewButton (core::Allocation
+                                                          *allocation)   
+{
+   return
+      new ::fltk::CheckButton (allocation->x, allocation->y, allocation->width,
+                               allocation->ascent + allocation->descent);
+}
+
+// ----------------------------------------------------------------------
+
+bool FltkRadioButtonResource::Group::FltkGroupIterator::hasNext ()
+{
+   return it.hasNext ();
+}
+
+dw::core::ui::RadioButtonResource
+*FltkRadioButtonResource::Group::FltkGroupIterator::getNext ()
+{
+   return (dw::core::ui::RadioButtonResource*)it.getNext ();
+}
+
+void FltkRadioButtonResource::Group::FltkGroupIterator::unref ()
+{
+   delete this;
+}
+
+
+FltkRadioButtonResource::Group::Group (FltkRadioButtonResource
+                                       *radioButtonResource)
+{
+   list = new container::typed::List <FltkRadioButtonResource> (false);
+   connect (radioButtonResource);
+}
+
+FltkRadioButtonResource::Group::~Group ()
+{
+   delete list;
+}
+      
+void FltkRadioButtonResource::Group::connect (FltkRadioButtonResource
+                                              *radioButtonResource)
+{
+   list->append (radioButtonResource);
+}
+
+void FltkRadioButtonResource::Group::unconnect (FltkRadioButtonResource
+                                                *radioButtonResource)
+{
+   list->removeRef (radioButtonResource);
+   if (list->isEmpty ())
+      delete this;
+}
+
+
+FltkRadioButtonResource::FltkRadioButtonResource (FltkPlatform *platform,
+                                                  FltkRadioButtonResource
+                                                  *groupedWith,
+                                                  bool activated):
+   FltkToggleButtonResource<dw::core::ui::RadioButtonResource> (platform,
+                                                                activated)
+{
+   init (platform);
+
+   if (groupedWith) {
+      group = groupedWith->group;
+      group->connect (this);
+   } else
+      group = new Group (this);
+}
+
+
+FltkRadioButtonResource::~FltkRadioButtonResource ()
+{
+   group->unconnect (this);
+}
+
+dw::core::ui::RadioButtonResource::GroupIterator
+*FltkRadioButtonResource::groupIterator ()
+{
+   return group->groupIterator ();
+}
+
+void FltkRadioButtonResource::widgetCallback (::fltk::Widget *widget,
+                                              void *data)
+{
+   if (widget->when () & ::fltk::WHEN_CHANGED)
+      ((FltkRadioButtonResource*)data)->buttonClicked ();
+}
+
+void FltkRadioButtonResource::buttonClicked ()
+{
+   for (Iterator <FltkRadioButtonResource> it = group->iterator ();
+        it.hasNext (); ) {
+      FltkRadioButtonResource *other = it.getNext ();
+      other->setActivated (other == this);
+   }
+}
+
+::fltk::Button *FltkRadioButtonResource::createNewButton (core::Allocation
+                                                          *allocation)   
+{
+   /*
+    * Groups of fltk::RadioButton must be added to one fltk::Group, which is
+    * not possible in this context. For this, we do the grouping ourself,
+    * based on FltkRadioButtonResource::Group.
+    *
+    * What we actually need for this, is a widget, which behaves like a
+    * check button, but looks like a radio button. The first depends on the
+    * type, the second on the style. Since the type is simpler to change
+    * than the style, we create a radio button, and then change the type
+    * (instead of creating a check button, and changing the style).
+    */
+
+   ::fltk::Button *button =
+      new ::fltk::RadioButton (allocation->x, allocation->y,
+                               allocation->width,
+                               allocation->ascent + allocation->descent);
+   button->when (::fltk::WHEN_CHANGED);
+   button->callback (widgetCallback, this);
+   button->type (::fltk::Button::TOGGLE);
+
+   return button;
+}
+
+// ----------------------------------------------------------------------
+
+template <class I> FltkSelectionResource<I>::Item::Item (Type type,
+                                                         const char *name,
+                                                         bool enabled,
+                                                         bool selected)
+{
+   this->type = type;
+   this->name = name ? strdup (name) : NULL;
+   this->enabled = enabled;
+   initSelected = selected;
+}
+
+template <class I> FltkSelectionResource<I>::Item::~Item ()
+{
+   if (name)
+      delete name;
+}
+
+template <class I>
+::fltk::Item *FltkSelectionResource<I>::Item::createNewWidget (int index)
+{
+   ::fltk::Item *item = new ::fltk::Item (name);
+   item->user_data ((void *) index);
+   return item;
+}
+
+template <class I>
+::fltk::ItemGroup *
+FltkSelectionResource<I>::Item::createNewGroupWidget ()
+{
+   ::fltk::ItemGroup *itemGroup = new ::fltk::ItemGroup (name);
+   itemGroup->user_data ((void *) -1L);
+   return itemGroup;
+}
+
+
+template <class I>
+FltkSelectionResource<I>::WidgetStack::WidgetStack (::fltk::Menu *widget)
+{
+   this->widget = widget;
+   this->stack = new Stack <TypedPointer < ::fltk::Menu> > (true);
+}
+
+template <class I> FltkSelectionResource<I>::WidgetStack::~WidgetStack ()
+{
+   delete stack;
+}
+
+
+template <class I>
+FltkSelectionResource<I>::FltkSelectionResource (FltkPlatform *platform):
+   FltkSpecificResource<I> (platform)
+{
+   widgetStacks = new List <WidgetStack> (true);
+   allItems = new List <Item> (true);
+   items = new Vector <Item> (16, false);
+}
+
+template <class I> FltkSelectionResource<I>::~FltkSelectionResource ()
+{
+   delete widgetStacks;
+   delete allItems;
+   delete items;
+}
+
+template <class I> dw::core::Iterator *
+FltkSelectionResource<I>::iterator (dw::core::Content::Type mask, bool atEnd)
+{
+   /** \bug Implementation. */
+   return new core::EmptyIterator (this->getEmbed (), mask, atEnd);
+}
+
+template <class I> ::fltk::Widget *
+FltkSelectionResource<I>::createNewWidget (core::Allocation *allocation)
+{
+   /** \todo Attributes (enabled, selected). */
+
+   ::fltk::Menu *menu = createNewMenu (allocation);
+   WidgetStack *widgetStack = new WidgetStack (menu);
+   widgetStack->stack->push (new TypedPointer < ::fltk::Menu> (menu));
+   widgetStacks->append (widgetStack);
+
+
+   ::fltk::Menu *itemGroup;
+   ::fltk::Item *itemWidget;
+
+   ::fltk::Group *currGroup = widgetStack->stack->getTop()->getTypedValue();
+
+   int index = 0;
+   for (Iterator <Item> it = allItems->iterator (); it.hasNext (); ) {
+      Item *item = it.getNext ();
+      switch (item->type) {
+      case Item::ITEM:
+         itemWidget = item->createNewWidget (index++);
+         currGroup->add (itemWidget);
+         break;
+
+      case Item::START:
+         itemGroup = item->createNewGroupWidget ();
+         currGroup->add (itemGroup);
+         widgetStack->stack->push (new TypedPointer < ::fltk::Menu> (menu));
+         currGroup = itemGroup;
+         break;
+
+      case Item::END:
+         widgetStack->stack->pop ();
+         currGroup = widgetStack->stack->getTop()->getTypedValue();
+         break;
+      }
+   }
+
+   return menu;
+}
+
+template <class I>
+typename FltkSelectionResource<I>::Item *
+FltkSelectionResource<I>::createNewItem (typename Item::Type type,
+                                         const char *name,
+                                         bool enabled,
+                                         bool selected) {
+   return new Item(type,name,enabled,selected);
+}
+
+template <class I> void FltkSelectionResource<I>::addItem (const char *str,
+                                                           bool enabled,
+                                                           bool selected)
+{
+   int index = items->size ();
+   Item *item = createNewItem (Item::ITEM, str, enabled, selected);
+   items->put (item);
+   allItems->append (item);
+
+   for (Iterator <WidgetStack> it = widgetStacks->iterator ();
+        it.hasNext(); ) {
+      WidgetStack *widgetStack = it.getNext ();
+      ::fltk::Item *itemWidget = item->createNewWidget (index);
+      widgetStack->stack->getTop()->getTypedValue()->add (itemWidget);
+
+      if (!enabled)
+         itemWidget->deactivate ();
+
+      if (selected) {
+         itemWidget->set_selected();
+         if (setSelectedItems ()) {
+            // Handle multiple item selection.
+            int pos[widgetStack->stack->size ()];
+            int i;
+            Iterator <TypedPointer < ::fltk::Menu> > it;
+            for (it = widgetStack->stack->iterator (),
+                    i = widgetStack->stack->size () - 1;
+                 it.hasNext ();
+                 i--) {
+               TypedPointer < ::fltk::Menu> * p = it.getNext ();
+               pos[i] =  p->getTypedValue()->children () - 1;
+            }
+            widgetStack->widget->set_item (pos, widgetStack->stack->size ());
+         }
+      }
+   }
+}
+   
+template <class I> void FltkSelectionResource<I>::pushGroup (const char *name,
+                                                             bool enabled)
+{
+   Item *item = createNewItem (Item::START, name, enabled);
+   allItems->append (item);
+
+   for (Iterator <WidgetStack> it = widgetStacks->iterator ();
+        it.hasNext(); ) {
+      WidgetStack *widgetStack = it.getNext ();
+      ::fltk::ItemGroup *group = item->createNewGroupWidget ();
+      widgetStack->stack->getTop()->getTypedValue()->add (group);
+      widgetStack->stack->push (new TypedPointer < ::fltk::Menu> (group));
+      if(!enabled)
+         group->deactivate ();
+   }
+}
+
+template <class I> void FltkSelectionResource<I>::popGroup ()
+{
+   Item *item = createNewItem (Item::END);
+   allItems->append (item);
+
+   for (Iterator <WidgetStack> it = widgetStacks->iterator ();
+        it.hasNext(); ) {
+      WidgetStack *widgetStack = it.getNext ();
+      widgetStack->stack->pop ();
+   }
+}
+
+template <class I> int FltkSelectionResource<I>::getNumberOfItems ()
+{
+   return items->size ();
+}
+
+template <class I> const char *FltkSelectionResource<I>::getItem (int index)
+{
+   return items->get(index)->name;
+}
+
+template <class I> int FltkSelectionResource<I>::getMaxStringWidth ()
+{
+   int width = 0, numberOfItems = getNumberOfItems ();
+   for (int i = 0; i < numberOfItems; i++) {
+      int len = (int)::fltk::getwidth (getItem(i));
+      if (len > width) width = len;
+   }
+   return width;
+}
+
+// ----------------------------------------------------------------------
+
+FltkOptionMenuResource::FltkOptionMenuResource (FltkPlatform *platform):
+   FltkSelectionResource <dw::core::ui::OptionMenuResource> (platform),
+   selection(-1)
+{
+   init (platform);
+}
+
+FltkOptionMenuResource::~FltkOptionMenuResource ()
+{
+}
+
+
+::fltk::Menu *FltkOptionMenuResource::createNewMenu (core::Allocation
+                                                     *allocation)
+{
+   ::fltk::Menu *menu =
+      new ::fltk::Choice (allocation->x, allocation->y,
+                          allocation->width,
+                          allocation->ascent + allocation->descent);
+   menu->callback(widgetCallback,this);
+   return menu;
+}
+
+void FltkOptionMenuResource::widgetCallback (::fltk::Widget *widget,
+                                             void *data)
+{
+   ((FltkOptionMenuResource *) data)->selection =
+      (long) (((::fltk::Menu *) widget)->item()->user_data());
+}
+
+void FltkOptionMenuResource::sizeRequest (core::Requisition *requisition)
+{
+   if (style) {
+      FltkFont *font = (FltkFont*)style->font;
+      ::fltk::setfont(font->font,font->size);
+      int maxStringWidth = getMaxStringWidth ();
+      requisition->ascent = font->ascent + RELIEF_Y_THICKNESS;
+      requisition->descent = font->descent + RELIEF_Y_THICKNESS;
+      requisition->width = maxStringWidth
+         + (requisition->ascent + requisition->descent) * 4 / 5
+         + 2 * RELIEF_X_THICKNESS;
+   } else {
+      requisition->width = 1;
+      requisition->ascent = 1;
+      requisition->descent = 0;
+   } 
+}
+
+void FltkOptionMenuResource::addItem (const char *str,
+                                      bool enabled, bool selected)
+{
+   FltkSelectionResource<dw::core::ui::OptionMenuResource>::addItem
+      (str,enabled,selected);
+   if (selected)
+      selection = (items->size ()) - 1;
+
+   queueResize (true);
+}
+
+bool FltkOptionMenuResource::isSelected (int index)
+{
+   return index == selection;
+}
+
+// ----------------------------------------------------------------------
+
+FltkListResource::FltkListResource (FltkPlatform *platform,
+                                    core::ui::ListResource::SelectionMode
+                                    selectionMode):
+   FltkSelectionResource <dw::core::ui::ListResource> (platform),
+   itemsSelected(8)
+{
+   init (platform);
+}
+
+FltkListResource::~FltkListResource ()
+{
+}
+
+
+::fltk::Menu *FltkListResource::createNewMenu (core::Allocation *allocation)
+{
+   ::fltk::Menu *menu =
+      new ::fltk::MultiBrowser (allocation->x, allocation->y,
+                                allocation->width,
+                                allocation->ascent + allocation->descent);
+   menu->callback(widgetCallback,this);
+   menu->when(::fltk::WHEN_CHANGED);
+   return menu;
+}
+
+void FltkListResource::widgetCallback (::fltk::Widget *widget, void *data)
+{
+   ::fltk::Widget *fltkItem = ((::fltk::Menu *) widget)->item ();
+   int index = (long) (fltkItem->user_data ());
+   if (index > -1) {
+      bool selected = fltkItem->selected ();
+      ((FltkListResource *) data)->itemsSelected.set (index, selected);
+   }
+}
+
+void FltkListResource::addItem (const char *str, bool enabled, bool selected)
+{
+   FltkSelectionResource<dw::core::ui::ListResource>::addItem
+      (str,enabled,selected);
+   int index = itemsSelected.size ();
+   itemsSelected.increase ();
+   itemsSelected.set (index,selected);
+   queueResize (true);
+}
+
+void FltkListResource::sizeRequest (core::Requisition *requisition)
+{
+   if (style) {
+      FltkFont *font = (FltkFont*)style->font;
+      ::fltk::setfont(font->font,font->size);
+      int maxStringWidth = getMaxStringWidth ();
+      requisition->ascent = font->ascent + RELIEF_Y_THICKNESS;
+      requisition->descent =
+         (getNumberOfItems () - 1) * (font->ascent) + font->descent;
+      requisition->width = maxStringWidth
+         + (font->ascent + font->descent) * 4 / 5
+         + 2 * RELIEF_X_THICKNESS;
+   } else {
+      requisition->width = 1;
+      requisition->ascent = 1;
+      requisition->descent = 0;
+   } 
+}
+
+bool FltkListResource::isSelected (int index)
+{
+   return itemsSelected.get (index);
+}
+
+} // namespace ui
+} // namespace fltk
+} // namespace dw
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkui.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,554 @@
+#ifndef __DW_FLTK_UI_HH__
+#define __DW_FLTK_UI_HH__
+
+#ifndef __INCLUDED_FROM_DW_FLTK_CORE_HH__
+#   error Do not include this file directly, use "fltkcore.hh" instead.
+#endif
+
+#include <fltk/Button.h>
+#include <fltk/Menu.h>
+#include <fltk/TextBuffer.h>
+#include <fltk/Item.h>
+#include <fltk/ItemGroup.h>
+
+namespace dw {
+namespace fltk {
+
+using namespace lout;
+
+/**
+ * \brief FLTK implementation of dw::core::ui.
+ *
+ * The design should be like this:
+ *
+ * \dot
+ * digraph G {
+ *    node [shape=record, fontname=Helvetica, fontsize=10];
+ *    edge [arrowhead="none", arrowtail="empty", labelfontname=Helvetica,
+ *          labelfontsize=10, color="#404040", labelfontcolor="#000080"];
+ *    fontname=Helvetica; fontsize=10;
+ * 
+ *    subgraph cluster_core {
+ *       style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ *       label="dw::core::ui";
+ *
+ *       Resource [color="#a0a0a0", URL="\ref dw::core::ui::Resource"];
+ *       LabelButtonResource [color="#a0a0a0",
+ *                            URL="\ref dw::core::ui::LabelButtonResource"];
+ *       EntryResource [color="#a0a0a0",
+ *                      URL="\ref dw::core::ui::EntryResource"];
+ *    }
+ *
+ *    subgraph cluster_fltk {
+ *       style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ *       label="dw::fltk::ui";
+ *
+ *       FltkResource [color="#a0a0a0", URL="\ref dw::fltk::ui::FltkResource"];
+ *       FltkLabelButtonResource
+ *          [URL="\ref dw::fltk::ui::FltkLabelButtonResource"];
+ *       FltkEntryResource [URL="\ref dw::fltk::ui::FltkEntryResource"];
+ *    }
+ *
+ *    Resource -> LabelButtonResource;
+ *    Resource -> EntryResource;
+ *    FltkResource -> FltkLabelButtonResource;
+ *    FltkResource -> FltkEntryResource;
+ *    Resource -> FltkResource;
+ *    LabelButtonResource -> FltkLabelButtonResource;
+ *    EntryResource -> FltkEntryResource;
+ * }
+ * \enddot
+ *
+ * <center>[\ref uml-legend "legend"]</center>
+ *
+ * where dw::fltk::ui::FltkResource provides some base funtionality for all
+ * conctrete FLTK implementations of sub-interfaces of dw::core::ui::Resource.
+ * However, this is not directly possible in C++, since the base class
+ * dw::core::ui::Resource is ambiguous for
+ * dw::fltk::ui::FltkLabelButtonResource.
+ *
+ * To solve this, we have to remove the depencency between
+ * dw::fltk::ui::FltkResource and dw::core::ui::Resource, instead, the part
+ * of dw::core::ui::Resource, which is implemented in
+ * dw::fltk::ui::FltkResource, must be explicitely delegated from
+ * dw::fltk::ui::FltkLabelButtonResourceto dw::fltk::ui::FltkResource:
+ *
+ * \dot
+ * digraph G {
+ *    node [shape=record, fontname=Helvetica, fontsize=10];
+ *    edge [arrowhead="none", arrowtail="empty", labelfontname=Helvetica,
+ *          labelfontsize=10, color="#404040", labelfontcolor="#000080"];
+ *    fontname=Helvetica; fontsize=10;
+ * 
+ *    subgraph cluster_core {
+ *       style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ *       label="dw::core::ui";
+ *
+ *       Resource [color="#a0a0a0", URL="\ref dw::core::ui::Resource"];
+ *       LabelButtonResource [color="#a0a0a0",
+ *                           URL="\ref dw::core::ui::LabelButtonResource"];
+ *       EntryResource [color="#a0a0a0",
+ *                      URL="\ref dw::core::ui::EntryResource"];
+ *    }
+ *
+ *    subgraph cluster_fltk {
+ *       style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ *       label="dw::fltk::ui";
+ *
+ *       FltkResource [color="#a0a0a0", URL="\ref dw::fltk::ui::FltkResource"];
+ *       FltkLabelButtonResource
+ *          [URL="\ref dw::fltk::ui::FltkLabelButtonResource"];
+ *       FltkEntryResource [URL="\ref dw::fltk::ui::FltkEntryResource"];
+ *    }
+ *
+ *    Resource -> LabelButtonResource;
+ *    Resource -> EntryResource;
+ *    FltkResource -> FltkLabelButtonResource;
+ *    FltkResource -> FltkEntryResource;
+ *    LabelButtonResource -> FltkLabelButtonResource;
+ *    EntryResource -> FltkEntryResource;
+ * }
+ * \enddot
+ *
+ * <center>[\ref uml-legend "legend"]</center>
+ *
+ * To make this a bit simpler, we use templates:
+ *
+ * \dot
+ * digraph G {
+ *    node [shape=record, fontname=Helvetica, fontsize=10];
+ *    edge [arrowhead="none", arrowtail="empty", labelfontname=Helvetica,
+ *          labelfontsize=10, color="#404040", labelfontcolor="#000080"];
+ *    fontname=Helvetica; fontsize=10;
+ * 
+ *    subgraph cluster_core {
+ *       style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ *       label="dw::core::ui";
+ *
+ *       Resource [color="#a0a0a0", URL="\ref dw::core::ui::Resource"];
+ *       LabelButtonResource [color="#a0a0a0",
+ *                            URL="\ref dw::core::ui::LabelButtonResource"];
+ *       EntryResource [color="#a0a0a0",
+ *                      URL="\ref dw::core::ui::EntryResource"];
+ *    }
+ *
+ *    subgraph cluster_fltk {
+ *       style="dashed"; color="#000080"; fontname=Helvetica; fontsize=10;
+ *       label="dw::fltk::ui";
+ *
+ *       FltkResource [color="#a0a0a0", URL="\ref dw::fltk::ui::FltkResource"];
+ *       FltkSpecificResource [color="#a0a0a0",
+ *                             fillcolor="#ffffc0", style="filled"
+ *                             URL="\ref dw::fltk::ui::FltkSpecificResource"];
+ *       FltkSpecificResource_button [color="#a0a0a0",
+ *                       label="FltkSpecificResource \<LabelButtonResource\>"];
+ *       FltkSpecificResource_entry [color="#a0a0a0",
+ *                             label="FltkSpecificResource \<EntryResource\>"];
+ *       FltkEntryResource [URL="\ref dw::fltk::ui::FltkEntryResource"];
+ *       FltkLabelButtonResource
+ *          [URL="\ref dw::fltk::ui::FltkLabelButtonResource"];
+ *    }
+ *
+ *    Resource -> LabelButtonResource;
+ *    Resource -> EntryResource;
+ *    FltkResource -> FltkSpecificResource;
+ *    FltkSpecificResource -> FltkSpecificResource_button [arrowhead="open",
+ *                                                         arrowtail="none",
+ *                                                         style="dashed",
+ *                                                         color="#808000"];
+ *    FltkSpecificResource -> FltkSpecificResource_entry [arrowhead="open",
+ *                                                        arrowtail="none",
+ *                                                        style="dashed",
+ *                                                        color="#808000"];
+ *    LabelButtonResource -> FltkSpecificResource_button;
+ *    EntryResource -> FltkSpecificResource_entry;
+ *    FltkSpecificResource_button -> FltkLabelButtonResource;
+ *    FltkSpecificResource_entry -> FltkEntryResource;
+ * }
+ * \enddot
+ *
+ * <center>[\ref uml-legend "legend"]</center>
+ */
+namespace ui {
+
+/**
+ * ...
+ */
+class FltkResource: public object::Object
+{
+protected:
+   class ViewAndWidget: public object::Object
+   {
+   public:
+      FltkView *view;
+      ::fltk::Widget *widget;
+   };
+
+   container::typed::List <ViewAndWidget> *viewsAndWidgets;
+   core::Allocation allocation;
+   FltkPlatform *platform;
+
+   core::style::Style *style;
+
+   FltkResource (FltkPlatform *platform);
+   void init (FltkPlatform *platform);
+   virtual ::fltk::Widget *createNewWidget (core::Allocation *allocation) = 0;
+
+   void setWidgetStyle (::fltk::Widget *widget, core::style::Style *style);
+public:
+   ~FltkResource ();
+
+   virtual void attachView (FltkView *view);
+   virtual void detachView (FltkView *view);
+   
+   void sizeAllocate (core::Allocation *allocation);
+   void draw (core::View *view, core::Rectangle *area);
+
+   void setStyle (core::style::Style *style);
+
+   bool isEnabled ();
+   void setEnabled (bool enabled);
+};
+
+
+template <class I> class FltkSpecificResource: public I, public FltkResource
+{
+public:
+   inline FltkSpecificResource (FltkPlatform *platform) :
+      FltkResource (platform) { }
+
+   void sizeAllocate (core::Allocation *allocation);
+   void draw (core::View *view, core::Rectangle *area);
+   void setStyle (core::style::Style *style);
+
+   bool isEnabled ();
+   void setEnabled (bool enabled);
+};
+
+
+class FltkLabelButtonResource:
+   public FltkSpecificResource <dw::core::ui::LabelButtonResource>
+{
+private:
+   const char *label;
+
+   static void widgetCallback (::fltk::Widget *widget, void *data);
+
+protected:
+   ::fltk::Widget *createNewWidget (core::Allocation *allocation);
+
+public:
+   FltkLabelButtonResource (FltkPlatform *platform, const char *label);
+   ~FltkLabelButtonResource ();
+
+   void sizeRequest (core::Requisition *requisition);
+
+   const char *getLabel ();
+   void setLabel (const char *label);
+};
+
+
+class FltkComplexButtonResource:
+   public FltkSpecificResource <dw::core::ui::ComplexButtonResource>
+{
+private:
+   bool relief;
+
+   static void widgetCallback (::fltk::Widget *widget, void *data);
+
+protected:
+   class ViewAndView: public object::Object
+   {
+   public:
+      FltkView *topView, *flatView;
+   };
+
+   FltkView *lastFlatView;
+
+   container::typed::List <ViewAndView> *viewsAndViews;
+
+   void attachView (FltkView *view);
+   void detachView (FltkView *view);
+
+   void sizeAllocate (core::Allocation *allocation);
+
+   dw::core::Platform *createPlatform ();
+   void setLayout (dw::core::Layout *layout);
+   
+   int reliefXThickness ();
+   int reliefYThickness ();
+
+   ::fltk::Widget *createNewWidget (core::Allocation *allocation);
+
+public:
+   FltkComplexButtonResource (FltkPlatform *platform, dw::core::Widget *widget,
+                              bool relief);
+   ~FltkComplexButtonResource ();
+};
+
+
+/**
+ * \bug Maximal length not supported yet.
+ * \todo Text values are not synchronized (not needed in dillo).
+ */
+class FltkEntryResource:
+   public FltkSpecificResource <dw::core::ui::EntryResource>
+{
+private:
+   int maxLength;
+   bool password;
+   const char *initText;
+   bool editable;
+
+   static void widgetCallback (::fltk::Widget *widget, void *data);
+
+protected:
+   ::fltk::Widget *createNewWidget (core::Allocation *allocation);
+
+public:
+   FltkEntryResource (FltkPlatform *platform, int maxLength, bool password);
+   ~FltkEntryResource ();
+
+   void sizeRequest (core::Requisition *requisition);
+
+   const char *getText ();
+   void setText (const char *text);
+   bool isEditable ();
+   void setEditable (bool editable);
+};
+
+
+class FltkMultiLineTextResource:
+   public FltkSpecificResource <dw::core::ui::MultiLineTextResource>
+{
+private:
+   ::fltk::TextBuffer *buffer;
+   bool editable;
+   int numCols, numRows;
+
+protected:
+   ::fltk::Widget *createNewWidget (core::Allocation *allocation);
+
+public:
+   FltkMultiLineTextResource (FltkPlatform *platform, int cols, int rows);
+   ~FltkMultiLineTextResource ();
+
+   void sizeRequest (core::Requisition *requisition);
+
+   const char *getText ();
+   void setText (const char *text);
+   bool isEditable ();
+   void setEditable (bool editable);
+};
+
+
+template <class I> class FltkToggleButtonResource:
+   public FltkSpecificResource <I>
+{
+private:
+   bool initActivated;
+
+protected:
+   virtual ::fltk::Button *createNewButton (core::Allocation *allocation) = 0;
+   ::fltk::Widget *createNewWidget (core::Allocation *allocation);
+   
+public:
+   FltkToggleButtonResource (FltkPlatform *platform,
+                             bool activated);
+   ~FltkToggleButtonResource ();
+
+   void sizeRequest (core::Requisition *requisition);
+
+   bool isActivated ();
+   void setActivated (bool activated);
+};
+
+
+class FltkCheckButtonResource:
+   public FltkToggleButtonResource <dw::core::ui::CheckButtonResource>
+{
+protected:
+   ::fltk::Button *createNewButton (core::Allocation *allocation);
+
+public:
+   FltkCheckButtonResource (FltkPlatform *platform,
+                            bool activated);
+   ~FltkCheckButtonResource ();
+};
+
+
+class FltkRadioButtonResource:
+   public FltkToggleButtonResource <dw::core::ui::RadioButtonResource>
+{
+private:
+   class Group
+   {
+   private:
+      class FltkGroupIterator:
+         public dw::core::ui::RadioButtonResource::GroupIterator
+      {
+      private:
+         container::typed::Iterator <FltkRadioButtonResource> it;
+
+      public:
+         inline FltkGroupIterator (container::typed::List
+                                   <FltkRadioButtonResource>
+                                   *list)
+            { it = list->iterator (); }
+
+         bool hasNext ();
+         dw::core::ui::RadioButtonResource *getNext ();
+         void unref ();
+      };
+
+      container::typed::List <FltkRadioButtonResource> *list;
+
+   protected:
+      ~Group ();
+
+   public:
+      Group (FltkRadioButtonResource *radioButtonResource);
+      
+      inline container::typed::Iterator <FltkRadioButtonResource> iterator ()
+      {
+         return list->iterator ();
+      }
+
+      inline dw::core::ui::RadioButtonResource::GroupIterator
+         *groupIterator ()
+      {
+         return new FltkGroupIterator (list);
+      }
+
+      void connect (FltkRadioButtonResource *radioButtonResource);
+      void unconnect (FltkRadioButtonResource *radioButtonResource);
+   };
+
+   Group *group;
+
+   static void widgetCallback (::fltk::Widget *widget, void *data);
+   void buttonClicked ();
+
+protected:
+   ::fltk::Button *createNewButton (core::Allocation *allocation);
+
+public:
+   FltkRadioButtonResource (FltkPlatform *platform,
+                            FltkRadioButtonResource *groupedWith,
+                            bool activated);
+   ~FltkRadioButtonResource ();
+
+   GroupIterator *groupIterator ();
+};
+
+
+template <class I> class FltkSelectionResource:
+   public FltkSpecificResource <I>
+{
+protected:
+   class Item: public object::Object
+   {
+   public:
+      enum Type { ITEM, START, END } type;
+
+      const char *name;
+      bool enabled, initSelected;
+
+      Item (Type type, const char *name = NULL, bool enabled = true,
+            bool selected = false);
+      ~Item ();
+
+      ::fltk::Item *createNewWidget (int index);
+      ::fltk::ItemGroup *createNewGroupWidget ();
+   };
+
+   class WidgetStack: public object::Object
+   {
+   public:
+      ::fltk::Menu *widget;
+      container::typed::Stack <object::TypedPointer < ::fltk::Menu> > *stack;
+
+      WidgetStack (::fltk::Menu *widget);
+      ~WidgetStack ();
+   };
+
+   container::typed::List <WidgetStack> *widgetStacks;
+   container::typed::List <Item> *allItems;
+   container::typed::Vector <Item> *items;
+
+   Item *createNewItem (typename Item::Type type,
+                        const char *name = NULL,
+                        bool enabled = true,
+                        bool selected = false);
+
+   ::fltk::Widget *createNewWidget (core::Allocation *allocation);
+   virtual ::fltk::Menu *createNewMenu (core::Allocation *allocation) = 0;
+   virtual bool setSelectedItems() { return false; }
+
+   int getMaxStringWidth ();
+
+public:
+   FltkSelectionResource (FltkPlatform *platform);
+   ~FltkSelectionResource ();
+
+   dw::core::Iterator *iterator (dw::core::Content::Type mask, bool atEnd); 
+
+   void addItem (const char *str, bool enabled, bool selected);
+   
+   void pushGroup (const char *name, bool enabled);
+   void popGroup ();
+
+   int getNumberOfItems ();
+   const char *getItem (int index);
+};
+
+
+class FltkOptionMenuResource:
+   public FltkSelectionResource <dw::core::ui::OptionMenuResource>
+{
+protected:
+   ::fltk::Menu *createNewMenu (core::Allocation *allocation);
+   virtual bool setSelectedItems() { return true; }
+
+private:
+   static void widgetCallback (::fltk::Widget *widget, void *data);
+   int selection;
+
+public:
+   FltkOptionMenuResource (FltkPlatform *platform);
+   ~FltkOptionMenuResource ();
+
+   void addItem (const char *str, bool enabled, bool selected);
+
+   void sizeRequest (core::Requisition *requisition);
+   bool isSelected (int index);
+};
+
+class FltkListResource:
+   public FltkSelectionResource <dw::core::ui::ListResource>
+{
+protected:
+   ::fltk::Menu *createNewMenu (core::Allocation *allocation);
+
+private:
+   static void widgetCallback (::fltk::Widget *widget, void *data);
+   misc::SimpleVector <bool> itemsSelected;
+
+public:
+   FltkListResource (FltkPlatform *platform,
+                     core::ui::ListResource::SelectionMode selectionMode);
+   ~FltkListResource ();
+
+   void addItem (const char *str, bool enabled, bool selected);
+
+   void sizeRequest (core::Requisition *requisition);
+   bool isSelected (int index);
+};
+
+
+} // namespace ui
+} // namespace fltk
+} // namespace dw
+
+
+#endif // __DW_FLTK_UI_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkviewbase.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,524 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "fltkviewport.hh"
+
+#include <fltk/draw.h>
+#include <fltk/damage.h>
+#include <fltk/layout.h>
+#include <fltk/events.h>
+#include <fltk/Cursor.h>
+#include <fltk/run.h>
+
+#include <stdio.h>
+
+using namespace fltk;
+using namespace lout::object;
+using namespace lout::container::typed;
+
+namespace dw {
+namespace fltk {
+
+::fltk::Image *FltkViewBase::backBuffer;
+bool FltkViewBase::backBufferInUse;
+
+FltkViewBase::FltkViewBase (int x, int y, int w, int h, const char *label):
+   Group (x, y, w, h, label)
+{
+   canvasWidth = 1;
+   canvasHeight = 1;
+   bgColor = WHITE;
+   lastDraw = time(0);
+   drawDelay = 2;      /* in seconds */
+   mouse_x = mouse_y = 0;
+#ifndef NO_DOUBLEBUFFER
+   if (!backBuffer) {
+      backBuffer = new Image ();
+   }
+#endif
+}
+
+FltkViewBase::~FltkViewBase ()
+{
+   cancelQueueDraw ();
+}
+
+void FltkViewBase::draw ()
+{
+   int d = damage ();
+
+   if ((d & DAMAGE_VALUE) && !(d & DAMAGE_EXPOSE)) {
+      container::typed::Iterator <core::Rectangle> it;
+
+      for (it = drawRegion.rectangles (); it.hasNext (); ) {
+         drawRectangle (it.getNext (), true);
+      }
+
+      drawRegion.clear ();
+      d &= ~DAMAGE_VALUE;
+   }
+
+   if (d & DAMAGE_CHILD) {
+      drawChildWidgets ();
+      d &= ~DAMAGE_CHILD;
+   }
+
+   if (d) {
+      dw::core::Rectangle rect (
+         translateViewXToCanvasX (0),
+         translateViewYToCanvasY (0),
+         w (),
+         h ());
+
+      drawRectangle (&rect, false);
+
+      if (! (d & DAMAGE_SCROLL)) {
+         drawRegion.clear ();
+      }
+   }
+}
+
+void FltkViewBase::drawRectangle (const core::Rectangle *rect,
+                                  bool doubleBuffer)
+{
+   int offsetX = 0, offsetY = 0;
+
+   /* fltk-clipping does not use widget coordinates */
+   transform (offsetX, offsetY);
+
+   ::fltk::Rectangle viewRect (
+      translateCanvasXToViewX (rect->x) + offsetX,
+      translateCanvasYToViewY (rect->y) + offsetY,
+      rect->width, rect->height);
+   
+   ::fltk::intersect_with_clip (viewRect);
+
+   viewRect.x (viewRect.x () - offsetX);
+   viewRect.y (viewRect.y () - offsetY);
+
+   if (! viewRect.empty ()) {
+      dw::core::Rectangle r (
+         translateViewXToCanvasX (viewRect.x ()),
+         translateViewYToCanvasY (viewRect.y ()),
+         viewRect.w (),
+         viewRect.h ());
+
+#ifdef NO_DOUBLEBUFFER
+      push_clip (viewRect);
+#endif
+
+      if (doubleBuffer && backBuffer && !backBufferInUse) {
+         backBufferInUse = true;
+         {
+            GSave gsave;
+
+            backBuffer->setsize (viewRect.w (), viewRect.h ());
+            backBuffer->make_current ();
+            translate (-viewRect.x (), -viewRect.y ());   
+
+            setcolor (bgColor);
+            fillrect (viewRect);
+            theLayout->expose (this, &r);
+         }
+
+         backBuffer->draw (Rectangle (0, 0, viewRect.w (), viewRect.h ()),
+            viewRect);
+
+         backBufferInUse = false;
+      } else {
+         setcolor (bgColor);
+         fillrect (viewRect);
+         theLayout->expose (this, &r);
+      }
+
+#ifdef NO_DOUBLEBUFFER
+      pop_clip ();
+#endif
+   }
+}
+
+void FltkViewBase::drawChildWidgets () {
+   for (int i = children () - 1; i >= 0; i--) {
+      Widget& w = *child(i);
+      if (w.damage() & DAMAGE_CHILD_LABEL) {
+         draw_outside_label(w);
+         w.set_damage(w.damage() & ~DAMAGE_CHILD_LABEL);
+      }
+      update_child(w);
+   }
+}
+
+core::ButtonState getDwButtonState ()
+{
+   int s1 = event_state ();
+   int s2 = (core::ButtonState)0;
+   
+   if(s1 & SHIFT)   s2 |= core::SHIFT_MASK;
+   if(s1 & CTRL)    s2 |= core::CONTROL_MASK;
+   if(s1 & ALT)     s2 |= core::META_MASK;
+   if(s1 & BUTTON1) s2 |= core::BUTTON1_MASK;
+   if(s1 & BUTTON2) s2 |= core::BUTTON2_MASK;
+   if(s1 & BUTTON3) s2 |= core::BUTTON3_MASK;
+
+   return (core::ButtonState)s2;
+}
+
+int FltkViewBase::handle (int event)
+{
+   bool processed;
+
+   /**
+    * \todo Consider, whether this from the FLTK documentation has any 
+    *    impacts: "To receive fltk::RELEASE events you must return non-zero
+    *    when passed a fltk::PUSH event. "
+    */
+   switch(event) {
+   case PUSH:
+      processed =
+         theLayout->buttonPress (this, event_clicks () + 1,
+                                 translateViewXToCanvasX (event_x ()),
+                                 translateViewYToCanvasY (event_y ()),
+                                 getDwButtonState (), event_button ());
+      //printf ("PUSH => %s\n", processed ? "true" : "false");
+      return processed ? true : Group::handle (event);
+
+   case RELEASE:
+      processed =
+         theLayout->buttonRelease (this, event_clicks () + 1,
+                                   translateViewXToCanvasX (event_x ()),
+                                   translateViewYToCanvasY (event_y ()),
+                                   getDwButtonState (), event_button ());
+      //printf ("RELEASE => %s\n", processed ? "true" : "false");
+      return processed ? true : Group::handle (event);
+
+   case MOVE:
+      mouse_x = event_x();
+      mouse_y = event_y();
+      processed =
+         theLayout->motionNotify (this,
+                                  translateViewXToCanvasX (mouse_x),
+                                  translateViewYToCanvasY (mouse_y),
+                                  getDwButtonState ());
+      //printf ("MOVE => %s\n", processed ? "true" : "false");
+      return processed ? true : Group::handle (event);
+
+   case DRAG:
+      processed =
+         theLayout->motionNotify (this,
+                                  translateViewXToCanvasX (event_x ()),
+                                  translateViewYToCanvasY (event_y ()),
+                                  getDwButtonState ());
+      //printf ("DRAG => %s\n", processed ? "true" : "false");
+      return processed ? true : Group::handle (event);
+
+   case ENTER:
+      theLayout->enterNotify (this, translateViewXToCanvasX (event_x ()),
+                              translateViewYToCanvasY (event_y ()),
+                              getDwButtonState ());
+      return Group::handle (event);
+
+   case LEAVE:
+      theLayout->leaveNotify (this, getDwButtonState ());
+      return Group::handle (event);
+      
+   default:
+      return Group::handle (event);
+   }
+}
+
+// ----------------------------------------------------------------------
+
+void FltkViewBase::setLayout (core::Layout *layout)
+{
+   theLayout = layout;
+}
+
+void FltkViewBase::setCanvasSize (int width, int ascent, int descent)
+{
+   canvasWidth = width;
+   canvasHeight = ascent + descent;
+}
+
+void FltkViewBase::setCursor (core::style::Cursor cursor)
+{
+   static Cursor *mapDwToFltk[] = {
+      CURSOR_CROSS,
+      CURSOR_ARROW,
+      CURSOR_HAND,
+      CURSOR_MOVE,
+      CURSOR_WE,
+      CURSOR_NESW,
+      CURSOR_NWSE,
+      CURSOR_NS,
+      CURSOR_NWSE,
+      CURSOR_NESW,
+      CURSOR_NS,
+      CURSOR_WE,
+      CURSOR_INSERT,
+      CURSOR_WAIT,
+      CURSOR_HELP
+   };
+
+   /*
+   static char *cursorName[] = {
+      "CURSOR_CROSS",
+      "CURSOR_ARROW",
+      "CURSOR_HAND",
+      "CURSOR_MOVE",
+      "CURSOR_WE",
+      "CURSOR_NESW",
+      "CURSOR_NWSE",
+      "CURSOR_NS",
+      "CURSOR_NWSE",
+      "CURSOR_NESW",
+      "CURSOR_NS",
+      "CURSOR_WE",
+      "CURSOR_INSERT",
+      "CURSOR_WAIT",
+      "CURSOR_HELP"
+   };
+
+   printf ("Cursor changes to '%s'.\n", cursorName[cursor]);
+   */
+
+   /** \bug Does not work */
+   this->cursor (mapDwToFltk[cursor]);
+}
+
+void FltkViewBase::setBgColor (core::style::Color *color)
+{
+   bgColor = color ?
+      ((FltkColor*)color)->colors[dw::core::style::Color::SHADING_NORMAL] :
+      WHITE;
+}
+
+void FltkViewBase::startDrawing (core::Rectangle *area)
+{
+}
+
+void FltkViewBase::finishDrawing (core::Rectangle *area)
+{
+}
+
+void FltkViewBase::queueDraw (core::Rectangle *area)
+{
+   drawRegion.addRectangle (area);
+   /** DAMAGE_VALUE is just an arbitrary value other than DAMAGE_EXPOSE here */
+   redraw (DAMAGE_VALUE);
+}
+
+static void drawTotalTimeout (void *data)
+{
+   FltkViewBase *view = (FltkViewBase*) data;
+   if (time(0) >= view->lastDraw + view->drawDelay) {
+      view->drawTotal ();
+   } else {
+      ::fltk::add_timeout (0.2f, drawTotalTimeout, data);
+   }
+}
+
+void FltkViewBase::drawTotal ()
+{
+   //static int calls = 0;
+   //printf(" FltkViewBase::drawTotal calls = %d\n", ++calls);
+   redraw (DAMAGE_EXPOSE);
+   lastDraw = time (0);
+   cancelQueueDraw ();
+}
+
+void FltkViewBase::queueDrawTotal ()
+{
+   drawTotal ();
+}
+
+void FltkViewBase::cancelQueueDraw ()
+{
+   ::fltk::remove_timeout (drawTotalTimeout, this);
+}
+
+void FltkViewBase::drawPoint (core::style::Color *color,
+                              core::style::Color::Shading shading,
+                              int x, int y)
+{
+}
+
+void FltkViewBase::drawLine (core::style::Color *color,
+                             core::style::Color::Shading shading,
+                             int x1, int y1, int x2, int y2)
+{
+   setcolor(((FltkColor*)color)->colors[shading]);
+   drawline (translateCanvasXToViewX (x1), translateCanvasYToViewY (y1),
+             translateCanvasXToViewX (x2), translateCanvasYToViewY (y2));
+}
+
+void FltkViewBase::drawRectangle (core::style::Color *color,
+                                  core::style::Color::Shading shading,
+                                  bool filled,
+                                  int x, int y, int width, int height)
+{
+   setcolor(((FltkColor*)color)->colors[shading]);
+   int x1 = translateCanvasXToViewX (x);
+   int y1 = translateCanvasYToViewY (y);
+   int x2 = translateCanvasXToViewX (x + width);
+   int y2 = translateCanvasYToViewY (y + height);
+   ::fltk::Rectangle rect (x1, y1, x2 - x1, y2 - y1);
+   if (filled)
+      fillrect (rect);
+   else
+      strokerect (rect);
+}
+
+void FltkViewBase::drawArc (core::style::Color *color,
+                            core::style::Color::Shading shading, bool filled,
+                            int x, int y, int width, int height,
+                            int angle1, int angle2)
+{
+   setcolor(((FltkColor*)color)->colors[shading]);
+   int x1 = translateCanvasXToViewX (x);
+   int y1 = translateCanvasYToViewY (y);
+   ::fltk::Rectangle rect (x1, y1, width, height);
+   addchord(rect, angle1, angle2);
+   closepath();
+   if (filled)
+      fillpath();
+   else
+      strokepath();
+}
+
+void FltkViewBase::drawPolygon (core::style::Color *color,
+                                core::style::Color::Shading shading,
+                                bool filled, int points[][2], int npoints)
+{
+   if (npoints > 0) {
+      for (int i = 0; i < npoints; i++) {
+         points[i][0] = translateCanvasXToViewX(points[i][0]);
+         points[i][1] = translateCanvasYToViewY(points[i][1]);
+      }
+      setcolor(((FltkColor*)color)->colors[shading]);
+      addvertices(npoints, points);
+      closepath();
+      if (filled)
+         fillpath();
+      else
+         strokepath();
+   }         
+}
+
+core::View *FltkViewBase::getClippingView (int x, int y, int width, int height)
+{
+   push_clip (translateCanvasXToViewX (x), translateCanvasYToViewY (y),
+              width, height);
+   return this;
+}
+
+void FltkViewBase::mergeClippingView (core::View *clippingView)
+{
+   pop_clip ();
+}
+
+// ----------------------------------------------------------------------
+
+FltkWidgetView::FltkWidgetView (int x, int y, int w, int h,
+                                const char *label):
+   FltkViewBase (x, y, w, h, label)
+{
+}
+
+FltkWidgetView::~FltkWidgetView ()
+{
+}
+
+void FltkWidgetView::layout () {
+   /**
+    * pass layout to child widgets. This is needed for complex fltk 
+    * widgets as TextEditor.
+    * We can't use Group::layout() as that would rearrange the widgets.
+    */
+   for (int i = children () - 1; i >= 0; i--) {
+      ::fltk::Widget *widget = child (i);
+
+      if (widget->layout_damage ()) {
+         widget->layout ();
+      }
+   }
+}
+
+void FltkWidgetView::drawText (core::style::Font *font,
+                             core::style::Color *color,
+                             core::style::Color::Shading shading,
+                             int x, int y, const char *text, int len)
+{
+   FltkFont *ff = (FltkFont*)font;
+   setfont(ff->font, ff->size);
+   setcolor(((FltkColor*)color)->colors[shading]);
+   drawtext(text, len,
+            translateCanvasXToViewX (x), translateCanvasYToViewY (y));
+}
+
+void FltkWidgetView::drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot,
+                              int x, int y, int width, int height)
+{
+   ((FltkImgbuf*)imgbuf)->draw (this,
+                                translateCanvasXToViewX (xRoot),
+                                translateCanvasYToViewY (yRoot),
+                                x, y, width, height);
+}
+
+bool FltkWidgetView::usesFltkWidgets ()
+{
+   return true;
+}
+
+void FltkWidgetView::addFltkWidget (::fltk::Widget *widget,
+                                  core::Allocation *allocation)
+{
+   allocateFltkWidget (widget, allocation);
+   add (widget);
+}
+
+void FltkWidgetView::removeFltkWidget (::fltk::Widget *widget)
+{
+   remove (widget);
+}
+
+void FltkWidgetView::allocateFltkWidget (::fltk::Widget *widget,
+                                       core::Allocation *allocation)
+{
+   widget->x (translateCanvasXToViewX (allocation->x));
+   widget->y (translateCanvasYToViewY (allocation->y));
+   widget->w (allocation->width);
+   widget->h (allocation->ascent + allocation->descent);
+
+   /* widgets created tiny and later resized need this flag to display */
+   uchar damage = widget->layout_damage ();
+   damage |= LAYOUT_XYWH;
+   widget->layout_damage (damage);
+}
+
+void FltkWidgetView::drawFltkWidget (::fltk::Widget *widget,
+                                   core::Rectangle *area)
+{
+   draw_child (*widget);
+}
+
+} // namespace fltk
+} // namespace dw
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkviewbase.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,108 @@
+#ifndef __DW_FLTKVIEWBASE_HH__
+#define __DW_FLTKVIEWBASE_HH__
+
+#include <time.h>         // for time_t
+#include <sys/time.h>     // for time_t in FreeBSD
+
+#include <fltk/Group.h>
+#include <fltk/Image.h>
+#include <fltk/Scrollbar.h>
+
+#include "fltkcore.hh"
+
+namespace dw {
+namespace fltk {
+
+class FltkViewBase: public FltkView, public ::fltk::Group
+{
+private:
+   int bgColor;
+   core::Region drawRegion;
+   static ::fltk::Image *backBuffer;
+   static bool backBufferInUse;
+
+   void drawRectangle (const core::Rectangle *rect, bool doubleBuffer);
+   void drawChildWidgets ();
+
+public:
+   time_t lastDraw;
+   time_t drawDelay;
+
+protected:
+   core::Layout *theLayout;
+   int canvasWidth, canvasHeight;
+   int mouse_x, mouse_y;
+
+   virtual int translateViewXToCanvasX (int x) = 0;
+   virtual int translateViewYToCanvasY (int y) = 0;
+   virtual int translateCanvasXToViewX (int x) = 0;
+   virtual int translateCanvasYToViewY (int y) = 0;
+
+public:
+   FltkViewBase (int x, int y, int w, int h, const char *label = 0);
+   ~FltkViewBase ();
+
+   void draw();
+   int handle (int event);
+
+   void setLayout (core::Layout *layout);
+   void setCanvasSize (int width, int ascent, int descent);
+   void setCursor (core::style::Cursor cursor);
+   void setBgColor (core::style::Color *color);
+
+   void startDrawing (core::Rectangle *area);
+   void finishDrawing (core::Rectangle *area);
+   void queueDraw (core::Rectangle *area);
+   void queueDrawTotal ();
+   void drawTotal ();
+   void cancelQueueDraw ();
+   void drawPoint (core::style::Color *color,
+                   core::style::Color::Shading shading,
+                   int x, int y);
+   void drawLine (core::style::Color *color,
+                  core::style::Color::Shading shading,
+                  int x1, int y1, int x2, int y2);
+   void drawRectangle (core::style::Color *color,
+                       core::style::Color::Shading shading, bool filled,
+                       int x, int y, int width, int height);
+   void drawArc (core::style::Color *color,
+                 core::style::Color::Shading shading, bool filled,
+                 int x, int y, int width, int height,
+                 int angle1, int angle2);
+    void drawPolygon (core::style::Color *color,
+                      core::style::Color::Shading shading,
+                      bool filled, int points[][2], int npoints);
+
+   core::View *getClippingView (int x, int y, int width, int height);
+   void mergeClippingView (core::View *clippingView);
+};
+
+
+class FltkWidgetView: public FltkViewBase
+{
+public:
+   FltkWidgetView (int x, int y, int w, int h, const char *label = 0);
+   ~FltkWidgetView ();
+ 
+   void layout();
+
+   void drawText (core::style::Font *font,
+                  core::style::Color *color,
+                  core::style::Color::Shading shading,
+                  int x, int y, const char *text, int len);
+   void drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot,
+                   int x, int y, int width, int height);
+
+   bool usesFltkWidgets ();
+   void addFltkWidget (::fltk::Widget *widget, core::Allocation *allocation);
+   void removeFltkWidget (::fltk::Widget *widget);
+   void allocateFltkWidget (::fltk::Widget *widget,
+                            core::Allocation *allocation);
+   void drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area);
+};
+
+} // namespace fltk
+} // namespace dw
+
+#endif // __DW_FLTKVIEWBASE_HH__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkviewport.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,496 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "fltkviewport.hh"
+
+#include <fltk/draw.h>
+#include <fltk/damage.h>
+#include <fltk/events.h>
+
+#include <stdio.h>
+
+using namespace fltk;
+using namespace lout::object;
+using namespace lout::container::typed;
+
+namespace dw {
+namespace fltk {
+
+FltkViewport::FltkViewport (int x, int y, int w, int h, const char *label):
+   FltkWidgetView (x, y, w, h, label)
+{
+   hscrollbar = new Scrollbar (0, 0, 1, 1);
+   hscrollbar->set_horizontal();
+   hscrollbar->callback (hscrollbarCallback, this);
+   add (hscrollbar);
+
+   vscrollbar = new Scrollbar (0, 0, 1, 1);
+   vscrollbar->set_vertical();
+   vscrollbar->callback (vscrollbarCallback, this);
+   add (vscrollbar);
+
+   scrollX = scrollY = scrollDX = scrollDY = 0;
+   dragScrolling = 0;
+
+   gadgetOrientation[0] = GADGET_HORIZONTAL;
+   gadgetOrientation[1] = GADGET_HORIZONTAL;
+   gadgetOrientation[2] = GADGET_VERTICAL;
+   gadgetOrientation[3] = GADGET_HORIZONTAL;
+
+   gadgets =
+      new container::typed::List <object::TypedPointer < ::fltk::Widget> >
+      (true);
+}
+
+FltkViewport::~FltkViewport ()
+{
+   delete gadgets;
+}
+
+void FltkViewport::adjustScrollbarsAndGadgetsAllocation ()
+{
+   int hdiff = 0, vdiff = 0;
+   int visibility = 0;
+
+   if (hscrollbar->visible ())
+      visibility |= 1;
+   if (vscrollbar->visible ())
+      visibility |= 2;
+
+   if (gadgets->size () > 0) {
+      switch (gadgetOrientation [visibility]) {
+      case GADGET_VERTICAL:
+         hdiff = SCROLLBAR_THICKNESS;
+         vdiff = SCROLLBAR_THICKNESS * gadgets->size ();
+         break;
+
+      case GADGET_HORIZONTAL:
+         hdiff = SCROLLBAR_THICKNESS * gadgets->size ();
+         vdiff = SCROLLBAR_THICKNESS;
+         break;
+      }
+   } else {
+      hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+      vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+   }
+
+   hscrollbar->x (0);
+   hscrollbar->y (0 + h () - SCROLLBAR_THICKNESS);
+   hscrollbar->w (w () - hdiff);
+   hscrollbar->h (SCROLLBAR_THICKNESS);
+
+   vscrollbar->x (0 + w () - SCROLLBAR_THICKNESS);
+   vscrollbar->y (0);
+   vscrollbar->h (h () - vdiff);
+   vscrollbar->w (SCROLLBAR_THICKNESS);
+
+   int x = w () - SCROLLBAR_THICKNESS, y = h () - SCROLLBAR_THICKNESS;
+   for(Iterator <TypedPointer < ::fltk::Widget> > it = gadgets->iterator ();
+       it.hasNext (); ) {
+      ::fltk::Widget *widget = it.getNext()->getTypedValue ();
+      widget->x (0);
+      widget->y (0);
+      widget->w (SCROLLBAR_THICKNESS);
+      widget->h (SCROLLBAR_THICKNESS);
+
+      switch (gadgetOrientation [visibility]) {
+      case GADGET_VERTICAL:
+         y -= SCROLLBAR_THICKNESS;
+         break;
+
+      case GADGET_HORIZONTAL:
+         x -= SCROLLBAR_THICKNESS;
+         break;
+      }
+   }
+}
+
+void FltkViewport::adjustScrollbarValues ()
+{
+   hscrollbar->value (scrollX, hscrollbar->w (), 0, canvasWidth);
+   vscrollbar->value (scrollY, vscrollbar->h (), 0, canvasHeight);
+}
+
+void FltkViewport::hscrollbarChanged ()
+{
+   scroll (hscrollbar->value () - scrollX, 0);
+}
+
+void FltkViewport::vscrollbarChanged ()
+{
+   scroll (0, vscrollbar->value () - scrollY);
+}
+
+void FltkViewport::vscrollbarCallback (Widget *vscrollbar, void *viewportPtr)
+{
+   ((FltkViewport*)viewportPtr)->vscrollbarChanged ();
+}
+
+void FltkViewport::hscrollbarCallback (Widget *hscrollbar, void *viewportPtr)
+{
+   ((FltkViewport*)viewportPtr)->hscrollbarChanged ();
+}
+
+// ----------------------------------------------------------------------
+
+void FltkViewport::layout ()
+{
+   theLayout->viewportSizeChanged (this, w(), h());
+   adjustScrollbarsAndGadgetsAllocation ();
+   
+   FltkWidgetView::layout ();
+}
+
+void FltkViewport::draw_area (void *data, const Rectangle& cr )
+{
+  FltkViewport *vp = (FltkViewport*) data;
+  push_clip(cr);
+
+  vp->FltkWidgetView::draw ();
+
+  for(Iterator <TypedPointer < ::fltk::Widget> > it = vp->gadgets->iterator ();
+          it.hasNext (); ) {
+          ::fltk::Widget *widget = it.getNext()->getTypedValue ();
+          vp->draw_child (*widget);
+  }
+
+  pop_clip();
+
+}
+
+void FltkViewport::draw ()
+{
+   int hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+   int vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+   Rectangle cr (0, 0, w () - hdiff, h () - vdiff);
+   int d = damage();
+
+   if (d & DAMAGE_SCROLL) {
+      set_damage (DAMAGE_SCROLL);
+      scrollrect(cr, -scrollDX, -scrollDY, draw_area, this);
+      d &= ~DAMAGE_SCROLL;
+      set_damage (d);
+   }
+
+   if (d) {
+      draw_area(this, cr);
+
+      if (d == DAMAGE_CHILD) {
+         if (hscrollbar->damage ())
+            draw_child (*hscrollbar);
+         if (vscrollbar->damage ())
+            draw_child (*vscrollbar);
+      } else {
+         draw_child (*hscrollbar);
+         draw_child (*vscrollbar);
+      }
+   }
+
+   scrollDX = 0; 
+   scrollDY = 0; 
+}
+
+int FltkViewport::handle (int event)
+{
+   //printf("FltkViewport::handle %d\n", event);
+
+   if (hscrollbar->Rectangle::contains (event_x (), event_y ()) &&
+       !(event_state() & (SHIFT | CTRL | ALT)) &&
+       hscrollbar->send (event)) {
+      return 1;
+   }
+
+   if (vscrollbar->Rectangle::contains (event_x (), event_y ()) &&
+      vscrollbar->send (event)) {
+      return 1;
+   }
+
+   switch(event) {
+   case ::fltk::FOCUS:
+      /** \bug Draw focus box. */
+      return 1;
+
+   case ::fltk::UNFOCUS:
+      /** \bug Undraw focus box. */
+      return 1;
+
+   case ::fltk::PUSH:
+      take_focus();
+      if (::fltk::event_button() == ::fltk::MiddleButton) {
+         /* pass event so that middle click can open link in new window */
+         if (FltkWidgetView::handle (event) == 0) {
+            dragScrolling = 1;
+            dragX = ::fltk::event_x();
+            dragY = ::fltk::event_y();
+            setCursor (core::style::CURSOR_MOVE);
+         }
+         return 1;
+      }
+      break;
+
+   case ::fltk::DRAG:
+      if (::fltk::event_button() == ::fltk::MiddleButton) {
+         if (dragScrolling) {
+            scroll(dragX - ::fltk::event_x(), dragY - ::fltk::event_y());
+            dragX = ::fltk::event_x();
+            dragY = ::fltk::event_y();
+            return 1;
+         }
+      }
+      break;
+
+   case ::fltk:: MOUSEWHEEL:
+      return (event_dx() ? hscrollbar : vscrollbar)->handle(event);
+      break;
+   
+   case ::fltk::RELEASE:
+      if (::fltk::event_button() == ::fltk::MiddleButton) {
+         dragScrolling = 0;
+         setCursor (core::style::CURSOR_DEFAULT);
+      } 
+      break;
+
+   case ::fltk::ENTER:
+      /* could be the result of, e.g., closing another window. */
+      mouse_x = ::fltk::event_x();
+      mouse_y = ::fltk::event_y();
+      positionChanged();
+      break;
+
+   case ::fltk::LEAVE:
+      mouse_x = mouse_y = -1;
+      break;
+
+   case ::fltk::KEY:
+      /* tell fltk we want to receive these KEY events as SHORTCUT */
+      switch (::fltk::event_key()) {
+      case PageUpKey:
+      case PageDownKey:
+      case SpaceKey:
+      case DownKey:
+      case UpKey:
+      case RightKey:
+      case LeftKey:
+      case HomeKey:
+      case EndKey:
+         return 0;
+      }
+      break;
+
+   case ::fltk::SHORTCUT:
+      switch (::fltk::event_key()) {
+      case PageUpKey:
+      case 'b':
+      case 'B':
+         scroll (0, -vscrollbar->pagesize ());
+         return 1;
+
+      case PageDownKey:
+      case SpaceKey:
+         scroll (0, vscrollbar->pagesize ());
+         return 1;
+
+      case DownKey:
+         scroll (0, (int) vscrollbar->linesize ());
+         return 1;
+
+      case UpKey:
+         scroll (0, (int) -vscrollbar->linesize ());
+         return 1;
+
+      case RightKey:
+         scroll ((int) hscrollbar->linesize (), 0);
+         return 1;
+
+      case LeftKey:
+         scroll ((int) -hscrollbar->linesize (), 0);
+         return 1;
+
+      case HomeKey:
+         scrollTo (scrollX, 0);
+         return 1;
+
+      case EndKey:
+         scrollTo (scrollX, canvasHeight); /* gets adjusted in scrollTo () */
+         return 1;
+      }
+   }
+
+   return FltkWidgetView::handle (event);
+}
+
+// ----------------------------------------------------------------------
+
+void FltkViewport::setCanvasSize (int width, int ascent, int descent)
+{
+   FltkWidgetView::setCanvasSize (width, ascent, descent);
+   adjustScrollbarValues ();
+}
+
+/*
+ * This is used to simulate mouse motion (e.g., when scrolling).
+ */
+void FltkViewport::positionChanged ()
+{
+   if (mouse_x != -1)
+      (void)theLayout->motionNotify (this,
+                                     translateViewXToCanvasX (mouse_x),
+                                     translateViewYToCanvasY (mouse_y),
+                                     (core::ButtonState)0);
+}
+
+/*
+ * For scrollbars, this currently sets the same step to both vertical and
+ * horizontal. It may me differentiated if necessary.
+ */ 
+void FltkViewport::setScrollStep(int step)
+{
+   vscrollbar->linesize(step);
+   hscrollbar->linesize(step);
+}
+
+bool FltkViewport::usesViewport ()
+{
+   return true;
+}
+
+int FltkViewport::getHScrollbarThickness ()
+{
+   return SCROLLBAR_THICKNESS;
+}
+
+int FltkViewport::getVScrollbarThickness ()
+{
+   return SCROLLBAR_THICKNESS;
+}
+
+void FltkViewport::scrollTo (int x, int y)
+{
+   int hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+   int vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0;
+
+   x = misc::min (x, canvasWidth - w() + hdiff);
+   x = misc::max (x, 0);
+
+   y = misc::min (y, canvasHeight - h() + vdiff);
+   y = misc::max (y, 0);
+
+   if (x == scrollX && y == scrollY) {
+      return;
+   }
+
+   /* multiple calls to scroll can happen before a redraw occurs.
+    * scrollDX / scrollDY can therefore be non-zero here.
+    */
+   updateCanvasWidgets (x - scrollX, y - scrollY);
+   scrollDX += x - scrollX;
+   scrollDY += y - scrollY;
+
+   scrollX = x;
+   scrollY = y;
+
+   adjustScrollbarValues ();
+   redraw (DAMAGE_SCROLL);
+   theLayout->scrollPosChanged (this, scrollX, scrollY);
+   positionChanged();
+}
+
+void FltkViewport::scroll (int dx, int dy)
+{
+   scrollTo (scrollX + dx, scrollY + dy);
+}
+
+void FltkViewport::setViewportSize (int width, int height,
+                                    int hScrollbarThickness,
+                                    int vScrollbarThickness)
+{
+   if (hScrollbarThickness > 0)
+      hscrollbar->show ();
+   else
+      hscrollbar->hide ();
+   if (vScrollbarThickness > 0)
+      vscrollbar->show ();
+   else
+      vscrollbar->hide ();
+
+   /* If no scrollbar, go to the beginning */
+   scroll(hScrollbarThickness ? 0 : -scrollX,
+          vScrollbarThickness ? 0 : -scrollY);
+}
+
+void FltkViewport::updateCanvasWidgets (int dx, int dy)
+{
+   // scroll all child widgets except scroll bars
+   for (int i = children () - 1; i > 0; i--) {
+      ::fltk::Widget *widget = child (i);
+     
+      if (widget == hscrollbar || widget == vscrollbar) 
+         continue;
+
+      widget->x (widget->x () - dx);
+      widget->y (widget->y () - dy);
+   }
+}
+
+int FltkViewport::translateViewXToCanvasX (int x)
+{
+   return x + scrollX;
+}
+
+int FltkViewport::translateViewYToCanvasY (int y)
+{
+   return y + scrollY;
+}
+
+int FltkViewport::translateCanvasXToViewX (int x)
+{
+   return x - scrollX;
+}
+
+int FltkViewport::translateCanvasYToViewY (int y)
+{
+   return y - scrollY;
+}
+
+// ----------------------------------------------------------------------
+
+void FltkViewport::setGadgetOrientation (bool hscrollbarVisible,
+                                         bool vscrollbarVisible,
+                                         FltkViewport::GadgetOrientation
+                                         gadgetOrientation)
+{
+   this->gadgetOrientation[(hscrollbarVisible ? 0 : 1) |
+                           (vscrollbarVisible ? 0 : 2)] = gadgetOrientation;
+   adjustScrollbarsAndGadgetsAllocation ();
+}
+
+void FltkViewport::addGadget (::fltk::Widget *gadget)
+{
+   /** \bug Reparent? */
+
+   gadgets->append (new TypedPointer < ::fltk::Widget> (gadget));
+   adjustScrollbarsAndGadgetsAllocation ();
+}
+
+
+} // namespace fltk
+} // namespace dw
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/fltkviewport.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,77 @@
+#ifndef __DW_FLTKVIEWPORT_HH__
+#define __DW_FLTKVIEWPORT_HH__
+
+#include <fltk/Group.h>
+#include <fltk/Scrollbar.h>
+
+#include "core.hh"
+#include "fltkcore.hh"
+#include "fltkviewbase.hh"
+
+namespace dw {
+namespace fltk {
+
+class FltkViewport: public FltkWidgetView
+{
+public:
+   enum GadgetOrientation { GADGET_VERTICAL, GADGET_HORIZONTAL };
+
+private:
+   enum { SCROLLBAR_THICKNESS = 15 };
+
+   int scrollX, scrollY;
+   int scrollDX, scrollDY;
+   int dragScrolling, dragX, dragY;
+
+   ::fltk::Scrollbar *vscrollbar, *hscrollbar;
+
+   GadgetOrientation gadgetOrientation[4];
+   container::typed::List <object::TypedPointer < ::fltk::Widget> > *gadgets; 
+
+   void adjustScrollbarsAndGadgetsAllocation ();
+   void adjustScrollbarValues ();
+   void hscrollbarChanged ();
+   void vscrollbarChanged ();
+   void positionChanged ();
+
+   static void hscrollbarCallback (Widget *hscrollbar, void *viewportPtr);
+   static void vscrollbarCallback (Widget *vscrollbar, void *viewportPtr);
+
+   void updateCanvasWidgets (int oldScrollX, int oldScrollY);
+   static void draw_area (void *data, const Rectangle& cr);
+
+protected:
+   int translateViewXToCanvasX (int x);
+   int translateViewYToCanvasY (int y);
+   int translateCanvasXToViewX (int x);
+   int translateCanvasYToViewY (int y);
+
+public:
+   FltkViewport (int x, int y, int w, int h, const char *label = 0);
+   ~FltkViewport ();
+ 
+   void layout();
+   void draw ();
+   int handle (int event);
+
+   void setCanvasSize (int width, int ascent, int descent);
+
+   bool usesViewport ();
+   int getHScrollbarThickness ();
+   int getVScrollbarThickness ();
+   void scroll(int dx, int dy);
+   void scrollTo (int x, int y);
+   void setViewportSize (int width, int height,
+                         int hScrollbarThickness, int vScrollbarThickness);
+   void setScrollStep(int step);
+
+   void setGadgetOrientation (bool hscrollbarVisible, bool vscrollbarVisible,
+                              GadgetOrientation gadgetOrientation);
+   void addGadget (::fltk::Widget *gadget);
+};
+
+} // namespace fltk
+} // namespace dw
+
+#endif // __DW_FLTKVIEWPORT_HH__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/image.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,392 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "image.hh"
+#include "../lout/misc.hh"
+
+namespace dw {
+
+using namespace lout;
+
+ImageMapsList::ImageMap::ImageMap ()
+{
+   shapesAndLinks = new container::typed::List <ShapeAndLink> (true);
+   defaultLink = -1;
+}
+
+ImageMapsList::ImageMap::~ImageMap ()
+{
+   delete shapesAndLinks;
+}
+
+void ImageMapsList::ImageMap::add (core::Shape *shape, int link) {
+   ShapeAndLink *shapeAndLink = new ShapeAndLink ();
+   shapeAndLink->shape = shape;
+   shapeAndLink->link = link;
+   shapesAndLinks->append (shapeAndLink);
+}
+
+int ImageMapsList::ImageMap::link (int x, int y) {
+   container::typed::Iterator <ShapeAndLink> it;
+   int link = defaultLink;
+
+   for (it = shapesAndLinks->iterator (); it.hasNext (); ) {
+      ShapeAndLink *shapeAndLink = it.getNext ();
+
+      if (shapeAndLink->shape->isPointWithin (x, y)) {
+         link = shapeAndLink->link;
+         break;
+      }
+   }
+
+   return link;
+}
+
+ImageMapsList::ImageMapsList ()
+{
+   imageMaps = new container::typed::HashTable <object::Object, ImageMap>
+      (true, true);
+   currentMap = NULL;
+}
+
+ImageMapsList::~ImageMapsList ()
+{
+   delete imageMaps;
+}
+
+/**
+ * \brief Start a new map and make it the current one.
+ *
+ * This has to be called before dw::ImageMapsList::addShapeToCurrentMap.
+ * "key" is owned by the image map list, so a copy should be passed, when
+ * necessary.
+ */
+void ImageMapsList::startNewMap (object::Object *key)
+{
+   currentMap = new ImageMap ();
+   imageMaps->put (key, currentMap);
+}
+
+/**
+ * \brief Add a shape to the current map-
+ *
+ * "shape" is owned by the image map list, so a copy should be passed, when
+ * necessary.
+ */
+void ImageMapsList::addShapeToCurrentMap (core::Shape *shape, int link)
+{
+   currentMap->add (shape, link);
+}
+
+/**
+ * \brief Set default link for current map-
+ */
+void ImageMapsList::setCurrentMapDefaultLink (int link)
+{
+   currentMap->setDefaultLink (link);
+}
+
+int ImageMapsList::link (object::Object *key, int x, int y)
+{
+   int link = -1;
+   ImageMap *map = imageMaps->get (key);
+
+   if (map)
+      link = map->link (x, y);
+
+   return link;
+}
+
+// ----------------------------------------------------------------------
+
+int Image::CLASS_ID = -1;
+
+Image::Image(const char *altText)
+{
+   registerName ("dw::Image", &CLASS_ID);
+   this->altText = altText ? strdup (altText) : NULL;
+   altTextWidth = -1; // not yet calculated
+   buffer = NULL;
+   clicking = false;
+   currLink = -1;
+   mapList = NULL;
+   mapKey = NULL;
+   isMap = false;
+}
+
+Image::~Image()
+{
+   if (altText)
+      delete altText;
+   if (buffer)
+      buffer->unref ();
+}
+
+void Image::sizeRequestImpl (core::Requisition *requisition)
+{
+   if (buffer) {
+      requisition->width = buffer->getRootWidth ();
+      requisition->ascent = buffer->getRootHeight ();
+      requisition->descent = 0;
+   } else {
+      if(altText && altText[0]) {
+         if (altTextWidth == -1)
+            altTextWidth =
+               layout->textWidth (getStyle()->font, altText, strlen (altText));
+
+         requisition->width = altTextWidth;
+         requisition->ascent = getStyle()->font->ascent;
+         requisition->descent = getStyle()->font->descent;
+      } else {
+         requisition->width = 0;
+         requisition->ascent = 0;
+         requisition->descent = 0;
+      }
+   }
+
+   requisition->width += getStyle()->boxDiffWidth ();
+   requisition->ascent += getStyle()->boxOffsetY ();
+   requisition->descent += getStyle()->boxRestHeight ();
+}
+
+void Image::sizeAllocateImpl (core::Allocation *allocation)
+{
+   core::Imgbuf *oldBuffer;
+   int dx, dy;
+
+   /* if image is moved only */
+   if (allocation->width == this->allocation.width &&
+       allocation->ascent + allocation->descent == getHeight ())
+      return;
+
+   dx = getStyle()->boxDiffWidth ();
+   dy = getStyle()->boxDiffHeight ();
+#if 0
+   printf("boxDiffHeight = %d + %d, buffer=%p\n",
+          getStyle()->boxOffsetY(), getStyle()->boxRestHeight(), buffer);
+   printf("getContentWidth() = allocation.width - style->boxDiffWidth ()"
+          " = %d - %d = %d\n",
+          this->allocation.width, getStyle()->boxDiffWidth(),
+          this->allocation.width - getStyle()->boxDiffWidth());
+   printf("getContentHeight() = getHeight() - style->boxDiffHeight ()"
+          " = %d - %d = %d\n", this->getHeight(), getStyle()->boxDiffHeight(),
+          this->getHeight() - getStyle()->boxDiffHeight());
+#endif
+   if (buffer != NULL &&
+       /* It may be, that the image is allocated at zero content size. In this
+        * case, we simply wait. */
+       getContentWidth () > 0 && getContentHeight () > 0) {
+      oldBuffer = buffer;
+      buffer = oldBuffer->getScaledBuf (allocation->width - dx,
+                                        allocation->ascent
+                                        + allocation->descent - dy);
+      oldBuffer->unref ();
+   }
+}
+
+void Image::enterNotifyImpl (core::EventCrossing *event)
+{
+   // BUG: this is wrong for image maps, but the cursor position is unknown.
+   currLink = getStyle()->x_link;
+
+   if (currLink != -1) {
+      (void) emitLinkEnter (currLink, -1, -1, -1);
+   }
+}
+
+void Image::leaveNotifyImpl (core::EventCrossing *event)
+{                                                          
+   clicking = false;
+
+   if (currLink != -1) {
+      currLink = -1;
+      (void) emitLinkEnter (-1, -1, -1, -1);
+   }
+}
+
+bool Image::motionNotifyImpl (core::EventMotion *event)
+{
+   if (mapList) {
+      /* client-side image map */
+      int newLink = mapList->link (mapKey, event->xWidget, event->yWidget);
+      if (newLink != currLink) {
+         currLink = newLink;
+         clicking = false;
+         setCursor(newLink == -1 ? core::style::CURSOR_DEFAULT :
+                                   core::style::CURSOR_POINTER);
+         (void) emitLinkEnter (newLink, -1, -1, -1);
+      }
+   } else if (isMap && currLink != -1) {
+      /* server-side image map */
+      (void) emitLinkEnter (currLink, -1, event->xWidget, event->yWidget);
+   }
+   return true;
+}
+
+bool Image::buttonPressImpl (core::EventButton *event)
+{
+   bool ret = false;
+   currLink = mapList ? mapList->link (mapKey, event->xWidget, event->yWidget):
+      getStyle()->x_link;
+   if (event->button == 3){
+      (void)emitLinkPress(currLink, getStyle()->x_img, -1,-1,event);
+      ret = true;
+   } else if (event->button == 1 || currLink != -1){
+      clicking = true;
+      ret = true;
+   }
+   return ret;
+}              
+
+bool Image::buttonReleaseImpl (core::EventButton *event)
+{
+   currLink = mapList ? mapList->link (mapKey, event->xWidget, event->yWidget):
+      getStyle()->x_link;
+   if (clicking) {
+      int x = isMap ? event->xWidget : -1;
+      int y = isMap ? event->yWidget : -1;
+      clicking = false;
+      emitLinkClick (currLink, getStyle()->x_img, x, y, event);
+      return true;
+   }
+   return false;
+}
+
+void Image::draw (core::View *view, core::Rectangle *area)
+{
+   int dx, dy;
+   core::Rectangle content, intersection;
+
+   drawWidgetBox (view, area, false);
+
+   if (buffer) {
+      dx = getStyle()->boxOffsetX ();
+      dy = getStyle()->boxOffsetY ();
+      content.x = dx;
+      content.y = dy;
+      content.width = getContentWidth ();
+      content.height = getContentHeight ();
+
+      if (area->intersectsWith (&content, &intersection))
+         view->drawImage (buffer,
+                          allocation.x + dx, allocation.y + dy,
+                          intersection.x - dx, intersection.y - dy,
+                          intersection.width, intersection.height);
+   } else {
+      if(altText && altText[0]) {
+         if (altTextWidth == -1)
+            altTextWidth =
+               layout->textWidth (getStyle()->font, altText, strlen (altText));
+         
+         core::View *clippingView = NULL, *usedView = view;
+         if (allocation.width < altTextWidth ||
+             allocation.ascent < getStyle()->font->ascent ||
+             allocation.descent < getStyle()->font->descent) {
+            clippingView = usedView =
+               view->getClippingView (allocation.x + getStyle()->boxOffsetX (),
+                                      allocation.y + getStyle()->boxOffsetY (),
+                                      allocation.width
+                                      - getStyle()->boxDiffWidth (),
+                                      allocation.ascent + allocation.descent
+                                      - getStyle()->boxDiffHeight ());
+         }
+
+         usedView->drawText (getStyle()->font, getStyle()->color,
+                             core::style::Color::SHADING_NORMAL,
+                             allocation.x + getStyle()->boxOffsetX (),
+                             allocation.y + getStyle()->boxOffsetY ()
+                             + getStyle()->font->ascent,
+                             altText, strlen(altText));
+
+         if(clippingView)
+            view->mergeClippingView (clippingView);
+      }
+   }
+
+   /** todo: draw selection */
+}
+
+core::Iterator *Image::iterator (core::Content::Type mask, bool atEnd)
+{
+   //return new core::TextIterator (this, mask, atEnd, altText);
+   /** \bug Not implemented. */
+   return new core::EmptyIterator (this, mask, atEnd);
+}
+
+void Image::setBuffer (core::Imgbuf *buffer, bool resize)
+{
+   core::Imgbuf *oldBuf = this->buffer;
+
+   if (resize)
+      queueResize (0, true);
+
+   // If the image has not yet been allocated, or is allocated at zero
+   // content size, the first part is useless.
+   if (wasAllocated () && getContentWidth () > 0 && getContentHeight () > 0) {
+         this->buffer =
+            buffer->getScaledBuf (getContentWidth (), getContentHeight ());
+   } else {
+      this->buffer = buffer;
+      buffer->ref ();
+   }
+
+   if (oldBuf)
+      oldBuf->unref ();
+}
+
+void Image::drawRow (int row)
+{
+   core::Rectangle area;
+
+   assert (buffer != NULL);
+   
+   buffer->getRowArea (row, &area);
+   if (area.width && area.height)
+      queueDrawArea (area.x + getStyle()->boxOffsetX (),
+                     area.y + getStyle()->boxOffsetY (),
+                     area.width, area.height);
+}
+
+
+/**
+ * \brief Sets image as server side image map.
+ */
+void Image::setIsMap ()
+{
+   isMap = true;
+}
+
+
+/**
+ * \brief Sets image as client side image map.
+ *
+ * "list" is not owned by the image, the caller has to free it. "key"
+ * is owned by the image, if it is used by the caller afterwards, a copy
+ * should be passed.
+ */
+void Image::setUseMap (ImageMapsList *list, object::Object *key)
+{
+   mapList = list;
+   mapKey = key;
+}
+
+} // namespace dw
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/image.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,161 @@
+#ifndef __DW_IMAGE_HH__
+#define __DW_IMAGE_HH__
+
+#include "core.hh"
+
+namespace dw {
+
+/**
+ * \brief Represents a list of client-side image maps.
+ *
+ * All image maps of a HTML page (in the future, also image maps from
+ * different HTML pages) are stored in a list, which is passed to the
+ * image, so that it is possible to deal with maps, which are defined
+ * after the image within the HTML page.
+ *
+ * Maps are referred by instances of object::Object. These keys are
+ * typically URLs, so the type representing URLS should be derived from
+ * object::Object.
+ *
+ * \todo Some methods within the key class have to be implemented, this
+ *       is not clear at this time.
+ */
+class ImageMapsList
+{
+private:
+   class ImageMap: public lout::object::Object {
+      private:
+         class ShapeAndLink: public lout::object::Object {
+         public:
+            core::Shape *shape;
+            int link;
+
+            ~ShapeAndLink () { if (shape) delete shape; };
+         };
+
+         lout::container::typed::List <ShapeAndLink> *shapesAndLinks;
+         int defaultLink;
+      public:
+         ImageMap ();
+         ~ImageMap ();
+         
+         void add (core::Shape *shape, int link);
+         void setDefaultLink (int link) { defaultLink = link; };
+         int link (int x, int y);
+   };
+
+   lout::container::typed::HashTable <lout::object::Object, ImageMap>
+      *imageMaps;
+   ImageMap *currentMap;
+   
+public:
+   ImageMapsList ();
+   ~ImageMapsList ();
+
+   void startNewMap (lout::object::Object *key);
+   void addShapeToCurrentMap (core::Shape *shape, int link);
+   void setCurrentMapDefaultLink (int link);
+   int link (lout::object::Object *key, int x, int y);
+};
+
+/**
+ * \brief Displays an instance of dw::core::Imgbuf.
+ *
+ * The dw::core::Imgbuf is automatically scaled, when needed, but dw::Image
+ * does not keep a reference on the root buffer.
+ *
+ *
+ * <h3>Signals</h3>
+ *
+ * For image maps, dw::Image uses the signals defined in
+ * dw::core::Widget::LinkReceiver. For client side image maps, -1 is
+ * passed for the coordinates, for server side image maps, the respective
+ * coordinates are used. See section "Image Maps" below.
+ *
+ *
+ * <h3>%Image Maps</h3>
+ *
+ * <h4>Client Side %Image Maps</h4>
+ *
+ * You must first create a list of image maps (dw::ImageMapList), which can
+ * be used for multiple images. The caller is responsible for freeing the
+ * dw::ImageMapList.
+ *
+ * Adding a map is done by dw::ImageMapsList::startNewMap. The key is an
+ * instance of a sub class of object::Object. In the context of HTML, this is
+ * a URL, which defines this map globally, by combining the URL of the
+ * document, this map is defined in, with the value of the attribute "name" of
+ * the \<MAP\> element, as a fragment.
+ *
+ * dw::ImageMapsList::addShapeToCurrentMap adds a shape to the current
+ * map. The \em link argument is a number, which is later passed to
+ * the dw::core::Widget::LinkReceiver.
+ * 
+ * This map list is then, together with the key for the image, passed to
+ * dw::Image::setUseMap. For HTML, a URL with the value of the "ismap"
+ * attribute of \<IMG\> should be used.
+ *
+ * dw::Image will search the correct map, when needed. If it is not found
+ * at this time, but later defined, it will be found and used later. This is
+ * the case, when an HTML \<MAP\> is defined below the \<IMG\> in the
+ * document.
+ *
+ * Currently, only maps defined in the same document as the image may be
+ * used, since the dw::ImageMapsList is stored in the HTML link block, and
+ * contains only the image maps defined in the document.
+ * 
+ * <h4>Server Side %Image Maps</h4>
+ * 
+ * To use images for server side image maps, you must call
+ * dw::Image::setIsMap, and the dw::Image::style must contain a valid link
+ * (dw::core::style::Style::x_link). After this, motions and clicks are
+ * delegated to dw::core::Widget::LinkReceiver.
+ *
+ * \sa\ref dw-images-and-backgrounds
+ */
+class Image: public core::Widget
+{
+private:
+   char *altText;
+   core::Imgbuf *buffer;
+   int altTextWidth;
+   bool clicking;
+   int currLink;
+   ImageMapsList *mapList;
+   Object *mapKey;
+   bool isMap;
+
+protected:
+   void sizeRequestImpl (core::Requisition *requisition);
+   void sizeAllocateImpl (core::Allocation *allocation);
+
+   void draw (core::View *view, core::Rectangle *area);  
+
+   bool buttonPressImpl (core::EventButton *event);
+   bool buttonReleaseImpl (core::EventButton *event);
+   void enterNotifyImpl (core::EventCrossing *event);
+   void leaveNotifyImpl (core::EventCrossing *event);
+   bool motionNotifyImpl (core::EventMotion *event);
+
+   //core::Iterator *iterator (Content::Type mask, bool atEnd); 
+
+public:
+   static int CLASS_ID;
+
+   Image(const char *altText);
+   ~Image();
+
+   core::Iterator *iterator (core::Content::Type mask, bool atEnd); 
+
+   inline core::Imgbuf *getBuffer () { return buffer; }
+   void setBuffer (core::Imgbuf *buffer, bool resize = false);
+
+   void drawRow (int row);
+
+   void setIsMap ();
+   void setUseMap (ImageMapsList *list, Object *key);
+};
+
+} // namespace dw
+
+#endif // __DW_IMAGE_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/imgbuf.hh	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,210 @@
+#ifndef __DW_IMGBUF_HH__
+#define __DW_IMGBUF_HH__
+
+#ifndef __INCLUDED_FROM_DW_CORE_HH__
+#   error Do not include this file directly, use "core.hh" instead.
+#endif
+
+namespace dw {
+namespace core {
+
+using namespace lout;
+
+/**
+ * \brief The platform independant interface for image buffers.
+ *
+ * %Image buffers depend on the platform (see \ref dw-images-and-backgrounds),
+ * but have this general, platform independant interface. The purpose of
+ * an image buffer is
+ *
+ * <ol>
+ * <li> storing the image data,
+ * <li> handling scaled versions of this buffer, and
+ * <li> drawing.
+ * </ol>
+ *
+ * The latter must be done independently from the window.
+ *
+ * <h3>Creating</h3>
+ *
+ * %Image buffers are created by calling dw::core::Platform::createImgbuf.
+ *
+ * <h3>Storing %Image Data</h3>
+ *
+ * dw::core::Imgbuf supports five image types, which are listed in the table
+ * below. The representation defines, how the colors are stored within
+ * the data, which is passed to dw::core::Imgbuf::copyRow.
+ *
+ * <table>
+ * <tr><th>Type (dw::core::Imgbuf::Type) <th>Bytes per
+ *                                           Pixel <th>Representation
+ * <tr><td>dw::core::Imgbuf::RGB           <td>3   <td>red, green, blue
+ * <tr><td>dw::core::Imgbuf::RGBA          <td>4   <td>red, green, blue, alpha
+ * <tr><td>dw::core::Imgbuf::GRAY          <td>1   <td>gray value
+ * <tr><td>dw::core::Imgbuf::INDEXED       <td>1   <td>index to colormap
+ * <tr><td>dw::core::Imgbuf::INDEXED_ALPHA <td>1    <td>index to colormap
+ * </table>
+ *
+ * The last two types need a colormap, which is set by
+ * dw::core::Imgbuf::setCMap, which must be called before
+ * dw::core::Imgbuf::copyRow. This function expects the colors as 32 bit
+ * unsigned integers, which have the format 0xrrbbgg (for indexed
+ * images), or 0xaarrggbb (for indexed alpha), respectively.
+ *
+ *
+ * <h3>Scaling</h3>
+ * 
+ * The buffer with the original size, which was created by
+ * dw::core::Platform::createImgbuf, is called root buffer. Imgbuf provides
+ * the ability to scale buffers. Generally, both root buffers, as well as
+ * scaled buffers, may be shared, memory management is done by reference
+ * counters.
+ * 
+ * Via dw::core::Imgbuf::getScaledBuf, you can retrieve a scaled buffer.
+ * Generally, something like this must work always, in an efficient way:
+ * 
+ * \code
+ * dw::core::Imgbuf *curBuf, *oldBuf;
+ * int width, heigt,
+ * // ...
+ * oldBuf = curBuf;
+ * curBuf = oldBuf->getScaledBuf(oldBuf, width, height);
+ * oldBuf->unref();
+ * \endcode
+ * 
+ * \em oldBuf may both be a root buffer, or a scaled buffer.
+ * 
+ * The root buffer keeps a list of all children, and all methods
+ * operating on the image data (dw::core::Imgbuf::copyRow and
+ * dw::core::Imgbuf::setCMap) are delegated to the scaled buffers, when
+ * processed, and inherited, when a new scaled buffer is created. This
+ * means, that they must only be performed for the root buffer.
+ * 
+ * A possible implementation could be (dw::fltk::FltkImgbuf does it this way):
+ *
+ * <ul>
+ * <li> If the method is called with an already scaled image buffer, this is
+ *      delegated to the root buffer.
+ *
+ * <li> If the given size is the original size, the root buffer is
+ *      returned, with an increased reference counter.
+ *
+ * <li> Otherwise, if this buffer has already been scaled to the given
+ *      size, return this scaled buffer, with an increased reference
+ *      counter.
+ * 
+ * <li> Otherwise, return a new scaled buffer with reference counter 1.
+ * </ul>
+ *
+ * Special care is to be taken, when the root buffer is not used anymore,
+ * i.e. after dw::core::Imgbuf::unref the reference counter is 0, but there
+ * are still scaled buffers. Since all methods operating on the image data
+ * (dw::core::Imgbuf::copyRow and dw::core::Imgbuf::setCMap) are called for
+ * the root buffer, the root buffer is still needed, and so must not be
+ * deleted at this point. This is, how dw::fltk::FltkImgbuf solves this
+ * problem:
+ *
+ * <ul>
+ * <li> dw::fltk::FltkImgbuf::unref does, for root buffers, check, not only
+ *      whether dw::fltk::FltkImgbuf::refCount is 0, but also, whether
+ *      there are children left. When the latter is the case, the buffer
+ *      is not deleted.
+ *
+ * <li> There is an additional check in dw::fltk::FltkImgbuf::detachScaledBuf,
+ *      which deals with the case, that dw::fltk::FltkImgbuf::refCount is 0,
+ *      and the last scaled buffer is removed.
+ * </ul>
+ *
+ * In the following example:
+ *
+ * \code
+ * dw::fltk::FltkPlatform *platform = new dw::fltk::FltkPlatform ();
+ * dw::core::Layout *layout = new dw::core::Layout (platform);
+ * 
+ * dw::core::Imgbuf *rootbuf =
+ *    layout->createImgbuf (dw::core::Imgbuf::RGB, 100, 100);
+ * dw::core::Imgbuf *scaledbuf = rootbuf->getScaledBuf (50, 50);
+ * rootbuf->unref ();
+ * scaledbuf->unref ();
+ * \endcode
+ *
+ * the root buffer is not deleted, when dw::core::Imgbuf::unref is called,
+ * since a scaled buffer is left. After calling dw::core::Imgbuf::unref for
+ * the scaled buffer, it is deleted, and after it, the root buffer.
+ *
+ * <h3>Drawing</h3>
+ * 
+ * dw::core::Imgbuf provides no methods for drawing, instead, this is
+ * done by the views (implementation of dw::core::View).
+ *
+ * There are two situations, when drawing is necessary:
+ * 
+ * <ol>
+ * <li> To react on expose events, the function dw::core::View::drawImage
+ *      should be used, with the following parameters:
+ *      <ul>
+ *      <li> of course, the image buffer,
+ *      <li> where the root of the image would be displayed (as \em xRoot
+ *           and \em yRoot), and
+ *      <li> the region within the image, which should be displayed (\em x,
+ *           \em y, \em width, \em height).
+ *      </ul>
+ * 
+ * <li> When a row has been copied, it has to be drawn. To determine the
+ *      area, which has to be drawn, the dw::core::Imgbuf::getRowArea
+ *      should be used. The result can then passed
+ *      to dw::core::View::drawImage.
+ * </ol>
+ *
+ * \sa \ref dw-images-and-backgrounds
+ */
+class Imgbuf: public object::Object, public lout::signal::ObservedObject
+{
+public:
+   enum Type { RGB, RGBA, GRAY, INDEXED, INDEXED_ALPHA };
+
+   /*
+    * Methods called from the image decoding
+    */
+
+   virtual void setCMap (int *colors, int num_colors) = 0;
+   virtual void copyRow (int row, const byte *data) = 0;
+   virtual void newScan () = 0;
+
+   /*
+    * Methods called from dw::Image
+    */
+
+   virtual Imgbuf* getScaledBuf (int width, int height) = 0;
+   virtual void getRowArea (int row, dw::core::Rectangle *area) = 0;
+   virtual int  getRootWidth () = 0;
+   virtual int  getRootHeight () = 0;
+
+   /*
+    * Reference counting.
+    */
+
+   virtual void ref () = 0;
+   virtual void unref () = 0;
+
+   /**
+    * \todo Comment
+    */
+   virtual bool lastReference () = 0;
+
+
+   /**
+    * \todo Comment
+    */
+   virtual void setDeleteOnUnref (bool deleteOnUnref) = 0;
+
+   /**
+    * \todo Comment
+    */
+   virtual bool isReferred () = 0;
+};
+
+} // namespace dw
+} // namespace core
+
+#endif // __DW_IMGBUF_HH__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw/iterator.cc	Wed Sep 24 18:44:40 2008 +0200
@@ -0,0 +1,797 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#include "core.hh"
+#include <limits.h>
+
+namespace dw {
+namespace core {
+
+// --------------
+//    Iterator
+// --------------
+
+Iterator::Iterator(Widget *widget, Content::Type mask, bool atEnd)
+{
+   this->widget = widget;
+   this->mask = mask;
+}
+
+Iterator::Iterator(Iterator &it): object::Object (), misc::Comparable ()
+{
+   widget = it.widget;
+   content = it.content;
+}
+
+Iterator::~Iterator()
+{
+}
+
+bool Iterator::equals (Object *other)
+{
+   Iterator *otherIt = (Iterator*)other;
+   return
+      this == otherIt ||
+      (getWidget() == otherIt->getWidget() && compareTo(otherIt) == 0);
+}
+
+/**
+ * \brief Delete the iterator.
+ *
+ * The desctructor is hidden, implementations may use optimizations for
+ * the allocation. (Will soon be the case for dw::core::EmptyIteratorFactory.)
+ */
+void Iterator::unref ()
+{
+   delete this;
+}
+
+/**
+ * \brief Scrolls the viewport, so that the region between \em it1 and
+ * \em it2 is seen, according to \em hpos and \em vpos.
+ *
+ * The parameters \em start and \em end have the same meaning as in
+ * dw::core::Iterator::getAllocation, \em start refers
+ * to \em it1, while \em end rerers to \em it2.
+ *
+ * If \em it1 and \em it2 point to the same location (see code), only
+ * \em it1 is regarded, and both belowstart and belowend refer to it.
+ */
+void Iterator::scrollTo (Iterator *it1, Iterator *it2, int start, int end,
+                         HPosition hpos, VPosition vpos)
+{
+   Allocation alloc1, alloc2, alloc;
+   int x1, x2, y1, y2;
+   DeepIterator *eit1, *eit2, *eit3;
+   int curStart, curEnd, cmp;
+   bool atStart;
+
+   if (it1->equals(it2)) {
+      it1->getAllocation (start, end, &alloc);
+      it1->getWidget()->getLayout()->scrollTo (hpos, vpos, alloc.x, alloc.y,
+                                               alloc.width,
+                                               alloc.ascent + alloc.descent);
+   } else {
+      // First, determine the rectangle all iterators from it1 and it2
+      // allocate, i.e. the smallest rectangle containing all allocations of
+      // these iterators.
+      eit1 = new DeepIterator (it1);
+      eit2 = new DeepIterator (it2);
+
+      x1 = INT_MAX;
+      x2 = INT_MIN;
+      y1 = INT_MAX;
+      y2 = INT_MIN;
+
+      for (eit3 = (DeepIterator*)eit1->clone