diff options
author | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2011-05-28 20:48:21 +0200 |
---|---|---|
committer | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2011-05-28 20:48:21 +0200 |
commit | b0b0cddaff10b4cff371b8bb7aa21e045f8e3915 (patch) | |
tree | 10f178f4d8cb6ad5b80cba3590d9dc0107027655 | |
parent | 1351b8d80044b898f92557e7ff90096deee5f5bc (diff) | |
parent | b99998a37d3ab1336d0ce82ddc60d0c406a2fd1b (diff) |
merge
73 files changed, 1928 insertions, 997 deletions
@@ -1,46 +1,40 @@ (^|/)CVS($|/) (^|/)\.hg($|/) (^|/)\.deps($|/) -(^|/)\html($|/) -.*\.a -.*\.o -config\..* -autom4te.cache -Makefile -Makefile.in -configure -aclocal.m4 -depcomp -install-sh -stamp-h1 -missing -tags -dillo -d_size.h -dpi/bookmarks.dpi -dpi/cookies.dpi -dpi/datauri.filter.dpi -dpi/downloads.dpi -dpi/file.dpi -dpi/ftp.filter.dpi -dpi/hello.filter.dpi -dpi/https.filter.dpi -dpid/dpid -test/cookies -test/dw-anchors-test -test/dw-border-test -test/dw-example -test/dw-find-test -test/dw-images-scaled -test/dw-images-scaled2 -test/dw-images-simple -test/dw-imgbuf-mem-test -test/dw-links -test/dw-links2 -test/dw-lists -test/dw-resource-test -test/dw-table -test/dw-table-aligned -test/dw-ui-test -test/fltk-browser -test/shapes +(^|/)html($|/) +\.a$ +\.o$ +^config\. +^autom4te\.cache$ +(^|/)Makefile$ +(^|/)Makefile\.in$ +^configure$ +^aclocal\.m4$ +^depcomp$ +^install-sh$ +^stamp-h1$ +^missing$ +(^|/)tags$ +^src/dillo$ +^dpi/[^/]*\.dpi$ +^dpid/dpid$ +^dpid/dpidc$ +^dpid/dpidrc$ +^test/cookies$ +^test/dw-anchors-test$ +^test/dw-border-test$ +^test/dw-example$ +^test/dw-find-test$ +^test/dw-images-scaled$ +^test/dw-images-scaled2$ +^test/dw-images-simple$ +^test/dw-imgbuf-mem-test$ +^test/dw-links$ +^test/dw-links2$ +^test/dw-lists$ +^test/dw-resource-test$ +^test/dw-table$ +^test/dw-table-aligned$ +^test/dw-ui-test$ +^test/fltk-browser$ +^test/shapes$ @@ -5,7 +5,10 @@ Dillo project dillo-2.2.1 [not released yet] +- Implemented "View source" as a dpi. - Patch: Jorge Arellano Cid + - Accept application/xhtml+xml. + - Small caps support. + - Border-collapse, border-style properties. + Patches: Jorge Arellano Cid +- Configurable User-Agent HTTP header. Patch: Alexander Voigt, corvid +- Include Accept header in HTTP queries. @@ -19,9 +22,20 @@ dillo-2.2.1 [not released yet] - Handle white-space: pre-wrap and pre-line. - Support for the word-spacing property. - Fix segfault with https and self-signed certificates. + - Text-indent property. Patches: corvid ++- Reintroduce bg_color dillorc option. + - Make Dillo compile with Clang. + - Fix Textblock flushing. + Patches: Johannes Hofmann +- Implement line-height. - Patch: Johannes Hofmann, corvid + - Draw image maps when image not loaded. + Patches: Johannes Hofmann, corvid ++- Support @media rules. + - Implement media-conditional @import rules. + - Configure/Makefile cleanup. + - Fix meta refresh looping. + Patches: Jeremy Henty ----------------------------------------------------------------------------- diff --git a/Makefile.am b/Makefile.am index 52acc2af..3cc1a098 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ SUBDIRS = lout dw dlib dpip src doc dpid dpi test -EXTRA_DIST = Doxyfile dillorc install-dpi-local +EXTRA_DIST = Doxyfile dillorc install-dpi-local d_size.h sysconf_DATA = dillorc diff --git a/config.h.in b/config.h.in index 54501855..371d658f 100644 --- a/config.h.in +++ b/config.h.in @@ -105,8 +105,29 @@ /* Version number of package */ #undef VERSION +/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>, + <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + /* Use char pointers for newer libiconv */ #undef inbuf_t +/* Define to the type of a signed integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef int16_t + +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef int32_t + /* Define the real type of socklen_t */ #undef socklen_t + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +#undef uint16_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t diff --git a/configure.in b/configure.in index a7fef723..6ddf8642 100644 --- a/configure.in +++ b/configure.in @@ -1,12 +1,14 @@ dnl Process this file with aclocal, autoconf and automake. -AC_INIT(src/dillo.cc) +AC_INIT([dillo], [2.2]) -dnl Detect the canonical host and target build environment -AC_CANONICAL_SYSTEM +dnl Detect the canonical target build environment +AC_CANONICAL_TARGET + +AM_INIT_AUTOMAKE +AC_CONFIG_SRCDIR([src/dillo.cc]) +AC_CONFIG_HEADERS([config.h]) -AM_INIT_AUTOMAKE(dillo, 2.2) -AM_CONFIG_HEADER(config.h) sysconfdir=${sysconfdir}/${PACKAGE} dnl Options @@ -38,7 +40,6 @@ AC_ARG_ENABLE(threaded-dns,[ --disable-threaded-dns Disable the advantage of a AC_ARG_ENABLE(rtfl, [ --enable-rtfl Build with rtfl messages]) AC_PROG_CC AC_PROG_CXX -AM_PROG_CC_STDC AC_PROG_RANLIB AC_PROG_CPP @@ -52,43 +53,10 @@ AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(void *) -case 2 in -$ac_cv_sizeof_short) gint16=short;; -$ac_cv_sizeof_int) gint16=int;; -esac -case 4 in -$ac_cv_sizeof_short) gint32=short;; -$ac_cv_sizeof_int) gint32=int;; -$ac_cv_sizeof_long) gint32=long;; -esac - -cat >d_size.h <<_______EOF -#ifndef __D_SIZE_H__ -#define __D_SIZE_H__ - - -#include "config.h" - -#if HAVE_STDINT_H == 0 -#include <stdint.h> -#elif defined(HAVE_INTTYPES_H) -#include <inttypes.h> -#else -typedef signed $gint16 int16_t; -typedef unsigned $gint16 uint16_t; -typedef signed $gint32 int32_t; -typedef unsigned $gint32 uint32_t; -#endif -typedef unsigned char uchar_t; -typedef unsigned short ushort_t; -typedef unsigned long ulong_t; -typedef unsigned int uint_t; -typedef unsigned char bool_t; - - -#endif /* __D_SIZE_H__ */ -_______EOF - +AC_TYPE_INT16_T +AC_TYPE_UINT16_T +AC_TYPE_INT32_T +AC_TYPE_UINT32_T dnl -------------------------------------- dnl Check whether to add /usr/local or not @@ -114,21 +82,21 @@ dnl -------------------- dnl AC_MSG_CHECKING([for socklen_t]) ac_cv_socklen_t="" -AC_TRY_COMPILE([ +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> #include <sys/socket.h> -],[ +]],[[ socklen_t a=0; getsockname(0,(struct sockaddr*)0, &a); -], +]])], ac_cv_socklen_t="socklen_t", -AC_TRY_COMPILE([ +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> #include <sys/socket.h> -],[ +]],[[ int a=0; getsockname(0,(struct sockaddr*)0, &a); -], +]])], ac_cv_socklen_t="int", ac_cv_socklen_t="size_t" ) @@ -150,9 +118,9 @@ if sh -c "fltk2-config --version" >/dev/null 2>&1 then AC_MSG_RESULT(yes) LIBFLTK_CXXFLAGS=`fltk2-config --cxxflags` LIBFLTK_CFLAGS=`fltk2-config --cflags` - LIBFLTK_LIBS=`fltk2-config --use-images --ldflags` + LIBFLTK_LIBS=`fltk2-config --ldflags` else AC_MSG_RESULT(no) - AC_ERROR(FLTK2 must be installed!) + AC_MSG_ERROR(FLTK2 must be installed!) fi @@ -201,7 +169,7 @@ fi if test "x$libz_ok" = xyes; then LIBZ_LIBS="-lz" else - AC_ERROR(zlib must be installed!) + AC_MSG_ERROR(zlib must be installed!) fi dnl --------------- @@ -317,8 +285,12 @@ if test "x$iconv_ok" = "xno"; then dnl Test for OpenBSD old_libs="$LIBS" LIBS="$old_libs -liconv" - AC_TRY_COMPILE([#include <iconv.h>],[iconv_open("","");], - iconv_ok=yes, iconv_ok=no) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include <iconv.h> +]],[[ +iconv_open("",""); +]])], +iconv_ok=yes,iconv_ok=no) LIBS="$old_libs" if test "x$iconv_ok" = "xyes"; then LIBICONV_LIBS="-liconv" @@ -326,7 +298,7 @@ if test "x$iconv_ok" = "xno"; then fi if test "x$iconv_ok" = "xno"; then - AC_ERROR(libiconv must be installed!) + AC_MSG_ERROR(libiconv must be installed!) fi dnl ---------------------- @@ -340,14 +312,15 @@ if test "x$iconv_ok" = "xyes"; then old_cflags="$CFLAGS" CFLAGS="$CFLAGS -Werror" AC_LANG_PUSH([C++]) - AC_TRY_COMPILE([#include <iconv.h>], -[ - const char *inPtr; - char *outPtr; - size_t inLeft = 0, outRoom = 0; - iconv_t encoder = iconv_open("ASCII", "UTF-8"); - iconv(encoder, &inPtr, &inLeft, &outPtr, &outRoom); -], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include <iconv.h> +]],[[ +const char *inPtr; +char *outPtr; +size_t inLeft = 0, outRoom = 0; +iconv_t encoder = iconv_open("ASCII", "UTF-8"); +iconv(encoder, &inPtr, &inLeft, &outPtr, &outRoom); +]])], iconv_old=yes,iconv_old=no) AC_LANG_POP([C++]) LIBS="$old_libs" @@ -386,7 +359,8 @@ case $target in AC_MSG_CHECKING(whether threads work with -pthread) LDSAVEFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -pthread" - AC_TRY_LINK_FUNC(pthread_create, pthread_ok=yes, pthread_ok=no) + AC_LINK_IFELSE([AC_LANG_CALL([],[pthread_create])], +pthread_ok=yes, pthread_ok=no) LDFLAGS=$LDSAVEFLAGS if test "x$pthread_ok" = "xyes"; then @@ -448,7 +422,6 @@ dnl ----------------------- dnl Checks for header files dnl ----------------------- dnl -AC_HEADER_STDC AC_CHECK_HEADERS(fcntl.h unistd.h sys/uio.h) dnl -------------------------- @@ -511,5 +484,18 @@ AC_SUBST(LIBFLTK_LIBS) AC_SUBST(LIBICONV_LIBS) AC_SUBST(datadir) -AC_OUTPUT(Makefile dlib/Makefile dpip/Makefile dpid/Makefile dpi/Makefile doc/Makefile dw/Makefile lout/Makefile src/Makefile src/IO/Makefile test/Makefile) - +AC_CONFIG_FILES([ + Makefile + dlib/Makefile + dpip/Makefile + dpid/Makefile + dpi/Makefile + doc/Makefile + dw/Makefile + lout/Makefile + src/Makefile + src/IO/Makefile + test/Makefile +]) + +AC_OUTPUT diff --git a/d_size.h b/d_size.h new file mode 100644 index 00000000..2e2019e7 --- /dev/null +++ b/d_size.h @@ -0,0 +1,24 @@ +#ifndef __D_SIZE_H__ +#define __D_SIZE_H__ + + +#include "config.h" + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#else +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#else +/* config.h defines {int,uint}*_t */ +#endif /* HAVE_INTTYPES_H */ +#endif /*HAVE_STDINT_H */ + +typedef unsigned char uchar_t; +typedef unsigned short ushort_t; +typedef unsigned long ulong_t; +typedef unsigned int uint_t; +typedef unsigned char bool_t; + + +#endif /* __D_SIZE_H__ */ @@ -112,7 +112,7 @@ # "%s" is replaced with the search keywords separated by '+'. # search_url="http://www.wikipedia.org/wiki/Special:Search?search=%s" # search_url="http://search.lycos.com/?query=%s" -# search_url="http://www.alltheweb.com/search?cat=web&query=%s" +# search_url="http://duckduckgo.com/html?q=%s" #search_url="http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s" # If set, dillo will ask web servers to send pages in this language. @@ -170,6 +170,11 @@ # COLORS SECTION #------------------------------------------------------------------------- +# Set the background color +# bg_color=gray +# bg_color=0xd6d6c0 +#bg_color=0xdcd1ba + # If your eyes suffer with white backgrounds, change this. #allow_white_bg=YES diff --git a/dlib/Makefile.am b/dlib/Makefile.am index 378cd785..0d44c139 100644 --- a/dlib/Makefile.am +++ b/dlib/Makefile.am @@ -1,6 +1,8 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) + noinst_LIBRARIES = libDlib.a libDlib_a_SOURCES = \ dlib.h \ dlib.c - @@ -47,5 +47,5 @@ Jorge.- * Please submit your patches with 'hg diff'. - Happy coding! + Happy coding! --Jcid diff --git a/doc/dillo.1 b/doc/dillo.1 index 6e96cf99..2342d76a 100644 --- a/doc/dillo.1 +++ b/doc/dillo.1 @@ -61,38 +61,38 @@ User's home directory. URL of proxy to send HTTP traffic through. .SH FILES .TP -.I dpid +.I dpid Dillo plugin daemon .TP -.I dpidc +.I dpidc Control program for dpid. .TP -.I ~/.dillo/bm.txt +.I ~/.dillo/bm.txt User bookmarks .TP .I ~/.dillo/certs/ Saved certificates for HTTPS. .TP -.I ~/.dillo/cookies.txt +.I ~/.dillo/cookies.txt Stored cookies .TP -.I ~/.dillo/cookiesrc +.I ~/.dillo/cookiesrc Cookie settings .TP -.I ~/.dillo/dillorc +.I ~/.dillo/dillorc Configuration file. .TP .I ~/.dillo/dpid_comm_keys Keys used in dpi daemon communication. .TP -.I ~/.dillo/dpidrc +.I ~/.dillo/dpidrc Contains name of directory containing dpis, and associates dpi files with protocols. .TP -.I ~/.dillo/keysrc +.I ~/.dillo/keysrc Keybindings. .TP -.I ~/.dillo/style.css +.I ~/.dillo/style.css User style sheet .SH SEE ALSO .BR wget (1) diff --git a/doc/dw-layout-widgets.doc b/doc/dw-layout-widgets.doc index d488efd8..e0215562 100644 --- a/doc/dw-layout-widgets.doc +++ b/doc/dw-layout-widgets.doc @@ -5,7 +5,7 @@ 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 +Where to define the borders of a widget, whether to combine different widgets to one, or to split one widget into multiple ones, should be considered based on different concerns: @@ -22,7 +22,7 @@ considered based on different concerns: <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 +<li> Furthermore, the granularity should not be too fine, because of the overhead each single widget adds. </ul> diff --git a/doc/dw-usage.doc b/doc/dw-usage.doc index 913a4862..32080d74 100644 --- a/doc/dw-usage.doc +++ b/doc/dw-usage.doc @@ -222,7 +222,7 @@ 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 +everything gets immediately visible, within reasonable times; Dw has been optimized for frequent updates. diff --git a/doc/dw-widget-sizes.doc b/doc/dw-widget-sizes.doc index c93ce541..419a4a73 100644 --- a/doc/dw-widget-sizes.doc +++ b/doc/dw-widget-sizes.doc @@ -41,7 +41,7 @@ In the example in the image, the widget has the following allocation: 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, +calling dw::core::Widget::sizeAllocate. This is a concrete method, which will call dw::core::Widget::sizeAllocateImpl (see code of dw::core::Widget::sizeAllocate for details). @@ -93,7 +93,7 @@ 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 +passed to the callees are <ul> <li> the viewport size (ascent is the heigt here, while descent is 0) for diff --git a/doc/user_help.html b/doc/user_help.html index 296b0c5a..91dc748f 100644 --- a/doc/user_help.html +++ b/doc/user_help.html @@ -41,7 +41,7 @@ </ul> </td></tr> </table> - + <table WIDTH="100%" BORDER=1 CELLSPACING=0 CELLPADDING=3> <tr ALIGN=LEFT VALIGN=TOP><td bgcolor="wheat"> <h4><font color="green">Usage:</font></h4> @@ -61,8 +61,8 @@ <li> <b>Configuration:</b> If you want to change Dillo's appearance or behaviour, look at the options in your <b><font color="#5040a0">dillorc</font></b> - file (if you don't have a copy in your ~/.dillo/ directory, get it - <a href='http://www.dillo.org/dillorc'>here</a>). + file (if you don't have a copy in your ~/.dillo/ directory, get it + <a href='http://www.dillo.org/dillorc'>here</a>). <li> Clicking the "Reload" button always requests an end-to-end reload of the page currently viewed, but it will *not* reload embedded images during this process. @@ -224,7 +224,7 @@ (<a href='http://www.dillo.org/dpi1.html'>dpi</a>) framework. This should be transparent to the end user. Please note that: <ul> - <li>It is a good idea to keep a backup of your + <li>It is a good idea to keep a backup of your <code>~/.dillo/bm.txt</code> <li>The server will stay alive after closing dillo. <li>You can stop the server by sending it a KILL signal. Dillo diff --git a/dpi/Makefile.am b/dpi/Makefile.am index 34e07483..ade14854 100644 --- a/dpi/Makefile.am +++ b/dpi/Makefile.am @@ -1,3 +1,6 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) + bookmarksdir = $(libdir)/dillo/dpi/bookmarks downloadsdir = $(libdir)/dillo/dpi/downloads ftpdir = $(libdir)/dillo/dpi/ftp @@ -17,15 +20,33 @@ file_PROGRAMS = file.dpi cookies_PROGRAMS = cookies.dpi datauri_PROGRAMS = datauri.filter.dpi -bookmarks_dpi_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a -downloads_dpi_LDADD = @LIBFLTK_LIBS@ ../dpip/libDpip.a ../dlib/libDlib.a -ftp_filter_dpi_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a -https_filter_dpi_LDADD = @LIBSSL_LIBS@ ../dpip/libDpip.a ../dlib/libDlib.a -hello_filter_dpi_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a -vsource_filter_dpi_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a -file_dpi_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a -cookies_dpi_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a -datauri_filter_dpi_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a +bookmarks_dpi_LDADD = \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a +downloads_dpi_LDADD = @LIBFLTK_LIBS@ \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a +ftp_filter_dpi_LDADD = \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a +https_filter_dpi_LDADD = @LIBSSL_LIBS@ \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a +hello_filter_dpi_LDADD = \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a +vsource_filter_dpi_LDADD = \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a +file_dpi_LDADD = \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a +cookies_dpi_LDADD = \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a +datauri_filter_dpi_LDADD = \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a downloads_dpi_CXXFLAGS = @LIBFLTK_CXXFLAGS@ diff --git a/dpi/bookmarks.c b/dpi/bookmarks.c index 58fc59f5..6e9cb3df 100644 --- a/dpi/bookmarks.c +++ b/dpi/bookmarks.c @@ -1628,16 +1628,19 @@ static int Bmsrv_parse_token(Dsh *sh, char *Buf) if (strcmp(url, "dpi:/bm/modify") == 0) { st = Bmsrv_send_modify_answer(sh, url); + dFree(url); return st; } else if (strncmp(url, "dpi:/bm/modify?", 15) == 0) { /* process request */ st = Bmsrv_process_modify_request(sh, url); + dFree(url); return st; } d_cmd = a_Dpip_build_cmd("cmd=%s url=%s", "start_send_page", url); + dFree(url); st = a_Dpip_dsh_write_str(sh, 1, d_cmd); dFree(d_cmd); if (st != 0) diff --git a/dpi/downloads.cc b/dpi/downloads.cc index 5aa7a87c..1a70d235 100644 --- a/dpi/downloads.cc +++ b/dpi/downloads.cc @@ -72,33 +72,33 @@ typedef enum { // class FL_API ProgressBar : public Widget { class ProgressBar : public Widget { protected: - double mMin; - double mMax; - double mPresent; - double mStep; - bool mShowPct, mShowMsg; - char mMsg[64]; - Color mTextColor; - void draw(); + double mMin; + double mMax; + double mPresent; + double mStep; + bool mShowPct, mShowMsg; + char mMsg[64]; + Color mTextColor; + void draw(); public: - ProgressBar(int x, int y, int w, int h, const char *lbl = 0); - void range(double min, double max, double step = 1) { - mMin = min; mMax = max; mStep = step; - }; - void step(double step) { mPresent += step; redraw(); }; - void move(double step); - double minimum() { return mMin; } - double maximum() { return mMax; } - void minimum(double nm) { mMin = nm; }; - void maximum(double nm) { mMax = nm; }; - double position () { return mPresent; } - double step() { return mStep; } - void position(double pos) { mPresent = pos; redraw(); } - void showtext(bool st) { mShowPct = st; } - void message(char *msg) { mShowMsg = true; strncpy(mMsg,msg,63); redraw(); } - bool showtext() { return mShowPct; } - void text_color(Color col) { mTextColor = col; } - Color text_color() { return mTextColor; } + ProgressBar(int x, int y, int w, int h, const char *lbl = 0); + void range(double min, double max, double step = 1) { + mMin = min; mMax = max; mStep = step; + }; + void step(double step) { mPresent += step; redraw(); }; + void move(double step); + double minimum() { return mMin; } + double maximum() { return mMax; } + void minimum(double nm) { mMin = nm; }; + void maximum(double nm) { mMax = nm; }; + double position () { return mPresent; } + double step() { return mStep; } + void position(double pos) { mPresent = pos; redraw(); } + void showtext(bool st) { mShowPct = st; } + void message(char *msg) { mShowMsg = true; strncpy(mMsg,msg,63); redraw(); } + bool showtext() { return mShowPct; } + void text_color(Color col) { mTextColor = col; } + Color text_color() { return mTextColor; } }; // Download-item class ------------------------------------------------------- @@ -261,7 +261,7 @@ void ProgressBar::draw() } else { Rectangle r2(int (r.w() * pct), 0, int (w() * .1), h()); push_clip(r2); - fillrect(r); + fillrect(r); pop_clip(); } @@ -318,6 +318,8 @@ DLItem::DLItem(const char *full_filename, const char *url, DLAction action) // Init value. Reset later, upon the first data bytes arrival init_time = time(NULL); + twosec_time = onesec_time = init_time; + // BUG:? test a URL with ' inside. /* escape "'" character for the shell. Is it necessary? */ esc_url = Escape_uri_str(url, "'"); @@ -349,71 +351,72 @@ DLItem::DLItem(const char *full_filename, const char *url, DLAction action) gw = 400, gh = 70; group = new Group(0,0,gw,gh); group->begin(); - prTitle = new Widget(24, 7, 290, 23, shortname); - prTitle->box(RSHADOW_BOX); - prTitle->align(ALIGN_LEFT|ALIGN_INSIDE|ALIGN_CLIP); - // Attach this 'log_text' to the tooltip - log_text_add("Target File: ", 13); - log_text_add(fullname, strlen(fullname)); - log_text_add("\n\n", 2); - - prBar = new ProgressBar(24, 40, 92, 20); - prBar->box(BORDER_BOX); // ENGRAVED_BOX - prBar->tooltip("Progress Status"); - - int ix = 122, iy = 36, iw = 50, ih = 14; - Widget *o = new Widget(ix,iy,iw,ih, "Got"); - o->box(RFLAT_BOX); - o->color((Color)0xc0c0c000); - o->tooltip("Downloaded Size"); - prGot = new Widget(ix,iy+14,iw,ih, "0KB"); - prGot->align(ALIGN_CENTER|ALIGN_INSIDE); - prGot->labelcolor((Color)0x6c6cbd00); - prGot->box(NO_BOX); - - ix += iw; - o = new Widget(ix,iy,iw,ih, "Size"); - o->box(RFLAT_BOX); - o->color((Color)0xc0c0c000); - o->tooltip("Total Size"); - prSize = new Widget(ix,iy+14,iw,ih, "??"); - prSize->align(ALIGN_CENTER|ALIGN_INSIDE); - prSize->box(NO_BOX); - - ix += iw; - o = new Widget(ix,iy,iw,ih, "Rate"); - o->box(RFLAT_BOX); - o->color((Color)0xc0c0c000); - o->tooltip("Current transfer Rate (KBytes/sec)"); - prRate = new Widget(ix,iy+14,iw,ih, "??"); - prRate->align(ALIGN_CENTER|ALIGN_INSIDE); - prRate->box(NO_BOX); - - ix += iw; - o = new Widget(ix,iy,iw,ih, "~Rate"); - o->box(RFLAT_BOX); - o->color((Color)0xc0c0c000); - o->tooltip("Average transfer Rate (KBytes/sec)"); - pr_Rate = new Widget(ix,iy+14,iw,ih, "??"); - pr_Rate->align(ALIGN_CENTER|ALIGN_INSIDE); - pr_Rate->box(NO_BOX); - - ix += iw; - prETAt = o = new Widget(ix,iy,iw,ih, "ETA"); - o->box(RFLAT_BOX); - o->color((Color)0xc0c0c000); - o->tooltip("Estimated Time of Arrival"); - prETA = new Widget(ix,iy+14,iw,ih, "??"); - prETA->align(ALIGN_CENTER|ALIGN_INSIDE); - prETA->box(NO_BOX); - - //ix += 50; - //prButton = new HighlightButton(ix, 41, 38, 19, "Stop"); - prButton = new HighlightButton(328, 9, 38, 19, "Stop"); - prButton->tooltip("Stop this transfer"); - prButton->box(UP_BOX); - prButton->clear_tab_to_focus(); - prButton->callback(prButton_scb, this); + prTitle = new Widget(24, 7, 290, 23, shortname); + prTitle->box(RSHADOW_BOX); + prTitle->align(ALIGN_LEFT|ALIGN_INSIDE|ALIGN_CLIP); + prTitle->set_flag (RAW_LABEL); + // Attach this 'log_text' to the tooltip + log_text_add("Target File: ", 13); + log_text_add(fullname, strlen(fullname)); + log_text_add("\n\n", 2); + + prBar = new ProgressBar(24, 40, 92, 20); + prBar->box(BORDER_BOX); // ENGRAVED_BOX + prBar->tooltip("Progress Status"); + + int ix = 122, iy = 36, iw = 50, ih = 14; + Widget *o = new Widget(ix,iy,iw,ih, "Got"); + o->box(RFLAT_BOX); + o->color((Color)0xc0c0c000); + o->tooltip("Downloaded Size"); + prGot = new Widget(ix,iy+14,iw,ih, "0KB"); + prGot->align(ALIGN_CENTER|ALIGN_INSIDE); + prGot->labelcolor((Color)0x6c6cbd00); + prGot->box(NO_BOX); + + ix += iw; + o = new Widget(ix,iy,iw,ih, "Size"); + o->box(RFLAT_BOX); + o->color((Color)0xc0c0c000); + o->tooltip("Total Size"); + prSize = new Widget(ix,iy+14,iw,ih, "??"); + prSize->align(ALIGN_CENTER|ALIGN_INSIDE); + prSize->box(NO_BOX); + + ix += iw; + o = new Widget(ix,iy,iw,ih, "Rate"); + o->box(RFLAT_BOX); + o->color((Color)0xc0c0c000); + o->tooltip("Current transfer Rate (KBytes/sec)"); + prRate = new Widget(ix,iy+14,iw,ih, "??"); + prRate->align(ALIGN_CENTER|ALIGN_INSIDE); + prRate->box(NO_BOX); + + ix += iw; + o = new Widget(ix,iy,iw,ih, "~Rate"); + o->box(RFLAT_BOX); + o->color((Color)0xc0c0c000); + o->tooltip("Average transfer Rate (KBytes/sec)"); + pr_Rate = new Widget(ix,iy+14,iw,ih, "??"); + pr_Rate->align(ALIGN_CENTER|ALIGN_INSIDE); + pr_Rate->box(NO_BOX); + + ix += iw; + prETAt = o = new Widget(ix,iy,iw,ih, "ETA"); + o->box(RFLAT_BOX); + o->color((Color)0xc0c0c000); + o->tooltip("Estimated Time of Arrival"); + prETA = new Widget(ix,iy+14,iw,ih, "??"); + prETA->align(ALIGN_CENTER|ALIGN_INSIDE); + prETA->box(NO_BOX); + + //ix += 50; + //prButton = new HighlightButton(ix, 41, 38, 19, "Stop"); + prButton = new HighlightButton(328, 9, 38, 19, "Stop"); + prButton->tooltip("Stop this transfer"); + prButton->box(UP_BOX); + prButton->clear_tab_to_focus(); + prButton->callback(prButton_scb, this); group->box(ROUND_UP_BOX); group->end(); @@ -593,7 +596,7 @@ void DLItem::update_size(int new_sz) static void read_log_cb(int fd_in, void *data) { DLItem *dl_item = (DLItem *)data; - int BufLen = 4096; + const int BufLen = 4096; char Buf[BufLen]; ssize_t st; int ret = -1; @@ -919,7 +922,7 @@ static void read_req_cb(int req_fd, void *) } action = dl_win->check_filename(&dl_dest); if (action != DL_ABORT) { - // Start the whole thing whithin FLTK. + // Start the whole thing within FLTK. dl_win->add(dl_dest, url, action); } else if (dl_win->num() == 0) { exit(0); @@ -1077,13 +1080,13 @@ DLWin::DLWin(int ww, int wh) { // Create the empty main window mWin = new Window(ww, wh, "Downloads:"); mWin->begin(); - mScroll = new ScrollGroup(0,0,ww,wh); - mScroll->begin(); - mPG = new PackedGroup(0,0,ww,wh); - mPG->end(); - //mPG->spacing(10); - mScroll->end(); - mScroll->type(ScrollGroup::VERTICAL); + mScroll = new ScrollGroup(0,0,ww,wh); + mScroll->begin(); + mPG = new PackedGroup(0,0,ww,wh); + mPG->end(); + //mPG->spacing(10); + mScroll->end(); + mScroll->type(ScrollGroup::VERTICAL); mWin->end(); mWin->resizable(mScroll); mWin->callback(dlwin_esc_cb, NULL); @@ -478,12 +478,10 @@ static void File_send_dir(ClientInfo *client) File_info2html(client, dList_nth_data(Ddir->flist,n), n+1); } - if (dList_length(Ddir->flist)) { - if (client->old_style) { - a_Dpip_dsh_write_str(client->sh, 0, "</pre>\n"); - } else { - a_Dpip_dsh_write_str(client->sh, 0, "</table>\n"); - } + if (client->old_style) { + a_Dpip_dsh_write_str(client->sh, 0, "</pre>\n"); + } else if (dList_length(Ddir->flist)) { + a_Dpip_dsh_write_str(client->sh, 0, "</table>\n"); } a_Dpip_dsh_write_str(client->sh, 1, "</BODY></HTML>\n"); diff --git a/dpi/https.c b/dpi/https.c index 3f474b81..71b0c0f9 100644 --- a/dpi/https.c +++ b/dpi/https.c @@ -409,6 +409,9 @@ static int get_network_connection(char * url) * allow the user to decide what to do. It may save the * certificate to the user's .dillo directory if it is * trusted. + * + * TODO: Rearrange this to get rid of redundancy. + * * Return value: -1 on abort, 0 or higher on continue */ static int handle_certificate_problem(SSL * ssl_connection) @@ -613,6 +616,40 @@ static int handle_certificate_problem(SSL * ssl_connection) "Continue", "Cancel"); a_Dpip_dsh_write_str(sh, 1, d_cmd); dFree(d_cmd); + response_number = dialog_get_answer_number(); + if (response_number == 1) { + ret = 0; + } + break; + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + d_cmd = a_Dpip_build_cmd( + "cmd=%s msg=%s alt1=%s alt2=%s", + "dialog", + "Self signed certificate in certificate chain. The certificate " + "chain could be built up using the untrusted certificates but the " + "root could not be found locally.", + "Continue", "Cancel"); + a_Dpip_dsh_write_str(sh, 1, d_cmd); + dFree(d_cmd); + response_number = dialog_get_answer_number(); + if (response_number == 1) { + ret = 0; + } + break; + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + d_cmd = a_Dpip_build_cmd( + "cmd=%s msg=%s alt1=%s alt2=%s", + "dialog", + "Unable to get local issuer certificate. The issuer certificate " + "of an untrusted certificate cannot be found.", + "Continue", "Cancel"); + a_Dpip_dsh_write_str(sh, 1, d_cmd); + dFree(d_cmd); + response_number = dialog_get_answer_number(); + if (response_number == 1) { + ret = 0; + } + break; default: /*Need to add more options later*/ snprintf(buf, 80, "The remote certificate cannot be verified (code %ld)", st); diff --git a/dpid/Makefile.am b/dpid/Makefile.am index 2b81a98a..a59fa083 100644 --- a/dpid/Makefile.am +++ b/dpid/Makefile.am @@ -1,8 +1,14 @@ -AM_CPPFLAGS=-DDPIDRC_SYS='"$(sysconfdir)/dpidrc"' +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -DDPIDRC_SYS='"$(sysconfdir)/dpidrc"' bin_PROGRAMS = dpid dpidc -dpid_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a -dpidc_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a +dpid_LDADD = \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a +dpidc_LDADD = \ + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a EXTRA_DIST = dpidrc.in diff --git a/dpip/Makefile.am b/dpip/Makefile.am index 099ac7d4..e88da0a1 100644 --- a/dpip/Makefile.am +++ b/dpip/Makefile.am @@ -1,3 +1,6 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) + noinst_LIBRARIES = libDpip.a libDpip_a_SOURCES = \ diff --git a/dpip/dpip.c b/dpip/dpip.c index 46ce6ec8..a5517784 100644 --- a/dpip/dpip.c +++ b/dpip/dpip.c @@ -33,7 +33,6 @@ * Local variables */ static const char Quote = '\''; -static const int DpipTag = 1; /* * Basically the syntax of a dpip tag is: diff --git a/dw/Makefile.am b/dw/Makefile.am index 7150fce9..3014b35d 100644 --- a/dw/Makefile.am +++ b/dw/Makefile.am @@ -1,3 +1,6 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) + noinst_LIBRARIES = \ libDw-core.a \ libDw-fltk.a \ diff --git a/dw/fltkimgbuf.cc b/dw/fltkimgbuf.cc index 6ba7ff1d..e3be41a9 100644 --- a/dw/fltkimgbuf.cc +++ b/dw/fltkimgbuf.cc @@ -193,7 +193,7 @@ core::Imgbuf* FltkImgbuf::getScaledBuf (int width, int height) */ if (width <= 0 || height <= 0 || width > IMAGE_MAX_AREA / height) { - MSG("FltkImgbuf::getScaledBuf: suspicious image size request %dx%d\n", + MSG("FltkImgbuf::getScaledBuf: suspicious image size request %d x %d\n", width, height); ref (); return this; diff --git a/dw/fltkplatform.cc b/dw/fltkplatform.cc index 97e10710..17eb5d51 100644 --- a/dw/fltkplatform.cc +++ b/dw/fltkplatform.cc @@ -17,6 +17,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <stdio.h> +#include <wchar.h> +#include <wctype.h> #include "../lout/msg.h" #include "fltkcore.hh" @@ -28,7 +31,6 @@ #include <fltk/InvisibleBox.h> #include <fltk/Tooltip.h> #include <fltk/utf.h> -#include <stdio.h> namespace dw { namespace fltk { @@ -351,20 +353,45 @@ void FltkPlatform::detachView (core::View *view) int FltkPlatform::textWidth (core::style::Font *font, const char *text, int len) { - int width; + char chbuf[4]; + wchar_t wc, wcu; + int width = 0; FltkFont *ff = (FltkFont*) font; - setfont (ff->font, ff->size); - width = (int) getwidth (text, len); + int curr = 0, next = 0, nb; - if (font->letterSpacing) { - int curr = 0, next = 0; - - while (next < len) { + if (font->fontVariant == 1) { + int sc_fontsize = lout::misc::roundInt(ff->size * 0.78); + for (curr = 0; next < len; curr = next) { next = nextGlyph(text, curr); - width += font->letterSpacing; - curr = next; + wc = utf8decode(text + curr, text + next, &nb); + if ((wcu = towupper(wc)) == wc) { + /* already uppercase, just draw the character */ + setfont(ff->font, ff->size); + width += font->letterSpacing; + width += (int)getwidth(text + curr, next - curr); + } else { + /* make utf8 string for converted char */ + nb = utf8encode(wcu, chbuf); + setfont(ff->font, sc_fontsize); + width += font->letterSpacing; + width += (int)getwidth(chbuf, nb); + } + } + } else { + setfont (ff->font, ff->size); + width = (int) getwidth (text, len); + + if (font->letterSpacing) { + int curr = 0, next = 0; + + while (next < len) { + next = nextGlyph(text, curr); + width += font->letterSpacing; + curr = next; + } } } + return width; } diff --git a/dw/fltkui.cc b/dw/fltkui.cc index c1bfd873..ff80e14c 100644 --- a/dw/fltkui.cc +++ b/dw/fltkui.cc @@ -524,7 +524,7 @@ void FltkEntryResource::widgetCallback (::fltk::Widget *widget, * The Back or Forward, buttons, or the first click on a rendered * page. BUG: this must be investigated and reported to FLTK2 team */ - MSG("when = %d\n", widget->when ()); + _MSG("when = %d\n", widget->when ()); if ((widget->when () & ::fltk::WHEN_ENTER_KEY_ALWAYS) && (::fltk::event_key() == ::fltk::ReturnKey)) ((FltkEntryResource*)data)->emitActivate (); @@ -989,7 +989,7 @@ template <class I> void FltkSelectionResource<I>::addItem (const char *str, itemWidget->set_selected(); if (setSelectedItems ()) { // Handle multiple item selection. - int pos[widgetStack->stack->size ()]; + int *pos = new int[widgetStack->stack->size ()]; int i; Iterator <TypedPointer < ::fltk::Menu> > it; for (it = widgetStack->stack->iterator (), @@ -1000,6 +1000,7 @@ template <class I> void FltkSelectionResource<I>::addItem (const char *str, pos[i] = p->getTypedValue()->children () - 1; } widgetStack->widget->set_item (pos, widgetStack->stack->size ()); + delete [] pos; } } } diff --git a/dw/fltkviewbase.cc b/dw/fltkviewbase.cc index 7d519f05..cab22cf4 100644 --- a/dw/fltkviewbase.cc +++ b/dw/fltkviewbase.cc @@ -27,8 +27,11 @@ #include <fltk/events.h> #include <fltk/Cursor.h> #include <fltk/run.h> +#include <fltk/utf.h> #include <stdio.h> +#include <wchar.h> +#include <wctype.h> #include "../lout/msg.h" using namespace fltk; @@ -366,6 +369,39 @@ void FltkViewBase::drawLine (core::style::Color *color, translateCanvasXToViewX (x2), translateCanvasYToViewY (y2)); } +void FltkViewBase::drawTypedLine (core::style::Color *color, + core::style::Color::Shading shading, + core::style::LineType type, int width, + int x1, int y1, int x2, int y2) +{ + char dashes[3], w, ng, d, gap, len; + const int f = 2; + + w = (width == 1) ? 0 : width; + if (type == core::style::LINE_DOTTED) { + /* customized drawing for dotted lines */ + len = (x2 == x1) ? y2 - y1 + 1 : (y2 == y1) ? x2 - x1 + 1 : 0; + ng = len / f*width; + d = len % f*width; + gap = ng ? d/ng + (w > 3 ? 2 : 0) : 0; + dashes[0] = 1; dashes[1] = f*width-gap; dashes[2] = 0; + line_style(::fltk::DASH + ::fltk::CAP_ROUND, w, dashes); + + /* These formulas also work, but ain't pretty ;) + * line_style(::fltk::DOT + ::fltk::CAP_ROUND, w); + * dashes[0] = 1; dashes[1] = 3*width-2; dashes[2] = 0; + */ + } else if (type == core::style::LINE_DASHED) { + line_style(::fltk::DASH + ::fltk::CAP_ROUND, w); + } + + setcolor(((FltkColor*)color)->colors[shading]); + drawLine (color, shading, x1, y1, x2, y2); + + if (type != core::style::LINE_NORMAL) + line_style(::fltk::SOLID); +} + void FltkViewBase::drawRectangle (core::style::Color *color, core::style::Color::Shading shading, bool filled, @@ -386,7 +422,7 @@ void FltkViewBase::drawRectangle (core::style::Color *color, int x2 = translateCanvasXToViewX (x + width); int y2 = translateCanvasYToViewY (y + height); - // We only support rectangles with line width 1px, so we clip with + // We only support rectangles with line width 1px, so we clip with // a rectangle 1px wider and higher than what we actually expose. // This is only really necessary for non-filled rectangles. clipPoint (&x1, &y1, 1); @@ -483,20 +519,45 @@ void FltkWidgetView::drawText (core::style::Font *font, setfont(ff->font, ff->size); setcolor(((FltkColor*)color)->colors[shading]); - if (!font->letterSpacing) { + if (!font->letterSpacing && !font->fontVariant) { drawtext(text, len, translateCanvasXToViewX (x), translateCanvasYToViewY (y)); } else { /* Nonzero letter spacing adjustment, draw each glyph individually */ int viewX = translateCanvasXToViewX (x), viewY = translateCanvasYToViewY (y); - int curr = 0, next = 0; - - while (next < len) { - next = theLayout->nextGlyph(text, curr); - drawtext(text + curr, next - curr, viewX, viewY); - viewX += font->letterSpacing + (int)getwidth(text + curr,next - curr); - curr = next; + int curr = 0, next = 0, nb; + char chbuf[4]; + wchar_t wc, wcu; + + if (font->fontVariant == 1) { + int sc_fontsize = lout::misc::roundInt(ff->size * 0.78); + for (curr = 0; next < len; curr = next) { + next = theLayout->nextGlyph(text, curr); + wc = utf8decode(text + curr, text + next, &nb); + if ((wcu = towupper(wc)) == wc) { + /* already uppercase, just draw the character */ + setfont(ff->font, ff->size); + drawtext(text + curr, next - curr, viewX, viewY); + viewX += font->letterSpacing; + viewX += (int)getwidth(text + curr, next - curr); + } else { + /* make utf8 string for converted char */ + nb = utf8encode(wcu, chbuf); + setfont(ff->font, sc_fontsize); + drawtext(chbuf, nb, viewX, viewY); + viewX += font->letterSpacing; + viewX += (int)getwidth(chbuf, nb); + } + } + } else { + while (next < len) { + next = theLayout->nextGlyph(text, curr); + drawtext(text + curr, next - curr, viewX, viewY); + viewX += font->letterSpacing + + (int)getwidth(text + curr,next - curr); + curr = next; + } } } } diff --git a/dw/fltkviewbase.hh b/dw/fltkviewbase.hh index 5e1981f8..b5c3ab5e 100644 --- a/dw/fltkviewbase.hh +++ b/dw/fltkviewbase.hh @@ -72,6 +72,10 @@ public: void drawLine (core::style::Color *color, core::style::Color::Shading shading, int x1, int y1, int x2, int y2); + void drawTypedLine (core::style::Color *color, + core::style::Color::Shading shading, + core::style::LineType type, int width, + 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); diff --git a/dw/layout.cc b/dw/layout.cc index d8b96d55..8f67e895 100644 --- a/dw/layout.cc +++ b/dw/layout.cc @@ -223,7 +223,8 @@ Layout::~Layout () platform->removeIdle (scrollIdleId); if (resizeIdleId != -1) platform->removeIdle (resizeIdleId); - + if (bgColor) + bgColor->unref (); if (topLevel) delete topLevel; delete platform; @@ -247,7 +248,6 @@ void Layout::addWidget (Widget *widget) canvasHeightGreater = false; setSizeHints (); - updateBgColor (); queueResize (); } @@ -610,17 +610,17 @@ void Layout::updateCursor () setCursor (style::CURSOR_DEFAULT); } -void Layout::updateBgColor () +void Layout::setBgColor (style::Color *color) { - /* The toplevel widget should always have a defined background color, - * except at the beginning. Searching a defined background is not - * necessary. */ - if (topLevel && topLevel->getStyle() && - topLevel->getStyle()->backgroundColor) - bgColor = topLevel->getStyle()->backgroundColor; - else - bgColor = NULL; - view->setBgColor (bgColor); + color->ref (); + + if (bgColor) + bgColor->unref (); + + bgColor = color; + + if (view) + view->setBgColor (bgColor); } void Layout::resizeIdle () diff --git a/dw/layout.hh b/dw/layout.hh index 304cf166..dc9bf227 100644 --- a/dw/layout.hh +++ b/dw/layout.hh @@ -202,7 +202,6 @@ private: void removeAnchor (Widget *widget, char* name); void setCursor (style::Cursor cursor); void updateCursor (); - void updateBgColor (); void queueDraw (int x, int y, int width, int height); void queueDrawExcept (int x, int y, int width, int height, int ex, int ey, int ewidth, int eheight); @@ -362,6 +361,10 @@ public: /** \brief See dw::core::FindtextState::resetSearch. */ inline void resetSearch () { findtextState.resetSearch (); } + + void setBgColor (style::Color *color); + + inline style::Color* getBgColor () { return bgColor; } }; } // namespace dw diff --git a/dw/ruler.cc b/dw/ruler.cc index 6dce07d0..115dfaa5 100644 --- a/dw/ruler.cc +++ b/dw/ruler.cc @@ -28,6 +28,7 @@ namespace dw { Ruler::Ruler () { + setFlags (BLOCK_LEVEL); unsetFlags (HAS_CONTENTS); } diff --git a/dw/style.cc b/dw/style.cc index c5866372..ae0f4526 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -21,6 +21,7 @@ #include <string.h> #include <unistd.h> #include <ctype.h> +#include <math.h> #include "core.hh" #include "../lout/msg.h" @@ -46,9 +47,11 @@ void StyleAttrs::initValues () width = height = lineHeight = LENGTH_AUTO; vloat = FLOAT_NONE; clear = CLEAR_NONE; + textIndent = 0; margin.setVal (0); borderWidth.setVal (0); padding.setVal (0); + borderCollapse = BORDER_MODEL_SEPARATE; setBorderColor (NULL); setBorderStyle (BORDER_NONE); hBorderSpacing = 0; @@ -124,9 +127,11 @@ bool StyleAttrs::equals (object::Object *other) { width == otherAttrs->width && height == otherAttrs->height && lineHeight == otherAttrs->lineHeight && + textIndent == otherAttrs->textIndent && margin.equals (&otherAttrs->margin) && borderWidth.equals (&otherAttrs->borderWidth) && padding.equals (&otherAttrs->padding) && + borderCollapse == otherAttrs->borderCollapse && borderColor.top == otherAttrs->borderColor.top && borderColor.right == otherAttrs->borderColor.right && borderColor.bottom == otherAttrs->borderColor.bottom && @@ -161,9 +166,11 @@ int StyleAttrs::hashValue () { width + height + lineHeight + + textIndent + margin.hashValue () + borderWidth.hashValue () + padding.hashValue () + + borderCollapse + (intptr_t) borderColor.top + (intptr_t) borderColor.right + (intptr_t) borderColor.bottom + @@ -251,9 +258,11 @@ void Style::copyAttrs (StyleAttrs *attrs) width = attrs->width; height = attrs->height; lineHeight = attrs->lineHeight; + textIndent = attrs->textIndent; margin = attrs->margin; borderWidth = attrs->borderWidth; padding = attrs->padding; + borderCollapse = attrs->borderCollapse; borderColor = attrs->borderColor; borderStyle = attrs->borderStyle; display = attrs->display; @@ -277,6 +286,7 @@ bool FontAttrs::equals(object::Object *other) weight == otherAttrs->weight && style == otherAttrs->style && letterSpacing == otherAttrs->letterSpacing && + fontVariant == otherAttrs->fontVariant && strcmp (name, otherAttrs->name) == 0); } @@ -287,6 +297,7 @@ int FontAttrs::hashValue() h = (h << 5) - h + weight; h = (h << 5) - h + style; h = (h << 5) - h + letterSpacing; + h = (h << 5) - h + fontVariant; return h; } @@ -302,6 +313,7 @@ void Font::copyAttrs (FontAttrs *attrs) weight = attrs->weight; style = attrs->style; letterSpacing = attrs->letterSpacing; + fontVariant = attrs->fontVariant; } Font *Font::create0 (Layout *layout, FontAttrs *attrs, @@ -408,18 +420,373 @@ Tooltip *Tooltip::create (Layout *layout, const char *text) // ---------------------------------------------------------------------- -static void drawTriangle (View *view, Color *color, Color::Shading shading, - int x1, int y1, int x2, int y2, int x3, int y3) { - int points[3][2]; +/* + * The drawBorder{Top,Bottom,Left,Right} functions are similar. They + * use a trapezium as draw polygon, or drawTypedLine() for dots and dashes. + * Although the concept is simple, achieving pixel accuracy is laborious [1]. + * + * [1] http://www.dillo.org/css_compat/tests/border-style.html + */ +static void drawBorderTop(View *view, Style *style, + int x1, int y1, int x2, int y2) + +{ + int points[4][2], d, w; + bool ridge = false, inset = false, dotted = false; + Color::Shading shading = Color::SHADING_NORMAL; + + if (!style->borderColor.top || style->borderWidth.top == 0) + return; + + switch (style->borderStyle.top) { + case BORDER_NONE: + case BORDER_HIDDEN: + break; + case BORDER_DOTTED: + dotted = true; + case BORDER_DASHED: + w = style->borderWidth.top; + view->drawTypedLine(style->borderColor.top, shading, + dotted ? LINE_DOTTED : LINE_DASHED, + w, x1+w/2, y1+w/2, x2-w/2, y2+w/2); + break; + case BORDER_SOLID: + case BORDER_INSET: + inset = true; + case BORDER_OUTSET: + if (style->borderStyle.top != BORDER_SOLID) + shading = (inset) ? Color::SHADING_DARK : Color::SHADING_LIGHT; + + if (style->borderWidth.top == 1) { + view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2); + } else { + points[0][0] = x1; + points[1][0] = x2 + 1; + points[0][1] = points[1][1] = y1; + points[2][0] = points[1][0] - style->borderWidth.right; + points[3][0] = x1 + style->borderWidth.left; + points[2][1] = points[3][1] = points[0][1] + style->borderWidth.top; + view->drawPolygon (style->borderColor.top, shading, true, points, 4); + } + break; + case BORDER_RIDGE: + ridge = true; + case BORDER_GROOVE: + d = style->borderWidth.top & 1; + points[0][0] = x1; + points[1][0] = x2 + 1; + points[0][1] = points[1][1] = y1; + points[2][0] = x2 - style->borderWidth.right / 2; + points[3][0] = x1 + style->borderWidth.left / 2; + points[2][1] = points[3][1] = y1 + style->borderWidth.top / 2 + d; + shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK; + view->drawPolygon (style->borderColor.top, shading, true, points, 4); + points[0][0] = x1 + style->borderWidth.left / 2 + d; + points[1][0] = x2 - style->borderWidth.right / 2 + 1 - d; + points[0][1] = points[1][1] = y1 + style->borderWidth.top / 2 + d; + points[2][0] = x2 - style->borderWidth.right + 1 - d; + points[3][0] = x1 + style->borderWidth.left; + points[2][1] = points[3][1] = y1 + style->borderWidth.top; + shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; + view->drawPolygon (style->borderColor.top, shading, true, points, 4); + break; + case BORDER_DOUBLE: + w = (int) rint(style->borderWidth.top / 3.0); + d = w ? style->borderWidth.top - 2 * w : 0; + int w_l = (int) rint(style->borderWidth.left / 3.0); + int w_r = (int) rint(style->borderWidth.right / 3.0); + if (style->borderWidth.top == 1) { + view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2); + break; + } + points[0][0] = x1; + points[1][0] = x2 + 1; + points[0][1] = points[1][1] = y1; + points[2][0] = points[1][0] - w_r; + points[3][0] = points[0][0] + w_l; + points[2][1] = points[3][1] = points[0][1] + w; + view->drawPolygon (style->borderColor.top, shading, true, points, 4); + points[0][0] = x1 + style->borderWidth.left - w_l; + points[1][0] = x2 + 1 - style->borderWidth.right + w_r; + points[0][1] = points[1][1] = y1 + w + d; + points[2][0] = x2 + 1 - style->borderWidth.right; + points[3][0] = x1 + style->borderWidth.left; + points[2][1] = points[3][1] = y1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.top, shading, true, points, 4); + break; + } +} + +static void drawBorderBottom(View *view, Style *style, + int x1, int y1, int x2, int y2) + +{ + int points[4][2], d, w; + bool ridge = false, inset = false, dotted = false; + Color::Shading shading = Color::SHADING_NORMAL; + + if (!style->borderColor.bottom || style->borderWidth.bottom == 0) + return; + + switch (style->borderStyle.bottom) { + case BORDER_NONE: + case BORDER_HIDDEN: + break; + case BORDER_DOTTED: + dotted = true; + case BORDER_DASHED: + w = style->borderWidth.bottom; + view->drawTypedLine(style->borderColor.bottom, shading, + dotted ? LINE_DOTTED : LINE_DASHED, + w, x1+w/2, y1-w/2, x2-w/2, y2-w/2); + break; + case BORDER_SOLID: + case BORDER_INSET: + inset = true; + case BORDER_OUTSET: + if (style->borderStyle.bottom != BORDER_SOLID) + shading = (inset) ? Color::SHADING_LIGHT : Color::SHADING_DARK; + + if (style->borderWidth.bottom == 1) { /* 1 pixel line */ + view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2); + } else { + points[0][0] = x1 - 1; + points[1][0] = x2 + 2; + points[0][1] = points[1][1] = y1 + 1; + points[2][0] = points[1][0] - style->borderWidth.right; + points[3][0] = points[0][0] + style->borderWidth.left; + points[2][1] = points[3][1] = points[0][1]-style->borderWidth.bottom; + view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + } + break; + case BORDER_RIDGE: + ridge = true; + case BORDER_GROOVE: + w = style->borderWidth.bottom; + d = w & 1; + points[0][0] = x1 - 1; + points[1][0] = x2 + 2 - d; + points[0][1] = points[1][1] = y1 + 1; + points[2][0] = points[1][0] - style->borderWidth.right / 2; + points[3][0] = points[0][0] + style->borderWidth.left / 2 + d; + points[2][1] = points[3][1] = points[0][1] - w/2 - d; + shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; + view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + // clockwise + points[0][0] = x1 + style->borderWidth.left - 1; + points[1][0] = x2 + 1 - style->borderWidth.right + 1; + points[0][1] = points[1][1] = y1 - w + 1; + points[2][0] = points[1][0] + style->borderWidth.right / 2; + points[3][0] = points[0][0] - style->borderWidth.left / 2; + points[2][1] = points[3][1] = points[0][1] + w/2; + shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK; + view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + break; + case BORDER_DOUBLE: + w = (int) rint(style->borderWidth.bottom / 3.0); + d = w ? style->borderWidth.bottom - 2 * w : 0; + int w_l = (int) rint(style->borderWidth.left / 3.0); + int w_r = (int) rint(style->borderWidth.right / 3.0); + if (style->borderWidth.bottom == 1) { + view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2); + break; + } + points[0][0] = x2 + 2; + points[1][0] = x1 - 1; + points[0][1] = points[1][1] = y1 + 1; + points[2][0] = points[1][0] + w_l; + points[3][0] = points[0][0] - w_r; + points[2][1] = points[3][1] = points[0][1] - w; + view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + points[0][0] = x2 + 2 - style->borderWidth.right + w_r; + points[1][0] = x1 - 1 + style->borderWidth.left - w_l; + points[0][1] = points[1][1] = y1 + 1 - w - d; + points[2][0] = x1 - 1 + style->borderWidth.left; + points[3][0] = x2 + 2 - style->borderWidth.right; + points[2][1] = points[3][1] = y1 + 1 - style->borderWidth.bottom; + view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + break; + } +} + +static void drawBorderLeft(View *view, Style *style, + int x1, int y1, int x2, int y2) + +{ + int points[4][2], d, w; + bool ridge = false, inset = false, dotted = false; + Color::Shading shading = Color::SHADING_NORMAL; + + if (!style->borderColor.left || style->borderWidth.left == 0) + return; - points[0][0] = x1; - points[0][1] = y1; - points[1][0] = x2; - points[1][1] = y2; - points[2][0] = x3; - points[2][1] = y3; + switch (style->borderStyle.left) { + case BORDER_NONE: + case BORDER_HIDDEN: + break; + case BORDER_DOTTED: + dotted = true; + case BORDER_DASHED: + w = style->borderWidth.left; + view->drawTypedLine(style->borderColor.left, shading, + dotted ? LINE_DOTTED : LINE_DASHED, + w, x1+w/2, y1+w/2, x1+w/2, y2-w/2); + break; + case BORDER_SOLID: + case BORDER_INSET: + inset = true; + case BORDER_OUTSET: + if (style->borderStyle.left != BORDER_SOLID) + shading = (inset) ? Color::SHADING_DARK : Color::SHADING_LIGHT; + if (style->borderWidth.left == 1) { /* 1 pixel line */ + view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2); + } else { + points[0][0] = points[1][0] = x1; + points[0][1] = y1 - 1; + points[1][1] = y2 + 1; + points[2][0] = points[3][0] = points[0][0] + style->borderWidth.left; + points[2][1] = points[1][1] - style->borderWidth.bottom; + points[3][1] = points[0][1] + style->borderWidth.top; + view->drawPolygon (style->borderColor.left, shading, true, points, 4); + } + break; + case BORDER_RIDGE: + ridge = true; + case BORDER_GROOVE: + w = style->borderWidth.left; + d = w & 1; + points[0][0] = points[1][0] = x1; + points[0][1] = y1; + points[1][1] = y2; + points[2][0] = points[3][0] = x1 + w / 2 + d; + points[2][1] = y2 - style->borderWidth.bottom / 2; + points[3][1] = y1 + style->borderWidth.top / 2; + shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK; + view->drawPolygon (style->borderColor.left, shading, true, points, 4); + points[0][0] = points[1][0] = x1 + w / 2 + d; + points[0][1] = y1 + style->borderWidth.top / 2; + points[1][1] = y2 - style->borderWidth.bottom / 2; + points[2][0] = points[3][0] = x1 + w; + points[2][1] = y2 - style->borderWidth.bottom; + points[3][1] = y1 + style->borderWidth.top; + shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; + view->drawPolygon (style->borderColor.left, shading, true, points, 4); + break; + case BORDER_DOUBLE: + w = (int) rint(style->borderWidth.left / 3.0); + d = w ? style->borderWidth.left - 2 * w : 0; + int w_b = (int) rint(style->borderWidth.bottom / 3.0); + int w_t = (int) rint(style->borderWidth.top / 3.0); + if (style->borderWidth.left == 1) { + view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2-1); + break; + } + points[0][0] = points[1][0] = x1; + points[0][1] = y1 - 1; + points[1][1] = y2 + 1; + points[2][0] = points[3][0] = points[0][0] + w; + points[2][1] = points[1][1] - w_b; + points[3][1] = points[0][1] + w_t; + view->drawPolygon (style->borderColor.left, shading, true, points, 4); + points[0][0] = points[1][0] = x1 + w + d; + points[0][1] = y1 - 1 + style->borderWidth.top - w_t; + points[1][1] = y2 + 1 - style->borderWidth.bottom + w_b; + points[2][0] = points[3][0] = points[0][0] + w; + points[2][1] = y2 + 1 - style->borderWidth.bottom; + points[3][1] = y1 - 1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.left, shading, true, points, 4); + break; + } +} - view->drawPolygon (color, shading, true, points, 3); +static void drawBorderRight(View *view, Style *style, + int x1, int y1, int x2, int y2) + +{ + int points[4][2], d, w; + bool ridge = false, inset = false, dotted = false; + Color::Shading shading = Color::SHADING_NORMAL; + + if (!style->borderColor.right || style->borderWidth.right == 0) + return; + + switch (style->borderStyle.right) { + case BORDER_NONE: + case BORDER_HIDDEN: + break; + case BORDER_DOTTED: + dotted = true; + case BORDER_DASHED: + w = style->borderWidth.right; + view->drawTypedLine(style->borderColor.right, shading, + dotted ? LINE_DOTTED : LINE_DASHED, + w, x1 - w/2, y1 + w/2, x1 - w/2, y2 - w/2); + break; + case BORDER_SOLID: + case BORDER_INSET: + inset = true; + case BORDER_OUTSET: + if (style->borderStyle.right != BORDER_SOLID) + shading = (inset) ? Color::SHADING_LIGHT : Color::SHADING_DARK; + if (style->borderWidth.right == 1) { /* 1 pixel line */ + view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2); + } else { + points[0][0] = points[1][0] = x1 + 1; + points[0][1] = y1 - 1; + points[1][1] = y2 + 1; + points[2][0] = points[3][0] = points[0][0]-style->borderWidth.right; + points[2][1] = points[1][1] - style->borderWidth.bottom; + points[3][1] = points[0][1] + style->borderWidth.top; + view->drawPolygon (style->borderColor.right, shading, true,points,4); + } + break; + case BORDER_RIDGE: + ridge = true; + case BORDER_GROOVE: + w = style->borderWidth.right; + d = w & 1; + points[0][0] = points[1][0] = x1 + 1; + points[0][1] = y1; + points[1][1] = y2; + points[2][0] = points[3][0] = points[0][0] - w / 2 - d; + points[2][1] = y2 - style->borderWidth.bottom / 2; + points[3][1] = points[0][1] + style->borderWidth.top / 2; + shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; + view->drawPolygon (style->borderColor.right, shading, true, points, 4); + points[0][0] = points[1][0] = x1 + 1 - w / 2 - d; + points[0][1] = y1 + style->borderWidth.top / 2; + points[1][1] = y2 - style->borderWidth.bottom / 2; + points[2][0] = points[3][0] = x1 + 1 - w; + points[2][1] = y2 - style->borderWidth.bottom; + points[3][1] = y1 + style->borderWidth.top; + shading = (ridge) ? Color::SHADING_LIGHT: Color::SHADING_DARK; + view->drawPolygon (style->borderColor.right, shading, true, points, 4); + break; + case BORDER_DOUBLE: + w = (int) rint(style->borderWidth.right / 3.0); + d = w ? style->borderWidth.right - 2 * w : 0; + int w_b = (int) rint(style->borderWidth.bottom / 3.0); + int w_t = (int) rint(style->borderWidth.top / 3.0); + if (style->borderWidth.right == 1) { + view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2); + break; + } + points[0][0] = points[1][0] = x1 + 1; + points[0][1] = y1 - 1; + points[1][1] = y2 + 1; + points[2][0] = points[3][0] = points[0][0] - w; + points[2][1] = points[1][1] - w_b; + points[3][1] = points[0][1] + w_t; + view->drawPolygon (style->borderColor.right, shading, true, points, 4); + points[0][0] = points[1][0] = x1 + 1 - w - d; + points[0][1] = y1 - 1 + style->borderWidth.top - w_t; + points[1][1] = y2 + 1 - style->borderWidth.bottom + w_b; + points[2][0] = points[3][0] = points[0][0] - w; + points[2][1] = y2 + 1 - style->borderWidth.bottom; + points[3][1] = y1 - 1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.right, shading, true, points, 4); + break; + } } /** @@ -433,14 +800,13 @@ void drawBorder (View *view, Rectangle *area, { /** \todo a lot! */ Color::Shading dark, light, normal; - Color::Shading top, right, bottom, left; int xb1, yb1, xb2, yb2, xp1, yp1, xp2, yp2; // top left and bottom right point of outer border boundary xb1 = x + style->margin.left; yb1 = y + style->margin.top; - xb2 = x + width - style->margin.right; - yb2 = y + height - style->margin.bottom; + xb2 = x + (width > 0 ? width - 1 : 0) - style->margin.right; + yb2 = y + (height > 0 ? height - 1 : 0) - style->margin.bottom; // top left and bottom right point of inner border boundary xp1 = xb1 + style->borderWidth.left; @@ -452,63 +818,10 @@ void drawBorder (View *view, Rectangle *area, dark = inverse ? Color::SHADING_LIGHT : Color::SHADING_DARK; normal = inverse ? Color::SHADING_INVERSE : Color::SHADING_NORMAL; - switch (style->borderStyle.top) { - case BORDER_INSET: - top = left = dark; - right = bottom = light; - break; - - case BORDER_OUTSET: - top = left = light; - right = bottom = dark; - break; - - default: - top = right = bottom = left = normal; - break; - } - - if (style->borderStyle.top != BORDER_NONE && style->borderColor.top) - view->drawRectangle(style->borderColor.top, top, true, - xb1, yb1, xb2 - xb1, style->borderWidth.top); - - if (style->borderStyle.bottom != BORDER_NONE && style->borderColor.bottom) - view->drawRectangle(style->borderColor.bottom, bottom, true, - xb1, yb2, xb2 - xb1, - style->borderWidth.bottom); - - if (style->borderStyle.left != BORDER_NONE && style->borderColor.left) - view->drawRectangle(style->borderColor.left, left, true, - xb1, yp1, style->borderWidth.left, yp2 - yp1); - - if (style->borderWidth.left > 1) { - if (style->borderWidth.top > 1 && - (style->borderColor.left != style->borderColor.top || - left != top)) - drawTriangle (view, style->borderColor.left, left, - xb1, yp1, xp1, yp1, xb1, yb1); - if (style->borderWidth.bottom > 1 && - (style->borderColor.left != style->borderColor.bottom || - left != bottom)) - drawTriangle (view, style->borderColor.left, left, - xb1, yp2, xp1, yp2, xb1, yb2); - } - - if (style->borderStyle.right != BORDER_NONE && style->borderColor.right) - view->drawRectangle(style->borderColor.right, right, true, - xb2, yp1, - style->borderWidth.right, yp2 - yp1); - - if (style->borderWidth.right > 1) { - if (style->borderWidth.top > 1 && - (style->borderColor.right != style->borderColor.top || - right != top)) - drawTriangle (view, style->borderColor.right, right, - xb2, yp1, xp2, yp1, xb2, yb1); - if (style->borderWidth.bottom > 1 && - (style->borderColor.right != style->borderColor.bottom || - right != bottom)) - drawTriangle (view, style->borderColor.right, right, - xb2, yp2, xp2, yp2, xb2, yb2); - } + drawBorderRight(view, style, xb2, yb1, xb2, yb2); + drawBorderLeft(view, style, xb1, yb1, xb1, yb2); + drawBorderTop(view, style, xb1, yb1, xb2, yb1); + drawBorderBottom(view, style, xb1, yb2, xb2, yb2); } diff --git a/dw/style.hh b/dw/style.hh index 57ee1d10..370d8d1b 100644 --- a/dw/style.hh +++ b/dw/style.hh @@ -64,7 +64,7 @@ namespace core { * attribute, which is supported by dillo, will refer to an attribute in * dw::core::style::Style. For this reason, the attributes in * dw::core::style::Style get the names from the CSS attributes, with - * "camelCase" instead of hythens (e.g. "background-color" becomes + * "camelCase" instead of hyphens (e.g. "background-color" becomes * "backgroundColor"). * * However, dw::core::style::Style will be extended by some more @@ -193,7 +193,7 @@ namespace core { namespace style { enum Cursor { - CURSOR_COSSHAIR, + CURSOR_CROSSHAIR, CURSOR_DEFAULT, CURSOR_POINTER, CURSOR_MOVE, @@ -210,6 +210,11 @@ enum Cursor { CURSOR_HELP }; +enum BorderCollapse { + BORDER_MODEL_SEPARATE, + BORDER_MODEL_COLLAPSE +}; + enum BorderStyle { BORDER_NONE, BORDER_HIDDEN, @@ -258,6 +263,12 @@ enum DisplayType { DISPLAY_TABLE_CELL }; +enum LineType { + LINE_NORMAL, + LINE_DOTTED, + LINE_DASHED +}; + enum ListStylePosition { LIST_STYLE_POSITION_INSIDE, LIST_STYLE_POSITION_OUTSIDE @@ -292,6 +303,11 @@ enum FontStyle { FONT_STYLE_OBLIQUE }; +enum FontVariant { + FONT_VARIANT_NORMAL, + FONT_VARIANT_SMALL_CAPS +}; + enum TextDecoration { TEXT_DECORATION_NONE = 0, TEXT_DECORATION_UNDERLINE = 1 << 0, @@ -442,9 +458,10 @@ public: ClearType clear; int hBorderSpacing, vBorderSpacing, wordSpacing; - Length width, height, lineHeight; + Length width, height, lineHeight, textIndent; Box margin, borderWidth, padding; + BorderCollapse borderCollapse; struct { Color *top, *right, *bottom, *left; } borderColor; struct { BorderStyle top, right, bottom, left; } borderStyle; @@ -573,6 +590,7 @@ public: int size; int weight; int letterSpacing; + FontVariant fontVariant; FontStyle style; bool equals(lout::object::Object *other); diff --git a/dw/table.cc b/dw/table.cc index 51718587..6708b3f0 100644 --- a/dw/table.cc +++ b/dw/table.cc @@ -34,6 +34,7 @@ int Table::CLASS_ID = -1; Table::Table(bool limitTextWidth) { registerName ("dw::Table", &CLASS_ID); + setFlags (BLOCK_LEVEL); setFlags (USES_HINTS); setButtonSensitive(false); diff --git a/dw/textblock.cc b/dw/textblock.cc index 32c39671..fffbac2f 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -35,6 +35,7 @@ int Textblock::CLASS_ID = -1; Textblock::Textblock (bool limitTextWidth) { registerName ("dw::Textblock", &CLASS_ID); + setFlags (BLOCK_LEVEL); setFlags (USES_HINTS); setButtonSensitive(true); @@ -260,10 +261,9 @@ void Textblock::getExtremesImpl (core::Extremes *extremes) word = words->getRef (wordIndex); getWordExtremes (word, &wordExtremes); - /* For the first word, we simply add the line1_offset. */ - /* This test looks questionable */ - if (ignoreLine1OffsetSometimes && wordIndex == 0) { - wordExtremes.minWidth += line1Offset; + if (wordIndex == 0) { + wordExtremes.minWidth += line1OffsetEff; + wordExtremes.maxWidth += line1OffsetEff; //DEBUG_MSG (DEBUG_SIZE_LEVEL + 1, // " (next plus %d)\n", page->line1_offset); } @@ -965,7 +965,20 @@ void Textblock::wordWrap(int wordIndex) line1Offset + word->size.width > availWidth) { line1OffsetEff = 0; } else { - line1OffsetEff = line1Offset; + int indent = 0; + + if (word->content.type == core::Content::WIDGET && + word->content.widget->blockLevel() == true) { + /* don't use text-indent when nesting blocks */ + } else { + if (core::style::isPerLength(getStyle()->textIndent)) { + indent = misc::roundInt(this->availWidth * + core::style::perLengthVal (getStyle()->textIndent)); + } else { + indent = core::style::absLengthVal (getStyle()->textIndent); + } + } + line1OffsetEff = line1Offset + indent; } } @@ -1314,20 +1327,20 @@ void Textblock::decorateText(core::View *view, core::style::Style *style, core::style::Color::Shading shading, int x, int yBase, int width) { - int y; + int y, height; + height = 1 + style->font->xHeight / 12; if (style->textDecoration & core::style::TEXT_DECORATION_UNDERLINE) { - y = yBase + 1; - view->drawLine (style->color, shading, x, y, x + width - 1, y); + y = yBase + style->font->descent / 3; + view->drawRectangle (style->color, shading, true, x, y, width, height); } if (style->textDecoration & core::style::TEXT_DECORATION_OVERLINE) { - y = yBase - style->font->ascent + 1; - view->drawLine (style->color, shading, x, y, x + width - 1, y); + y = yBase - style->font->ascent; + view->drawRectangle (style->color, shading, true, x, y, width, height); } if (style->textDecoration & core::style::TEXT_DECORATION_LINE_THROUGH) { - int height = 1 + style->font->xHeight / 10; - - y = yBase + (style->font->descent - style->font->ascent) / 2; + y = yBase + (style->font->descent - style->font->ascent) / 2 + + style->font->descent / 4; view->drawRectangle (style->color, shading, true, x, y, width, height); } } @@ -1693,8 +1706,8 @@ void Textblock::calcTextSize (const char *text, size_t len, factor /= (style->font->ascent + style->font->descent); - size->ascent = size->ascent * factor + 0.5; - size->descent = size->descent * factor + 0.5; + size->ascent = lout::misc::roundInt(size->ascent * factor); + size->descent = lout::misc::roundInt(size->descent * factor); /* TODO: The containing block's line-height property gives a minimum * height for the line boxes. (Even when it's set to 'normal', i.e., @@ -1704,8 +1717,9 @@ void Textblock::calcTextSize (const char *text, size_t len, if (core::style::isAbsLength (style->lineHeight)) height = core::style::absLengthVal(style->lineHeight); else - height = core::style::perLengthVal(style->lineHeight) * - style->font->size; + height = lout::misc::roundInt ( + core::style::perLengthVal(style->lineHeight) * + style->font->size); leading = height - style->font->size; size->ascent += leading / 2; diff --git a/dw/types.cc b/dw/types.cc index 672ec7f6..4d94f494 100644 --- a/dw/types.cc +++ b/dw/types.cc @@ -1,7 +1,3 @@ -// Rectangle::intersectsWith() has code that was derived from gdkrectangle.c. -// gdkrectangle.c bears the notice that GDK, the GIMP Drawing Kit, is -// "Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald". - /* * Dillo Widget * @@ -56,55 +52,24 @@ void Rectangle::draw (core::View *view, core::style::Style *style, int x,int y) */ bool Rectangle::intersectsWith (Rectangle *otherRect, Rectangle *dest) { - Rectangle *src1 = this, *src2 = otherRect, *temp; - int src1_x2, src1_y2; - int src2_x2, src2_y2; - bool return_val; - - return_val = false; - - if (src2->x < src1->x) { - temp = src1; - src1 = src2; - src2 = temp; + bool doIntersect = + this->x < otherRect->x + otherRect->width && + this->y < otherRect->y + otherRect->height && + otherRect->x < this->x + this->width && + otherRect->y < this->y + this->height; + + if (doIntersect) { + dest->x = misc::max(this->x, otherRect->x); + dest->y = misc::max(this->y, otherRect->y); + dest->width = misc::min(this->x + this->width, + otherRect->x + otherRect->width) - dest->x; + dest->height = misc::min(this->y + this->height, + otherRect->y + otherRect->height) - dest->y; + } else { + dest->x = dest->y = dest->width = dest->height = 0; } - dest->x = src2->x; - - src1_x2 = src1->x + src1->width; - src2_x2 = src2->x + src2->width; - - if (src2->x < src1_x2) { - if (src1_x2 < src2_x2) - dest->width = src1_x2 - dest->x; - else - dest->width = src2_x2 - dest->x; - - if (src2->y < src1->y) { - temp = src1; - src1 = src2; - src2 = temp; - } - dest->y = src2->y; - - src1_y2 = src1->y + src1->height; - src2_y2 = src2->y + src2->height; - if (src2->y < src1_y2) { - return_val = true; - - if (src1_y2 < src2_y2) - dest->height = src1_y2 - dest->y; - else - dest->height = src2_y2 - dest->y; - - if (dest->height == 0) - return_val = false; - if (dest->width == 0) - return_val = false; - } - } - - return return_val; + return doIntersect; } /* @@ -212,9 +177,10 @@ bool Polygon::linesCross0(int ax1, int ay1, int ax2, int ay2, /** TODO Some more description */ // If the scalar product is 0, it means that one point is on the second // line, so we check for <= 0, not < 0. - return - zOfVectorProduct (ax1 - bx1, ay1 - by1, bx2 - bx1, by2 - by1) * - zOfVectorProduct (ax2 - bx1, ay2 - by1, bx2 - bx1, by2 - by1) <= 0; + int z1 = zOfVectorProduct (ax1 - bx1, ay1 - by1, bx2 - bx1, by2 - by1); + int z2 = zOfVectorProduct (ax2 - bx1, ay2 - by1, bx2 - bx1, by2 - by1); + + return (z1 <= 0 && z2 >= 0) || (z1 >= 0 && z2 <= 0); } /** @@ -280,7 +280,7 @@ ComplexButtonResource::ComplexButtonResource () void ComplexButtonResource::init (Widget *widget) { - this->widget = widget; + this->childWidget = widget; layout = new Layout (createPlatform ()); setLayout (layout); @@ -292,7 +292,7 @@ void ComplexButtonResource::setEmbed (Embed *embed) { ButtonResource::setEmbed (embed); - if (widget->usesHints ()) + if (childWidget->usesHints ()) embed->setUsesHints (); } @@ -304,7 +304,7 @@ ComplexButtonResource::~ComplexButtonResource () void ComplexButtonResource::sizeRequest (Requisition *requisition) { Requisition widgetRequisition; - widget->sizeRequest (&widgetRequisition); + childWidget->sizeRequest (&widgetRequisition); requisition->width = widgetRequisition.width + 2 * reliefXThickness (); requisition->ascent = widgetRequisition.ascent + reliefYThickness (); requisition->descent = widgetRequisition.descent + reliefYThickness (); @@ -313,7 +313,7 @@ void ComplexButtonResource::sizeRequest (Requisition *requisition) void ComplexButtonResource::getExtremes (Extremes *extremes) { Extremes widgetExtremes; - widget->getExtremes (&widgetExtremes); + childWidget->getExtremes (&widgetExtremes); extremes->minWidth = widgetExtremes.minWidth + 2 * reliefXThickness (); extremes->maxWidth = widgetExtremes.maxWidth + 2 * reliefXThickness (); } @@ -324,17 +324,17 @@ void ComplexButtonResource::sizeAllocate (Allocation *allocation) void ComplexButtonResource::setWidth (int width) { - widget->setWidth (width - 2 * reliefXThickness ()); + childWidget->setWidth (width - 2 * reliefXThickness ()); } void ComplexButtonResource::setAscent (int ascent) { - widget->setAscent (ascent - reliefYThickness ()); + childWidget->setAscent (ascent - reliefYThickness ()); } void ComplexButtonResource::setDescent (int descent) { - widget->setDescent (descent - reliefYThickness ()); + childWidget->setDescent (descent - reliefYThickness ()); } Iterator *ComplexButtonResource::iterator (Content::Type mask, bool atEnd) @@ -382,7 +382,7 @@ private: friend class LayoutReceiver; LayoutReceiver layoutReceiver; - Widget *widget; + Widget *childWidget; protected: Layout *layout; @@ -166,6 +166,10 @@ public: virtual void drawLine (style::Color *color, style::Color::Shading shading, int x1, int y1, int x2, int y2) = 0; + virtual void drawTypedLine (style::Color *color, + style::Color::Shading shading, + style::LineType type, int width, + int x1, int y1, int x2, int y2) = 0; virtual void drawRectangle (style::Color *color, style::Color::Shading shading, bool filled, int x, int y, int width, int height) = 0; diff --git a/dw/widget.cc b/dw/widget.cc index 751cdcdf..cc73b32b 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -294,18 +294,17 @@ void Widget::setStyle (style::Style *style) { bool sizeChanged; + style->ref (); + if (this->style) { sizeChanged = this->style->sizeDiffs (style); this->style->unref (); } else sizeChanged = true; - style->ref (); this->style = style; if (layout != NULL) { - if (parent == NULL) - layout->updateBgColor (); layout->updateCursor (); } @@ -341,9 +340,7 @@ style::Color *Widget::getBgColor () widget = widget->parent; } - MSG_WARN("No background color found!\n"); - return NULL; - + return layout->getBgColor (); } @@ -401,7 +398,9 @@ void Widget::drawWidgetBox (View *view, Rectangle *area, bool inverse) * widget->style->background_color is NULL (shining through). */ /** \todo Background images? */ - if (parent && style->backgroundColor) + + if (style->backgroundColor && + (parent || layout->getBgColor () != style->backgroundColor)) style::drawBackground (view, &viewArea, allocation.x, allocation.y, allocation.width, getHeight (), style, inverse); } diff --git a/dw/widget.hh b/dw/widget.hh index 013be27b..3034b982 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -67,6 +67,11 @@ protected: * The dw::Image widget uses this flag, see dw::Image::setBuffer. */ WAS_ALLOCATED = 1 << 5, + + /** + * \brief Set for block-level widgets (as opposed to inline widgets) + */ + BLOCK_LEVEL = 1 << 6, }; private: @@ -241,6 +246,7 @@ public: inline bool wasAllocated () { return flags & WAS_ALLOCATED; } inline bool usesHints () { return flags & USES_HINTS; } inline bool hasContents () { return flags & HAS_CONTENTS; } + inline bool blockLevel () { return flags & BLOCK_LEVEL; } void setParent (Widget *parent); diff --git a/lout/Makefile.am b/lout/Makefile.am index 5a246708..a3f947db 100644 --- a/lout/Makefile.am +++ b/lout/Makefile.am @@ -1,3 +1,6 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) + noinst_LIBRARIES = liblout.a liblout_a_SOURCES = \ diff --git a/lout/misc.hh b/lout/misc.hh index 393bac0c..e78e7576 100644 --- a/lout/misc.hh +++ b/lout/misc.hh @@ -38,6 +38,11 @@ inline void assertNotReached () abort (); } +inline int roundInt(double d) +{ + return (int) ((d > 0) ? (d + 0.5) : (d - 0.5)); +} + /** * \brief Instances of a sub class of this interface may be compared (less, * greater). diff --git a/lout/object.cc b/lout/object.cc index 9eec028e..d72b1eec 100644 --- a/lout/object.cc +++ b/lout/object.cc @@ -21,6 +21,7 @@ #include "object.hh" #include <stdio.h> +#include <config.h> namespace lout { diff --git a/src/IO/Makefile.am b/src/IO/Makefile.am index b168073c..c889dae8 100644 --- a/src/IO/Makefile.am +++ b/src/IO/Makefile.am @@ -1,4 +1,6 @@ -AM_CPPFLAGS=-DDILLO_BINDIR='"$(bindir)/"' +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -DDILLO_BINDIR='"$(bindir)/"' AM_CFLAGS = @LIBFLTK_CFLAGS@ AM_CXXFLAGS = @LIBFLTK_CXXFLAGS@ diff --git a/src/IO/mime.c b/src/IO/mime.c index 9bffd619..19dc601a 100644 --- a/src/IO/mime.c +++ b/src/IO/mime.c @@ -108,6 +108,7 @@ void a_Mime_init() Mime_add_minor_type("image/x-png", a_Dicache_png_image); /* deprecated */ #endif Mime_add_minor_type("text/html", a_Html_text); + Mime_add_minor_type("application/xhtml+xml", a_Html_text); /* Add a major type to handle all the text stuff */ Mime_add_major_type("text", a_Plain_text); diff --git a/src/cache.c b/src/cache.c index fcd27a05..d26ae610 100644 --- a/src/cache.c +++ b/src/cache.c @@ -311,6 +311,10 @@ static void Cache_entry_free(CacheEntry_t *entry) dStr_free(entry->UTF8Data, 1); if (entry->CharsetDecoder) a_Decode_free(entry->CharsetDecoder); + if (entry->TransferDecoder) + a_Decode_free(entry->TransferDecoder); + if (entry->ContentDecoder) + a_Decode_free(entry->ContentDecoder); dFree(entry); } @@ -516,6 +520,10 @@ const char *a_Cache_set_content_type(const DilloUrl *url, const char *ctype, ((!major || !*major) && (!minor || !*minor))) { /* META only gives charset; use detected MIME type too */ entry->TypeNorm = dStrconcat(entry->TypeDet, ctype, NULL); + } else if (*from == 'm' && + !dStrncasecmp(ctype, "text/xhtml", 10)) { + /* WORKAROUND: doxygen uses "text/xhtml" in META */ + entry->TypeNorm = dStrdup(entry->TypeDet); } if (charset) { if (entry->CharsetDecoder) @@ -932,7 +940,7 @@ static int Cache_redirect(CacheEntry_t *entry, int Flags, BrowserWindow *bw) (entry->Flags & CA_ForceRedirect || entry->Flags & CA_TempRedirect || !entry->Data->len || entry->Data->len < 1024)) { - _MSG(">>>Redirect from: %s\n to %s\n", + _MSG(">>>> Redirect from: %s\n to %s <<<<\n", URL_STR_(entry->Url), URL_STR_(entry->Location)); _MSG("%s", entry->Header->str); @@ -946,9 +954,9 @@ static int Cache_redirect(CacheEntry_t *entry, int Flags, BrowserWindow *bw) } else { /* Sub entity redirection (most probably an image) */ if (!entry->Data->len) { - _MSG(">>>Image redirection without entity-content<<<\n"); + _MSG(">>>> Image redirection without entity-content <<<<\n"); } else { - _MSG(">>>Image redirection with entity-content<<<\n"); + _MSG(">>>> Image redirection with entity-content <<<<\n"); } } } @@ -362,9 +362,9 @@ static void Capi_dpi_send_source(BrowserWindow *bw, DilloUrl *url) * For a user request, the action will be permitted. * For an automatic request, permission to load depends on the filter set * by the user. - */ -static bool_t Capi_filters_allow(const DilloUrl *wanted, - const DilloUrl *requester) + */ +static bool_t Capi_filters_test(const DilloUrl *wanted, + const DilloUrl *requester) { bool_t ret; @@ -392,8 +392,8 @@ static bool_t Capi_filters_allow(const DilloUrl *wanted, ret = dStrcasecmp(req_suffix, want_suffix) == 0; } - MSG("Capi_filters_allow: from %s to %s: %s\n", req_host, want_host, - ret ? "ALLOWED" : "DENIED"); + MSG("Capi_filters_test: %s from '%s' to '%s'\n", + ret ? "ALLOW" : "DENY", req_host, want_host); break; } case PREFS_FILTER_ALLOW_ALL: @@ -422,7 +422,7 @@ int a_Capi_open_url(DilloWeb *web, CA_Callback_t Call, void *CbData) int safe = 0, ret = 0, use_cache = 0; dReturn_val_if_fail((a_Capi_get_flags(web->url) & CAPI_IsCached) || - Capi_filters_allow(web->url, web->requester), 0); + Capi_filters_test(web->url, web->requester), 0); /* reload test */ reload = (!(a_Capi_get_flags(web->url) & CAPI_IsCached) || @@ -480,7 +480,7 @@ int a_Capi_open_url(DilloWeb *web, CA_Callback_t Call, void *CbData) /* create a new connection and start the CCC operations */ conn = Capi_conn_new(web->url, web->bw, "http", "none"); /* start the reception branch before the query one because the DNS - * may callback immediatly. This may avoid a race condition. */ + * may callback immediately. This may avoid a race condition. */ a_Capi_ccc(OpStart, 2, BCK, a_Chain_new(), conn, "http"); a_Capi_ccc(OpStart, 1, BCK, a_Chain_new(), conn, web); } diff --git a/src/cookies.h b/src/cookies.h index 482aa5ae..d6ee1ccd 100644 --- a/src/cookies.h +++ b/src/cookies.h @@ -8,6 +8,7 @@ extern "C" { #ifdef DISABLE_COOKIES # define a_Cookies_get_query(url) dStrdup("") +# define a_Cookies_set() ; # define a_Cookies_init() ; # define a_Cookies_freeall() ; #else @@ -25,6 +25,28 @@ void CssProperty::print () { (int)value.intVal); } +CssPropertyList::CssPropertyList (const CssPropertyList &p, bool deep) : + lout::misc::SimpleVector <CssProperty> (p) +{ + refCount = 0; + if (deep) { + for (int i = 0; i < size (); i++) { + CssProperty *p = getRef(i); + switch (p->type) { + case CSS_TYPE_STRING: + case CSS_TYPE_SYMBOL: + p->value.strVal = dStrdup (p->value.strVal); + break; + default: + break; + } + } + ownerOfStrings = true; + } else { + ownerOfStrings = false; + } +}; + CssPropertyList::~CssPropertyList () { if (ownerOfStrings) for (int i = 0; i < size (); i++) @@ -428,7 +450,7 @@ void CssStyleSheet::apply (CssPropertyList *props, } } - ruleList[numLists] = elementTable[docTree->top ()->element]; + ruleList[numLists] = elementTable[node->element]; if (ruleList[numLists]) numLists++; @@ -512,9 +534,8 @@ CssContext::~CssContext () { * This allows e.g. user styles to overwrite author styles. */ void CssContext::apply (CssPropertyList *props, Doctree *docTree, + DoctreeNode *node, CssPropertyList *tagStyle, CssPropertyList *nonCssHints) { - const DoctreeNode *node = docTree->top (); - if (sheet[CSS_PRIMARY_USER_AGENT]) sheet[CSS_PRIMARY_USER_AGENT]->apply (props, docTree, node); @@ -558,8 +579,7 @@ void CssContext::addRule (CssSelector *sel, CssPropertyList *props, */ void CssContext::buildUserAgentStyle () { const char *cssBuf = - "body {background-color: #e0e0a3; font-family: sans-serif; color: black;" - " margin: 5px}" + "body {margin: 5px}" "big {font-size: 1.17em}" "blockquote, dd {margin-left: 40px; margin-right: 40px}" "center {text-align: center}" @@ -589,8 +609,8 @@ void CssContext::buildUserAgentStyle () { "sub {vertical-align: sub}" "sup {vertical-align: super}" "s, strike, del {text-decoration: line-through}" - "table {border-style: outset; border-spacing: 1px}" - "td, th {border-style: inset; padding: 2px}" + "table {border-spacing: 2px}" + "td, th {padding: 2px}" "thead, tbody, tfoot {vertical-align: middle}" "th {font-weight: bolder; text-align: center}" "code, tt, pre, samp, kbd {font-family: monospace}" @@ -90,7 +90,7 @@ inline CssLength CSS_CREATE_LENGTH (float v, CssLengthType t) { switch (t) { case CSS_LENGTH_TYPE_PX: - iv = (int) (v + 0.5); + iv = lout::misc::roundInt(v); if (iv > CSS_LENGTH_INT_MAX) iv = CSS_LENGTH_INT_MAX; else if (iv < -CSS_LENGTH_INT_MAX) @@ -304,25 +304,11 @@ class CssPropertyList : public lout::misc::SimpleVector <CssProperty> { refCount = 0; this->ownerOfStrings = ownerOfStrings; }; - inline CssPropertyList(const CssPropertyList &p) : - lout::misc::SimpleVector <CssProperty> (p) { - refCount = 0; - ownerOfStrings = false; - }; + CssPropertyList(const CssPropertyList &p, bool deep = false); ~CssPropertyList (); void set (CssPropertyName name, CssValueType type, CssPropertyValue value); - inline void set (CssPropertyName name, CssValueType type, char *value) { - CssPropertyValue v; - v.strVal = value; - set (name, type, v); - }; - inline void set (CssPropertyName name, CssValueType type, int value) { - CssPropertyValue v; - v.intVal = value; - set (name, type, v); - }; void apply (CssPropertyList *props); void print (); inline void ref () { refCount++; } @@ -476,7 +462,7 @@ class CssContext { static CssStyleSheet *userStyle; static CssStyleSheet *userImportantStyle; CssStyleSheet *sheet[CSS_PRIMARY_USER_IMPORTANT + 1]; - int pos; + int pos; void buildUserAgentStyle (); void buildUserStyle (); @@ -488,7 +474,7 @@ class CssContext { void addRule (CssSelector *sel, CssPropertyList *props, CssPrimaryOrder order); void apply (CssPropertyList *props, - Doctree *docTree, + Doctree *docTree, DoctreeNode *node, CssPropertyList *tagStyle, CssPropertyList *nonCssHints); }; diff --git a/src/cssparser.cc b/src/cssparser.cc index 9d141293..7b522c8c 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -47,6 +47,14 @@ typedef struct { const char *const *enum_symbols; } CssPropertyInfo; +static const char *const Css_border_collapse_enum_vals[] = { + "separate", "collapse", NULL +}; + +static const char *const Css_border_color_enum_vals[] = { + "transparent", NULL +}; + static const char *const Css_border_style_enum_vals[] = { "none", "hidden", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset", NULL @@ -81,6 +89,10 @@ static const char *const Css_font_style_enum_vals[] = { "normal", "italic", "oblique", NULL }; +static const char *const Css_font_variant_enum_vals[] = { + "normal", "small-caps", NULL +}; + static const char *const Css_font_weight_enum_vals[] = { "bold", "bolder", "light", "lighter", "normal", NULL }; @@ -132,24 +144,29 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"background-image", {CSS_TYPE_UNUSED}, NULL}, {"background-position", {CSS_TYPE_UNUSED}, NULL}, {"background-repeat", {CSS_TYPE_UNUSED}, NULL}, - {"border-bottom-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, + {"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, + Css_border_color_enum_vals}, {"border-bottom-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_border_style_enum_vals}, {"border-bottom-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, Css_border_width_enum_vals}, - {"border-collapse", {CSS_TYPE_UNUSED}, NULL}, - {"border-left-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, + {"border-collapse", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, + Css_border_collapse_enum_vals}, + {"border-left-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, + Css_border_color_enum_vals}, {"border-left-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_border_style_enum_vals}, {"border-left-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, Css_border_width_enum_vals}, - {"border-right-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, + {"border-right-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, + Css_border_color_enum_vals}, {"border-right-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_border_style_enum_vals}, {"border-rigth-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, Css_border_width_enum_vals}, {"border-spacing", {CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, NULL}, - {"border-top-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, + {"border-top-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, + Css_border_color_enum_vals}, {"border-top-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_border_style_enum_vals}, {"border-top-width", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH, CSS_TYPE_UNUSED}, @@ -173,7 +190,8 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"font-size-adjust", {CSS_TYPE_UNUSED}, NULL}, {"font-stretch", {CSS_TYPE_UNUSED}, NULL}, {"font-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_font_style_enum_vals}, - {"font-variant", {CSS_TYPE_UNUSED}, NULL}, + {"font-variant", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, + Css_font_variant_enum_vals}, {"font-weight", {CSS_TYPE_ENUM, CSS_TYPE_FONT_WEIGHT, CSS_TYPE_UNUSED}, Css_font_weight_enum_vals}, {"height", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL}, @@ -212,7 +230,7 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"text-align", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_text_align_enum_vals}, {"text-decoration", {CSS_TYPE_MULTI_ENUM, CSS_TYPE_UNUSED}, Css_text_decoration_enum_vals}, - {"text-indent", {CSS_TYPE_UNUSED}, NULL}, + {"text-indent", {CSS_TYPE_LENGTH_PERCENTAGE, CSS_TYPE_UNUSED}, NULL}, {"text-shadow", {CSS_TYPE_UNUSED}, NULL}, {"text-transform", {CSS_TYPE_UNUSED}, NULL}, {"top", {CSS_TYPE_UNUSED}, NULL}, @@ -441,21 +459,21 @@ void CssParser::ungetChar() /* * Skip string str if it is found in the input buffer. + * If string is found leave bufptr pointing to last matched char. * If not wind back. The first char is passed as parameter c * to avoid unnecessary getChar() / ungetChar() calls. */ inline bool CssParser::skipString(int c, const char *str) { - int n = 0; + for (int n = 0; str[n]; n++) { + if (n > 0) + c = getChar(); - while (str[n]) { if (str[n] != c) { while (n--) ungetChar(); return false; } - c = getChar(); - n++; } return true; @@ -663,9 +681,9 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type) case CSS_TYPE_MULTI_ENUM: if (ttype == CSS_TK_SYMBOL) { - if (dStrcasecmp(tval, "none") == 0) - return true; - else { + if (dStrcasecmp(tval, "none") == 0) { + return true; + } else { for (i = 0; Css_property_info[prop].enum_symbols[i]; i++) { if (dStrcasecmp(tval, Css_property_info[prop].enum_symbols[i]) == 0) @@ -1409,54 +1427,171 @@ char * CssParser::parseUrl() void CssParser::parseImport(DilloHtml *html, DilloUrl *baseUrl) { char *urlStr = NULL; + bool importSyntaxIsOK = false; + bool mediaSyntaxIsOK = true; + bool mediaIsSelected = true; - if (html != NULL && - ttype == CSS_TK_SYMBOL && - dStrcasecmp(tval, "import") == 0) { - nextToken(); + nextToken(); - if (ttype == CSS_TK_SYMBOL && - dStrcasecmp(tval, "url") == 0) - urlStr = parseUrl(); - else if (ttype == CSS_TK_STRING) - urlStr = dStrdup (tval); + if (ttype == CSS_TK_SYMBOL && + dStrcasecmp(tval, "url") == 0) + urlStr = parseUrl(); + else if (ttype == CSS_TK_STRING) + urlStr = dStrdup (tval); - /* Skip all tokens until the expected end. */ - while (!(ttype == CSS_TK_END || - (ttype == CSS_TK_CHAR && (tval[0] == ';')))) + nextToken(); + + /* parse a comma-separated list of media */ + if (ttype == CSS_TK_SYMBOL) { + mediaSyntaxIsOK = false; + mediaIsSelected = false; + while (ttype == CSS_TK_SYMBOL) { + if (dStrcasecmp(tval, "all") == 0 || + dStrcasecmp(tval, "screen") == 0) + mediaIsSelected = true; nextToken(); + if (ttype == CSS_TK_CHAR && tval[0] == ',') { + nextToken(); + } else { + mediaSyntaxIsOK = true; + break; + } + } + } + if (mediaSyntaxIsOK && + ttype == CSS_TK_CHAR && + tval[0] == ';') { + importSyntaxIsOK = true; nextToken(); + } else + ignoreStatement(); - if (urlStr) { + if (urlStr) { + if (importSyntaxIsOK && mediaIsSelected) { MSG("CssParser::parseImport(): @import %s\n", urlStr); DilloUrl *url = a_Html_url_new (html, urlStr, a_Url_str(baseUrl), baseUrl ? 1 : 0); a_Html_load_stylesheet(html, url); a_Url_free(url); - dFree (urlStr); + } + dFree (urlStr); + } +} + +void CssParser::parseMedia() +{ + bool mediaSyntaxIsOK = false; + bool mediaIsSelected = false; + + nextToken(); + + /* parse a comma-separated list of media */ + while (ttype == CSS_TK_SYMBOL) { + if (dStrcasecmp(tval, "all") == 0 || + dStrcasecmp(tval, "screen") == 0) + mediaIsSelected = true; + nextToken(); + if (ttype == CSS_TK_CHAR && tval[0] == ',') { + nextToken(); + } else { + mediaSyntaxIsOK = true; + break; } } + + /* check that the syntax is OK so far */ + if (!(mediaSyntaxIsOK && + ttype == CSS_TK_CHAR && + tval[0] == '{')) { + ignoreStatement(); + return; + } + + /* parse/ignore the block as required */ + if (mediaIsSelected) { + nextToken(); + while (ttype != CSS_TK_END) { + parseRuleset(); + if (ttype == CSS_TK_CHAR && tval[0] == '}') { + nextToken(); + break; + } + } + } else + ignoreBlock(); } const char * CssParser::propertyNameString(CssPropertyName name) { return Css_property_info[name].symbol; } + +void CssParser::ignoreBlock() +{ + int depth = 0; + + while (ttype != CSS_TK_END) { + if (ttype == CSS_TK_CHAR) { + if (tval[0] == '{') { + depth++; + } else if (tval[0] == '}') { + depth--; + if (depth == 0) { + nextToken(); + return; + } + } + } + nextToken(); + } +} + +void CssParser::ignoreStatement() +{ + while (ttype != CSS_TK_END) { + if (ttype == CSS_TK_CHAR) { + if (tval[0] == ';') { + nextToken(); + return; + } else if (tval[0] =='{') { + ignoreBlock(); + return; + } + } + nextToken(); + } +} void CssParser::parse(DilloHtml *html, DilloUrl *url, CssContext * context, const char *buf, int buflen, CssOrigin origin) { CssParser parser (context, origin, buf, buflen); - - while (parser.ttype == CSS_TK_CHAR && parser.tval[0] == '@') { - parser.nextToken(); - parser.parseImport(html, url); + bool importsAreAllowed = true; + + while (parser.ttype != CSS_TK_END) { + if (parser.ttype == CSS_TK_CHAR && + parser.tval[0] == '@') { + parser.nextToken(); + if (parser.ttype == CSS_TK_SYMBOL) { + if (dStrcasecmp(parser.tval, "import") == 0 && + html != NULL && + importsAreAllowed) { + parser.parseImport(html, url); + } else if (dStrcasecmp(parser.tval, "media") == 0) { + parser.parseMedia(); + } else { + parser.ignoreStatement(); + } + } else { + parser.ignoreStatement(); + } + } else { + importsAreAllowed = false; + parser.parseRuleset(); + } } - - while (parser.ttype != CSS_TK_END) - parser.parseRuleset(); } CssPropertyList *CssParser::parseDeclarationBlock(const char *buf, int buflen) diff --git a/src/cssparser.hh b/src/cssparser.hh index 1e471c68..1542405d 100644 --- a/src/cssparser.hh +++ b/src/cssparser.hh @@ -40,8 +40,11 @@ class CssParser { bool parseSimpleSelector(CssSimpleSelector *selector); char *parseUrl(); void parseImport(DilloHtml *html, DilloUrl *url); + void parseMedia(); CssSelector *parseSelector(); void parseRuleset(); + void ignoreBlock(); + void ignoreStatement(); public: static CssPropertyList *parseDeclarationBlock(const char *buf, diff --git a/src/dillo.cc b/src/dillo.cc index a42b0dab..3159674e 100644 --- a/src/dillo.cc +++ b/src/dillo.cc @@ -22,6 +22,7 @@ #include <stdlib.h> #include <time.h> #include <signal.h> +#include <locale.h> #include <fltk/Window.h> #include <fltk/TabGroup.h> diff --git a/src/form.cc b/src/form.cc index 38afea8f..18441fb8 100644 --- a/src/form.cc +++ b/src/form.cc @@ -554,12 +554,9 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) } if (prefs.show_tooltip && (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { - CssPropertyList props; - char *tooltip_str = dStrdup(attrbuf); - props.set (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, tooltip_str); - html->styleEngine->setNonCssHints (&props); - dFree(tooltip_str); + html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, + attrbuf); } HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle()); } @@ -930,7 +927,7 @@ DilloHtmlForm::~DilloHtmlForm () void DilloHtmlForm::eventHandler(Resource *resource, EventButton *event) { - MSG("DilloHtmlForm::eventHandler\n"); + _MSG("DilloHtmlForm::eventHandler\n"); if (event && (event->button == 3)) { a_UIcmd_form_popup(html->bw, html->page_url, this, showing_hiddens); } else { @@ -351,8 +351,6 @@ static size_t Gif_do_extension(DilloGif *gif, uint_t Label, return Gif_data_blocks(buf, BSize); case Txt_Ext: /* Plain text Extension */ - /* This extension allows (rcm thinks) the image to be rendered as text. - */ case App_Ext: /* Application Extension */ default: return Gif_do_generic_ext(buf, BSize); /*Ignore Extension */ @@ -428,16 +426,6 @@ static void Gif_emit_line(DilloGif *gif, const uchar_t *linebuf) } /* - * I apologize for the large size of this routine and the goto error - * construct - I almost _never_ do that. I offer the excuse of - * optimizing for speed. - * - * RCM -- busted these down into smaller subroutines... still very hard to - * read. - */ - - -/* * Decode the packetized lwz bytes */ static void Gif_literal(DilloGif *gif, uint_t code) @@ -816,7 +804,7 @@ static size_t Gif_do_img_desc(DilloGif *gif, void *Buf, /* check max image size */ if (gif->Width <= 0 || gif->Height <= 0 || gif->Width > IMAGE_MAX_AREA / gif->Height) { - MSG("Gif_do_img_desc: suspicious image size request %ux%u\n", + MSG("Gif_do_img_desc: suspicious image size request %u x %u\n", gif->Width, gif->Height); gif->state = 999; return 0; diff --git a/src/html.cc b/src/html.cc index 25942514..bcefe14b 100644 --- a/src/html.cc +++ b/src/html.cc @@ -68,9 +68,8 @@ using namespace dw::core::style; * Typedefs *---------------------------------------------------------------------------*/ class DilloHtml; -typedef void (*TagOpenFunct) (DilloHtml *Html, const char *Tag, int Tagsize); -typedef void (*TagCloseFunct) (DilloHtml *Html, int TagIdx); -typedef struct _DilloHtmlClass DilloHtmlClass; +typedef void (*TagOpenFunct) (DilloHtml *html, const char *tag, int tagsize); +typedef void (*TagCloseFunct) (DilloHtml *html, int TagIdx); typedef enum { SEEK_ATTR_START, @@ -305,9 +304,7 @@ static void Html_add_new_htmlimage(DilloHtml *html, * Evaluates the ALIGN attribute (left|center|right|justify) and * sets the style at the top of the stack. */ -void a_Html_tag_set_align_attr(DilloHtml *html, - CssPropertyList *props, - const char *tag, int tagsize) +void a_Html_tag_set_align_attr(DilloHtml *html, const char *tag, int tagsize) { const char *align; @@ -340,7 +337,8 @@ void a_Html_tag_set_align_attr(DilloHtml *html, style_attrs.textAlignChar = '.'; } #endif - props->set (CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, textAlignType); + html->styleEngine->setNonCssHint(CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, + textAlignType); } } @@ -348,8 +346,7 @@ void a_Html_tag_set_align_attr(DilloHtml *html, * Evaluates the VALIGN attribute (top|bottom|middle|baseline) and * sets the style in style_attrs. Returns true when set. */ -bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag, - int tagsize, CssPropertyList *props) +bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag, int tagsize) { const char *attr; VAlignType valign; @@ -364,7 +361,8 @@ bool a_Html_tag_set_valign_attr(DilloHtml *html, const char *tag, else valign = VALIGN_MIDDLE; - props->set (CSS_PROPERTY_VERTICAL_ALIGN, CSS_TYPE_ENUM, valign); + html->styleEngine->setNonCssHint (CSS_PROPERTY_VERTICAL_ALIGN, + CSS_TYPE_ENUM, valign); return true; } else return false; @@ -433,9 +431,9 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url, stack = new misc::SimpleVector <DilloHtmlState> (16); stack->increase(); - stack->getRef(0)->table_cell_props = NULL; stack->getRef(0)->parse_mode = DILLO_HTML_PARSE_MODE_INIT; stack->getRef(0)->table_mode = DILLO_HTML_TABLE_MODE_NONE; + stack->getRef(0)->table_border_mode = DILLO_HTML_TABLE_BORDER_SEPARATE; stack->getRef(0)->cell_text_align_set = false; stack->getRef(0)->list_type = HTML_LIST_NONE; stack->getRef(0)->list_number = 0; @@ -586,9 +584,6 @@ int DilloHtml::getCurTagLineNumber() */ void DilloHtml::freeParseData() { - for (int i = stack->size () - 1; i >= 0; i--) - if (stack->getRef (i)->table_cell_props) - stack->getRef (i)->table_cell_props->unref (); delete(stack); dStr_free(Stash, TRUE); @@ -1189,13 +1184,13 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) dFree(Pword); } else { - const char *word2, *word2_end; + const char *word2, *beyond_word2; Pword = NULL; if (!memchr(word,'&', size)) { /* No entities */ word2 = word; - word2_end = word + size - 1; + beyond_word2 = word + size; } else { /* Collapse white-space entities inside the word (except ) */ Pword = a_Html_parse_entities(html, word, size); @@ -1210,7 +1205,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) } } word2 = Pword; - word2_end = word2 + strlen(word2) - 1; + beyond_word2 = word2 + strlen(word2); } for (start = i = 0; word2[i]; start = i) { int len; @@ -1220,7 +1215,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) Html_process_space(html, word2 + start, i - start); } else if (!strncmp(word2+i, utf8_zero_width_space, 3)) { i += 3; - } else if (a_Utf8_ideographic(word2+i, word2_end, &len)) { + } else if (a_Utf8_ideographic(word2+i, beyond_word2, &len)) { i += len; HT2TB(html)->addText(word2 + start, i - start, html->styleEngine->wordStyle ()); @@ -1229,7 +1224,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) i += len; } while (word2[i] && !isspace(word2[i]) && strncmp(word2+i, utf8_zero_width_space, 3) && - (!a_Utf8_ideographic(word2+i, word2_end, &len))); + (!a_Utf8_ideographic(word2+i, beyond_word2, &len))); HT2TB(html)->addText(word2 + start, i - start, html->styleEngine->wordStyle ()); } @@ -1284,8 +1279,6 @@ static void Html_push_tag(DilloHtml *html, int tag_idx) * instead of copying all fields except for tag. --Jcid */ *html->stack->getRef(n_items) = *html->stack->getRef(n_items - 1); html->stack->getRef(n_items)->tag_idx = tag_idx; - if (S_TOP(html)->table_cell_props) - S_TOP(html)->table_cell_props->ref (); html->dw = S_TOP(html)->textblock; } @@ -1307,8 +1300,6 @@ static void Html_real_pop_tag(DilloHtml *html) bool hand_over_break; html->styleEngine->endElement (S_TOP(html)->tag_idx); - if (S_TOP(html)->table_cell_props) - S_TOP(html)->table_cell_props->unref (); hand_over_break = S_TOP(html)->hand_over_break; html->stack->setSize (html->stack->size() - 1); Html_eventually_pop_dw(html, hand_over_break); @@ -1505,7 +1496,8 @@ static int */ static void Html_parse_doctype(DilloHtml *html, const char *tag, int tagsize) { - static const char HTML_sig [] = "<!DOCTYPE HTML PUBLIC "; + static const char HTML_SGML_sig [] = "<!DOCTYPE HTML PUBLIC "; + static const char HTML5_sig [] = "<!DOCTYPE html>"; static const char HTML20 [] = "-//IETF//DTD HTML 2.0"; static const char HTML32 [] = "-//W3C//DTD HTML 3.2"; static const char HTML40 [] = "-//W3C//DTD HTML 4.0"; @@ -1541,8 +1533,8 @@ static void Html_parse_doctype(DilloHtml *html, const char *tag, int tagsize) _MSG("New: {%s}\n", ntag); /* The default DT_NONE type is TagSoup */ - if (!dStrncasecmp(ntag, HTML_sig, strlen(HTML_sig))) { - p = ntag + strlen(HTML_sig) + 1; + if (!dStrncasecmp(ntag, HTML_SGML_sig, strlen(HTML_SGML_sig))) { + p = ntag + strlen(HTML_SGML_sig) + 1; if (!strncmp(p, HTML401, strlen(HTML401)) && dStristr(p + strlen(HTML401), HTML401_url)) { html->DocType = DT_HTML; @@ -1565,6 +1557,10 @@ static void Html_parse_doctype(DilloHtml *html, const char *tag, int tagsize) html->DocType = DT_HTML; html->DocTypeVersion = 2.0f; } + } else if (!dStrcasecmp(ntag, HTML5_sig)) { + BUG_MSG("Document follows HTML5 working draft; treating as HTML4.\n"); + html->DocType = DT_HTML; + html->DocTypeVersion = 5.0f; } dFree(ntag); @@ -1728,9 +1724,9 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) { const char *attrbuf; Textblock *textblock; - CssPropertyList props; int32_t color; int tag_index_a = a_Html_tag_index ("a"); + style::Color *bgColor; if (!(html->InFlags & IN_BODY)) html->InFlags |= IN_BODY; @@ -1750,24 +1746,32 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) { color = a_Html_color_parse(html, attrbuf, -1); if (color != -1) - props.set (CSS_PROPERTY_BACKGROUND_COLOR, CSS_TYPE_COLOR, color); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BACKGROUND_COLOR, + CSS_TYPE_COLOR, color); } if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "text"))) { color = a_Html_color_parse(html, attrbuf, -1); if (color != -1) - props.set (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, color); + html->styleEngine->setNonCssHint (CSS_PROPERTY_COLOR, + CSS_TYPE_COLOR, color); } + html->styleEngine->restyle (); + if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "link"))) html->non_css_link_color = a_Html_color_parse(html, attrbuf, -1); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vlink"))) html->non_css_visited_color = a_Html_color_parse(html, attrbuf, -1); - html->styleEngine->setNonCssHints (&props); html->dw->setStyle (html->styleEngine->style ()); + bgColor = html->styleEngine->backgroundColor (); + + if (bgColor) + HT2LT(html)->setBgColor(bgColor); + /* Determine a color for visited links. * This color is computed once per page and used for immediate feedback * when clicking a link. @@ -1777,10 +1781,8 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->startElement (tag_index_a); html->styleEngine->setPseudoVisited (); if (html->non_css_visited_color != -1) { - CssPropertyList vprops; - vprops.set (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, - html->non_css_visited_color); - html->styleEngine->setNonCssHints (&vprops); + html->styleEngine->setNonCssHint (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, + html->non_css_visited_color); } html->visited_color = html->styleEngine->style ()->color->getColor (); html->styleEngine->endElement (tag_index_a); @@ -1794,6 +1796,7 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->backgroundStyle()->backgroundColor->getColor()); } + S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_BODY; } @@ -1817,9 +1820,8 @@ static void Html_tag_open_p(DilloHtml *html, const char *tag, int tagsize) { CssPropertyList props; - a_Html_tag_set_align_attr (html, &props, tag, tagsize); + a_Html_tag_set_align_attr (html, tag, tagsize); html->styleEngine->inheritBackgroundColor (); - html->styleEngine->setNonCssHints (&props); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); } @@ -1855,8 +1857,8 @@ static void Html_tag_open_frame (DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setPseudoLink (); } - props.set (PROPERTY_X_LINK, CSS_TYPE_INTEGER, Html_set_new_link(html,&url)); - html->styleEngine->setNonCssHints (&props); + html->styleEngine->setNonCssHint (PROPERTY_X_LINK, CSS_TYPE_INTEGER, + Html_set_new_link(html,&url)); textblock->addParbreak (5, html->styleEngine->wordStyle ()); @@ -1902,12 +1904,8 @@ static void Html_tag_open_frameset (DilloHtml *html, */ static void Html_tag_open_h(DilloHtml *html, const char *tag, int tagsize) { - CssPropertyList props; - - html->styleEngine->inheritBackgroundColor (); - a_Html_tag_set_align_attr (html, &props, tag, tagsize); - html->styleEngine->setNonCssHints (&props); + a_Html_tag_set_align_attr (html, tag, tagsize); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); @@ -1932,7 +1930,6 @@ static void Html_tag_open_font(DilloHtml *html, const char *tag, int tagsize) const char *attrbuf; char *fontFamily = NULL; int32_t color; - CssPropertyList props; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "color"))) { if (prefs.contrast_visited_color && html->InVisitedLink) { @@ -1942,15 +1939,16 @@ static void Html_tag_open_font(DilloHtml *html, const char *tag, int tagsize) color = a_Html_color_parse(html, attrbuf, -1); } if (color != -1) - props.set (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, color); + html->styleEngine->setNonCssHint (CSS_PROPERTY_COLOR, + CSS_TYPE_COLOR, color); } if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "face"))) { fontFamily = dStrdup(attrbuf); - props.set (CSS_PROPERTY_FONT_FAMILY, CSS_TYPE_SYMBOL, fontFamily); + html->styleEngine->setNonCssHint (CSS_PROPERTY_FONT_FAMILY, + CSS_TYPE_SYMBOL, fontFamily); } - html->styleEngine->setNonCssHints (&props); dFree(fontFamily); } @@ -1961,14 +1959,13 @@ static void Html_tag_open_abbr(DilloHtml *html, const char *tag, int tagsize) { const char *attrbuf; + html->styleEngine->inheritBackgroundColor (); + if (prefs.show_tooltip && (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { - CssPropertyList props; - char *tooltip_str = dStrdup(attrbuf); - props.set (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, tooltip_str); - html->styleEngine->setNonCssHints (&props); - dFree(tooltip_str); + html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, + attrbuf); } } @@ -1977,6 +1974,7 @@ static void Html_tag_open_abbr(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_open_center(DilloHtml *html, const char *tag, int tagsize) { + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (0, html->styleEngine->wordStyle ()); } @@ -1994,6 +1992,7 @@ static void Html_tag_close_center(DilloHtml *html, int TagIdx) static void Html_tag_open_address(DilloHtml *html, const char *tag, int tagsize) { + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); } @@ -2010,13 +2009,11 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, CssLength l_h = CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO); int space, border, w = 0, h = 0; bool load_now; - CssPropertyList props; - char *tooltip_str = NULL; if (prefs.show_tooltip && (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { - tooltip_str = dStrdup(attrbuf); - props.set (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, tooltip_str); + html->styleEngine->setNonCssHint(PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, + attrbuf); } alt_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "alt", NULL); if ((!alt_ptr || !*alt_ptr) && !prefs.load_images) { @@ -2052,12 +2049,14 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, dFree(width_ptr); dFree(height_ptr); width_ptr = height_ptr = NULL; - MSG("a_Html_image_new: suspicious image size request %dx%d\n", w, h); + MSG("a_Html_image_new: suspicious image size request %d x %d\n", w, h); } else { if (CSS_LENGTH_TYPE(l_w) != CSS_LENGTH_TYPE_AUTO) - props.set (CSS_PROPERTY_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, l_w); + html->styleEngine->setNonCssHint (CSS_PROPERTY_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, l_w); if (CSS_LENGTH_TYPE(l_h) != CSS_LENGTH_TYPE_AUTO) - props.set (CSS_PROPERTY_HEIGHT, CSS_TYPE_LENGTH_PERCENTAGE, l_h); + html->styleEngine->setNonCssHint (CSS_PROPERTY_HEIGHT, + CSS_TYPE_LENGTH_PERCENTAGE, l_h); } /* TODO: we should scale the image respecting its ratio. @@ -2072,10 +2071,10 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, space = strtol(attrbuf, NULL, 10); if (space > 0) { space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_MARGIN_LEFT, CSS_TYPE_LENGTH_PERCENTAGE, - space); - props.set (CSS_PROPERTY_MARGIN_RIGHT, CSS_TYPE_LENGTH_PERCENTAGE, - space); + html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_LEFT, + CSS_TYPE_LENGTH_PERCENTAGE, space); + html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_RIGHT, + CSS_TYPE_LENGTH_PERCENTAGE, space); } } @@ -2084,10 +2083,10 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, space = strtol(attrbuf, NULL, 10); if (space > 0) { space = CSS_CREATE_LENGTH(space, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_MARGIN_TOP, CSS_TYPE_LENGTH_PERCENTAGE, - space); - props.set (CSS_PROPERTY_MARGIN_BOTTOM, CSS_TYPE_LENGTH_PERCENTAGE, - space); + html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_TOP, + CSS_TYPE_LENGTH_PERCENTAGE, space); + html->styleEngine->setNonCssHint (CSS_PROPERTY_MARGIN_BOTTOM, + CSS_TYPE_LENGTH_PERCENTAGE, space); } } @@ -2096,31 +2095,30 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, border = strtol(attrbuf, NULL, 10); if (border >= 0) { border = CSS_CREATE_LENGTH(border, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_BORDER_TOP_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - border); - props.set (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, border); - props.set (CSS_PROPERTY_BORDER_LEFT_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, border); - props.set (CSS_PROPERTY_BORDER_RIGHT_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, border); - - props.set (CSS_PROPERTY_BORDER_TOP_STYLE, CSS_TYPE_ENUM, - BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_BOTTOM_STYLE, CSS_TYPE_ENUM, - BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_LEFT_STYLE, CSS_TYPE_ENUM, - BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_RIGHT_STYLE, CSS_TYPE_ENUM, - BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, border); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, border); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, border); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, border); + + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); } } /* x_img is an index to a list of {url,image} pairs. * We know Html_add_new_htmlimage() will use size() as its next index */ - props.set (PROPERTY_X_IMG, CSS_TYPE_INTEGER, html->images->size()); - - html->styleEngine->setNonCssHints(&props); + html->styleEngine->setNonCssHint (PROPERTY_X_IMG, CSS_TYPE_INTEGER, + html->images->size()); /* Add a new image widget to this page */ Image = a_Image_new(alt_ptr, 0); @@ -2135,7 +2133,6 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, loading = Html_load_image(html->bw, url, html->page_url, Image); Html_add_new_htmlimage(html, &url, loading ? NULL : Image); - dFree(tooltip_str); dFree(width_ptr); dFree(height_ptr); dFree(alt_ptr); @@ -2279,7 +2276,7 @@ misc::SimpleVector<int> *Html_read_coords(DilloHtml *html, const char *str) if (!*newtail) break; if (*newtail != ',') { - BUG_MSG("usemap coords MUST be separated by commas.\n"); + BUG_MSG("area coords must be integers separated by commas.\n"); } tail = newtail + 1; } @@ -2347,10 +2344,6 @@ static void Html_tag_open_area(DilloHtml *html, const char *tag, int tagsize) shape = poly = new Polygon(); for (i = 0; i < (coords->size() / 2); i++) poly->addPoint(coords->get(2*i), coords->get(2*i + 1)); - if (i) { - /* be sure to close it */ - poly->addPoint(coords->get(0), coords->get(1)); - } } delete(coords); } @@ -2379,7 +2372,6 @@ static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize) { DilloUrl *url, *base_url = NULL; const char *attrbuf; - CssPropertyList props; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "codebase"))) { base_url = a_Html_url_new(html, attrbuf, NULL, 0); @@ -2396,9 +2388,8 @@ static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setPseudoLink (); } - props.set(PROPERTY_X_LINK, CSS_TYPE_INTEGER, - Html_set_new_link(html, &url)); - html->styleEngine->setNonCssHints (&props); + html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER, + Html_set_new_link(html, &url)); HT2TB(html)->addText("[OBJECT]", html->styleEngine->wordStyle ()); } @@ -2452,8 +2443,6 @@ static void Html_add_anchor(DilloHtml *html, const char *name) static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize) { DilloUrl *url; - char *tooltip_str = NULL; - CssPropertyList props; const char *attrbuf; /* TODO: add support for MAP with A HREF */ @@ -2472,25 +2461,23 @@ static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize) html->InVisitedLink = true; html->styleEngine->setPseudoVisited (); if (html->non_css_visited_color != -1) - props.set (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, - html->non_css_visited_color); + html->styleEngine->setNonCssHint(CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, + html->non_css_visited_color); } else { html->styleEngine->setPseudoLink (); if (html->non_css_link_color != -1) - props.set (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, - html->non_css_link_color); + html->styleEngine->setNonCssHint(CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, + html->non_css_link_color); } - props.set (PROPERTY_X_LINK, CSS_TYPE_INTEGER, - Html_set_new_link(html, &url)); + html->styleEngine->setNonCssHint (PROPERTY_X_LINK, CSS_TYPE_INTEGER, + Html_set_new_link(html, &url)); } if (prefs.show_tooltip && (attrbuf = a_Html_get_attr(html, tag, tagsize, "title"))) { - tooltip_str = dStrdup(attrbuf); - props.set (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, tooltip_str); + html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, + attrbuf); } - html->styleEngine->setNonCssHints (&props); - dFree(tooltip_str); html->styleEngine->inheritBackgroundColor (); @@ -2538,13 +2525,14 @@ static void Html_tag_open_blockquote(DilloHtml *html, */ static void Html_tag_open_q(DilloHtml *html, const char *tag, int tagsize) { - /* - * Left Double Quotation Mark, which is wrong in many cases, but - * should at least be widely recognized. - */ - const char *U201C = "\xe2\x80\x9c"; + /* + * Left Double Quotation Mark, which is wrong in many cases, but + * should at least be widely recognized. + */ + const char *U201C = "\xe2\x80\x9c"; - HT2TB(html)->addText (U201C, html->styleEngine->wordStyle ()); + html->styleEngine->inheritBackgroundColor (); + HT2TB(html)->addText (U201C, html->styleEngine->wordStyle ()); } /* @@ -2567,7 +2555,6 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize) ListStyleType list_style_type; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) { - CssPropertyList props; /* list_style_type explicitly defined */ if (dStrcasecmp(attrbuf, "disc") == 0) @@ -2580,8 +2567,8 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize) /* invalid value */ list_style_type = LIST_STYLE_TYPE_DISC; - props.set(CSS_PROPERTY_LIST_STYLE_TYPE, CSS_TYPE_ENUM, list_style_type); - html->styleEngine->setNonCssHints (&props); + html->styleEngine->setNonCssHint (CSS_PROPERTY_LIST_STYLE_TYPE, + CSS_TYPE_ENUM, list_style_type); } Html_add_textblock(html, 9); @@ -2597,6 +2584,7 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_open_dir(DilloHtml *html, const char *tag, int tagsize) { + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); S_TOP(html)->list_type = HTML_LIST_UNORDERED; @@ -2624,7 +2612,6 @@ static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize) int n = 1; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "type"))) { - CssPropertyList props; ListStyleType listStyleType = LIST_STYLE_TYPE_DECIMAL; if (*attrbuf == '1') @@ -2638,8 +2625,8 @@ static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize) else if (*attrbuf == 'I') listStyleType = LIST_STYLE_TYPE_UPPER_ROMAN; - props.set (CSS_PROPERTY_LIST_STYLE_TYPE, CSS_TYPE_ENUM, listStyleType); - html->styleEngine->setNonCssHints (&props); + html->styleEngine->setNonCssHint (CSS_PROPERTY_LIST_STYLE_TYPE, + CSS_TYPE_ENUM, listStyleType); } Html_add_textblock(html, 9); @@ -2717,29 +2704,33 @@ static void Html_tag_close_li(DilloHtml *html, int TagIdx) static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize) { Widget *hruler; - CssPropertyList props; char *width_ptr; const char *attrbuf; int32_t size = 0; width_ptr = a_Html_get_attr_wdef(html, tag, tagsize, "width", NULL); if (width_ptr) { - props.set (CSS_PROPERTY_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - a_Html_parse_length (html, width_ptr)); + html->styleEngine->setNonCssHint (CSS_PROPERTY_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, + a_Html_parse_length (html, width_ptr)); dFree(width_ptr); } if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "size"))) size = strtol(attrbuf, NULL, 10); - a_Html_tag_set_align_attr(html, &props, tag, tagsize); + a_Html_tag_set_align_attr(html, tag, tagsize); /* TODO: evaluate attribute */ if (a_Html_get_attr(html, tag, tagsize, "noshade")) { - props.set (CSS_PROPERTY_BORDER_TOP_STYLE, CSS_TYPE_ENUM, BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_BOTTOM_STYLE,CSS_TYPE_ENUM,BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_LEFT_STYLE, CSS_TYPE_ENUM, BORDER_SOLID); - props.set (CSS_PROPERTY_BORDER_RIGHT_STYLE, CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE, + CSS_TYPE_ENUM, BORDER_SOLID); if (size <= 0) size = 1; @@ -2748,18 +2739,16 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize) if (size > 0) { CssLength size_top = CSS_CREATE_LENGTH ((size+1)/2, CSS_LENGTH_TYPE_PX); CssLength size_bottom = CSS_CREATE_LENGTH (size / 2, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_BORDER_TOP_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - size_top); - props.set (CSS_PROPERTY_BORDER_LEFT_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - size_top); - props.set (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - size_bottom); - props.set (CSS_PROPERTY_BORDER_RIGHT_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - size_bottom); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, size_top); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, size_top); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, size_bottom); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, size_bottom); } - html->styleEngine->setNonCssHints (&props); - HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); hruler = new Ruler(); @@ -2774,6 +2763,7 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize) static void Html_tag_open_dl(DilloHtml *html, const char *tag, int tagsize) { /* may want to actually do some stuff here. */ + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); } @@ -2782,6 +2772,7 @@ static void Html_tag_open_dl(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_open_dt(DilloHtml *html, const char *tag, int tagsize) { + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); } @@ -2798,6 +2789,7 @@ static void Html_tag_open_dd(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_open_pre(DilloHtml *html, const char *tag, int tagsize) { + html->styleEngine->inheritBackgroundColor (); HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); html->InFlags |= IN_PRE; @@ -2879,41 +2871,44 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize) } /* Skip to anything after "URL=" */ while (*content && *(content++) != '=') ; - /* Handle the case of a quoted URL */ - if (*content == '"' || *content == '\'') { - if ((p = strchr(content + 1, *content))) - mr_url = dStrndup(content + 1, p - content - 1); - else - mr_url = dStrdup(content + 1); - } else { - mr_url = dStrdup(content); - } + if (*content) { - if (delay == 0) { - /* zero-delay redirection */ - html->stop_parser = true; - DilloUrl *new_url = a_Url_new(mr_url, URL_STR(html->base_url)); - if (a_Capi_dpi_verify_request(html->bw, new_url)) - a_UIcmd_redirection0((void*)html->bw, new_url); - a_Url_free(new_url); - } else { - /* Send a custom HTML message. - * TODO: This is a hairy hack, - * It'd be much better to build a widget. */ - Dstr *ds_msg = dStr_sized_new(256); - dStr_sprintf(ds_msg, meta_template, mr_url, delay_str); - { - int o_InFlags = html->InFlags; - int o_TagSoup = html->TagSoup; - html->InFlags = IN_BODY; - html->TagSoup = false; - Html_write_raw(html, ds_msg->str, ds_msg->len, 0); - html->TagSoup = o_TagSoup; - html->InFlags = o_InFlags; + /* Handle the case of a quoted URL */ + if (*content == '"' || *content == '\'') { + if ((p = strchr(content + 1, *content))) + mr_url = dStrndup(content + 1, p - content - 1); + else + mr_url = dStrdup(content + 1); + } else { + mr_url = dStrdup(content); + } + + if (delay == 0) { + /* zero-delay redirection */ + html->stop_parser = true; + DilloUrl *new_url = a_Url_new(mr_url, URL_STR(html->base_url)); + if (a_Capi_dpi_verify_request(html->bw, new_url)) + a_UIcmd_redirection0((void*)html->bw, new_url); + a_Url_free(new_url); + } else { + /* Send a custom HTML message. + * TODO: This is a hairy hack, + * It'd be much better to build a widget. */ + Dstr *ds_msg = dStr_sized_new(256); + dStr_sprintf(ds_msg, meta_template, mr_url, delay_str); + { + int o_InFlags = html->InFlags; + int o_TagSoup = html->TagSoup; + html->InFlags = IN_BODY; + html->TagSoup = false; + Html_write_raw(html, ds_msg->str, ds_msg->len, 0); + html->TagSoup = o_TagSoup; + html->InFlags = o_InFlags; + } + dStr_free(ds_msg, 1); } - dStr_free(ds_msg, 1); + dFree(mr_url); } - dFree(mr_url); } else if (!dStrcasecmp(equiv, "content-type") && (content = a_Html_get_attr(html, tag, tagsize, "content"))) { @@ -3095,10 +3090,7 @@ static void Html_tag_open_default(DilloHtml *html,const char *tag,int tagsize) */ static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize) { - CssPropertyList props; - - a_Html_tag_set_align_attr (html, &props, tag, tagsize); - html->styleEngine->setNonCssHints (&props); + a_Html_tag_set_align_attr (html, tag, tagsize); Html_add_textblock(html, 0); } @@ -3137,14 +3129,6 @@ static void Html_tag_close_par(DilloHtml *html, int TagIdx) * - Empty elements have both inline and block container clear. * (flow have both set) */ -struct _TagInfo{ - const char *name; - unsigned char Flags; - char EndTag; - uchar_t TagLevel; - TagOpenFunct open; - TagCloseFunct close; -}; const TagInfo Tags[] = { @@ -3739,11 +3723,8 @@ static void Html_callback(int Op, CacheClient_t *Client) static int Html_write_raw(DilloHtml *html, char *buf, int bufsize, int Eof) { char ch = 0, *p, *text; - Textblock *textblock; int token_start, buf_index; - dReturn_val_if_fail ((textblock = HT2TB(html)) != NULL, 0); - /* Now, 'buf' and 'bufsize' define a buffer aligned to start at a token * boundary. Iterate through tokens until end of buffer is reached. */ buf_index = 0; @@ -3862,7 +3843,7 @@ static int Html_write_raw(DilloHtml *html, char *buf, int bufsize, int Eof) } }/*while*/ - textblock->flush (); + HT2TB(html)->flush (); return token_start; } diff --git a/src/html_common.hh b/src/html_common.hh index 3cca82de..cf5c8114 100644 --- a/src/html_common.hh +++ b/src/html_common.hh @@ -64,6 +64,11 @@ typedef enum { } DilloHtmlTableMode; typedef enum { + DILLO_HTML_TABLE_BORDER_SEPARATE, + DILLO_HTML_TABLE_BORDER_COLLAPSE +} DilloHtmlTableBorderMode; + +typedef enum { HTML_LIST_NONE, HTML_LIST_UNORDERED, HTML_LIST_ORDERED @@ -94,10 +99,11 @@ struct _DilloHtmlImage { }; struct _DilloHtmlState { - CssPropertyList *table_cell_props; DilloHtmlParseMode parse_mode; DilloHtmlTableMode table_mode; + DilloHtmlTableBorderMode table_border_mode; bool cell_text_align_set; + DilloHtmlListMode list_type; int list_number; @@ -242,11 +248,9 @@ int32_t a_Html_color_parse(DilloHtml *html, const char *subtag, int32_t default_color); dw::core::style::Length a_Html_parse_length (DilloHtml *html, const char *attr); -void a_Html_tag_set_align_attr(DilloHtml *html, CssPropertyList *props, - const char *tag, int tagsize); +void a_Html_tag_set_align_attr(DilloHtml *html, const char *tag, int tagsize); bool a_Html_tag_set_valign_attr(DilloHtml *html, - const char *tag, int tagsize, - CssPropertyList *props); + const char *tag, int tagsize); void a_Html_load_stylesheet(DilloHtml *html, DilloUrl *url); @@ -1,7 +1,6 @@ /* * File: jpeg.c * - * Copyright (C) 1997 Raph Levien <raph@acm.org> * Copyright (C) 2000-2007 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify @@ -292,7 +291,7 @@ static void Jpeg_write(DilloJpeg *jpeg, void *Buf, uint_t BufSize) if (jpeg->cinfo.image_width <= 0 || jpeg->cinfo.image_height <= 0 || jpeg->cinfo.image_width > IMAGE_MAX_AREA / jpeg->cinfo.image_height) { - MSG("Jpeg_write: suspicious image size request %ux%u\n", + MSG("Jpeg_write: suspicious image size request %u x %u\n", (uint_t)jpeg->cinfo.image_width, (uint_t)jpeg->cinfo.image_height); jpeg->state = DILLO_JPEG_ERROR; @@ -1,7 +1,6 @@ /* * File: misc.c * - * Copyright (C) 2000 Jörgen Viksell <vsksga@hotmail.com> * Copyright (C) 2000-2007 Jorge Arellano Cid <jcid@dillo.org>, * * This program is free software; you can redistribute it and/or modify @@ -105,6 +104,7 @@ typedef struct ContentType_ { static const ContentType_t MimeTypes[] = { { "application/octet-stream", 24 }, + { "application/xhtml+xml", 21 }, { "text/html", 9 }, { "text/plain", 10 }, { "image/gif", 9 }, @@ -342,7 +342,12 @@ int a_Misc_content_type_check(const char *EntryType, const char *DetectedType) dStrncasecmp(DetectedType, "application/", 12)) { /* Not an application sent as text */ st = 0; + } else if (dStrncasecmp(EntryType, "application/xhtml+xml", 21) && + dStrncasecmp(DetectedType, "text/html", 9)) { + /* XML version of HTML */ + st = 0; } + _MSG("Type check: %s\n", st == 0 ? "MATCH" : "MISMATCH"); return st; } @@ -395,7 +395,7 @@ static void Nav_repush_callback(void *data) void a_Nav_repush(BrowserWindow *bw) { dReturn_if_fail (bw != NULL); - MSG(">>> a_Nav_repush <<<<\n"); + MSG(">>>> a_Nav_repush <<<<\n"); a_Timeout_add(0.0, Nav_repush_callback, (void*)bw); } @@ -424,7 +424,7 @@ static void Nav_redirection0_callback(void *data) void a_Nav_redirection0(BrowserWindow *bw, const DilloUrl *new_url) { dReturn_if_fail (bw != NULL); - _MSG(">>> a_Nav_redirection0 <<<<\n"); + _MSG(">>>> a_Nav_redirection0 <<<<\n"); a_Url_free(bw->meta_refresh_url); bw->meta_refresh_url = a_Url_dup(new_url); @@ -65,8 +65,8 @@ struct _DilloPng { int version; /* Secondary Key for the dicache */ double display_exponent; /* gamma correction */ - ulong_t width; /* png image width */ - ulong_t height; /* png image height */ + png_uint_32 width; /* png image width */ + png_uint_32 height; /* png image height */ png_structp png_ptr; /* libpng private data */ png_infop info_ptr; /* libpng private info */ uchar_t *image_data; /* decoded image data */ @@ -135,17 +135,17 @@ Png_datainfo_callback(png_structp png_ptr, png_infop info_ptr) &bit_depth, &color_type, &interlace_type, NULL, NULL); /* check max image size */ - if (png->width <= 0 || png->height <= 0 || + if (png->width == 0 || png->height == 0 || png->width > IMAGE_MAX_AREA / png->height) { - MSG("Png_datainfo_callback: suspicious image size request %ldx%ld\n", - png->width, png->height); + MSG("Png_datainfo_callback: suspicious image size request %lu x %lu\n", + (ulong_t) png->width, (ulong_t) png->height); Png_error_handling(png_ptr, "Aborting..."); return; /* not reached */ } - _MSG("Png_datainfo_callback: png->width = %ld\n" - "Png_datainfo_callback: png->height = %ld\n", - png->width, png->height); + _MSG("Png_datainfo_callback: png->width = %lu\n" + "Png_datainfo_callback: png->height = %lu\n", + (ulong_t) png->width, (ulong_t) png->height); /* we need RGB/RGBA in the end */ if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) { @@ -193,9 +193,9 @@ Png_datainfo_callback(png_structp png_ptr, png_infop info_ptr) /* init Dillo specifics */ _MSG("Png_datainfo_callback: rowbytes = %d\n" - "Png_datainfo_callback: width = %ld\n" - "Png_datainfo_callback: height = %ld\n", - png->rowbytes, png->width, png->height); + "Png_datainfo_callback: width = %lu\n" + "Png_datainfo_callback: height = %lu\n", + png->rowbytes, (ulong_t) png->width, (ulong_t) png->height); png->image_data = (uchar_t *) dMalloc(png->rowbytes * png->height); png->row_pointers = (uchar_t **) dMalloc(png->height * sizeof(uchar_t *)); diff --git a/src/prefs.c b/src/prefs.c index 5514c01a..f968710a 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -36,6 +36,7 @@ DilloPrefs prefs; void a_Prefs_init(void) { prefs.allow_white_bg = TRUE; + prefs.bg_color = 0xdcd1ba; prefs.buffered_drawing = 1; prefs.contrast_visited_color = TRUE; prefs.enterpress_forces_submit = FALSE; diff --git a/src/prefs.h b/src/prefs.h index 684262ed..4009925c 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -46,6 +46,7 @@ struct _DilloPrefs { DilloUrl *start_page; DilloUrl *home; bool_t allow_white_bg; + int32_t bg_color; bool_t contrast_visited_color; bool_t show_tooltip; int panel_size; diff --git a/src/prefsparser.cc b/src/prefsparser.cc index 78cade0b..95f98c16 100644 --- a/src/prefsparser.cc +++ b/src/prefsparser.cc @@ -16,11 +16,13 @@ #include "prefs.h" #include "misc.h" #include "msg.h" +#include "colors.h" #include "prefsparser.hh" typedef enum { PREFS_BOOL, + PREFS_COLOR, PREFS_STRING, PREFS_URL, PREFS_INT32, @@ -43,10 +45,12 @@ int PrefsParser::parseOption(char *name, char *value) { const SymNode_t *node; uint_t i; + int st; /* Symbol array, sorted alphabetically */ const SymNode_t symbols[] = { { "allow_white_bg", &prefs.allow_white_bg, PREFS_BOOL }, + { "bg_color", &prefs.bg_color, PREFS_COLOR }, { "buffered_drawing", &prefs.buffered_drawing, PREFS_INT32 }, { "contrast_visited_color", &prefs.contrast_visited_color, PREFS_BOOL }, { "enterpress_forces_submit", &prefs.enterpress_forces_submit, @@ -122,6 +126,9 @@ int PrefsParser::parseOption(char *name, char *value) *(bool_t *)node->pref = (!dStrcasecmp(value, "yes") || !dStrcasecmp(value, "true")); break; + case PREFS_COLOR: + *(int32_t *)node->pref = a_Color_parse(value, *(int32_t*)node->pref,&st); + break; case PREFS_STRING: dFree(*(char **)node->pref); *(char **)node->pref = dStrdup(value); diff --git a/src/styleengine.cc b/src/styleengine.cc index b861e717..776c1694 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -15,6 +15,7 @@ #include "html_common.hh" #include "styleengine.hh" +using namespace lout::misc; using namespace dw::core::style; StyleEngine::StyleEngine (dw::core::Layout *layout) { @@ -32,7 +33,7 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) { /* Create a dummy font, attribute, and tag for the bottom of the stack. */ font_attrs.name = prefs.font_sans_serif; - font_attrs.size = (int) (14 * prefs.font_factor + 0.5); + font_attrs.size = roundInt(14 * prefs.font_factor); if (font_attrs.size < prefs.font_min_size) font_attrs.size = prefs.font_min_size; if (font_attrs.size > prefs.font_max_size) @@ -40,6 +41,7 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) { font_attrs.weight = 400; font_attrs.style = FONT_STYLE_NORMAL; font_attrs.letterSpacing = 0; + font_attrs.fontVariant = FONT_VARIANT_NORMAL; style_attrs.initValues (); style_attrs.font = Font::create (layout, &font_attrs); @@ -48,13 +50,23 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) { n->style = Style::create (layout, &style_attrs); n->wordStyle = NULL; - n->styleAttribute = NULL; + n->backgroundStyle = NULL; + n->styleAttrProperties = NULL; + n->nonCssProperties = NULL; n->inheritBackgroundColor = false; } StyleEngine::~StyleEngine () { while (doctree->top ()) endElement (doctree->top ()->element); + assert (stack->size () == 1); // dummy node on the bottom of the stack + Node *n = stack->getRef (stack->size () - 1); + if (n->style) + n->style->unref (); + if (n->wordStyle) + n->wordStyle->unref (); + if (n->backgroundStyle) + n->backgroundStyle->unref (); delete stack; delete doctree; delete cssContext; @@ -65,17 +77,20 @@ StyleEngine::~StyleEngine () { */ void StyleEngine::startElement (int element) { if (stack->getRef (stack->size () - 1)->style == NULL) - style0 (); + style0 (stack->size () - 1); stack->increase (); Node *n = stack->getRef (stack->size () - 1); + n->styleAttrProperties = NULL; + n->nonCssProperties = NULL; n->style = NULL; n->wordStyle = NULL; - n->styleAttribute = NULL; + n->backgroundStyle = NULL; n->inheritBackgroundColor = false; DoctreeNode *dn = doctree->push (); dn->element = element; + n->doctreeNode = dn; } void StyleEngine::startElement (const char *tagname) { @@ -119,20 +134,36 @@ void StyleEngine::setClass (const char *klass) { dn->klass = splitStr (klass, ' '); }; -void StyleEngine::setStyle (const char *style) { +void StyleEngine::setStyle (const char *styleAttr) { Node *n = stack->getRef (stack->size () - 1); - assert (n->styleAttribute == NULL); - n->styleAttribute = dStrdup (style); + assert (n->styleAttrProperties == NULL); + // parse style information from style="" attribute, if it exists + if (styleAttr && prefs.parse_embedded_css) + n->styleAttrProperties = + CssParser::parseDeclarationBlock (styleAttr, + strlen (styleAttr)); }; /** - * \brief set properties that were definded using (mostly deprecated) HTML - * attributes (e.g. bgColor). + * \brief Instruct StyleEngine to use the nonCssHints from parent element + * This is only used for tables where nonCssHints on the TABLE-element + * (e.g. border=1) also affect child elements like TD. */ -void StyleEngine::setNonCssHints (CssPropertyList *nonCssHints) { - if (stack->getRef (stack->size () - 1)->style) - stack->getRef (stack->size () - 1)->style->unref (); - style0 (nonCssHints); // evaluate now, so caller can free nonCssHints +void StyleEngine::inheritNonCssHints () { + Node *pn = stack->getRef (stack->size () - 2); + Node *n = stack->getRef (stack->size () - 1); + + if (pn->nonCssProperties) + n->nonCssProperties = new CssPropertyList (*pn->nonCssProperties, true); +} + +void StyleEngine::clearNonCssHints () { + Node *n = stack->getRef (stack->size () - 1); + + if (n->nonCssProperties) { + delete n->nonCssProperties; + n->nonCssProperties = NULL; + } } /** @@ -145,6 +176,17 @@ void StyleEngine::inheritBackgroundColor () { stack->getRef (stack->size () - 1)->inheritBackgroundColor = true; } +dw::core::style::Color *StyleEngine::backgroundColor () { + for (int i = 1; i < stack->size (); i++) { + Node *n = stack->getRef (i); + + if (n->style && n->style->backgroundColor) + return n->style->backgroundColor; + } + + return NULL; +} + /** * \brief set the CSS pseudo class :link. */ @@ -165,32 +207,80 @@ void StyleEngine::setPseudoVisited () { * \brief tell the styleEngine that a html element has ended. */ void StyleEngine::endElement (int element) { - assert (stack->size () > 0); assert (element == doctree->top ()->element); Node *n = stack->getRef (stack->size () - 1); + if (n->styleAttrProperties) + delete n->styleAttrProperties; + if (n->nonCssProperties) + delete n->nonCssProperties; if (n->style) n->style->unref (); if (n->wordStyle) n->wordStyle->unref (); - if (n->styleAttribute) - dFree ((void*) n->styleAttribute); + if (n->backgroundStyle) + n->backgroundStyle->unref (); doctree->pop (); stack->setSize (stack->size () - 1); } +void StyleEngine::preprocessAttrs (dw::core::style::StyleAttrs *attrs) { + /* workaround for styling of inline elements */ + if (stack->getRef (stack->size () - 2)->inheritBackgroundColor) { + attrs->backgroundColor = + stack->getRef (stack->size () - 2)->style->backgroundColor; + + attrs->valign = stack->getRef (stack->size () - 2)->style->valign; + } + attrs->borderColor.top = (Color *) -1; + attrs->borderColor.bottom = (Color *) -1; + attrs->borderColor.left = (Color *) -1; + attrs->borderColor.right = (Color *) -1; + /* initial value of border-width is 'medium' */ + attrs->borderWidth.top = 2; + attrs->borderWidth.bottom = 2; + attrs->borderWidth.left = 2; + attrs->borderWidth.right = 2; +} + +void StyleEngine::postprocessAttrs (dw::core::style::StyleAttrs *attrs) { + /* if border-color is not specified, use color as computed value */ + if (attrs->borderColor.top == (Color *) -1) + attrs->borderColor.top = attrs->color; + if (attrs->borderColor.bottom == (Color *) -1) + attrs->borderColor.bottom = attrs->color; + if (attrs->borderColor.left == (Color *) -1) + attrs->borderColor.left = attrs->color; + if (attrs->borderColor.right == (Color *) -1) + attrs->borderColor.right = attrs->color; + /* computed value of border-width is 0 if border-style + is 'none' or 'hidden' */ + if (attrs->borderStyle.top == BORDER_NONE || + attrs->borderStyle.top == BORDER_HIDDEN) + attrs->borderWidth.top = 0; + if (attrs->borderStyle.bottom == BORDER_NONE || + attrs->borderStyle.bottom == BORDER_HIDDEN) + attrs->borderWidth.bottom = 0; + if (attrs->borderStyle.left == BORDER_NONE || + attrs->borderStyle.left == BORDER_HIDDEN) + attrs->borderWidth.left = 0; + if (attrs->borderStyle.right == BORDER_NONE || + attrs->borderStyle.right == BORDER_HIDDEN) + attrs->borderWidth.right = 0; +} + /** * \brief Make changes to StyleAttrs attrs according to CssPropertyList props. */ -void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { +void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props) { FontAttrs fontAttrs = *attrs->font; - Font *parentFont = stack->get (stack->size () - 2).style->font; + Font *parentFont = stack->get (i - 1).style->font; char *c, *fontName; int lineHeight; - /* Determine font first so it can be used to resolve relative lenths. */ + /* Determine font first so it can be used to resolve relative lengths. */ for (int i = 0; i < props->size (); i++) { CssProperty *p = props->getRef (i); @@ -233,31 +323,30 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { if (p->type == CSS_TYPE_ENUM) { switch (p->value.intVal) { case CSS_FONT_SIZE_XX_SMALL: - fontAttrs.size = (int) (11.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(11.0 * prefs.font_factor); break; case CSS_FONT_SIZE_X_SMALL: - fontAttrs.size = (int) (12.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(12.0 * prefs.font_factor); break; case CSS_FONT_SIZE_SMALL: - fontAttrs.size = (int) (13.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(13.0 * prefs.font_factor); break; case CSS_FONT_SIZE_MEDIUM: - fontAttrs.size = (int) (14.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(14.0 * prefs.font_factor); break; case CSS_FONT_SIZE_LARGE: - fontAttrs.size = (int) (15.0 * prefs.font_factor + 0.5); break; case CSS_FONT_SIZE_X_LARGE: - fontAttrs.size = (int) (16.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(16.0 * prefs.font_factor); break; case CSS_FONT_SIZE_XX_LARGE: - fontAttrs.size = (int) (17.0 * prefs.font_factor + 0.5); + fontAttrs.size = roundInt(17.0 * prefs.font_factor); break; case CSS_FONT_SIZE_SMALLER: - fontAttrs.size -= (int) (1.0 * prefs.font_factor + 0.5); + fontAttrs.size -= roundInt(1.0 * prefs.font_factor); break; case CSS_FONT_SIZE_LARGER: - fontAttrs.size += (int) (1.0 * prefs.font_factor + 0.5); + fontAttrs.size += roundInt(1.0 * prefs.font_factor); break; default: assert(false); // invalid font-size enum @@ -327,6 +416,9 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { else if (fontAttrs.letterSpacing < -1000) fontAttrs.letterSpacing = -1000; break; + case CSS_PROPERTY_FONT_VARIANT: + fontAttrs.fontVariant = (FontVariant) p->value.intVal; + break; default: break; } @@ -346,21 +438,24 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { //attrs->backgroundColor = Color::create(layout, 0xdcd1ba); attrs->backgroundColor = Color::create(layout, 0xe0e0a3); break; + case CSS_PROPERTY_BORDER_COLLAPSE: + attrs->borderCollapse = (BorderCollapse) p->value.intVal; + break; case CSS_PROPERTY_BORDER_TOP_COLOR: - attrs->borderColor.top = - Color::create (layout, p->value.intVal); + attrs->borderColor.top = (p->type == CSS_TYPE_ENUM) ? NULL : + Color::create (layout, p->value.intVal); break; case CSS_PROPERTY_BORDER_BOTTOM_COLOR: - attrs->borderColor.bottom = - Color::create (layout, p->value.intVal); + attrs->borderColor.bottom = (p->type == CSS_TYPE_ENUM) ? NULL : + Color::create (layout, p->value.intVal); break; case CSS_PROPERTY_BORDER_LEFT_COLOR: - attrs->borderColor.left = - Color::create (layout, p->value.intVal); + attrs->borderColor.left = (p->type == CSS_TYPE_ENUM) ? NULL : + Color::create (layout, p->value.intVal); break; case CSS_PROPERTY_BORDER_RIGHT_COLOR: - attrs->borderColor.right = - Color::create (layout, p->value.intVal); + attrs->borderColor.right = (p->type == CSS_TYPE_ENUM) ? NULL : + Color::create (layout, p->value.intVal); break; case CSS_PROPERTY_BORDER_BOTTOM_STYLE: attrs->borderStyle.bottom = (BorderStyle) p->value.intVal; @@ -409,9 +504,8 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { if (CSS_LENGTH_TYPE (p->value.intVal) == CSS_LENGTH_TYPE_NONE) { attrs->lineHeight = createPerLength(CSS_LENGTH_VALUE(p->value.intVal)); - } else { - computeValue (&lineHeight, p->value.intVal, attrs->font, - attrs->font->size); + } else if (computeValue (&lineHeight, p->value.intVal, + attrs->font, attrs->font->size)) { attrs->lineHeight = createAbsLength(lineHeight); } } @@ -460,6 +554,9 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { case CSS_PROPERTY_TEXT_DECORATION: attrs->textDecoration |= p->value.intVal; break; + case CSS_PROPERTY_TEXT_INDENT: + computeLength (&attrs->textIndent, p->value.intVal, attrs->font); + break; case CSS_PROPERTY_VERTICAL_ALIGN: attrs->valign = (VAlignType) p->value.intVal; break; @@ -501,16 +598,6 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) { } } - /* make sure border colors are set */ - if (attrs->borderColor.top == NULL) - attrs->borderColor.top = attrs->color; - if (attrs->borderColor.bottom == NULL) - attrs->borderColor.bottom = attrs->color; - if (attrs->borderColor.left == NULL) - attrs->borderColor.left = attrs->color; - if (attrs->borderColor.right == NULL) - attrs->borderColor.right = attrs->color; - } /** @@ -527,14 +614,21 @@ bool StyleEngine::computeValue (int *dest, CssLength value, Font *font) { *dest = (int) CSS_LENGTH_VALUE (value); return true; case CSS_LENGTH_TYPE_MM: - *dest = (int) (CSS_LENGTH_VALUE (value) * dpmm + 0.5); - return true; + *dest = roundInt (CSS_LENGTH_VALUE (value) * dpmm); + return true; case CSS_LENGTH_TYPE_EM: - *dest = (int) (CSS_LENGTH_VALUE (value) * font->size + 0.5); - return true; + *dest = roundInt (CSS_LENGTH_VALUE (value) * font->size); + return true; case CSS_LENGTH_TYPE_EX: - *dest = (int) (CSS_LENGTH_VALUE(value) * font->xHeight + 0.5); - return true; + *dest = roundInt (CSS_LENGTH_VALUE(value) * font->xHeight); + return true; + case CSS_LENGTH_TYPE_NONE: + // length values other than 0 without unit are only allowed + // in special cases (line-height) and have to be handled + // separately. + assert ((int) CSS_LENGTH_VALUE (value) == 0); + *dest = 0; + return true; default: break; } @@ -545,7 +639,7 @@ bool StyleEngine::computeValue (int *dest, CssLength value, Font *font) { bool StyleEngine::computeValue (int *dest, CssLength value, Font *font, int percentageBase) { if (CSS_LENGTH_TYPE (value) == CSS_LENGTH_TYPE_PERCENTAGE) { - *dest = (int) (CSS_LENGTH_VALUE (value) * percentageBase + 0.5); + *dest = roundInt (CSS_LENGTH_VALUE (value) * percentageBase); return true; } else return computeValue (dest, value, font); @@ -596,13 +690,17 @@ void StyleEngine::computeBorderWidth (int *dest, CssProperty *p, * background. This method ensures that backgroundColor is set. */ Style * StyleEngine::backgroundStyle () { - StyleAttrs attrs = *style (); + if (!stack->getRef (stack->size () - 1)->backgroundStyle) { + StyleAttrs attrs = *style (); - for (int i = stack->size () - 1; i >= 0 && ! attrs.backgroundColor; i--) - attrs.backgroundColor = stack->getRef (i)->style->backgroundColor; + for (int i = stack->size () - 1; i >= 0 && ! attrs.backgroundColor; i--) + attrs.backgroundColor = stack->getRef (i)->style->backgroundColor; - assert (attrs.backgroundColor); - return Style::create (layout, &attrs); + assert (attrs.backgroundColor); + stack->getRef (stack->size () - 1)->backgroundStyle = + Style::create (layout, &attrs); + } + return stack->getRef (stack->size () - 1)->backgroundStyle; } /** @@ -610,56 +708,45 @@ Style * StyleEngine::backgroundStyle () { * HTML elements and the nonCssProperties that have been set. * This method is private. Call style() to get a current style object. */ -Style * StyleEngine::style0 (CssPropertyList *nonCssProperties) { - CssPropertyList props, *styleAttributeProps = NULL; - const char *styleAttribute = - stack->getRef (stack->size () - 1)->styleAttribute; +Style * StyleEngine::style0 (int i) { + CssPropertyList props, *styleAttrProperties, *nonCssProperties; // get previous style from the stack - StyleAttrs attrs = *stack->getRef (stack->size () - 2)->style; + StyleAttrs attrs = *stack->getRef (i - 1)->style; // Ensure that StyleEngine::style0() has not been called before for // this element. // Style computation is expensive so limit it as much as possible. // If this assertion is hit, you need to rearrange the code that is - // doing styleEngine calls to call setNonCssHints() before calling + // doing styleEngine calls to call setNonCssHint() before calling // style() or wordStyle() for each new element. - assert (stack->getRef (stack->size () - 1)->style == NULL); + assert (stack->getRef (i)->style == NULL); // reset values that are not inherited according to CSS attrs.resetValues (); + preprocessAttrs (&attrs); - if (stack->getRef (stack->size () - 2)->inheritBackgroundColor) { - attrs.backgroundColor = - stack->getRef (stack->size () - 2)->style->backgroundColor; - - attrs.valign = stack->getRef (stack->size () - 2)->style->valign; - } - - // parse style information from style="" attribute, if it exists - if (styleAttribute && prefs.parse_embedded_css) - styleAttributeProps = - CssParser::parseDeclarationBlock (styleAttribute, - strlen (styleAttribute)); + styleAttrProperties = stack->getRef (i)->styleAttrProperties; + nonCssProperties = stack->getRef (i)->nonCssProperties; // merge style information - cssContext->apply (&props, doctree, styleAttributeProps, nonCssProperties); + cssContext->apply (&props, doctree, stack->getRef(i)->doctreeNode, + styleAttrProperties, nonCssProperties); // apply style - apply (&attrs, &props); + apply (i, &attrs, &props); - stack->getRef (stack->size () - 1)->style = Style::create (layout, &attrs); + postprocessAttrs (&attrs); - if (styleAttributeProps) - delete styleAttributeProps; + stack->getRef (i)->style = Style::create (layout, &attrs); - return stack->getRef (stack->size () - 1)->style; + return stack->getRef (i)->style; } -Style * StyleEngine::wordStyle0 (CssPropertyList *nonCssProperties) { +Style * StyleEngine::wordStyle0 () { StyleAttrs attrs = *style (); attrs.resetValues (); - if (stack->getRef (stack->size () - 1)->inheritBackgroundColor) + if (stack->getRef (stack->size() - 1)->inheritBackgroundColor) attrs.backgroundColor = style ()->backgroundColor; attrs.valign = style ()->valign; @@ -668,6 +755,33 @@ Style * StyleEngine::wordStyle0 (CssPropertyList *nonCssProperties) { return stack->getRef (stack->size () - 1)->wordStyle; } +/** + * \brief Recompute all style information from scratch + * This is used to take into account CSS styles for the HTML-element. + * The CSS data is only completely available after parsing the HEAD-section + * and thereby after the HTML-element has been opened. + * Note that restyle() does not change any styles in the widget tree. + */ +void StyleEngine::restyle () { + for (int i = 1; i < stack->size (); i++) { + Node *n = stack->getRef (i); + if (n->style) { + n->style->unref (); + n->style = NULL; + } + if (n->wordStyle) { + n->wordStyle->unref (); + n->wordStyle = NULL; + } + if (n->backgroundStyle) { + n->backgroundStyle->unref (); + n->backgroundStyle = NULL; + } + + style0 (i); + } +} + void StyleEngine::parse (DilloHtml *html, DilloUrl *url, const char *buf, int buflen, CssOrigin origin) { if (importDepth > 10) { // avoid looping with recursive @import directives diff --git a/src/styleengine.hh b/src/styleengine.hh index 66f28cee..e37aeed1 100644 --- a/src/styleengine.hh +++ b/src/styleengine.hh @@ -19,12 +19,14 @@ class StyleEngine; */ class StyleEngine { private: - class Node { - public: - dw::core::style::Style *style; - dw::core::style::Style *wordStyle; - const char *styleAttribute; - bool inheritBackgroundColor; + struct Node { + CssPropertyList *styleAttrProperties; + CssPropertyList *nonCssProperties; + dw::core::style::Style *style; + dw::core::style::Style *wordStyle; + dw::core::style::Style *backgroundStyle; + bool inheritBackgroundColor; + DoctreeNode *doctreeNode; }; dw::core::Layout *layout; @@ -33,9 +35,19 @@ class StyleEngine { Doctree *doctree; int importDepth; - dw::core::style::Style *style0 (CssPropertyList *nonCssHints = NULL); - dw::core::style::Style *wordStyle0 (CssPropertyList *nonCssHints = NULL); - void apply (dw::core::style::StyleAttrs *attrs, CssPropertyList *props); + dw::core::style::Style *style0 (int i); + dw::core::style::Style *wordStyle0 (); + inline void setNonCssHint(CssPropertyName name, CssValueType type, + CssPropertyValue value) { + Node *n = stack->getRef (stack->size () - 1); + + if (!n->nonCssProperties) + n->nonCssProperties = new CssPropertyList (true); + n->nonCssProperties->set(name, type, value); + } + void preprocessAttrs (dw::core::style::StyleAttrs *attrs); + void postprocessAttrs (dw::core::style::StyleAttrs *attrs); + void apply (int i, dw::core::style::StyleAttrs *attrs, CssPropertyList *props); bool computeValue (int *dest, CssLength value, dw::core::style::Font *font); bool computeValue (int *dest, CssLength value, @@ -60,16 +72,31 @@ class StyleEngine { void endElement (int tag); void setPseudoLink (); void setPseudoVisited (); - void setNonCssHints (CssPropertyList *nonCssHints); + inline void setNonCssHint(CssPropertyName name, CssValueType type, + int value) { + CssPropertyValue v; + v.intVal = value; + setNonCssHint (name, type, v); + } + inline void setNonCssHint(CssPropertyName name, CssValueType type, + const char *value) { + CssPropertyValue v; + v.strVal = dStrdup(value); + setNonCssHint (name, type, v); + } + void inheritNonCssHints (); + void clearNonCssHints (); + void restyle (); void inheritBackgroundColor (); /* \todo get rid of this somehow */ dw::core::style::Style *backgroundStyle (); + dw::core::style::Color *backgroundColor (); inline dw::core::style::Style *style () { dw::core::style::Style *s = stack->getRef (stack->size () - 1)->style; if (s) return s; else - return style0 (); + return style0 (stack->size () - 1); }; inline dw::core::style::Style *wordStyle () { diff --git a/src/table.cc b/src/table.cc index 43304206..58cdf22e 100644 --- a/src/table.cc +++ b/src/table.cc @@ -38,7 +38,6 @@ static void Html_tag_open_table_cell(DilloHtml *html, void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize) { dw::core::Widget *table; - CssPropertyList props, *table_cell_props; const char *attrbuf; int32_t border = -1, cellspacing = -1, cellpadding = -1, bgcolor = -1; CssLength cssLength; @@ -52,81 +51,95 @@ void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize) if (border != -1) { cssLength = CSS_CREATE_LENGTH (border, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_BORDER_TOP_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - cssLength); - props.set (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - cssLength); - props.set (CSS_PROPERTY_BORDER_LEFT_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - cssLength); - props.set (CSS_PROPERTY_BORDER_RIGHT_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE, + CSS_TYPE_ENUM, BORDER_OUTSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE, + CSS_TYPE_ENUM, BORDER_OUTSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE, + CSS_TYPE_ENUM, BORDER_OUTSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE, + CSS_TYPE_ENUM, BORDER_OUTSET); } if (cellspacing != -1) { cssLength = CSS_CREATE_LENGTH (cellspacing, CSS_LENGTH_TYPE_PX); - props.set (CSS_PROPERTY_BORDER_SPACING, CSS_TYPE_LENGTH_PERCENTAGE, - cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_SPACING, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); } if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) - props.set (CSS_PROPERTY_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - a_Html_parse_length (html, attrbuf)); + html->styleEngine->setNonCssHint (CSS_PROPERTY_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, + a_Html_parse_length (html, attrbuf)); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "align"))) { if (dStrcasecmp (attrbuf, "left") == 0) - props.set (CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, TEXT_ALIGN_LEFT); + html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN, + CSS_TYPE_ENUM, TEXT_ALIGN_LEFT); else if (dStrcasecmp (attrbuf, "right") == 0) - props.set (CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, TEXT_ALIGN_RIGHT); + html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN, + CSS_TYPE_ENUM, TEXT_ALIGN_RIGHT); else if (dStrcasecmp (attrbuf, "center") == 0) - props.set (CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, TEXT_ALIGN_CENTER); + html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN, + CSS_TYPE_ENUM, TEXT_ALIGN_CENTER); } if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) { bgcolor = a_Html_color_parse(html, attrbuf, -1); if (bgcolor != -1) - props.set (CSS_PROPERTY_BACKGROUND_COLOR, CSS_TYPE_COLOR, bgcolor); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BACKGROUND_COLOR, + CSS_TYPE_COLOR, bgcolor); } - html->styleEngine->setNonCssHints (&props); - HT2TB(html)->addParbreak (0, html->styleEngine->wordStyle ()); /* The style for the cells */ - table_cell_props = new CssPropertyList (); + html->styleEngine->clearNonCssHints (); if (border > 0) { cssLength = CSS_CREATE_LENGTH (1, CSS_LENGTH_TYPE_PX); - table_cell_props->set (CSS_PROPERTY_BORDER_TOP_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_BORDER_LEFT_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_BORDER_RIGHT_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_TOP_STYLE, + CSS_TYPE_ENUM, BORDER_INSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_STYLE, + CSS_TYPE_ENUM, BORDER_INSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_STYLE, + CSS_TYPE_ENUM, BORDER_INSET); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_STYLE, + CSS_TYPE_ENUM, BORDER_INSET); } if (cellpadding != -1) { cssLength = CSS_CREATE_LENGTH (cellpadding, CSS_LENGTH_TYPE_PX); - table_cell_props->set (CSS_PROPERTY_PADDING_TOP, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_PADDING_BOTTOM, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_PADDING_LEFT, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); - table_cell_props->set (CSS_PROPERTY_PADDING_RIGHT, - CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_PADDING_TOP, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_PADDING_BOTTOM, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_PADDING_LEFT, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); + html->styleEngine->setNonCssHint (CSS_PROPERTY_PADDING_RIGHT, + CSS_TYPE_LENGTH_PERCENTAGE, cssLength); } - if (S_TOP(html)->table_cell_props) - S_TOP(html)->table_cell_props->unref (); - - S_TOP(html)->table_cell_props = table_cell_props; - S_TOP(html)->table_cell_props->ref (); - table = new dw::Table(prefs.limit_text_width); HT2TB(html)->addWidget (table, html->styleEngine->style ()); S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TOP; + S_TOP(html)->table_border_mode = DILLO_HTML_TABLE_BORDER_SEPARATE; S_TOP(html)->cell_text_align_set = FALSE; S_TOP(html)->table = table; } @@ -139,7 +152,8 @@ void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize) const char *attrbuf; int32_t bgcolor = -1; bool new_style = false; - CssPropertyList props, *table_cell_props; + + html->styleEngine->inheritNonCssHints (); switch (S_TOP(html)->table_mode) { case DILLO_HTML_TABLE_MODE_NONE: @@ -153,34 +167,26 @@ void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize) if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) { bgcolor = a_Html_color_parse(html, attrbuf, -1); if (bgcolor != -1) - props.set (CSS_PROPERTY_BACKGROUND_COLOR, CSS_TYPE_COLOR, bgcolor); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BACKGROUND_COLOR, + CSS_TYPE_COLOR, bgcolor); } if (a_Html_get_attr (html, tag, tagsize, "align")) { S_TOP(html)->cell_text_align_set = TRUE; - a_Html_tag_set_align_attr (html, &props, tag, tagsize); + a_Html_tag_set_align_attr (html, tag, tagsize); } html->styleEngine->inheritBackgroundColor (); - html->styleEngine->setNonCssHints (&props); ((dw::Table*)S_TOP(html)->table)->addRow (html->styleEngine->style ()); - table_cell_props = new CssPropertyList (*S_TOP(html)->table_cell_props); if (bgcolor != -1) { - table_cell_props->set (CSS_PROPERTY_BACKGROUND_COLOR, - CSS_TYPE_COLOR, bgcolor); + html->styleEngine->setNonCssHint(CSS_PROPERTY_BACKGROUND_COLOR, + CSS_TYPE_COLOR, bgcolor); new_style = true; } - if (a_Html_tag_set_valign_attr (html, tag, tagsize, table_cell_props)) + if (a_Html_tag_set_valign_attr (html, tag, tagsize)) new_style = true; - if (new_style) { - S_TOP(html)->table_cell_props->unref (); - S_TOP(html)->table_cell_props = table_cell_props; - S_TOP(html)->table_cell_props->ref (); - } else { - delete table_cell_props; - } break; default: break; @@ -212,6 +218,96 @@ void Html_tag_open_th(DilloHtml *html, const char *tag, int tagsize) */ /* + * The table border model is stored in the table's stack item + */ +static int Html_table_get_border_model(DilloHtml *html) +{ + static int i_TABLE = -1; + if (i_TABLE == -1) + i_TABLE = a_Html_tag_index("table"); + + int s_idx = html->stack->size(); + while (--s_idx > 0 && html->stack->getRef(s_idx)->tag_idx != i_TABLE) + ; + return html->stack->getRef(s_idx)->table_border_mode; +} + +/* + * Set current table's border model + */ +static void Html_table_set_border_model(DilloHtml *html, + DilloHtmlTableBorderMode mode) +{ + int s_idx = html->stack->size(), i_TABLE = a_Html_tag_index("table"); + + while (--s_idx > 0 && html->stack->getRef(s_idx)->tag_idx != i_TABLE) ; + if (s_idx > 0) + html->stack->getRef(s_idx)->table_border_mode = mode; +} + +/* WORKAROUND: collapsing border model requires moving rendering code from + * the cell to the table, and making table-code aware of each + * cell style. + * This workaround mimics collapsing model within separate model. This is not + * a complete emulation but should be enough for most cases. + */ +static void Html_set_collapsing_border_model(DilloHtml *html, Widget *col_tb) +{ + dw::core::style::Style *collapseStyle, *tableStyle; + dw::core::style::StyleAttrs collapseCellAttrs, collapseTableAttrs; + int borderWidth, marginWidth; + + tableStyle = ((dw::Table*)S_TOP(html)->table)->getStyle (); + borderWidth = html->styleEngine->style ()->borderWidth.top; + marginWidth = tableStyle->margin.top; + + collapseCellAttrs = *(html->styleEngine->style ()); + collapseCellAttrs.margin.setVal (0); + collapseCellAttrs.borderWidth.left = 0; + collapseCellAttrs.borderWidth.top = 0; + collapseCellAttrs.borderWidth.right = borderWidth; + collapseCellAttrs.borderWidth.bottom = borderWidth; + collapseCellAttrs.hBorderSpacing = 0; + collapseCellAttrs.vBorderSpacing = 0; + collapseStyle = Style::create(HT2LT(html), &collapseCellAttrs); + col_tb->setStyle (collapseStyle); + + if (Html_table_get_border_model(html) != DILLO_HTML_TABLE_BORDER_COLLAPSE) { + Html_table_set_border_model(html, DILLO_HTML_TABLE_BORDER_COLLAPSE); + collapseTableAttrs = *tableStyle; + collapseTableAttrs.margin.setVal (marginWidth); + collapseTableAttrs.borderWidth.left = borderWidth; + collapseTableAttrs.borderWidth.top = borderWidth; + collapseTableAttrs.borderWidth.right = 0; + collapseTableAttrs.borderWidth.bottom = 0; + collapseTableAttrs.hBorderSpacing = 0; + collapseTableAttrs.vBorderSpacing = 0; + collapseTableAttrs.borderColor = collapseCellAttrs.borderColor; + collapseTableAttrs.borderStyle = collapseCellAttrs.borderStyle; + /* CSS2 17.6.2: table does not have padding (in collapsing mode) */ + collapseTableAttrs.padding.setVal (0); + collapseStyle = Style::create(HT2LT(html), &collapseTableAttrs); + ((dw::Table*)S_TOP(html)->table)->setStyle (collapseStyle); + } +} + +/* + * Adjust style for separate border model. + * (Dw uses this model internally). + */ +static void Html_set_separate_border_model(DilloHtml *html, Widget *col_tb) +{ + dw::core::style::Style *separateStyle; + dw::core::style::StyleAttrs separateCellAttrs; + + separateCellAttrs = *(html->styleEngine->style ()); + /* CSS2 17.5: Internal table elements do not have margins */ + separateCellAttrs.margin.setVal (0); + separateStyle = Style::create(HT2LT(html), &separateCellAttrs); + col_tb->setStyle (separateStyle); +} + +/* * used by <TD> and <TH> */ static void Html_tag_open_table_cell(DilloHtml *html, @@ -224,6 +320,8 @@ static void Html_tag_open_table_cell(DilloHtml *html, int32_t bgcolor; bool_t new_style; + html->styleEngine->inheritNonCssHints (); + switch (S_TOP(html)->table_mode) { case DILLO_HTML_TABLE_MODE_NONE: BUG_MSG("<td> or <th> outside <table>\n"); @@ -245,41 +343,36 @@ static void Html_tag_open_table_cell(DilloHtml *html, if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "rowspan"))) rowspan = MAX(1, strtol (attrbuf, NULL, 10)); - CssPropertyList *props; - // \todo any shorter way to do this? - if (S_TOP(html)->table_cell_props != NULL) - props = new CssPropertyList (*S_TOP(html)->table_cell_props); - else - props = new CssPropertyList (); - /* text style */ if (!S_TOP(html)->cell_text_align_set) { - props->set (CSS_PROPERTY_TEXT_ALIGN, CSS_TYPE_ENUM, text_align); + html->styleEngine->setNonCssHint (CSS_PROPERTY_TEXT_ALIGN, + CSS_TYPE_ENUM, text_align); } if (a_Html_get_attr(html, tag, tagsize, "nowrap")) - props->set(CSS_PROPERTY_WHITE_SPACE,CSS_TYPE_ENUM,WHITE_SPACE_NOWRAP); + html->styleEngine->setNonCssHint(CSS_PROPERTY_WHITE_SPACE, + CSS_TYPE_ENUM, WHITE_SPACE_NOWRAP); else - props->set(CSS_PROPERTY_WHITE_SPACE,CSS_TYPE_ENUM,WHITE_SPACE_NORMAL); + html->styleEngine->setNonCssHint(CSS_PROPERTY_WHITE_SPACE, + CSS_TYPE_ENUM, WHITE_SPACE_NORMAL); - a_Html_tag_set_align_attr (html, props, tag, tagsize); + a_Html_tag_set_align_attr (html, tag, tagsize); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "width"))) { - props->set (CSS_PROPERTY_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, - a_Html_parse_length (html, attrbuf)); + html->styleEngine->setNonCssHint (CSS_PROPERTY_WIDTH, + CSS_TYPE_LENGTH_PERCENTAGE, + a_Html_parse_length (html, attrbuf)); } - if (a_Html_tag_set_valign_attr (html, tag, tagsize, props)) + if (a_Html_tag_set_valign_attr (html, tag, tagsize)) new_style = TRUE; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) { bgcolor = a_Html_color_parse(html, attrbuf, -1); if (bgcolor != -1) - props->set (CSS_PROPERTY_BACKGROUND_COLOR, CSS_TYPE_COLOR,bgcolor); + html->styleEngine->setNonCssHint (CSS_PROPERTY_BACKGROUND_COLOR, + CSS_TYPE_COLOR, bgcolor); } - html->styleEngine->setNonCssHints (props); - delete props; - if (html->styleEngine->style ()->textAlign == TEXT_ALIGN_STRING) col_tb = new dw::TableCell ( @@ -288,7 +381,11 @@ static void Html_tag_open_table_cell(DilloHtml *html, else col_tb = new Textblock (prefs.limit_text_width); - col_tb->setStyle (html->styleEngine->style ()); + if (html->styleEngine->style()->borderCollapse == BORDER_MODEL_COLLAPSE){ + Html_set_collapsing_border_model(html, col_tb); + } else { + Html_set_separate_border_model(html, col_tb); + } ((dw::Table*)S_TOP(html)->table)->addCell (col_tb, colspan, rowspan); S_TOP(html)->textblock = html->dw = col_tb; diff --git a/src/uicmd.cc b/src/uicmd.cc index 93836735..5573db11 100644 --- a/src/uicmd.cc +++ b/src/uicmd.cc @@ -449,6 +449,8 @@ BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh, // Now create the Dw render layout and viewport FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); + style::Color *bgColor = style::Color::create (layout, prefs.bg_color); + layout->setBgColor (bgColor); FltkViewport *viewport = new FltkViewport (0, 0, 1, 1); if (prefs.buffered_drawing == 1) @@ -507,6 +509,8 @@ static BrowserWindow *UIcmd_tab_new(const void *vbw) // Now create the Dw render layout and viewport FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); + style::Color *bgColor = style::Color::create (layout, prefs.bg_color); + layout->setBgColor (bgColor); FltkViewport *viewport = new FltkViewport (0, 0, 1, 1); @@ -1296,14 +1300,14 @@ void a_UIcmd_fullscreen_toggle(BrowserWindow *bw) * Search for next/previous occurrence of key. */ void a_UIcmd_findtext_search(BrowserWindow *bw, const char *key, - int case_sens, int backwards) + int case_sens, int backward) { Layout *l = (Layout *)bw->render_layout; - switch (l->search(key, case_sens, backwards)) { + switch (l->search(key, case_sens, backward)) { case FindtextState::RESTART: - a_UIcmd_set_msg(bw, "No further occurrences of \"%s\". " - "Restarting from the top.", key); + a_UIcmd_set_msg(bw, backward?"Top reached; restarting from the bottom." + :"Bottom reached; restarting from the top."); break; case FindtextState::NOT_FOUND: a_UIcmd_set_msg(bw, "\"%s\" not found.", key); @@ -1,7 +1,6 @@ /* * File: url.c * - * Copyright (C) 2001 Livio Baldini Soares <livio@linux.ime.usp.br> * Copyright (C) 2001-2009 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify @@ -2,7 +2,6 @@ * File : url.h - Dillo * * Copyright (C) 2001 Jorge Arellano Cid <jcid@dillo.org> - * 2001 Livio Baldini Soares <livio@linux.ime.usp.br> * * Parse and normalize all URL's inside Dillo. */ @@ -61,10 +61,13 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web, if (Web->flags & WEB_RootUrl) { /* We have RootUrl! */ + style::Color *bgColor = style::Color::create (layout, prefs.bg_color); + Web->bgColor = bgColor->getColor (); + layout->setBgColor (bgColor); + /* Set a style for the widget */ StyleEngine styleEngine (layout); styleEngine.startElement ("body"); - Web->bgColor= styleEngine.backgroundStyle()->backgroundColor->getColor(); dw = (Widget*) a_Mime_set_viewer(Type, Web, Call, Data); if (dw == NULL) @@ -89,12 +92,12 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web, } else { /* A non-RootUrl. At this moment we only handle image-children */ - if (!dStrncasecmp(Type, "image/", 6)) + if (!dStrncasecmp(Type, "image/", 6)) { dw = (Widget*) a_Mime_set_viewer(Type, Web, Call, Data); - } - - if (!dw) { - MSG_HTTP("unhandled MIME type: \"%s\"\n", Type); + } else { + MSG_HTTP("'%s' cannot be displayed as image; has media type '%s'\n", + URL_STR(Web->url), Type); + } } return (dw ? 1 : -1); } diff --git a/test/Makefile.am b/test/Makefile.am index 709196f4..c95bad98 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,3 +1,5 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) AM_CFLAGS = @LIBFLTK_CFLAGS@ AM_CXXFLAGS = @LIBFLTK_CXXFLAGS@ @@ -24,26 +26,26 @@ noinst_PROGRAMS = \ dw_anchors_test_SOURCES = dw_anchors_test.cc dw_anchors_test_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_example_SOURCES = dw_example.cc dw_example_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_find_test_SOURCES = dw_find_test.cc dw_find_test_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_float_test_SOURCES = dw_float_test.cc @@ -56,91 +58,91 @@ dw_float_test_LDADD = \ dw_links_SOURCES = dw_links.cc dw_links_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_links2_SOURCES = dw_links2.cc dw_links2_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_images_simple_SOURCES = dw_images_simple.cc dw_images_simple_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_images_scaled_SOURCES = dw_images_scaled.cc dw_images_scaled_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_images_scaled2_SOURCES = dw_images_scaled2.cc dw_images_scaled2_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_lists_SOURCES = dw_lists.cc dw_lists_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_table_aligned_SOURCES = dw_table_aligned.cc dw_table_aligned_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_table_SOURCES = dw_table.cc dw_table_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_border_test_SOURCES = dw_border_test.cc dw_border_test_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_imgbuf_mem_test_SOURCES = dw_imgbuf_mem_test.cc dw_imgbuf_mem_test_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_resource_test_SOURCES = dw_resource_test.cc dw_resource_test_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ dw_ui_test_SOURCES = \ @@ -148,10 +150,10 @@ dw_ui_test_SOURCES = \ form.cc \ form.hh dw_ui_test_LDADD = \ - ../dw/libDw-widgets.a \ - ../dw/libDw-fltk.a \ - ../dw/libDw-core.a \ - ../lout/liblout.a \ + $(top_builddir)/dw/libDw-widgets.a \ + $(top_builddir)/dw/libDw-fltk.a \ + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a \ @LIBFLTK_LIBS@ fltk_browser_SOURCES = fltk_browser.cc @@ -159,10 +161,10 @@ fltk_browser_LDADD = @LIBFLTK_LIBS@ shapes_SOURCES = shapes.cc shapes_LDADD = \ - ../dw/libDw-core.a \ - ../lout/liblout.a + $(top_builddir)/dw/libDw-core.a \ + $(top_builddir)/lout/liblout.a cookies_SOURCES = cookies.c cookies_LDADD = \ - ../dpip/libDpip.a \ - ../dlib/libDlib.a + $(top_builddir)/dpip/libDpip.a \ + $(top_builddir)/dlib/libDlib.a |