summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/libcroco
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/libcroco')
-rw-r--r--src/3rdparty/libcroco/.clang-format16
-rw-r--r--src/3rdparty/libcroco/ABOUT-NLS226
-rw-r--r--src/3rdparty/libcroco/AUTHORS13
-rw-r--r--src/3rdparty/libcroco/CMakeLists.txt33
-rw-r--r--src/3rdparty/libcroco/CODING-STYLE113
-rw-r--r--src/3rdparty/libcroco/COPYING481
-rw-r--r--src/3rdparty/libcroco/COPYING.LIB481
-rw-r--r--src/3rdparty/libcroco/COPYRIGHTS4
-rw-r--r--src/3rdparty/libcroco/Doxyfile946
-rw-r--r--src/3rdparty/libcroco/Makefile.am72
-rw-r--r--src/3rdparty/libcroco/NEWS178
-rw-r--r--src/3rdparty/libcroco/README.md15
-rw-r--r--src/3rdparty/libcroco/TODO45
-rw-r--r--src/3rdparty/libcroco/acinclude.m4319
-rwxr-xr-xsrc/3rdparty/libcroco/autogen.sh37
-rw-r--r--src/3rdparty/libcroco/config.h.win32.in99
-rw-r--r--src/3rdparty/libcroco/configure.ac191
-rw-r--r--src/3rdparty/libcroco/croco-config.137
-rw-r--r--src/3rdparty/libcroco/croco-config.in82
-rw-r--r--src/3rdparty/libcroco/csslint/CMakeLists.txt16
-rw-r--r--src/3rdparty/libcroco/csslint/ChangeLog29
-rw-r--r--src/3rdparty/libcroco/csslint/Makefile.am18
-rw-r--r--src/3rdparty/libcroco/csslint/csslint.164
-rw-r--r--src/3rdparty/libcroco/csslint/csslint.c1011
-rw-r--r--src/3rdparty/libcroco/docs/Makefile.am3
-rw-r--r--src/3rdparty/libcroco/docs/design/parser-architecture.txt146
-rw-r--r--src/3rdparty/libcroco/docs/design/sel-instr.txt64
-rw-r--r--src/3rdparty/libcroco/docs/examples/Makefile.am1
-rw-r--r--src/3rdparty/libcroco/docs/examples/cssom-example-1.c109
-rw-r--r--src/3rdparty/libcroco/docs/examples/sac-example-1.c198
-rw-r--r--src/3rdparty/libcroco/docs/examples/sac-example-2.c349
-rw-r--r--src/3rdparty/libcroco/docs/examples/selection-example-1.c191
-rw-r--r--src/3rdparty/libcroco/docs/examples/selection-example-1.css41
-rw-r--r--src/3rdparty/libcroco/docs/examples/selection-example-1.xml14
-rw-r--r--src/3rdparty/libcroco/docs/reference/Makefile.am53
-rw-r--r--src/3rdparty/libcroco/docs/reference/libcroco-docs.sgml39
-rw-r--r--src/3rdparty/libcroco/docs/release-notes-template.txt41
-rw-r--r--src/3rdparty/libcroco/docs/usage.txt47
-rw-r--r--src/3rdparty/libcroco/global-test-vars.sh.in12
-rwxr-xr-xsrc/3rdparty/libcroco/libcroco-indent102
-rwxr-xr-xsrc/3rdparty/libcroco/libcroco-zip.in25
-rw-r--r--src/3rdparty/libcroco/libcroco.doap30
-rw-r--r--src/3rdparty/libcroco/libcroco.pc.in11
-rw-r--r--src/3rdparty/libcroco/libcroco.spec.in82
-rw-r--r--src/3rdparty/libcroco/src/CMakeLists.txt85
-rw-r--r--src/3rdparty/libcroco/src/Makefile.am136
-rw-r--r--src/3rdparty/libcroco/src/cr-additional-sel.c456
-rw-r--r--src/3rdparty/libcroco/src/cr-additional-sel.h98
-rw-r--r--src/3rdparty/libcroco/src/cr-attr-sel.c221
-rw-r--r--src/3rdparty/libcroco/src/cr-attr-sel.h74
-rw-r--r--src/3rdparty/libcroco/src/cr-cascade.c214
-rw-r--r--src/3rdparty/libcroco/src/cr-cascade.h74
-rw-r--r--src/3rdparty/libcroco/src/cr-declaration.c794
-rw-r--r--src/3rdparty/libcroco/src/cr-declaration.h136
-rw-r--r--src/3rdparty/libcroco/src/cr-doc-handler.c276
-rw-r--r--src/3rdparty/libcroco/src/cr-doc-handler.h298
-rw-r--r--src/3rdparty/libcroco/src/cr-enc-handler.c184
-rw-r--r--src/3rdparty/libcroco/src/cr-enc-handler.h94
-rw-r--r--src/3rdparty/libcroco/src/cr-fonts.c943
-rw-r--r--src/3rdparty/libcroco/src/cr-fonts.h315
-rw-r--r--src/3rdparty/libcroco/src/cr-input.c1181
-rw-r--r--src/3rdparty/libcroco/src/cr-input.h174
-rw-r--r--src/3rdparty/libcroco/src/cr-libxml-node-iface.c81
-rw-r--r--src/3rdparty/libcroco/src/cr-libxml-node-iface.h14
-rw-r--r--src/3rdparty/libcroco/src/cr-node-iface.h34
-rw-r--r--src/3rdparty/libcroco/src/cr-num.c345
-rw-r--r--src/3rdparty/libcroco/src/cr-num.h127
-rw-r--r--src/3rdparty/libcroco/src/cr-om-parser.c1150
-rw-r--r--src/3rdparty/libcroco/src/cr-om-parser.h98
-rw-r--r--src/3rdparty/libcroco/src/cr-parser.c4568
-rw-r--r--src/3rdparty/libcroco/src/cr-parser.h130
-rw-r--r--src/3rdparty/libcroco/src/cr-parsing-location.c172
-rw-r--r--src/3rdparty/libcroco/src/cr-parsing-location.h70
-rw-r--r--src/3rdparty/libcroco/src/cr-prop-list.c404
-rw-r--r--src/3rdparty/libcroco/src/cr-prop-list.h80
-rw-r--r--src/3rdparty/libcroco/src/cr-pseudo.c166
-rw-r--r--src/3rdparty/libcroco/src/cr-pseudo.h66
-rw-r--r--src/3rdparty/libcroco/src/cr-rgb.c686
-rw-r--r--src/3rdparty/libcroco/src/cr-rgb.h94
-rw-r--r--src/3rdparty/libcroco/src/cr-sel-eng.c2236
-rw-r--r--src/3rdparty/libcroco/src/cr-sel-eng.h118
-rw-r--r--src/3rdparty/libcroco/src/cr-selector.c333
-rw-r--r--src/3rdparty/libcroco/src/cr-selector.h95
-rw-r--r--src/3rdparty/libcroco/src/cr-simple-sel.c322
-rw-r--r--src/3rdparty/libcroco/src/cr-simple-sel.h131
-rw-r--r--src/3rdparty/libcroco/src/cr-statement.c2810
-rw-r--r--src/3rdparty/libcroco/src/cr-statement.h440
-rw-r--r--src/3rdparty/libcroco/src/cr-string.c170
-rw-r--r--src/3rdparty/libcroco/src/cr-string.h76
-rw-r--r--src/3rdparty/libcroco/src/cr-style.c2852
-rw-r--r--src/3rdparty/libcroco/src/cr-style.h339
-rw-r--r--src/3rdparty/libcroco/src/cr-stylesheet.c268
-rw-r--r--src/3rdparty/libcroco/src/cr-stylesheet.h117
-rw-r--r--src/3rdparty/libcroco/src/cr-term.c744
-rw-r--r--src/3rdparty/libcroco/src/cr-term.h195
-rw-r--r--src/3rdparty/libcroco/src/cr-tknzr.c2777
-rw-r--r--src/3rdparty/libcroco/src/cr-tknzr.h115
-rw-r--r--src/3rdparty/libcroco/src/cr-token.c636
-rw-r--r--src/3rdparty/libcroco/src/cr-token.h212
-rw-r--r--src/3rdparty/libcroco/src/cr-utils.c1330
-rw-r--r--src/3rdparty/libcroco/src/cr-utils.h245
-rw-r--r--src/3rdparty/libcroco/src/libcroco-config.h.in17
-rw-r--r--src/3rdparty/libcroco/src/libcroco.h44
-rw-r--r--src/3rdparty/libcroco/src/libcroco.symbols538
-rw-r--r--src/3rdparty/libcroco/tests/CMakeLists.txt69
-rw-r--r--src/3rdparty/libcroco/tests/Makefile.am36
-rw-r--r--src/3rdparty/libcroco/tests/README-description.txt125
-rw-r--r--src/3rdparty/libcroco/tests/cr-test-utils.c59
-rw-r--r--src/3rdparty/libcroco/tests/cr-test-utils.h50
-rw-r--r--src/3rdparty/libcroco/tests/global-vars.sh.in10
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-functional-notation.sh5
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/Makefile.am16
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/functional-notation.css2
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/lots-of-comments.css198
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/parsing-location.css26
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/prop-vendor-ident.css3
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/sel-child-class.css1
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/sel-child-class.xml10
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/several-media.css10
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test0.1.css258
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test1.css316
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test2.1.css47
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test2.2.css686
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test2.css9
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test3.1.css36
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test3.2.css693
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test3.css9
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test4.1.css682
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test4.2.css24
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test5.1.css14
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule.css3
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule2.css3
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-lots-of-comments.sh5
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/Makefile.am16
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-functional-notation.out7
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-lots-of-comments.out26
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-parsing-location.out219
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-prop-ident.out3
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-sel-child-class.out4
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-several-media.out17
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule.out1
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule2.out2
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test0.1.css.out1
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test1.css.out316
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test2.1.css.out173
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test2.2.css.out3328
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test2.css.out63
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test3.1.css.out0
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test3.2.css.out0
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test3.css.out0
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test4.1.css.out766
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test4.2.css.out24
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test5.1.css.out105
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test6.out8
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test7.out43
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test8.out15
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-parsing-location.sh5
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-prop-ident.sh5
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-sel-child-class.sh5
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-several-media.sh5
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-unknown-at-rule.sh5
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-unknown-at-rule2.sh5
-rw-r--r--src/3rdparty/libcroco/tests/test0-main.c203
-rw-r--r--src/3rdparty/libcroco/tests/test1-main.c197
-rw-r--r--src/3rdparty/libcroco/tests/test2-main.c564
-rw-r--r--src/3rdparty/libcroco/tests/test3-main.c545
-rw-r--r--src/3rdparty/libcroco/tests/test4-main.c435
-rw-r--r--src/3rdparty/libcroco/tests/test5-main.c255
-rw-r--r--src/3rdparty/libcroco/tests/test6-main.c84
-rw-r--r--src/3rdparty/libcroco/tests/test7-main.c95
-rw-r--r--src/3rdparty/libcroco/tests/test8-main.c44
-rwxr-xr-xsrc/3rdparty/libcroco/tests/testctl462
-rwxr-xr-xsrc/3rdparty/libcroco/tests/valgrind-version.sh48
-rw-r--r--src/3rdparty/libcroco/tests/valgrind.log0
-rwxr-xr-xsrc/3rdparty/libcroco/tests/vg24
-rw-r--r--src/3rdparty/libcroco/tests/vg.supp57
-rw-r--r--src/3rdparty/libcroco/win32/Makefile-newvs.am55
-rw-r--r--src/3rdparty/libcroco/win32/Makefile.am22
-rw-r--r--src/3rdparty/libcroco/win32/Makefile.msvcproj153
-rw-r--r--src/3rdparty/libcroco/win32/crocopc.py33
-rw-r--r--src/3rdparty/libcroco/win32/pc_base.py124
-rw-r--r--src/3rdparty/libcroco/win32/replace.py115
-rw-r--r--src/3rdparty/libcroco/win32/vs10/Makefile.am48
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-build-defines.props48
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-gen-srcs.props44
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-install.propsin62
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj134
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj.filters29
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-version-paths.props.in89
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco.vcxproj.filtersin43
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco.vcxprojin222
-rw-r--r--src/3rdparty/libcroco/win32/vs10/csslint.vcxproj194
-rw-r--r--src/3rdparty/libcroco/win32/vs10/csslint.vcxproj.filters33
-rw-r--r--src/3rdparty/libcroco/win32/vs10/libcroco.sln46
-rw-r--r--src/3rdparty/libcroco/win32/vs11/Makefile.am39
-rw-r--r--src/3rdparty/libcroco/win32/vs12/Makefile.am39
-rw-r--r--src/3rdparty/libcroco/win32/vs14/Makefile.am39
-rw-r--r--src/3rdparty/libcroco/win32/vs15/Makefile.am40
-rw-r--r--src/3rdparty/libcroco/win32/vs16/Makefile.am40
-rw-r--r--src/3rdparty/libcroco/win32/vs9/Makefile.am39
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco-build-defines.vsprops41
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco-gen-srcs.vsprops38
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco-install.vcproj137
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco-install.vspropsin51
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco-version-paths.vsprops.in88
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco.vcprojin273
-rw-r--r--src/3rdparty/libcroco/win32/vs9/csslint.vcproj189
-rw-r--r--src/3rdparty/libcroco/win32/vs9/libcroco.sln53
208 files changed, 51467 insertions, 0 deletions
diff --git a/src/3rdparty/libcroco/.clang-format b/src/3rdparty/libcroco/.clang-format
new file mode 100644
index 0000000..7612e59
--- /dev/null
+++ b/src/3rdparty/libcroco/.clang-format
@@ -0,0 +1,16 @@
+BasedOnStyle: LLVM
+
+AlwaysBreakAfterDefinitionReturnType: All
+BreakBeforeBinaryOperators: NonAssignment
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterEnum: true
+ AfterCaseLabel: true
+ AfterStruct: true
+ AfterFunction: true
+
+BinPackParameters: false
+ColumnLimit: 80
+IndentWidth: 8
+SpaceAfterCStyleCast: true
+SpaceBeforeParens: Always
diff --git a/src/3rdparty/libcroco/ABOUT-NLS b/src/3rdparty/libcroco/ABOUT-NLS
new file mode 100644
index 0000000..28d38c7
--- /dev/null
+++ b/src/3rdparty/libcroco/ABOUT-NLS
@@ -0,0 +1,226 @@
+Notes on the Free Translation Project
+*************************************
+
+ Free software is going international! The Free Translation Project
+is a way to get maintainers of free software, translators, and users all
+together, so that will gradually become able to speak many languages.
+A few packages already provide translations for their messages.
+
+ If you found this `ABOUT-NLS' file inside a distribution, you may
+assume that the distributed package does use GNU `gettext' internally,
+itself available at your nearest GNU archive site. But you do *not*
+need to install GNU `gettext' prior to configuring, installing or using
+this package with messages translated.
+
+ Installers will find here some useful hints. These notes also
+explain how users should proceed for getting the programs to use the
+available translations. They tell how people wanting to contribute and
+work at translations should contact the appropriate team.
+
+ When reporting bugs in the `intl/' directory or bugs which may be
+related to internationalization, you should tell about the version of
+`gettext' which is used. The information can be found in the
+`intl/VERSION' file, in internationalized packages.
+
+One advise in advance
+=====================
+
+ If you want to exploit the full power of internationalization, you
+should configure it using
+
+ ./configure --with-included-gettext
+
+to force usage of internationalizing routines provided within this
+package, despite the existence of internationalizing capabilities in the
+operating system where this package is being installed. So far, only
+the `gettext' implementation in the GNU C library version 2 provides as
+many features (such as locale alias or message inheritance) as the
+implementation here. It is also not possible to offer this additional
+functionality on top of a `catgets' implementation. Future versions of
+GNU `gettext' will very likely convey even more functionality. So it
+might be a good idea to change to GNU `gettext' as soon as possible.
+
+ So you need not provide this option if you are using GNU libc 2 or
+you have installed a recent copy of the GNU gettext package with the
+included `libintl'.
+
+INSTALL Matters
+===============
+
+ Some packages are "localizable" when properly installed; the
+programs they contain can be made to speak your own native language.
+Most such packages use GNU `gettext'. Other packages have their own
+ways to internationalization, predating GNU `gettext'.
+
+ By default, this package will be installed to allow translation of
+messages. It will automatically detect whether the system provides
+usable `catgets' (if using this is selected by the installer) or
+`gettext' functions. If neither is available, the GNU `gettext' own
+library will be used. This library is wholly contained within this
+package, usually in the `intl/' subdirectory, so prior installation of
+the GNU `gettext' package is *not* required. Installers may use
+special options at configuration time for changing the default
+behaviour. The commands:
+
+ ./configure --with-included-gettext
+ ./configure --with-catgets
+ ./configure --disable-nls
+
+will respectively bypass any pre-existing `catgets' or `gettext' to use
+the internationalizing routines provided within this package, enable
+the use of the `catgets' functions (if found on the locale system), or
+else, *totally* disable translation of messages.
+
+ When you already have GNU `gettext' installed on your system and run
+configure without an option for your new package, `configure' will
+probably detect the previously built and installed `libintl.a' file and
+will decide to use this. This might be not what is desirable. You
+should use the more recent version of the GNU `gettext' library. I.e.
+if the file `intl/VERSION' shows that the library which comes with this
+package is more recent, you should use
+
+ ./configure --with-included-gettext
+
+to prevent auto-detection.
+
+ By default the configuration process will not test for the `catgets'
+function and therefore they will not be used. The reasons are already
+given above: the emulation on top of `catgets' cannot provide all the
+extensions provided by the GNU `gettext' library. If you nevertheless
+want to use the `catgets' functions use
+
+ ./configure --with-catgets
+
+to enable the test for `catgets' (this causes no harm if `catgets' is
+not available on your system). If you really select this option we
+would like to hear about the reasons because we cannot think of any
+good one ourself.
+
+ Internationalized packages have usually many `po/LL.po' files, where
+LL gives an ISO 639 two-letter code identifying the language. Unless
+translations have been forbidden at `configure' time by using the
+`--disable-nls' switch, all available translations are installed
+together with the package. However, the environment variable `LINGUAS'
+may be set, prior to configuration, to limit the installed set.
+`LINGUAS' should then contain a space separated list of two-letter
+codes, stating which languages are allowed.
+
+Using This Package
+==================
+
+ As a user, if your language has been installed for this package, you
+only have to set the `LANG' environment variable to the appropriate
+ISO 639 `LL' two-letter code prior to using the programs in the
+package. For example, let's suppose that you speak German. At the
+shell prompt, merely execute `setenv LANG de' (in `csh'),
+`export LANG; LANG=de' (in `sh') or `export LANG=de' (in `bash'). This
+can be done from your `.login' or `.profile' file, once and for all.
+
+ An operating system might already offer message localization for
+many of its programs, while other programs have been installed locally
+with the full capabilities of GNU `gettext'. Just using `gettext'
+extended syntax for `LANG' would break proper localization of already
+available operating system programs. In this case, users should set
+both `LANGUAGE' and `LANG' variables in their environment, as programs
+using GNU `gettext' give preference to `LANGUAGE'. For example, some
+Swedish users would rather read translations in German than English for
+when Swedish is not available. This is easily accomplished by setting
+`LANGUAGE' to `sv:de' while leaving `LANG' to `sv'.
+
+Translating Teams
+=================
+
+ For the Free Translation Project to be a success, we need interested
+people who like their own language and write it well, and who are also
+able to synergize with other translators speaking the same language.
+Each translation team has its own mailing list, courtesy of Linux
+International. You may reach your translation team at the address
+`LL@li.org', replacing LL by the two-letter ISO 639 code for your
+language. Language codes are *not* the same as the country codes given
+in ISO 3166. The following translation teams exist, as of December
+1997:
+
+ Chinese `zh', Czech `cs', Danish `da', Dutch `nl', English `en',
+ Esperanto `eo', Finnish `fi', French `fr', German `de', Hungarian
+ `hu', Irish `ga', Italian `it', Indonesian `id', Japanese `ja',
+ Korean `ko', Latin `la', Norwegian `no', Persian `fa', Polish
+ `pl', Portuguese `pt', Russian `ru', Slovenian `sl', Spanish `es',
+ Swedish `sv', and Turkish `tr'.
+
+For example, you may reach the Chinese translation team by writing to
+`zh@li.org'.
+
+ If you'd like to volunteer to *work* at translating messages, you
+should become a member of the translating team for your own language.
+The subscribing address is *not* the same as the list itself, it has
+`-request' appended. For example, speakers of Swedish can send a
+message to `sv-request@li.org', having this message body:
+
+ subscribe
+
+ Keep in mind that team members are expected to participate
+*actively* in translations, or at solving translational difficulties,
+rather than merely lurking around. If your team does not exist yet and
+you want to start one, or if you are unsure about what to do or how to
+get started, please write to `translation@iro.umontreal.ca' to reach the
+coordinator for all translator teams.
+
+ The English team is special. It works at improving and uniformizing
+the terminology in use. Proven linguistic skill are praised more than
+programming skill, here.
+
+Available Packages
+==================
+
+ Languages are not equally supported in all packages. The following
+matrix shows the current state of internationalization, as of December
+1997. The matrix shows, in regard of each package, for which languages
+PO files have been submitted to translation coordination.
+
+ Ready PO files cs da de en es fi fr it ja ko nl no pl pt ru sl sv
+ .----------------------------------------------------.
+ bash | [] [] [] | 3
+ bison | [] [] [] | 3
+ clisp | [] [] [] [] | 4
+ cpio | [] [] [] [] [] [] | 6
+ diffutils | [] [] [] [] [] | 5
+ enscript | [] [] [] [] [] [] | 6
+ fileutils | [] [] [] [] [] [] [] [] [] [] | 10
+ findutils | [] [] [] [] [] [] [] [] [] | 9
+ flex | [] [] [] [] | 4
+ gcal | [] [] [] [] [] | 5
+ gettext | [] [] [] [] [] [] [] [] [] [] [] | 12
+ grep | [] [] [] [] [] [] [] [] [] [] | 10
+ hello | [] [] [] [] [] [] [] [] [] [] [] | 11
+ id-utils | [] [] [] | 3
+ indent | [] [] [] [] [] | 5
+ libc | [] [] [] [] [] [] [] | 7
+ m4 | [] [] [] [] [] [] | 6
+ make | [] [] [] [] [] [] | 6
+ music | [] [] | 2
+ ptx | [] [] [] [] [] [] [] [] | 8
+ recode | [] [] [] [] [] [] [] [] [] | 9
+ sh-utils | [] [] [] [] [] [] [] [] | 8
+ sharutils | [] [] [] [] [] [] | 6
+ tar | [] [] [] [] [] [] [] [] [] [] [] | 11
+ texinfo | [] [] [] | 3
+ textutils | [] [] [] [] [] [] [] [] [] | 9
+ wdiff | [] [] [] [] [] [] [] [] | 8
+ `----------------------------------------------------'
+ 17 languages cs da de en es fi fr it ja ko nl no pl pt ru sl sv
+ 27 packages 6 4 25 1 18 1 26 2 1 12 20 9 19 7 4 7 17 179
+
+ Some counters in the preceding matrix are higher than the number of
+visible blocks let us expect. This is because a few extra PO files are
+used for implementing regional variants of languages, or language
+dialects.
+
+ For a PO file in the matrix above to be effective, the package to
+which it applies should also have been internationalized and
+distributed as such by its maintainer. There might be an observable
+lag between the mere existence a PO file and its wide availability in a
+distribution.
+
+ If December 1997 seems to be old, you may fetch a more recent copy
+of this `ABOUT-NLS' file on most GNU archive sites.
+
diff --git a/src/3rdparty/libcroco/AUTHORS b/src/3rdparty/libcroco/AUTHORS
new file mode 100644
index 0000000..75562c3
--- /dev/null
+++ b/src/3rdparty/libcroco/AUTHORS
@@ -0,0 +1,13 @@
+Dodji Seketeli <dodji@gnome.org>
+-----------------------------------
+Initial Author, main maintainer and main architect.
+
+Gael Chamoulaud <strider@gnome.org>
+##########################################
+Programmer.
+
+Rob BUIS <rwlbuis@xs4all.nl>
+----------------------------
+Sent several patches.
+
+
diff --git a/src/3rdparty/libcroco/CMakeLists.txt b/src/3rdparty/libcroco/CMakeLists.txt
new file mode 100644
index 0000000..d3e0366
--- /dev/null
+++ b/src/3rdparty/libcroco/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.6)
+
+project(libcroco LANGUAGES C)
+
+if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ set(LIBCROCO_STANDALONE TRUE)
+endif()
+
+set(LIBCROCO_MAJOR_VERSION 0)
+set(LIBCROCO_MINOR_VERSION 6)
+set(LIBCROCO_MICRO_VERSION 99)
+set(LIBCROCO_VERSION ${LIBCROCO_MAJOR_VERSION}.${LIBCROCO_MINOR_VERSION}.${LIBCROCO_MICRO_VERSION})
+math(EXPR LIBCROCO_VERSION_NUMBER "${LIBCROCO_MAJOR_VERSION} * 10000 +
+ ${LIBCROCO_MINOR_VERSION} * 100 +
+ ${LIBCROCO_MICRO_VERSION}")
+
+find_package(PkgConfig REQUIRED)
+
+set(GLIB_REQUIRED 2.0)
+set(LIBXML_REQUIRED 2.4.23)
+
+pkg_check_modules(GLIB REQUIRED glib-2.0>=${GLIB_REQUIRED})
+pkg_check_modules(LIBXML REQUIRED libxml-2.0>=${LIBXML_REQUIRED})
+
+add_subdirectory(src)
+
+option(LIBCROCO_TESTING "Build tests" "${LIBCROCO_STANDALONE}")
+
+if (LIBCROCO_TESTING)
+ enable_testing()
+ add_subdirectory(csslint)
+ add_subdirectory(tests)
+endif()
diff --git a/src/3rdparty/libcroco/CODING-STYLE b/src/3rdparty/libcroco/CODING-STYLE
new file mode 100644
index 0000000..1e76519
--- /dev/null
+++ b/src/3rdparty/libcroco/CODING-STYLE
@@ -0,0 +1,113 @@
+Author: Dodji Seketeli.
+-----------------------
+
+Introduction
+------------
+
+The coding standard we use are based on the GNU coding standards
+available at http://www.gnu.org/prep/standards_toc.html
+and on the Gnome Coding standards available at
+http://developer.gnome.org/doc/guides/programming-guidelines/book1.html .
+
+Please, make sure you read these documents before you read this one.
+
+I) General coding style rules
+---------------------------
+
+Coding style refers to the way the code is formatted.
+Here are the guidelines we use in this project:
+
+Indentation Style
+- - - - - - - - - -
+
+We use the 2-spaces tab indentation style (the GNU's one) .
+
+Make sure as much as possible that each code line does not
+exceed 80 characters length. Why ? because you don't know
+who will read your code. The smallest screens are 80 chars
+wide. So, please, make the code available to everybody.
+
+
+Functions naming
+- - - - - - - -
+
+We use the GNU name scheme to name our functions.
+
+GOOD:
+
+int
+my_function_name (char a_variable_name)
+{
+ printf ("The variable value is %c", a_variable_name) ;
+ return 0 ;
+}
+
+
+BAD:
+
+int
+myFunctionName (char blabla)
+{
+ printf ("This is awfull\n") ;
+}
+
+or
+
+int my_FunctionName (char Blabla) {
+ printf ("This is bad\n") ;
+}
+
+The words of the function names are separared by an underscore ('_') and
+are written in lower case.
+The name functions arguments always start with by a "a_" .
+
+Avoid for instance the Java function (method) name scheme by mixing
+upper and lower case in the function names.
+
+
+Be genereous with white spaces:
+
+GOOD:
+
+int foo (int a_parameter)
+{
+ if (test == TRUE) {
+ printf ("Coucou\n") ;
+ }
+}
+
+BAD:
+
+int foo(int a_parameter)
+{
+ if(test==TRUE) {
+ printf("coucou\n")
+ }
+}
+
+
+To ensure that the each line of code is less than 80 characters,
+if a function has many parameters, you can write it this way:
+
+
+Constants naming
+- - - - - - - - -
+Constants (defines or constant variables) must be in upper case.
+The worlds of the constant name must be separated by an underscore ('_').
+For instance:
+
+GOOD:
+gint A_CONSTANT = 10 ;
+#define ANOTHER_CONSTANT 100 ;
+
+BAD:
+gin a_Constant = 10 ;
+#define another_Constant ;
+
+
+structure and enum naming
+---------------------
+
+
+II) Object Oriented C programming
+-----------------------------
diff --git a/src/3rdparty/libcroco/COPYING b/src/3rdparty/libcroco/COPYING
new file mode 100644
index 0000000..eb685a5
--- /dev/null
+++ b/src/3rdparty/libcroco/COPYING
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/src/3rdparty/libcroco/COPYING.LIB b/src/3rdparty/libcroco/COPYING.LIB
new file mode 100644
index 0000000..eb685a5
--- /dev/null
+++ b/src/3rdparty/libcroco/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/src/3rdparty/libcroco/COPYRIGHTS b/src/3rdparty/libcroco/COPYRIGHTS
new file mode 100644
index 0000000..fa33102
--- /dev/null
+++ b/src/3rdparty/libcroco/COPYRIGHTS
@@ -0,0 +1,4 @@
+Except where otherwise noted in the source code all the files are:
+
+ Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
+
diff --git a/src/3rdparty/libcroco/Doxyfile b/src/3rdparty/libcroco/Doxyfile
new file mode 100644
index 0000000..0c210a3
--- /dev/null
+++ b/src/3rdparty/libcroco/Doxyfile
@@ -0,0 +1,946 @@
+# Doxyfile 1.2.16
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = Libcroco
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = docs/apis
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Korean,
+# Norwegian, Polish, Portuguese, Romanian, Russian, Slovak, Slovene,
+# Spanish, Swedish and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these class will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH =
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower case letters. If set to YES upper case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consist of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = src
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl
+
+FILE_PATTERNS = *.c *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse.
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the Html help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+,
+# or Internet explorer 4.0+). Note that for large projects the tree generation
+# can take a very long time. In such cases it is better to disable this feature.
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_XML = NO
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line and do not end with a semicolon. Such function macros are typically
+# used for boiler-plate code, and will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yield more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermedate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+CGI_NAME = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for
+# details.
+
+CGI_URL =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+DOC_ABSPATH =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+BIN_ABSPATH = /usr/local/bin/
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS =
diff --git a/src/3rdparty/libcroco/Makefile.am b/src/3rdparty/libcroco/Makefile.am
new file mode 100644
index 0000000..4b482f3
--- /dev/null
+++ b/src/3rdparty/libcroco/Makefile.am
@@ -0,0 +1,72 @@
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
+
+SUBDIRS = src csslint docs tests win32
+
+PKG_CONFIG_FILE_UNINSTALLED=libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-uninstalled.pc
+PKG_CONFIG_FILE=libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@.pc
+
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_DATA=$(PKG_CONFIG_FILE)
+
+INCLUDE_DIR_NAME=@PACKAGE@-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
+extraincludedir=$(includedir)/$INCLUDE_DIR_NAME
+
+CROCO_CONFIG_FILE_UNINSTALLED=croco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-config-uninstalled
+CROCO_CONFIG_FILE=croco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-config
+bin_SCRIPTS=$(CROCO_CONFIG_FILE)
+
+#man_MANS = croco-config.1
+
+EXTRA_DIST= croco-config.in $(PKG_CONFIG_FILE) TODO Doxyfile \
+HACKING COPYING.LIB COPYING libcroco.spec libcroco-zip.in \
+autogen.sh libcroco.doap config.h.win32.in config.h.win32
+
+all-local: $(PKG_CONFIG_FILE_UNINSTALLED) $(PKG_CONFIG_FILE) \
+$(CROCO_CONFIG_FILE_UNINSTALLED) $(CROCO_CONFIG_FILE)
+
+
+%-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@.pc: %.pc
+ cp $< $@
+
+%-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-uninstalled.pc: %.pc
+ cp $< $@
+
+%-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-config: %-config
+ cp $< $@
+
+%-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-config-uninstalled: %-config
+ cp $< $@
+
+clean-local: cleantest
+distclean-local:
+ -rm ./croco-0.6-config ./libcroco-0.6.pc ./libcroco-0.6-uninstalled.pc ./croco-0.6-config-uninstalled
+
+cleantest:
+ if test -x $(top_srcdir)/tests/testctl ; then $(top_srcdir)/tests/testctl cleanup ; fi
+
+cleantar:
+ @(rm -f libcroco*.tar.gz)
+ @(rm -rf $(top_srcdir)/rpmbuildroot)
+
+rpm: cleantar
+ @(mkdir -p $(top_srcdir)/rpmbuildroot ; $(MAKE) dist && rpmbuild -ta --buildroot $(top_srcdir)/rpmbuildroot $(distdir).tar.gz)
+
+test: all
+ if test -x $(top_srcdir)/tests/testctl ; then $(top_srcdir)/tests/testctl cleanup ; $(top_srcdir)/tests/testctl run ; fi
+
+apidoc:
+ if ! test -d docs/apis ; then mkdir -p docs/apis ; fi ;
+ doxygen Doxyfile
+
+ChangeLog:
+ $(AM_V_GEN) if test -f $(top_srcdir)/.git/HEAD; then \
+ git log --stat > $@; \
+ fi
+
+dist: ChangeLog
+
+.PHONY: ChangeLog
+
+
diff --git a/src/3rdparty/libcroco/NEWS b/src/3rdparty/libcroco/NEWS
new file mode 100644
index 0000000..a74ee44
--- /dev/null
+++ b/src/3rdparty/libcroco/NEWS
@@ -0,0 +1,178 @@
+0.6.99
+ * Apply inkscape modifications
+ * Consider significant digits for number formatting
+ * Use single instead of double quotes for string output
+ * cr_cascade_set_sheet: Allow a_sheet=NULL
+ * cr_stylesheet_new: Fix reference counting
+ * Mem leak fixes
+
+0.6.13
+ * Visual Studio builds: Enhance security of x64 binaries
+ * win32/replace.py: Fix replacing items in files with UTF-8 content
+ * tknzr: support only max long rgb values
+ * input: check end of input before reading a byte
+
+0.6.12
+ * Add support for Visual Studio 2017 (Chun-wei Fan)
+ * Misc bug fixes
+
+0.6.11
+ * Fix regression in cr_tknzr_consume_chars (Florian Müllner)
+ * Misc bug fixes
+
+0.6.10
+ * Misc bug fixes
+
+0.6.9
+ * Added Visual Studio projects (Chun-wei Fan)
+ * Lots of warnings fixed (Руслан Ижбулатов)
+ * Improve build system (Nuno Araujo, Ignacio Casal Quinteiro)
+ * Misc bug fixes
+
+0.6.8
+ * Handle signed units (Jasper St. Pierre, #686239)
+
+0.6.6.6
+ * Fix 'green' colour (#685679)
+ * Build fixes
+
+0.6.6
+ * Mem leak fixes (#678736)
+
+0.6.5
+
+ Changes & Bugfixes since 0.6.4
+ ==============================
+ * Fix mapping of 'green' colour (#672332)
+
+0.6.4
+
+ Changes & Bugfixes since 0.6.3
+ ==============================
+ * Use -Bsymbolic-functions when available
+ * Modernise and simplify configure
+ * #666248: vc++ compilation support
+ * #640897: fix format string warning in testcase
+
+0.6.3:
+
+ Bugfixes since 0.6.2
+ ====================
+ - #342370: ensure the library and compiler flags are not hardcoded into the pc file
+ - add gtk-doc build infrastructure
+
+0.6.2: February 4, 2009
+
+ Bugfixes since 0.6.1
+ ====================
+
+ - #306823: improve precision of non-integer numbers [Peter Moulder]
+ - #148790, #333834: Cygwin fixes
+ - #340298: Documentation fixes [Peter Moulder]
+ - #375194: fix to builtin color processing [Dom Lachowicz]
+ - #380438: Leak and trace message in cr_token_clear [Mark Rogers]
+ - #381040: floating numbers always output to exactly 3 digits after
+ decimal points [Dom Lachowicz]
+ - #336621: cr_tknzr_get_next_token wasn't handling "<!--" correctly
+ - #372011: comments not parsed correctly [Benjamin Dauvergne]
+ - #394680: problem parsing function name starting with 'u' or 'r'
+ [Benjamin Dauvergne]
+ - #139878: keep end of ruleset parsing location, and give it to the
+ end_selector sac-handler. [Benjamin Dauvergne]
+ - #394294: Escape are wrongly computed [Benjamin Dauvergne]
+ - #314831: Escapes not recognized [Benjamin Dauvergne]
+ - #395099: overly aggressive rule matching [Bruno Haible]
+ - #553937: CRDocHandler instances created with reference count of 0
+ [Robert Staudinger]
+
+ - Various fixes to the font handling [Bruno Haible]
+ - Add ‘const’ to various function prototypes [Peter Moulder]
+
+
+0.6.1: March 5, 2006
+
+ Bugfixes since 0.6.0
+ ====================
+
+ - parse fractional parts of numbers properly [Dom Lachowicz]
+ - win32 port [Tor Lillqvist]
+ - gtk-doc compliance [Sven Herzberg]
+ - test infrastructure enhancements [Peter Moulder]
+ - nasty memory management bug fix [ArjanV, Daniel Veillard]
+
+0.6.0: June 9, 2004
+
+ Enhancements since 0.5.1
+ ========================
+
+ - add parsing location to all the CSS constructions at SAC level [Dodji Seketeli]
+ - add --dump-location option to csslint [Dodji Seketeli]
+ - enable several API/ABI incompatible versions of Libcroco to be
+ installed on the same box [Dodji Seketeli]
+ - CSS properties inheritance support [Benjamin Dauvergne]
+ - CRStyle struct gatehering code cleanup [Benjamin Dauvergne]
+ - Better support for font selection [Dodji Seketeli]
+
+ Bugfixes since 0.5.1
+ ======================
+
+ - #143308: fix parsing of non trivial functional #notations. [Dodji Seketeli]
+ - #143450: fix gcc 2.xx errors. [Dodji Seketeli]
+ - #139881: proper setting of parsing locations in urls. [Dodji Seketeli]
+ - #138267: remove C99-isms.
+ - #139889: fix an infinite loop in the parser [Dodji Seketeli]
+ - #139891: better @media rule reporting [Dodji Seketeli]
+ - #140317: fix class sel without class name crash [Dodji Seketeli]
+ - #140334: fix an infinite loop in the parser [Dodji Seketeli]
+ - attribute selectors evaluation fixes. [Dodji Seketeli]
+ - Better support of descendant selectors evaluation [Dodji Seketeli]
+ - Better regression tests framework [Dodji Seketeli]
+
+0.5.1: April 18 2004:
+
+ - fixes: #140334, #140317, #139891, #139615. [Dodji Seketeli]
+
+0.5: March 16 2004:
+
+ - better regression suite framework [Dodji Seketeli]
+ - support of the 'color' property gathering [Benjamin Dauvergne]
+ - furious memory leaks/corruptions hunting [Dodji Seketeli, Rob BUIS]
+ - total support of the !important keyword [Dodji Seketeli, Rob BUIS]
+ - selectors evaluation in csslint [Dodji Seketeli, Rob BUIS]
+ - fix compilation warnings [David A Knight, Dodji Seketeli]
+ - more complete CSS statement serialisation [Dodji Seketeli]
+ - better gathering of style information [Dodjij Seketeli]
+ - better cascading algorithm conformance [Dodji Seketeli, Rob BUIS]
+ - @import rule parsing fix [Dodji Seketeli]
+ - support of CSS3 indentifiers [Dodji Seketeli]
+ - better w3c DOM integration support [Rob BUIS, Dodji Seketeli]
+ - many parsing fixes [Dodji Seketeli]
+ - style structure debugging facility [Dodji Seketeli]
+ - better fragment parsing support [Dodji Seketeli]
+ - Split libcroco and sewfox [Dodji Seketeli]
+ - class selector evaluation fix [Rob BUIS]
+ - csslint cleanup and bugfixes [Dodji Seketeli]
+ - :first-child pseudo class selector support [Dodji Seketeli]
+ - pluggable pseudo class selectors evaluators [Dodji Seketeli]
+
+
+libcroco 0.2.0
+ 2003 Jun 29
+ libcroco 0.2.0 ChangeLog:
+ * Went forward in the layout engine. Can now render
+ simple xml element along with simple CSS sheets.
+ Supported layout is normal layout for box and inline
+ context.
+ * Cleaned up the parsing api. Fixed a lot of bugs.
+ * Added some new api calls to the parsing api.
+ * See the ChangeLog shipped within the tarball for
+ more precise descriptions.
+
+libcroco 0.1.0
+
+ 2003 Mar 19
+ With the approval off all contributors the library has been
+ relicensed from GPL -> LGPL
+
+------------------------------------------------------------------------------
+
diff --git a/src/3rdparty/libcroco/README.md b/src/3rdparty/libcroco/README.md
new file mode 100644
index 0000000..d7aa48e
--- /dev/null
+++ b/src/3rdparty/libcroco/README.md
@@ -0,0 +1,15 @@
+[![build status](https://gitlab.com/inkscape/libcroco/badges/master/pipeline.svg)](https://gitlab.com/inkscape/libcroco/-/pipelines)
+
+What is The Croco Project ?
+------------------------------
+
+Libcroco is a standalone css2 parsing and manipulation library.
+The parser provides a low level event driven SAC like api
+and a css object model like api.
+Libcroco provides a CSS2 selection engine and an experimental
+xml/css rendering engine.
+
+This is a fork of the original
+[Gnome libcroco](https://gitlab.gnome.org/Archive/libcroco)
+project, which was discontinued. It's sole purpose is to be used with
+[Inkscape](https://gitlab.com/inkscape/inkscape). \ No newline at end of file
diff --git a/src/3rdparty/libcroco/TODO b/src/3rdparty/libcroco/TODO
new file mode 100644
index 0000000..d0062d6
--- /dev/null
+++ b/src/3rdparty/libcroco/TODO
@@ -0,0 +1,45 @@
+
+*coding:)
+
+
+
+Well, in the cr_statement_xxx_parse_functions, memleaks
+occur (the parsing result set in the sac callback is not freed)
+when a parsing fails. This is because the unrecoverable error
+does not get called when the standalone parsing functions exported
+by CRParser are called independently.
+I have now to support 2 modes of parsing. Normal and standalone.
+In standalone mode, the standalone parsing functions must
+call the "unrecoverable_error" sac callback when they fail.
+
+implements the width:20% case. (on going)
+ implement the size wrapping using the rightmost_x field of CRLayEngPriv.
+
+Provide support for font selection. (hard, started, is well underway.)
+ First make sure to be able to gather all the font related property
+ values.
+ Then, figure out how to implement a font selector that uses
+ pango. (on going)
+
+Go forward in the cascading implementation in cr-sel-eng.c
+ test/debug it.
+ write test cases to test/debug/validate this kind of stylesheets:
+ P {border: thick}
+ P {display: block}
+ /*
+ *stylesheets where the same selector is used several times
+ *to define different declarations.
+ */
+ write test cases to test/debug/validate the multi stylesheet support.
+
+
+*Doc:)
+
+Write examples of how to use the SAC api of libcroco and how to
+walk the css stylesheet tree.
+
+Finish the design of the instruction set of the selection engine.
+ The draft design is in the file
+ docs/designs/docs/design/sel-instr.txt.
+
+Write a little doc about how to use the parser as it is today.
diff --git a/src/3rdparty/libcroco/acinclude.m4 b/src/3rdparty/libcroco/acinclude.m4
new file mode 100644
index 0000000..cc65b75
--- /dev/null
+++ b/src/3rdparty/libcroco/acinclude.m4
@@ -0,0 +1,319 @@
+dnl Macros to check the presence of generic (non-typed) symbols.
+dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes@gmail.com>
+dnl Copyright (c) 2006-2008 xine project
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+dnl 02110-1301, USA.
+dnl
+dnl As a special exception, the copyright owners of the
+dnl macro gives unlimited permission to copy, distribute and modify the
+dnl configure scripts that are the output of Autoconf when processing the
+dnl Macro. You need not follow the terms of the GNU General Public
+dnl License when using or distributing such scripts, even though portions
+dnl of the text of the Macro appear in them. The GNU General Public
+dnl License (GPL) does govern all other use of the material that
+dnl constitutes the Autoconf Macro.
+dnl
+dnl This special exception to the GPL applies to versions of the
+dnl Autoconf Macro released by this project. When you make and
+dnl distribute a modified version of the Autoconf Macro, you may extend
+dnl this special exception to the GPL to apply to your modified version as
+dnl well.
+
+dnl Check if the flag is supported by compiler
+dnl CC_CHECK_CFLAGS_SILENT([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
+
+AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [
+ AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]),
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $1"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a;])],
+ [eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"],
+ [eval "AS_TR_SH([cc_cv_cflags_$1])='no'"])
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
+ [$2], [$3])
+])
+
+dnl Check if the flag is supported by compiler (cacheable)
+dnl CC_CHECK_CFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
+
+AC_DEFUN([CC_CHECK_CFLAGS], [
+ AC_CACHE_CHECK([if $CC supports $1 flag],
+ AS_TR_SH([cc_cv_cflags_$1]),
+ CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here!
+ )
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
+ [$2], [$3])
+])
+
+dnl CC_CHECK_CFLAG_APPEND(FLAG, [action-if-found], [action-if-not-found])
+dnl Check for CFLAG and appends them to CFLAGS if supported
+AC_DEFUN([CC_CHECK_CFLAG_APPEND], [
+ AC_CACHE_CHECK([if $CC supports $1 flag],
+ AS_TR_SH([cc_cv_cflags_$1]),
+ CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here!
+ )
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
+ [CFLAGS="$CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3])
+])
+
+dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not])
+AC_DEFUN([CC_CHECK_CFLAGS_APPEND], [
+ for flag in $1; do
+ CC_CHECK_CFLAG_APPEND($flag, [$2], [$3])
+ done
+])
+
+dnl Check if the flag is supported by linker (cacheable)
+dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
+
+AC_DEFUN([CC_CHECK_LDFLAGS], [
+ AC_CACHE_CHECK([if $CC supports $1 flag],
+ AS_TR_SH([cc_cv_ldflags_$1]),
+ [ac_save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $1"
+ AC_LANG_PUSH([C])
+ AC_LINK_IFELSE([AC_LANG_SOURCE([int main() { return 1; }])],
+ [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
+ [eval "AS_TR_SH([cc_cv_ldflags_$1])="])
+ AC_LANG_POP([C])
+ LDFLAGS="$ac_save_LDFLAGS"
+ ])
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes],
+ [$2], [$3])
+])
+
+dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for
+dnl the current linker to avoid undefined references in a shared object.
+AC_DEFUN([CC_NOUNDEFINED], [
+ dnl We check $host for which systems to enable this for.
+ AC_REQUIRE([AC_CANONICAL_HOST])
+
+ case $host in
+ dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads
+ dnl are requested, as different implementations are present; to avoid problems
+ dnl use -Wl,-z,defs only for those platform not behaving this way.
+ *-freebsd* | *-openbsd*) ;;
+ *)
+ dnl First of all check for the --no-undefined variant of GNU ld. This allows
+ dnl for a much more readable commandline, so that people can understand what
+ dnl it does without going to look for what the heck -z defs does.
+ for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do
+ CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"])
+ break
+ done
+ ;;
+ esac
+
+ AC_SUBST([LDFLAGS_NOUNDEFINED])
+])
+
+dnl Check for a -Werror flag or equivalent. -Werror is the GCC
+dnl and ICC flag that tells the compiler to treat all the warnings
+dnl as fatal. We usually need this option to make sure that some
+dnl constructs (like attributes) are not simply ignored.
+dnl
+dnl Other compilers don't support -Werror per se, but they support
+dnl an equivalent flag:
+dnl - Sun Studio compiler supports -errwarn=%all
+AC_DEFUN([CC_CHECK_WERROR], [
+ AC_CACHE_CHECK(
+ [for $CC way to treat warnings as errors],
+ [cc_cv_werror],
+ [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror],
+ [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])])
+ ])
+])
+
+AC_DEFUN([CC_CHECK_ATTRIBUTE], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))],
+ AS_TR_SH([cc_cv_attribute_$1]),
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ AC_LANG_PUSH([C])
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])],
+ [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"],
+ [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"])
+ AC_LANG_POP([C])
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes],
+ [AC_DEFINE(
+ AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1,
+ [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))]
+ )
+ $4],
+ [$5])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
+ CC_CHECK_ATTRIBUTE(
+ [constructor],,
+ [void __attribute__((constructor)) ctor() { int a; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
+ CC_CHECK_ATTRIBUTE(
+ [format], [format(printf, n, n)],
+ [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [
+ CC_CHECK_ATTRIBUTE(
+ [format_arg], [format_arg(printf)],
+ [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
+ CC_CHECK_ATTRIBUTE(
+ [visibility_$1], [visibility("$1")],
+ [void __attribute__((visibility("$1"))) $1_function() { }],
+ [$2], [$3])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
+ CC_CHECK_ATTRIBUTE(
+ [nonnull], [nonnull()],
+ [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
+ CC_CHECK_ATTRIBUTE(
+ [unused], ,
+ [void some_function(void *foo, __attribute__((unused)) void *bar);],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [
+ CC_CHECK_ATTRIBUTE(
+ [sentinel], ,
+ [void some_function(void *foo, ...) __attribute__((sentinel));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [
+ CC_CHECK_ATTRIBUTE(
+ [deprecated], ,
+ [void some_function(void *foo, ...) __attribute__((deprecated));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_ALIAS], [
+ CC_CHECK_ATTRIBUTE(
+ [alias], [weak, alias],
+ [void other_function(void *foo) { }
+ void some_function(void *foo) __attribute__((weak, alias("other_function")));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_MALLOC], [
+ CC_CHECK_ATTRIBUTE(
+ [malloc], ,
+ [void * __attribute__((malloc)) my_alloc(int n);],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_PACKED], [
+ CC_CHECK_ATTRIBUTE(
+ [packed], ,
+ [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_CONST], [
+ CC_CHECK_ATTRIBUTE(
+ [const], ,
+ [int __attribute__((const)) twopow(int n) { return 1 << n; } ],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_FLAG_VISIBILITY], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([if $CC supports -fvisibility=hidden],
+ [cc_cv_flag_visibility],
+ [cc_flag_visibility_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden],
+ cc_cv_flag_visibility='yes',
+ cc_cv_flag_visibility='no')
+ CFLAGS="$cc_flag_visibility_save_CFLAGS"])
+
+ AS_IF([test "x$cc_cv_flag_visibility" = "xyes"],
+ [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1,
+ [Define this if the compiler supports the -fvisibility flag])
+ $1],
+ [$2])
+])
+
+AC_DEFUN([CC_FUNC_EXPECT], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([if compiler has __builtin_expect function],
+ [cc_cv_func_expect],
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ AC_LANG_PUSH([C])
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+ [int some_function() {
+ int a = 3;
+ return (int)__builtin_expect(a, 3);
+ }])],
+ [cc_cv_func_expect=yes],
+ [cc_cv_func_expect=no])
+ AC_LANG_POP([C])
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ AS_IF([test "x$cc_cv_func_expect" = "xyes"],
+ [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1,
+ [Define this if the compiler supports __builtin_expect() function])
+ $1],
+ [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported],
+ [cc_cv_attribute_aligned],
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ AC_LANG_PUSH([C])
+ for cc_attribute_align_try in 64 32 16 8 4 2; do
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+ int main() {
+ static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0;
+ return c;
+ }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
+ done
+ AC_LANG_POP([C])
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ if test "x$cc_cv_attribute_aligned" != "x"; then
+ AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned],
+ [Define the highest alignment supported])
+ fi
+])
diff --git a/src/3rdparty/libcroco/autogen.sh b/src/3rdparty/libcroco/autogen.sh
new file mode 100755
index 0000000..8a7d049
--- /dev/null
+++ b/src/3rdparty/libcroco/autogen.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+test -n "$srcdir" || srcdir=`dirname "$0"`
+test -n "$srcdir" || srcdir=.
+
+olddir=`pwd`
+
+cd $srcdir
+
+(test -f configure.ac) || {
+ echo "*** ERROR: Directory "\`$srcdir\'" does not look like the top-level project directory ***"
+ exit 1
+}
+
+PKG_NAME=`autoconf --trace 'AC_INIT:$1' configure.ac`
+
+if [ "$#" = 0 -a "x$NOCONFIGURE" = "x" ]; then
+ echo "*** WARNING: I am going to run \`configure' with no arguments." >&2
+ echo "*** If you wish to pass any to it, please specify them on the" >&2
+ echo "*** \`$0\' command line." >&2
+ echo "" >&2
+fi
+
+aclocal --install || exit 1
+gtkdocize --copy || exit 1
+autoreconf --verbose --force --install -Wno-portability || exit 1
+
+cd $olddir
+if [ "$NOCONFIGURE" = "" ]; then
+ $srcdir/configure "$@" || exit 1
+
+ if [ "$1" = "--help" ]; then exit 0 else
+ echo "Now type \`make\' to compile $PKG_NAME" || exit 1
+ fi
+else
+ echo "Skipping configure process."
+fi
diff --git a/src/3rdparty/libcroco/config.h.win32.in b/src/3rdparty/libcroco/config.h.win32.in
new file mode 100644
index 0000000..63d5c09
--- /dev/null
+++ b/src/3rdparty/libcroco/config.h.win32.in
@@ -0,0 +1,99 @@
+/* config.h.in. Handwritten for Windows compilation with MSVC. */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the
+ * GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Fan, Chun-wei
+ * See COPYRIGHTS file for copyright information.
+ */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/*#undef HAVE_DLFCN_H*/
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#ifndef _MSC_VER
+#define HAVE_INTTYPES_H 1
+#endif
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#if (!defined(_MSC_VER) || (_MSC_VER >= 1600))
+#define HAVE_STDINT_H 1
+#endif
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#ifndef _MSC_VER
+#define HAVE_STRINGS_H 1
+#endif
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#ifndef _MSC_VER
+#define HAVE_UNISTD_H 1
+#endif
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "libcroco"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "http://bugzilla.gnome.org/enter_bug.cgi?product=libcroco"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "libcroco"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libcroco @LIBCROCO_VERSION@"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libcroco"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "@LIBCROCO_VERSION@"
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "@LIBCROCO_VERSION@"
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#define __PROTOTYPES 1
diff --git a/src/3rdparty/libcroco/configure.ac b/src/3rdparty/libcroco/configure.ac
new file mode 100644
index 0000000..59aa072
--- /dev/null
+++ b/src/3rdparty/libcroco/configure.ac
@@ -0,0 +1,191 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.64)
+AC_INIT([libcroco],[0.6.99],[https://gitlab.com/inkscape/libcroco/-/issues],[libcroco])
+AC_CONFIG_SRCDIR([src/cr-input.c])
+AC_CANONICAL_HOST
+
+# gnu strictness to generate the INSTALL file
+AM_INIT_AUTOMAKE([1.13 tar-ustar dist-xz no-dist-gzip -Wno-portability foreign])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+if test -z "$enable_maintainer_mode"; then
+ enable_maintainer_mode=yes
+fi
+AM_MAINTAINER_MODE([enable])
+
+m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+
+LIBCROCO_MAJOR_VERSION=0
+LIBCROCO_MINOR_VERSION=6
+LIBCROCO_MICRO_VERSION=99
+
+LIBCROCO_CURRENT=3
+LIBCROCO_REVISION=1
+LIBCROCO_AGE=0
+
+#LIBCROCO_VERSION_INFO=`expr $LIBCROCO_MAJOR_VERSION + $LIBCROCO_MINOR_VERSION`:$LIBCROCO_MICRO_VERSION:$LIBCROCO_MINOR_VERSION
+LIBCROCO_VERSION_INFO="$LIBCROCO_CURRENT:$LIBCROCO_REVISION:$LIBCROCO_AGE"
+LIBCROCO_VERSION=$LIBCROCO_MAJOR_VERSION.$LIBCROCO_MINOR_VERSION.$LIBCROCO_MICRO_VERSION
+LIBCROCO_VERSION_NUMBER=`expr $LIBCROCO_MAJOR_VERSION \* 10000 + $LIBCROCO_MINOR_VERSION \* 100 + $LIBCROCO_MICRO_VERSION`
+
+AC_SUBST(LIBCROCO_MAJOR_VERSION)
+AC_SUBST(LIBCROCO_MINOR_VERSION)
+AC_SUBST(LIBCROCO_MICRO_VERSION)
+AC_SUBST(LIBCROCO_VERSION)
+AC_SUBST(LIBCROCO_VERSION_INFO)
+AC_SUBST(LIBCROCO_VERSION_NUMBER)
+AC_SUBST(LIBCROCO_CURRENT)
+AC_SUBST(LIBCROCO_AGE)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_CPP
+AC_PROG_MAKE_SET
+AC_STDC_HEADERS
+AC_ISC_POSIX
+
+LT_INIT([])
+
+CROCO_LIB=libcroco-$LIBCROCO_MAJOR_VERSION.$LIBCROCO_MINOR_VERSION.la
+AC_SUBST(CROCO_LIB)
+
+case "$host" in
+ *-*-cygwin*|*-*-mingw*)
+ platform_win32=yes
+ ;;
+ *)
+ platform_win32=no
+ ;;
+esac
+AM_CONDITIONAL(PLATFORM_WIN32, [test "$platform_win32" = "yes"])
+
+GTK_DOC_CHECK([1.0])
+
+dnl **************************************************************
+dnl check for the different --enable-option=val
+dnl messages issued by the user
+dnl ***************************************************************
+G_DISABLE_CHECKS=0
+AC_ARG_ENABLE(checks,
+ AC_HELP_STRING([--enable-checks=yes|no],
+ [enables runtime safety checks. Default=yes]),
+ WITH_CHECKS=$enableval,
+ WITH_CHECKS="yes")
+
+if test "$WITH_CHECKS" = "no" ; then
+ G_DISABLE_CHECKS=1
+fi
+AC_SUBST(G_DISABLE_CHECKS)
+
+dnl ************************************************
+dnl end of check of the different --enable-feature options
+dnl *************************************************
+
+##############
+# Dependencies
+##############
+
+GLIB_REQUIRED=2.0
+LIBXML_REQUIRED=2.4.23
+
+PKG_CHECK_MODULES([CROCO],[
+ glib-2.0 >= $GLIB_REQUIRED
+ libxml-2.0 >= $LIBXML_REQUIRED])
+
+##########################################################
+# Check for -Bsymbolic-functions linker flag used to avoid
+# intra-library PLT jumps, if available.
+##########################################################
+
+AC_ARG_ENABLE([Bsymbolic],
+ [AS_HELP_STRING([--disable-Bsymbolic],
+ [disable linking with -Bsymbolic])],
+ [],[enable_Bsymbolic=yes])
+
+BSYMBOLIC_LDFLAG=
+if test "$enable_Bsymbolic" != "no"; then
+ CC_CHECK_LDFLAGS(["-Wl,-Bsymbolic-functions"],
+ [BSYMBOLIC_LDFLAG="-Wl,-Bsymbolic-functions"],
+ [if test "$enable_Bsymbolic" = "auto"; then
+ AC_MSG_WARN([-Bsymbolic not supported by ld; disabling])
+ enable_Bsymbolic=no
+ else
+ AC_MSG_ERROR([-Bsymbolic requested but not supported by ld. Use --disable-Bsymbolic to disable])
+ fi])
+fi
+
+AC_SUBST([BSYMBOLIC_LDFLAG])
+
+##############################################
+# Check whether MSVC toolset is explicitly set
+##############################################
+
+AM_CONDITIONAL(MSVC_BASE_NO_TOOLSET_SET, [test x$MSVC_BASE_TOOLSET = x])
+AM_CONDITIONAL(MSVC_NO_TOOLSET_SET, [test x$MSVC_TOOLSET = x])
+
+###################
+# Compiler warnings
+###################
+
+CC_CHECK_CFLAGS_APPEND([ \
+ -Wall -Wextra \
+ -Wunused -Wreturn-type -Wswitch -Wcomment -Wtrigraphs \
+ -Wchar-subscripts -Wparentheses -Winline -Wredundant-decls \
+ -Wformat-nonliteral -Werror=format-security \
+ -Wsign-compare -Werror=implicit-function-declaration \
+ -Wpointer-arith -Wwrite-strings -Wstrict-prototypes \
+ -Wcast-align -Wimplicit -Wuninitialized \
+ -Wmissing-prototypes -Wmissing-declarations -Wnested-externs \
+ -Wpacked -Wmissing-format-attribute -Wshadow \
+ -Wstrict-aliasing=2 -Winit-self -Wunsafe-loop-optimizations \
+ -Wdeclaration-after-statement -Wold-style-definition \
+ -Wno-missing-field-initializers -Wno-unused-parameter \
+ -fno-common -Wno-switch-enum])
+
+##########################################
+
+AC_OUTPUT([
+Makefile
+libcroco.pc
+libcroco.spec
+libcroco-zip
+croco-config
+config.h.win32
+win32/Makefile
+win32/vs9/Makefile
+win32/vs9/croco-version-paths.vsprops
+win32/vs10/Makefile
+win32/vs10/croco-version-paths.props
+win32/vs11/Makefile
+win32/vs12/Makefile
+win32/vs14/Makefile
+win32/vs15/Makefile
+win32/vs16/Makefile
+docs/Makefile
+docs/examples/Makefile
+docs/reference/Makefile
+tests/Makefile
+tests/test-inputs/Makefile
+tests/test-output-refs/Makefile
+global-test-vars.sh
+src/Makefile
+src/libcroco-config.h
+csslint/Makefile
+
+])
+
+dnl =======================================================================
+echo "
+ =====================================================================
+ LIBCROCO, GNOME CSS2 PARSING AND MANIPULATION TOOLKIT $VERSION
+ =====================================================================
+
+ prefix: : ${prefix}
+ source code location: : ${srcdir}
+ compiler: : ${CC}
+ cflags: : ${CFLAGS}
+
+ Maintainer mode: : ${USE_MAINTAINER_MODE}
+"
diff --git a/src/3rdparty/libcroco/croco-config.1 b/src/3rdparty/libcroco/croco-config.1
new file mode 100644
index 0000000..9418e72
--- /dev/null
+++ b/src/3rdparty/libcroco/croco-config.1
@@ -0,0 +1,37 @@
+.TH LIBCROCO 1 "20 January 2003" Version 0.1.0
+.SH NAME
+croco-config - script to get information about the installed version of LIBCROCO
+.SH SYNOPSIS
+.B croco-config
+[\-\-prefix\fI[=DIR]\fP] [\-\-libs] [\-\-cflags] [\-\-version] [\-\-help]
+.SH DESCRIPTION
+\fIcroco-config\fP is a tool used to determine the necessary flags to compile and
+link programs that uses \fILIBCROCO\fP.
+.SH OPTIONS
+.l
+\fIcroco-config\fP accepts the following options:
+.TP 8
+.B \-\-version
+Print the currently installed version of \fILIBCROCO\fP on the standard output.
+.TP 8
+.B \-\-libs
+Print the linker flags necessary to link a \fILIBCROCO\fP program.
+.TP 8
+.B \-\-cflags
+Print the compiler flags necessary to compile a \fILIBCROCO\fP program.
+.TP 8
+.B \-\-prefix=PREFIX
+If specified, use PREFIX instead of the installation prefix that
+\fILIBCROCO\fP was built with when computing the output for the
+\-\-cflags and \-\-libs options. This option must be specified before
+any \-\-libs or \-\-cflags options.
+.SH AUTHOR
+This manual page was written by Gael CHAMOULAUD (strider) <strider@freespiders.org>
+.SH REPORTING BUGS
+Please report bugs at http://bugzilla.gnome.org.
+.SH COPYRIGHT
+Copyright (C) 2002-2003 Dodji SEKETELI, Gael CHAMOULAUD.
+.br
+This is a free software; see the source for copying conditions. There is
+NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/src/3rdparty/libcroco/croco-config.in b/src/3rdparty/libcroco/croco-config.in
new file mode 100644
index 0000000..36ef10a
--- /dev/null
+++ b/src/3rdparty/libcroco/croco-config.in
@@ -0,0 +1,82 @@
+#! /bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+exec_prefix_set=no
+
+usage()
+{
+ cat <<EOF
+Usage: croco-config [OPTION]...
+
+Known values for OPTION are:
+
+ --prefix=DIR change CROCO prefix [default $prefix]
+ --exec-prefix=DIR change CROCO executable prefix [default $exec_prefix]
+ --libs print library linking information
+ --cflags print pre-processor and compiler flags
+ --help display this help and exit
+ --version output version information
+EOF
+
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case "$1" in
+ --prefix=*)
+ prefix=$optarg
+ if test $exec_prefix_set = no ; then
+ exec_prefix=$optarg
+ fi
+ ;;
+
+ --prefix)
+ echo $prefix
+ ;;
+
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ exec_prefix_set=yes
+ ;;
+
+ --exec-prefix)
+ echo $exec_prefix
+ ;;
+
+ --version)
+ echo @VERSION@
+ exit 0
+ ;;
+
+ --help)
+ usage 0
+ ;;
+
+ --cflags)
+ echo @CROCO_CFLAGS@ @GLIB2_CFLAGS@ @LIBXML2_CFLAGS@
+ ;;
+
+ --libs)
+ echo @CROCO_LIBS@ @GLIB2_LIBS@ @LIBXML2_LIBS@
+ ;;
+
+ *)
+ usage
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+
+exit 0
diff --git a/src/3rdparty/libcroco/csslint/CMakeLists.txt b/src/3rdparty/libcroco/csslint/CMakeLists.txt
new file mode 100644
index 0000000..8f125c8
--- /dev/null
+++ b/src/3rdparty/libcroco/csslint/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(csslint_EXE csslint)
+
+add_executable(${csslint_EXE} csslint.c)
+
+target_include_directories(${csslint_EXE}
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/src
+ ${CMAKE_BINARY_DIR}/src
+ ${GLIB_INCLUDE_DIRS}
+ ${LIBXML_INCLUDE_DIRS}
+)
+
+target_link_libraries(${csslint_EXE}
+ PRIVATE
+ croco_LIB
+)
diff --git a/src/3rdparty/libcroco/csslint/ChangeLog b/src/3rdparty/libcroco/csslint/ChangeLog
new file mode 100644
index 0000000..b7b1df6
--- /dev/null
+++ b/src/3rdparty/libcroco/csslint/ChangeLog
@@ -0,0 +1,29 @@
+2004-01-27 Gael CHAMOULAUD <strider@gnome.org>
+
+ * csslint/csslint.c: (csslint_show_version): Made smallish cleanup
+
+2003-06-28 Gal Chamoulaud <strider@freespiders.org>
+
+ * csslint.c (csslint_show_version): Added CROCO_LAYENG_ENABLED test
+ in csslint_show_version function.
+
+2003-04-02 Gal Chamoulaud <strider@freespiders.org>
+
+ * csslint.1: updated man page
+
+2003-03-24 Gal Chamoulaud <strider@freespiders.org>
+
+ * csslint.c (csslint_usage): Added the ability to parse
+ a CSS file and builds a CSS object model.
+ * csslint.1: updated csslint man page
+
+
+2003-03-23 Gal Chamoulaud <strider@freespiders.org>
+
+ * Makefile.am (AM_CFLAGS): added a man page for csslint program.
+
+ * csslint.1: added a man page for csslint program.
+
+ * csslint.c: initialized the csslint program. A command CSS
+ parser tool for LIBCRCCO.
+
diff --git a/src/3rdparty/libcroco/csslint/Makefile.am b/src/3rdparty/libcroco/csslint/Makefile.am
new file mode 100644
index 0000000..3969962
--- /dev/null
+++ b/src/3rdparty/libcroco/csslint/Makefile.am
@@ -0,0 +1,18 @@
+bin_PROGRAMS = csslint-0.6
+#man_MANS = csslint.1
+
+csslint_0_6_SOURCES = csslint.c
+
+croco_lib = $(top_builddir)/src/@CROCO_LIB@
+
+csslint_0_6_LDADD = $(croco_lib)
+
+csslint_0_6_CPPFLAGS = \
+ -I$(top_srcdir)/intl \
+ -I$(top_srcdir)/src \
+ -I$(top_builddir)/src \
+ $(CROCO_CFLAGS)
+
+csslint_0_6_LDFLAGS=$(CROCO_LIBS)
+
+#EXTRA_DIST = $(man_MANS)
diff --git a/src/3rdparty/libcroco/csslint/csslint.1 b/src/3rdparty/libcroco/csslint/csslint.1
new file mode 100644
index 0000000..a4c76a0
--- /dev/null
+++ b/src/3rdparty/libcroco/csslint/csslint.1
@@ -0,0 +1,64 @@
+.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "CSSLINT" 1 "" "" "csslint Manual"
+.SH NAME
+csslint \- command line CSS tool
+.SH "SYNOPSIS"
+
+.nf
+\fBcsslint\fR [\fB--version\fR | \fB--cssom\fR]
+.fi
+
+.SH "INTRODUCTION"
+
+.PP
+The csslint program parses one or more CSS files, specified on the command line as \fIcssfile\fR\&. It prints various types of output, depending upon the options selected\&. It is useful for detecting errors both in CSS code and in the CSS parser itself\&.
+
+.PP
+It is included in libcroco\&.
+
+.SH "OPTIONS"
+
+.TP
+\fB--version\fR
+Display the version of libcroco used\&.
+
+.TP
+\fB--cssom\fR
+parse a CSS file and builds a CSS object model\&.
+
+.SH AUTHOR
+Written by Gael CHAMOULAUD (strider) <strider@freespiders.org>
+
+.SH REPORTING BUGS
+Please report bugs at http://bugzilla.gnome.org.
+
+.SH COPYRIGHT
+Copyright (C) 2002-2003 Dodji SEKETELI, Gael CHAMOULAUD.
+.br
+This is a free software; see the source for copying conditions. There is
+NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
+
+.SH SEE ALSO
+.br
+croco-config (1)
+
+
diff --git a/src/3rdparty/libcroco/csslint/csslint.c b/src/3rdparty/libcroco/csslint/csslint.c
new file mode 100644
index 0000000..3495eff
--- /dev/null
+++ b/src/3rdparty/libcroco/csslint/csslint.c
@@ -0,0 +1,1011 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * csslint.c : a small tester program for libcroco.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Initial Author: Gael Chamoulaud.
+ * Main programmer: Dodji Seketeli
+ * Contributor: Rob Buis
+ * See COPYRGIGHTS file for copyright information.
+ */
+
+#include "libcroco.h"
+#include "cr-libxml-node-iface.h"
+#include <libxml/xpath.h>
+
+#include <glib.h>
+#include <string.h>
+
+/**
+ *The options data structure.
+ *The variable of this data structure are set
+ *during the parsing the command line by the
+ *parse_command_line() function.
+ */
+struct Options {
+ gboolean show_version;
+ gboolean use_cssom;
+ gboolean display_help;
+ gboolean evaluate;
+ gboolean dump_location;
+ gchar *author_sheet_path;
+ gchar *user_sheet_path;
+ gchar *ua_sheet_path;
+ gchar *xml_path;
+ gchar *xpath;
+ gchar **css_files_list;
+};
+
+struct SacContext {
+ gint level;
+
+};
+
+static enum CRStatus sac_parse_and_display_locations (guchar * a_file_uri);
+
+static void parse_cmd_line (int a_argc, char **a_argv,
+ struct Options *a_options);
+
+static void display_version (void);
+
+static void display_usage (void);
+
+static enum CRStatus cssom_parse (guchar * a_file_uri);
+
+static enum CRStatus get_and_dump_node_style (xmlNode * a_node,
+ CRSelEng * a_sel_eng,
+ CRCascade * a_cascade);
+
+static enum CRStatus evaluate_selectors (gchar * a_xml_path,
+ gchar * a_author_sheet_path,
+ gchar * a_user_sheet_path,
+ gchar * a_ua_sheet_path,
+ gchar * a_xpath);
+
+/**
+ *Parses the command line.
+ *@param a_argc the argc parameter of the main routine.
+ *@param the argv parameter of the main routine.
+ *@param a_options out parameter the parsed options.
+ */
+static void
+parse_cmd_line (int a_argc, char **a_argv, struct Options *a_options)
+{
+ int i = 0;
+
+ g_return_if_fail (a_options);
+
+ if (a_argc <= 1) {
+ display_usage ();
+ }
+
+ for (i = 1; i < a_argc; i++) {
+ if (a_argv[i][0] != '-')
+ break;
+
+ if ((!strcmp (a_argv[i], "-version")) ||
+ (!strcmp (a_argv[i], "-v"))) {
+ a_options->show_version = TRUE;
+ } else if (!strcmp (a_argv[i], "--evaluate") ||
+ !strcmp (a_argv[i], "-e")) {
+ for (i++; i < a_argc; i++) {
+ if (!strcmp (a_argv[i], "--author-sheet")) {
+ if (a_options->author_sheet_path) {
+ display_usage ();
+ exit (-1);
+ }
+ i++;
+ if (i >= a_argc
+ || a_argv[i][0] == '-') {
+ g_print ("--author-sheet should be followed by a path to the sheet\n");
+ display_usage ();
+ exit (-1);
+ }
+ a_options->author_sheet_path =
+ a_argv[i];
+ } else if (!strcmp
+ (a_argv[i], "--user-sheet")) {
+ if (a_options->user_sheet_path) {
+ display_usage ();
+ exit (-1);
+ }
+ i++;
+ if (i >= a_argc
+ || a_argv[i][0] == '-') {
+ g_print ("--user-sheet should be followed by a path to the sheet\n");
+ display_usage ();
+ exit (-1);
+ }
+ a_options->user_sheet_path =
+ a_argv[i];
+ } else if (!strcmp (a_argv[i], "--ua-sheet")) {
+ if (a_options->ua_sheet_path) {
+ display_usage ();
+ exit (-1);
+ }
+ i++;
+ if (i >= a_argc
+ || a_argv[i][0] == '-') {
+ g_print ("--ua-sheet should be followed by a path to the sheet\n");
+ display_usage ();
+ exit (-1);
+ }
+ a_options->ua_sheet_path = a_argv[i];
+ } else if (!strcmp (a_argv[i], "--xml")) {
+ i++;
+ if (i >= a_argc
+ || a_argv[i][0] == '-') {
+ g_print ("--xml should be followed by a path to the xml document\n");
+ display_usage ();
+ exit (-1);
+ }
+ a_options->xml_path = a_argv[i];
+ } else if (!strcmp (a_argv[i], "--xpath")) {
+ i++;
+ if (i >= a_argc
+ || a_argv[i][0] == '-') {
+ g_print ("--xpath should be followed by an xpath expression\n");
+ display_usage ();
+ exit (-1);
+ }
+ a_options->xpath = a_argv[i];
+ } else {
+ break;
+ }
+ }
+ if (!a_options->author_sheet_path
+ && !a_options->user_sheet_path &&
+ !a_options->ua_sheet_path) {
+ g_print ("Error: you must specify at least one stylesheet\n");
+ display_usage ();
+ exit (-1);
+
+ }
+ if (!a_options->xpath) {
+ g_printerr
+ ("Error: you must specify an xpath expression using the --xpath option\n");
+ display_usage ();
+ exit (-1);
+
+ }
+ a_options->evaluate = TRUE;
+ } else if (!strcmp (a_argv[i], "--dump-location")) {
+ a_options->dump_location = TRUE;
+ a_options->use_cssom = FALSE;
+ } else if (!strcmp (a_argv[i], "--help") ||
+ !strcmp (a_argv[i], "-h")) {
+ a_options->display_help = TRUE;
+ } else {
+ display_usage ();
+ exit (-1);
+ }
+ }
+
+ if (i >= a_argc) {
+ a_options->css_files_list = NULL;
+ } else {
+ if (a_argv[i][0] == '-') {
+ display_usage ();
+ exit (-1);
+ }
+ a_options->css_files_list = &a_argv[i];
+ }
+}
+
+/**
+ *Displays the version text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_version (void)
+{
+ g_print ("%s\n", LIBCROCO_VERSION);
+}
+
+/**
+ *Displays the usage text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_usage (void)
+{
+ g_print ("Usage: csslint <path to a css file>\n");
+ g_print ("\t| csslint -v|--version\n");
+ g_print ("\t| csslint --dump-location <path to a css file>\n");
+ g_print ("\t| csslint <--evaluate | -e> [--author-sheet <path> --user-sheet <path> --ua-sheet <path>\n\t ] --xml <path> --xpath <xpath expression>\n");
+}
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+cssom_parse (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+ CRStyleSheet *stylesheet = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ parser = cr_om_parser_new (NULL);
+ status = cr_om_parser_parse_file (parser,
+ a_file_uri, CR_ASCII, &stylesheet);
+ if (status == CR_OK && stylesheet) {
+ cr_stylesheet_dump (stylesheet, stdout);
+ g_print ("\n");
+ cr_stylesheet_destroy (stylesheet);
+ }
+ cr_om_parser_destroy (parser);
+
+ return status;
+}
+
+static enum CRStatus
+get_and_dump_node_style (xmlNode * a_node,
+ CRSelEng * a_sel_eng, CRCascade * a_cascade)
+{
+ CRPropList *prop_list = NULL,
+ *pair = NULL,
+ *prev_pair = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_node && a_sel_eng && a_cascade,
+ CR_BAD_PARAM_ERROR);
+
+ status = cr_sel_eng_get_matched_properties_from_cascade
+ (a_sel_eng, a_cascade, a_node, &prop_list);
+ if (status != CR_OK) {
+ g_printerr ("Error: unable to run the selection engine\n");
+ return CR_OK;
+ }
+ g_print ("Properties of xml element %s are:\n", a_node->name);
+ for (pair = prop_list; pair; pair = cr_prop_list_get_next (pair)) {
+ CRDeclaration *decl = NULL;
+
+ cr_prop_list_get_decl (pair, &decl);
+ if (decl) {
+ prev_pair = cr_prop_list_get_prev (pair);
+ if (prev_pair) {
+ g_print ("\n");
+ prev_pair = NULL;
+ }
+ cr_declaration_dump_one (decl, stdout, 2);
+ decl = NULL;
+ }
+ }
+ g_print ("\n=====================\n\n");
+
+ if (prop_list) {
+ cr_prop_list_destroy (prop_list);
+ prop_list = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+evaluate_selectors (gchar * a_xml_path,
+ gchar * a_author_sheet_path,
+ gchar * a_user_sheet_path,
+ gchar * a_ua_sheet_path, gchar * a_xpath)
+{
+ CRSelEng *sel_eng = NULL;
+ xmlDoc *xml_doc = NULL;
+ xmlXPathContext *xpath_context = NULL;
+ xmlXPathObject *xpath_object = NULL;
+ CRStyleSheet *author_sheet = NULL,
+ *user_sheet = NULL,
+ *ua_sheet = NULL;
+ CRCascade *cascade = NULL;
+ xmlNode *cur_node = NULL;
+ gint i = 0;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_xml_path && a_xpath, CR_BAD_PARAM_ERROR);
+
+ xml_doc = xmlParseFile (a_xml_path);
+ if (!xml_doc) {
+ g_printerr ("Error: Could not parse file %s\n", a_xml_path);
+ status = CR_ERROR;
+ goto end;
+ }
+ if (a_author_sheet_path) {
+ status = cr_om_parser_simply_parse_file
+ ((const guchar *) a_author_sheet_path, CR_ASCII, &author_sheet);
+ if (!author_sheet) {
+ g_printerr ("Error: Could not parse author sheet\n");
+ }
+ }
+ if (a_user_sheet_path) {
+ status = cr_om_parser_simply_parse_file
+ ((const guchar *) a_user_sheet_path, CR_ASCII, &user_sheet);
+ if (!user_sheet) {
+ g_printerr ("Error: Could not parse author sheet\n");
+ }
+ }
+ if (a_ua_sheet_path) {
+ status = cr_om_parser_simply_parse_file
+ ((const guchar *) a_ua_sheet_path, CR_ASCII, &ua_sheet);
+ if (!ua_sheet) {
+ g_printerr ("Error: Could not parse ua sheet\n");
+ }
+ }
+ cascade = cr_cascade_new (author_sheet, user_sheet, ua_sheet);
+
+ if (author_sheet)
+ cr_stylesheet_unref (author_sheet);
+
+ if (user_sheet)
+ cr_stylesheet_unref (user_sheet);
+
+ if (ua_sheet)
+ cr_stylesheet_unref (ua_sheet);
+
+ if (!cascade) {
+ g_printerr ("Could not instantiate the cascade\n");
+ status = CR_ERROR;
+ goto end;
+ }
+ sel_eng = cr_sel_eng_new (&cr_libxml_node_iface);
+ if (!sel_eng) {
+ g_printerr
+ ("Error: Could not instantiate the selection engine\n");
+ status = CR_ERROR;
+ goto end;
+ }
+ xpath_context = xmlXPathNewContext (xml_doc);
+ if (!xpath_context) {
+ g_printerr
+ ("Error: Could not instantiate the xpath context\n");
+ status = CR_ERROR;
+ goto end;
+ }
+ xpath_object = xmlXPathEvalExpression ((const xmlChar *) a_xpath, xpath_context);
+ if (!xpath_object) {
+ g_printerr ("Error: Could not evaluate xpath expression\n");
+ status = CR_ERROR;
+ goto end;
+ }
+ if (xpath_object->type != XPATH_NODESET || !xpath_object->nodesetval) {
+ g_printerr
+ ("Error: xpath does not evalualuate to a node set\n");
+ status = CR_ERROR;
+ goto end;
+ }
+
+ for (i = 0; i < xpath_object->nodesetval->nodeNr; i++) {
+ cur_node = xpath_object->nodesetval->nodeTab[i];
+ if (cur_node->type == XML_ELEMENT_NODE) {
+ status = get_and_dump_node_style (cur_node, sel_eng,
+ cascade);
+ }
+ }
+
+ end:
+
+ if (xpath_context) {
+ xmlXPathFreeContext (xpath_context);
+ xpath_context = NULL;
+ }
+ if (xpath_object) {
+ xmlXPathFreeObject (xpath_object);
+ xpath_object = NULL;
+ }
+ if (sel_eng) {
+ cr_sel_eng_destroy (sel_eng);
+ sel_eng = NULL;
+ }
+ if (cascade) {
+ cr_cascade_destroy (cascade);
+ cascade = NULL;
+ }
+ if (xml_doc) {
+ xmlFreeDoc (xml_doc);
+ xml_doc = NULL;
+ }
+
+ return status;
+}
+
+/***************************
+ *SAC related stuff for the
+ *line/col annotation stylesheet
+ *dumping
+ ***************************/
+static void
+start_document (CRDocHandler * a_this)
+{
+ struct SacContext *context = NULL;
+
+ g_return_if_fail (a_this);
+
+ context = g_try_malloc (sizeof (struct SacContext));
+ if (!context) {
+ cr_utils_trace_info ("instantiation of sac context failed");
+ return;
+ }
+ cr_doc_handler_set_ctxt (a_this, context);
+}
+
+static void
+end_document (CRDocHandler * a_this)
+{
+ struct SacContext *context = NULL;
+
+ g_return_if_fail (a_this);
+
+ cr_doc_handler_get_ctxt (a_this, (gpointer *) (gpointer) & context);
+ if (context) {
+ g_free (context);
+ context = NULL;
+ }
+}
+
+static void
+charset (CRDocHandler *a_this,
+ CRString *a_charset,
+ CRParsingLocation *a_charset_sym_location)
+{
+ gchar *str = NULL ;
+
+ g_return_if_fail (a_this && a_charset && a_charset_sym_location) ;
+
+ str = (gchar*)cr_string_peek_raw_str (a_charset) ;
+ if (str) {
+ g_print ("\n\n@charset \"%s\";\n\n", str) ;
+ str = NULL ;
+ } else {
+ return ;
+ }
+ g_print ("/********************************************\n") ;
+ g_print (" * Parsing location information of the @charset rule\n") ;
+ g_print (" ********************************************/\n") ;
+ if (a_charset_sym_location) {
+ str = cr_parsing_location_to_string (a_charset_sym_location, 0) ;
+ if (str) {
+ g_print (" /*@charset*/\n") ;
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+ str = (gchar*) cr_string_peek_raw_str (a_charset) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = NULL ;
+ }
+ str = cr_parsing_location_to_string (&a_charset->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+static void
+import_style (CRDocHandler *a_this,
+ GList *a_media_list,
+ CRString *a_uri,
+ CRString *a_uri_default_ns,
+ CRParsingLocation *a_location)
+{
+ gchar *str = NULL ;
+ GString *gstr = NULL ;
+ GList *cur_media = NULL ;
+
+ g_return_if_fail (a_this && a_location) ;
+
+ gstr = g_string_new (NULL) ;
+ if (!gstr) {
+ cr_utils_trace_info ("Out of memory error") ;
+ return ;
+ }
+ for (cur_media = a_media_list ;
+ cur_media ;
+ cur_media = g_list_next (cur_media)) {
+ str = (gchar*)cr_string_peek_raw_str
+ ((CRString*)cur_media->data) ;
+ if (str) {
+ if (g_list_previous (cur_media)) {
+ g_string_append_printf (gstr, ", %s",
+ str) ;
+ } else {
+ g_string_append_printf (gstr, "%s",
+ str) ;
+ }
+ }
+ }
+ str = (gchar*)cr_string_peek_raw_str (a_uri) ;
+ if (str) {
+ g_print ("@import url(\"%s\") ", str) ;
+ if (gstr) {
+ g_print ("%s;\n\n", gstr->str) ;
+ }
+ str = NULL ;
+ }
+ str = cr_parsing_location_to_string (a_location, 0) ;
+ if (str) {
+ g_print ("/*****************************************************\n") ;
+ g_print (" *Parsing location information for the @import rule\n") ;
+ g_print (" ******************************************************/\n\n") ;
+ g_print (" /*@import*/\n") ;
+ g_print (" /*%s*/\n\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+
+ str = (gchar*)cr_string_peek_raw_str (a_uri) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = cr_parsing_location_to_string
+ (&a_uri->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+
+ for (cur_media = a_media_list ;
+ cur_media ;
+ cur_media = g_list_next (cur_media)) {
+ str = (gchar*)cr_string_peek_raw_str
+ ((CRString*)cur_media->data) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ }
+ str = cr_parsing_location_to_string
+ (&((CRString*)cur_media->data)->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+
+ if (gstr) {
+ g_string_free (gstr, TRUE) ;
+ gstr = NULL ;
+ }
+}
+
+static void
+start_font_face (CRDocHandler *a_this,
+ CRParsingLocation *a_location)
+{
+ gchar *str = NULL ;
+
+ g_print ("@font-face {\n") ;
+ g_print ("/******************************************************\n") ;
+ g_print (" Parsing location information for the @font-face rule\n") ;
+ g_print (" ******************************************************/\n\n") ;
+
+ g_print (" /*@font-face*/\n") ;
+ if (a_location) {
+ str = cr_parsing_location_to_string (a_location, 0) ;
+ }
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+static void
+end_font_face (CRDocHandler *a_this)
+{
+ g_print ("}\n") ;
+}
+
+static void
+start_media (CRDocHandler *a_this,
+ GList *a_media_list,
+ CRParsingLocation *a_location)
+{
+ GList *cur_media = NULL ;
+ gchar *str = NULL ;
+
+ g_print ("@media ") ;
+ for (cur_media = a_media_list ;
+ cur_media ;
+ cur_media = g_list_next (cur_media)) {
+ CRString *crstr = cur_media->data ;
+ if (crstr) {
+ str = (gchar*)cr_string_peek_raw_str (crstr) ;
+ if (str) {
+ if (cur_media->prev) {
+ g_print (", %s", str) ;
+ } else {
+ g_print ("%s", str) ;
+ }
+ }
+ }
+ }
+ /*****************************
+ *new print parsing locations
+ *****************************/
+ g_print ("\n /*@media*/\n") ;
+ if (a_location)
+ str = cr_parsing_location_to_string (a_location,
+ 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ for (cur_media = a_media_list ;
+ cur_media ;
+ cur_media = g_list_next (cur_media)) {
+ CRString *crstr = cur_media->data ;
+ if (crstr) {
+ str = (gchar*)cr_string_peek_raw_str (crstr) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = cr_parsing_location_to_string
+ (&crstr->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+ }
+ }
+ g_print ("\n{\n") ;
+}
+
+static void
+end_media (CRDocHandler *a_this,
+ GList *a_media_list)
+{
+ g_print ("\n}\n") ;
+}
+
+static void
+start_page (CRDocHandler *a_this,
+ CRString *a_name,
+ CRString *a_pseudo_page,
+ CRParsingLocation *a_location)
+{
+ gchar *str = NULL ;
+
+ g_print ("@page ") ;
+ if (a_name)
+ str = (gchar*)cr_string_peek_raw_str (a_name) ;
+ if (str) {
+ g_print ("%s ", str) ;
+ }
+ if (a_pseudo_page)
+ str = (gchar*) cr_string_peek_raw_str (a_pseudo_page) ;
+ if (str) {
+ g_print (":%s", str) ;
+ str = NULL ;
+ }
+ /*************************************
+ *print parsing location information
+ ************************************/
+ g_print ("\n\n /*@page*/\n") ;
+ if (a_location)
+ str = cr_parsing_location_to_string
+ (a_location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ if (a_name)
+ str = (gchar*)cr_string_peek_raw_str (a_name) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = cr_parsing_location_to_string
+ (&a_name->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+ if (a_pseudo_page)
+ str = (gchar*) cr_string_peek_raw_str
+ (a_pseudo_page) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = cr_parsing_location_to_string
+ (&a_pseudo_page->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+ g_print ("\n{\n") ;
+}
+
+static void
+end_page (CRDocHandler *a_this,
+ CRString *a_name,
+ CRString *pseudo_page)
+{
+ g_print ("}\n") ;
+}
+
+static void
+dump_location_annotated_simple_sel (CRSimpleSel *a_this)
+{
+ CRSimpleSel *cur_simple_sel = a_this ;
+ CRAdditionalSel *cur_add_sel = NULL ;
+ gchar *str0 = NULL ;
+
+ g_return_if_fail (a_this) ;
+
+ /*first, display the entire simple sel*/
+ str0 = (gchar *) cr_simple_sel_one_to_string
+ (cur_simple_sel) ;
+ if (str0) {
+ g_print ("/*%s*/\n", str0) ;
+ g_free (str0) ;
+ str0 = NULL ;
+ }
+ g_print ("/*") ;
+ cr_parsing_location_dump
+ (&cur_simple_sel->location, 0,
+ stdout);
+ g_print ("*/\n") ;
+
+ /*now display the details of the simple sel*/
+ if (cur_simple_sel->name) {
+ str0 = (gchar*) cr_string_peek_raw_str
+ (cur_simple_sel->name) ;
+ if (str0) {
+ g_print (" /*%s*/\n", str0) ;
+ str0 = NULL ;
+ }
+ str0 = cr_parsing_location_to_string
+ (&cur_simple_sel->name->location,
+ 0) ;
+ if (str0) {
+ g_print (" /*%s*/\n", str0) ;
+ g_free (str0) ;
+ str0 = NULL ;
+ }
+ }
+ for (cur_add_sel = cur_simple_sel->add_sel;
+ cur_add_sel;
+ cur_add_sel = cur_add_sel->next) {
+ str0 = (gchar *) cr_additional_sel_one_to_string
+ (cur_add_sel) ;
+ if (str0) {
+ g_print ("\n /*%s*/\n", str0) ;
+ g_free (str0) ;
+ str0 = NULL ;
+ }
+ str0 = cr_parsing_location_to_string
+ (&cur_add_sel->location, 0) ;
+ if (str0) {
+ g_print (" /*%s*/\n", str0) ;
+ g_free (str0) ;
+ str0 = NULL ;
+ }
+ }
+}
+
+static void
+start_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
+{
+ struct SacContext *context = NULL;
+ CRSelector *cur_sel = NULL ;
+ CRSimpleSel *cur_simple_sel = NULL ;
+
+ g_return_if_fail (a_this);
+
+ cr_doc_handler_get_ctxt (a_this, (gpointer *) (gpointer) & context);
+ if (context) {
+ context->level++;
+ }
+ cr_selector_dump (a_selector_list, stdout);
+ g_print (" {\n") ;
+ g_print ("/************************************************\n") ;
+ g_print (" *Parsing location information of the selector\n") ;
+ g_print (" ************************************************/\n") ;
+
+ for (cur_sel = a_selector_list;
+ cur_sel ;
+ cur_sel = cur_sel->next) {
+ for (cur_simple_sel = cur_sel->simple_sel ;
+ cur_simple_sel ;
+ cur_simple_sel = cur_simple_sel->next) {
+
+ dump_location_annotated_simple_sel
+ (cur_simple_sel) ;
+ }
+ }
+}
+
+static void
+end_selector (CRDocHandler * a_this,
+ CRSelector *a_selector_list)
+{
+ struct SacContext *context = NULL;
+
+ g_return_if_fail (a_this);
+
+ cr_doc_handler_get_ctxt (a_this, (gpointer *) (gpointer) & context);
+ if (context) {
+ context->level--;
+ }
+ g_print (" }\n") ;
+}
+
+static void
+property (CRDocHandler *a_this,
+ CRString *a_name,
+ CRTerm *a_expr,
+ gboolean a_is_important)
+{
+ gchar *str = NULL ;
+ CRTerm *cur_term = NULL ;
+
+ str = (gchar*) cr_string_peek_raw_str (a_name) ;
+ if (str) {
+ g_print ("\n\n") ;
+ g_print ("%s", str) ;
+ str = NULL ;
+ if (a_expr) {
+ str = (gchar *) cr_term_to_string (a_expr) ;
+ if (str) {
+ g_print (" : %s;\n\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ } else {
+ g_print (";\n\n") ;
+ }
+ }
+
+ /*Now dump each part of the property declaration*/
+
+ g_print ("\n") ;
+ g_print ("/************************************************\n") ;
+ g_print (" *Parsing location information of the property\n") ;
+ g_print (" ************************************************/\n") ;
+
+ str = (gchar*) cr_string_peek_raw_str (a_name) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = NULL ;
+ }
+ str = cr_parsing_location_to_string (&a_name->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+
+ for (cur_term = a_expr ;
+ cur_term;
+ cur_term = cur_term->next) {
+ str = (gchar *) cr_term_one_to_string (cur_term) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ str = cr_parsing_location_to_string
+ (&cur_term->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+}
+
+
+static enum CRStatus
+sac_parse_and_display_locations (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CRDocHandler *sac_handler = NULL;
+ CRParser *parser = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ parser = cr_parser_new_from_file (a_file_uri, CR_UTF_8);
+ if (!parser) {
+ cr_utils_trace_info ("parser instantiation failed");
+ return CR_ERROR;
+ }
+ sac_handler = cr_doc_handler_new ();
+ if (!sac_handler) {
+ cr_utils_trace_info ("sac handler instantiation failed");
+ status = CR_OUT_OF_MEMORY_ERROR;
+ goto cleanup;
+ }
+ sac_handler->start_document = start_document ;
+ sac_handler->end_document = end_document ;
+ sac_handler->charset = charset ;
+ sac_handler->import_style = import_style ;
+ sac_handler->start_font_face = start_font_face ;
+ sac_handler->end_font_face = end_font_face ;
+ sac_handler->start_media = start_media ;
+ sac_handler->end_media = end_media ;
+ sac_handler->start_page = start_page ;
+ sac_handler->end_page = end_page ;
+ sac_handler->start_selector = start_selector;
+ sac_handler->end_selector = end_selector;
+ sac_handler->property = property ;
+
+ cr_parser_set_sac_handler (parser, sac_handler) ;
+ status = cr_parser_parse (parser) ;
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+ return status;
+}
+
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+ enum CRStatus status = CR_OK;
+
+ memset (&options, 0, sizeof (struct Options));
+ options.use_cssom = TRUE;
+ parse_cmd_line (argc, argv, &options);
+
+ if (options.show_version == TRUE) {
+ display_version ();
+ return 0;
+ }
+
+ if (options.display_help == TRUE) {
+ display_usage ();
+ return 0;
+ }
+ if (options.use_cssom == TRUE) {
+ if (options.evaluate == TRUE) {
+ status = evaluate_selectors
+ (options.xml_path,
+ options.author_sheet_path,
+ options.user_sheet_path,
+ options.ua_sheet_path, options.xpath);
+ } else if (options.css_files_list != NULL) {
+ status = cssom_parse ((guchar *) options.css_files_list[0]);
+ }
+ } else if (options.dump_location == TRUE) {
+ if (options.css_files_list) {
+ status = sac_parse_and_display_locations
+ ((guchar *) options.css_files_list[0]) ;
+ } else {
+ display_usage () ;
+ return -1 ;
+ }
+ }
+
+ return (status == CR_OK) ? 0 : -2;
+}
diff --git a/src/3rdparty/libcroco/docs/Makefile.am b/src/3rdparty/libcroco/docs/Makefile.am
new file mode 100644
index 0000000..ece8c4b
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS=examples reference
+
+EXTRA_DIST=usage.txt
diff --git a/src/3rdparty/libcroco/docs/design/parser-architecture.txt b/src/3rdparty/libcroco/docs/design/parser-architecture.txt
new file mode 100644
index 0000000..67b7713
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/design/parser-architecture.txt
@@ -0,0 +1,146 @@
+Libcroco parser architecture
+-----------------------------
+
+Author: Dodji Seketeli <dodji@seketeli.org>
+
+$Id$
+
+I) Forethoughts.
+===================
+
+Libcroco's parser is a simple recursive descent parser.
+The major design focus has been simplicity, reliability and
+conformance.
+
+Simplicity
+-----------
+We want the code to be maintainable by anyone who knows the CSS spec
+and who knows how to code in C. Therefore, we avoid to overuse
+the C preprocessor magic and all the tricks that tend to turn C into
+a maintenance nightmare.
+
+We also try to adhere to the Gnome coding guidelines specified
+at http://developer.gnome.org/doc/guides/programming-guidelines.
+
+
+Reliability
+-----------
+Each single function of the libcroco library should never crash,
+and this, whatever the arguments it takes.
+As a consequence we tend to be paranoid when it comes to check
+pointers values before dereferencing them for example...
+
+Conformance
+-----------
+We try to stick to the CSS spec. We know this is almost impossible to achieve
+given the resources we have but we think it is a sane target to chase.
+
+II) Overall architecture
+=========================
+The parser is organized around several main classes:
+
+1/ CRInput
+2/ CRTknzr (Tokenizer or lexer)
+3/ CRParser
+4/ CROMParser
+
+II.1 The CRInput class
+-----------------------
+The CRInput class provides the abstraction of
+an utf8-encoded character stream.
+
+Ideally, it should abstract local data sources
+(local files and in-memory buffers)
+and remote data sources (sockets, url-identified resources) but for the
+moment, it can only abstract local data sources.
+
+Adding a new type of data source should be transparent for the
+classes that already use CRInput. After all, this is what abstraction is about :)
+
+
+II.2 The CRTknzr class
+----------------------
+The main job of the tokenizer (or lexer) is to
+provide a get_next_token() method.
+This methods returns the next CSS token found in the input stream.
+(Note that the input stream here is an instance of CRInput).
+
+This provides an extremely useful facility to the parser.
+
+II.3 The CRParser class
+-------------------------
+The core of the parser.
+
+The main job of this class is to provide a cr_parser_parse_stylesheet()
+method. During the parsing (the execution of the cr_parser_stylesheet())
+the parser sends events to notify the application when it encounters
+remarkable CSS constructions. This is the SAC (Simple API for CSS) API model.
+
+To achieve that task, almost each production of the CSS grammar
+has a matching parsing function (or method) in this class.
+
+For example, the following production named "ruleset" (specified in the
+CSS2 spec in appendix D.1):
+
+ruleset : selector [ ',' S* selector ]*
+ '{' S* declaration [ ';' S* declaration ]* '}' S*
+
+is "implemented" by the cr_parser_parse_ruleset() method.
+
+The same thing applies for the "selector" production:
+
+selector : simple_selector [ combinator simple_selector ]*
+
+which is implemented by the cr_parser_parse_selector() method... and so on
+and so forth.
+
+II.3.1 Structure of a parsing method.
+-------------------------------------
+A parsing method (e.g cr_parser_parse_ruleset()) is there
+to:
+
+ * try to recognize a substring of the incoming character string
+ as something that matches a given CSS grammar production.
+
+ e.g: the job of the cr_parser_parse_ruleset() is to try
+ to recognize if "what" comes next in the input stream
+ is a CSS2 "ruleset".
+
+ * build a basic abstract data structure to
+ store the information encountered
+ during the parsing of the current character string.
+
+ eg: cr_parser_parse_declaration() has the following prototype:
+
+ enum CRStatus
+ cr_parser_parse_declaration (CRParser *a_this, GString **a_property,
+ CRTerm **a_value) ;
+
+ In case of successful parsing, this method returns
+ (via its parameters) the property _and_ the
+ value of the CSS2 declaration.
+ Note that a CSS2 declaration is specified as follows:
+
+ declaration : property ':' S* expr prio?
+ | /* empty */
+
+ * After completion, say if the parsing has succeeded or not.
+
+ eg: cr_parser_parse_declaration() returns CR_OK if the
+ parsing has succeeded, and error code otherwise. Obviously,
+ the out parameters "a_property" and "a_value" are valid if and only
+ if the return value is CR_OK.
+
+ * whenever the function is parsing a construct that must
+ be notified to the user as part of the SAC API spec, notify
+ the user by calling the right SAC callback.
+
+ * if the parsing failed, leave the position in the stream unchanged.
+ That is, the position in the character stream should be as if
+ the parsing function hasn't been called at all.
+
+
+II.4 The selection Engine.
+--------------------------
+
+Hmmh, I should kick my ass to write this down ... \ No newline at end of file
diff --git a/src/3rdparty/libcroco/docs/design/sel-instr.txt b/src/3rdparty/libcroco/docs/design/sel-instr.txt
new file mode 100644
index 0000000..6b19389
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/design/sel-instr.txt
@@ -0,0 +1,64 @@
+Draft of the libcroco selector internal instruction set.
+*********************************************************
+
+READERS SHOULD READ THE CHAPTER 5 of THE CSS2 CSS2 SPEC INTITLED
+"Selectors" FIRST.
+
+I) Introduction
+''''''''''''''''''''
+This is the instructions set understood by the libcroco
+sel-eng.c module (Selection engine).
+
+The purpose of the selection engine is to basically to say whether if a given
+xml node is matched by a given css2 selector or not.
+
+II) Rationale
+''''''''''''''''''''
+For the sake of performance (mostly processing speed) each CSS2
+selector is compiled into a sequences of atomic selection instructions
+that are easily executable by the selection engine.
+
+III) Selection instruction set overview
+''''''''''''''''''''''''''''''''''''''''
+
+Each selection instruction returns a boolean value (TRUE or FALSE).
+The execution of a sequence of selection instruction stops at the
+first instruction that returns a FALSE value and the selection engine
+returns returns the value FALSE to say that the current xml node
+is matched by the CSS2 selection expression being evaluated.
+
+Note that during the evaluation of a CSS2 selection expression,
+all the contextual information are stored into an evaluation context.
+For example, the context will hold a pointer to the xml node the
+selection engine is trying to match.
+
+III.1) The instruction set.
+'''''''''''''''''''''''''''
+
+set-cur-node 'a_node'
+----------------------
+a_node: an xml node
+Sets the current xml node (in the context) to a_node.
+
+match-n-ancestor 'a_n' 'a_parent'
+----------------------------------
+a_parent: a string.
+a_n: a number. The depth of the ancestor
+
+Returns true if the current xml node has an ancestor
+located at a depth 'n' (going upward from the current node)
+and named 'a_parent'. An ancestor located at depth '0' designates
+the current xml node. An ancesstor located at depth '1' designates
+the parent of the current xml node etc ...
+
+match-any
+---------
+Always returns true.
+
+match-first-child 'a_name'
+--------------------------
+Returns true if the current xml element's name equal 'a_name' and
+if the current xml element is the first child of its parent.
+
+TODO: continue reading the chapter 5 of the css2 spec and finish
+the design of this instruction set.
diff --git a/src/3rdparty/libcroco/docs/examples/Makefile.am b/src/3rdparty/libcroco/docs/examples/Makefile.am
new file mode 100644
index 0000000..e960594
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/Makefile.am
@@ -0,0 +1 @@
+EXTRA_DIST=cssom-example-1.c sac-example-1.c sac-example-2.c
diff --git a/src/3rdparty/libcroco/docs/examples/cssom-example-1.c b/src/3rdparty/libcroco/docs/examples/cssom-example-1.c
new file mode 100644
index 0000000..85079ce
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/cssom-example-1.c
@@ -0,0 +1,109 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/**
+ *This is an example that shows how to use
+ *the CSSOM api of the libcroco CSS2 parsing library.
+ *It just parses the CSS document given in argument and
+ *it dumps it (serializes) it on the screen.
+ *
+ *To compile it using gcc, type
+ *
+ *gcc -g -Wall `croco-0.6-config --cflags` `croco-0.6-config --libs` -o cssom-example-1 cssom-example-1.c
+ *
+ *Prior to that, you must have compiled and installed libcroco, of course.
+ *
+ *@author Dodji Seketeli
+ */
+
+#include <string.h>
+#include <libcroco/libcroco.h>
+
+/**
+ *Displays the usage of this program.
+ *@param prg_name the name of the program.
+ */
+void
+display_usage (char *prg_name)
+{
+ printf ("\nusage: %s [options] <css file to parse>\n\n",
+ prg_name) ;
+ printf ("\twhere options are:\n") ;
+ printf ("\t--help|h\tdisplays this help\n") ;
+ printf ("\n") ;
+}
+
+
+/**
+ *Main entry point.
+ *This function illustrates a way to use libcroco.
+ *In this example, we will use a CSS Object Model parser
+ *to parse a cascading style sheet and dump what we have parsed on stdout.
+ *
+ *The goal of the object model parser is to parse a css and build
+ *an abstract tree out of it. One can then walk the tree to perform
+ *whatever action he wants. In our case, the function used to
+ *dump the tree on stdout will walk the tree and dump each one of its
+ *components (a.k.a. css statements).
+ */
+int
+main (int argc, char **argv)
+{
+ short i = 0 ;
+ enum CRStatus status = CR_OK ;
+ CRStyleSheet *stylesheet = NULL ;
+
+ /*first parse command line arguments*/
+ for (i = 1 ; i < argc ; i++)
+ {
+ if (argv[i][0] != '-')
+ break ;
+ if (!strcmp (argv[i],"--help")
+ || !strcmp (argv[i], "-h"))
+ {
+ display_usage (argv[0]) ;
+ return 0 ;
+ }
+ else
+ {
+ display_usage (argv[0]) ;
+ return 0 ;
+ }
+ }
+ if (i >= argc)
+ {
+ display_usage (argv[0]) ;
+ return 0;
+ }
+
+ /*****************************************************
+ *Enough plumbering... now, the real libcroco stuffs.
+ ***************************************************/
+
+ /*
+ *What we want here is to simply parse
+ *a CSS document using the cssom api.
+ */
+ status = cr_om_parser_simply_parse_file ((const guchar*)argv[i] /*sheet*/,
+ CR_ASCII /*the encoding*/,
+ &stylesheet) ;
+ if (status == CR_OK && stylesheet)
+ {
+ /*
+ *everything went well,
+ *so dump the stylesheet on stdout.
+ */
+ cr_stylesheet_dump (stylesheet, stdout) ;
+ }
+
+ if (stylesheet)
+ {
+ /*
+ *free the the memory used to hold the css
+ *object model
+ */
+ cr_stylesheet_destroy (stylesheet) ;
+ stylesheet = NULL ;
+ }
+
+ return 0 ;
+}
diff --git a/src/3rdparty/libcroco/docs/examples/sac-example-1.c b/src/3rdparty/libcroco/docs/examples/sac-example-1.c
new file mode 100644
index 0000000..074fc07
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/sac-example-1.c
@@ -0,0 +1,198 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/**
+ *This test example shows how to use the SAC api.
+ *
+ *This features a simple parser that says "hey" when
+ *it encounters the beginning of a CSS ruleset, and "woohoo"
+ *at the end of a CSS ruleset.
+ *
+ *To compile this file, type:
+ *
+ *gcc -g -Wall -o sac-example-1 `croco-0.6-config --cflags` `croco-0.6-config --libs` sac-example-1.c
+ *
+ *Make sure you have compiled and installed libcroco prior to trying to
+ *compile this file :)
+ *
+ *Once you have compiled it, type:
+ *
+ *./sac-example-1 <a-path-to-a-css-file>
+ *
+ *to try it on a CSS file of your choice.
+ *
+ *Initial Author: Dodji Seketeli <Dodji 47 seketeli dot org>
+ */
+
+#include <string.h>
+#include <libcroco/libcroco.h>
+
+/**
+ *This is a callback function that will
+ *be called at the beginning of each css ruleset.
+ *@param a_handler a pointer to the current sac
+ *document handler
+ *@param a_selector a pointer to the selector.
+ *of the current ruleset.
+ */
+static void
+start_selector_cb (CRDocHandler *a_handler,
+ CRSelector *a_selector)
+{
+ printf ("==========================================\n") ;
+ printf ("Hey, this is the beginning of a ruleset\n") ;
+}
+
+/**
+ *This is a callback function that will be called at the end
+ *of the each css ruleset.
+ */
+static void
+end_selector_cb (CRDocHandler *a_handler,
+ CRSelector *a_selector)
+{
+ printf ("Woohoo, this is the end of a ruleset\n") ;
+ printf ("======================================\n\n") ;
+}
+
+/**
+ *Displays some information about how to use this program.
+ *@param a_prog_name the name of the current program.
+ */
+void
+display_usage (unsigned char *a_prog_name)
+{
+ unsigned char *prog_name = a_prog_name ;
+
+ if (!prog_name)
+ {
+ prog_name = (unsigned char*)"sac-example-1" ;
+ }
+
+ printf ("usage: %s [--help] | <css file name>\n", prog_name) ;
+}
+
+int
+main (int argc, char **argv)
+{
+ unsigned short i = 0 ;
+ unsigned char * file_path = NULL ;
+ CRParser * parser = NULL ;
+ CRDocHandler *sac_handler = NULL ;
+
+ if (argc <= 1)
+ {
+ display_usage ((unsigned char*)argv[0]) ;
+ return -1 ;
+ }
+
+ /*
+ *Let's parse the
+ *command line arguments of this
+ *program in this loop.
+ */
+ for (i=1 ; i < argc ;i++)
+ {
+ if (*argv[i] != '-')
+ break ;
+
+ if (!strcmp (argv[i], "--help")
+ || !strcmp (argv[i], "-h"))
+ {
+ display_usage ((unsigned char*)argv[0]) ;
+ return -1;
+ }
+ else
+ {
+ /*
+ *no other option is
+ *available now, so this is
+ *a bit redundant...
+ */
+ display_usage ((unsigned char*)argv[0]) ;
+ }
+ }
+
+ if (i > argc)
+ {
+ /*
+ *no file name has been given
+ *in parameter, go out.
+ */
+ return -1 ;
+ }
+
+ /****************************************
+ *Now, the real libcroco related stuffs...
+ ****************************************/
+
+ file_path = (unsigned char*)argv[i] ;
+
+ /*
+ *Instantiate the libcroco parser.
+ */
+ parser = cr_parser_new_from_file (file_path,
+ CR_ASCII) ;
+ if (!parser)
+ {
+ /*
+ *Damned, something bad happened ...
+ */
+ return -1;
+ }
+
+ /*
+ *Instantiates the SAC document handler.
+ */
+ sac_handler = cr_doc_handler_new () ;
+ if (!sac_handler)
+ {
+ /*
+ *Argh, something bad happened here :-\
+ *Let's release the resources we allocated
+ *and let's get out.
+ */
+
+ cr_parser_destroy (parser) ;
+ return -1;
+ }
+
+ /******************
+ *Sets some of the sac document handlers.
+ ****************/
+
+ /*
+ *This sac handler callback function will get called by the parser
+ *each time it encounters the beginning of a ruleset.
+ */
+ sac_handler->start_selector = start_selector_cb ;
+
+ /*
+ *This sac handler callback function will get called by the parser
+ *each time it encounters the end of a ruleset.
+ */
+ sac_handler->end_selector = end_selector_cb ;
+
+ /*
+ *Let's register our sac handler into the parser.
+ */
+ cr_parser_set_sac_handler (parser, sac_handler) ;
+
+ /*
+ *Now, let's do the parsing !!!
+ */
+ cr_parser_parse (parser) ;
+
+ /*******************************************************
+ *End of the parsing. A lot of sentences beginning with "Hey"
+ *may have been printed on the screen...
+ ***********************************************/
+
+ /*
+ *Time to free the resources we allocated.
+ */
+ cr_parser_destroy (parser) ;
+
+ cr_doc_handler_unref (sac_handler) ;
+
+ return 0 ;
+}
diff --git a/src/3rdparty/libcroco/docs/examples/sac-example-2.c b/src/3rdparty/libcroco/docs/examples/sac-example-2.c
new file mode 100644
index 0000000..63b002d
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/sac-example-2.c
@@ -0,0 +1,349 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+/**
+ *This test example shows how to use the SAC api.
+ *
+ *This features a simple parser that prints the selector list
+ *and the properties list of each CSS ruleset found.
+ *It also prints the number of properties found in each CSS ruleset.
+ *
+ *At the end of the parsing, it a prints the number of rulesets found
+ *in the CSS document.
+ *
+ *To to this, several handler callbacks have been registered.
+ *We have also created a data structure that we call a parsing context.
+ *This parsing context stores the data necessary to achieve the calculation
+ *done during the parsing (count the number of rulesets and the number
+ *of properties per ruleset)
+ *The parsing context itself is stored in the "app_data" field of the sac handler.
+ *This field is there to provide applications with a
+ *place to store the custom data they want to be able to get/set during the parsing.
+ *
+ *To compile this file, type:
+ *
+ *gcc -g -Wall -o sac-example-2 `croco-0.6-config --cflags` `croco-0.6-config --libs` sac-example-2.c
+ *
+ *Make sure you have compiled and installed libcroco prior to trying to
+ *compile this file :)
+ *
+ *Once you have compiled it, type:
+ *
+ *./sac-example-2 <a-path-to-a-css-file>
+ *
+ *to try it on a CSS file of your choice.
+ *
+ *Initial Author: Dodji Seketeli <Dodji 47 seketeli dot org>
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <libcroco/libcroco.h>
+
+/**
+ *A Context that will hold the
+ *variables necessary to count the number
+ *of rulesets and the number of properties
+ *per ruleset.
+ */
+struct MyFooContext
+{
+ /**the total number of rulesets in the stylesheet.*/
+ int nb_rulesets ;
+
+ /**the number of property per ruleset.*/
+ int nb_props_per_ruleset ;
+} ;
+
+/**
+ *This callback is called only once, at the beginning of
+ *the CSS Document.
+ *So here, we will allocate a custom parsing context
+ *where we will store data necessary for us to
+ *count the number of rulesets and properties found in
+ *the CSS document.
+ *@param a_handler the sac handler.
+ */
+static void
+start_document_cb (CRDocHandler *a_handler)
+{
+ struct MyFooContext * parsing_context = NULL ;
+
+ /*
+ *Allocate the parsing context.
+ *Our custom parsing context.
+ */
+ parsing_context = (struct MyFooContext*) malloc
+ (sizeof (struct MyFooContext)) ;
+ if (!parsing_context)
+ {
+ /*
+ *the system ran out of memory. Advertise it and
+ *stop the program.
+ */
+ fprintf (stderr, "program ran out of memory") ;
+ exit (-1) ;
+ }
+
+ /*
+ *Initialize the newly allocated custom parsing context
+ *to zero.
+ */
+ memset (parsing_context, 0, sizeof (struct MyFooContext)) ;
+
+ /*
+ *Store the parsing context in the document handler.
+ *The app_data field CRDocHandler is especially there
+ *for that: give applications a place to store some data
+ *during the parsing.
+ */
+ a_handler->app_data = parsing_context ;
+}
+
+/**
+ *This callback function will
+ *be called at the beginning of each css ruleset.
+ *@param a_handler a pointer to the current sac
+ *document handler
+ *@param a_selector a pointer to the selector.
+ *of the current ruleset.
+ */
+static void
+start_selector_cb (CRDocHandler *a_handler,
+ CRSelector *a_selector)
+{
+ struct MyFooContext *context = NULL ;
+
+ context = (struct MyFooContext*) a_handler->app_data ;
+ if (!context)
+ return ;
+ context->nb_props_per_ruleset = 0 ;
+
+ cr_selector_dump (a_selector, stdout) ;
+ printf (" {\n") ;
+
+}
+
+/**
+ *This callback function is called when
+ *the parser encounters a CSS property.
+ *@param a_handler the SAC handler.
+ *@param a_name string that contains the
+ *name of the property.
+ *@param a_value the value of the property.
+ */
+static void
+property_cb (CRDocHandler *a_handler,
+ CRString *a_name,
+ CRTerm *a_value,
+ gboolean a_important)
+{
+ struct MyFooContext *context = NULL ;
+
+ context = (struct MyFooContext *)a_handler->app_data ;
+
+ if (!context || !a_name)
+ return ;
+ context->nb_props_per_ruleset ++ ;
+
+ printf ("%s : ", cr_string_peek_raw_str (a_name)) ;
+ cr_term_dump (a_value, stdout) ;
+ printf ("\n") ;
+}
+
+
+/**
+ *This is a callback function that will be called at the end
+ *of the each css ruleset.
+ */
+static void
+end_selector_cb (CRDocHandler *a_handler,
+ CRSelector *a_selector)
+{
+ struct MyFooContext *context = NULL ;
+
+ context = (struct MyFooContext*)a_handler->app_data ;
+ if (!context)
+ return ;
+ context->nb_rulesets ++ ;
+ printf ("\n}\n") ;
+ printf ("**Number of properties in this ruleset: %d\n\n\n",
+ context->nb_props_per_ruleset) ;
+}
+
+/**
+ *This callback is called only once at the end
+ *of the CSS document.
+ *@param a_handler the SAC handler.
+ */
+static void
+end_document_cb (CRDocHandler *a_handler)
+{
+ struct MyFooContext *context = NULL ;
+
+ context = (struct MyFooContext*) a_handler->app_data ;
+ if (!context)
+ return ;
+
+ printf ("\nTotal number of rulesets: %d\n",
+ context->nb_rulesets) ;
+
+ free (context) ;
+ a_handler->app_data = NULL ;
+}
+
+/**
+ *Displays some information about how to use this program.
+ *@param a_prog_name the name of the current program.
+ */
+void
+display_usage (unsigned char *a_prog_name)
+{
+ unsigned char *prog_name = a_prog_name ;
+
+ if (!prog_name)
+ {
+ prog_name = (unsigned char*) "sac-example-1" ;
+ }
+
+ printf ("usage: %s [--help] | <css file name>\n", prog_name) ;
+}
+
+int
+main (int argc, char **argv)
+{
+ unsigned short i = 0 ;
+ unsigned char * file_path = NULL ;
+ CRParser * parser = NULL ;
+ CRDocHandler *sac_handler = NULL ;
+
+ if (argc <= 1)
+ {
+ display_usage ((unsigned char*)argv[0]) ;
+ return -1 ;
+ }
+
+ /*
+ *Let's parse the
+ *command line arguments of this
+ *program in this loop.
+ */
+ for (i=1 ; i < argc ;i++)
+ {
+ if (*argv[i] != '-')
+ break ;
+
+ if (!strcmp (argv[i], "--help")
+ || !strcmp (argv[i], "-h"))
+ {
+ display_usage ((unsigned char*)argv[0]) ;
+ return -1;
+ }
+ else
+ {
+ /*
+ *no other option is
+ *available now, so this is
+ *a bit redundant...
+ */
+ /*display_usage ((unsigned char*)argv[0]) ;*/
+ }
+ }
+
+ if (i > argc)
+ {
+ /*
+ *no file name has been given
+ *in parameter, go out.
+ */
+ return -1;
+ }
+
+ /****************************************
+ *Now, the real libcroco related stuffs...
+ ****************************************/
+
+ file_path = (unsigned char*)argv[i] ;
+
+ /*
+ *Instantiate the libcroco parser.
+ */
+ parser = cr_parser_new_from_file (file_path,
+ CR_ASCII) ;
+ if (!parser)
+ {
+ /*
+ *Damned, something bad happened ...
+ */
+ return -1 ;
+ }
+
+ /*
+ *Instantiates the SAC document handler.
+ */
+ sac_handler = cr_doc_handler_new () ;
+ if (!sac_handler)
+ {
+ /*
+ *Argh, something bad happened here :-\
+ *Let's release the resources we allocated
+ *and let's get out.
+ */
+
+ cr_parser_destroy (parser) ;
+ return -1 ;
+ }
+
+ /****************************************
+ *Set some of the sac document handlers.
+ ****************************************/
+
+ /*
+ *This callback function will be called by the parser
+ *only once, at the beginning of the CSS Document.
+ */
+ sac_handler->start_document = start_document_cb ;
+
+ /*
+ *This callback function will be called by the parser
+ *only once, at the end of the CSS Document.
+ */
+ sac_handler->end_document =end_document_cb ;
+
+ /*
+ *This callback function will be called by the parser
+ *each time it encounters the beginning of a ruleset.
+ */
+ sac_handler->start_selector = start_selector_cb ;
+
+ /*
+ *This callback function will be called by the parser
+ *each time it encounters the beginning of a ruleset.
+ */
+ sac_handler->property = property_cb ;
+
+ /*
+ *This sac handler callback function will be called by the parser
+ *each time it encounters the end of a ruleset.
+ */
+ sac_handler->end_selector = end_selector_cb ;
+
+ /*
+ *Let's register our sac handler into the parser.
+ */
+ cr_parser_set_sac_handler (parser, sac_handler) ;
+
+ /*
+ *Now, let's do the parsing !!!
+ */
+ cr_parser_parse (parser) ;
+
+ /*******************************************************
+ *End of the parsing. A Couple of CSS rulesets must have
+ *been printed on the screen...
+ ***********************************************/
+
+ /*
+ *Time to free the resources we allocated.
+ */
+ cr_parser_destroy (parser) ;
+
+ return 0 ;
+}
diff --git a/src/3rdparty/libcroco/docs/examples/selection-example-1.c b/src/3rdparty/libcroco/docs/examples/selection-example-1.c
new file mode 100644
index 0000000..3215a99
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/selection-example-1.c
@@ -0,0 +1,191 @@
+/**
+ * This example looks up a node from a document with an
+ * xpath expression, then reports all properties that apply
+ * from a given stylesheet.
+ *
+ * To compile it using gcc, type
+ *
+ * gcc -g -Wall `croco-0.6-config --cflags` `croco-0.6-config --libs` -o selection-example-1 selection-example-1.c
+ *
+ * Initial author: Stefan Seefeld.
+ */
+
+#include <libcroco/libcroco.h>
+#include <libcroco/cr-libxml-node-iface.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+void
+usage_and_exit (char *progname)
+{
+ fprintf (stderr,
+ "Usage: %s <xml doc> <stylesheet> <xpath>\n",
+ progname);
+ exit(-1);
+}
+
+struct workspace
+{
+ xmlDoc *document;
+ xmlXPathContext *xpath;
+ xmlXPathObject *result;
+ CRStyleSheet *stylesheet;
+ CRCascade *cascade;
+ CRSelEng *selector;
+};
+
+/**
+ *construct workspace members in order...
+ * return 0 on success and -1 on error
+ */
+int
+init (struct workspace *ws, char **args)
+{
+ enum CRStatus status = CR_OK;
+
+ ws->document = 0;
+ ws->xpath = 0;
+ ws->result = 0;
+ ws->stylesheet = 0;
+ ws->cascade = 0;
+ ws->selector = 0;
+
+
+ ws->document = xmlParseFile(args[0]);
+ if (!ws->document)
+ {
+ fprintf(stderr, "could not parse the document %s", args[0]);
+ return -1;
+ }
+ ws->xpath = xmlXPathNewContext(ws->document);
+ if (!ws->xpath)
+ {
+ fprintf(stderr, "Error: unable to create new XPath context\n");
+ return -1;
+ }
+ ws->result = xmlXPathEvalExpression((xmlChar *)args[2], ws->xpath);
+ if (!ws->result)
+ {
+ fprintf(stderr, "Error: unable to evaluate xpath expression\n");
+ return -1;
+ }
+ if (ws->result->type != XPATH_NODESET || !ws->result->nodesetval)
+ {
+ fprintf(stderr, "Error: xpath does not evaluate to a node set\n");
+ return -1;
+ }
+
+ status = cr_om_parser_simply_parse_file((const guchar*)args[1] /*sheet*/,
+ CR_ASCII /*the encoding*/,
+ &ws->stylesheet);
+ if (status != CR_OK || !ws->stylesheet)
+ {
+ fprintf(stderr, "could not parse the stylesheet %s", args[1]);
+ return -1;
+ }
+ ws->cascade = cr_cascade_new(ws->stylesheet, 0, 0);
+ ws->selector = cr_sel_eng_new(&cr_libxml_node_iface);
+ return 1 ;
+}
+
+/* ...and destruct in reverse order*/
+void
+fini(struct workspace *ws)
+{
+ if (ws->selector)
+ {
+ cr_sel_eng_destroy(ws->selector);
+ ws->selector = NULL ;
+ }
+ if (ws->cascade)
+ {
+ cr_cascade_destroy(ws->cascade);
+ ws->cascade = NULL ;
+ }
+
+ if (ws->result)
+ {
+ xmlXPathFreeObject(ws->result);
+ ws->result = NULL ;
+ }
+ if (ws->xpath)
+ {
+ xmlXPathFreeContext(ws->xpath);
+ ws->xpath = NULL ;
+ }
+ if (ws->document)
+ {
+ xmlFreeDoc(ws->document);
+ ws->document = NULL ;
+ }
+ xmlCleanupParser () ;
+}
+
+void
+print_properties_real (CRPropList *proplist)
+{
+ CRDeclaration *decl = NULL ;
+ CRPropList *cur_pair = NULL ;
+
+ for (cur_pair = proplist ; cur_pair ;
+ cur_pair= cr_prop_list_get_next (cur_pair)) {
+ gchar *str = NULL ;
+ decl = NULL ;
+
+ cr_prop_list_get_decl (cur_pair, &decl) ;
+ if (decl) {
+ str = cr_declaration_to_string (decl, 0) ;
+ if (str) {
+ printf ("%s\n", str) ;
+ g_free (str);
+ str = NULL ;
+ }
+ }
+ }
+}
+
+void
+print_properties (struct workspace *ws)
+{
+ enum CRStatus status;
+ CRPropList *prop_list = NULL;
+ xmlNode *node = ws->result->nodesetval->nodeTab[0];
+
+ status = cr_sel_eng_get_matched_properties_from_cascade
+ (ws->selector, ws->cascade,
+ node, &prop_list);
+
+ if (status != CR_OK)
+ fprintf(stderr, "Error retrieving properties\n");
+ else
+ {
+ xmlChar *prop = NULL ;
+ prop = xmlGetNodePath(node) ;
+ if (prop) {
+ printf("properties for node %s :\n", prop);
+ xmlFree (prop) ;
+ prop = NULL ;
+ }
+ print_properties_real (prop_list) ;
+ }
+ cr_prop_list_destroy (prop_list) ;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct workspace ws;
+ if (argc != 4) usage_and_exit(argv[0]);
+ if (!init(&ws, argv + 1)) {
+ fini(&ws);
+ return -1 ;
+ }
+
+ if (ws.result->nodesetval->nodeNr == 0)
+ printf("no matching nodes found\n");
+ else
+ print_properties(&ws);
+
+ fini(&ws);
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/docs/examples/selection-example-1.css b/src/3rdparty/libcroco/docs/examples/selection-example-1.css
new file mode 100644
index 0000000..044e053
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/selection-example-1.css
@@ -0,0 +1,41 @@
+report
+{
+ color : red;
+}
+
+report > entry
+{
+ color : blue;
+}
+
+note
+{
+ color : note-color;
+ frame : solid;
+}
+
+note[id]
+{
+ color : note-id-color;
+ frame : solid;
+}
+
+note[id=bar]
+{
+ margin : 5px;
+ color: note-id-bar-color ;
+}
+
+note[id=foo]
+{
+ color : note-id-foo-color;
+}
+
+entry[type=notice] note[id=bar]
+{
+ padding : 5px;
+}
+
+note + notea {
+ color: notea-color ;
+}
diff --git a/src/3rdparty/libcroco/docs/examples/selection-example-1.xml b/src/3rdparty/libcroco/docs/examples/selection-example-1.xml
new file mode 100644
index 0000000..4c3f558
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/selection-example-1.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" ?>
+<report>
+ <entry type="notice">
+ <note id="foo"/>
+ <notea/>
+ <note id="bar"/>
+ </entry>
+ <entry>
+ <notea/>
+ <note/>
+ <note id="foo"/>
+ <note id="bar"/>
+ </entry>
+</report>
diff --git a/src/3rdparty/libcroco/docs/reference/Makefile.am b/src/3rdparty/libcroco/docs/reference/Makefile.am
new file mode 100644
index 0000000..0ec463d
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/reference/Makefile.am
@@ -0,0 +1,53 @@
+## Process this file with automake to produce Makefile.in
+NULL=
+
+# The name of the module, e.g. 'glib'.
+DOC_MODULE=libcroco
+
+# The top-level SGML file. Change it if you want.
+DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
+
+# The directory containing the source code. Relative to $(srcdir).
+# gtk-doc will search all .c & .h files beneath here for inline comments
+# documenting functions and macros.
+DOC_SOURCE_DIR=../../src
+
+# Extra options to pass to gtkdoc-scanobj or gtkdoc-scangobj.
+SCANGOBJ_OPTIONS=--type-init-func="g_type_init()"
+
+# Extra options to supply to gtkdoc-scan.
+SCAN_OPTIONS=
+
+# Extra options to supply to gtkdoc-mkdb.
+MKDB_OPTIONS=--sgml-mode --output-format=xml
+
+# Extra options to supply to gtkdoc-fixref.
+FIXXREF_OPTIONS=
+
+# Used for dependencies.
+HFILE_GLOB=$(top_srcdir)/src/*.h
+CFILE_GLOB=$(top_srcdir)/src/*.c
+
+# Header files to ignore when scanning.
+IGNORE_HFILES=\
+ $(NULL)
+
+# Images to copy into HTML directory.
+HTML_IMAGES=\
+ $(NULL)
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+content_files=\
+ $(NULL)
+
+# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib
+# contains GtkObjects/GObjects and you want to document signals and properties.
+GTKDOC_CFLAGS=\
+ $(CROCO_CFLAGS) \
+ $(NULL)
+GTKDOC_LIBS=\
+ $(CROCO_LIBS) \
+ $(NULL)
+
+include $(top_srcdir)/gtk-doc.make
+
diff --git a/src/3rdparty/libcroco/docs/reference/libcroco-docs.sgml b/src/3rdparty/libcroco/docs/reference/libcroco-docs.sgml
new file mode 100644
index 0000000..f67e318
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/reference/libcroco-docs.sgml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
+ <bookinfo>
+ <title>Libcroco Reference Manual</title>
+ </bookinfo>
+
+ <chapter>
+ <title>Extensive APIs description</title>
+ <xi:include href="xml/cr-additional-sel.xml"/>
+ <xi:include href="xml/cr-attr-sel.xml"/>
+ <xi:include href="xml/cr-cascade.xml"/>
+ <xi:include href="xml/cr-declaration.xml"/>
+ <xi:include href="xml/cr-doc-handler.xml"/>
+ <xi:include href="xml/cr-enc-handler.xml"/>
+ <xi:include href="xml/cr-fonts.xml"/>
+ <xi:include href="xml/cr-input.xml"/>
+ <xi:include href="xml/cr-num.xml"/>
+ <xi:include href="xml/cr-om-parser.xml"/>
+ <xi:include href="xml/cr-parser.xml"/>
+ <xi:include href="xml/cr-parsing-location.xml"/>
+ <xi:include href="xml/cr-prop-list.xml"/>
+ <xi:include href="xml/cr-pseudo.xml"/>
+ <xi:include href="xml/cr-rgb.xml"/>
+ <xi:include href="xml/cr-sel-eng.xml"/>
+ <xi:include href="xml/cr-selector.xml"/>
+ <xi:include href="xml/cr-simple-sel.xml"/>
+ <xi:include href="xml/cr-statement.xml"/>
+ <xi:include href="xml/cr-string.xml"/>
+ <xi:include href="xml/cr-style.xml"/>
+ <xi:include href="xml/cr-stylesheet.xml"/>
+ <xi:include href="xml/cr-term.xml"/>
+ <xi:include href="xml/cr-tknzr.xml"/>
+ <xi:include href="xml/cr-token.xml"/>
+ <xi:include href="xml/cr-utils.xml"/>
+ <xi:include href="xml/libcroco-config.xml"/>
+ </chapter>
+</book>
diff --git a/src/3rdparty/libcroco/docs/release-notes-template.txt b/src/3rdparty/libcroco/docs/release-notes-template.txt
new file mode 100644
index 0000000..df66f98
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/release-notes-template.txt
@@ -0,0 +1,41 @@
+Application
+===========
+
+Libcroco 0.4
+
+Description
+===========
+
+Libcroco is a CSS parsing and manipulation library
+written in C for the gnome project.
+
+It provides :
+
+-two CSS parsing apis: SAC and CSSOM.
+-A CSS2 selection and cascading engine based on libxml2.
+-An experimental XML/CSS rendering engine.
+
+Changes
+=======
+- Removed the pango dependency from the
+ selection engine and put it in the layout engine. (Dodji Seketeli)
+- Added a test example to demonstrate the use of the selection engine (Stefan Seefeld)
+
+Fixes
+=====
+- Fixed some gcc-2.96 parse errors (Dodji Seketeli)
+- Make sure the header files are C++ friendly (Dodji Seketeli)
+- Make sure the code examples compile with g++ (Dodji Seketeli)
+- Fixed a bug in the selection engine (Dodji Seketeli)
+
+Homepage
+========
+http://www.freespiders.org/projects/libcroco
+
+Download
+========
+http://ftp.gnome.org/pub/GNOME/sources/libcroco
+
+GNOME Software Map entry
+========================
+http://www.gnome.org/softwaremap/projects/libcroco
diff --git a/src/3rdparty/libcroco/docs/usage.txt b/src/3rdparty/libcroco/docs/usage.txt
new file mode 100644
index 0000000..a061116
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/usage.txt
@@ -0,0 +1,47 @@
+initial author: Dodji Seketeli <dodji@seketeli.org>
+
+Note:
+----
+Users can generate an html doc of all the functions of libcroco.
+This is documentation is an unvaluable tool to master the libcroco
+usage and internals.
+To generate the documentation, just cd into the libcroco project
+directory and type 'make apidoc' ;
+This will generate the documentation in the docs/api directory.
+
+
+Usage of the libcroco css2 parsing library
+===========================================
+
+libcroco has two main user programming interfaces:
+the SAC parser, and the CSSOM parser.
+
+
+The SAC parser
+''''''''''''''''
+
+The SAC (Simple Api for CSS) is the lowest level parsing api
+provided by libcroco.
+It is an event driven api in which the parser notifies the
+caller whenever it encounters a remarquable css construction.
+
+The SAC parser is implemented in the CRParser class.
+To use it, one must first instantiate a CRParser.
+
+I said earlier the the SAC parser notifies it caller
+whenever it encounters certain css language constructions during
+the parsing. "Notifies" actually means that it calls a subset of given
+callback function pointers set. This set of function pointers is
+called a "Document Handler". So, by overriding some function pointers
+of the document handler, the user can define the actions to be
+performed when a given css language construction is encountered.
+
+The SAC parser's api is defined in cr-parser.h and
+the document handler's api is defined in cr-doc-handler.h .
+
+
+The CSSOM parser
+'''''''''''''''''
+
+
+
diff --git a/src/3rdparty/libcroco/global-test-vars.sh.in b/src/3rdparty/libcroco/global-test-vars.sh.in
new file mode 100644
index 0000000..cfe1849
--- /dev/null
+++ b/src/3rdparty/libcroco/global-test-vars.sh.in
@@ -0,0 +1,12 @@
+TEST_OUT_DIR=./tests
+TEST_SOURCE_DIR=@srcdir@/tests
+TEST_INPUTS_DIR="$TEST_SOURCE_DIR"/test-inputs
+CSSLINT=./csslint/.libs/csslint-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
+if ! test -x $CSSLINT ; then
+ echo "Error: Could not find an executable csslint. I was looking for $CSSLINT" >&2
+ exit 1
+fi
+
+if ! test x"$VALGRIND" = x ; then
+ CSSLINT="$VALGRIND $CSSLINT"
+fi
diff --git a/src/3rdparty/libcroco/libcroco-indent b/src/3rdparty/libcroco/libcroco-indent
new file mode 100755
index 0000000..f367987
--- /dev/null
+++ b/src/3rdparty/libcroco/libcroco-indent
@@ -0,0 +1,102 @@
+#!/bin/sh
+#This is just a smallish indent script to indent mlview
+#to indent all the sources correctly (before committing for ex),
+#type:
+#./indent-mlview src/*.[ch]
+
+#Here go some explanations of the indent options:
+#
+#-bad: forces a blank line after every block of declaration
+#=============================================================
+#-bap: forces a blank line after every procedure body
+#=============================================================
+#-bbb: forces a blank line before every boxed comment.
+#=============================================================
+#-sob: forces indent to swallow every optional blank line.
+#=============================================================
+#-bl -bli2 formats braces like this:
+#if (x > 2)
+# {
+# x-- ;
+# }
+#=============================================================
+#-nce formats the "else" not to cudle up to the
+#immediately preceding }:
+#if (x > 2)
+# {
+# x-- ;
+# }
+#else
+# {
+# x++ ;
+# }
+#==============================
+#-ce is the contrary of -nce
+#=============================================================
+#-ss: put a space before a semi colon that is at the same line as a
+#for.
+#=============================================================
+#-pcs: puts a space between the name of a procedure being called
+#and the '('.
+#=============================================================
+#-bs: puts a space between the sizeof operator and its argument.
+#=============================================================
+#-saf: puts a space between a for an the following parenthesis.
+#=============================================================
+#-sai: puts a space between an if and its arguments
+#=============================================================
+#-saw: puts a space between a while and its arguments
+#=============================================================
+#-psl: causes the type of a procedure being defined to be placed
+#on the line before the name of the procedure.
+#=============================================================
+#-bls: formats braces in struct declarations like this:
+#struct foo
+#{
+# int x;
+#};
+#-brs: formats braces in struct decls like this:
+#struct foo {
+# int x;
+#};
+#=============================================================
+#-bc: forces a newline after each comma in a declaration.
+#=============================================================
+#-i2: puts indentation at 2 blank chars.
+#=============================================================
+#-lp:
+#without -lp the code looks like this:
+#p1 = first_procedure (second_procedure (p2, p3),
+# third_procedure (p4, p5));
+#with -lp the code looks like this:
+#p1 = first_procedure (second_procedure (p2, p3),
+# third_procedure (p4, p5));
+#=============================================================
+#-ppi2: indents preprocessor directives using 2 spaces.
+#=============================================================
+#=============================================================
+#-ts2:set tabs spaces to 2 blank chars.
+#=============================================================
+#-l60 == --line-length60
+#=============================================================
+#-bbo: break long lines before boolean operators when found.
+#=============================================================
+
+INDENT=`which indent`
+GREP=`which grep`
+if test x$INDENT = x ; then
+ echo "Argh !!! Could not find indent in your PATH. Exited."
+ exit -1
+ if test x$GREP = x ; then
+ echo "Argh!!! Could not find grep in you PATH. Exited."
+ exit -1 ;
+ fi
+ is_gnu=`$INDENT -version | $GREP gnu`
+ if test x$is_gnu = x ; then
+ echo "Found a indent that is not the GNU one. Exited."
+ exit -1 ;
+ fi
+fi
+
+exec $INDENT -bad -bap -nbbb -br -ce -ss -pcs -bs -saf -sai \
+-cdw -saw -psl -brs -bc -i8 -ppi0 -lp -ts0 -bbo -sob $@
diff --git a/src/3rdparty/libcroco/libcroco-zip.in b/src/3rdparty/libcroco/libcroco-zip.in
new file mode 100755
index 0000000..5b6e2ee
--- /dev/null
+++ b/src/3rdparty/libcroco/libcroco-zip.in
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Build distribution zipfiles for libcroco on Win32: Runtime and
+# developer.
+
+ZIP=/tmp/libcroco-@VERSION@.zip
+DEVZIP=/tmp/libcroco-dev-@VERSION@.zip
+
+# The DLL name generated by libtool with the passed --version-info
+DLLNAME=libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-`expr @LIBCROCO_CURRENT@ - @LIBCROCO_AGE@`.dll
+
+cd @prefix@
+rm $ZIP
+
+zip $ZIP -@ <<EOF
+bin/$DLLNAME
+EOF
+
+rm $DEVZIP
+zip -r $DEVZIP -@ <<EOF
+bin/csslint-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@.exe
+include/libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
+lib/libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@.dll.a
+lib/pkgconfig/libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@.pc
+EOF
diff --git a/src/3rdparty/libcroco/libcroco.doap b/src/3rdparty/libcroco/libcroco.doap
new file mode 100644
index 0000000..4ffc1c6
--- /dev/null
+++ b/src/3rdparty/libcroco/libcroco.doap
@@ -0,0 +1,30 @@
+<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+ xmlns:foaf="http://xmlns.com/foaf/0.1/"
+ xmlns:gnome="http://api.gnome.org/doap-extensions#"
+ xmlns="http://usefulinc.com/ns/doap#">
+
+ <name xml:lang="en">libcroco</name>
+ <shortdesc xml:lang="en">A CSS parsing library</shortdesc>
+ <description>A CSS parsing library</description>
+ <homepage rdf:resource="http://www.linuxfromscratch.org/blfs/view/svn/general/libcroco.html" />
+ <mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/libcroco-list" />
+ <download-page rdf:resource="https://download.gnome.org/sources/libcroco/" />
+ <category rdf:resource="http://api.gnome.org/doap-extensions#core" />
+ <programming-language>C</programming-language>
+
+ <maintainer>
+ <foaf:Person>
+ <foaf:name>Abhishek Sharma</foaf:name>
+ <foaf:mbox rdf:resource="mailto:abhisheks@gnome.org" />
+ <gnome:userid>abhisheks</gnome:userid>
+ </foaf:Person>
+ </maintainer>
+ <maintainer>
+ <foaf:Person>
+ <foaf:name>Dodji Seketeli</foaf:name>
+ <foaf:mbox rdf:resource="mailto:dodji@gnome.org" />
+ <gnome:userid>dodji</gnome:userid>
+ </foaf:Person>
+ </maintainer>
+</Project>
diff --git a/src/3rdparty/libcroco/libcroco.pc.in b/src/3rdparty/libcroco/libcroco.pc.in
new file mode 100644
index 0000000..3d0dc0a
--- /dev/null
+++ b/src/3rdparty/libcroco/libcroco.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libcroco
+Version: @VERSION@
+Description: a CSS2 Parsing and manipulation Library in C.
+Requires: glib-2.0 libxml-2.0
+Libs: -L${libdir} -lcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
+Cflags: -I${includedir}/libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
diff --git a/src/3rdparty/libcroco/libcroco.spec.in b/src/3rdparty/libcroco/libcroco.spec.in
new file mode 100644
index 0000000..466d379
--- /dev/null
+++ b/src/3rdparty/libcroco/libcroco.spec.in
@@ -0,0 +1,82 @@
+%define lib_major 0
+
+Name: libcroco
+Summary: CSS2 parser library
+Version: @VERSION@
+Release: 1
+License: LGPL
+Group: System/Libraries
+Source0: ftp://ftp.gnome.org/pub/GNOME/sources/%{name}-%{version}.tar.gz
+URL: http://savannah.nongnu.org/projects/libcroco
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+BuildRequires: libxml2-devel
+BuildRequires: glib2-devel
+
+%description
+libcroco is a standalone css2 parsing library.
+It provides a low level event driven SAC like api
+and a css object model like api.
+
+%package devel
+Summary: Libraries and include files for developing with librsvg.
+Group: Development/C
+Requires: %{name} = %{version}-%{release}
+Provides: %{name}-devel = %{version}-%{release}
+Requires: libxml2-devel
+Requires: glib2-devel
+
+%description devel
+This package provides the necessary development libraries and include
+files to allow you to develop with libcroco?
+
+%prep
+%setup -q
+
+%build
+
+%configure
+
+make
+
+%install
+[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf $RPM_BUILD_ROOT
+%makeinstall
+
+%clean
+[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf $RPM_BUILD_ROOT
+
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-, root, root)
+%doc AUTHORS COPYING COPYING.LIB ChangeLog NEWS README.md
+%{_bindir}/csslint
+%{_mandir}/man1/csslint*
+%{_libdir}/*.so.*
+
+%files devel
+%defattr(-,root,root)
+%{_bindir}/croco-config
+%{_mandir}/man1/croco-config*
+%{_libdir}/*.la
+%{_libdir}/*.a
+%{_libdir}/*.so
+%{_includedir}/*
+%{_libdir}/pkgconfig/*
+
+%changelog
+* Tue Jul 8 2003 Christian Schaller <Uraeus@gnome.org>
+- Udate for 0.3 and Red Hat
+
+* Mon Jul 7 2003 Frederic Crozat <fcrozat@mandrakesoft.com> - 0.2.0-1mdk
+- Release 0.2.0
+- WARNING : binary compat is broken, you need to recompile apps built with libcroco 0.1
+
+* Fri Jun 13 2003 Gtz Waschk <waschk@linux-mandrake.com> 0.1.0-2mdk
+- rebuild for new rpm
+
+* Fri Apr 18 2003 Frederic Crozat <fcrozat@mandrakesoft.com> - 0.1.0-1mdk
+- First Mdk package.
diff --git a/src/3rdparty/libcroco/src/CMakeLists.txt b/src/3rdparty/libcroco/src/CMakeLists.txt
new file mode 100644
index 0000000..077c847
--- /dev/null
+++ b/src/3rdparty/libcroco/src/CMakeLists.txt
@@ -0,0 +1,85 @@
+set(G_DISABLE_CHECKS 0)
+configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/libcroco-config.h.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/libcroco-config.h")
+
+set(libcroco_headers
+ cr-additional-sel.h
+ cr-attr-sel.h
+ cr-cascade.h
+ cr-declaration.h
+ cr-doc-handler.h
+ cr-enc-handler.h
+ cr-fonts.h
+ cr-input.h
+ cr-libxml-node-iface.h
+ cr-node-iface.h
+ cr-num.h
+ cr-om-parser.h
+ cr-parser.h
+ cr-parsing-location.h
+ cr-prop-list.h
+ cr-pseudo.h
+ cr-rgb.h
+ cr-sel-eng.h
+ cr-selector.h
+ cr-simple-sel.h
+ cr-statement.h
+ cr-string.h
+ cr-style.h
+ cr-stylesheet.h
+ cr-term.h
+ cr-tknzr.h
+ cr-token.h
+ cr-utils.h
+ libcroco.h
+)
+
+set(libcroco_SRC
+ cr-additional-sel.c
+ cr-attr-sel.c
+ cr-cascade.c
+ cr-declaration.c
+ cr-doc-handler.c
+ cr-enc-handler.c
+ cr-fonts.c
+ cr-input.c
+ cr-libxml-node-iface.c
+ cr-num.c
+ cr-om-parser.c
+ cr-parser.c
+ cr-parsing-location.c
+ cr-prop-list.c
+ cr-pseudo.c
+ cr-rgb.c
+ cr-selector.c
+ cr-sel-eng.c
+ cr-simple-sel.c
+ cr-statement.c
+ cr-string.c
+ cr-style.c
+ cr-stylesheet.c
+ cr-term.c
+ cr-tknzr.c
+ cr-token.c
+ cr-utils.c
+ ${libcroco_headers}
+)
+
+add_library(croco_LIB STATIC "${libcroco_SRC}")
+
+target_include_directories(croco_LIB
+ PRIVATE
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${LIBXML_INCLUDE_DIRS}
+ PUBLIC
+ ${GLIB_INCLUDE_DIRS}
+)
+
+target_link_libraries(croco_LIB
+ PRIVATE
+ ${GLIB_LDFLAGS}
+ INTERFACE
+ ${LIBXML_LDFLAGS}
+ m
+)
diff --git a/src/3rdparty/libcroco/src/Makefile.am b/src/3rdparty/libcroco/src/Makefile.am
new file mode 100644
index 0000000..00711d4
--- /dev/null
+++ b/src/3rdparty/libcroco/src/Makefile.am
@@ -0,0 +1,136 @@
+NULL =
+
+lib_LTLIBRARIES=libcroco-0.6.la
+
+if PLATFORM_WIN32
+no_undefined = -no-undefined
+endif
+
+#Headers files to be distributed
+crocoincdir = $(includedir)/$(PACKAGE)-$(LIBCROCO_MAJOR_VERSION).$(LIBCROCO_MINOR_VERSION)/libcroco
+crocoinc_HEADERS = \
+ libcroco.h \
+ cr-additional-sel.h \
+ cr-attr-sel.h \
+ cr-cascade.h \
+ cr-declaration.h \
+ cr-doc-handler.h \
+ cr-enc-handler.h \
+ cr-input.h \
+ cr-libxml-node-iface.h \
+ cr-num.h \
+ cr-om-parser.h \
+ cr-parser.h \
+ cr-pseudo.h \
+ cr-rgb.h \
+ cr-selector.h \
+ cr-simple-sel.h \
+ cr-statement.h \
+ cr-stylesheet.h \
+ cr-term.h \
+ cr-tknzr.h \
+ cr-token.h \
+ cr-utils.h \
+ cr-fonts.h \
+ cr-sel-eng.h \
+ cr-style.h \
+ cr-prop-list.h \
+ cr-parsing-location.h \
+ cr-string.h \
+ libcroco-config.h \
+ $(NULL)
+
+libcroco_0_6_la_SOURCES = \
+ cr-utils.c \
+ cr-utils.h \
+ cr-input.c \
+ cr-input.h \
+ cr-enc-handler.c \
+ cr-enc-handler.h \
+ cr-libxml-node-iface.c \
+ cr-node-iface.h \
+ cr-num.c \
+ cr-num.h \
+ cr-rgb.c \
+ cr-rgb.h \
+ cr-token.c \
+ cr-token.h \
+ cr-tknzr.c \
+ cr-tknzr.h \
+ cr-term.c \
+ cr-term.h \
+ cr-attr-sel.c \
+ cr-attr-sel.h \
+ cr-pseudo.c \
+ cr-pseudo.h \
+ cr-additional-sel.c \
+ cr-additional-sel.h \
+ cr-simple-sel.c \
+ cr-simple-sel.h \
+ cr-selector.c \
+ cr-selector.h \
+ cr-doc-handler.c \
+ cr-doc-handler.h \
+ cr-parser.c \
+ cr-parser.h \
+ cr-declaration.c \
+ cr-declaration.h \
+ cr-statement.c \
+ cr-statement.h \
+ cr-stylesheet.c \
+ cr-stylesheet.h \
+ cr-cascade.c \
+ cr-cascade.h \
+ cr-om-parser.c \
+ cr-om-parser.h \
+ cr-style.c \
+ cr-style.h \
+ cr-sel-eng.c \
+ cr-sel-eng.h \
+ cr-fonts.c \
+ cr-fonts.h \
+ cr-prop-list.c \
+ cr-prop-list.h \
+ cr-parsing-location.c \
+ cr-parsing-location.h \
+ cr-string.c \
+ cr-string.h \
+ $(NULL)
+
+libcroco_0_6_la_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/intl \
+ -I$(top_builddir)/src \
+ $(AM_CPPFLAGS)
+
+libcroco_0_6_la_CFLAGS = \
+ $(CROCO_CFLAGS) \
+ $(AM_CFLAGS)
+
+libcroco_0_6_la_LDFLAGS = \
+ -version-info @LIBCROCO_VERSION_INFO@ \
+ $(no_undefined) \
+ $(BSYMBOLIC_LDFLAG) \
+ $(AM_LDFLAGS)
+
+libcroco_0_6_la_LIBADD = \
+ $(CROCO_LIBS)
+
+EXTRA_DIST = libcroco.symbols
+
+# MSVC Build Items
+
+MSVCPROJS = croco
+
+croco_FILES = $(libcroco_0_6_la_SOURCES)
+croco_EXCLUDES = dummy
+
+croco_HEADERS_DIR = $(crocoincdir)
+croco_HEADERS_INST = $(crocoinc_HEADERS)
+croco_HEADERS_EXCLUDES = dummy
+
+include $(top_srcdir)/win32/Makefile.msvcproj
+
+dist-hook: \
+ $(top_builddir)/win32/vs9/croco.vcproj \
+ $(top_builddir)/win32/vs9/croco.headers
diff --git a/src/3rdparty/libcroco/src/cr-additional-sel.c b/src/3rdparty/libcroco/src/cr-additional-sel.c
new file mode 100644
index 0000000..0296a6d
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-additional-sel.c
@@ -0,0 +1,456 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ *
+ */
+
+#include "cr-additional-sel.h"
+#include "string.h"
+
+/**
+ * CRAdditionalSel:
+ *
+ * #CRAdditionalSel abstracts an additional selector.
+ * An additional selector is the selector part
+ * that comes after the combination of type selectors.
+ * It can be either "a class selector (the .class part),
+ * a pseudo class selector, an attribute selector
+ * or an id selector.
+ */
+
+/**
+ * cr_additional_sel_new:
+ *
+ * Default constructor of #CRAdditionalSel.
+ * Returns the newly build instance of #CRAdditionalSel.
+ */
+CRAdditionalSel *
+cr_additional_sel_new (void)
+{
+ CRAdditionalSel *result = NULL;
+
+ result = g_try_malloc (sizeof (CRAdditionalSel));
+
+ if (result == NULL) {
+ cr_utils_trace_debug ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRAdditionalSel));
+
+ return result;
+}
+
+/**
+ * cr_additional_sel_new_with_type:
+ * @a_sel_type: the type of the newly built instance
+ * of #CRAdditionalSel.
+ *
+ * Constructor of #CRAdditionalSel.
+ * Returns the newly built instance of #CRAdditionalSel.
+ */
+CRAdditionalSel *
+cr_additional_sel_new_with_type (enum AddSelectorType a_sel_type)
+{
+ CRAdditionalSel *result = NULL;
+
+ result = cr_additional_sel_new ();
+
+ g_return_val_if_fail (result, NULL);
+
+ result->type = a_sel_type;
+
+ return result;
+}
+
+/**
+ * cr_additional_sel_set_class_name:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_class_name: the new class name to set.
+ *
+ * Sets a new class name to a
+ * CLASS additional selector.
+ */
+void
+cr_additional_sel_set_class_name (CRAdditionalSel * a_this,
+ CRString * a_class_name)
+{
+ g_return_if_fail (a_this && a_this->type == CLASS_ADD_SELECTOR);
+
+ if (a_this->content.class_name) {
+ cr_string_destroy (a_this->content.class_name);
+ }
+
+ a_this->content.class_name = a_class_name;
+}
+
+/**
+ * cr_additional_sel_set_id_name:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_id: the new id to set.
+ *
+ * Sets a new id name to an
+ * ID additional selector.
+ */
+void
+cr_additional_sel_set_id_name (CRAdditionalSel * a_this, CRString * a_id)
+{
+ g_return_if_fail (a_this && a_this->type == ID_ADD_SELECTOR);
+
+ if (a_this->content.id_name) {
+ cr_string_destroy (a_this->content.id_name);
+ }
+
+ a_this->content.id_name = a_id;
+}
+
+/**
+ * cr_additional_sel_set_pseudo:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_pseudo: the new pseudo to set.
+ *
+ * Sets a new pseudo to a
+ * PSEUDO additional selector.
+ */
+void
+cr_additional_sel_set_pseudo (CRAdditionalSel * a_this, CRPseudo * a_pseudo)
+{
+ g_return_if_fail (a_this
+ && a_this->type == PSEUDO_CLASS_ADD_SELECTOR);
+
+ if (a_this->content.pseudo) {
+ cr_pseudo_destroy (a_this->content.pseudo);
+ }
+
+ a_this->content.pseudo = a_pseudo;
+}
+
+/**
+ * cr_additional_sel_set_attr_sel:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_sel: the new instance of #CRAttrSel to set.
+ *
+ * Sets a new instance of #CRAttrSel to
+ * a ATTRIBUTE additional selector.
+ */
+void
+cr_additional_sel_set_attr_sel (CRAdditionalSel * a_this, CRAttrSel * a_sel)
+{
+ g_return_if_fail (a_this && a_this->type == ATTRIBUTE_ADD_SELECTOR);
+
+ if (a_this->content.attr_sel) {
+ cr_attr_sel_destroy (a_this->content.attr_sel);
+ }
+
+ a_this->content.attr_sel = a_sel;
+}
+
+/**
+ * cr_additional_sel_append:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_sel: the new instance to #CRAdditional to append.
+ *
+ * Appends a new instance of #CRAdditional to the
+ * current list of #CRAdditional.
+ *
+ * Returns the new list of CRAdditionalSel or NULL if an error arises.
+ */
+CRAdditionalSel *
+cr_additional_sel_append (CRAdditionalSel * a_this, CRAdditionalSel * a_sel)
+{
+ CRAdditionalSel *cur_sel = NULL;
+
+ g_return_val_if_fail (a_sel, NULL);
+
+ if (a_this == NULL) {
+ return a_sel;
+ }
+
+ if (a_sel == NULL)
+ return NULL;
+
+ for (cur_sel = a_this;
+ cur_sel && cur_sel->next; cur_sel = cur_sel->next) ;
+
+ g_return_val_if_fail (cur_sel != NULL, NULL);
+
+ cur_sel->next = a_sel;
+ a_sel->prev = cur_sel;
+
+ return a_this;
+}
+
+/**
+ * cr_additional_sel_prepend:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_sel: the new instance to #CRAdditional to preappend.
+ *
+ * Preppends a new instance of #CRAdditional to the
+ * current list of #CRAdditional.
+ *
+ * Returns the new list of CRAdditionalSel or NULL if an error arises.
+ */
+CRAdditionalSel *
+cr_additional_sel_prepend (CRAdditionalSel * a_this, CRAdditionalSel * a_sel)
+{
+ g_return_val_if_fail (a_sel, NULL);
+
+ if (a_this == NULL) {
+ return a_sel;
+ }
+
+ a_sel->next = a_this;
+ a_this->prev = a_sel;
+
+ return a_sel;
+}
+
+guchar *
+cr_additional_sel_to_string (CRAdditionalSel const * a_this)
+{
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+ CRAdditionalSel const *cur = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ switch (cur->type) {
+ case CLASS_ADD_SELECTOR:
+ {
+ if (cur->content.class_name) {
+ g_string_append_printf
+ (str_buf, ".%s",
+ cur->content.class_name->stryng->str);
+ }
+ }
+ break;
+
+ case ID_ADD_SELECTOR:
+ {
+ if (cur->content.id_name) {
+ g_string_append_printf
+ (str_buf, "#%s",
+ cur->content.id_name->stryng->str);
+ }
+ }
+
+ break;
+
+ case PSEUDO_CLASS_ADD_SELECTOR:
+ {
+ if (cur->content.pseudo) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_pseudo_to_string
+ (cur->content.pseudo);
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf, ":%s",
+ tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ }
+ break;
+
+ case ATTRIBUTE_ADD_SELECTOR:
+ if (cur->content.attr_sel) {
+ guchar *tmp_str = NULL;
+
+ g_string_append_c (str_buf, '[');
+ tmp_str = cr_attr_sel_to_string
+ (cur->content.attr_sel);
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf, "%s]", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+guchar *
+cr_additional_sel_one_to_string (CRAdditionalSel const *a_this)
+{
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+
+ g_return_val_if_fail (a_this, NULL) ;
+
+ str_buf = g_string_new (NULL) ;
+
+ switch (a_this->type) {
+ case CLASS_ADD_SELECTOR:
+ if (a_this->content.class_name) {
+ g_string_append_printf
+ (str_buf, ".%s",
+ a_this->content.class_name->stryng->str);
+ }
+ break;
+
+ case ID_ADD_SELECTOR:
+ if (a_this->content.id_name) {
+ g_string_append_printf
+ (str_buf, "#%s",
+ a_this->content.id_name->stryng->str);
+ }
+
+ break;
+
+ case PSEUDO_CLASS_ADD_SELECTOR:
+ {
+ if (a_this->content.pseudo) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_pseudo_to_string
+ (a_this->content.pseudo);
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf, ":%s",
+ tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ }
+ break;
+
+ case ATTRIBUTE_ADD_SELECTOR:
+ if (a_this->content.attr_sel) {
+ guchar *tmp_str = NULL;
+
+ g_string_append_printf (str_buf, "[");
+ tmp_str = cr_attr_sel_to_string
+ (a_this->content.attr_sel);
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf, "%s]", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_additional_sel_dump:
+ * @a_this: the "this pointer" of the current instance of
+ * #CRAdditionalSel.
+ * @a_fp: the destination file.
+ *
+ * Dumps the current instance of #CRAdditionalSel to a file
+ */
+void
+cr_additional_sel_dump (CRAdditionalSel const * a_this, FILE * a_fp)
+{
+ guchar *tmp_str = NULL;
+
+ g_return_if_fail (a_fp);
+
+ if (a_this) {
+ tmp_str = cr_additional_sel_to_string (a_this);
+ if (tmp_str) {
+ fprintf (a_fp, "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+}
+
+/**
+ * cr_additional_sel_destroy:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ *
+ * Destroys an instance of #CRAdditional.
+ */
+void
+cr_additional_sel_destroy (CRAdditionalSel * a_this)
+{
+ g_return_if_fail (a_this);
+
+ switch (a_this->type) {
+ case CLASS_ADD_SELECTOR:
+ cr_string_destroy (a_this->content.class_name);
+ a_this->content.class_name = NULL;
+ break;
+
+ case PSEUDO_CLASS_ADD_SELECTOR:
+ cr_pseudo_destroy (a_this->content.pseudo);
+ a_this->content.pseudo = NULL;
+ break;
+
+ case ID_ADD_SELECTOR:
+ cr_string_destroy (a_this->content.id_name);
+ a_this->content.id_name = NULL;
+ break;
+
+ case ATTRIBUTE_ADD_SELECTOR:
+ cr_attr_sel_destroy (a_this->content.attr_sel);
+ a_this->content.attr_sel = NULL;
+ break;
+
+ default:
+ break;
+ }
+
+ if (a_this->next) {
+ cr_additional_sel_destroy (a_this->next);
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-additional-sel.h b/src/3rdparty/libcroco/src/cr-additional-sel.h
new file mode 100644
index 0000000..7ca3e07
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-additional-sel.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See the COPYRIGHTS file for copyright information.
+ */
+
+
+#ifndef __CR_ADD_SEL_H__
+#define __CR_ADD_SEL_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-attr-sel.h"
+#include "cr-pseudo.h"
+#include "cr-additional-sel.h"
+
+G_BEGIN_DECLS
+
+enum AddSelectorType
+{
+ NO_ADD_SELECTOR = 0 ,
+ CLASS_ADD_SELECTOR = 1 ,
+ PSEUDO_CLASS_ADD_SELECTOR = 1 << 1,
+ ID_ADD_SELECTOR = 1 << 3,
+ ATTRIBUTE_ADD_SELECTOR = 1 << 4
+} ;
+
+union CRAdditionalSelectorContent
+{
+ CRString *class_name ;
+ CRString *id_name ;
+ CRPseudo *pseudo ;
+ CRAttrSel *attr_sel ;
+} ;
+
+typedef struct _CRAdditionalSel CRAdditionalSel ;
+
+struct _CRAdditionalSel
+{
+ enum AddSelectorType type ;
+ union CRAdditionalSelectorContent content ;
+
+ CRAdditionalSel * next ;
+ CRAdditionalSel * prev ;
+ CRParsingLocation location ;
+} ;
+
+CRAdditionalSel * cr_additional_sel_new (void) ;
+
+CRAdditionalSel * cr_additional_sel_new_with_type (enum AddSelectorType a_sel_type) ;
+
+CRAdditionalSel * cr_additional_sel_append (CRAdditionalSel *a_this,
+ CRAdditionalSel *a_sel) ;
+
+void cr_additional_sel_set_class_name (CRAdditionalSel *a_this,
+ CRString *a_class_name) ;
+
+void cr_additional_sel_set_id_name (CRAdditionalSel *a_this,
+ CRString *a_id) ;
+
+void cr_additional_sel_set_pseudo (CRAdditionalSel *a_this,
+ CRPseudo *a_pseudo) ;
+
+void cr_additional_sel_set_attr_sel (CRAdditionalSel *a_this,
+ CRAttrSel *a_sel) ;
+
+CRAdditionalSel * cr_additional_sel_prepend (CRAdditionalSel *a_this,
+ CRAdditionalSel *a_sel) ;
+
+guchar * cr_additional_sel_to_string (CRAdditionalSel const *a_this) ;
+
+guchar * cr_additional_sel_one_to_string (CRAdditionalSel const *a_this) ;
+
+void cr_additional_sel_dump (CRAdditionalSel const *a_this, FILE *a_fp) ;
+
+void cr_additional_sel_destroy (CRAdditionalSel *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_ADD_SEL_H*/
diff --git a/src/3rdparty/libcroco/src/cr-attr-sel.c b/src/3rdparty/libcroco/src/cr-attr-sel.c
new file mode 100644
index 0000000..b4c64c3
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-attr-sel.c
@@ -0,0 +1,221 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#include <stdio.h>
+#include "cr-attr-sel.h"
+
+/**
+ * CRAttrSel:
+ *
+ * #CRAdditionalSel abstracts an attribute selector.
+ * Attributes selectors are described in the css2 spec [5.8].
+ * There are more generally used in the css2 selectors described in
+ * css2 spec [5] .
+ */
+
+/**
+ * cr_attr_sel_new:
+ * The constructor of #CRAttrSel.
+ * Returns the newly allocated instance
+ * of #CRAttrSel.
+ */
+CRAttrSel *
+cr_attr_sel_new (void)
+{
+ CRAttrSel *result = NULL;
+
+ result = g_malloc0 (sizeof (CRAttrSel));
+
+ return result;
+}
+
+/**
+ * cr_attr_sel_append_attr_sel:
+ * @a_this: the this pointer of the current instance of #CRAttrSel.
+ * @a_attr_sel: selector to append.
+ *
+ * Appends an attribute selector to the current list of
+ * attribute selectors represented by a_this.
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_attr_sel_append_attr_sel (CRAttrSel * a_this, CRAttrSel * a_attr_sel)
+{
+ CRAttrSel *cur_sel = NULL;
+
+ g_return_val_if_fail (a_this && a_attr_sel,
+ CR_BAD_PARAM_ERROR);
+
+ for (cur_sel = a_this;
+ cur_sel->next;
+ cur_sel = cur_sel->next) ;
+
+ cur_sel->next = a_attr_sel;
+ a_attr_sel->prev = cur_sel;
+
+ return CR_OK;
+}
+
+/**
+ * cr_attr_sel_prepend_attr_sel:
+ *@a_this: the "this pointer" of the current instance *of #CRAttrSel.
+ *@a_attr_sel: the attribute selector to append.
+ *
+ *Prepends an attribute selector to the list of
+ *attributes selector represented by a_this.
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_attr_sel_prepend_attr_sel (CRAttrSel * a_this,
+ CRAttrSel * a_attr_sel)
+{
+ g_return_val_if_fail (a_this && a_attr_sel,
+ CR_BAD_PARAM_ERROR);
+
+ a_attr_sel->next = a_this;
+ a_this->prev = a_attr_sel;
+
+ return CR_OK;
+}
+
+/**
+ * cr_attr_sel_to_string:
+ * @a_this: the current instance of #CRAttrSel.
+ *
+ * Serializes an attribute selector into a string
+ * Returns the serialized attribute selector.
+ */
+guchar *
+cr_attr_sel_to_string (CRAttrSel const * a_this)
+{
+ CRAttrSel const *cur = NULL;
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ if (cur->prev) {
+ g_string_append_c (str_buf, ' ');
+ }
+
+ if (cur->name) {
+ gchar const *name = cur->name->stryng->str;
+ if (name) {
+ g_string_append (str_buf, (const gchar *) name);
+ }
+ }
+
+ if (cur->value) {
+ gchar const *value = cur->value->stryng->str;
+ if (value) {
+ switch (cur->match_way) {
+ case SET:
+ break;
+
+ case EQUALS:
+ g_string_append_c (str_buf, '=');
+ break;
+
+ case INCLUDES:
+ g_string_append (str_buf, "~=");
+ break;
+
+ case DASHMATCH:
+ g_string_append (str_buf, "|=");
+ break;
+
+ default:
+ break;
+ }
+
+ g_string_append_printf
+ (str_buf, "\"%s\"", value);
+ }
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ }
+
+ return result;
+}
+
+/**
+ * cr_attr_sel_dump:
+ * @a_this: the "this pointer" of the current instance of
+ * #CRAttrSel.
+ * @a_fp: the destination file.
+ *
+ * Dumps the current instance of #CRAttrSel to a file.
+ */
+void
+cr_attr_sel_dump (CRAttrSel const * a_this, FILE * a_fp)
+{
+ guchar *tmp_str = NULL;
+
+ g_return_if_fail (a_this);
+
+ tmp_str = cr_attr_sel_to_string (a_this);
+
+ if (tmp_str) {
+ fprintf (a_fp, "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+}
+
+/**
+ *cr_attr_sel_destroy:
+ *@a_this: the "this pointer" of the current
+ *instance of #CRAttrSel.
+ *
+ *Destroys the current instance of #CRAttrSel.
+ *Frees all the fields if they are non null.
+ */
+void
+cr_attr_sel_destroy (CRAttrSel * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->name) {
+ cr_string_destroy (a_this->name);
+ a_this->name = NULL;
+ }
+
+ if (a_this->value) {
+ cr_string_destroy (a_this->value);
+ a_this->value = NULL;
+ }
+
+ if (a_this->next) {
+ cr_attr_sel_destroy (a_this->next);
+ a_this->next = NULL;
+ }
+
+ g_free (a_this);
+}
+
diff --git a/src/3rdparty/libcroco/src/cr-attr-sel.h b/src/3rdparty/libcroco/src/cr-attr-sel.h
new file mode 100644
index 0000000..82d5a87
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-attr-sel.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_ATTR_SEL_H__
+#define __CR_ATTR_SEL_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-parsing-location.h"
+#include "cr-string.h"
+
+G_BEGIN_DECLS
+
+
+struct _CRAttrSel ;
+typedef struct _CRAttrSel CRAttrSel ;
+
+enum AttrMatchWay
+{
+ NO_MATCH = 0,
+ SET,
+ EQUALS,
+ INCLUDES,
+ DASHMATCH
+} ;
+
+struct _CRAttrSel
+{
+ CRString *name ;
+ CRString *value ;
+ enum AttrMatchWay match_way ;
+ CRAttrSel *next ;
+ CRAttrSel *prev ;
+ CRParsingLocation location ;
+} ;
+
+CRAttrSel * cr_attr_sel_new (void) ;
+
+enum CRStatus cr_attr_sel_append_attr_sel (CRAttrSel * a_this,
+ CRAttrSel *a_attr_sel) ;
+
+enum CRStatus cr_attr_sel_prepend_attr_sel (CRAttrSel *a_this,
+ CRAttrSel *a_attr_sel) ;
+
+guchar * cr_attr_sel_to_string (CRAttrSel const *a_this) ;
+
+void cr_attr_sel_dump (CRAttrSel const *a_this, FILE *a_fp) ;
+
+void cr_attr_sel_destroy (CRAttrSel *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_ATTR_SEL_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-cascade.c b/src/3rdparty/libcroco/src/cr-cascade.c
new file mode 100644
index 0000000..3f32a51
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-cascade.c
@@ -0,0 +1,214 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the
+ * GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+#include <string.h>
+#include "cr-cascade.h"
+
+#define PRIVATE(a_this) ((a_this)->priv)
+
+struct _CRCascadePriv {
+ /**
+ *the 3 style sheets of the cascade:
+ *author, user, and useragent sheet.
+ *Intended to be addressed by
+ *sheets[ORIGIN_AUTHOR] or sheets[ORIGIN_USER]
+ *of sheets[ORIGIN_UA] ;
+ */
+ CRStyleSheet *sheets[3];
+ guint ref_count;
+};
+
+/**
+ * cr_cascade_new:
+ *@a_author_sheet: the author origin style sheet. May be NULL.
+ *@a_user_sheet: the user origin style sheet. May be NULL.
+ *@a_ua_sheet: the user agent origin style sheet. May be NULL.
+ *
+ *Constructor of the #CRCascade class.
+ *Note that all three parameters of this
+ *method are ref counted and their refcount is increased.
+ *Their refcount will be decreased at the destruction of
+ *the instance of #CRCascade.
+ *So the caller should not call their destructor. The caller
+ *should call their ref/unref method instead if it wants
+ *
+ *Returns the newly built instance of CRCascade or NULL if
+ *an error arose during construction.
+ */
+CRCascade *
+cr_cascade_new (CRStyleSheet * a_author_sheet,
+ CRStyleSheet * a_user_sheet, CRStyleSheet * a_ua_sheet)
+{
+ CRCascade *result = NULL;
+
+ result = g_try_malloc (sizeof (CRCascade));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRCascade));
+
+ PRIVATE (result) = g_try_malloc (sizeof (CRCascadePriv));
+ if (!PRIVATE (result)) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (PRIVATE (result), 0, sizeof (CRCascadePriv));
+
+ if (a_author_sheet) {
+ cr_cascade_set_sheet (result, a_author_sheet, ORIGIN_AUTHOR);
+ }
+ if (a_user_sheet) {
+ cr_cascade_set_sheet (result, a_user_sheet, ORIGIN_USER);
+ }
+ if (a_ua_sheet) {
+ cr_cascade_set_sheet (result, a_ua_sheet, ORIGIN_UA);
+ }
+
+ return result;
+}
+
+/**
+ * cr_cascade_get_sheet:
+ *@a_this: the current instance of #CRCascade.
+ *@a_origin: the origin of the style sheet as
+ *defined in the css2 spec in chapter 6.4.
+ *Gets a given origin sheet.
+ *
+ *Gets a sheet, part of the cascade.
+ *Note that the returned stylesheet
+ *is refcounted so if the caller wants
+ *to manage its lifecycle, it must use
+ *cr_stylesheet_ref()/cr_stylesheet_unref() instead
+ *of the cr_stylesheet_destroy() method.
+ *Returns the style sheet, or NULL if it does not
+ *exist.
+ */
+CRStyleSheet *
+cr_cascade_get_sheet (CRCascade * a_this, enum CRStyleOrigin a_origin)
+{
+ g_return_val_if_fail (a_this
+ && (unsigned)a_origin < NB_ORIGINS, NULL);
+
+ return PRIVATE (a_this)->sheets[a_origin];
+}
+
+/**
+ * cr_cascade_set_sheet:
+ *@a_this: the current instance of #CRCascade.
+ *@a_sheet: the stylesheet to set. May be NULL.
+ *@a_origin: the origin of the stylesheet.
+ *
+ *Sets a stylesheet in the cascade
+ *
+ *Returns CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_cascade_set_sheet (CRCascade * a_this,
+ CRStyleSheet * a_sheet, enum CRStyleOrigin a_origin)
+{
+ g_return_val_if_fail (a_this
+ && (unsigned)a_origin < NB_ORIGINS, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->sheets[a_origin])
+ cr_stylesheet_unref (PRIVATE (a_this)->sheets[a_origin]);
+ PRIVATE (a_this)->sheets[a_origin] = a_sheet;
+ if (a_sheet) {
+ cr_stylesheet_ref (a_sheet);
+ a_sheet->origin = a_origin;
+ }
+ return CR_OK;
+}
+
+/**
+ *cr_cascade_ref:
+ *@a_this: the current instance of #CRCascade
+ *
+ *Increases the reference counter of the current instance
+ *of #CRCascade.
+ */
+void
+cr_cascade_ref (CRCascade * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ PRIVATE (a_this)->ref_count++;
+}
+
+/**
+ * cr_cascade_unref:
+ *@a_this: the current instance of
+ *#CRCascade.
+ *
+ *Decrements the reference counter associated
+ *to this instance of #CRCascade. If the reference
+ *counter reaches zero, the instance is destroyed
+ *using cr_cascade_destroy()
+ */
+void
+cr_cascade_unref (CRCascade * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ if (PRIVATE (a_this)->ref_count)
+ PRIVATE (a_this)->ref_count--;
+ if (!PRIVATE (a_this)->ref_count) {
+ cr_cascade_destroy (a_this);
+ }
+}
+
+/**
+ * cr_cascade_destroy:
+ * @a_this: the current instance of #CRCascade
+ *
+ * Destructor of #CRCascade.
+ */
+void
+cr_cascade_destroy (CRCascade * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (PRIVATE (a_this)) {
+ gulong i = 0;
+
+ for (i = 0; i < NB_ORIGINS; i++) {
+ if (PRIVATE (a_this)->sheets[i]) {
+ if (cr_stylesheet_unref
+ (PRIVATE (a_this)->sheets[i])
+ == TRUE) {
+ PRIVATE (a_this)->sheets[i] = NULL;
+ }
+ }
+ }
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ }
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-cascade.h b/src/3rdparty/libcroco/src/cr-cascade.h
new file mode 100644
index 0000000..3119ae8
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-cascade.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the
+ * GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ */
+
+/*
+ *$Id$
+ */
+
+#ifndef __CR_CASCADE_H__
+#define __CR_CASCADE_H__
+
+#include "cr-stylesheet.h"
+
+/**
+ *@file
+ *the declaration of the #CRCascade class.
+ */
+
+G_BEGIN_DECLS
+
+
+typedef struct _CRCascadePriv CRCascadePriv ;
+
+/**
+ *An abstraction of the "Cascade" defined
+ *in the css2 spec, chapter 6.4.
+ */
+typedef struct _CRCascade CRCascade ;
+
+struct _CRCascade
+{
+ CRCascadePriv *priv ;
+};
+
+
+CRCascade * cr_cascade_new (CRStyleSheet *a_author_sheet,
+ CRStyleSheet *a_user_sheet,
+ CRStyleSheet *a_ua_sheet) ;
+
+CRStyleSheet * cr_cascade_get_sheet (CRCascade *a_this,
+ enum CRStyleOrigin a_origin) ;
+
+enum CRStatus cr_cascade_set_sheet (CRCascade *a_this,
+ CRStyleSheet *a_sheet,
+ enum CRStyleOrigin a_origin) ;
+
+void cr_cascade_ref (CRCascade *a_this) ;
+
+void cr_cascade_unref (CRCascade *a_this) ;
+
+void cr_cascade_destroy (CRCascade *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_CASCADE_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-declaration.c b/src/3rdparty/libcroco/src/cr-declaration.c
new file mode 100644
index 0000000..f998a2a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-declaration.c
@@ -0,0 +1,794 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See COPYRIGHTS file for copyright information.
+ */
+
+
+#include <string.h>
+#include "cr-declaration.h"
+#include "cr-statement.h"
+#include "cr-parser.h"
+
+/**
+ *@CRDeclaration:
+ *
+ *The definition of the #CRDeclaration class.
+ */
+
+/**
+ * dump:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of indentation white char.
+ *
+ *Dumps (serializes) one css declaration to a file.
+ */
+static void
+dump (CRDeclaration const * a_this, FILE * a_fp, glong a_indent)
+{
+ guchar *str = NULL;
+
+ g_return_if_fail (a_this);
+
+ str = (guchar *) cr_declaration_to_string (a_this, a_indent);
+ if (str) {
+ fprintf (a_fp, "%s", str);
+ g_free (str);
+ str = NULL;
+ }
+}
+
+/**
+ * cr_declaration_new:
+ * @a_statement: the statement this declaration belongs to. can be NULL.
+ *@a_property: the property string of the declaration
+ *@a_value: the value expression of the declaration.
+ *Constructor of #CRDeclaration.
+ *
+ *Returns the newly built instance of #CRDeclaration, or NULL in
+ *case of error.
+ *
+ *The returned CRDeclaration takes ownership of @a_property and @a_value.
+ *(E.g. cr_declaration_destroy on this CRDeclaration will also free
+ *@a_property and @a_value.)
+ */
+CRDeclaration *
+cr_declaration_new (CRStatement * a_statement,
+ CRString * a_property, CRTerm * a_value)
+{
+ CRDeclaration *result = NULL;
+
+ g_return_val_if_fail (a_property, NULL);
+
+ if (a_statement)
+ g_return_val_if_fail (a_statement
+ && ((a_statement->type == RULESET_STMT)
+ || (a_statement->type
+ == AT_FONT_FACE_RULE_STMT)
+ || (a_statement->type
+ == AT_PAGE_RULE_STMT)), NULL);
+
+ result = g_try_malloc (sizeof (CRDeclaration));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRDeclaration));
+ result->property = a_property;
+ result->value = a_value;
+
+ if (a_value) {
+ cr_term_ref (a_value);
+ }
+ result->parent_statement = a_statement;
+ return result;
+}
+
+/**
+ * cr_declaration_parse_from_buf:
+ *@a_statement: the parent css2 statement of this
+ *this declaration. Must be non NULL and of type
+ *RULESET_STMT (must be a ruleset).
+ *@a_str: the string that contains the statement.
+ *@a_enc: the encoding of a_str.
+ *
+ *Parses a text buffer that contains
+ *a css declaration.
+ *Returns the parsed declaration, or NULL in case of error.
+ */
+CRDeclaration *
+cr_declaration_parse_from_buf (CRStatement * a_statement,
+ const guchar * a_str, enum CREncoding a_enc)
+{
+ enum CRStatus status = CR_OK;
+ CRTerm *value = NULL;
+ CRString *property = NULL;
+ CRDeclaration *result = NULL;
+ CRParser *parser = NULL;
+ gboolean important = FALSE;
+
+ g_return_val_if_fail (a_str, NULL);
+ if (a_statement)
+ g_return_val_if_fail (a_statement->type == RULESET_STMT,
+ NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_str, strlen ((const char *) a_str), a_enc, FALSE);
+ g_return_val_if_fail (parser, NULL);
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_parse_declaration (parser, &property,
+ &value, &important);
+ if (status != CR_OK || !property)
+ goto cleanup;
+
+ result = cr_declaration_new (a_statement, property, value);
+ if (result) {
+ property = NULL;
+ value = NULL;
+ result->important = important;
+ }
+
+ cleanup:
+
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+
+ if (value) {
+ cr_term_destroy (value);
+ value = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_declaration_parse_list_from_buf:
+ *@a_str: the input buffer that contains the list of declaration to
+ *parse.
+ *@a_enc: the encoding of a_str
+ *
+ *Parses a ';' separated list of properties declaration.
+ *Returns the parsed list of declaration, NULL if parsing failed.
+ */
+CRDeclaration *
+cr_declaration_parse_list_from_buf (const guchar * a_str,
+ enum CREncoding a_enc)
+{
+
+ enum CRStatus status = CR_OK;
+ CRTerm *value = NULL;
+ CRString *property = NULL;
+ CRDeclaration *result = NULL,
+ *cur_decl = NULL;
+ CRParser *parser = NULL;
+ CRTknzr *tokenizer = NULL;
+ gboolean important = FALSE;
+ gboolean first = TRUE;
+
+ g_return_val_if_fail (a_str, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_str, strlen ((const char *) a_str), a_enc, FALSE);
+ g_return_val_if_fail (parser, NULL);
+ status = cr_parser_get_tknzr (parser, &tokenizer);
+ if (status != CR_OK || !tokenizer) {
+ if (status == CR_OK)
+ status = CR_ERROR;
+ goto cleanup;
+ }
+
+ for (;; first = FALSE) {
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ if (!first) {
+ guint32 c = 0;
+
+ status = cr_tknzr_peek_char (tokenizer, &c);
+ if (status != CR_OK) {
+ goto cleanup;
+ }
+ if (c == ';') {
+ status = cr_tknzr_read_char (tokenizer, &c);
+ } else {
+ cr_tknzr_read_char (tokenizer, &c);
+ continue; // try to keep reading until we reach the end or a ;
+ }
+ important = FALSE;
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+ }
+
+ status = cr_parser_parse_declaration (parser, &property,
+ &value, &important);
+ if (status != CR_OK || !property) {
+ if (status == CR_END_OF_INPUT_ERROR) {
+ break;
+ } else {
+ continue; // even if one declaration is broken, it's no reason to discard others (see http://www.w3.org/TR/CSS21/syndata.html#declaration)
+ }
+ }
+ cur_decl = cr_declaration_new (NULL, property, value);
+ if (cur_decl) {
+ cur_decl->important = important;
+ if (result) {
+ result = cr_declaration_append (result, cur_decl);
+ } else {
+ result = cur_decl;
+ }
+ property = NULL;
+ value = NULL;
+ cur_decl = NULL;
+ } else {
+ break;
+ }
+ }
+
+ cleanup:
+
+ if (status == CR_END_OF_INPUT_ERROR && result) {
+ status = CR_OK;
+ }
+
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+
+ if (value) {
+ cr_term_destroy (value);
+ value = NULL;
+ }
+
+ if (status != CR_OK && result) {
+ cr_declaration_destroy (result);
+ result = NULL;
+ }
+ return result;
+}
+
+/**
+ * cr_declaration_append:
+ *@a_this: the current declaration list.
+ *@a_new: the declaration to append.
+ *
+ *Appends a new declaration to the current declarations list.
+ *Returns the declaration list with a_new appended to it, or NULL
+ *in case of error.
+ */
+CRDeclaration *
+cr_declaration_append (CRDeclaration * a_this, CRDeclaration * a_new)
+{
+ CRDeclaration *cur = NULL;
+
+ g_return_val_if_fail (a_new, NULL);
+
+ if (!a_this)
+ return a_new;
+
+ for (cur = a_this; cur && cur->next; cur = cur->next) ;
+
+ cur->next = a_new;
+ a_new->prev = cur;
+
+ return a_this;
+}
+
+/**
+ * cr_declaration_unlink:
+ *@a_decls: the declaration to unlink.
+ *
+ *Unlinks the declaration from the declaration list.
+ *case of a successful completion, NULL otherwise.
+ *
+ *Returns a pointer to the unlinked declaration in
+ */
+CRDeclaration *
+cr_declaration_unlink (CRDeclaration * a_decl)
+{
+ CRDeclaration *result = a_decl;
+
+ g_return_val_if_fail (result, NULL);
+
+ /*
+ *some sanity checks first
+ */
+ if (a_decl->prev) {
+ g_return_val_if_fail (a_decl->prev->next == a_decl, NULL);
+
+ }
+ if (a_decl->next) {
+ g_return_val_if_fail (a_decl->next->prev == a_decl, NULL);
+ }
+
+ /*
+ *now, the real unlinking job.
+ */
+ if (a_decl->prev) {
+ a_decl->prev->next = a_decl->next;
+ }
+ if (a_decl->next) {
+ a_decl->next->prev = a_decl->prev;
+ }
+ if (a_decl->parent_statement) {
+ CRDeclaration **children_decl_ptr = NULL;
+
+ switch (a_decl->parent_statement->type) {
+ case RULESET_STMT:
+ if (a_decl->parent_statement->kind.ruleset) {
+ children_decl_ptr =
+ &a_decl->parent_statement->
+ kind.ruleset->decl_list;
+ }
+
+ break;
+
+ case AT_FONT_FACE_RULE_STMT:
+ if (a_decl->parent_statement->kind.font_face_rule) {
+ children_decl_ptr =
+ &a_decl->parent_statement->
+ kind.font_face_rule->decl_list;
+ }
+ break;
+ case AT_PAGE_RULE_STMT:
+ if (a_decl->parent_statement->kind.page_rule) {
+ children_decl_ptr =
+ &a_decl->parent_statement->
+ kind.page_rule->decl_list;
+ }
+
+ default:
+ break;
+ }
+ if (children_decl_ptr
+ && *children_decl_ptr && *children_decl_ptr == a_decl)
+ *children_decl_ptr = (*children_decl_ptr)->next;
+ }
+
+ a_decl->next = NULL;
+ a_decl->prev = NULL;
+ a_decl->parent_statement = NULL;
+
+ return result;
+}
+
+/**
+ * cr_declaration_prepend:
+ * @a_this: the current declaration list.
+ * @a_new: the declaration to prepend.
+ *
+ * prepends a declaration to the current declaration list.
+ *
+ * Returns the list with a_new prepended or NULL in case of error.
+ */
+CRDeclaration *
+cr_declaration_prepend (CRDeclaration * a_this, CRDeclaration * a_new)
+{
+ CRDeclaration *cur = NULL;
+
+ g_return_val_if_fail (a_new, NULL);
+
+ if (!a_this)
+ return a_new;
+
+ a_this->prev = a_new;
+ a_new->next = a_this;
+
+ for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
+
+ return cur;
+}
+
+/**
+ * cr_declaration_append2:
+ *@a_this: the current declaration list.
+ *@a_prop: the property string of the declaration to append.
+ *@a_value: the value of the declaration to append.
+ *
+ *Appends a declaration to the current declaration list.
+ *Returns the list with the new property appended to it, or NULL in
+ *case of an error.
+ */
+CRDeclaration *
+cr_declaration_append2 (CRDeclaration * a_this,
+ CRString * a_prop, CRTerm * a_value)
+{
+ CRDeclaration *new_elem = NULL;
+
+ if (a_this) {
+ new_elem = cr_declaration_new (a_this->parent_statement,
+ a_prop, a_value);
+ } else {
+ new_elem = cr_declaration_new (NULL, a_prop, a_value);
+ }
+
+ g_return_val_if_fail (new_elem, NULL);
+
+ return cr_declaration_append (a_this, new_elem);
+}
+
+/**
+ * cr_declaration_dump:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_fp: the destination file.
+ *@a_indent: the number of indentation white char.
+ *@a_one_per_line: whether to put one declaration per line of not .
+ *
+ *
+ *Dumps a declaration list to a file.
+ */
+void
+cr_declaration_dump (CRDeclaration const * a_this, FILE * a_fp, glong a_indent,
+ gboolean a_one_per_line)
+{
+ CRDeclaration const *cur = NULL;
+
+ g_return_if_fail (a_this);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ if (cur->prev) {
+ if (a_one_per_line == TRUE)
+ fprintf (a_fp, ";\n");
+ else
+ fprintf (a_fp, "; ");
+ }
+ dump (cur, a_fp, a_indent);
+ }
+}
+
+/**
+ * cr_declaration_dump_one:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_fp: the destination file.
+ *@a_indent: the number of indentation white char.
+ *
+ *Dumps the first declaration of the declaration list to a file.
+ */
+void
+cr_declaration_dump_one (CRDeclaration const * a_this, FILE * a_fp, glong a_indent)
+{
+ g_return_if_fail (a_this);
+
+ dump (a_this, a_fp, a_indent);
+}
+
+/**
+ * cr_declaration_to_string:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_indent: the number of indentation white char
+ *to put before the actual serialisation.
+ *
+ *Serializes the declaration into a string
+ *Returns the serialized form the declaration. The caller must
+ *free the string using g_free().
+ */
+gchar *
+cr_declaration_to_string (CRDeclaration const * a_this, gulong a_indent)
+{
+ GString *stringue = NULL;
+
+ gchar *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ stringue = g_string_new (NULL);
+
+ if (a_this->property
+ && a_this->property->stryng
+ && a_this->property->stryng->str) {
+ gchar const *str = a_this->property->stryng->str;
+ if (str) {
+ cr_utils_dump_n_chars2 (' ', stringue,
+ a_indent);
+ g_string_append (stringue, str);
+ } else
+ goto error;
+
+ if (a_this->value) {
+ guchar *value_str = NULL;
+
+ value_str = cr_term_to_string (a_this->value);
+ if (value_str) {
+ g_string_append_printf (stringue, " : %s",
+ value_str);
+ g_free (value_str);
+ } else
+ goto error;
+ }
+ if (a_this->important == TRUE) {
+ g_string_append_printf (stringue, " %s",
+ "!important");
+ }
+ }
+ if (stringue && stringue->str) {
+ result = stringue->str;
+ g_string_free (stringue, FALSE);
+ }
+ return result;
+
+ error:
+ if (stringue) {
+ g_string_free (stringue, TRUE);
+ stringue = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_declaration_list_to_string:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_indent: the number of indentation white char
+ *to put before the actual serialisation.
+ *
+ *Serializes the declaration list into a string
+ */
+guchar *
+cr_declaration_list_to_string (CRDeclaration const * a_this, gulong a_indent)
+{
+ CRDeclaration const *cur = NULL;
+ GString *stringue = NULL;
+ guchar *str = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ stringue = g_string_new (NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ str = (guchar *) cr_declaration_to_string (cur, a_indent);
+ if (str) {
+ g_string_append_printf (stringue, "%s;", str);
+ g_free (str);
+ } else
+ break;
+ }
+ if (stringue && stringue->str) {
+ result = (guchar *) stringue->str;
+ g_string_free (stringue, FALSE);
+ }
+
+ return result;
+}
+
+/**
+ * cr_declaration_list_to_string2:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_indent: the number of indentation white char
+ *@a_one_decl_per_line: whether to output one doc per line or not.
+ *to put before the actual serialisation.
+ *
+ *Serializes the declaration list into a string
+ *Returns the serialized form the declararation.
+ */
+guchar *
+cr_declaration_list_to_string2 (CRDeclaration const * a_this,
+ gulong a_indent, gboolean a_one_decl_per_line)
+{
+ CRDeclaration const *cur = NULL;
+ GString *stringue = NULL;
+ guchar *str = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ stringue = g_string_new (NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ str = (guchar *) cr_declaration_to_string (cur, a_indent);
+ if (str) {
+ if (a_one_decl_per_line == TRUE) {
+ if (cur->next)
+ g_string_append_printf (stringue,
+ "%s;\n", str);
+ else
+ g_string_append (stringue,
+ (const gchar *) str);
+ } else {
+ if (cur->next)
+ g_string_append_printf (stringue,
+ "%s;", str);
+ else
+ g_string_append (stringue,
+ (const gchar *) str);
+ }
+ g_free (str);
+ } else
+ break;
+ }
+ if (stringue && stringue->str) {
+ result = (guchar *) stringue->str;
+ g_string_free (stringue, FALSE);
+ }
+
+ return result;
+}
+
+/**
+ * cr_declaration_nr_props:
+ *@a_this: the current instance of #CRDeclaration.
+ *Return the number of properties in the declaration
+ */
+gint
+cr_declaration_nr_props (CRDeclaration const * a_this)
+{
+ CRDeclaration const *cur = NULL;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, -1);
+
+ for (cur = a_this; cur; cur = cur->next)
+ nr++;
+ return nr;
+}
+
+/**
+ * cr_declaration_get_from_list:
+ *@a_this: the current instance of #CRDeclaration.
+ *@itemnr: the index into the declaration list.
+ *
+ *Use an index to get a CRDeclaration from the declaration list.
+ *
+ *Returns #CRDeclaration at position itemnr,
+ *if itemnr > number of declarations - 1,
+ *it will return NULL.
+ */
+CRDeclaration *
+cr_declaration_get_from_list (CRDeclaration * a_this, int itemnr)
+{
+ CRDeclaration *cur = NULL;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ for (cur = a_this; cur; cur = cur->next)
+ if (nr++ == itemnr)
+ return cur;
+ return NULL;
+}
+
+/**
+ * cr_declaration_get_by_prop_name:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_prop: the property name to search for.
+ *
+ *Use property name to get a CRDeclaration from the declaration list.
+ *Returns #CRDeclaration with property name a_prop, or NULL if not found.
+ */
+CRDeclaration *
+cr_declaration_get_by_prop_name (CRDeclaration * a_this,
+ const guchar * a_prop)
+{
+ CRDeclaration *cur = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+ g_return_val_if_fail (a_prop, NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ if (cur->property
+ && cur->property->stryng
+ && cur->property->stryng->str) {
+ if (!strcmp (cur->property->stryng->str,
+ (const char *) a_prop)) {
+ return cur;
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * cr_declaration_ref:
+ *@a_this: the current instance of #CRDeclaration.
+ *
+ *Increases the ref count of the current instance of #CRDeclaration.
+ */
+void
+cr_declaration_ref (CRDeclaration * a_this)
+{
+ g_return_if_fail (a_this);
+
+ a_this->ref_count++;
+}
+
+/**
+ * cr_declaration_unref:
+ *@a_this: the current instance of #CRDeclaration.
+ *
+ *Decrements the ref count of the current instance of #CRDeclaration.
+ *If the ref count reaches zero, the current instance of #CRDeclaration
+ *if destroyed.
+ *Returns TRUE if @a_this was destroyed (ref count reached zero),
+ *FALSE otherwise.
+ */
+gboolean
+cr_declaration_unref (CRDeclaration * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->ref_count) {
+ a_this->ref_count--;
+ }
+
+ if (a_this->ref_count == 0) {
+ cr_declaration_destroy (a_this);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * cr_declaration_destroy:
+ *@a_this: the current instance of #CRDeclaration.
+ *
+ *Destructor of the declaration list.
+ */
+void
+cr_declaration_destroy (CRDeclaration * a_this)
+{
+ CRDeclaration *cur = NULL;
+
+ g_return_if_fail (a_this);
+
+ /*
+ * Go to the last element of the list.
+ */
+ for (cur = a_this; cur->next; cur = cur->next)
+ g_assert (cur->next->prev == cur);
+
+ /*
+ * Walk backward the list and free each "next" element.
+ * Meanwhile, free each property/value pair contained in the list.
+ */
+ for (; cur; cur = cur->prev) {
+ g_free (cur->next);
+ cur->next = NULL;
+
+ if (cur->property) {
+ cr_string_destroy (cur->property);
+ cur->property = NULL;
+ }
+
+ if (cur->value) {
+ cr_term_destroy (cur->value);
+ cur->value = NULL;
+ }
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-declaration.h b/src/3rdparty/libcroco/src/cr-declaration.h
new file mode 100644
index 0000000..eee8be3
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-declaration.h
@@ -0,0 +1,136 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See the COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_DECLARATION_H__
+#define __CR_DECLARATION_H__
+
+#include <stdio.h>
+#include "cr-utils.h"
+#include "cr-term.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The declaration of the #CRDeclaration class.
+ */
+
+/*forward declaration of what is defined in cr-statement.h*/
+typedef struct _CRStatement CRStatement ;
+
+/**
+ *The abstraction of a css declaration defined by the
+ *css2 spec in chapter 4.
+ *It is actually a chained list of property/value pairs.
+ */
+typedef struct _CRDeclaration CRDeclaration ;
+struct _CRDeclaration
+{
+ /**The property.*/
+ CRString *property ;
+
+ /**The value of the property.*/
+ CRTerm *value ;
+
+ /*the ruleset that contains this declaration*/
+ CRStatement *parent_statement ;
+
+ /*the next declaration*/
+ CRDeclaration *next ;
+
+ /*the previous one declaration*/
+ CRDeclaration *prev ;
+
+ /*does the declaration have the important keyword ?*/
+ gboolean important ;
+
+ glong ref_count ;
+
+ CRParsingLocation location ;
+ /*reserved for future usage*/
+ gpointer rfu0 ;
+ gpointer rfu1 ;
+ gpointer rfu2 ;
+ gpointer rfu3 ;
+} ;
+
+
+CRDeclaration * cr_declaration_new (CRStatement *a_statement,
+ CRString *a_property,
+ CRTerm *a_value) ;
+
+
+CRDeclaration * cr_declaration_parse_from_buf (CRStatement *a_statement,
+ const guchar *a_str,
+ enum CREncoding a_enc) ;
+
+CRDeclaration * cr_declaration_parse_list_from_buf (const guchar *a_str,
+ enum CREncoding a_enc) ;
+
+CRDeclaration * cr_declaration_append (CRDeclaration *a_this,
+ CRDeclaration *a_new) ;
+
+CRDeclaration * cr_declaration_append2 (CRDeclaration *a_this,
+ CRString *a_prop,
+ CRTerm *a_value) ;
+
+CRDeclaration * cr_declaration_prepend (CRDeclaration *a_this,
+ CRDeclaration *a_new) ;
+
+CRDeclaration * cr_declaration_unlink (CRDeclaration * a_decl) ;
+
+void
+cr_declaration_dump (CRDeclaration const *a_this,
+ FILE *a_fp, glong a_indent,
+ gboolean a_one_per_line) ;
+
+void cr_declaration_dump_one (CRDeclaration const *a_this,
+ FILE *a_fp, glong a_indent) ;
+
+gint cr_declaration_nr_props (CRDeclaration const *a_this) ;
+
+CRDeclaration * cr_declaration_get_from_list (CRDeclaration *a_this,
+ int itemnr) ;
+
+CRDeclaration * cr_declaration_get_by_prop_name (CRDeclaration *a_this,
+ const guchar *a_str) ;
+
+gchar * cr_declaration_to_string (CRDeclaration const *a_this,
+ gulong a_indent) ;
+
+guchar * cr_declaration_list_to_string (CRDeclaration const *a_this,
+ gulong a_indent) ;
+
+guchar * cr_declaration_list_to_string2 (CRDeclaration const *a_this,
+ gulong a_indent,
+ gboolean a_one_decl_per_line) ;
+
+void cr_declaration_ref (CRDeclaration *a_this) ;
+
+gboolean cr_declaration_unref (CRDeclaration *a_this) ;
+
+void cr_declaration_destroy (CRDeclaration *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_DECLARATION_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-doc-handler.c b/src/3rdparty/libcroco/src/cr-doc-handler.c
new file mode 100644
index 0000000..b0ef13c
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-doc-handler.c
@@ -0,0 +1,276 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPRYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-doc-handler.h"
+#include "cr-parser.h"
+
+/**
+ *@CRDocHandler:
+ *
+ *The definition of the CRDocHandler class.
+ *Contains methods to instantiate, destroy,
+ *and initialize instances of #CRDocHandler
+ *to custom values.
+ */
+
+#define PRIVATE(obj) (obj)->priv
+
+struct _CRDocHandlerPriv {
+ /**
+ *This pointer is to hold an application parsing context.
+ *For example, it used by the Object Model parser to
+ *store it parsing context. #CRParser does not touch it, but
+ *#CROMParser does. #CROMParser allocates this pointer at
+ *the beginning of the css document, and frees it at the end
+ *of the document.
+ */
+ gpointer context;
+
+ /**
+ *The place where #CROMParser puts the result of its parsing, if
+ *any.
+ */
+ gpointer result;
+ /**
+ *a pointer to the parser used to parse
+ *the current document.
+ */
+ CRParser *parser ;
+};
+
+/**
+ * cr_doc_handler_new:
+ *Constructor of #CRDocHandler.
+ *
+ *Returns the newly built instance of
+ *#CRDocHandler
+ *
+ */
+CRDocHandler *
+cr_doc_handler_new (void)
+{
+ CRDocHandler *result = NULL;
+
+ result = g_try_malloc (sizeof (CRDocHandler));
+
+ g_return_val_if_fail (result, NULL);
+
+ memset (result, 0, sizeof (CRDocHandler));
+ result->ref_count++;
+
+ result->priv = g_try_malloc (sizeof (CRDocHandlerPriv));
+ if (!result->priv) {
+ cr_utils_trace_info ("Out of memory exception");
+ g_free (result);
+ return NULL;
+ }
+
+ cr_doc_handler_set_default_sac_handler (result);
+
+ return result;
+}
+
+/**
+ * cr_doc_handler_get_ctxt:
+ *@a_this: the current instance of #CRDocHandler.
+ *@a_ctxt: out parameter. The new parsing context.
+ *
+ *Gets the private parsing context associated to the document handler
+ *The private parsing context is used by libcroco only.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_doc_handler_get_ctxt (CRDocHandler const * a_this, gpointer * a_ctxt)
+{
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
+
+ *a_ctxt = a_this->priv->context;
+
+ return CR_OK;
+}
+
+/**
+ * cr_doc_handler_set_ctxt:
+ *@a_this: the current instance of #CRDocHandler
+ *@a_ctxt: a pointer to the parsing context.
+ *
+ *Sets the private parsing context.
+ *This is used by libcroco only.
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_doc_handler_set_ctxt (CRDocHandler * a_this, gpointer a_ctxt)
+{
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
+ a_this->priv->context = a_ctxt;
+ return CR_OK;
+}
+
+/**
+ * cr_doc_handler_get_result:
+ *@a_this: the current instance of #CRDocHandler
+ *@a_result: out parameter. The returned result.
+ *
+ *Gets the private parsing result.
+ *The private parsing result is used by libcroco only.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_doc_handler_get_result (CRDocHandler const * a_this, gpointer * a_result)
+{
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
+
+ *a_result = a_this->priv->result;
+
+ return CR_OK;
+}
+
+/**
+ * cr_doc_handler_set_result:
+ *@a_this: the current instance of #CRDocHandler
+ *@a_result: the new result.
+ *
+ *Sets the private parsing context.
+ *This is used by libcroco only.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_doc_handler_set_result (CRDocHandler * a_this, gpointer a_result)
+{
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
+ a_this->priv->result = a_result;
+ return CR_OK;
+}
+
+/**
+ *cr_doc_handler_set_default_sac_handler:
+ *@a_this: a pointer to the current instance of #CRDocHandler.
+ *
+ *Sets the sac handlers contained in the current
+ *instance of DocHandler to the default handlers.
+ *For the time being the default handlers are
+ *test handlers. This is expected to change in a
+ *near future, when the libcroco gets a bit debugged.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_doc_handler_set_default_sac_handler (CRDocHandler * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ a_this->start_document = NULL;
+ a_this->end_document = NULL;
+ a_this->import_style = NULL;
+ a_this->namespace_declaration = NULL;
+ a_this->comment = NULL;
+ a_this->start_selector = NULL;
+ a_this->end_selector = NULL;
+ a_this->property = NULL;
+ a_this->start_font_face = NULL;
+ a_this->end_font_face = NULL;
+ a_this->start_media = NULL;
+ a_this->end_media = NULL;
+ a_this->start_page = NULL;
+ a_this->end_page = NULL;
+ a_this->ignorable_at_rule = NULL;
+ a_this->error = NULL;
+ a_this->unrecoverable_error = NULL;
+ return CR_OK;
+}
+
+/**
+ * cr_doc_handler_ref:
+ *@a_this: the current instance of #CRDocHandler.
+ */
+void
+cr_doc_handler_ref (CRDocHandler * a_this)
+{
+ g_return_if_fail (a_this);
+
+ a_this->ref_count++;
+}
+
+/**
+ * cr_doc_handler_unref:
+ *@a_this: the current instance of #CRDocHandler.
+ *
+ *Decreases the ref count of the current instance of #CRDocHandler.
+ *If the ref count reaches '0' then, destroys the instance.
+ *
+ *Returns TRUE if the instance as been destroyed, FALSE otherwise.
+ */
+gboolean
+cr_doc_handler_unref (CRDocHandler * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->ref_count > 0) {
+ a_this->ref_count--;
+ }
+
+ if (a_this->ref_count == 0) {
+ cr_doc_handler_destroy (a_this);
+ return TRUE;
+ }
+ return FALSE ;
+}
+
+/**
+ * cr_doc_handler_destroy:
+ *@a_this: the instance of #CRDocHandler to
+ *destroy.
+ *
+ *The destructor of the #CRDocHandler class.
+ */
+void
+cr_doc_handler_destroy (CRDocHandler * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->priv) {
+ g_free (a_this->priv);
+ a_this->priv = NULL;
+ }
+ g_free (a_this);
+}
+
+/**
+ * cr_doc_handler_associate_a_parser:
+ *Associates a parser to the current document handler
+ *
+ *@a_this: the current instance of document handler.
+ *@a_parser: the parser to associate.
+ */
+void
+cr_doc_handler_associate_a_parser (CRDocHandler *a_this,
+ gpointer a_parser)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this)
+ && a_parser) ;
+
+ PRIVATE (a_this)->parser = a_parser ;
+}
diff --git a/src/3rdparty/libcroco/src/cr-doc-handler.h b/src/3rdparty/libcroco/src/cr-doc-handler.h
new file mode 100644
index 0000000..d12673f
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-doc-handler.h
@@ -0,0 +1,298 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See the COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_DOC_HANDLER_H__
+#define __CR_DOC_HANDLER_H__
+
+/**
+ *@file
+ *The declaration of the #CRDocumentHandler class.
+ *This class is actually the parsing events handler.
+ */
+
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-input.h"
+#include "cr-stylesheet.h"
+
+G_BEGIN_DECLS
+
+
+typedef struct _CRDocHandler CRDocHandler ;
+
+struct _CRDocHandlerPriv ;
+typedef struct _CRDocHandlerPriv CRDocHandlerPriv ;
+
+
+/**
+ *The SAC document handler.
+ *An instance of this class is to
+ *be passed to a parser. Then, during the parsing
+ *the parser calls the convenient function pointer
+ *whenever a particular event (a css construction) occurs.
+ */
+struct _CRDocHandler
+{
+ CRDocHandlerPriv *priv ;
+
+ /**
+ *This pointer is to be used by the application for
+ *it custom needs. It is there to extend the doc handler.
+ */
+ gpointer app_data ;
+
+ /**
+ *Is called at the beginning of the parsing of the document.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ */
+ void (*start_document) (CRDocHandler *a_this) ;
+
+ /**
+ *Is called to notify the end of the parsing of the document.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ */
+ void (*end_document) (CRDocHandler *a_this) ;
+
+ /**
+ *Is called to notify an at charset rule.
+ *@param a_this the document handler.
+ *@param a_charset the declared charset.
+ */
+ void (*charset) (CRDocHandler *a_this,
+ CRString *a_charset,
+ CRParsingLocation *a_charset_sym_location) ;
+
+ /**
+ *Is called to notify an import statement in
+ *the stylesheet.
+ *@param a_this the current instance of #CRDocHandler.
+ *@param a_media_list a doubly linked list of GString objects.
+ *Each GString object contains a string which is the
+ *destination media for style information.
+ *@param a_uri the uri of the imported style sheet.
+ *@param a_uri_default_ns the default namespace of URI
+ *@param a_location the parsing location of the '\@import'
+ *keyword.
+ *of the imported style sheet.
+ */
+ void (*import_style) (CRDocHandler *a_this,
+ GList *a_media_list,
+ CRString *a_uri,
+ CRString *a_uri_default_ns,
+ CRParsingLocation *a_location) ;
+
+ void (*import_style_result) (CRDocHandler *a_this,
+ GList *a_media_list,
+ CRString *a_uri,
+ CRString *a_uri_default_ns,
+ CRStyleSheet *a_sheet) ;
+
+ /**
+ *Is called to notify a namespace declaration.
+ *Not used yet.
+ *@param a_this the current instance of #CRDocHandler.
+ *@param a_prefix the prefix of the namespace.
+ *@param a_uri the uri of the namespace.
+ *@param a_location the location of the "@namespace" keyword.
+ */
+ void (*namespace_declaration) (CRDocHandler *a_this,
+ CRString *a_prefix,
+ CRString *a_uri,
+ CRParsingLocation *a_location) ;
+
+ /**
+ *Is called to notify a comment.
+ *@param a_this a pointer to the current instance
+ *of #CRDocHandler.
+ *@param a_comment the comment.
+ */
+ void (*comment) (CRDocHandler *a_this,
+ CRString *a_comment) ;
+
+ /**
+ *Is called to notify the beginning of a rule
+ *statement.
+ *@param a_this the current instance of #CRDocHandler.
+ *@param a_selector_list the list of selectors that precedes
+ *the rule declarations.
+ */
+ void (*start_selector) (CRDocHandler * a_this,
+ CRSelector *a_selector_list) ;
+
+ /**
+ *Is called to notify the end of a rule statement.
+ *@param a_this the current instance of #CRDocHandler.
+ *@param a_selector_list the list of selectors that precedes
+ *the rule declarations. This pointer is the same as
+ *the one passed to start_selector() ;
+ */
+ void (*end_selector) (CRDocHandler *a_this,
+ CRSelector *a_selector_list) ;
+
+
+ /**
+ *Is called to notify a declaration.
+ *@param a_this a pointer to the current instance
+ *of #CRDocHandler.
+ *@param a_name the name of the parsed property.
+ *@param a_expression a css expression that represents
+ *the value of the property. A css expression is
+ *actually a linked list of 'terms'. Each term can
+ *be linked to other using operators.
+ *
+ */
+ void (*property) (CRDocHandler *a_this,
+ CRString *a_name,
+ CRTerm *a_expression,
+ gboolean a_is_important) ;
+ /**
+ *Is called to notify the start of a font face statement.
+ *The parser invokes this method at the beginning of every
+ *font face statement in the style sheet. There will
+ *be a corresponding end_font_face () event for every
+ *start_font_face () event.
+ *
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ *@param a_location the parsing location of the "\@font-face"
+ *keyword.
+ */
+ void (*start_font_face) (CRDocHandler *a_this,
+ CRParsingLocation *a_location) ;
+
+ /**
+ *Is called to notify the end of a font face statement.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ */
+ void (*end_font_face) (CRDocHandler *a_this) ;
+
+
+ /**
+ *Is called to notify the beginning of a media statement.
+ *The parser will invoke this method at the beginning of
+ *every media statement in the style sheet. There will be
+ *a corresponding end_media() event for every start_media()
+ *event.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ *@param a_media_list a double linked list of
+ #CRString * objects.
+ *Each CRString objects is actually a destination media for
+ *the style information.
+ */
+ void (*start_media) (CRDocHandler *a_this,
+ GList *a_media_list,
+ CRParsingLocation *a_location) ;
+
+ /**
+ *Is called to notify the end of a media statement.
+ *@param a_this a pointer to the current instance
+ *of #CRDocHandler.
+ *@param a_media_list a double linked list of GString * objects.
+ *Each GString objects is actually a destination media for
+ *the style information.
+ */
+ void (*end_media) (CRDocHandler *a_this,
+ GList *a_media_list) ;
+
+ /**
+ *Is called to notify the beginning of a page statement.
+ *The parser invokes this function at the beginning of
+ *every page statement in the style sheet. There will be
+ *a corresponding end_page() event for every single
+ *start_page() event.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ *@param a_name the name of the page (if any, null otherwise).
+ *@param a_pseudo_page the pseudo page (if any, null otherwise).
+ *@param a_location the parsing location of the "\@page" keyword.
+ */
+ void (*start_page) (CRDocHandler *a_this,
+ CRString *a_name,
+ CRString *a_pseudo_page,
+ CRParsingLocation *a_location) ;
+
+ /**
+ *Is called to notify the end of a page statement.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ *@param a_name the name of the page (if any, null otherwise).
+ *@param a_pseudo_page the pseudo page (if any, null otherwise).
+ */
+ void (*end_page) (CRDocHandler *a_this,
+ CRString *a_name,
+ CRString *pseudo_page) ;
+
+ /**
+ *Is Called to notify an unknown at-rule not supported
+ *by this parser.
+ */
+ void (*ignorable_at_rule) (CRDocHandler *a_this,
+ CRString *a_name) ;
+
+ /**
+ *Is called to notify a parsing error. After this error
+ *the application must ignore the rule being parsed, if
+ *any. After completion of this callback,
+ *the parser will then try to resume the parsing,
+ *ignoring the current error.
+ */
+ void (*error) (CRDocHandler *a_this) ;
+
+ /**
+ *Is called to notify an unrecoverable parsing error.
+ *This is the place to put emergency routines that free allocated
+ *resources.
+ */
+ void (*unrecoverable_error) (CRDocHandler *a_this) ;
+
+ gboolean resolve_import ;
+ gulong ref_count ;
+} ;
+
+CRDocHandler * cr_doc_handler_new (void) ;
+
+enum CRStatus cr_doc_handler_set_result (CRDocHandler *a_this, gpointer a_result) ;
+
+enum CRStatus cr_doc_handler_get_result (CRDocHandler const *a_this, gpointer * a_result) ;
+
+enum CRStatus cr_doc_handler_set_ctxt (CRDocHandler *a_this, gpointer a_ctxt) ;
+
+enum CRStatus cr_doc_handler_get_ctxt (CRDocHandler const *a_this, gpointer * a_ctxt) ;
+
+enum CRStatus cr_doc_handler_set_default_sac_handler (CRDocHandler *a_this) ;
+
+void cr_doc_handler_associate_a_parser (CRDocHandler *a_this,
+ gpointer a_parser) ;
+
+void cr_doc_handler_ref (CRDocHandler *a_this) ;
+
+gboolean cr_doc_handler_unref (CRDocHandler *a_this) ;
+
+void cr_doc_handler_destroy (CRDocHandler *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_DOC_HANDLER_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-enc-handler.c b/src/3rdparty/libcroco/src/cr-enc-handler.c
new file mode 100644
index 0000000..65adc7a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-enc-handler.c
@@ -0,0 +1,184 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+/**
+ *@file
+ *The definition of the #CREncHandler class.
+ */
+
+#include "cr-enc-handler.h"
+#include "cr-utils.h"
+
+#include <string.h>
+
+struct CREncAlias {
+ const gchar *name;
+ enum CREncoding encoding;
+};
+
+static struct CREncAlias gv_default_aliases[] = {
+ {"UTF-8", CR_UTF_8},
+ {"UTF_8", CR_UTF_8},
+ {"UTF8", CR_UTF_8},
+ {"UTF-16", CR_UTF_16},
+ {"UTF_16", CR_UTF_16},
+ {"UTF16", CR_UTF_16},
+ {"UCS1", CR_UCS_1},
+ {"UCS-1", CR_UCS_1},
+ {"UCS_1", CR_UCS_1},
+ {"ISO-8859-1", CR_UCS_1},
+ {"ISO_8859-1", CR_UCS_1},
+ {"UCS-1", CR_UCS_1},
+ {"UCS_1", CR_UCS_1},
+ {"UCS4", CR_UCS_4},
+ {"UCS-4", CR_UCS_4},
+ {"UCS_4", CR_UCS_4},
+ {"ASCII", CR_ASCII},
+ {0, 0}
+};
+
+static CREncHandler gv_default_enc_handlers[] = {
+ {CR_UCS_1, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
+ cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
+
+ {CR_ISO_8859_1, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
+ cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
+
+ {CR_ASCII, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
+ cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
+
+ {0, NULL, NULL, NULL, NULL}
+};
+
+/**
+ * cr_enc_handler_get_instance:
+ *@a_enc: the encoding of the Handler.
+ *
+ *Gets the instance of encoding handler.
+ *This function implements a singleton pattern.
+ *
+ *Returns the instance of #CREncHandler.
+ */
+CREncHandler *
+cr_enc_handler_get_instance (enum CREncoding a_enc)
+{
+ gulong i = 0;
+
+ for (i = 0; gv_default_enc_handlers[i].encoding; i++) {
+ if (gv_default_enc_handlers[i].encoding == a_enc) {
+ return (CREncHandler *) & gv_default_enc_handlers[i];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * cr_enc_handler_resolve_enc_alias:
+ *@a_alias_name: the encoding name.
+ *@a_enc: output param. The returned encoding type
+ *or 0 if the alias is not supported.
+ *
+ *Given an encoding name (called an alias name)
+ *the function returns the matching encoding type.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_enc_handler_resolve_enc_alias (const guchar * a_alias_name,
+ enum CREncoding *a_enc)
+{
+ gulong i = 0;
+ guchar *alias_name_up = NULL;
+ enum CRStatus status = CR_ENCODING_NOT_FOUND_ERROR;
+
+ g_return_val_if_fail (a_alias_name != NULL, CR_BAD_PARAM_ERROR);
+
+ alias_name_up = (guchar *) g_ascii_strup ((const gchar *) a_alias_name, -1);
+
+ for (i = 0; gv_default_aliases[i].name; i++) {
+ if (!strcmp (gv_default_aliases[i].name, (const gchar *) alias_name_up)) {
+ *a_enc = gv_default_aliases[i].encoding;
+ status = CR_OK;
+ break;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * cr_enc_handler_convert_input:
+ *@a_this: the current instance of #CREncHandler.
+ *@a_in: the input buffer to convert.
+ *@a_in_len: in/out parameter. The len of the input
+ *buffer to convert. After return, contains the number of
+ *bytes actually consumed.
+ *@a_out: output parameter. The converted output buffer.
+ *Must be freed by the buffer.
+ *@a_out_len: output parameter. The length of the output buffer.
+ *
+ *Converts a raw input buffer into an utf8 buffer.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_enc_handler_convert_input (CREncHandler * a_this,
+ const guchar * a_in,
+ gulong * a_in_len,
+ guchar ** a_out, gulong * a_out_len)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && a_in && a_in_len && a_out,
+ CR_BAD_PARAM_ERROR);
+
+ if (a_this->decode_input == NULL)
+ return CR_OK;
+
+ if (a_this->enc_str_len_as_utf8) {
+ status = a_this->enc_str_len_as_utf8 (a_in,
+ &a_in[*a_in_len - 1],
+ a_out_len);
+
+ g_return_val_if_fail (status == CR_OK, status);
+ } else {
+ *a_out_len = *a_in_len;
+ }
+
+ *a_out = g_malloc0 (*a_out_len);
+
+ status = a_this->decode_input (a_in, a_in_len, *a_out, a_out_len);
+
+ if (status != CR_OK) {
+ g_free (*a_out);
+ *a_out = NULL;
+ }
+
+ g_return_val_if_fail (status == CR_OK, status);
+
+ return CR_OK;
+}
diff --git a/src/3rdparty/libcroco/src/cr-enc-handler.h b/src/3rdparty/libcroco/src/cr-enc-handler.h
new file mode 100644
index 0000000..0727764
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-enc-handler.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+/**
+ *@file:
+ *The declaration of the #CREncHandler class.
+ *
+ */
+
+#ifndef __CR_ENC_HANDLER_H__
+#define __CR_ENC_HANDLER_H__
+
+#include "cr-utils.h"
+
+G_BEGIN_DECLS
+
+
+typedef struct _CREncHandler CREncHandler ;
+
+typedef enum CRStatus (*CREncInputFunc) (const guchar * a_in,
+ gulong *a_in_len,
+ guchar *a_out,
+ gulong *a_out_len) ;
+
+typedef enum CRStatus (*CREncOutputFunc) (const guchar * a_in,
+ gulong *a_in_len,
+ guchar *a_out,
+ gulong *a_out_len) ;
+
+typedef enum CRStatus (*CREncInputStrLenAsUtf8Func)
+(const guchar *a_in_start,
+ const guchar *a_in_end,
+ gulong *a_in_size);
+
+typedef enum CRStatus (*CREncUtf8StrLenAsOutputFunc)
+(const guchar *a_in_start,
+ const guchar *a_in_end,
+ gulong *a_in_size) ;
+
+/**
+ *This class is responsible of the
+ *the encoding conversions stuffs in
+ *libcroco.
+ */
+
+struct _CREncHandler
+{
+ enum CREncoding encoding ;
+ CREncInputFunc decode_input ;
+ CREncInputFunc encode_output ;
+ CREncInputStrLenAsUtf8Func enc_str_len_as_utf8 ;
+ CREncUtf8StrLenAsOutputFunc utf8_str_len_as_enc ;
+} ;
+
+CREncHandler *
+cr_enc_handler_get_instance (enum CREncoding a_enc) ;
+
+enum CRStatus
+cr_enc_handler_resolve_enc_alias (const guchar *a_alias_name,
+ enum CREncoding *a_enc) ;
+
+enum CRStatus
+cr_enc_handler_convert_input (CREncHandler *a_this,
+ const guchar *a_in,
+ gulong *a_in_len,
+ guchar **a_out,
+ gulong *a_out_len) ;
+
+G_END_DECLS
+
+#endif /*__CR_ENC_HANDLER_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-fonts.c b/src/3rdparty/libcroco/src/cr-fonts.c
new file mode 100644
index 0000000..3f7a287
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-fonts.c
@@ -0,0 +1,943 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of
+ * the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ *See COPYRIGHTS file for copyright information
+ */
+
+#include "cr-fonts.h"
+#include <string.h>
+
+static enum CRStatus
+cr_font_family_to_string_real (CRFontFamily const * a_this,
+ gboolean a_walk_list, GString ** a_string)
+{
+ guchar const *name = NULL;
+ enum CRStatus result = CR_OK;
+
+ if (!*a_string) {
+ *a_string = g_string_new (NULL);
+ g_return_val_if_fail (*a_string,
+ CR_INSTANCIATION_FAILED_ERROR);
+ }
+
+ if (!a_this) {
+ g_string_append (*a_string, "NULL");
+ return CR_OK;
+ }
+
+ switch (a_this->type) {
+ case FONT_FAMILY_SANS_SERIF:
+ name = (guchar const *) "sans-serif";
+ break;
+
+ case FONT_FAMILY_SERIF:
+ name = (guchar const *) "sans-serif";
+ break;
+
+ case FONT_FAMILY_CURSIVE:
+ name = (guchar const *) "cursive";
+ break;
+
+ case FONT_FAMILY_FANTASY:
+ name = (guchar const *) "fantasy";
+ break;
+
+ case FONT_FAMILY_MONOSPACE:
+ name = (guchar const *) "monospace";
+ break;
+
+ case FONT_FAMILY_NON_GENERIC:
+ name = (guchar const *) a_this->name;
+ break;
+
+ default:
+ name = NULL;
+ break;
+ }
+
+ if (name) {
+ if (a_this->prev) {
+ g_string_append_printf (*a_string, ", %s", name);
+ } else {
+ g_string_append (*a_string, (const gchar *) name);
+ }
+ }
+ if (a_walk_list == TRUE && a_this->next) {
+ result = cr_font_family_to_string_real (a_this->next,
+ TRUE, a_string);
+ }
+ return result;
+}
+
+static const gchar *
+cr_predefined_absolute_font_size_to_string (enum CRPredefinedAbsoluteFontSize
+ a_code)
+{
+ gchar const *str = NULL;
+
+ switch (a_code) {
+ case FONT_SIZE_XX_SMALL:
+ str = "xx-small";
+ break;
+ case FONT_SIZE_X_SMALL:
+ str = "x-small";
+ break;
+ case FONT_SIZE_SMALL:
+ str = "small";
+ break;
+ case FONT_SIZE_MEDIUM:
+ str = "medium";
+ break;
+ case FONT_SIZE_LARGE:
+ str = "large";
+ break;
+ case FONT_SIZE_X_LARGE:
+ str = "x-large";
+ break;
+ case FONT_SIZE_XX_LARGE:
+ str = "xx-large";
+ break;
+ default:
+ str = "unknown absolute font size value";
+ }
+ return str;
+}
+
+static const gchar *
+cr_relative_font_size_to_string (enum CRRelativeFontSize a_code)
+{
+ gchar const *str = NULL;
+
+ switch (a_code) {
+ case FONT_SIZE_LARGER:
+ str = "larger";
+ break;
+ case FONT_SIZE_SMALLER:
+ str = "smaller";
+ break;
+ default:
+ str = "unknown relative font size value";
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_family_new:
+ * @a_type: the type of font family to create.
+ * @a_name: the name of the font family.
+ *
+ * create a font family.
+ *
+ * Returns the newly built font family.
+ */
+CRFontFamily *
+cr_font_family_new (enum CRFontFamilyType a_type, guchar * a_name)
+{
+ CRFontFamily *result = NULL;
+
+ result = g_try_malloc (sizeof (CRFontFamily));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRFontFamily));
+ result->type = a_type;
+
+ cr_font_family_set_name (result, a_name);
+
+ return result;
+}
+
+/**
+ * cr_font_family_to_string:
+ * @a_this: the current instance of #CRFontFamily.
+ * @a_walk_font_family_list: whether the serialize the entire list.
+ *
+ * Returns the seriliazed font family. The caller has to free it using
+ * g_free().
+ */
+guchar *
+cr_font_family_to_string (CRFontFamily const * a_this,
+ gboolean a_walk_font_family_list)
+{
+ enum CRStatus status = CR_OK;
+ guchar *result = NULL;
+ GString *stringue = NULL;
+
+ if (!a_this) {
+ result = (guchar *) g_strdup ("NULL");
+ g_return_val_if_fail (result, NULL);
+ return result;
+ }
+ status = cr_font_family_to_string_real (a_this,
+ a_walk_font_family_list,
+ &stringue);
+
+ if (status == CR_OK && stringue) {
+ result = (guchar *) stringue->str;
+ g_string_free (stringue, FALSE);
+ stringue = NULL;
+
+ } else {
+ if (stringue) {
+ g_string_free (stringue, TRUE);
+ stringue = NULL;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * cr_font_family_set_name:
+ * @a_this: the current instance of #CRFontFamily.
+ * @a_name: the new name
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_family_set_name (CRFontFamily * a_this, guchar * a_name)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ /*
+ *only non generic font families can have a name
+ */
+
+ if (a_this->type != FONT_FAMILY_NON_GENERIC) {
+ return CR_BAD_PARAM_ERROR;
+ }
+
+ if (a_this->name) {
+ g_free (a_this->name);
+ a_this->name = NULL;
+ }
+
+ a_this->name = a_name;
+ return CR_OK;
+}
+
+/**
+ * cr_font_family_append:
+ * @a_this: the current instance of #CRFontFamily.
+ * @a_family_to_append: the font family to append to the list
+ *
+ * Returns the new font family list.
+ */
+CRFontFamily *
+cr_font_family_append (CRFontFamily * a_this,
+ CRFontFamily * a_family_to_append)
+{
+ CRFontFamily *cur_ff = NULL;
+
+ g_return_val_if_fail (a_family_to_append, NULL);
+
+ if (!a_this)
+ return a_family_to_append;
+
+ for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ;
+
+ cur_ff->next = a_family_to_append;
+ a_family_to_append->prev = cur_ff;
+
+ return a_this;
+
+}
+
+/**
+ * cr_font_family_prepend:
+ * @a_this: the current instance #CRFontFamily.
+ * @a_family_to_prepend: the font family to prepend to the list.
+ *
+ * Returns the font family list.
+ */
+CRFontFamily *
+cr_font_family_prepend (CRFontFamily * a_this,
+ CRFontFamily * a_family_to_prepend)
+{
+ g_return_val_if_fail (a_this && a_family_to_prepend, NULL);
+
+ if (!a_this)
+ return a_family_to_prepend;
+
+ a_family_to_prepend->next = a_this;
+ a_this->prev = a_family_to_prepend;
+
+ return a_family_to_prepend;
+}
+
+/**
+ * cr_font_family_destroy:
+ * @a_this: the current instance of #CRFontFamily.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_family_destroy (CRFontFamily * a_this)
+{
+ CRFontFamily *cur_ff = NULL;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ;
+
+ for (; cur_ff; cur_ff = cur_ff->prev) {
+ if (a_this->name) {
+ g_free (a_this->name);
+ a_this->name = NULL;
+ }
+
+ if (cur_ff->next) {
+ g_free (cur_ff->next);
+
+ }
+
+ if (cur_ff->prev == NULL) {
+ g_free (a_this);
+ }
+ }
+
+ return CR_OK;
+}
+
+/***************************************************
+ *'font-size' manipulation functions definitions
+ ***************************************************/
+
+/**
+ * cr_font_size_new:
+ *
+ * Returns the newly created font size.
+ */
+CRFontSize *
+cr_font_size_new (void)
+{
+ CRFontSize *result = NULL;
+
+ result = g_try_malloc (sizeof (CRFontSize));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRFontSize));
+
+ return result;
+}
+
+/**
+ * cr_font_size_clear:
+ * @a_this: the current instance of #CRFontSize
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_clear (CRFontSize * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ switch (a_this->type) {
+ case PREDEFINED_ABSOLUTE_FONT_SIZE:
+ case RELATIVE_FONT_SIZE:
+ case INHERITED_FONT_SIZE:
+ memset (a_this, 0, sizeof (CRFontSize));
+ break;
+
+ case ABSOLUTE_FONT_SIZE:
+ memset (a_this, 0, sizeof (CRFontSize));
+ break;
+
+ default:
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ return CR_OK;
+}
+
+/**
+ * cr_font_size_copy:
+ * @a_dst: the destination #CRFontSize (where to copy to).
+ * @a_src: the source #CRFontSize (where to copy from).
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_copy (CRFontSize * a_dst, CRFontSize const * a_src)
+{
+ g_return_val_if_fail (a_dst && a_src, CR_BAD_PARAM_ERROR);
+
+ switch (a_src->type) {
+ case PREDEFINED_ABSOLUTE_FONT_SIZE:
+ case RELATIVE_FONT_SIZE:
+ case INHERITED_FONT_SIZE:
+ cr_font_size_clear (a_dst);
+ memcpy (a_dst, a_src, sizeof (CRFontSize));
+ break;
+
+ case ABSOLUTE_FONT_SIZE:
+ cr_font_size_clear (a_dst);
+ cr_num_copy (&a_dst->value.absolute,
+ &a_src->value.absolute);
+ a_dst->type = a_src->type;
+ break;
+
+ default:
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+ return CR_OK;
+}
+
+/**
+ * cr_font_size_set_predefined_absolute_font_size:
+ * @a_this: the current instance of #CRFontSize.
+ * @a_predefined: what to set.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_set_predefined_absolute_font_size (CRFontSize *a_this,
+ enum CRPredefinedAbsoluteFontSize a_predefined)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+ g_return_val_if_fail ((unsigned)a_predefined < NB_PREDEFINED_ABSOLUTE_FONT_SIZES,
+ CR_BAD_PARAM_ERROR) ;
+
+ a_this->type = PREDEFINED_ABSOLUTE_FONT_SIZE ;
+ a_this->value.predefined = a_predefined ;
+
+ return CR_OK ;
+}
+
+/**
+ * cr_font_size_set_relative_font_size:
+ * @a_this: the current instance of #CRFontSize
+ * @a_relative: the new relative font size
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_set_relative_font_size (CRFontSize *a_this,
+ enum CRRelativeFontSize a_relative)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+ g_return_val_if_fail ((unsigned)a_relative < NB_RELATIVE_FONT_SIZE,
+ CR_BAD_PARAM_ERROR) ;
+
+ a_this->type = RELATIVE_FONT_SIZE ;
+ a_this->value.relative = a_relative ;
+ return CR_OK ;
+}
+
+/**
+ * cr_font_size_set_absolute_font_size:
+ * @a_this: the current instance of #CRFontSize
+ * @a_num_type: the type of number to set.
+ * @a_value: the actual value to set.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_set_absolute_font_size (CRFontSize *a_this,
+ enum CRNumType a_num_type,
+ gdouble a_value)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+ g_return_val_if_fail ((unsigned)a_num_type < NB_NUM_TYPE,
+ CR_BAD_PARAM_ERROR) ;
+
+ a_this->type = ABSOLUTE_FONT_SIZE ;
+ cr_num_set (&a_this->value.absolute,
+ a_value, a_num_type) ;
+ return CR_OK ;
+}
+
+/**
+ * cr_font_size_set_to_inherit:
+ * @a_this: the current instance of #CRFontSize
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_set_to_inherit (CRFontSize *a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+
+ cr_font_size_clear (a_this) ;
+ a_this->type = INHERITED_FONT_SIZE ;
+
+ return CR_OK ;
+}
+
+/**
+ * cr_font_size_is_set_to_inherit:
+ * @a_this: the current instance of #CRFontSize.
+ *
+ * Returns TRUE if the current instance is set to 'inherit'.
+ */
+gboolean
+cr_font_size_is_set_to_inherit (CRFontSize const *a_this)
+{
+ g_return_val_if_fail (a_this, FALSE) ;
+
+ return a_this->type == INHERITED_FONT_SIZE ;
+}
+
+/**
+ * cr_font_size_to_string:
+ * @a_this: the current instance of #CRFontSize
+ *
+ * Returns the serialized form of #CRFontSize. The returned string
+ * has to bee freed using g_free().
+ */
+gchar *
+cr_font_size_to_string (CRFontSize const * a_this)
+{
+ gchar *str = NULL;
+
+ if (!a_this) {
+ str = g_strdup ("NULL");
+ g_return_val_if_fail (str, NULL);
+ return str;
+ }
+ switch (a_this->type) {
+ case PREDEFINED_ABSOLUTE_FONT_SIZE:
+ str = g_strdup (cr_predefined_absolute_font_size_to_string
+ (a_this->value.predefined));
+ break;
+ case ABSOLUTE_FONT_SIZE:
+ str = (gchar *) cr_num_to_string (&a_this->value.absolute);
+ break;
+ case RELATIVE_FONT_SIZE:
+ str = g_strdup (cr_relative_font_size_to_string
+ (a_this->value.relative));
+ break;
+ case INHERITED_FONT_SIZE:
+ str = g_strdup ("inherit");
+ break;
+ default:
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_size_get_smaller_predefined:
+ * @a_font_size: the font size to consider.
+ * @a_smaller_size: out parameter. The a smaller value than @a_font_size.
+ */
+void
+cr_font_size_get_smaller_predefined_font_size
+ (enum CRPredefinedAbsoluteFontSize a_font_size,
+ enum CRPredefinedAbsoluteFontSize *a_smaller_size)
+{
+ enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ;
+
+ g_return_if_fail (a_smaller_size) ;
+ g_return_if_fail ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) ;
+
+ switch (a_font_size) {
+ case FONT_SIZE_XX_SMALL:
+ result = FONT_SIZE_XX_SMALL ;
+ break ;
+ case FONT_SIZE_X_SMALL:
+ result = FONT_SIZE_XX_SMALL ;
+ break ;
+ case FONT_SIZE_SMALL:
+ result = FONT_SIZE_X_SMALL;
+ break ;
+ case FONT_SIZE_MEDIUM:
+ result = FONT_SIZE_SMALL;
+ break ;
+ case FONT_SIZE_LARGE:
+ result = FONT_SIZE_MEDIUM;
+ break ;
+ case FONT_SIZE_X_LARGE:
+ result = FONT_SIZE_LARGE;
+ break ;
+ case FONT_SIZE_XX_LARGE:
+ result = FONT_SIZE_XX_LARGE;
+ break ;
+ case FONT_SIZE_INHERIT:
+ cr_utils_trace_info ("can't return a smaller size for FONT_SIZE_INHERIT") ;
+ result = FONT_SIZE_MEDIUM ;
+ break ;
+ default:
+ cr_utils_trace_info ("Unknown FONT_SIZE") ;
+ result = FONT_SIZE_MEDIUM ;
+ break ;
+ }
+ *a_smaller_size = result ;
+}
+
+
+/**
+ * cr_font_size_get_larger_predefined_font_size:
+ * @a_font_size: the font size to consider.
+ * @a_larger_size: out parameter. the font size considered larger than
+ * @a_font_size.
+ *
+ */
+void
+cr_font_size_get_larger_predefined_font_size
+ (enum CRPredefinedAbsoluteFontSize a_font_size,
+ enum CRPredefinedAbsoluteFontSize *a_larger_size)
+{
+ enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ;
+
+ g_return_if_fail (a_larger_size) ;
+ g_return_if_fail ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) ;
+
+ switch (a_font_size) {
+ case FONT_SIZE_XX_SMALL:
+ result = FONT_SIZE_X_SMALL ;
+ break ;
+ case FONT_SIZE_X_SMALL:
+ result = FONT_SIZE_SMALL ;
+ break ;
+ case FONT_SIZE_SMALL:
+ result = FONT_SIZE_MEDIUM;
+ break ;
+ case FONT_SIZE_MEDIUM:
+ result = FONT_SIZE_LARGE;
+ break ;
+ case FONT_SIZE_LARGE:
+ result = FONT_SIZE_X_LARGE;
+ break ;
+ case FONT_SIZE_X_LARGE:
+ result = FONT_SIZE_XX_LARGE ;
+ break ;
+ case FONT_SIZE_XX_LARGE:
+ result = FONT_SIZE_XX_LARGE;
+ break ;
+ case FONT_SIZE_INHERIT:
+ cr_utils_trace_info ("can't return a bigger size for FONT_SIZE_INHERIT") ;
+ result = FONT_SIZE_MEDIUM ;
+ break ;
+ default:
+ cr_utils_trace_info ("Unknown FONT_SIZE") ;
+ result = FONT_SIZE_MEDIUM ;
+ break ;
+ }
+ *a_larger_size = result ;
+}
+
+/**
+ * cr_font_size_is_predefined_absolute_font_size:
+ * @a_font_size: the font size to consider.
+ *
+ * Returns TRUE if the instance is an predefined absolute font size, FALSE
+ * otherwise.
+ */
+gboolean
+cr_font_size_is_predefined_absolute_font_size
+ (enum CRPredefinedAbsoluteFontSize a_font_size)
+{
+ if ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) {
+ return TRUE ;
+ } else {
+ return FALSE ;
+ }
+}
+
+/**
+ * cr_font_size_adjust_to_string:
+ * @a_this: the instance of #CRFontSizeAdjust.
+ *
+ * Returns the serialized form of #CRFontSizeAdjust
+ */
+gchar *
+cr_font_size_adjust_to_string (CRFontSizeAdjust const * a_this)
+{
+ gchar *str = NULL;
+
+ if (!a_this) {
+ str = g_strdup ("NULL");
+ g_return_val_if_fail (str, NULL);
+ return str;
+ }
+
+ switch (a_this->type) {
+ case FONT_SIZE_ADJUST_NONE:
+ str = g_strdup ("none");
+ break;
+ case FONT_SIZE_ADJUST_NUMBER:
+ if (a_this->num)
+ str = (gchar *) cr_num_to_string (a_this->num);
+ else
+ str = g_strdup ("unknown font-size-adjust property value"); /* Should raise an error no?*/
+ break;
+ case FONT_SIZE_ADJUST_INHERIT:
+ str = g_strdup ("inherit");
+ }
+ return str;
+}
+
+/**
+ * cr_font_style_to_string:
+ * @a_code: the current instance of #CRFontStyle .
+ *
+ * Returns the serialized #CRFontStyle. The caller must free the returned
+ * string using g_free().
+ */
+const gchar *
+cr_font_style_to_string (enum CRFontStyle a_code)
+{
+ gchar *str = NULL;
+
+ switch (a_code) {
+ case FONT_STYLE_NORMAL:
+ str = (gchar *) "normal";
+ break;
+ case FONT_STYLE_ITALIC:
+ str = (gchar *) "italic";
+ break;
+ case FONT_STYLE_OBLIQUE:
+ str = (gchar *) "oblique";
+ break;
+ case FONT_STYLE_INHERIT:
+ str = (gchar *) "inherit";
+ break;
+ default:
+ str = (gchar *) "unknown font style value";
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_variant_to_string:
+ * @a_code: the current instance of #CRFontVariant.
+ *
+ * Returns the serialized form of #CRFontVariant. The caller has
+ * to free the returned string using g_free().
+ */
+const gchar *
+cr_font_variant_to_string (enum CRFontVariant a_code)
+{
+ gchar *str = NULL;
+
+ switch (a_code) {
+ case FONT_VARIANT_NORMAL:
+ str = (gchar *) "normal";
+ break;
+ case FONT_VARIANT_SMALL_CAPS:
+ str = (gchar *) "small-caps";
+ break;
+ case FONT_VARIANT_INHERIT:
+ str = (gchar *) "inherit";
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_weight_get_bolder:
+ * @a_weight: the #CRFontWeight to consider.
+ *
+ * Returns a font weight bolder than @a_weight
+ */
+enum CRFontWeight
+cr_font_weight_get_bolder (enum CRFontWeight a_weight)
+{
+ if (a_weight == FONT_WEIGHT_INHERIT) {
+ cr_utils_trace_info ("can't return a bolder weight for FONT_WEIGHT_INHERIT") ;
+ return a_weight;
+ } else if (a_weight >= FONT_WEIGHT_900) {
+ return FONT_WEIGHT_900 ;
+ } else if (a_weight < FONT_WEIGHT_NORMAL) {
+ return FONT_WEIGHT_NORMAL ;
+ } else if (a_weight == FONT_WEIGHT_BOLDER
+ || a_weight == FONT_WEIGHT_LIGHTER) {
+ cr_utils_trace_info ("FONT_WEIGHT_BOLDER or FONT_WEIGHT_LIGHTER should not appear here") ;
+ return FONT_WEIGHT_NORMAL ;
+ } else {
+ return a_weight << 1 ;
+ }
+}
+
+/**
+ * cr_font_weight_to_string:
+ * @a_code: the font weight to consider.
+ *
+ * Returns the serialized form of #CRFontWeight.
+ */
+const gchar *
+cr_font_weight_to_string (enum CRFontWeight a_code)
+{
+ gchar *str = NULL;
+
+ switch (a_code) {
+ case FONT_WEIGHT_NORMAL:
+ str = (gchar *) "normal";
+ break;
+ case FONT_WEIGHT_BOLD:
+ str = (gchar *) "bold";
+ break;
+ case FONT_WEIGHT_BOLDER:
+ str = (gchar *) "bolder";
+ break;
+ case FONT_WEIGHT_LIGHTER:
+ str = (gchar *) "lighter";
+ break;
+ case FONT_WEIGHT_100:
+ str = (gchar *) "100";
+ break;
+ case FONT_WEIGHT_200:
+ str = (gchar *) "200";
+ break;
+ case FONT_WEIGHT_300:
+ str = (gchar *) "300";
+ break;
+ case FONT_WEIGHT_400:
+ str = (gchar *) "400";
+ break;
+ case FONT_WEIGHT_500:
+ str = (gchar *) "500";
+ break;
+ case FONT_WEIGHT_600:
+ str = (gchar *) "600";
+ break;
+ case FONT_WEIGHT_700:
+ str = (gchar *) "700";
+ break;
+ case FONT_WEIGHT_800:
+ str = (gchar *) "800";
+ break;
+ case FONT_WEIGHT_900:
+ str = (gchar *) "900";
+ break;
+ case FONT_WEIGHT_INHERIT:
+ str = (gchar *) "inherit";
+ break;
+ default:
+ str = (gchar *) "unknown font-weight property value";
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_stretch_to_string:
+ * @a_code: the instance of #CRFontStretch to consider.
+ *
+ * Returns the serialized form of #CRFontStretch.
+ */
+const gchar *
+cr_font_stretch_to_string (enum CRFontStretch a_code)
+{
+ gchar *str = NULL;
+
+ switch (a_code) {
+ case FONT_STRETCH_NORMAL:
+ str = (gchar *) "normal";
+ break;
+ case FONT_STRETCH_WIDER:
+ str = (gchar *) "wider";
+ break;
+ case FONT_STRETCH_NARROWER:
+ str = (gchar *) "narrower";
+ break;
+ case FONT_STRETCH_ULTRA_CONDENSED:
+ str = (gchar *) "ultra-condensed";
+ break;
+ case FONT_STRETCH_EXTRA_CONDENSED:
+ str = (gchar *) "extra-condensed";
+ break;
+ case FONT_STRETCH_CONDENSED:
+ str = (gchar *) "condensed";
+ break;
+ case FONT_STRETCH_SEMI_CONDENSED:
+ str = (gchar *) "semi-condensed";
+ break;
+ case FONT_STRETCH_SEMI_EXPANDED:
+ str = (gchar *) "semi-expanded";
+ break;
+ case FONT_STRETCH_EXPANDED:
+ str = (gchar *) "expanded";
+ break;
+ case FONT_STRETCH_EXTRA_EXPANDED:
+ str = (gchar *) "extra-expaned";
+ break;
+ case FONT_STRETCH_ULTRA_EXPANDED:
+ str = (gchar *) "ultra-expanded";
+ break;
+ case FONT_STRETCH_INHERIT:
+ str = (gchar *) "inherit";
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_size_destroy:
+ * @a_font_size: the font size to destroy
+ *
+ */
+void
+cr_font_size_destroy (CRFontSize * a_font_size)
+{
+ g_return_if_fail (a_font_size);
+
+ g_free (a_font_size) ;
+}
+
+/*******************************************************
+ *'font-size-adjust' manipulation function definition
+ *******************************************************/
+
+/**
+ * cr_font_size_adjust_new:
+ *
+ * Returns a newly built instance of #CRFontSizeAdjust
+ */
+CRFontSizeAdjust *
+cr_font_size_adjust_new (void)
+{
+ CRFontSizeAdjust *result = NULL;
+
+ result = g_try_malloc (sizeof (CRFontSizeAdjust));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRFontSizeAdjust));
+
+ return result;
+}
+
+/**
+ * cr_font_size_adjust_destroy:
+ * @a_this: the current instance of #CRFontSizeAdjust.
+ *
+ */
+void
+cr_font_size_adjust_destroy (CRFontSizeAdjust * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->type == FONT_SIZE_ADJUST_NUMBER && a_this->num) {
+ cr_num_destroy (a_this->num);
+ a_this->num = NULL;
+ }
+}
diff --git a/src/3rdparty/libcroco/src/cr-fonts.h b/src/3rdparty/libcroco/src/cr-fonts.h
new file mode 100644
index 0000000..9eaeeeb
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-fonts.h
@@ -0,0 +1,315 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of
+ * the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_FONTS_H__
+#define __CR_FONTS_H__
+
+#include "cr-utils.h"
+#include "cr-num.h"
+
+/**
+ *@file
+ *Various type declarations about font selection related
+ *properties.
+ */
+G_BEGIN_DECLS
+
+
+enum CRFontFamilyType
+{
+ FONT_FAMILY_SANS_SERIF,
+ FONT_FAMILY_SERIF,
+ FONT_FAMILY_CURSIVE,
+ FONT_FAMILY_FANTASY,
+ FONT_FAMILY_MONOSPACE,
+ FONT_FAMILY_NON_GENERIC,
+ FONT_FAMILY_INHERIT,
+ /**/
+ NB_FONT_FAMILIE_TYPES
+} ;
+
+typedef struct _CRFontFamily CRFontFamily ;
+
+struct _CRFontFamily
+{
+ enum CRFontFamilyType type ;
+
+ /*
+ *The name of the font family, in case
+ *it is non generic.
+ *Is set only if the type is FONT_FAMILY_NON_GENERIC.
+ */
+ guchar *name ;
+
+ CRFontFamily *next ;
+ CRFontFamily *prev ;
+} ;
+
+
+/**
+ *The different types
+ *of absolute font size.
+ *This is used by the 'font-size'
+ *property defined in css2 spec
+ *in chapter 15.2.4 .
+ *These values a indexes of
+ *table of size so please, do not
+ *change their definition order unless
+ *you know what you are doing.
+ */
+enum CRPredefinedAbsoluteFontSize
+{
+ FONT_SIZE_XX_SMALL=0,
+ FONT_SIZE_X_SMALL,
+ FONT_SIZE_SMALL,
+ FONT_SIZE_MEDIUM,
+ FONT_SIZE_LARGE,
+ FONT_SIZE_X_LARGE,
+ FONT_SIZE_XX_LARGE,
+ FONT_SIZE_INHERIT,
+ NB_PREDEFINED_ABSOLUTE_FONT_SIZES
+} ;
+
+/**
+ *The different types
+ *of relative font size.
+ *This is used by the 'font-size'
+ *property defined in css2 spec
+ *in chapter 15.2.4 .
+ *These values a indexes of
+ *table of size so please, do not
+ *change their definition order unless
+ *you know what you are doing.
+ */
+enum CRRelativeFontSize
+{
+ FONT_SIZE_LARGER,
+ FONT_SIZE_SMALLER,
+ NB_RELATIVE_FONT_SIZE
+} ;
+
+/**
+ *The type of font-size property.
+ *Used to define the type of #CRFontSize .
+ *See css2 spec chapter 15.2.4 to understand.
+ */
+enum CRFontSizeType {
+ /**
+ *If the type of #CRFontSize is
+ *PREDEFINED_ABSOLUTE_FONT_SIZE,
+ *the CRFontSize::value.predefined_absolute
+ *field will be defined.
+ */
+ PREDEFINED_ABSOLUTE_FONT_SIZE,
+
+ /**
+ *If the type of #CRFontSize is
+ *ABSOLUTE_FONT_SIZE,
+ *the CRFontSize::value.absolute
+ *field will be defined.
+ */
+ ABSOLUTE_FONT_SIZE,
+
+ /**
+ *If the type of #CRFontSize is
+ *RELATIVE_FONT_SIZE,
+ *the CRFontSize::value.relative
+ *field will be defined.
+ */
+ RELATIVE_FONT_SIZE,
+
+ /**
+ *If the type of #CRFontSize is
+ *INHERITED_FONT_SIZE,
+ *the None of the field of the CRFontSize::value enum
+ *will be defined.
+ */
+ INHERITED_FONT_SIZE,
+
+ NB_FONT_SIZE_TYPE
+} ;
+
+typedef struct _CRFontSize CRFontSize ;
+struct _CRFontSize {
+ enum CRFontSizeType type ;
+ union {
+ enum CRPredefinedAbsoluteFontSize predefined ;
+ enum CRRelativeFontSize relative ;
+ CRNum absolute ;
+ } value;
+} ;
+
+enum CRFontSizeAdjustType
+{
+ FONT_SIZE_ADJUST_NONE = 0,
+ FONT_SIZE_ADJUST_NUMBER,
+ FONT_SIZE_ADJUST_INHERIT
+} ;
+typedef struct _CRFontSizeAdjust CRFontSizeAdjust ;
+struct _CRFontSizeAdjust
+{
+ enum CRFontSizeAdjustType type ;
+ CRNum *num ;
+} ;
+
+enum CRFontStyle
+{
+ FONT_STYLE_NORMAL=0,
+ FONT_STYLE_ITALIC,
+ FONT_STYLE_OBLIQUE,
+ FONT_STYLE_INHERIT
+} ;
+
+enum CRFontVariant
+{
+ FONT_VARIANT_NORMAL=0,
+ FONT_VARIANT_SMALL_CAPS,
+ FONT_VARIANT_INHERIT
+} ;
+
+enum CRFontWeight
+{
+ FONT_WEIGHT_NORMAL = 1,
+ FONT_WEIGHT_BOLD = 1<<1,
+ FONT_WEIGHT_BOLDER = 1<<2,
+ FONT_WEIGHT_LIGHTER = 1<<3,
+ FONT_WEIGHT_100 = 1<<4,
+ FONT_WEIGHT_200 = 1<<5,
+ FONT_WEIGHT_300 = 1<<6,
+ FONT_WEIGHT_400 = 1<<7,
+ FONT_WEIGHT_500 = 1<<8,
+ FONT_WEIGHT_600 = 1<<9,
+ FONT_WEIGHT_700 = 1<<10,
+ FONT_WEIGHT_800 = 1<<11,
+ FONT_WEIGHT_900 = 1<<12,
+ FONT_WEIGHT_INHERIT = 1<<13,
+ NB_FONT_WEIGHTS
+} ;
+
+enum CRFontStretch
+{
+ FONT_STRETCH_NORMAL=0,
+ FONT_STRETCH_WIDER,
+ FONT_STRETCH_NARROWER,
+ FONT_STRETCH_ULTRA_CONDENSED,
+ FONT_STRETCH_EXTRA_CONDENSED,
+ FONT_STRETCH_CONDENSED,
+ FONT_STRETCH_SEMI_CONDENSED,
+ FONT_STRETCH_SEMI_EXPANDED,
+ FONT_STRETCH_EXPANDED,
+ FONT_STRETCH_EXTRA_EXPANDED,
+ FONT_STRETCH_ULTRA_EXPANDED,
+ FONT_STRETCH_INHERIT
+} ;
+
+/**************************************
+ *'font-family' manipulation functions
+ ***************************************/
+CRFontFamily *
+cr_font_family_new (enum CRFontFamilyType a_type, guchar *a_name) ;
+
+CRFontFamily *
+cr_font_family_append (CRFontFamily *a_this,
+ CRFontFamily *a_family_to_append) ;
+
+guchar *
+cr_font_family_to_string (CRFontFamily const *a_this,
+ gboolean a_walk_font_family_list) ;
+
+CRFontFamily *
+cr_font_family_prepend (CRFontFamily *a_this,
+ CRFontFamily *a_family_to_prepend);
+
+enum CRStatus
+cr_font_family_destroy (CRFontFamily *a_this) ;
+
+enum CRStatus
+cr_font_family_set_name (CRFontFamily *a_this, guchar *a_name) ;
+
+
+/************************************
+ *'font-size' manipulation functions
+ ***********************************/
+
+CRFontSize * cr_font_size_new (void) ;
+
+enum CRStatus cr_font_size_clear (CRFontSize *a_this) ;
+
+enum CRStatus cr_font_size_copy (CRFontSize *a_dst,
+ CRFontSize const *a_src) ;
+enum CRStatus cr_font_size_set_predefined_absolute_font_size (CRFontSize *a_this,
+ enum CRPredefinedAbsoluteFontSize a_predefined) ;
+enum CRStatus cr_font_size_set_relative_font_size (CRFontSize *a_this,
+ enum CRRelativeFontSize a_relative) ;
+
+enum CRStatus cr_font_size_set_absolute_font_size (CRFontSize *a_this,
+ enum CRNumType a_num_type,
+ gdouble a_value) ;
+
+enum CRStatus cr_font_size_set_to_inherit (CRFontSize *a_this) ;
+
+gboolean cr_font_size_is_set_to_inherit (CRFontSize const *a_this) ;
+
+gchar* cr_font_size_to_string (CRFontSize const *a_this) ;
+
+void cr_font_size_destroy (CRFontSize *a_font_size) ;
+
+/*******************************************************
+ *'font-size-adjust' manipulation function declarations
+ *******************************************************/
+
+CRFontSizeAdjust * cr_font_size_adjust_new (void) ;
+
+gchar * cr_font_size_adjust_to_string (CRFontSizeAdjust const *a_this) ;
+
+void cr_font_size_adjust_destroy (CRFontSizeAdjust *a_this) ;
+
+void
+cr_font_size_get_smaller_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size,
+ enum CRPredefinedAbsoluteFontSize *a_smaller_size) ;
+void
+cr_font_size_get_larger_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size,
+ enum CRPredefinedAbsoluteFontSize *a_larger_size) ;
+
+gboolean
+cr_font_size_is_predefined_absolute_font_size (enum CRPredefinedAbsoluteFontSize a_font_size) ;
+
+/***********************************
+ *various other font related functions
+ ***********************************/
+const gchar * cr_font_style_to_string (enum CRFontStyle a_code) ;
+
+const gchar * cr_font_weight_to_string (enum CRFontWeight a_code) ;
+
+enum CRFontWeight
+cr_font_weight_get_bolder (enum CRFontWeight a_weight) ;
+
+const gchar * cr_font_variant_to_string (enum CRFontVariant a_code) ;
+
+const gchar * cr_font_stretch_to_string (enum CRFontStretch a_code) ;
+
+G_END_DECLS
+
+#endif
diff --git a/src/3rdparty/libcroco/src/cr-input.c b/src/3rdparty/libcroco/src/cr-input.c
new file mode 100644
index 0000000..645c4c5
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-input.c
@@ -0,0 +1,1181 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include "stdio.h"
+#include <string.h>
+#include "cr-input.h"
+#include "cr-enc-handler.h"
+
+/**
+ *@CRInput:
+ *
+ *The definition of the #CRInput class.
+ */
+
+/*******************
+ *Private type defs
+ *******************/
+
+/**
+ *The private attributes of
+ *the #CRInputPriv class.
+ */
+struct _CRInputPriv {
+ /*
+ *The input buffer
+ */
+ guchar *in_buf;
+ gulong in_buf_size;
+
+ gulong nb_bytes;
+
+ /*
+ *The index of the next byte
+ *to be read.
+ */
+ gulong next_byte_index;
+
+ /*
+ *The current line number
+ */
+ gulong line;
+
+ /*
+ *The current col number
+ */
+ gulong col;
+
+ gboolean end_of_line;
+ gboolean end_of_input;
+
+ /*
+ *the reference count of this
+ *instance.
+ */
+ guint ref_count;
+ gboolean free_in_buf;
+};
+
+#define PRIVATE(object) (object)->priv
+
+/***************************
+ *private constants
+ **************************/
+#define CR_INPUT_MEM_CHUNK_SIZE 1024 * 4
+
+static CRInput *cr_input_new_real (void);
+
+static CRInput *
+cr_input_new_real (void)
+{
+ CRInput *result = NULL;
+
+ result = g_try_malloc (sizeof (CRInput));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRInput));
+
+ PRIVATE (result) = g_try_malloc (sizeof (CRInputPriv));
+ if (!PRIVATE (result)) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (PRIVATE (result), 0, sizeof (CRInputPriv));
+ PRIVATE (result)->free_in_buf = TRUE;
+ return result;
+}
+
+/****************
+ *Public methods
+ ***************/
+
+/**
+ * cr_input_new_from_buf:
+ *@a_buf: the memory buffer to create the input stream from.
+ *The #CRInput keeps this pointer so user should not free it !.
+ *@a_len: the size of the input buffer.
+ *@a_enc: the buffer's encoding.
+ *@a_free_buf: if set to TRUE, this a_buf will be freed
+ *at the destruction of this instance. If set to false, it is up
+ *to the caller to free it.
+ *
+ *Creates a new input stream from a memory buffer.
+ *Returns the newly built instance of #CRInput.
+ */
+CRInput *
+cr_input_new_from_buf (guchar * a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_buf)
+{
+ CRInput *result = NULL;
+ enum CRStatus status = CR_OK;
+ CREncHandler *enc_handler = NULL;
+ gulong len = a_len;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ result = cr_input_new_real ();
+ g_return_val_if_fail (result, NULL);
+
+ /*transform the encoding in utf8 */
+ if (a_enc != CR_UTF_8) {
+ enc_handler = cr_enc_handler_get_instance (a_enc);
+ if (!enc_handler) {
+ goto error;
+ }
+
+ status = cr_enc_handler_convert_input
+ (enc_handler, a_buf, &len,
+ &PRIVATE (result)->in_buf,
+ &PRIVATE (result)->in_buf_size);
+ if (status != CR_OK)
+ goto error;
+ PRIVATE (result)->free_in_buf = TRUE;
+ if (a_free_buf == TRUE && a_buf) {
+ g_free (a_buf) ;
+ a_buf = NULL ;
+ }
+ PRIVATE (result)->nb_bytes = PRIVATE (result)->in_buf_size;
+ } else {
+ PRIVATE (result)->in_buf = (guchar *) a_buf;
+ PRIVATE (result)->in_buf_size = a_len;
+ PRIVATE (result)->nb_bytes = a_len;
+ PRIVATE (result)->free_in_buf = a_free_buf;
+ }
+ PRIVATE (result)->line = 1;
+ PRIVATE (result)->col = 0;
+ return result;
+
+ error:
+ if (result) {
+ cr_input_destroy (result);
+ result = NULL;
+ }
+
+ return NULL;
+}
+
+/**
+ * cr_input_new_from_uri:
+ *@a_file_uri: the file to create *the input stream from.
+ *@a_enc: the encoding of the file *to create the input from.
+ *
+ *Creates a new input stream from
+ *a file.
+ *
+ *Returns the newly created input stream if
+ *this method could read the file and create it,
+ *NULL otherwise.
+ */
+
+CRInput *
+cr_input_new_from_uri (const gchar * a_file_uri, enum CREncoding a_enc)
+{
+ CRInput *result = NULL;
+ enum CRStatus status = CR_OK;
+ FILE *file_ptr = NULL;
+ guchar tmp_buf[CR_INPUT_MEM_CHUNK_SIZE] = { 0 };
+ gulong nb_read = 0,
+ len = 0;
+ gboolean loop = TRUE;
+ guchar *buf = NULL;
+
+ g_return_val_if_fail (a_file_uri, NULL);
+
+ file_ptr = fopen (a_file_uri, "r");
+
+ if (file_ptr == NULL) {
+
+#ifdef CR_DEBUG
+ cr_utils_trace_debug ("could not open file");
+#endif
+ g_warning ("Could not open file %s\n", a_file_uri);
+
+ return NULL;
+ }
+
+ /*load the file */
+ while (loop) {
+ nb_read = fread (tmp_buf, 1 /*read bytes */ ,
+ CR_INPUT_MEM_CHUNK_SIZE /*nb of bytes */ ,
+ file_ptr);
+
+ if (nb_read != CR_INPUT_MEM_CHUNK_SIZE) {
+ /*we read less chars than we wanted */
+ if (feof (file_ptr)) {
+ /*we reached eof */
+ loop = FALSE;
+ } else {
+ /*a pb occurred !! */
+ cr_utils_trace_debug ("an io error occurred");
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ }
+
+ if (status == CR_OK) {
+ /*read went well */
+ buf = g_realloc (buf, len + CR_INPUT_MEM_CHUNK_SIZE);
+ memcpy (buf + len, tmp_buf, nb_read);
+ len += nb_read;
+ }
+ }
+
+ if (status == CR_OK) {
+ result = cr_input_new_from_buf (buf, len, a_enc, TRUE);
+ if (!result) {
+ goto cleanup;
+ }
+ /*
+ *we should free buf here because it's own by CRInput.
+ *(see the last parameter of cr_input_new_from_buf().
+ */
+ buf = NULL;
+ }
+
+ cleanup:
+ if (file_ptr) {
+ fclose (file_ptr);
+ file_ptr = NULL;
+ }
+
+ if (buf) {
+ g_free (buf);
+ buf = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_input_destroy:
+ *@a_this: the current instance of #CRInput.
+ *
+ *The destructor of the #CRInput class.
+ */
+void
+cr_input_destroy (CRInput * a_this)
+{
+ if (a_this == NULL)
+ return;
+
+ if (PRIVATE (a_this)) {
+ if (PRIVATE (a_this)->in_buf && PRIVATE (a_this)->free_in_buf) {
+ g_free (PRIVATE (a_this)->in_buf);
+ PRIVATE (a_this)->in_buf = NULL;
+ }
+
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ }
+
+ g_free (a_this);
+}
+
+/**
+ * cr_input_ref:
+ *@a_this: the current instance of #CRInput.
+ *
+ *Increments the reference count of the current
+ *instance of #CRInput.
+ */
+void
+cr_input_ref (CRInput * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ PRIVATE (a_this)->ref_count++;
+}
+
+/**
+ * cr_input_unref:
+ *@a_this: the current instance of #CRInput.
+ *
+ *Decrements the reference count of this instance
+ *of #CRInput. If the reference count goes down to
+ *zero, this instance is destroyed.
+ *
+ * Returns TRUE if the instance of #CRInput got destroyed, false otherwise.
+ */
+gboolean
+cr_input_unref (CRInput * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE);
+
+ if (PRIVATE (a_this)->ref_count) {
+ PRIVATE (a_this)->ref_count--;
+ }
+
+ if (PRIVATE (a_this)->ref_count == 0) {
+ cr_input_destroy (a_this);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * cr_input_end_of_input:
+ *@a_this: the current instance of #CRInput.
+ *@a_end_of_input: out parameter. Is set to TRUE if
+ *the current instance has reached the end of its input buffer,
+ *FALSE otherwise.
+ *
+ *Tests whether the current instance of
+ *#CRInput has reached its input buffer.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ * Note that all the out parameters of this method are valid if
+ * and only if this method returns CR_OK.
+ */
+enum CRStatus
+cr_input_end_of_input (CRInput const * a_this, gboolean * a_end_of_input)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_end_of_input, CR_BAD_PARAM_ERROR);
+
+ *a_end_of_input = (PRIVATE (a_this)->next_byte_index
+ >= PRIVATE (a_this)->in_buf_size) ? TRUE : FALSE;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_nb_bytes_left:
+ *@a_this: the current instance of #CRInput.
+ *
+ *Returns the number of bytes left in the input stream
+ *before the end, -1 in case of error.
+ */
+glong
+cr_input_get_nb_bytes_left (CRInput const * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), -1);
+ g_return_val_if_fail (PRIVATE (a_this)->nb_bytes
+ <= PRIVATE (a_this)->in_buf_size, -1);
+ g_return_val_if_fail (PRIVATE (a_this)->next_byte_index
+ <= PRIVATE (a_this)->nb_bytes, -1);
+
+ if (PRIVATE (a_this)->end_of_input)
+ return 0;
+
+ return PRIVATE (a_this)->nb_bytes - PRIVATE (a_this)->next_byte_index;
+}
+
+/**
+ * cr_input_read_byte:
+ *@a_this: the current instance of #CRInput.
+ *@a_byte: out parameter the returned byte.
+ *
+ *Gets the next byte of the input.
+ *Updates the state of the input so that
+ *the next invocation of this method returns
+ *the next coming byte.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise. All the out parameters of this method are valid if
+ *and only if this method returns CR_OK.
+ */
+enum CRStatus
+cr_input_read_byte (CRInput * a_this, guchar * a_byte)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_byte, CR_BAD_PARAM_ERROR);
+
+ g_return_val_if_fail (PRIVATE (a_this)->next_byte_index <=
+ PRIVATE (a_this)->nb_bytes, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->end_of_input == TRUE)
+ return CR_END_OF_INPUT_ERROR;
+
+ *a_byte = PRIVATE (a_this)->in_buf[PRIVATE (a_this)->next_byte_index];
+
+ if (PRIVATE (a_this)->nb_bytes -
+ PRIVATE (a_this)->next_byte_index < 2) {
+ PRIVATE (a_this)->end_of_input = TRUE;
+ } else {
+ PRIVATE (a_this)->next_byte_index++;
+ }
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_read_char:
+ *@a_this: the current instance of CRInput.
+ *@a_char: out parameter. The read character.
+ *
+ *Reads an unicode character from the current instance of
+ *#CRInput.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_read_char (CRInput * a_this, guint32 * a_char)
+{
+ enum CRStatus status = CR_OK;
+ gulong consumed = 0,
+ nb_bytes_left = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
+ CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->end_of_input == TRUE)
+ return CR_END_OF_INPUT_ERROR;
+
+ nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
+
+ if (nb_bytes_left < 1) {
+ return CR_END_OF_INPUT_ERROR;
+ }
+
+ status = cr_utils_read_char_from_utf8_buf
+ (PRIVATE (a_this)->in_buf
+ +
+ PRIVATE (a_this)->next_byte_index,
+ nb_bytes_left, a_char, &consumed);
+
+ if (status == CR_OK) {
+ /*update next byte index */
+ PRIVATE (a_this)->next_byte_index += consumed;
+
+ /*update line and column number */
+ if (PRIVATE (a_this)->end_of_line == TRUE) {
+ PRIVATE (a_this)->col = 1;
+ PRIVATE (a_this)->line++;
+ PRIVATE (a_this)->end_of_line = FALSE;
+ } else if (*a_char != '\n') {
+ PRIVATE (a_this)->col++;
+ }
+
+ if (*a_char == '\n') {
+ PRIVATE (a_this)->end_of_line = TRUE;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * cr_input_set_line_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_line_num: the new line number.
+ *
+ *Setter of the current line number.
+ *
+ *Return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_line_num (CRInput * a_this, glong a_line_num)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->line = a_line_num;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_line_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_line_num: the returned line number.
+ *
+ *Getter of the current line number.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_line_num (CRInput const * a_this, glong * a_line_num)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_line_num, CR_BAD_PARAM_ERROR);
+
+ *a_line_num = PRIVATE (a_this)->line;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_set_column_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_col: the new column number.
+ *
+ *Setter of the current column number.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_column_num (CRInput * a_this, glong a_col)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->col = a_col;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_column_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_col: out parameter
+ *
+ *Getter of the current column number.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_column_num (CRInput const * a_this, glong * a_col)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_col,
+ CR_BAD_PARAM_ERROR);
+
+ *a_col = PRIVATE (a_this)->col;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_increment_line_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_increment: the increment to add to the line number.
+ *
+ *Increments the current line number.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_increment_line_num (CRInput * a_this, glong a_increment)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->line += a_increment;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_increment_col_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_increment: the increment to add to the column number.
+ *
+ *Increments the current column number.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_increment_col_num (CRInput * a_this, glong a_increment)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->col += a_increment;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_consume_char:
+ *@a_this: the this pointer.
+ *@a_char: the character to consume. If set to zero,
+ *consumes any character.
+ *
+ *Consumes the next character of the input stream if
+ *and only if that character equals a_char.
+ *
+ *Returns CR_OK upon successful completion, CR_PARSING_ERROR if
+ *next char is different from a_char, an other error code otherwise
+ */
+enum CRStatus
+cr_input_consume_char (CRInput * a_this, guint32 a_char)
+{
+ guint32 c;
+ enum CRStatus status;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if ((status = cr_input_peek_char (a_this, &c)) != CR_OK) {
+ return status;
+ }
+
+ if (c == a_char || a_char == 0) {
+ status = cr_input_read_char (a_this, &c);
+ } else {
+ return CR_PARSING_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * cr_input_consume_chars:
+ *@a_this: the this pointer of the current instance of #CRInput.
+ *@a_char: the character to consume.
+ *@a_nb_char: in/out parameter. The number of characters to consume.
+ *If set to a negative value, the function will consume all the occurrences
+ *of a_char found.
+ *After return, if the return value equals CR_OK, this variable contains
+ *the number of characters actually consumed.
+ *
+ *Consumes up to a_nb_char occurrences of the next contiguous characters
+ *which equal a_char. Note that the next character of the input stream
+ **MUST* equal a_char to trigger the consumption, or else, the error
+ *code CR_PARSING_ERROR is returned.
+ *If the number of contiguous characters that equals a_char is less than
+ *a_nb_char, then this function consumes all the characters it can consume.
+ *
+ *Returns CR_OK if at least one character has been consumed, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_consume_chars (CRInput * a_this, guint32 a_char, gulong * a_nb_char)
+{
+ enum CRStatus status = CR_OK;
+ gulong nb_consumed = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_char,
+ CR_BAD_PARAM_ERROR);
+
+ g_return_val_if_fail (a_char != 0 || a_nb_char != NULL,
+ CR_BAD_PARAM_ERROR);
+
+ for (nb_consumed = 0; ((status == CR_OK)
+ && (*a_nb_char > 0
+ && nb_consumed < *a_nb_char));
+ nb_consumed++) {
+ status = cr_input_consume_char (a_this, a_char);
+ }
+
+ *a_nb_char = nb_consumed;
+
+ if ((nb_consumed > 0)
+ && ((status == CR_PARSING_ERROR)
+ || (status == CR_END_OF_INPUT_ERROR))) {
+ status = CR_OK;
+ }
+
+ return status;
+}
+
+/**
+ * cr_input_consume_white_spaces:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_nb_chars: in/out parameter. The number of white spaces to
+ *consume. After return, holds the number of white spaces actually consumed.
+ *
+ *Same as cr_input_consume_chars() but this one consumes white
+ *spaces.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_consume_white_spaces (CRInput * a_this, gulong * a_nb_chars)
+{
+ enum CRStatus status = CR_OK;
+ guint32 cur_char = 0,
+ nb_consumed = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_chars,
+ CR_BAD_PARAM_ERROR);
+
+ for (nb_consumed = 0;
+ ((*a_nb_chars > 0) && (nb_consumed < *a_nb_chars));
+ nb_consumed++) {
+ status = cr_input_peek_char (a_this, &cur_char);
+ if (status != CR_OK)
+ break;
+
+ /*if the next char is a white space, consume it ! */
+ if (cr_utils_is_white_space (cur_char) == TRUE) {
+ status = cr_input_read_char (a_this, &cur_char);
+ if (status != CR_OK)
+ break;
+ continue;
+ }
+
+ break;
+
+ }
+
+ *a_nb_chars = (gulong) nb_consumed;
+
+ if (nb_consumed && status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ }
+
+ return status;
+}
+
+/**
+ * cr_input_peek_char:
+ *@a_this: the current instance of #CRInput.
+ *@a_char: out parameter. The returned character.
+ *
+ *Same as cr_input_read_char() but does not update the
+ *internal state of the input stream. The next call
+ *to cr_input_peek_char() or cr_input_read_char() will thus
+ *return the same character as the current one.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_peek_char (CRInput const * a_this, guint32 * a_char)
+{
+ enum CRStatus status = CR_OK;
+ gulong consumed = 0,
+ nb_bytes_left = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_char, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->next_byte_index >=
+ PRIVATE (a_this)->in_buf_size) {
+ return CR_END_OF_INPUT_ERROR;
+ }
+
+ nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
+
+ if (nb_bytes_left < 1) {
+ return CR_END_OF_INPUT_ERROR;
+ }
+
+ status = cr_utils_read_char_from_utf8_buf
+ (PRIVATE (a_this)->in_buf +
+ PRIVATE (a_this)->next_byte_index,
+ nb_bytes_left, a_char, &consumed);
+
+ return status;
+}
+
+/**
+ * cr_input_peek_byte:
+ *@a_this: the current instance of #CRInput.
+ *@a_origin: the origin to consider in the calculation
+ *of the position of the byte to peek.
+ *@a_offset: the offset of the byte to peek, starting from
+ *the origin specified by a_origin.
+ *@a_byte: out parameter the peeked byte.
+ *
+ *Gets a byte from the input stream,
+ *starting from the current position in the input stream.
+ *Unlike cr_input_peek_next_byte() this method
+ *does not update the state of the current input stream.
+ *Subsequent calls to cr_input_peek_byte with the same arguments
+ *will return the same byte.
+ *
+ *Returns CR_OK upon successful completion or,
+ *CR_BAD_PARAM_ERROR if at least one of the parameters is invalid;
+ *CR_OUT_OF_BOUNDS_ERROR if the indexed byte is out of bounds.
+ */
+enum CRStatus
+cr_input_peek_byte (CRInput const * a_this, enum CRSeekPos a_origin,
+ gulong a_offset, guchar * a_byte)
+{
+ gulong abs_offset = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_byte, CR_BAD_PARAM_ERROR);
+
+ switch (a_origin) {
+
+ case CR_SEEK_CUR:
+ abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_offset;
+ break;
+
+ case CR_SEEK_BEGIN:
+ abs_offset = a_offset;
+ break;
+
+ case CR_SEEK_END:
+ abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_offset;
+ break;
+
+ default:
+ return CR_BAD_PARAM_ERROR;
+ }
+
+ if (abs_offset < PRIVATE (a_this)->in_buf_size) {
+
+ *a_byte = PRIVATE (a_this)->in_buf[abs_offset];
+
+ return CR_OK;
+
+ } else {
+ return CR_END_OF_INPUT_ERROR;
+ }
+}
+
+/**
+ * cr_input_peek_byte2:
+ *@a_this: the current byte input stream.
+ *@a_offset: the offset of the byte to peek, starting
+ *from the current input position pointer.
+ *@a_eof: out parameter. Is set to true is we reach end of
+ *stream. If set to NULL by the caller, this parameter is not taken
+ *in account.
+ *
+ *Same as cr_input_peek_byte() but with a simplified
+ *interface.
+ *
+ *Returns the read byte or 0 if something bad happened.
+ */
+guchar
+cr_input_peek_byte2 (CRInput const * a_this, gulong a_offset, gboolean * a_eof)
+{
+ guchar result = 0;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), 0);
+
+ if (a_eof)
+ *a_eof = FALSE;
+
+ status = cr_input_peek_byte (a_this, CR_SEEK_CUR, a_offset, &result);
+
+ if ((status == CR_END_OF_INPUT_ERROR)
+ && a_eof)
+ *a_eof = TRUE;
+
+ return result;
+}
+
+/**
+ * cr_input_get_byte_addr:
+ *@a_this: the current instance of #CRInput.
+ *@a_offset: the offset of the byte in the input stream starting
+ *from the beginning of the stream.
+ *
+ *Gets the memory address of the byte located at a given offset
+ *in the input stream.
+ *
+ *Returns the address, otherwise NULL if an error occurred.
+ */
+guchar *
+cr_input_get_byte_addr (CRInput * a_this, gulong a_offset)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
+
+ if (a_offset >= PRIVATE (a_this)->nb_bytes) {
+ return NULL;
+ }
+
+ return &PRIVATE (a_this)->in_buf[a_offset];
+}
+
+/**
+ * cr_input_get_cur_byte_addr:
+ *@a_this: the current input stream
+ *@a_offset: out parameter. The returned address.
+ *
+ *Gets the address of the current character pointer.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_cur_byte_addr (CRInput * a_this, guchar ** a_offset)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_offset,
+ CR_BAD_PARAM_ERROR);
+
+ if (!PRIVATE (a_this)->next_byte_index) {
+ return CR_START_OF_INPUT_ERROR;
+ }
+
+ *a_offset = cr_input_get_byte_addr
+ (a_this, PRIVATE (a_this)->next_byte_index - 1);
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_seek_index:
+ *@a_this: the current instance of #CRInput.
+ *@a_origin: the origin to consider during the calculation
+ *of the absolute position of the new "current byte index".
+ *@a_pos: the relative offset of the new "current byte index."
+ *This offset is relative to the origin a_origin.
+ *
+ *Sets the "current byte index" of the current instance
+ *of #CRInput. Next call to cr_input_get_byte() will return
+ *the byte next after the new "current byte index".
+ *
+ *Returns CR_OK upon successful completion otherwise returns
+ *CR_BAD_PARAM_ERROR if at least one of the parameters is not valid
+ *or CR_OUT_BOUNDS_ERROR in case of error.
+ */
+enum CRStatus
+cr_input_seek_index (CRInput * a_this, enum CRSeekPos a_origin, gint a_pos)
+{
+
+ glong abs_offset = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ switch (a_origin) {
+
+ case CR_SEEK_CUR:
+ abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_pos;
+ break;
+
+ case CR_SEEK_BEGIN:
+ abs_offset = a_pos;
+ break;
+
+ case CR_SEEK_END:
+ abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_pos;
+ break;
+
+ default:
+ return CR_BAD_PARAM_ERROR;
+ }
+
+ if ((abs_offset > 0)
+ && (gulong) abs_offset < PRIVATE (a_this)->nb_bytes) {
+
+ /*update the input stream's internal state */
+ PRIVATE (a_this)->next_byte_index = abs_offset + 1;
+
+ return CR_OK;
+ }
+
+ return CR_OUT_OF_BOUNDS_ERROR;
+}
+
+/**
+ * cr_input_get_cur_pos:
+ *@a_this: the current instance of #CRInput.
+ *@a_pos: out parameter. The returned position.
+ *
+ *Gets the position of the "current byte index" which
+ *is basically the position of the last returned byte in the
+ *input stream.
+ *
+ *Returns CR_OK upon successful completion. Otherwise,
+ *CR_BAD_PARAMETER_ERROR if at least one of the arguments is invalid.
+ *CR_START_OF_INPUT if no call to either cr_input_read_byte()
+ *or cr_input_seek_index() have been issued before calling
+ *cr_input_get_cur_pos()
+ *Note that the out parameters of this function are valid if and only if this
+ *function returns CR_OK.
+ */
+enum CRStatus
+cr_input_get_cur_pos (CRInput const * a_this, CRInputPos * a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
+ CR_BAD_PARAM_ERROR);
+
+ a_pos->next_byte_index = PRIVATE (a_this)->next_byte_index;
+ a_pos->line = PRIVATE (a_this)->line;
+ a_pos->col = PRIVATE (a_this)->col;
+ a_pos->end_of_line = PRIVATE (a_this)->end_of_line;
+ a_pos->end_of_file = PRIVATE (a_this)->end_of_input;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_parsing_location:
+ *@a_this: the current instance of #CRInput
+ *@a_loc: the set parsing location.
+ *
+ *Gets the current parsing location.
+ *The Parsing location is a public datastructure that
+ *represents the current line/column/byte offset/ in the input
+ *stream.
+ *
+ *Returns CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_input_get_parsing_location (CRInput const *a_this,
+ CRParsingLocation *a_loc)
+{
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && a_loc,
+ CR_BAD_PARAM_ERROR) ;
+
+ a_loc->line = PRIVATE (a_this)->line ;
+ a_loc->column = PRIVATE (a_this)->col ;
+ if (PRIVATE (a_this)->next_byte_index) {
+ a_loc->byte_offset = PRIVATE (a_this)->next_byte_index - 1 ;
+ } else {
+ a_loc->byte_offset = PRIVATE (a_this)->next_byte_index ;
+ }
+ return CR_OK ;
+}
+
+/**
+ * cr_input_get_cur_index:
+ *@a_this: the "this pointer" of the current instance of
+ *#CRInput
+ *@a_index: out parameter. The returned index.
+ *
+ *Getter of the next byte index.
+ *It actually returns the index of the
+ *next byte to be read.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_get_cur_index (CRInput const * a_this, glong * a_index)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_index, CR_BAD_PARAM_ERROR);
+
+ *a_index = PRIVATE (a_this)->next_byte_index;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_set_cur_index:
+ *@a_this: the "this pointer" of the current instance
+ *of #CRInput .
+ *@a_index: the new index to set.
+ *
+ *Setter of the next byte index.
+ *It sets the index of the next byte to be read.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_cur_index (CRInput * a_this, glong a_index)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->next_byte_index = a_index;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_set_end_of_file:
+ *@a_this: the current instance of #CRInput.
+ *@a_eof: the new end of file flag.
+ *
+ *Sets the end of file flag.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_end_of_file (CRInput * a_this, gboolean a_eof)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->end_of_input = a_eof;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_end_of_file:
+ *@a_this: the current instance of #CRInput.
+ *@a_eof: out parameter the place to put the end of
+ *file flag.
+ *
+ *Gets the end of file flag.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_end_of_file (CRInput const * a_this, gboolean * a_eof)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_eof, CR_BAD_PARAM_ERROR);
+
+ *a_eof = PRIVATE (a_this)->end_of_input;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_set_end_of_line:
+ *@a_this: the current instance of #CRInput.
+ *@a_eol: the new end of line flag.
+ *
+ *Sets the end of line flag.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_set_end_of_line (CRInput * a_this, gboolean a_eol)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->end_of_line = a_eol;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_end_of_line:
+ *@a_this: the current instance of #CRInput
+ *@a_eol: out parameter. The place to put
+ *the returned flag
+ *
+ *Gets the end of line flag of the current input.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_get_end_of_line (CRInput const * a_this, gboolean * a_eol)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_eol, CR_BAD_PARAM_ERROR);
+
+ *a_eol = PRIVATE (a_this)->end_of_line;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_set_cur_pos:
+ *@a_this: the "this pointer" of the current instance of
+ *#CRInput.
+ *@a_pos: the new position.
+ *
+ *Sets the current position in the input stream.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_cur_pos (CRInput * a_this, CRInputPos const * a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
+ CR_BAD_PARAM_ERROR);
+
+ cr_input_set_column_num (a_this, a_pos->col);
+ cr_input_set_line_num (a_this, a_pos->line);
+ cr_input_set_cur_index (a_this, a_pos->next_byte_index);
+ cr_input_set_end_of_line (a_this, a_pos->end_of_line);
+ cr_input_set_end_of_file (a_this, a_pos->end_of_file);
+
+ return CR_OK;
+}
diff --git a/src/3rdparty/libcroco/src/cr-input.h b/src/3rdparty/libcroco/src/cr-input.h
new file mode 100644
index 0000000..9eb402a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-input.h
@@ -0,0 +1,174 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See the COPYRIGHTS file for copyrights information.
+ */
+
+#ifndef __CR_INPUT_SRC_H__
+#define __CR_INPUT_SRC_H__
+
+
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The libcroco basic input stream class
+ *declaration file.
+ */
+
+typedef struct _CRInput CRInput ;
+typedef struct _CRInputPriv CRInputPriv ;
+
+/**
+ *The #CRInput class provides the abstraction of
+ *an utf8-encoded character stream.
+ */
+struct _CRInput
+{
+ CRInputPriv *priv ;
+} ;
+
+typedef struct _CRInputPos CRInputPos ;
+
+struct _CRInputPos
+{
+ glong line ;
+ glong col ;
+ gboolean end_of_file ;
+ gboolean end_of_line ;
+ glong next_byte_index ;
+} ;
+
+CRInput *
+cr_input_new_from_buf (guchar *a_buf, gulong a_len,
+ enum CREncoding a_enc, gboolean a_free_buf) ;
+CRInput *
+cr_input_new_from_uri (const gchar *a_file_uri,
+ enum CREncoding a_enc) ;
+
+void
+cr_input_destroy (CRInput *a_this) ;
+
+void
+cr_input_ref (CRInput *a_this) ;
+
+gboolean
+cr_input_unref (CRInput *a_this) ;
+
+enum CRStatus
+cr_input_read_byte (CRInput *a_this, guchar *a_byte) ;
+
+enum CRStatus
+cr_input_read_char (CRInput *a_this, guint32 *a_char) ;
+
+enum CRStatus
+cr_input_consume_chars (CRInput *a_this, guint32 a_char,
+ gulong *a_nb_char) ;
+
+enum CRStatus
+cr_input_consume_char (CRInput *a_this, guint32 a_char) ;
+
+enum CRStatus
+cr_input_consume_white_spaces (CRInput *a_this, gulong *a_nb_chars) ;
+
+enum CRStatus
+cr_input_peek_byte (CRInput const *a_this, enum CRSeekPos a_origin,
+ gulong a_offset, guchar *a_byte) ;
+
+guchar
+cr_input_peek_byte2 (CRInput const *a_this, gulong a_offset,
+ gboolean *a_eof) ;
+
+enum CRStatus
+cr_input_peek_char (CRInput const *a_this, guint32 *a_char) ;
+
+guchar *
+cr_input_get_byte_addr (CRInput *a_this,
+ gulong a_offset) ;
+
+enum CRStatus
+cr_input_get_cur_byte_addr (CRInput *a_this, guchar ** a_offset) ;
+
+enum CRStatus
+cr_input_seek_index (CRInput *a_this,
+ enum CRSeekPos a_origin, gint a_pos) ;
+
+enum CRStatus
+cr_input_get_cur_index (CRInput const *a_this, glong *a_index) ;
+
+enum CRStatus
+cr_input_set_cur_index (CRInput *a_this, glong a_index) ;
+
+enum CRStatus
+cr_input_get_cur_pos (CRInput const *a_this, CRInputPos * a_pos) ;
+
+enum CRStatus
+cr_input_set_cur_pos (CRInput *a_this, CRInputPos const *a_pos) ;
+
+enum CRStatus
+cr_input_get_parsing_location (CRInput const *a_this,
+ CRParsingLocation *a_loc) ;
+
+enum CRStatus
+cr_input_get_end_of_line (CRInput const *a_this, gboolean *a_eol) ;
+
+enum CRStatus
+cr_input_set_end_of_line (CRInput *a_this, gboolean a_eol) ;
+
+enum CRStatus
+cr_input_get_end_of_file (CRInput const *a_this, gboolean *a_eof) ;
+
+enum CRStatus
+cr_input_set_end_of_file (CRInput *a_this, gboolean a_eof) ;
+
+enum CRStatus
+cr_input_set_line_num (CRInput *a_this, glong a_line_num) ;
+
+enum CRStatus
+cr_input_get_line_num (CRInput const *a_this, glong *a_line_num) ;
+
+enum CRStatus
+cr_input_set_column_num (CRInput *a_this, glong a_col) ;
+
+enum CRStatus
+cr_input_get_column_num (CRInput const *a_this, glong *a_col) ;
+
+enum CRStatus
+cr_input_increment_line_num (CRInput *a_this,
+ glong a_increment) ;
+
+enum CRStatus
+cr_input_increment_col_num (CRInput *a_this,
+ glong a_increment) ;
+
+glong
+cr_input_get_nb_bytes_left (CRInput const *a_this) ;
+
+enum CRStatus
+cr_input_end_of_input (CRInput const *a_this, gboolean *a_end_of_input) ;
+
+G_END_DECLS
+
+#endif /*__CR_INPUT_SRC_H__*/
+
diff --git a/src/3rdparty/libcroco/src/cr-libxml-node-iface.c b/src/3rdparty/libcroco/src/cr-libxml-node-iface.c
new file mode 100644
index 0000000..bc860f9
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-libxml-node-iface.c
@@ -0,0 +1,81 @@
+#include <libxml/tree.h>
+#include <string.h>
+#include "cr-libxml-node-iface.h"
+
+static CRXMLNodePtr
+libxml_getParentNode(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return xnode->parent;
+}
+
+static CRXMLNodePtr
+libxml_getFirstChild(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return xnode->children;
+}
+
+static CRXMLNodePtr
+libxml_getNextSibling(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return xnode->next;
+}
+
+static CRXMLNodePtr
+libxml_getPrevSibling(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return xnode->prev;
+}
+
+static char const *
+local_part(char const *const qname)
+{
+ char const *ret = strrchr(qname, ':');
+ if (ret)
+ return ++ret;
+ else
+ return qname;
+}
+
+static char const *
+libxml_getLocalName(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return local_part((char *)xnode->name);
+}
+
+static char *
+libxml_getProp(CRXMLNodePtr cnode, char const *cprop)
+{
+ xmlNodePtr xnode = (xmlNodePtr) cnode;
+ xmlChar const *xprop = (xmlChar const *) cprop;
+ return (char *)xmlGetProp(xnode, xprop);
+}
+
+static gboolean
+libxml_isElementNode(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return xnode->type == XML_ELEMENT_NODE;
+}
+
+static void
+libxml_freePropVal(void *const cval)
+{
+ xmlFree(cval);
+}
+
+CRNodeIface const cr_libxml_node_iface = {
+ libxml_getParentNode,
+ libxml_getFirstChild,
+ libxml_getNextSibling,
+ libxml_getPrevSibling,
+ libxml_getLocalName,
+ libxml_getProp, /* fixme: Check whether we want xmlGetNoNsProp instead. */
+
+ libxml_freePropVal,
+ libxml_isElementNode
+};
diff --git a/src/3rdparty/libcroco/src/cr-libxml-node-iface.h b/src/3rdparty/libcroco/src/cr-libxml-node-iface.h
new file mode 100644
index 0000000..b4a6212
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-libxml-node-iface.h
@@ -0,0 +1,14 @@
+#ifndef __CR_LIBXML_NODE_IFACE_H__
+#define __CR_LIBXML_NODE_IFACE_H__
+
+#include <glib.h>
+#include "cr-node-iface.h"
+
+G_BEGIN_DECLS
+
+extern CRNodeIface const cr_libxml_node_iface;
+
+G_END_DECLS
+
+
+#endif/*__CR_LIBXML_NODE_IFACE_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-node-iface.h b/src/3rdparty/libcroco/src/cr-node-iface.h
new file mode 100644
index 0000000..01898d6
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-node-iface.h
@@ -0,0 +1,34 @@
+#ifndef __CR_NODE_IFACE_H__
+#define __CR_NODE_IFACE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef gconstpointer CRXMLNodePtr ;
+typedef struct _CRNodeIface CRNodeIface ;
+
+struct _CRNodeIface {
+ /* Names based on DOM. */
+ CRXMLNodePtr (*getParentNode)(CRXMLNodePtr);
+ CRXMLNodePtr (*getFirstChild)(CRXMLNodePtr);
+ CRXMLNodePtr (*getNextSibling)(CRXMLNodePtr);
+ CRXMLNodePtr (*getPrevSibling)(CRXMLNodePtr);
+ char const *(*getLocalName)(CRXMLNodePtr);
+ char *(*getProp)(CRXMLNodePtr, char const *);
+
+ /* Others. */
+ void (*freePropVal)(void *);
+ gboolean (*isElementNode)(CRXMLNodePtr);
+
+#if 0
+ char const *getLang(CRXMLNodePtr);
+ /* todo: Make it easy to have the default xml rules for lang. Maybe interpret NULL
+ like this. Or provide a cr_get_xml_lang(CRNodeIface const *, CRXMLNodePtr) function. */
+#endif
+};
+
+G_END_DECLS
+
+
+#endif/*__CR_NODE_IFACE_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-num.c b/src/3rdparty/libcroco/src/cr-num.c
new file mode 100644
index 0000000..12da520
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-num.c
@@ -0,0 +1,345 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+/**
+ *@CRNum:
+ *
+ *The definition
+ *of the #CRNum class.
+ */
+
+#include "cr-num.h"
+#include "string.h"
+
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+
+/**
+ * cr_num_new:
+ *
+ *#CRNum.
+ *
+ *Returns the newly built instance of
+ *#CRNum.
+ */
+CRNum *
+cr_num_new (void)
+{
+ CRNum *result = NULL;
+
+ result = g_try_malloc (sizeof (CRNum));
+
+ if (result == NULL) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRNum));
+
+ return result;
+}
+
+/**
+ * cr_num_new_with_val:
+ * @a_val: the numerical value of the number.
+ * @a_type: the type of number.
+ *
+ * A constructor of #CRNum.
+ *
+ * Returns the newly built instance of #CRNum or
+ * NULL if an error arises.
+ */
+CRNum *
+cr_num_new_with_val (gdouble a_val, enum CRNumType a_type)
+{
+ CRNum *result = NULL;
+
+ result = cr_num_new ();
+
+ g_return_val_if_fail (result, NULL);
+
+ result->val = a_val;
+ result->type = a_type;
+
+ return result;
+}
+
+
+/**
+ * Like g_ascii_dtostr() but uses not more than DBL_DIG significant digits
+ * to avoid results like "1.0000000000000001".
+ */
+static void
+pretty_ascii_dtostr (gchar *buffer, gint buf_len, gdouble d)
+{
+ gint digits = DBL_DIG - ceil (log10 (fabs (d)));
+ gchar format[8] = "%.";
+ sprintf (format + 2, "%df", CLAMP (digits, 0, 9999));
+
+ g_ascii_formatd (buffer, buf_len, format, d);
+
+ // strip trailing zeros and trailing dot
+ if (strchr (buffer, '.') != NULL) {
+ gsize pos = strlen (buffer) - 1;
+ while (buffer[pos] == '0') {
+ --pos;
+ }
+ if (buffer[pos] == '.') {
+ --pos;
+ }
+ buffer[pos + 1] = '\0';
+ }
+}
+
+/**
+ * cr_num_to_string:
+ *@a_this: the current instance of #CRNum.
+ *
+ *Returns the newly built string representation
+ *of the current instance of #CRNum. The returned
+ *string is NULL terminated. The caller *must*
+ *free the returned string.
+ */
+guchar *
+cr_num_to_string (CRNum const * a_this)
+{
+ gdouble test_val = 0.0;
+
+ guchar *tmp_char1 = NULL,
+ *tmp_char2 = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ test_val = a_this->val - (glong) a_this->val;
+
+ if (!test_val) {
+ tmp_char1 = (guchar *) g_strdup_printf ("%ld", (glong) a_this->val);
+ } else {
+ tmp_char1 = (guchar *) g_new0 (char, G_ASCII_DTOSTR_BUF_SIZE + 1);
+ if (tmp_char1 != NULL)
+ pretty_ascii_dtostr ((gchar *) tmp_char1, G_ASCII_DTOSTR_BUF_SIZE, a_this->val);
+ }
+
+ g_return_val_if_fail (tmp_char1, NULL);
+
+ switch (a_this->type) {
+ case NUM_LENGTH_EM:
+ tmp_char2 = (guchar *) "em";
+ break;
+
+ case NUM_LENGTH_EX:
+ tmp_char2 = (guchar *) "ex";
+ break;
+
+ case NUM_LENGTH_PX:
+ tmp_char2 = (guchar *) "px";
+ break;
+
+ case NUM_LENGTH_IN:
+ tmp_char2 = (guchar *) "in";
+ break;
+
+ case NUM_LENGTH_CM:
+ tmp_char2 = (guchar *) "cm";
+ break;
+
+ case NUM_LENGTH_MM:
+ tmp_char2 = (guchar *) "mm";
+ break;
+
+ case NUM_LENGTH_PT:
+ tmp_char2 = (guchar *) "pt";
+ break;
+
+ case NUM_LENGTH_PC:
+ tmp_char2 = (guchar *) "pc";
+ break;
+
+ case NUM_ANGLE_DEG:
+ tmp_char2 = (guchar *) "deg";
+ break;
+
+ case NUM_ANGLE_RAD:
+ tmp_char2 = (guchar *) "rad";
+ break;
+
+ case NUM_ANGLE_GRAD:
+ tmp_char2 = (guchar *) "grad";
+ break;
+
+ case NUM_TIME_MS:
+ tmp_char2 = (guchar *) "ms";
+ break;
+
+ case NUM_TIME_S:
+ tmp_char2 = (guchar *) "s";
+ break;
+
+ case NUM_FREQ_HZ:
+ tmp_char2 = (guchar *) "Hz";
+ break;
+
+ case NUM_FREQ_KHZ:
+ tmp_char2 = (guchar *) "KHz";
+ break;
+
+ case NUM_PERCENTAGE:
+ tmp_char2 = (guchar *) "%";
+ break;
+ case NUM_INHERIT:
+ tmp_char2 = (guchar *) "inherit";
+ break ;
+ case NUM_AUTO:
+ tmp_char2 = (guchar *) "auto";
+ break ;
+ case NUM_GENERIC:
+ tmp_char2 = NULL ;
+ break ;
+ default:
+ tmp_char2 = (guchar *) "unknown";
+ break;
+ }
+
+ if (tmp_char2) {
+ result = (guchar *) g_strconcat ((gchar *) tmp_char1, tmp_char2, NULL);
+ g_free (tmp_char1);
+ } else {
+ result = tmp_char1;
+ }
+
+ return result;
+}
+
+/**
+ * cr_num_copy:
+ *@a_src: the instance of #CRNum to copy.
+ *Must be non NULL.
+ *@a_dest: the destination of the copy.
+ *Must be non NULL
+ *
+ *Copies an instance of #CRNum.
+ *
+ *Returns CR_OK upon successful completion, an
+ *error code otherwise.
+ */
+enum CRStatus
+cr_num_copy (CRNum * a_dest, CRNum const * a_src)
+{
+ g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
+
+ memcpy (a_dest, a_src, sizeof (CRNum));
+
+ return CR_OK;
+}
+
+/**
+ * cr_num_dup:
+ *@a_this: the instance of #CRNum to duplicate.
+ *
+ *Duplicates an instance of #CRNum
+ *
+ *Returns the newly created (duplicated) instance of #CRNum.
+ *Must be freed by cr_num_destroy().
+ */
+CRNum *
+cr_num_dup (CRNum const * a_this)
+{
+ CRNum *result = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ result = cr_num_new ();
+ g_return_val_if_fail (result, NULL);
+
+ status = cr_num_copy (result, a_this);
+ if (status != CR_OK)
+ g_clear_pointer (&result, cr_num_destroy);
+
+ return result;
+}
+
+/**
+ * cr_num_set:
+ *Sets an instance of #CRNum.
+ *@a_this: the current instance of #CRNum to be set.
+ *@a_val: the new numerical value to be hold by the current
+ *instance of #CRNum
+ *@a_type: the new type of #CRNum.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_num_set (CRNum * a_this, gdouble a_val, enum CRNumType a_type)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ a_this->val = a_val;
+ a_this->type = a_type;
+
+ return CR_OK;
+}
+
+/**
+ * cr_num_is_fixed_length:
+ * @a_this: the current instance of #CRNum .
+ *
+ *Tests if the current instance of #CRNum is a fixed
+ *length value or not. Typically a fixed length value
+ *is anything from NUM_LENGTH_EM to NUM_LENGTH_PC.
+ *See the definition of #CRNumType to see what we mean.
+ *
+ *Returns TRUE if the instance of #CRNum is a fixed length number,
+ *FALSE otherwise.
+ */
+gboolean
+cr_num_is_fixed_length (CRNum const * a_this)
+{
+ gboolean result = FALSE;
+
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->type >= NUM_LENGTH_EM
+ && a_this->type <= NUM_LENGTH_PC) {
+ result = TRUE ;
+ }
+ return result ;
+}
+
+/**
+ * cr_num_destroy:
+ *@a_this: the this pointer of
+ *the current instance of #CRNum.
+ *
+ *The destructor of #CRNum.
+ */
+void
+cr_num_destroy (CRNum * a_this)
+{
+ g_return_if_fail (a_this);
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-num.h b/src/3rdparty/libcroco/src/cr-num.h
new file mode 100644
index 0000000..2b73aaf
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-num.h
@@ -0,0 +1,127 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information
+ */
+
+
+/**
+ *@file
+ *The declaration
+ *of the #CRNum class.
+ */
+
+#ifndef __CR_NUM_H__
+#define __CR_NUM_H__
+
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The declaration of the #CRNum class.
+ *
+ */
+
+/**
+ *The different types
+ *of numbers.
+ *Please, do not modify
+ *the declaration order of the enum
+ *members, unless you know
+ *what you are doing.
+ */
+enum CRNumType
+{
+ NUM_AUTO = 0,
+ NUM_GENERIC,
+ NUM_LENGTH_EM,
+ NUM_LENGTH_EX,
+ NUM_LENGTH_PX,
+ NUM_LENGTH_IN,
+ NUM_LENGTH_CM,
+ NUM_LENGTH_MM,
+ NUM_LENGTH_PT,
+ NUM_LENGTH_PC,
+ NUM_ANGLE_DEG,
+ NUM_ANGLE_RAD,
+ NUM_ANGLE_GRAD,
+ NUM_TIME_MS,
+ NUM_TIME_S,
+ NUM_FREQ_HZ,
+ NUM_FREQ_KHZ,
+ NUM_PERCENTAGE,
+ NUM_INHERIT,
+ NUM_UNKNOWN_TYPE,
+ NB_NUM_TYPE
+} ;
+
+
+/**
+ *An abstraction of a number (num)
+ *as defined in the css2 spec.
+ */
+typedef struct _CRNum CRNum ;
+
+/**
+ *An abstraction of a number (num)
+ *as defined in the css2 spec.
+ */
+struct _CRNum
+{
+ enum CRNumType type ;
+ gdouble val ;
+ CRParsingLocation location ;
+} ;
+
+CRNum *
+cr_num_new (void) ;
+
+CRNum *
+cr_num_new_with_val (gdouble a_val,
+ enum CRNumType a_type) ;
+
+CRNum *
+cr_num_dup (CRNum const *a_this) ;
+
+guchar *
+cr_num_to_string (CRNum const *a_this) ;
+
+enum CRStatus
+cr_num_copy (CRNum *a_dest, CRNum const *a_src) ;
+
+enum CRStatus
+cr_num_set (CRNum *a_this, gdouble a_val,
+ enum CRNumType a_type) ;
+
+gboolean
+cr_num_is_fixed_length (CRNum const *a_this) ;
+
+void
+cr_num_destroy (CRNum *a_this) ;
+
+
+G_END_DECLS
+
+
+#endif /*__CR_NUM_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-om-parser.c b/src/3rdparty/libcroco/src/cr-om-parser.c
new file mode 100644
index 0000000..3b0ae26
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-om-parser.c
@@ -0,0 +1,1150 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-utils.h"
+#include "cr-om-parser.h"
+
+/**
+ *@CROMParser:
+ *
+ *The definition of the CSS Object Model Parser.
+ *This parser uses (and sits) the SAC api of libcroco defined
+ *in cr-parser.h and cr-doc-handler.h
+ */
+
+struct _CROMParserPriv {
+ CRParser *parser;
+};
+
+#define PRIVATE(a_this) ((a_this)->priv)
+
+/*
+ *Forward declaration of a type defined later
+ *in this file.
+ */
+struct _ParsingContext;
+typedef struct _ParsingContext ParsingContext;
+
+static ParsingContext *new_parsing_context (void);
+
+static void destroy_context (ParsingContext * a_ctxt);
+
+static void unrecoverable_error (CRDocHandler * a_this);
+
+static void error (CRDocHandler * a_this);
+
+static void property (CRDocHandler * a_this,
+ CRString * a_name,
+ CRTerm * a_expression,
+ gboolean a_important);
+
+static void end_selector (CRDocHandler * a_this,
+ CRSelector * a_selector_list);
+
+static void start_selector (CRDocHandler * a_this,
+ CRSelector * a_selector_list);
+
+static void start_font_face (CRDocHandler * a_this,
+ CRParsingLocation *a_location);
+
+static void end_font_face (CRDocHandler * a_this);
+
+static void end_document (CRDocHandler * a_this);
+
+static void start_document (CRDocHandler * a_this);
+
+static void charset (CRDocHandler * a_this,
+ CRString * a_charset,
+ CRParsingLocation *a_location);
+
+static void start_page (CRDocHandler * a_this, CRString * a_page,
+ CRString * a_pseudo_page,
+ CRParsingLocation *a_location);
+
+static void end_page (CRDocHandler * a_this, CRString * a_page,
+ CRString * a_pseudo_page);
+
+static void start_media (CRDocHandler * a_this,
+ GList * a_media_list,
+ CRParsingLocation *a_location);
+
+static void end_media (CRDocHandler * a_this,
+ GList * a_media_list);
+
+static void import_style (CRDocHandler * a_this,
+ GList * a_media_list,
+ CRString * a_uri,
+ CRString * a_uri_default_ns,
+ CRParsingLocation *a_location);
+
+struct _ParsingContext {
+ CRStyleSheet *stylesheet;
+ CRStatement *cur_stmt;
+ CRStatement *cur_media_stmt;
+};
+
+/********************************************
+ *Private methods
+ ********************************************/
+
+static ParsingContext *
+new_parsing_context (void)
+{
+ ParsingContext *result = NULL;
+
+ result = g_try_malloc (sizeof (ParsingContext));
+ if (!result) {
+ cr_utils_trace_info ("Out of Memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (ParsingContext));
+ return result;
+}
+
+static void
+destroy_context (ParsingContext * a_ctxt)
+{
+ g_return_if_fail (a_ctxt);
+
+ if (a_ctxt->stylesheet) {
+ cr_stylesheet_destroy (a_ctxt->stylesheet);
+ a_ctxt->stylesheet = NULL;
+ }
+ if (a_ctxt->cur_stmt) {
+ cr_statement_destroy (a_ctxt->cur_stmt);
+ a_ctxt->cur_stmt = NULL;
+ }
+ g_free (a_ctxt);
+}
+
+static enum CRStatus
+cr_om_parser_init_default_sac_handler (CROMParser * a_this)
+{
+ CRDocHandler *sac_handler = NULL;
+ gboolean created_handler = FALSE;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->parser,
+ CR_BAD_PARAM_ERROR);
+
+ status = cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
+ &sac_handler);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ if (!sac_handler) {
+ sac_handler = cr_doc_handler_new ();
+ created_handler = TRUE;
+ }
+
+ /*
+ *initialize here the sac handler.
+ */
+ sac_handler->start_document = start_document;
+ sac_handler->end_document = end_document;
+ sac_handler->start_selector = start_selector;
+ sac_handler->end_selector = end_selector;
+ sac_handler->property = property;
+ sac_handler->start_font_face = start_font_face;
+ sac_handler->end_font_face = end_font_face;
+ sac_handler->error = error;
+ sac_handler->unrecoverable_error = unrecoverable_error;
+ sac_handler->charset = charset;
+ sac_handler->start_page = start_page;
+ sac_handler->end_page = end_page;
+ sac_handler->start_media = start_media;
+ sac_handler->end_media = end_media;
+ sac_handler->import_style = import_style;
+
+ if (created_handler) {
+ status = cr_parser_set_sac_handler (PRIVATE (a_this)->parser,
+ sac_handler);
+ cr_doc_handler_unref (sac_handler);
+ }
+
+ return status;
+
+}
+
+static void
+start_document (CRDocHandler * a_this)
+{
+ ParsingContext *ctxt = NULL;
+ CRStyleSheet *stylesheet = NULL;
+
+ g_return_if_fail (a_this);
+
+ ctxt = new_parsing_context ();
+ g_return_if_fail (ctxt);
+
+ stylesheet = cr_stylesheet_new (NULL);
+ ctxt->stylesheet = stylesheet;
+ cr_doc_handler_set_ctxt (a_this, ctxt);
+}
+
+static void
+start_font_face (CRDocHandler * a_this,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ (void) a_location;
+
+ g_return_if_fail (a_this);
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+ g_return_if_fail (ctxt->cur_stmt == NULL);
+
+ ctxt->cur_stmt =
+ cr_statement_new_at_font_face_rule (ctxt->stylesheet, NULL);
+
+ g_return_if_fail (ctxt->cur_stmt);
+}
+
+static void
+end_font_face (CRDocHandler * a_this)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ CRStatement *stmts = NULL;
+
+ g_return_if_fail (a_this);
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+ g_return_if_fail
+ (ctxt->cur_stmt
+ && ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT
+ && ctxt->stylesheet);
+
+ stmts = cr_statement_append (ctxt->stylesheet->statements,
+ ctxt->cur_stmt);
+ if (!stmts)
+ goto error;
+
+ ctxt->stylesheet->statements = stmts;
+ stmts = NULL;
+ ctxt->cur_stmt = NULL;
+
+ return;
+
+ error:
+
+ if (ctxt->cur_stmt) {
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ }
+
+ if (!stmts) {
+ cr_statement_destroy (stmts);
+ stmts = NULL;
+ }
+}
+
+static void
+end_document (CRDocHandler * a_this)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ if (!ctxt->stylesheet || ctxt->cur_stmt)
+ goto error;
+
+ status = cr_doc_handler_set_result (a_this, ctxt->stylesheet);
+ g_return_if_fail (status == CR_OK);
+
+ ctxt->stylesheet = NULL;
+ destroy_context (ctxt);
+ cr_doc_handler_set_ctxt (a_this, NULL);
+
+ return;
+
+ error:
+ if (ctxt) {
+ destroy_context (ctxt);
+ }
+}
+
+static void
+charset (CRDocHandler * a_this, CRString * a_charset,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *stmt = NULL,
+ *stmt2 = NULL;
+ CRString *charset = NULL;
+
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ (void) a_location;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+ g_return_if_fail (ctxt->stylesheet);
+
+ charset = cr_string_dup (a_charset) ;
+ stmt = cr_statement_new_at_charset_rule (ctxt->stylesheet, charset);
+ if (stmt)
+ stmt2 = cr_statement_append (ctxt->stylesheet->statements, stmt);
+ if (!stmt2) {
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+ if (charset) {
+ cr_string_destroy (charset);
+ }
+ return;
+ }
+ ctxt->stylesheet->statements = stmt2;
+ stmt2 = NULL;
+}
+
+static void
+start_page (CRDocHandler * a_this,
+ CRString * a_page,
+ CRString * a_pseudo,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ (void) a_location;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+ g_return_if_fail (ctxt->cur_stmt == NULL);
+
+ ctxt->cur_stmt = cr_statement_new_at_page_rule
+ (ctxt->stylesheet, NULL, NULL, NULL);
+ if (a_page) {
+ ctxt->cur_stmt->kind.page_rule->name =
+ cr_string_dup (a_page) ;
+
+ if (!ctxt->cur_stmt->kind.page_rule->name) {
+ goto error;
+ }
+ }
+ if (a_pseudo) {
+ ctxt->cur_stmt->kind.page_rule->pseudo =
+ cr_string_dup (a_pseudo) ;
+ if (!ctxt->cur_stmt->kind.page_rule->pseudo) {
+ goto error;
+ }
+ }
+ return;
+
+ error:
+ if (ctxt->cur_stmt) {
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ }
+}
+
+static void
+end_page (CRDocHandler * a_this,
+ CRString * a_page,
+ CRString * a_pseudo_page)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ CRStatement *stmt = NULL;
+
+ (void) a_page;
+ (void) a_pseudo_page;
+
+ g_return_if_fail (a_this);
+
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ g_return_if_fail (ctxt->cur_stmt
+ && ctxt->cur_stmt->type == AT_PAGE_RULE_STMT
+ && ctxt->stylesheet);
+
+ stmt = cr_statement_append (ctxt->stylesheet->statements,
+ ctxt->cur_stmt);
+
+ if (stmt) {
+ ctxt->stylesheet->statements = stmt;
+ stmt = NULL;
+ ctxt->cur_stmt = NULL;
+ }
+
+ if (ctxt->cur_stmt) {
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ }
+ a_page = NULL; /*keep compiler happy */
+ a_pseudo_page = NULL; /*keep compiler happy */
+}
+
+static void
+start_media (CRDocHandler * a_this,
+ GList * a_media_list,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ GList *media_list = NULL;
+
+ (void) a_location;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ g_return_if_fail (ctxt
+ && ctxt->cur_stmt == NULL
+ && ctxt->cur_media_stmt == NULL
+ && ctxt->stylesheet);
+ if (a_media_list) {
+ /*duplicate the media_list */
+ media_list = cr_utils_dup_glist_of_cr_string
+ (a_media_list);
+ }
+ ctxt->cur_media_stmt =
+ cr_statement_new_at_media_rule
+ (ctxt->stylesheet, NULL, media_list);
+
+}
+
+static void
+end_media (CRDocHandler * a_this, GList * a_media_list)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ CRStatement *stmts = NULL;
+
+ (void) a_media_list;
+
+ g_return_if_fail (a_this);
+
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ g_return_if_fail (ctxt
+ && ctxt->cur_media_stmt
+ && ctxt->cur_media_stmt->type == AT_MEDIA_RULE_STMT
+ && ctxt->stylesheet);
+
+ stmts = cr_statement_append (ctxt->stylesheet->statements,
+ ctxt->cur_media_stmt);
+
+ if (!stmts) {
+ cr_statement_destroy (ctxt->cur_media_stmt);
+ ctxt->cur_media_stmt = NULL;
+ }
+
+ ctxt->stylesheet->statements = stmts;
+ stmts = NULL;
+
+ ctxt->cur_stmt = NULL ;
+ ctxt->cur_media_stmt = NULL ;
+ a_media_list = NULL;
+}
+
+static void
+import_style (CRDocHandler * a_this,
+ GList * a_media_list,
+ CRString * a_uri,
+ CRString * a_uri_default_ns,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ CRString *uri = NULL;
+ CRStatement *stmt = NULL,
+ *stmt2 = NULL;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ GList *media_list = NULL ;
+
+ (void) a_uri_default_ns;
+ (void) a_location;
+
+ g_return_if_fail (a_this);
+
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ g_return_if_fail (ctxt->stylesheet);
+
+ uri = cr_string_dup (a_uri) ;
+
+ if (a_media_list)
+ media_list = cr_utils_dup_glist_of_cr_string (a_media_list) ;
+
+ stmt = cr_statement_new_at_import_rule
+ (ctxt->stylesheet, uri, media_list, NULL);
+
+ if (!stmt)
+ goto error;
+
+ if (ctxt->cur_stmt) {
+ stmt2 = cr_statement_append (ctxt->cur_stmt, stmt);
+ if (!stmt2)
+ goto error;
+ ctxt->cur_stmt = stmt2;
+ stmt2 = NULL;
+ stmt = NULL;
+ } else {
+ stmt2 = cr_statement_append (ctxt->stylesheet->statements,
+ stmt);
+ if (!stmt2)
+ goto error;
+ ctxt->stylesheet->statements = stmt2;
+ stmt2 = NULL;
+ stmt = NULL;
+ }
+
+ return;
+
+ error:
+ if (uri) {
+ cr_string_destroy (uri);
+ }
+
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+ a_uri_default_ns = NULL; /*keep compiler happy */
+}
+
+static void
+start_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
+{
+ enum CRStatus status = CR_OK ;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+ if (ctxt->cur_stmt) {
+ /*hmm, this should be NULL so free it */
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ }
+
+ ctxt->cur_stmt = cr_statement_new_ruleset
+ (ctxt->stylesheet, a_selector_list, NULL, NULL);
+}
+
+static void
+end_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ (void) a_selector_list;
+
+ g_return_if_fail (a_this);
+
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet);
+
+ if (ctxt->cur_stmt) {
+ CRStatement *stmts = NULL;
+
+ if (ctxt->cur_media_stmt) {
+ CRAtMediaRule *media_rule = NULL;
+
+ media_rule = ctxt->cur_media_stmt->kind.media_rule;
+
+ stmts = cr_statement_append
+ (media_rule->rulesets, ctxt->cur_stmt);
+
+ if (!stmts) {
+ cr_utils_trace_info
+ ("Could not append a new statement");
+ cr_statement_destroy (media_rule->rulesets);
+ ctxt->cur_media_stmt->
+ kind.media_rule->rulesets = NULL;
+ return;
+ }
+ media_rule->rulesets = stmts;
+ ctxt->cur_stmt = NULL;
+ } else {
+ stmts = cr_statement_append
+ (ctxt->stylesheet->statements,
+ ctxt->cur_stmt);
+ if (!stmts) {
+ cr_utils_trace_info
+ ("Could not append a new statement");
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ return;
+ }
+ ctxt->stylesheet->statements = stmts;
+ ctxt->cur_stmt = NULL;
+ }
+
+ }
+
+ a_selector_list = NULL; /*keep compiler happy */
+}
+
+static void
+property (CRDocHandler * a_this,
+ CRString * a_name,
+ CRTerm * a_expression,
+ gboolean a_important)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ CRDeclaration *decl = NULL,
+ *decl2 = NULL;
+ CRString *str = NULL;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ /*
+ *make sure a current ruleset statement has been allocated
+ *already.
+ */
+ g_return_if_fail
+ (ctxt->cur_stmt
+ &&
+ (ctxt->cur_stmt->type == RULESET_STMT
+ || ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT
+ || ctxt->cur_stmt->type == AT_PAGE_RULE_STMT));
+
+ if (a_name) {
+ str = cr_string_dup (a_name);
+ g_return_if_fail (str);
+ }
+
+ /*instantiates a new declaration */
+ decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression);
+ if (decl == NULL)
+ g_clear_pointer (&str, cr_string_destroy);
+ g_return_if_fail (decl);
+ str = NULL;
+ decl->important = a_important;
+ /*
+ *add the new declaration to the current statement
+ *being build.
+ */
+ switch (ctxt->cur_stmt->type) {
+ case RULESET_STMT:
+ decl2 = cr_declaration_append
+ (ctxt->cur_stmt->kind.ruleset->decl_list, decl);
+ if (!decl2) {
+ cr_utils_trace_info
+ ("Could not append decl to ruleset");
+ goto error;
+ }
+ ctxt->cur_stmt->kind.ruleset->decl_list = decl2;
+ decl = NULL;
+ decl2 = NULL;
+ break;
+
+ case AT_FONT_FACE_RULE_STMT:
+ decl2 = cr_declaration_append
+ (ctxt->cur_stmt->kind.font_face_rule->decl_list,
+ decl);
+ if (!decl2) {
+ cr_utils_trace_info
+ ("Could not append decl to ruleset");
+ goto error;
+ }
+ ctxt->cur_stmt->kind.font_face_rule->decl_list = decl2;
+ decl = NULL;
+ decl2 = NULL;
+ break;
+ case AT_PAGE_RULE_STMT:
+ decl2 = cr_declaration_append
+ (ctxt->cur_stmt->kind.page_rule->decl_list, decl);
+ if (!decl2) {
+ cr_utils_trace_info
+ ("Could not append decl to ruleset");
+ goto error;
+ }
+ ctxt->cur_stmt->kind.page_rule->decl_list = decl2;
+ decl = NULL;
+ decl2 = NULL;
+ break;
+
+ default:
+ goto error;
+ break;
+ }
+
+ return;
+
+ error:
+ if (str) {
+ g_free (str);
+ str = NULL;
+ }
+
+ if (decl) {
+ cr_declaration_destroy (decl);
+ decl = NULL;
+ }
+}
+
+static void
+error (CRDocHandler * a_this)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ if (ctxt->cur_stmt) {
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ }
+}
+
+static void
+unrecoverable_error (CRDocHandler * a_this)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK);
+
+ if (ctxt) {
+ if (ctxt->stylesheet) {
+ status = cr_doc_handler_set_result
+ (a_this, ctxt->stylesheet);
+ g_return_if_fail (status == CR_OK);
+ }
+ g_free (ctxt);
+ cr_doc_handler_set_ctxt (a_this, NULL);
+ }
+}
+
+/********************************************
+ *Public methods
+ ********************************************/
+
+/**
+ * cr_om_parser_new:
+ *@a_input: the input stream.
+ *
+ *Constructor of the CROMParser.
+ *Returns the newly built instance of #CROMParser.
+ */
+CROMParser *
+cr_om_parser_new (CRInput * a_input)
+{
+ CROMParser *result = NULL;
+ enum CRStatus status = CR_OK;
+
+ result = g_try_malloc (sizeof (CROMParser));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CROMParser));
+ PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv));
+
+ if (!PRIVATE (result)) {
+ cr_utils_trace_info ("Out of memory");
+ goto error;
+ }
+
+ memset (PRIVATE (result), 0, sizeof (CROMParserPriv));
+
+ PRIVATE (result)->parser = cr_parser_new_from_input (a_input);
+
+ if (!PRIVATE (result)->parser) {
+ cr_utils_trace_info ("parsing instantiation failed");
+ goto error;
+ }
+
+ status = cr_om_parser_init_default_sac_handler (result);
+
+ if (status != CR_OK) {
+ goto error;
+ }
+
+ return result;
+
+ error:
+
+ if (result) {
+ cr_om_parser_destroy (result);
+ }
+
+ return NULL;
+}
+
+/**
+ * cr_om_parser_parse_buf:
+ *@a_this: the current instance of #CROMParser.
+ *@a_buf: the in memory buffer to parse.
+ *@a_len: the length of the in memory buffer in number of bytes.
+ *@a_enc: the encoding of the in memory buffer.
+ *@a_result: out parameter the resulting style sheet
+ *
+ *Parses the content of an in memory buffer.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_om_parser_parse_buf (CROMParser * a_this,
+ const guchar * a_buf,
+ gulong a_len,
+ enum CREncoding a_enc, CRStyleSheet ** a_result)
+{
+
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR);
+
+ if (!PRIVATE (a_this)->parser) {
+ PRIVATE (a_this)->parser = cr_parser_new (NULL);
+ }
+
+ status = cr_parser_parse_buf (PRIVATE (a_this)->parser,
+ a_buf, a_len, a_enc);
+
+ if (status == CR_OK) {
+ CRStyleSheet *result = NULL;
+ CRStyleSheet **resultptr = NULL;
+ CRDocHandler *sac_handler = NULL;
+
+ cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
+ &sac_handler);
+ g_return_val_if_fail (sac_handler, CR_ERROR);
+ resultptr = &result;
+ status = cr_doc_handler_get_result (sac_handler,
+ (gpointer *) resultptr);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ if (result)
+ *a_result = result;
+ }
+
+ return status;
+}
+
+/**
+ * cr_om_parser_simply_parse_buf:
+ *@a_buf: the css2 in memory buffer.
+ *@a_len: the length of the in memory buffer.
+ *@a_enc: the encoding of the in memory buffer.
+ *@a_result: out parameter. The resulting css2 style sheet.
+ *
+ *The simpler way to parse an in memory css2 buffer.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_om_parser_simply_parse_buf (const guchar * a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ CRStyleSheet ** a_result)
+{
+ CROMParser *parser = NULL;
+ enum CRStatus status = CR_OK;
+
+ parser = cr_om_parser_new (NULL);
+ if (!parser) {
+ cr_utils_trace_info ("Could not create om parser");
+ cr_utils_trace_info ("System possibly out of memory");
+ return CR_ERROR;
+ }
+
+ status = cr_om_parser_parse_buf (parser, a_buf, a_len,
+ a_enc, a_result);
+
+ if (parser) {
+ cr_om_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ return status;
+}
+
+/**
+ * cr_om_parser_parse_file:
+ *@a_this: the current instance of the cssom parser.
+ *@a_file_uri: the uri of the file.
+ *(only local file paths are supported so far)
+ *@a_enc: the encoding of the file.
+ *@a_result: out parameter. A pointer
+ *the build css object model.
+ *
+ *Parses a css2 stylesheet contained
+ *in a file.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_om_parser_parse_file (CROMParser * a_this,
+ const guchar * a_file_uri,
+ enum CREncoding a_enc, CRStyleSheet ** a_result)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && a_file_uri && a_result,
+ CR_BAD_PARAM_ERROR);
+
+ if (!PRIVATE (a_this)->parser) {
+ PRIVATE (a_this)->parser = cr_parser_new_from_file
+ (a_file_uri, a_enc);
+ }
+
+ status = cr_parser_parse_file (PRIVATE (a_this)->parser,
+ a_file_uri, a_enc);
+
+ if (status == CR_OK) {
+ CRStyleSheet *result = NULL;
+ CRStyleSheet **resultptr = NULL;
+ CRDocHandler *sac_handler = NULL;
+
+ cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
+ &sac_handler);
+ g_return_val_if_fail (sac_handler, CR_ERROR);
+ resultptr = &result;
+ status = cr_doc_handler_get_result
+ (sac_handler, (gpointer *) resultptr);
+ g_return_val_if_fail (status == CR_OK, status);
+ if (result)
+ *a_result = result;
+ }
+
+ return status;
+}
+
+/**
+ * cr_om_parser_simply_parse_file:
+ *@a_file_path: the css2 local file path.
+ *@a_enc: the file encoding.
+ *@a_result: out parameter. The returned css stylesheet.
+ *Must be freed by the caller using cr_stylesheet_destroy.
+ *
+ *The simpler method to parse a css2 file.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ *Note that this method uses cr_om_parser_parse_file() so both methods
+ *have the same return values.
+ */
+enum CRStatus
+cr_om_parser_simply_parse_file (const guchar * a_file_path,
+ enum CREncoding a_enc,
+ CRStyleSheet ** a_result)
+{
+ CROMParser *parser = NULL;
+ enum CRStatus status = CR_OK;
+
+ parser = cr_om_parser_new (NULL);
+ if (!parser) {
+ cr_utils_trace_info ("Could not allocate om parser");
+ cr_utils_trace_info ("System may be out of memory");
+ return CR_ERROR;
+ }
+
+ status = cr_om_parser_parse_file (parser, a_file_path,
+ a_enc, a_result);
+ if (parser) {
+ cr_om_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ return status;
+}
+
+/**
+ * cr_om_parser_parse_paths_to_cascade:
+ *@a_this: the current instance of #CROMParser
+ *@a_author_path: the path to the author stylesheet
+ *@a_user_path: the path to the user stylesheet
+ *@a_ua_path: the path to the User Agent stylesheet
+ *@a_encoding: the encoding of the sheets.
+ *@a_result: out parameter. The resulting cascade if the parsing
+ *was okay
+ *
+ *Parses three sheets located by their paths and build a cascade
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise
+ */
+enum CRStatus
+cr_om_parser_parse_paths_to_cascade (CROMParser * a_this,
+ const guchar * a_author_path,
+ const guchar * a_user_path,
+ const guchar * a_ua_path,
+ enum CREncoding a_encoding,
+ CRCascade ** a_result)
+{
+ enum CRStatus status = CR_OK;
+
+ /*0->author sheet, 1->user sheet, 2->UA sheet */
+ CRStyleSheet *sheets[3];
+ guchar *paths[3];
+ CRCascade *result = NULL;
+ gint i = 0;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ memset (sheets, 0, sizeof (CRStyleSheet*) * 3);
+ paths[0] = (guchar *) a_author_path;
+ paths[1] = (guchar *) a_user_path;
+ paths[2] = (guchar *) a_ua_path;
+
+ for (i = 0; i < 3; i++) {
+ status = cr_om_parser_parse_file (a_this, paths[i],
+ a_encoding, &sheets[i]);
+ if (status != CR_OK) {
+ if (sheets[i]) {
+ cr_stylesheet_unref (sheets[i]);
+ sheets[i] = NULL;
+ }
+ continue;
+ }
+ }
+ result = cr_cascade_new (sheets[0], sheets[1], sheets[2]);
+ if (!result) {
+ for (i = 0; i < 3; i++) {
+ cr_stylesheet_unref (sheets[i]);
+ sheets[i] = 0;
+ }
+ return CR_ERROR;
+ }
+ *a_result = result;
+ return CR_OK;
+}
+
+/**
+ * cr_om_parser_simply_parse_paths_to_cascade:
+ *@a_author_path: the path to the author stylesheet
+ *@a_user_path: the path to the user stylesheet
+ *@a_ua_path: the path to the User Agent stylesheet
+ *@a_encoding: the encoding of the sheets.
+ *@a_result: out parameter. The resulting cascade if the parsing
+ *was okay
+ *
+ *Parses three sheets located by their paths and build a cascade
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise
+ */
+enum CRStatus
+cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path,
+ const guchar * a_user_path,
+ const guchar * a_ua_path,
+ enum CREncoding a_encoding,
+ CRCascade ** a_result)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+
+ parser = cr_om_parser_new (NULL);
+ if (!parser) {
+ cr_utils_trace_info ("could not allocated om parser");
+ cr_utils_trace_info ("System may be out of memory");
+ return CR_ERROR;
+ }
+ status = cr_om_parser_parse_paths_to_cascade (parser,
+ a_author_path,
+ a_user_path,
+ a_ua_path,
+ a_encoding, a_result);
+ if (parser) {
+ cr_om_parser_destroy (parser);
+ parser = NULL;
+ }
+ return status;
+}
+
+/**
+ * cr_om_parser_destroy:
+ *@a_this: the current instance of #CROMParser.
+ *
+ *Destructor of the #CROMParser.
+ */
+void
+cr_om_parser_destroy (CROMParser * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ if (PRIVATE (a_this)->parser) {
+ cr_parser_destroy (PRIVATE (a_this)->parser);
+ PRIVATE (a_this)->parser = NULL;
+ }
+
+ if (PRIVATE (a_this)) {
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ }
+
+ if (a_this) {
+ g_free (a_this);
+ a_this = NULL;
+ }
+}
diff --git a/src/3rdparty/libcroco/src/cr-om-parser.h b/src/3rdparty/libcroco/src/cr-om-parser.h
new file mode 100644
index 0000000..13d35b1
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-om-parser.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+#ifndef __CR_OM_PARSER_H__
+#define __CR_OM_PARSER_H__
+
+#include "cr-parser.h"
+#include "cr-cascade.h"
+
+
+/**
+ *@file
+ *The definition of the CSS Object Model Parser.
+ *This parser uses (and sits) the SAC api of libcroco defined
+ *in cr-parser.h and cr-doc-handler.h
+ */
+
+G_BEGIN_DECLS
+
+typedef struct _CROMParser CROMParser ;
+typedef struct _CROMParserPriv CROMParserPriv ;
+
+/**
+ *The Object model parser.
+ *Can parse a css file and build a css object model.
+ *This parser uses an instance of #CRParser and defines
+ *a set of SAC callbacks to build the Object Model.
+ */
+struct _CROMParser
+{
+ CROMParserPriv *priv ;
+} ;
+
+CROMParser * cr_om_parser_new (CRInput *a_input) ;
+
+
+enum CRStatus cr_om_parser_simply_parse_file (const guchar *a_file_path,
+ enum CREncoding a_enc,
+ CRStyleSheet **a_result) ;
+
+enum CRStatus cr_om_parser_parse_file (CROMParser *a_this,
+ const guchar *a_file_uri,
+ enum CREncoding a_enc,
+ CRStyleSheet **a_result) ;
+
+enum CRStatus cr_om_parser_simply_parse_buf (const guchar *a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ CRStyleSheet **a_result) ;
+
+enum CRStatus cr_om_parser_parse_buf (CROMParser *a_this,
+ const guchar *a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ CRStyleSheet **a_result) ;
+
+enum CRStatus cr_om_parser_parse_paths_to_cascade (CROMParser *a_this,
+ const guchar *a_author_path,
+ const guchar *a_user_path,
+ const guchar *a_ua_path,
+ enum CREncoding a_encoding,
+ CRCascade ** a_result) ;
+
+enum CRStatus cr_om_parser_simply_parse_paths_to_cascade (const guchar *a_author_path,
+ const guchar *a_user_path,
+ const guchar *a_ua_path,
+ enum CREncoding a_encoding,
+ CRCascade ** a_result) ;
+
+void cr_om_parser_destroy (CROMParser *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_OM_PARSER_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-parser.c b/src/3rdparty/libcroco/src/cr-parser.c
new file mode 100644
index 0000000..e9a5f90
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-parser.c
@@ -0,0 +1,4568 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the
+ * GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+/**
+ *@CRParser:
+ *
+ *The definition of the #CRParser class.
+ */
+
+#include "string.h"
+#include "cr-parser.h"
+#include "cr-num.h"
+#include "cr-term.h"
+#include "cr-simple-sel.h"
+#include "cr-attr-sel.h"
+
+/*
+ *Random notes:
+ *CSS core syntax vs CSS level 2 syntax
+ *=====================================
+ *
+ *One must keep in mind
+ *that css UA must comply with two syntaxes.
+ *
+ *1/the specific syntax that defines the css language
+ *for a given level of specification (e.g css2 syntax
+ *defined in appendix D.1 of the css2 spec)
+ *
+ *2/the core (general) syntax that is there to allow
+ *UAs to parse style sheets written in levels of CSS that
+ *didn't exist at the time the UAs were created.
+ *
+ *the name of parsing functions (or methods) contained in this file
+ *follows the following scheme: cr_parser_parse_<production_name> (...) ;
+ *where <production_name> is the name
+ *of a production of the css2 language.
+ *When a given production is
+ *defined by the css2 level grammar *and* by the
+ *css core syntax, there will be two functions to parse that production:
+ *one will parse the production defined by the css2 level grammar and the
+ *other will parse the production defined by the css core grammar.
+ *The css2 level grammar related parsing function will be called:
+ *cr_parser_parse_<production_name> (...) ;
+ *Then css core grammar related parsing function will be called:
+ *cr_parser_parse_<production_name>_core (...) ;
+ *
+ *If a production is defined only by the css core grammar, then
+ *it will be named:
+ *cr_parser_parse_<production_name>_core (...) ;
+ */
+
+typedef struct _CRParserError CRParserError;
+
+/**
+ *An abstraction of an error reported by by the
+ *parsing routines.
+ */
+struct _CRParserError {
+ guchar *msg;
+ enum CRStatus status;
+ glong line;
+ glong column;
+ glong byte_num;
+};
+
+enum CRParserState {
+ READY_STATE = 0,
+ TRY_PARSE_CHARSET_STATE,
+ CHARSET_PARSED_STATE,
+ TRY_PARSE_IMPORT_STATE,
+ IMPORT_PARSED_STATE,
+ TRY_PARSE_RULESET_STATE,
+ RULESET_PARSED_STATE,
+ TRY_PARSE_MEDIA_STATE,
+ MEDIA_PARSED_STATE,
+ TRY_PARSE_PAGE_STATE,
+ PAGE_PARSED_STATE,
+ TRY_PARSE_FONT_FACE_STATE,
+ FONT_FACE_PARSED_STATE
+} ;
+
+/**
+ *The private attributes of
+ *#CRParser.
+ */
+struct _CRParserPriv {
+ /**
+ *The tokenizer
+ */
+ CRTknzr *tknzr;
+
+ /**
+ *The sac handlers to call
+ *to notify the parsing of
+ *the css2 constructions.
+ */
+ CRDocHandler *sac_handler;
+
+ /**
+ *A stack of errors reported
+ *by the parsing routines.
+ *Contains instance of #CRParserError.
+ *This pointer is the top of the stack.
+ */
+ GList *err_stack;
+
+ enum CRParserState state;
+ gboolean resolve_import;
+ gboolean is_case_sensitive;
+ gboolean use_core_grammar;
+};
+
+#define PRIVATE(obj) ((obj)->priv)
+
+#define CHARS_TAB_SIZE 12
+
+#define RECURSIVE_CALLERS_LIMIT 100
+
+/**
+ * IS_NUM:
+ *@a_char: the char to test.
+ *return TRUE if the character is a number ([0-9]), FALSE otherwise
+ */
+#define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE)
+
+/**
+ *Checks if 'status' equals CR_OK. If not, goto the 'error' label.
+ *
+ *@param status the status (of type enum CRStatus) to test.
+ *@param is_exception if set to FALSE, the final status returned
+ *by the current function will be CR_PARSING_ERROR. If set to TRUE, the
+ *current status will be the current value of the 'status' variable.
+ *
+ */
+#define CHECK_PARSING_STATUS(status, is_exception) \
+if ((status) != CR_OK) \
+{ \
+ if (is_exception == FALSE) \
+ { \
+ status = CR_PARSING_ERROR ; \
+ } \
+ goto error ; \
+}
+
+/**
+ * CHECK_PARSING_STATUS_ERR:
+ *@a_this: the current instance of #CRParser .
+ *@a_status: the status to check. Is of type enum #CRStatus.
+ *@a_is_exception: in case of error, if is TRUE, the status
+ *is set to CR_PARSING_ERROR before goto error. If is false, the
+ *real low level status is kept and will be returned by the
+ *upper level function that called this macro. Usually, this must
+ *be set to FALSE.
+ *
+ *same as CHECK_PARSING_STATUS() but this one pushes an error
+ *on the parser error stack when an error arises.
+ *
+ */
+#define CHECK_PARSING_STATUS_ERR(a_this, a_status, a_is_exception,\
+ a_err_msg, a_err_status) \
+if ((a_status) != CR_OK) \
+{ \
+ if (a_is_exception == FALSE) a_status = CR_PARSING_ERROR ; \
+ cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
+ goto error ; \
+}
+
+/**
+ *Peeks the next char from the input stream of the current parser
+ *by invoking cr_tknzr_input_peek_char().
+ *invokes CHECK_PARSING_STATUS on the status returned by
+ *cr_tknzr_peek_char().
+ *
+ *@param a_this the current instance of #CRParser.
+ *@param a_to_char a pointer to the char where to store the
+ *char peeked.
+ */
+#define PEEK_NEXT_CHAR(a_this, a_to_char) \
+{\
+status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
+CHECK_PARSING_STATUS (status, TRUE) \
+}
+
+/**
+ *Reads the next char from the input stream of the current parser.
+ *In case of error, jumps to the "error:" label located in the
+ *function where this macro is called.
+ *@param a_this the current instance of #CRParser
+ *@param to_char a pointer to the guint32 char where to store
+ *the character read.
+ */
+#define READ_NEXT_CHAR(a_this, a_to_char) \
+status = cr_tknzr_read_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
+CHECK_PARSING_STATUS (status, TRUE)
+
+/**
+ *Gets information about the current position in
+ *the input of the parser.
+ *In case of failure, this macro returns from the
+ *calling function and
+ *returns a status code of type enum #CRStatus.
+ *@param a_this the current instance of #CRParser.
+ *@param a_pos out parameter. A pointer to the position
+ *inside the current parser input. Must
+ */
+#define RECORD_INITIAL_POS(a_this, a_pos) \
+status = cr_tknzr_get_cur_pos (PRIVATE \
+(a_this)->tknzr, a_pos) ; \
+g_return_val_if_fail (status == CR_OK, status)
+
+/**
+ *Gets the address of the current byte inside the
+ *parser input.
+ *@param parser the current instance of #CRParser.
+ *@param addr out parameter a pointer (guchar*)
+ *to where the address must be put.
+ */
+#define RECORD_CUR_BYTE_ADDR(a_this, a_addr) \
+status = cr_tknzr_get_cur_byte_addr \
+ (PRIVATE (a_this)->tknzr, a_addr) ; \
+CHECK_PARSING_STATUS (status, TRUE)
+
+/**
+ *Peeks a byte from the topmost parser input at
+ *a given offset from the current position.
+ *If it fails, goto the "error:" label.
+ *
+ *@param a_parser the current instance of #CRParser.
+ *@param a_offset the offset of the byte to peek, the
+ *current byte having the offset '0'.
+ *@param a_byte_ptr out parameter a pointer (guchar*) to
+ *where the peeked char is to be stored.
+ */
+#define PEEK_BYTE(a_parser, a_offset, a_byte_ptr) \
+status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr, \
+ a_offset, \
+ a_byte_ptr) ; \
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+#define BYTE(a_parser, a_offset, a_eof) \
+cr_tknzr_peek_byte2 (PRIVATE (a_this)->tknzr, a_offset, a_eof)
+
+/**
+ *Reads a byte from the topmost parser input
+ *steam.
+ *If it fails, goto the "error" label.
+ *@param a_this the current instance of #CRParser.
+ *@param a_byte_ptr the guchar * where to put the read char.
+ */
+#define READ_NEXT_BYTE(a_this, a_byte_ptr) \
+status = cr_tknzr_read_byte (PRIVATE (a_this)->tknzr, a_byte_ptr) ; \
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+/**
+ *Skips a given number of byte in the topmost
+ *parser input. Don't update line and column number.
+ *In case of error, jumps to the "error:" label
+ *of the surrounding function.
+ *@param a_parser the current instance of #CRParser.
+ *@param a_nb_bytes the number of bytes to skip.
+ */
+#define SKIP_BYTES(a_this, a_nb_bytes) \
+status = cr_tknzr_seek_index (PRIVATE (a_this)->tknzr, \
+ CR_SEEK_CUR, a_nb_bytes) ; \
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+/**
+ *Skip utf8 encoded characters.
+ *Updates line and column numbers.
+ *@param a_parser the current instance of #CRParser.
+ *@param a_nb_chars the number of chars to skip. Must be of
+ *type glong.
+ */
+#define SKIP_CHARS(a_parser, a_nb_chars) \
+{ \
+glong nb_chars = a_nb_chars ; \
+status = cr_tknzr_consume_chars \
+ (PRIVATE (a_parser)->tknzr,0, &nb_chars) ; \
+CHECK_PARSING_STATUS (status, TRUE) ; \
+}
+
+/**
+ *Tests the condition and if it is false, sets
+ *status to "CR_PARSING_ERROR" and goto the 'error'
+ *label.
+ *@param condition the condition to test.
+ */
+#define ENSURE_PARSING_COND(condition) \
+if (! (condition)) {status = CR_PARSING_ERROR; goto error ;}
+
+#define ENSURE_PARSING_COND_ERR(a_this, a_condition, \
+ a_err_msg, a_err_status) \
+if (! (a_condition)) \
+{ \
+ status = CR_PARSING_ERROR; \
+ cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
+ goto error ; \
+}
+
+#define GET_NEXT_TOKEN(a_this, a_token_ptr) \
+status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, \
+ a_token_ptr) ; \
+ENSURE_PARSING_COND (status == CR_OK) ;
+
+#ifdef WITH_UNICODE_ESCAPE_AND_RANGE
+static enum CRStatus cr_parser_parse_unicode_escape (CRParser * a_this,
+ guint32 * a_unicode);
+static enum CRStatus cr_parser_parse_escape (CRParser * a_this,
+ guint32 * a_esc_code);
+
+static enum CRStatus cr_parser_parse_unicode_range (CRParser * a_this,
+ CRString ** a_inf,
+ CRString ** a_sup);
+#endif
+
+static enum CRStatus cr_parser_parse_stylesheet_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_atrule_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_ruleset_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_selector_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_declaration_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_any_core (CRParser * a_this,
+ guint n_calls);
+
+static enum CRStatus cr_parser_parse_block_core (CRParser * a_this,
+ guint n_calls);
+
+static enum CRStatus cr_parser_parse_value_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_string (CRParser * a_this,
+ CRString ** a_str);
+
+static enum CRStatus cr_parser_parse_ident (CRParser * a_this,
+ CRString ** a_str);
+
+static enum CRStatus cr_parser_parse_uri (CRParser * a_this,
+ CRString ** a_str);
+
+static enum CRStatus cr_parser_parse_function (CRParser * a_this,
+ CRString ** a_func_name,
+ CRTerm ** a_expr);
+static enum CRStatus cr_parser_parse_property (CRParser * a_this,
+ CRString ** a_property);
+
+static enum CRStatus cr_parser_parse_attribute_selector (CRParser * a_this,
+ CRAttrSel ** a_sel);
+
+static enum CRStatus cr_parser_parse_simple_selector (CRParser * a_this,
+ CRSimpleSel ** a_sel);
+
+static enum CRStatus cr_parser_parse_simple_sels (CRParser * a_this,
+ CRSimpleSel ** a_sel);
+
+static CRParserError *cr_parser_error_new (const guchar * a_msg,
+ enum CRStatus);
+
+static void cr_parser_error_set_msg (CRParserError * a_this,
+ const guchar * a_msg);
+
+static void cr_parser_error_dump (CRParserError * a_this);
+
+static void cr_parser_error_set_status (CRParserError * a_this,
+ enum CRStatus a_status);
+
+static void cr_parser_error_set_pos (CRParserError * a_this,
+ glong a_line,
+ glong a_column, glong a_byte_num);
+static void
+ cr_parser_error_destroy (CRParserError * a_this);
+
+static enum CRStatus cr_parser_push_error (CRParser * a_this,
+ const guchar * a_msg,
+ enum CRStatus a_status);
+
+static enum CRStatus cr_parser_dump_err_stack (CRParser * a_this,
+ gboolean a_clear_errs);
+static enum CRStatus
+ cr_parser_clear_errors (CRParser * a_this);
+
+/*****************************
+ *error managemet methods
+ *****************************/
+
+/**
+ *Constructor of #CRParserError class.
+ *@param a_msg the brute error message.
+ *@param a_status the error status.
+ *@return the newly built instance of #CRParserError.
+ */
+static CRParserError *
+cr_parser_error_new (const guchar * a_msg, enum CRStatus a_status)
+{
+ CRParserError *result = NULL;
+
+ result = g_try_malloc (sizeof (CRParserError));
+
+ if (result == NULL) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRParserError));
+
+ cr_parser_error_set_msg (result, a_msg);
+ cr_parser_error_set_status (result, a_status);
+
+ return result;
+}
+
+/**
+ *Sets the message associated to this instance of #CRError.
+ *@param a_this the current instance of #CRParserError.
+ *@param a_msg the new message.
+ */
+static void
+cr_parser_error_set_msg (CRParserError * a_this, const guchar * a_msg)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->msg) {
+ g_free (a_this->msg);
+ }
+
+ a_this->msg = (guchar *) g_strdup ((const gchar *) a_msg);
+}
+
+/**
+ *Sets the error status.
+ *@param a_this the current instance of #CRParserError.
+ *@param a_status the new error status.
+ *
+ */
+static void
+cr_parser_error_set_status (CRParserError * a_this, enum CRStatus a_status)
+{
+ g_return_if_fail (a_this);
+
+ a_this->status = a_status;
+}
+
+/**
+ *Sets the position of the parser error.
+ *@param a_this the current instance of #CRParserError.
+ *@param a_line the line number.
+ *@param a_column the column number.
+ *@param a_byte_num the byte number.
+ */
+static void
+cr_parser_error_set_pos (CRParserError * a_this,
+ glong a_line, glong a_column, glong a_byte_num)
+{
+ g_return_if_fail (a_this);
+
+ a_this->line = a_line;
+ a_this->column = a_column;
+ a_this->byte_num = a_byte_num;
+}
+
+static void
+cr_parser_error_dump (CRParserError * a_this)
+{
+ g_return_if_fail (a_this);
+
+ g_printerr ("parsing error: %ld:%ld:", a_this->line, a_this->column);
+
+ g_printerr ("%s\n", a_this->msg);
+}
+
+/**
+ *The destructor of #CRParserError.
+ *@param a_this the current instance of #CRParserError.
+ */
+static void
+cr_parser_error_destroy (CRParserError * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->msg) {
+ g_free (a_this->msg);
+ a_this->msg = NULL;
+ }
+
+ g_free (a_this);
+}
+
+/**
+ *Pushes an error on the parser error stack.
+ *@param a_this the current instance of #CRParser.
+ *@param a_msg the error message.
+ *@param a_status the error status.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_push_error (CRParser * a_this,
+ const guchar * a_msg, enum CRStatus a_status)
+{
+ enum CRStatus status = CR_OK;
+
+ CRParserError *error = NULL;
+ CRInputPos pos;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_msg, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &pos);
+
+ error = cr_parser_error_new (a_msg, a_status);
+
+ g_return_val_if_fail (error, CR_ERROR);
+
+ cr_parser_error_set_pos
+ (error, pos.line, pos.col, pos.next_byte_index - 1);
+
+ PRIVATE (a_this)->err_stack =
+ g_list_prepend (PRIVATE (a_this)->err_stack, error);
+
+ if (PRIVATE (a_this)->err_stack == NULL)
+ goto error;
+
+ return CR_OK;
+
+ error:
+
+ if (error) {
+ cr_parser_error_destroy (error);
+ error = NULL;
+ }
+
+ return status;
+}
+
+/**
+ *Dumps the error stack using g_printerr.
+ *@param a_this the current instance of #CRParser.
+ *@param a_clear_errs whether to clear the error stack
+ *after the dump or not.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+static enum CRStatus
+cr_parser_dump_err_stack (CRParser * a_this, gboolean a_clear_errs)
+{
+ GList *cur = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->err_stack == NULL)
+ return CR_OK;
+
+ for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
+ cr_parser_error_dump ((CRParserError *) cur->data);
+ }
+
+ if (a_clear_errs == TRUE) {
+ cr_parser_clear_errors (a_this);
+ }
+
+ return CR_OK;
+}
+
+/**
+ *Clears all the errors contained in the parser error stack.
+ *Frees all the errors, and the stack that contains'em.
+ *@param a_this the current instance of #CRParser.
+ */
+static enum CRStatus
+cr_parser_clear_errors (CRParser * a_this)
+{
+ GList *cur = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
+ if (cur->data) {
+ cr_parser_error_destroy ((CRParserError *)
+ cur->data);
+ }
+ }
+
+ if (PRIVATE (a_this)->err_stack) {
+ g_list_free (PRIVATE (a_this)->err_stack);
+ PRIVATE (a_this)->err_stack = NULL;
+ }
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_try_to_skip_spaces_and_comments:
+ *@a_this: the current instance of #CRParser.
+ *
+ *Same as cr_parser_try_to_skip_spaces() but this one skips
+ *spaces and comments.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_try_to_skip_spaces_and_comments (CRParser * a_this)
+{
+ enum CRStatus status = CR_ERROR;
+ CRToken *token = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
+ do {
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ if (status != CR_OK)
+ goto error;
+ }
+ while ((token != NULL)
+ && (token->type == COMMENT_TK || token->type == S_TK));
+
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+
+ return status;
+
+ error:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ return status;
+}
+
+/***************************************
+ *End of Parser input handling routines
+ ***************************************/
+
+
+/*************************************
+ *Non trivial terminal productions
+ *parsing routines
+ *************************************/
+
+/**
+ *Parses a css stylesheet following the core css grammar.
+ *This is mainly done for test purposes.
+ *During the parsing, no callback is called. This is just
+ *to validate that the stylesheet is well formed according to the
+ *css core syntax.
+ *stylesheet : [ CDO | CDC | S | statement ]*;
+ *@param a_this the current instance of #CRParser.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_stylesheet_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ continue_parsing:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ goto done;
+ } else if (status != CR_OK) {
+ goto error;
+ }
+
+ switch (token->type) {
+
+ case CDO_TK:
+ case CDC_TK:
+ goto continue_parsing;
+ break;
+ default:
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+ status = cr_parser_parse_statement_core (a_this);
+ cr_parser_clear_errors (a_this);
+ if (status == CR_OK) {
+ goto continue_parsing;
+ } else if (status == CR_END_OF_INPUT_ERROR) {
+ goto done;
+ } else {
+ goto error;
+ }
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+ cr_parser_push_error
+ (a_this, (const guchar *) "could not recognize next production", CR_ERROR);
+
+ cr_parser_dump_err_stack (a_this, TRUE);
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses an at-rule as defined by the css core grammar
+ *in chapter 4.1 in the css2 spec.
+ *at-rule : ATKEYWORD S* any* [ block | ';' S* ];
+ *@param a_this the current instance of #CRParser.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_atrule_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ &&
+ (token->type == ATKEYWORD_TK
+ || token->type == IMPORT_SYM_TK
+ || token->type == PAGE_SYM_TK
+ || token->type == MEDIA_SYM_TK
+ || token->type == FONT_FACE_SYM_TK
+ || token->type == CHARSET_SYM_TK));
+
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ do {
+ status = cr_parser_parse_any_core (a_this, 0);
+ } while (status == CR_OK);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == CBO_TK) {
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ status = cr_parser_parse_block_core (a_this, 0);
+ CHECK_PARSING_STATUS (status,
+ FALSE);
+ goto done;
+ } else if (token->type == SEMICOLON_TK) {
+ goto done;
+ } else {
+ status = CR_PARSING_ERROR ;
+ goto error;
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr,
+ &init_pos);
+ return status;
+}
+
+/**
+ *Parses a ruleset as defined by the css core grammar in chapter
+ *4.1 of the css2 spec.
+ *ruleset ::= selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*;
+ *@param a_this the current instance of #CRParser.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_ruleset_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_selector_core (a_this);
+
+ ENSURE_PARSING_COND (status == CR_OK
+ || status == CR_PARSING_ERROR
+ || status == CR_END_OF_INPUT_ERROR);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == CBO_TK);
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_declaration_core (a_this);
+
+ parse_declaration_list:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+ if (token->type == CBC_TK) {
+ goto done;
+ }
+
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == SEMICOLON_TK);
+
+ cr_token_destroy (token);
+ token = NULL;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_declaration_core (a_this);
+ cr_parser_clear_errors (a_this);
+ ENSURE_PARSING_COND (status == CR_OK || status == CR_PARSING_ERROR);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+ if (token->type == CBC_TK) {
+ cr_token_destroy (token);
+ token = NULL;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ goto done;
+ } else {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ goto parse_declaration_list;
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (status == CR_OK) {
+ return CR_OK;
+ }
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a "selector" as specified by the css core
+ *grammar.
+ *selector : any+;
+ *@param a_this the current instance of #CRParser.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_selector_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_any_core (a_this, 0);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ do {
+ status = cr_parser_parse_any_core (a_this, 0);
+
+ } while (status == CR_OK);
+
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a "block" as defined in the css core grammar
+ *in chapter 4.1 of the css2 spec.
+ *block ::= '{' S* [ any | block | ATKEYWORD S* | ';' ]* '}' S*;
+ *@param a_this the current instance of #CRParser.
+ *@param n_calls used to limit recursion depth
+ *FIXME: code this function.
+ */
+static enum CRStatus
+cr_parser_parse_block_core (CRParser * a_this,
+ guint n_calls)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if (n_calls > RECURSIVE_CALLERS_LIMIT)
+ return CR_ERROR;
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == CBO_TK);
+
+ parse_block_content:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == CBC_TK) {
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ goto done;
+ } else if (token->type == SEMICOLON_TK) {
+ goto parse_block_content;
+ } else if (token->type == ATKEYWORD_TK) {
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ goto parse_block_content;
+ } else if (token->type == CBO_TK) {
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ status = cr_parser_parse_block_core (a_this, n_calls + 1);
+ CHECK_PARSING_STATUS (status, FALSE);
+ goto parse_block_content;
+ } else {
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ status = cr_parser_parse_any_core (a_this, n_calls + 1);
+ CHECK_PARSING_STATUS (status, FALSE);
+ goto parse_block_content;
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (status == CR_OK)
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+static enum CRStatus
+cr_parser_parse_declaration_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+ CRString *prop = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_property (a_this, &prop);
+ CHECK_PARSING_STATUS (status, FALSE);
+ cr_parser_clear_errors (a_this);
+ ENSURE_PARSING_COND (status == CR_OK && prop);
+ cr_string_destroy (prop);
+ prop = NULL;
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ && token->type == DELIM_TK
+ && token->u.unichar == ':');
+ cr_token_destroy (token);
+ token = NULL;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_value_core (a_this);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ return CR_OK;
+
+ error:
+
+ if (prop) {
+ cr_string_destroy (prop);
+ prop = NULL;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a "value" production as defined by the css core grammar
+ *in chapter 4.1.
+ *value ::= [ any | block | ATKEYWORD S* ]+;
+ *@param a_this the current instance of #CRParser.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_value_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+ glong ref = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ continue_parsing:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ switch (token->type) {
+ case CBO_TK:
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ status = cr_parser_parse_block_core (a_this, 0);
+ CHECK_PARSING_STATUS (status, FALSE);
+ ref++;
+ goto continue_parsing;
+
+ case ATKEYWORD_TK:
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ ref++;
+ goto continue_parsing;
+
+ default:
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ status = cr_parser_parse_any_core (a_this, 0);
+ if (status == CR_OK) {
+ ref++;
+ goto continue_parsing;
+ } else if (status == CR_PARSING_ERROR) {
+ status = CR_OK;
+ goto done;
+ } else {
+ goto error;
+ }
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (status == CR_OK && ref)
+ return CR_OK;
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses an "any" as defined by the css core grammar in the
+ *css2 spec in chapter 4.1.
+ *any ::= [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING
+ * | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES
+ * | FUNCTION | DASHMATCH | '(' any* ')' | '[' any* ']' ] S*;
+ *
+ *@param a_this the current instance of #CRParser.
+ *@param n_calls used to limit recursion depth
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_any_core (CRParser * a_this,
+ guint n_calls)
+{
+ CRToken *token1 = NULL,
+ *token2 = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ if (n_calls > RECURSIVE_CALLERS_LIMIT)
+ return CR_ERROR;
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token1);
+
+ ENSURE_PARSING_COND (status == CR_OK && token1);
+
+ switch (token1->type) {
+ case IDENT_TK:
+ case NUMBER_TK:
+ case RGB_TK:
+ case PERCENTAGE_TK:
+ case DIMEN_TK:
+ case EMS_TK:
+ case EXS_TK:
+ case LENGTH_TK:
+ case ANGLE_TK:
+ case FREQ_TK:
+ case TIME_TK:
+ case STRING_TK:
+ case DELIM_TK:
+ case URI_TK:
+ case HASH_TK:
+ case UNICODERANGE_TK:
+ case INCLUDES_TK:
+ case DASHMATCH_TK:
+ case S_TK:
+ case COMMENT_TK:
+ case IMPORTANT_SYM_TK:
+ status = CR_OK;
+ break;
+ case FUNCTION_TK:
+ /*
+ *this case isn't specified by the spec but it
+ *does happen. So we have to handle it.
+ *We must consider function with parameters.
+ *We consider parameter as being an "any*" production.
+ */
+ do {
+ status = cr_parser_parse_any_core (a_this, n_calls + 1);
+ } while (status == CR_OK);
+
+ ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token2);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token2 && token2->type == PC_TK);
+ break;
+ case PO_TK:
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token2);
+ ENSURE_PARSING_COND (status == CR_OK && token2);
+
+ if (token2->type == PC_TK) {
+ cr_token_destroy (token2);
+ token2 = NULL;
+ goto done;
+ } else {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token2);
+ token2 = NULL;
+ }
+
+ do {
+ status = cr_parser_parse_any_core (a_this, n_calls + 1);
+ } while (status == CR_OK);
+
+ ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token2);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token2 && token2->type == PC_TK);
+ status = CR_OK;
+ break;
+
+ case BO_TK:
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token2);
+ ENSURE_PARSING_COND (status == CR_OK && token2);
+
+ if (token2->type == BC_TK) {
+ cr_token_destroy (token2);
+ token2 = NULL;
+ goto done;
+ } else {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token2);
+ token2 = NULL;
+ }
+
+ do {
+ status = cr_parser_parse_any_core (a_this, n_calls + 1);
+ } while (status == CR_OK);
+
+ ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token2);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token2 && token2->type == BC_TK);
+ status = CR_OK;
+ break;
+ default:
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ done:
+ if (token1) {
+ cr_token_destroy (token1);
+ token1 = NULL;
+ }
+
+ if (token2) {
+ cr_token_destroy (token2);
+ token2 = NULL;
+ }
+
+ return CR_OK;
+
+ error:
+
+ if (token1) {
+ cr_token_destroy (token1);
+ token1 = NULL;
+ }
+
+ if (token2) {
+ cr_token_destroy (token2);
+ token2 = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+ return status;
+}
+
+/**
+ *Parses an attribute selector as defined in the css2 spec in
+ *appendix D.1:
+ *attrib ::= '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
+ * [ IDENT | STRING ] S* ]? ']'
+ *
+ *@param a_this the "this pointer" of the current instance of
+ *#CRParser .
+ *@param a_sel out parameter. The successfully parsed attribute selector.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_attribute_selector (CRParser * a_this,
+ CRAttrSel ** a_sel)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ CRAttrSel *result = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == BO_TK);
+ cr_parsing_location_copy
+ (&location, &token->location) ;
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ result = cr_attr_sel_new ();
+ if (!result) {
+ cr_utils_trace_info ("result failed") ;
+ status = CR_OUT_OF_MEMORY_ERROR ;
+ goto error ;
+ }
+ cr_parsing_location_copy (&result->location,
+ &location) ;
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == IDENT_TK);
+
+ result->name = token->u.str;
+ token->u.str = NULL;
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == INCLUDES_TK) {
+ result->match_way = INCLUDES;
+ goto parse_right_part;
+ } else if (token->type == DASHMATCH_TK) {
+ result->match_way = DASHMATCH;
+ goto parse_right_part;
+ } else if (token->type == DELIM_TK && token->u.unichar == '=') {
+ result->match_way = EQUALS;
+ goto parse_right_part;
+ } else if (token->type == BC_TK) {
+ result->match_way = SET;
+ goto done;
+ }
+
+ parse_right_part:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == IDENT_TK) {
+ result->value = token->u.str;
+ token->u.str = NULL;
+ } else if (token->type == STRING_TK) {
+ result->value = token->u.str;
+ token->u.str = NULL;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == BC_TK);
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (*a_sel) {
+ status = cr_attr_sel_append_attr_sel (*a_sel, result);
+ CHECK_PARSING_STATUS (status, FALSE);
+ } else {
+ *a_sel = result;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ if (result) {
+ cr_attr_sel_destroy (result);
+ result = NULL;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a "property" as specified by the css2 spec at [4.1.1]:
+ *property : IDENT S*;
+ *
+ *@param a_this the "this pointer" of the current instance of #CRParser.
+ *@param GString a_property out parameter. The parsed property without the
+ *trailing spaces. If *a_property is NULL, this function allocates a
+ *new instance of GString and set it content to the parsed property.
+ *If not, the property is just appended to a_property's previous content.
+ *In both cases, it is up to the caller to free a_property.
+ *@return CR_OK upon successful completion, CR_PARSING_ERROR if the
+ *next construction was not a "property", or an error code.
+ */
+static enum CRStatus
+cr_parser_parse_property (CRParser * a_this,
+ CRString ** a_property)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr
+ && a_property,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_ident (a_this, a_property);
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_term:
+ *@a_term: out parameter. The successfully parsed term.
+ *
+ *Parses a "term" as defined in the css2 spec, appendix D.1:
+ *term ::= unary_operator? [NUMBER S* | PERCENTAGE S* | LENGTH S* |
+ *EMS S* | EXS S* | ANGLE S* | TIME S* | FREQ S* | function ] |
+ *STRING S* | IDENT S* | URI S* | RGB S* | UNICODERANGE S* | hexcolor
+ *
+ * As a special case for 'an+b', parse integer followed immediately by 'n'.
+ * The 'an' is parsed as a DIMEN.
+ *
+ *TODO: handle parsing of 'RGB'
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_term (CRParser * a_this, CRTerm ** a_term)
+{
+ enum CRStatus status = CR_PARSING_ERROR;
+ CRInputPos init_pos;
+ CRTerm *result = NULL;
+ CRTerm *param = NULL;
+ CRToken *token = NULL;
+ CRString *func_name = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && a_term, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ result = cr_term_new ();
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ if (status != CR_OK || !token)
+ goto error;
+
+ cr_parsing_location_copy (&location, &token->location) ;
+ if (token->type == DELIM_TK && token->u.unichar == '+') {
+ result->unary_op = PLUS_UOP;
+ cr_token_destroy (token) ;
+ token = NULL ;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ if (status != CR_OK || !token)
+ goto error;
+ } else if (token->type == DELIM_TK && token->u.unichar == '-') {
+ result->unary_op = MINUS_UOP;
+ cr_token_destroy (token) ;
+ token = NULL ;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ if (status != CR_OK || !token)
+ goto error;
+ }
+
+ if (token->type == EMS_TK
+ || token->type == EXS_TK
+ || token->type == LENGTH_TK
+ || token->type == ANGLE_TK
+ || token->type == TIME_TK
+ || token->type == FREQ_TK
+ || token->type == PERCENTAGE_TK
+ || token->type == NUMBER_TK) {
+ status = cr_term_set_number (result, token->u.num);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.num = NULL;
+ status = CR_OK;
+ } else if (token && token->type == FUNCTION_TK) {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ status = cr_parser_parse_function (a_this, &func_name,
+ &param);
+
+ if (status == CR_OK) {
+ status = cr_term_set_function (result,
+ func_name,
+ param);
+ CHECK_PARSING_STATUS (status, TRUE);
+ }
+ } else if (token && token->type == STRING_TK) {
+ status = cr_term_set_string (result,
+ token->u.str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.str = NULL;
+ } else if (token && token->type == IDENT_TK) {
+ status = cr_term_set_ident (result, token->u.str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.str = NULL;
+ } else if (token && token->type == URI_TK) {
+ status = cr_term_set_uri (result, token->u.str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.str = NULL;
+ } else if (token && token->type == RGB_TK) {
+ status = cr_term_set_rgb (result, token->u.rgb);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.rgb = NULL;
+ } else if (token && token->type == UNICODERANGE_TK) {
+ result->type = TERM_UNICODERANGE;
+ status = CR_PARSING_ERROR;
+ } else if (token && token->type == HASH_TK) {
+ status = cr_term_set_hash (result, token->u.str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.str = NULL;
+ } else if (token && token->type == DIMEN_TK) {
+ gboolean n = !strcmp(token->dimen->stryng->str, "n");
+ status = cr_term_set_number (result, token->u.num);
+ result->n = n; // For nth-child (an+b)
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.num = NULL;
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ }
+
+ if (status != CR_OK) {
+ goto error;
+ }
+ cr_parsing_location_copy (&result->location,
+ &location) ;
+ *a_term = cr_term_append_term (*a_term, result);
+
+ result = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ if (result) {
+ cr_term_destroy (result);
+ result = NULL;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (param) {
+ cr_term_destroy (param);
+ param = NULL;
+ }
+
+ if (func_name) {
+ cr_string_destroy (func_name);
+ func_name = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_simple_selector:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *@a_sel: out parameter. Is set to the successfully parsed simple
+ *selector.
+ *
+ *Parses a "simple_selector" as defined by the css2 spec in appendix D.1 :
+ *element_name? [ HASH | class | attrib | pseudo ]* S*
+ *and where pseudo is:
+ *pseudo ::= ':' [ IDENT | FUNCTION S* IDENT S* ')' ]
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_simple_selector (CRParser * a_this, CRSimpleSel ** a_sel)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ CRSimpleSel *sel = NULL;
+ CRPseudo *pseudo = NULL;
+ CRAdditionalSel *add_sel_list = NULL;
+ gboolean found_sel = FALSE;
+
+ g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ if (status != CR_OK)
+ goto error;
+
+ sel = cr_simple_sel_new ();
+ ENSURE_PARSING_COND (sel);
+
+ cr_parsing_location_copy
+ (&sel->location,
+ &token->location) ;
+
+ if (token && token->type == DELIM_TK
+ && token->u.unichar == '*') {
+ int comb = (int)sel->type_mask | (int) UNIVERSAL_SELECTOR;
+ sel->type_mask = (enum SimpleSelectorType)comb;
+ sel->name = cr_string_new_from_string ("*");
+ found_sel = TRUE;
+ } else if (token && token->type == IDENT_TK) {
+ int comb = (int)sel->type_mask | (int) TYPE_SELECTOR;
+ sel->type_mask = (enum SimpleSelectorType)comb;
+ sel->name = token->u.str;
+ token->u.str = NULL;
+ found_sel = TRUE;
+ } else {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ while (cr_tknzr_get_nb_bytes_left ((PRIVATE (a_this)->tknzr))) {
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr,
+ &token);
+ if (status != CR_OK)
+ goto error;
+
+ if (token && token->type == HASH_TK) {
+ /*we parsed an attribute id */
+ CRAdditionalSel *add_sel = NULL;
+
+ add_sel = cr_additional_sel_new_with_type
+ (ID_ADD_SELECTOR);
+
+ add_sel->content.id_name = token->u.str;
+ token->u.str = NULL;
+
+ cr_parsing_location_copy
+ (&add_sel->location,
+ &token->location) ;
+ add_sel_list =
+ cr_additional_sel_append
+ (add_sel_list, add_sel);
+ found_sel = TRUE;
+ } else if (token && (token->type == DELIM_TK)
+ && (token->u.unichar == '.')) {
+ cr_token_destroy (token);
+ token = NULL;
+
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ if (status != CR_OK)
+ goto error;
+
+ if (token && token->type == IDENT_TK) {
+ CRAdditionalSel *add_sel = NULL;
+
+ add_sel = cr_additional_sel_new_with_type
+ (CLASS_ADD_SELECTOR);
+
+ add_sel->content.class_name = token->u.str;
+ token->u.str = NULL;
+
+ add_sel_list =
+ cr_additional_sel_append
+ (add_sel_list, add_sel);
+ found_sel = TRUE;
+
+ cr_parsing_location_copy
+ (&add_sel->location,
+ & token->location) ;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ } else if (token && token->type == BO_TK) {
+ CRAttrSel *attr_sel = NULL;
+ CRAdditionalSel *add_sel = NULL;
+
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ if (status != CR_OK)
+ goto error;
+ token = NULL;
+
+ status = cr_parser_parse_attribute_selector
+ (a_this, &attr_sel);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ add_sel = cr_additional_sel_new_with_type
+ (ATTRIBUTE_ADD_SELECTOR);
+
+ ENSURE_PARSING_COND (add_sel != NULL);
+
+ add_sel->content.attr_sel = attr_sel;
+
+ add_sel_list =
+ cr_additional_sel_append
+ (add_sel_list, add_sel);
+ found_sel = TRUE;
+ cr_parsing_location_copy
+ (&add_sel->location,
+ &attr_sel->location) ;
+ } else if (token && (token->type == DELIM_TK)
+ && (token->u.unichar == ':')) {
+
+ /*try to parse a pseudo */
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ pseudo = cr_pseudo_new ();
+
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ cr_parsing_location_copy
+ (&pseudo->location,
+ &token->location) ;
+
+ /* Save selector name for use by 'type' pseudo selectors */
+ if (sel->name)
+ pseudo->sel_name = cr_string_dup (sel->name);
+
+ if (token->type == IDENT_TK) {
+ pseudo->type = IDENT_PSEUDO;
+ pseudo->name = token->u.str;
+ token->u.str = NULL;
+ found_sel = TRUE;
+ } else if (token->type == FUNCTION_TK) {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ status = cr_parser_parse_function (a_this, &pseudo->name, &pseudo->term);
+ ENSURE_PARSING_COND (status == CR_OK);
+
+ pseudo->type = FUNCTION_PSEUDO;
+ found_sel = TRUE;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ if (status == CR_OK) {
+ CRAdditionalSel *add_sel = NULL;
+
+ add_sel = cr_additional_sel_new_with_type
+ (PSEUDO_CLASS_ADD_SELECTOR);
+
+ add_sel->content.pseudo = pseudo;
+ cr_parsing_location_copy
+ (&add_sel->location,
+ &pseudo->location) ;
+ pseudo = NULL;
+ add_sel_list =
+ cr_additional_sel_append
+ (add_sel_list, add_sel);
+ status = CR_OK;
+ }
+ } else {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ break;
+ }
+ } // for loop
+
+ if (status == CR_OK && found_sel == TRUE) {
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ sel->add_sel = add_sel_list;
+ add_sel_list = NULL;
+
+ if (*a_sel == NULL) {
+ *a_sel = sel;
+ } else {
+ cr_simple_sel_append_simple_sel (*a_sel, sel);
+ }
+
+ sel = NULL;
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ }
+
+ error:
+
+ g_clear_pointer (&pseudo, cr_pseudo_destroy);
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (add_sel_list) {
+ cr_additional_sel_destroy (add_sel_list);
+ add_sel_list = NULL;
+ }
+
+ if (sel) {
+ cr_simple_sel_destroy (sel);
+ sel = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+
+}
+
+/**
+ * cr_parser_parse_simple_sels:
+ *@a_this: the this pointer of the current instance of #CRParser.
+ *@a_start: a pointer to the
+ *first chararcter of the successfully parsed
+ *string.
+ *@a_end: a pointer to the last character of the successfully parsed
+ *string.
+ *
+ *Parses a "selector" as defined by the css2 spec in appendix D.1:
+ *selector ::= simple_selector [ combinator simple_selector ]*
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_simple_sels (CRParser * a_this,
+ CRSimpleSel ** a_sel)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ CRSimpleSel *sel = NULL;
+ guint32 cur_char = 0;
+
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && a_sel,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_simple_selector (a_this, &sel);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ *a_sel = cr_simple_sel_append_simple_sel (*a_sel, sel);
+
+ for (;;) {
+ guint32 next_char = 0;
+ enum Combinator comb = NO_COMBINATOR;
+
+ sel = NULL;
+
+ status =
+ cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, &next_char);
+ if (status == CR_END_OF_INPUT_ERROR)
+ break;
+ if (status != CR_OK)
+ goto error;
+
+ if (next_char == '+') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ comb = COMB_PLUS;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ } else if (next_char == '~') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ comb = COMB_TILDE;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ } else if (next_char == '>') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ comb = COMB_GT;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ } else {
+ comb = COMB_WS;
+ }
+
+ status = cr_parser_parse_simple_selector (a_this, &sel);
+ if (status != CR_OK)
+ break;
+
+ if (comb != NO_COMBINATOR && sel) {
+ sel->combinator = comb;
+ comb = NO_COMBINATOR;
+ }
+ if (sel) {
+ *a_sel = cr_simple_sel_append_simple_sel (*a_sel,
+ sel) ;
+ }
+ }
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_selector:
+ *@a_this: the current instance of #CRParser.
+ *@a_selector: the parsed list of comma separated
+ *selectors.
+ *
+ *Parses a comma separated list of selectors.
+ *
+ *Returns CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_selector (CRParser * a_this,
+ CRSelector ** a_selector)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ guint32 cur_char = 0,
+ next_char = 0;
+ CRSimpleSel *simple_sels = NULL;
+ CRSelector *selector = NULL;
+
+ g_return_val_if_fail (a_this && a_selector, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_simple_sels (a_this, &simple_sels);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ if (simple_sels) {
+ selector = cr_selector_append_simple_sel
+ (selector, simple_sels);
+ if (selector) {
+ cr_parsing_location_copy
+ (&selector->location,
+ &simple_sels->location) ;
+ }
+ simple_sels = NULL;
+ } else {
+ status = CR_PARSING_ERROR ;
+ goto error ;
+ }
+
+ status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
+ &next_char);
+ if (status != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ goto okay;
+ } else {
+ goto error;
+ }
+ }
+
+ if (next_char == ',') {
+ for (;;) {
+ simple_sels = NULL;
+
+ status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
+ &next_char);
+ if (status != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ break;
+ } else {
+ goto error;
+ }
+ }
+
+ if (next_char != ',')
+ break;
+
+ /*consume the ',' char */
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_simple_sels
+ (a_this, &simple_sels);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ if (simple_sels) {
+ selector =
+ cr_selector_append_simple_sel
+ (selector, simple_sels);
+
+ simple_sels = NULL;
+ }
+ }
+ }
+
+ okay:
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ if (!*a_selector) {
+ *a_selector = selector;
+ } else {
+ *a_selector = cr_selector_append (*a_selector, selector);
+ }
+
+ selector = NULL;
+ return CR_OK;
+
+ error:
+
+ if (simple_sels) {
+ cr_simple_sel_destroy (simple_sels);
+ simple_sels = NULL;
+ }
+
+ if (selector) {
+ cr_selector_unref (selector);
+ selector = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_function:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *
+ *@a_func_name: out parameter. The parsed function name
+ *@a_expr: out parameter. The successfully parsed term.
+ *
+ *Parses a "function" as defined in css spec at appendix D.1:
+ *function ::= FUNCTION S* expr ')' S*
+ *FUNCTION ::= ident'('
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_function (CRParser * a_this,
+ CRString ** a_func_name,
+ CRTerm ** a_expr)
+{
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ CRToken *token = NULL;
+ CRTerm *expr = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_func_name,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ if (status != CR_OK)
+ goto error;
+
+ if (token && token->type == FUNCTION_TK) {
+ *a_func_name = token->u.str;
+ token->u.str = NULL;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this) ;
+
+ status = cr_parser_parse_expr (a_this, &expr);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ if (status != CR_OK)
+ goto error;
+
+ ENSURE_PARSING_COND (token && token->type == PC_TK);
+
+ cr_token_destroy (token);
+ token = NULL;
+
+ if (expr) {
+ *a_expr = cr_term_append_term (*a_expr, expr);
+ expr = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ if (*a_func_name) {
+ cr_string_destroy (*a_func_name);
+ *a_func_name = NULL;
+ }
+
+ if (expr) {
+ cr_term_destroy (expr);
+ expr = NULL;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_uri:
+ *@a_this: the current instance of #CRParser.
+ *@a_str: the successfully parsed url.
+ *
+ *Parses an uri as defined by the css spec [4.1.1]:
+ * URI ::= url\({w}{string}{w}\)
+ * |url\({w}([!#$%&*-~]|{nonascii}|{escape})*{w}\)
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_uri (CRParser * a_this, CRString ** a_str)
+{
+
+ enum CRStatus status = CR_PARSING_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
+
+ status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
+ URI_TK, NO_ET, a_str, NULL);
+ return status;
+}
+
+/**
+ * cr_parser_parse_string:
+ *@a_this: the current instance of #CRParser.
+ *@a_start: out parameter. Upon successful completion,
+ *points to the beginning of the string, points to an undefined value
+ *otherwise.
+ *@a_end: out parameter. Upon successful completion, points to
+ *the beginning of the string, points to an undefined value otherwise.
+ *
+ *Parses a string type as defined in css spec [4.1.1]:
+ *
+ *string ::= {string1}|{string2}
+ *string1 ::= \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"
+ *string2 ::= \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_string (CRParser * a_this, CRString ** a_str)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr
+ && a_str, CR_BAD_PARAM_ERROR);
+
+ status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
+ STRING_TK, NO_ET, a_str, NULL);
+ return status;
+}
+
+/**
+ *Parses an "ident" as defined in css spec [4.1.1]:
+ *ident ::= {nmstart}{nmchar}*
+ *
+ *@param a_this the currens instance of #CRParser.
+ *
+ *@param a_str a pointer to parsed ident. If *a_str is NULL,
+ *this function allocates a new instance of #CRString. If not,
+ *the function just appends the parsed string to the one passed.
+ *In both cases it is up to the caller to free *a_str.
+ *
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_ident (CRParser * a_this, CRString ** a_str)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr
+ && a_str, CR_BAD_PARAM_ERROR);
+
+ status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
+ IDENT_TK, NO_ET, a_str, NULL);
+ return status;
+}
+
+/**
+ *the next rule is ignored as well. This seems to be a bug
+ *Parses a stylesheet as defined in the css2 spec in appendix D.1:
+ *stylesheet ::= [ CHARSET_SYM S* STRING S* ';' ]?
+ * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
+ * [ [ ruleset | media | page | font_face ] [S|CDO|CDC]* ]*
+ *
+ *TODO: Finish the code of this function. Think about splitting it into
+ *smaller functions.
+ *
+ *@param a_this the "this pointer" of the current instance of #CRParser.
+ *@param a_start out parameter. A pointer to the first character of
+ *the successfully parsed string.
+ *@param a_end out parameter. A pointer to the first character of
+ *the successfully parsed string.
+ *
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_stylesheet (CRParser * a_this)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ CRString *charset = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PRIVATE (a_this)->state = READY_STATE;
+
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->start_document) {
+ PRIVATE (a_this)->sac_handler->start_document
+ (PRIVATE (a_this)->sac_handler);
+ }
+
+ parse_charset:
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto done;
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ if (token && token->type == CHARSET_SYM_TK) {
+ CRParsingLocation location = {0,0,0} ;
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+
+ status = cr_parser_parse_charset (a_this,
+ &charset,
+ &location);
+
+ if (status == CR_OK && charset) {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->charset) {
+ PRIVATE (a_this)->sac_handler->charset
+ (PRIVATE (a_this)->sac_handler,
+ charset, &location);
+ }
+ } else if (status != CR_END_OF_INPUT_ERROR) {
+ status = cr_parser_parse_atrule_core (a_this);
+ CHECK_PARSING_STATUS (status, FALSE);
+ }
+
+ if (charset) {
+ cr_string_destroy (charset);
+ charset = NULL;
+ }
+ } else if (token
+ && (token->type == S_TK
+ || token->type == COMMENT_TK)) {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ goto parse_charset ;
+ } else if (token) {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ CHECK_PARSING_STATUS (status, TRUE);
+ }
+
+/* parse_imports:*/
+ do {
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this) ;
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto done;
+ CHECK_PARSING_STATUS (status, TRUE);
+ } while (token
+ && (token->type == S_TK
+ || token->type == CDO_TK || token->type == CDC_TK));
+
+ if (token) {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ }
+
+ for (;;) {
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto done;
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ if (token && token->type == IMPORT_SYM_TK) {
+ GList *media_list = NULL;
+ CRString *import_string = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ status = cr_parser_parse_import (a_this,
+ &media_list,
+ &import_string,
+ &location);
+ if (status == CR_OK) {
+ if (import_string
+ && PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->import_style) {
+ PRIVATE (a_this)->sac_handler->import_style
+ (PRIVATE(a_this)->sac_handler,
+ media_list,
+ import_string,
+ NULL, &location) ;
+
+ if (PRIVATE (a_this)->sac_handler->resolve_import == TRUE) {
+ /*
+ *TODO: resolve the
+ *import rule.
+ */
+ }
+
+ if (PRIVATE (a_this)->sac_handler->import_style_result) {
+ PRIVATE (a_this)->sac_handler->import_style_result
+ (PRIVATE (a_this)->sac_handler,
+ media_list, import_string,
+ NULL, NULL);
+ }
+ }
+ } else if (status != CR_END_OF_INPUT_ERROR) {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->error
+ (PRIVATE (a_this)->sac_handler);
+ }
+ status = cr_parser_parse_atrule_core (a_this);
+ CHECK_PARSING_STATUS (status, TRUE) ;
+ } else {
+ goto error ;
+ }
+
+ /*
+ *then, after calling the appropriate
+ *SAC handler, free
+ *the media_list and import_string.
+ */
+ if (media_list) {
+ GList *cur = NULL;
+
+ /*free the medium list */
+ for (cur = media_list; cur; cur = cur->next) {
+ if (cur->data) {
+ cr_string_destroy (cur->data);
+ }
+ }
+
+ g_list_free (media_list);
+ media_list = NULL;
+ }
+
+ if (import_string) {
+ cr_string_destroy (import_string);
+ import_string = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ } else if (token
+ && (token->type == S_TK
+ || token->type == CDO_TK
+ || token->type == CDC_TK)) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+
+ do {
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto done;
+ CHECK_PARSING_STATUS (status, TRUE);
+ } while (token
+ && (token->type == S_TK
+ || token->type == CDO_TK
+ || token->type == CDC_TK));
+ } else {
+ if (token) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ }
+ goto parse_ruleset_and_others;
+ }
+ }
+
+ parse_ruleset_and_others:
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ for (;;) {
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto done;
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ if (token
+ && (token->type == S_TK
+ || token->type == CDO_TK || token->type == CDC_TK)) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+
+ do {
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments
+ (a_this);
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ } while (token
+ && (token->type == S_TK
+ || token->type == COMMENT_TK
+ || token->type == CDO_TK
+ || token->type == CDC_TK));
+ if (token) {
+ cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ }
+ } else if (token
+ && (token->type == HASH_TK
+ || (token->type == DELIM_TK
+ && token->u.unichar == '.')
+ || (token->type == DELIM_TK
+ && token->u.unichar == ':')
+ || (token->type == DELIM_TK
+ && token->u.unichar == '*')
+ || (token->type == BO_TK)
+ || token->type == IDENT_TK)) {
+ /*
+ *Try to parse a CSS2 ruleset.
+ *if the parsing fails, try to parse
+ *a css core ruleset.
+ */
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+
+ status = cr_parser_parse_ruleset (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->
+ error
+ (PRIVATE (a_this)->
+ sac_handler);
+ }
+
+ status = cr_parser_parse_ruleset_core
+ (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ } else if (token && token->type == MEDIA_SYM_TK) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+
+ status = cr_parser_parse_media (a_this);
+ if (status == CR_OK) {
+ continue;
+ } else {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->
+ error
+ (PRIVATE (a_this)->
+ sac_handler);
+ }
+
+ status = cr_parser_parse_atrule_core (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ } else if (token && token->type == PAGE_SYM_TK) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+ status = cr_parser_parse_page (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->
+ error
+ (PRIVATE (a_this)->
+ sac_handler);
+ }
+
+ status = cr_parser_parse_atrule_core (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ } else if (token && token->type == FONT_FACE_SYM_TK) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+ status = cr_parser_parse_font_face (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->
+ error
+ (PRIVATE (a_this)->
+ sac_handler);
+ }
+
+ status = cr_parser_parse_atrule_core (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ } else {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+ status = cr_parser_parse_statement_core (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (status == CR_END_OF_INPUT_ERROR || status == CR_OK) {
+
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->end_document) {
+ PRIVATE (a_this)->sac_handler->end_document
+ (PRIVATE (a_this)->sac_handler);
+ }
+
+ return CR_OK;
+ }
+
+ cr_parser_push_error
+ (a_this, (const guchar *) "could not recognize next production", CR_ERROR);
+
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
+ PRIVATE (a_this)->sac_handler->
+ unrecoverable_error (PRIVATE (a_this)->sac_handler);
+ }
+
+ cr_parser_dump_err_stack (a_this, TRUE);
+
+ return status;
+
+ error:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
+ PRIVATE (a_this)->sac_handler->
+ unrecoverable_error (PRIVATE (a_this)->sac_handler);
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/****************************************
+ *Public CRParser Methods
+ ****************************************/
+
+/**
+ * cr_parser_new:
+ * @a_tknzr: the tokenizer to use for the parsing.
+ *
+ *Creates a new parser to parse data
+ *coming the input stream given in parameter.
+ *
+ *Returns the newly created instance of #CRParser,
+ *or NULL if an error occurred.
+ */
+CRParser *
+cr_parser_new (CRTknzr * a_tknzr)
+{
+ CRParser *result = NULL;
+ enum CRStatus status = CR_OK;
+
+ result = g_malloc0 (sizeof (CRParser));
+
+ PRIVATE (result) = g_malloc0 (sizeof (CRParserPriv));
+
+ if (a_tknzr) {
+ status = cr_parser_set_tknzr (result, a_tknzr);
+ if (status != CR_OK)
+ cr_parser_destroy (result);
+ }
+
+ g_return_val_if_fail (status == CR_OK, NULL);
+
+ return result;
+}
+
+/**
+ * cr_parser_new_from_buf:
+ *@a_buf: the buffer to parse.
+ *@a_len: the length of the data in the buffer.
+ *@a_enc: the encoding of the input buffer a_buf.
+ *@a_free_buf: if set to TRUE, a_buf will be freed
+ *during the destruction of the newly built instance
+ *of #CRParser. If set to FALSE, it is up to the caller to
+ *eventually free it.
+ *
+ *Instantiates a new parser from a memory buffer.
+ *
+ *Returns the newly built parser, or NULL if an error arises.
+ */
+CRParser *
+cr_parser_new_from_buf (guchar * a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_buf)
+{
+ CRParser *result = NULL;
+ CRInput *input = NULL;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ input = cr_input_new_from_buf (a_buf, a_len, a_enc, a_free_buf);
+ g_return_val_if_fail (input, NULL);
+
+ result = cr_parser_new_from_input (input);
+ if (!result) {
+ cr_input_destroy (input);
+ input = NULL;
+ return NULL;
+ }
+ return result;
+}
+
+/**
+ * cr_parser_new_from_input:
+ * @a_input: the parser input stream to use.
+ *
+ * Returns a newly built parser input.
+ */
+CRParser *
+cr_parser_new_from_input (CRInput * a_input)
+{
+ CRParser *result = NULL;
+ CRTknzr *tokenizer = NULL;
+
+ if (a_input) {
+ tokenizer = cr_tknzr_new (a_input);
+ g_return_val_if_fail (tokenizer, NULL);
+ }
+
+ result = cr_parser_new (tokenizer);
+ if (!result)
+ g_clear_pointer (&tokenizer, cr_tknzr_unref);
+ g_return_val_if_fail (result, NULL);
+
+ return result;
+}
+
+/**
+ * cr_parser_new_from_file:
+ * @a_file_uri: the uri of the file to parse.
+ * @a_enc: the file encoding to use.
+ *
+ * Returns the newly built parser.
+ */
+CRParser *
+cr_parser_new_from_file (const guchar * a_file_uri, enum CREncoding a_enc)
+{
+ CRParser *result = NULL;
+ CRTknzr *tokenizer = NULL;
+
+ tokenizer = cr_tknzr_new_from_uri (a_file_uri, a_enc);
+ if (!tokenizer) {
+ cr_utils_trace_info ("Could not open input file");
+ return NULL;
+ }
+
+ result = cr_parser_new (tokenizer);
+ if (!result)
+ g_clear_pointer (&tokenizer, cr_tknzr_unref);
+ g_return_val_if_fail (result, NULL);
+ return result;
+}
+
+/**
+ * cr_parser_set_sac_handler:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *@a_handler: the handler to set.
+ *
+ *Sets a SAC document handler to the parser.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_set_sac_handler (CRParser * a_this, CRDocHandler * a_handler)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->sac_handler) {
+ cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
+ }
+
+ PRIVATE (a_this)->sac_handler = a_handler;
+ cr_doc_handler_ref (a_handler);
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_get_sac_handler:
+ *@a_this: the "this pointer" of the current instance of
+ *#CRParser.
+ *@a_handler: out parameter. The returned handler.
+ *
+ *Gets the SAC document handler.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_parser_get_sac_handler (CRParser * a_this, CRDocHandler ** a_handler)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ *a_handler = PRIVATE (a_this)->sac_handler;
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_set_default_sac_handler:
+ *@a_this: a pointer to the current instance of #CRParser.
+ *
+ *Sets the SAC handler associated to the current instance
+ *of #CRParser to the default SAC handler.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_set_default_sac_handler (CRParser * a_this)
+{
+ CRDocHandler *default_sac_handler = NULL;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ default_sac_handler = cr_doc_handler_new ();
+
+ cr_doc_handler_set_default_sac_handler (default_sac_handler);
+
+ status = cr_parser_set_sac_handler (a_this, default_sac_handler);
+
+ if (status != CR_OK) {
+ cr_doc_handler_destroy (default_sac_handler);
+ default_sac_handler = NULL;
+ }
+
+ return status;
+}
+
+/**
+ * cr_parser_set_use_core_grammar:
+ * @a_this: the current instance of #CRParser.
+ * @a_use_core_grammar: where to parse against the css core grammar.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_set_use_core_grammar (CRParser * a_this,
+ gboolean a_use_core_grammar)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->use_core_grammar = a_use_core_grammar;
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_get_use_core_grammar:
+ * @a_this: the current instance of #CRParser.
+ * @a_use_core_grammar: whether to use the core grammar or not.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_get_use_core_grammar (CRParser const * a_this,
+ gboolean * a_use_core_grammar)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ *a_use_core_grammar = PRIVATE (a_this)->use_core_grammar;
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_parse_file:
+ *@a_this: a pointer to the current instance of #CRParser.
+ *@a_file_uri: the uri to the file to load. For the time being,
+ *@a_enc: the encoding of the file to parse.
+ *only local files are supported.
+ *
+ *Parses a the given in parameter.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_file (CRParser * a_this,
+ const guchar * a_file_uri, enum CREncoding a_enc)
+{
+ enum CRStatus status = CR_ERROR;
+ CRTknzr *tknzr = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_file_uri, CR_BAD_PARAM_ERROR);
+
+ tknzr = cr_tknzr_new_from_uri (a_file_uri, a_enc);
+
+ g_return_val_if_fail (tknzr != NULL, CR_ERROR);
+
+ status = cr_parser_set_tknzr (a_this, tknzr);
+ if (status != CR_OK)
+ g_clear_pointer (&tknzr, cr_tknzr_unref);
+ g_return_val_if_fail (status == CR_OK, CR_ERROR);
+
+ status = cr_parser_parse (a_this);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_expr:
+ * @a_this: the current instance of #CRParser.
+ * @a_expr: out parameter. the parsed expression.
+ *
+ *Parses an expression as defined by the css2 spec in appendix
+ *D.1:
+ *expr: term [ operator term ]*
+ *
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_expr (CRParser * a_this, CRTerm ** a_expr)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ CRTerm *expr = NULL,
+ *expr2 = NULL;
+ guchar next_byte = 0;
+ gulong nb_terms = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_expr, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_term (a_this, &expr);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ for (;;) {
+ guchar operatr = 0;
+
+ status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr,
+ 1, &next_byte);
+ if (status != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR) {
+ /*
+ if (!nb_terms)
+ {
+ goto error ;
+ }
+ */
+ status = CR_OK;
+ break;
+ } else {
+ goto error;
+ }
+ }
+
+ if (next_byte == '/' || next_byte == ',') {
+ READ_NEXT_BYTE (a_this, &operatr);
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_term (a_this, &expr2);
+
+ if (status != CR_OK || expr2 == NULL) {
+ status = CR_OK;
+ break;
+ }
+
+ switch (operatr) {
+ case '/':
+ expr2->the_operator = DIVIDE;
+ break;
+ case ',':
+ expr2->the_operator = COMMA;
+
+ default:
+ break;
+ }
+
+ expr = cr_term_append_term (expr, expr2);
+ expr2 = NULL;
+ operatr = 0;
+ nb_terms++;
+ }
+
+ if (status == CR_OK) {
+ *a_expr = cr_term_append_term (*a_expr, expr);
+ expr = NULL;
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+ }
+
+ error:
+
+ if (expr) {
+ cr_term_destroy (expr);
+ expr = NULL;
+ }
+
+ if (expr2) {
+ cr_term_destroy (expr2);
+ expr2 = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_prio:
+ *@a_this: the current instance of #CRParser.
+ *@a_prio: a string representing the priority.
+ *Today, only "!important" is returned as only this
+ *priority is defined by css2.
+ *
+ *Parses a declaration priority as defined by
+ *the css2 grammar in appendix C:
+ *prio: IMPORTANT_SYM S*
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_prio (CRParser * a_this, CRString ** a_prio)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_prio
+ && *a_prio == NULL, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ if (status == CR_END_OF_INPUT_ERROR) {
+ goto error;
+ }
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == IMPORTANT_SYM_TK);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ *a_prio = cr_string_new_from_string ("!important");
+ cr_token_destroy (token);
+ token = NULL;
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_declaration:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *@a_property: the successfully parsed property. The caller
+ * *must* free the returned pointer.
+ *@a_expr: the expression that represents the attribute value.
+ *The caller *must* free the returned pointer.
+ *
+ *TODO: return the parsed priority, so that
+ *upper layers can take benefit from it.
+ *Parses a "declaration" as defined by the css2 spec in appendix D.1:
+ *declaration ::= [property ':' S* expr prio?]?
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_declaration (CRParser * a_this,
+ CRString ** a_property,
+ CRTerm ** a_expr, gboolean * a_important)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ guint32 cur_char = 0;
+ CRTerm *expr = NULL;
+ CRString *prio = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_property && a_expr
+ && a_important, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_property (a_this, a_property);
+
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto error;
+
+ CHECK_PARSING_STATUS_ERR
+ (a_this, status, FALSE,
+ (const guchar *) "while parsing declaration: next property is malformed",
+ CR_SYNTAX_ERROR);
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char != ':') {
+ status = CR_PARSING_ERROR;
+ cr_parser_push_error
+ (a_this,
+ (const guchar *) "while parsing declaration: this char must be ':'",
+ CR_SYNTAX_ERROR);
+ goto error;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_expr (a_this, &expr);
+
+ CHECK_PARSING_STATUS_ERR
+ (a_this, status, FALSE,
+ (const guchar *) "while parsing declaration: next expression is malformed",
+ CR_SYNTAX_ERROR);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_prio (a_this, &prio);
+ if (prio) {
+ cr_string_destroy (prio);
+ prio = NULL;
+ *a_important = TRUE;
+ } else {
+ *a_important = FALSE;
+ }
+ if (*a_expr) {
+ cr_term_append_term (*a_expr, expr);
+ expr = NULL;
+ } else {
+ *a_expr = expr;
+ expr = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ if (expr) {
+ cr_term_destroy (expr);
+ expr = NULL;
+ }
+
+ if (*a_property) {
+ cr_string_destroy (*a_property);
+ *a_property = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_statement_core:
+ *@a_this: the current instance of #CRParser.
+ *
+ *Parses a statement as defined by the css core grammar in
+ *chapter 4.1 of the css2 spec.
+ *statement : ruleset | at-rule;
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_statement_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ switch (token->type) {
+ case ATKEYWORD_TK:
+ case IMPORT_SYM_TK:
+ case PAGE_SYM_TK:
+ case MEDIA_SYM_TK:
+ case FONT_FACE_SYM_TK:
+ case CHARSET_SYM_TK:
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ status = cr_parser_parse_atrule_core (a_this);
+ CHECK_PARSING_STATUS (status, TRUE);
+ break;
+
+ default:
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ status = cr_parser_parse_ruleset_core (a_this);
+ cr_parser_clear_errors (a_this);
+ CHECK_PARSING_STATUS (status, TRUE);
+ }
+
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_ruleset:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *
+ *Parses a "ruleset" as defined in the css2 spec at appendix D.1.
+ *ruleset ::= selector [ ',' S* selector ]*
+ *'{' S* declaration? [ ';' S* declaration? ]* '}' S*;
+ *
+ *This methods calls the SAC handler on the relevant SAC handler
+ *callbacks whenever it encounters some specific constructions.
+ *See the documentation of #CRDocHandler (the SAC handler) to know
+ *when which SAC handler is called.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_ruleset (CRParser * a_this)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ guint32 cur_char = 0,
+ next_char = 0;
+ CRString *property = NULL;
+ CRTerm *expr = NULL;
+ CRSimpleSel *simple_sels = NULL;
+ CRSelector *selector = NULL;
+ gboolean start_selector = FALSE,
+ is_important = FALSE;
+ CRParsingLocation end_parsing_location;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_selector (a_this, &selector);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ ENSURE_PARSING_COND_ERR
+ (a_this, cur_char == '{',
+ (const guchar *) "while parsing rulset: current char should be '{'",
+ CR_SYNTAX_ERROR);
+
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->start_selector) {
+ /*
+ *the selector is ref counted so that the parser's user
+ *can choose to keep it.
+ */
+ if (selector) {
+ cr_selector_ref (selector);
+ }
+
+ PRIVATE (a_this)->sac_handler->start_selector
+ (PRIVATE (a_this)->sac_handler, selector);
+ start_selector = TRUE;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ PRIVATE (a_this)->state = TRY_PARSE_RULESET_STATE;
+
+ status = cr_parser_parse_declaration (a_this, &property,
+ &expr,
+ &is_important);
+ if (expr) {
+ cr_term_ref (expr);
+ }
+ if (status == CR_OK
+ && PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->property) {
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler, property, expr,
+ is_important);
+ }
+ if (status == CR_OK) {
+ /*
+ *free the allocated
+ *'property' and 'term' before parsing
+ *next declarations.
+ */
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (expr) {
+ cr_term_unref (expr);
+ expr = NULL;
+ }
+ } else {/*status != CR_OK*/
+ guint32 c = 0 ;
+ /*
+ *test if we have reached '}', which
+ *would mean that we are parsing an empty ruleset (eg. x{ })
+ *In that case, goto end_of_ruleset.
+ */
+ status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, &c) ;
+ if (status == CR_OK && c == '}') {
+ status = CR_OK ;
+ goto end_of_ruleset ;
+ }
+ }
+ CHECK_PARSING_STATUS_ERR
+ (a_this, status, FALSE,
+ (const guchar *) "while parsing ruleset: next construction should be a declaration",
+ CR_SYNTAX_ERROR);
+
+ for (;;) {
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char != ';')
+ break;
+
+ /*consume the ';' char */
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_declaration (a_this, &property,
+ &expr, &is_important);
+
+ if (expr) {
+ cr_term_ref (expr);
+ }
+ if (status == CR_OK
+ && PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->property) {
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler,
+ property, expr, is_important);
+ }
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (expr) {
+ cr_term_unref (expr);
+ expr = NULL;
+ }
+ }
+
+ end_of_ruleset:
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ cr_parser_get_parsing_location (a_this, &end_parsing_location);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ ENSURE_PARSING_COND_ERR
+ (a_this, cur_char == '}',
+ (const guchar *) "while parsing rulset: current char must be a '}'",
+ CR_SYNTAX_ERROR);
+
+ selector->location = end_parsing_location;
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->end_selector) {
+ PRIVATE (a_this)->sac_handler->end_selector
+ (PRIVATE (a_this)->sac_handler, selector);
+ start_selector = FALSE;
+ }
+
+ if (expr) {
+ cr_term_unref (expr);
+ expr = NULL;
+ }
+
+ if (simple_sels) {
+ cr_simple_sel_destroy (simple_sels);
+ simple_sels = NULL;
+ }
+
+ if (selector) {
+ cr_selector_unref (selector);
+ selector = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->state = RULESET_PARSED_STATE;
+
+ return CR_OK;
+
+ error:
+ if (start_selector == TRUE
+ && PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->error
+ (PRIVATE (a_this)->sac_handler);
+ }
+ if (expr) {
+ cr_term_unref (expr);
+ expr = NULL;
+ }
+ if (simple_sels) {
+ cr_simple_sel_destroy (simple_sels);
+ simple_sels = NULL;
+ }
+ if (property) {
+ cr_string_destroy (property);
+ }
+ if (selector) {
+ cr_selector_unref (selector);
+ selector = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_import:
+ *@a_this: the "this pointer" of the current instance
+ *of #CRParser.
+ *@a_media_list: out parameter. A linked list of
+ *#CRString
+ *Each CRString is a string that contains
+ *a 'medium' declaration part of the successfully
+ *parsed 'import' declaration.
+ *@a_import_string: out parameter.
+ *A string that contains the 'import
+ *string". The import string can be either an uri (if it starts with
+ *the substring "uri(") or a any other css2 string. Note that
+ * *a_import_string must be initially set to NULL or else, this function
+ *will return CR_BAD_PARAM_ERROR.
+ *@a_location: the location (line, column) where the import has been parsed
+ *
+ *Parses an 'import' declaration as defined in the css2 spec
+ *in appendix D.1:
+ *
+ *import ::=
+ *\@import [STRING|URI] S* [ medium [ ',' S* medium]* ]? ';' S*
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_import (CRParser * a_this,
+ GList ** a_media_list,
+ CRString ** a_import_string,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ guint32 cur_char = 0,
+ next_char = 0;
+ CRString *medium = NULL;
+
+ g_return_val_if_fail (a_this
+ && a_import_string
+ && (*a_import_string == NULL),
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ if (BYTE (a_this, 1, NULL) == '@'
+ && BYTE (a_this, 2, NULL) == 'i'
+ && BYTE (a_this, 3, NULL) == 'm'
+ && BYTE (a_this, 4, NULL) == 'p'
+ && BYTE (a_this, 5, NULL) == 'o'
+ && BYTE (a_this, 6, NULL) == 'r'
+ && BYTE (a_this, 7, NULL) == 't') {
+ SKIP_CHARS (a_this, 1);
+ if (a_location) {
+ cr_parser_get_parsing_location
+ (a_this, a_location) ;
+ }
+ SKIP_CHARS (a_this, 6);
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ PRIVATE (a_this)->state = TRY_PARSE_IMPORT_STATE;
+
+ PEEK_NEXT_CHAR (a_this, &next_char);
+
+ if (next_char == '"' || next_char == '\'') {
+ status = cr_parser_parse_string (a_this, a_import_string);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+ } else {
+ status = cr_parser_parse_uri (a_this, a_import_string);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_ident (a_this, &medium);
+
+ if (status == CR_OK && medium) {
+ *a_media_list = g_list_append (*a_media_list, medium);
+ medium = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ for (; status == CR_OK;) {
+ if ((status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
+ &next_char)) != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ goto okay;
+ }
+ goto error;
+ }
+
+ if (next_char == ',') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ } else {
+ break;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_ident (a_this, &medium);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ if ((status == CR_OK) && medium) {
+ *a_media_list = g_list_append (*a_media_list, medium);
+
+ medium = NULL;
+ }
+
+ CHECK_PARSING_STATUS (status, FALSE);
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == ';');
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ okay:
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->state = IMPORT_PARSED_STATE;
+
+ return CR_OK;
+
+ error:
+
+ if (*a_media_list) {
+ GList *cur = NULL;
+
+ /*
+ *free each element of *a_media_list.
+ *Note that each element of *a_medium list *must*
+ *be a GString* or else, the code that is coming next
+ *will corrupt the memory and lead to hard to debug
+ *random crashes.
+ *This is where C++ and its compile time
+ *type checking mechanism (through STL containers) would
+ *have prevented us to go through this hassle.
+ */
+ for (cur = *a_media_list; cur; cur = cur->next) {
+ if (cur->data) {
+ cr_string_destroy (cur->data);
+ }
+ }
+
+ g_list_free (*a_media_list);
+ *a_media_list = NULL;
+ }
+
+ if (*a_import_string) {
+ cr_string_destroy (*a_import_string);
+ *a_import_string = NULL;
+ }
+
+ if (medium) {
+ cr_string_destroy (medium);
+ medium = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_media:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *
+ *Parses a 'media' declaration as specified in the css2 spec at
+ *appendix D.1:
+ *
+ *media ::= \@media S* medium [ ',' S* medium ]* '{' S* ruleset* '}' S*
+ *
+ *Note that this function calls the required sac handlers during the parsing
+ *to notify media productions. See #CRDocHandler to know the callback called
+ *during \@media parsing.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_media (CRParser * a_this)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ guint32 next_char = 0,
+ cur_char = 0;
+ CRString *medium = NULL;
+ GList *media_list = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this),
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ && token->type == MEDIA_SYM_TK);
+ cr_parsing_location_copy (&location, &token->location) ;
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == IDENT_TK);
+
+ medium = token->u.str;
+ token->u.str = NULL;
+ cr_token_destroy (token);
+ token = NULL;
+
+ if (medium) {
+ media_list = g_list_append (media_list, medium);
+ medium = NULL;
+ }
+
+ for (; status == CR_OK;) {
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ PEEK_NEXT_CHAR (a_this, &next_char);
+
+ if (next_char == ',') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ } else {
+ break;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_ident (a_this, &medium);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ if (medium) {
+ media_list = g_list_append (media_list, medium);
+ medium = NULL;
+ }
+ }
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ ENSURE_PARSING_COND (cur_char == '{');
+
+ /*
+ *call the SAC handler api here.
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->start_media) {
+ PRIVATE (a_this)->sac_handler->start_media
+ (PRIVATE (a_this)->sac_handler, media_list,
+ &location);
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ PRIVATE (a_this)->state = TRY_PARSE_MEDIA_STATE;
+
+ for (; status == CR_OK;) {
+ status = cr_parser_parse_ruleset (a_this);
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ }
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ ENSURE_PARSING_COND (cur_char == '}');
+
+ /*
+ *call the right SAC handler api here.
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->end_media) {
+ PRIVATE (a_this)->sac_handler->end_media
+ (PRIVATE (a_this)->sac_handler, media_list);
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ /*
+ *Then, free the data structures passed to
+ *the last call to the SAC handler.
+ */
+ if (medium) {
+ cr_string_destroy (medium);
+ medium = NULL;
+ }
+
+ if (media_list) {
+ GList *cur = NULL;
+
+ for (cur = media_list; cur; cur = cur->next) {
+ cr_string_destroy (cur->data);
+ }
+
+ g_list_free (media_list);
+ media_list = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->state = MEDIA_PARSED_STATE;
+
+ return CR_OK;
+
+ error:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (medium) {
+ cr_string_destroy (medium);
+ medium = NULL;
+ }
+
+ if (media_list) {
+ GList *cur = NULL;
+
+ for (cur = media_list; cur; cur = cur->next) {
+ cr_string_destroy (cur->data);
+ }
+
+ g_list_free (media_list);
+ media_list = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_page:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *
+ *Parses '\@page' rule as specified in the css2 spec in appendix D.1:
+ *page ::= PAGE_SYM S* IDENT? pseudo_page? S*
+ *'{' S* declaration [ ';' S* declaration ]* '}' S*
+ *
+ *This function also calls the relevant SAC handlers whenever it
+ *encounters a construction that must
+ *be reported to the calling application.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_page (CRParser * a_this)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ CRTerm *css_expression = NULL;
+ CRString *page_selector = NULL,
+ *page_pseudo_class = NULL,
+ *property = NULL;
+ gboolean important = TRUE;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token) ;
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ && token->type == PAGE_SYM_TK);
+
+ cr_parsing_location_copy (&location, &token->location) ;
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == IDENT_TK) {
+ page_selector = token->u.str;
+ token->u.str = NULL;
+ cr_token_destroy (token);
+ token = NULL;
+ } else {
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ }
+
+ /*
+ *try to parse pseudo_page
+ */
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == DELIM_TK && token->u.unichar == ':') {
+ cr_token_destroy (token);
+ token = NULL;
+ status = cr_parser_parse_ident (a_this, &page_pseudo_class);
+ CHECK_PARSING_STATUS (status, FALSE);
+ } else {
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ }
+
+ /*
+ *parse_block
+ *
+ */
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == CBO_TK);
+
+ cr_token_destroy (token);
+ token = NULL;
+
+ /*
+ *Call the appropriate SAC handler here.
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->start_page) {
+ PRIVATE (a_this)->sac_handler->start_page
+ (PRIVATE (a_this)->sac_handler,
+ page_selector, page_pseudo_class,
+ &location);
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ PRIVATE (a_this)->state = TRY_PARSE_PAGE_STATE;
+
+ status = cr_parser_parse_declaration (a_this, &property,
+ &css_expression,
+ &important);
+ ENSURE_PARSING_COND (status == CR_OK);
+
+ /*
+ *call the relevant SAC handler here...
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->property) {
+ if (css_expression)
+ cr_term_ref (css_expression);
+
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler,
+ property, css_expression, important);
+ }
+ /*
+ *... and free the data structure passed to that last
+ *SAC handler.
+ */
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_unref (css_expression);
+ css_expression = NULL;
+ }
+
+ for (;;) {
+ /*parse the other ';' separated declarations */
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type != SEMICOLON_TK) {
+ cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL ;
+ break;
+ }
+
+ cr_token_destroy (token);
+ token = NULL;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_declaration (a_this, &property,
+ &css_expression,
+ &important);
+ if (status != CR_OK)
+ break ;
+
+ /*
+ *call the relevant SAC handler here...
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->property) {
+ cr_term_ref (css_expression);
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler,
+ property, css_expression, important);
+ }
+ /*
+ *... and free the data structure passed to that last
+ *SAC handler.
+ */
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_unref (css_expression);
+ css_expression = NULL;
+ }
+ }
+ cr_parser_try_to_skip_spaces_and_comments
+ (a_this) ;
+ if (token) {
+ cr_token_destroy (token) ;
+ token = NULL ;
+ }
+
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ && token->type == CBC_TK) ;
+ cr_token_destroy (token) ;
+ token = NULL ;
+ /*
+ *call the relevant SAC handler here.
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->end_page) {
+ PRIVATE (a_this)->sac_handler->end_page
+ (PRIVATE (a_this)->sac_handler,
+ page_selector, page_pseudo_class);
+ }
+
+ if (page_selector) {
+ cr_string_destroy (page_selector);
+ page_selector = NULL;
+ }
+
+ if (page_pseudo_class) {
+ cr_string_destroy (page_pseudo_class);
+ page_pseudo_class = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ /*here goes the former implem of this function ... */
+
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->state = PAGE_PARSED_STATE;
+
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ if (page_selector) {
+ cr_string_destroy (page_selector);
+ page_selector = NULL;
+ }
+ if (page_pseudo_class) {
+ cr_string_destroy (page_pseudo_class);
+ page_pseudo_class = NULL;
+ }
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_destroy (css_expression);
+ css_expression = NULL;
+ }
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+ return status;
+}
+
+/**
+ * cr_parser_parse_charset:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *@a_value: out parameter. The actual parsed value of the charset
+ *declararation. Note that for safety check reasons, *a_value must be
+ *set to NULL.
+ *@a_charset_sym_location: the parsing location of the charset rule
+ *
+ *Parses a charset declaration as defined implicitly by the css2 spec in
+ *appendix D.1:
+ *charset ::= CHARSET_SYM S* STRING S* ';'
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_charset (CRParser * a_this, CRString ** a_value,
+ CRParsingLocation *a_charset_sym_location)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ CRString *charset_str = NULL;
+
+ g_return_val_if_fail (a_this && a_value
+ && (*a_value == NULL),
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == CHARSET_SYM_TK);
+ if (a_charset_sym_location) {
+ cr_parsing_location_copy (a_charset_sym_location,
+ &token->location) ;
+ }
+ cr_token_destroy (token);
+ token = NULL;
+
+ PRIVATE (a_this)->state = TRY_PARSE_CHARSET_STATE;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == STRING_TK);
+ charset_str = token->u.str;
+ token->u.str = NULL;
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == SEMICOLON_TK);
+ cr_token_destroy (token);
+ token = NULL;
+
+ if (charset_str) {
+ *a_value = charset_str;
+ charset_str = NULL;
+ }
+
+ PRIVATE (a_this)->state = CHARSET_PARSED_STATE;
+ return CR_OK;
+
+ error:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (*a_value) {
+ cr_string_destroy (*a_value);
+ *a_value = NULL;
+ }
+
+ if (charset_str) {
+ cr_string_destroy (charset_str);
+ charset_str = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_font_face:
+ *@a_this: the current instance of #CRParser.
+ *
+ *Parses the "\@font-face" rule specified in the css1 spec in
+ *appendix D.1:
+ *
+ *font_face ::= FONT_FACE_SYM S*
+ *'{' S* declaration [ ';' S* declaration ]* '}' S*
+ *
+ *This function will call SAC handlers whenever it is necessary.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_font_face (CRParser * a_this)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ CRString *property = NULL;
+ CRTerm *css_expression = NULL;
+ CRToken *token = NULL;
+ gboolean important = FALSE;
+ guint32 next_char = 0,
+ cur_char = 0;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ && token->type == FONT_FACE_SYM_TK);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ if (token) {
+ cr_parsing_location_copy (&location,
+ &token->location) ;
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == CBO_TK);
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ /*
+ *here, call the relevant SAC handler.
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->start_font_face) {
+ PRIVATE (a_this)->sac_handler->start_font_face
+ (PRIVATE (a_this)->sac_handler, &location);
+ }
+ PRIVATE (a_this)->state = TRY_PARSE_FONT_FACE_STATE;
+ /*
+ *and resume the parsing.
+ */
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_declaration (a_this, &property,
+ &css_expression, &important);
+ if (status == CR_OK) {
+ /*
+ *here, call the relevant SAC handler.
+ */
+ cr_term_ref (css_expression);
+ if (PRIVATE (a_this)->sac_handler &&
+ PRIVATE (a_this)->sac_handler->property) {
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler,
+ property, css_expression, important);
+ }
+ ENSURE_PARSING_COND (css_expression && property);
+ }
+ /*free the data structures allocated during last parsing. */
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_unref (css_expression);
+ css_expression = NULL;
+ }
+ for (;;) {
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char == ';') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ } else {
+ break;
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_declaration (a_this,
+ &property,
+ &css_expression,
+ &important);
+ if (status != CR_OK)
+ break;
+ /*
+ *here, call the relevant SAC handler.
+ */
+ cr_term_ref (css_expression);
+ if (PRIVATE (a_this)->sac_handler->property) {
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler,
+ property, css_expression, important);
+ }
+ /*
+ *Then, free the data structures allocated during
+ *last parsing.
+ */
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_unref (css_expression);
+ css_expression = NULL;
+ }
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == '}');
+ /*
+ *here, call the relevant SAC handler.
+ */
+ if (PRIVATE (a_this)->sac_handler->end_font_face) {
+ PRIVATE (a_this)->sac_handler->end_font_face
+ (PRIVATE (a_this)->sac_handler);
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->state = FONT_FACE_PARSED_STATE;
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_destroy (css_expression);
+ css_expression = NULL;
+ }
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+ return status;
+}
+
+/**
+ * cr_parser_parse:
+ *@a_this: the current instance of #CRParser.
+ *
+ *Parses the data that comes from the
+ *input previously associated to the current instance of
+ *#CRParser.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse (CRParser * a_this)
+{
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->use_core_grammar == FALSE) {
+ status = cr_parser_parse_stylesheet (a_this);
+ } else {
+ status = cr_parser_parse_stylesheet_core (a_this);
+ }
+
+ return status;
+}
+
+/**
+ * cr_parser_set_tknzr:
+ * @a_this: the current instance of #CRParser;
+ * @a_tknzr: the new tokenizer.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_set_tknzr (CRParser * a_this, CRTknzr * a_tknzr)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->tknzr) {
+ cr_tknzr_unref (PRIVATE (a_this)->tknzr);
+ }
+
+ PRIVATE (a_this)->tknzr = a_tknzr;
+
+ if (a_tknzr)
+ cr_tknzr_ref (a_tknzr);
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_get_tknzr:
+ *@a_this: the current instance of #CRParser
+ *@a_tknzr: out parameter. The returned tokenizer
+ *
+ *Getter of the parser's underlying tokenizer
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise
+ */
+enum CRStatus
+cr_parser_get_tknzr (CRParser * a_this, CRTknzr ** a_tknzr)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_tknzr, CR_BAD_PARAM_ERROR);
+
+ *a_tknzr = PRIVATE (a_this)->tknzr;
+ return CR_OK;
+}
+
+/**
+ * cr_parser_get_parsing_location:
+ *@a_this: the current instance of #CRParser
+ *@a_loc: the parsing location to get.
+ *
+ *Gets the current parsing location.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_parser_get_parsing_location (CRParser const *a_this,
+ CRParsingLocation *a_loc)
+{
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && a_loc, CR_BAD_PARAM_ERROR) ;
+
+ return cr_tknzr_get_parsing_location
+ (PRIVATE (a_this)->tknzr, a_loc) ;
+}
+
+/**
+ * cr_parser_parse_buf:
+ *@a_this: the current instance of #CRparser
+ *@a_buf: the input buffer
+ *@a_len: the length of the input buffer
+ *@a_enc: the encoding of the buffer
+ *
+ *Parses a stylesheet from a buffer
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_buf (CRParser * a_this,
+ const guchar * a_buf,
+ gulong a_len, enum CREncoding a_enc)
+{
+ enum CRStatus status = CR_ERROR;
+ CRTknzr *tknzr = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_buf, CR_BAD_PARAM_ERROR);
+
+ tknzr = cr_tknzr_new_from_buf ((guchar*)a_buf, a_len, a_enc, FALSE);
+
+ g_return_val_if_fail (tknzr != NULL, CR_ERROR);
+
+ status = cr_parser_set_tknzr (a_this, tknzr);
+ if (status != CR_OK)
+ g_clear_pointer (&tknzr, cr_tknzr_unref);
+ g_return_val_if_fail (status == CR_OK, CR_ERROR);
+
+ status = cr_parser_parse (a_this);
+
+ return status;
+}
+
+/**
+ * cr_parser_destroy:
+ *@a_this: the current instance of #CRParser to
+ *destroy.
+ *
+ *Destroys the current instance
+ *of #CRParser.
+ */
+void
+cr_parser_destroy (CRParser * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ if (PRIVATE (a_this)->tknzr) {
+ if (cr_tknzr_unref (PRIVATE (a_this)->tknzr) == TRUE)
+ PRIVATE (a_this)->tknzr = NULL;
+ }
+
+ if (PRIVATE (a_this)->sac_handler) {
+ cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
+ PRIVATE (a_this)->sac_handler = NULL;
+ }
+
+ if (PRIVATE (a_this)->err_stack) {
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->err_stack = NULL;
+ }
+
+ if (PRIVATE (a_this)) {
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-parser.h b/src/3rdparty/libcroco/src/cr-parser.h
new file mode 100644
index 0000000..24cf5df
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-parser.h
@@ -0,0 +1,130 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#ifndef __CR_PARSER_H__
+#define __CR_PARSER_H__
+
+#include <glib.h>
+#include "cr-input.h"
+#include "cr-tknzr.h"
+#include "cr-utils.h"
+#include "cr-doc-handler.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The declaration file
+ *of the #CRParser class.
+ */
+typedef struct _CRParser CRParser ;
+typedef struct _CRParserPriv CRParserPriv ;
+
+
+/**
+ *The implementation of
+ *the SAC parser.
+ *The Class is opaque
+ *and must be manipulated through
+ *the provided methods.
+ */
+struct _CRParser {
+ CRParserPriv *priv ;
+} ;
+
+
+CRParser * cr_parser_new (CRTknzr *a_tknzr) ;
+
+CRParser * cr_parser_new_from_buf (guchar *a_buf, gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_buf) ;
+
+CRParser * cr_parser_new_from_file (const guchar *a_file_uri,
+ enum CREncoding a_enc) ;
+
+CRParser * cr_parser_new_from_input (CRInput *a_input) ;
+
+enum CRStatus cr_parser_set_tknzr (CRParser *a_this, CRTknzr *a_tknzr) ;
+
+enum CRStatus cr_parser_get_tknzr (CRParser *a_this, CRTknzr **a_tknzr) ;
+
+enum CRStatus cr_parser_get_parsing_location (CRParser const *a_this, CRParsingLocation *a_loc) ;
+
+enum CRStatus cr_parser_try_to_skip_spaces_and_comments (CRParser *a_this) ;
+
+
+enum CRStatus cr_parser_set_sac_handler (CRParser *a_this,
+ CRDocHandler *a_handler) ;
+
+enum CRStatus cr_parser_get_sac_handler (CRParser *a_this,
+ CRDocHandler **a_handler) ;
+
+enum CRStatus cr_parser_set_use_core_grammar (CRParser *a_this,
+ gboolean a_use_core_grammar) ;
+enum CRStatus cr_parser_get_use_core_grammar (CRParser const *a_this,
+ gboolean *a_use_core_grammar) ;
+
+enum CRStatus cr_parser_parse (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_file (CRParser *a_this,
+ const guchar *a_file_uri,
+ enum CREncoding a_enc) ;
+
+enum CRStatus cr_parser_parse_buf (CRParser *a_this, const guchar *a_buf,
+ gulong a_len, enum CREncoding a_enc) ;
+
+enum CRStatus cr_parser_set_default_sac_handler (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_term (CRParser *a_this, CRTerm **a_term) ;
+
+enum CRStatus cr_parser_parse_selector (CRParser * a_this, CRSelector ** a_selector) ;
+
+enum CRStatus cr_parser_parse_expr (CRParser *a_this, CRTerm **a_expr) ;
+
+enum CRStatus cr_parser_parse_prio (CRParser *a_this, CRString **a_prio) ;
+
+enum CRStatus cr_parser_parse_declaration (CRParser *a_this, CRString **a_property,
+ CRTerm **a_expr, gboolean *a_important) ;
+
+enum CRStatus cr_parser_parse_statement_core (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_ruleset (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_import (CRParser *a_this, GList ** a_media_list,
+ CRString **a_import_string,
+ CRParsingLocation *a_location) ;
+
+enum CRStatus cr_parser_parse_media (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_page (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_charset (CRParser *a_this, CRString **a_value,
+ CRParsingLocation *a_charset_sym_location) ;
+
+enum CRStatus cr_parser_parse_font_face (CRParser *a_this) ;
+
+void cr_parser_destroy (CRParser *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_PARSER_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-parsing-location.c b/src/3rdparty/libcroco/src/cr-parsing-location.c
new file mode 100644
index 0000000..0aa0a45
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-parsing-location.c
@@ -0,0 +1,172 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See the COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-parsing-location.h"
+
+/**
+ *@CRParsingLocation:
+ *
+ *Definition of the #CRparsingLocation class.
+ */
+
+
+/**
+ * cr_parsing_location_new:
+ *Instantiates a new parsing location.
+ *
+ *Returns the newly instantiated #CRParsingLocation.
+ *Must be freed by cr_parsing_location_destroy()
+ */
+CRParsingLocation *
+cr_parsing_location_new (void)
+{
+ CRParsingLocation * result = NULL ;
+
+ result = g_try_malloc (sizeof (CRParsingLocation)) ;
+ if (!result) {
+ cr_utils_trace_info ("Out of memory error") ;
+ return NULL ;
+ }
+ cr_parsing_location_init (result) ;
+ return result ;
+}
+
+/**
+ * cr_parsing_location_init:
+ *@a_this: the current instance of #CRParsingLocation.
+ *
+ *Initializes the an instance of #CRparsingLocation.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parsing_location_init (CRParsingLocation *a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+
+ memset (a_this, 0, sizeof (CRParsingLocation)) ;
+ return CR_OK ;
+}
+
+/**
+ * cr_parsing_location_copy:
+ *@a_to: the destination of the copy.
+ *Must be allocated by the caller.
+ *@a_from: the source of the copy.
+ *
+ *Copies an instance of CRParsingLocation into another one.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_parsing_location_copy (CRParsingLocation *a_to,
+ CRParsingLocation const *a_from)
+{
+ g_return_val_if_fail (a_to && a_from, CR_BAD_PARAM_ERROR) ;
+
+ memcpy (a_to, a_from, sizeof (CRParsingLocation)) ;
+ return CR_OK ;
+}
+
+/**
+ * cr_parsing_location_to_string:
+ *@a_this: the current instance of #CRParsingLocation.
+ *@a_mask: a bitmap that defines which parts of the
+ *parsing location are to be serialized (line, column or byte offset)
+ *
+ *Returns the serialized string or NULL in case of an error.
+ */
+gchar *
+cr_parsing_location_to_string (CRParsingLocation const *a_this,
+ enum CRParsingLocationSerialisationMask a_mask)
+{
+ GString *result = NULL ;
+ gchar *str = NULL ;
+
+ g_return_val_if_fail (a_this, NULL) ;
+
+ if (!a_mask) {
+ a_mask = DUMP_LINE | DUMP_COLUMN | DUMP_BYTE_OFFSET ;
+ }
+ result =g_string_new (NULL) ;
+ if (!result)
+ return NULL ;
+ if (a_mask & DUMP_LINE) {
+ g_string_append_printf (result, "line:%d ",
+ a_this->line) ;
+ }
+ if (a_mask & DUMP_COLUMN) {
+ g_string_append_printf (result, "column:%d ",
+ a_this->column) ;
+ }
+ if (a_mask & DUMP_BYTE_OFFSET) {
+ g_string_append_printf (result, "byte offset:%d ",
+ a_this->byte_offset) ;
+ }
+ if (result->len) {
+ str = result->str ;
+ g_string_free (result, FALSE) ;
+ } else {
+ g_string_free (result, TRUE) ;
+ }
+ return str ;
+}
+
+/**
+ * cr_parsing_location_dump:
+ * @a_this: current instance of #CRParsingLocation
+ * @a_mask: the serialization mask.
+ * @a_fp: the file pointer to dump the parsing location to.
+ */
+void
+cr_parsing_location_dump (CRParsingLocation const *a_this,
+ enum CRParsingLocationSerialisationMask a_mask,
+ FILE *a_fp)
+{
+ gchar *str = NULL ;
+
+ g_return_if_fail (a_this && a_fp) ;
+ str = cr_parsing_location_to_string (a_this, a_mask) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ * cr_parsing_location_destroy:
+ *@a_this: the current instance of #CRParsingLocation. Must
+ *have been allocated with cr_parsing_location_new().
+ *
+ *Destroys the current instance of #CRParsingLocation
+ */
+void
+cr_parsing_location_destroy (CRParsingLocation *a_this)
+{
+ g_return_if_fail (a_this) ;
+ g_free (a_this) ;
+}
+
diff --git a/src/3rdparty/libcroco/src/cr-parsing-location.h b/src/3rdparty/libcroco/src/cr-parsing-location.h
new file mode 100644
index 0000000..b8064a5
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-parsing-location.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See the COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_PARSING_LOCATION_H__
+#define __CR_PARSING_LOCATION_H__
+
+#include "cr-utils.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The declaration of the CRParsingLocation
+ *object. This object keeps track of line/column/byte offset/
+ *at which the parsing of a given CSS construction appears.
+ */
+
+typedef struct _CRParsingLocation CRParsingLocation;
+struct _CRParsingLocation {
+ guint line ;
+ guint column ;
+ guint byte_offset ;
+} ;
+
+
+enum CRParsingLocationSerialisationMask {
+ DUMP_LINE = 1,
+ DUMP_COLUMN = 1 << 1,
+ DUMP_BYTE_OFFSET = 1 << 2
+} ;
+
+CRParsingLocation * cr_parsing_location_new (void) ;
+
+enum CRStatus cr_parsing_location_init (CRParsingLocation *a_this) ;
+
+enum CRStatus cr_parsing_location_copy (CRParsingLocation *a_to,
+ CRParsingLocation const *a_from) ;
+
+gchar * cr_parsing_location_to_string (CRParsingLocation const *a_this,
+ enum CRParsingLocationSerialisationMask a_mask) ;
+void cr_parsing_location_dump (CRParsingLocation const *a_this,
+ enum CRParsingLocationSerialisationMask a_mask,
+ FILE *a_fp) ;
+
+void cr_parsing_location_destroy (CRParsingLocation *a_this) ;
+
+
+
+G_END_DECLS
+#endif
diff --git a/src/3rdparty/libcroco/src/cr-prop-list.c b/src/3rdparty/libcroco/src/cr-prop-list.c
new file mode 100644
index 0000000..8e42cee
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-prop-list.c
@@ -0,0 +1,404 @@
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#include <string.h>
+#include "cr-prop-list.h"
+
+#define PRIVATE(a_obj) (a_obj)->priv
+
+struct _CRPropListPriv {
+ CRString *prop;
+ CRDeclaration *decl;
+ CRPropList *next;
+ CRPropList *prev;
+};
+
+static CRPropList *cr_prop_list_allocate (void);
+
+/**
+ *Default allocator of CRPropList
+ *@return the newly allocated CRPropList or NULL
+ *if an error arises.
+ */
+static CRPropList *
+cr_prop_list_allocate (void)
+{
+ CRPropList *result = NULL;
+
+ result = g_try_malloc (sizeof (CRPropList));
+ if (!result) {
+ cr_utils_trace_info ("could not allocate CRPropList");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRPropList));
+ PRIVATE (result) = g_try_malloc (sizeof (CRPropListPriv));
+ if (!PRIVATE (result)) {
+ cr_utils_trace_info ("could not allocate CRPropListPriv");
+ g_free (result);
+ return NULL;
+ }
+ memset (PRIVATE (result), 0, sizeof (CRPropListPriv));
+ return result;
+}
+
+/****************
+ *public methods
+ ***************/
+
+/**
+ * cr_prop_list_append:
+ *@a_this: the current instance of #CRPropList
+ *@a_to_append: the property list to append
+ *
+ *Appends a property list to the current one.
+ *
+ *Returns the resulting prop list, or NULL if an error
+ *occurred
+ */
+CRPropList *
+cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append)
+{
+ CRPropList *cur = NULL;
+
+ g_return_val_if_fail (a_to_append, NULL);
+
+ if (!a_this)
+ return a_to_append;
+
+ /*go fetch the last element of the list */
+ for (cur = a_this;
+ cur && PRIVATE (cur) && PRIVATE (cur)->next;
+ cur = PRIVATE (cur)->next) ;
+ g_return_val_if_fail (cur, NULL);
+ PRIVATE (cur)->next = a_to_append;
+ PRIVATE (a_to_append)->prev = cur;
+ return a_this;
+}
+
+/**
+ * cr_prop_list_append2:
+ *Appends a pair of prop/declaration to
+ *the current prop list.
+ *@a_this: the current instance of #CRPropList
+ *@a_prop: the property to consider
+ *@a_decl: the declaration to consider
+ *
+ *Returns the resulting property list, or NULL in case
+ *of an error.
+ */
+CRPropList *
+cr_prop_list_append2 (CRPropList * a_this,
+ CRString * a_prop,
+ CRDeclaration * a_decl)
+{
+ CRPropList *list = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_prop && a_decl, NULL);
+
+ list = cr_prop_list_allocate ();
+ g_return_val_if_fail (list && PRIVATE (list), NULL);
+
+ PRIVATE (list)->prop = a_prop;
+ PRIVATE (list)->decl = a_decl;
+
+ result = cr_prop_list_append (a_this, list);
+ return result;
+}
+
+/**
+ * cr_prop_list_prepend:
+ *@a_this: the current instance of #CRPropList
+ *@a_to_prepend: the new list to prepend.
+ *
+ *Prepends a list to the current list
+ *Returns the new properties list.
+ */
+CRPropList *
+cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend)
+{
+ CRPropList *cur = NULL;
+
+ g_return_val_if_fail (a_to_prepend, NULL);
+
+ if (!a_this)
+ return a_to_prepend;
+
+ for (cur = a_to_prepend; cur && PRIVATE (cur)->next;
+ cur = PRIVATE (cur)->next) ;
+ g_return_val_if_fail (cur, NULL);
+ PRIVATE (cur)->next = a_this;
+ PRIVATE (a_this)->prev = cur;
+ return a_to_prepend;
+}
+
+/**
+ * cr_prop_list_prepend2:
+ *@a_this: the current instance of #CRPropList
+ *@a_prop_name: property name to append
+ *@a_decl: the property value to append.
+ *
+ *Prepends a property to a list of properties
+ *
+ *Returns the new property list.
+ */
+CRPropList *
+cr_prop_list_prepend2 (CRPropList * a_this,
+ CRString * a_prop_name, CRDeclaration * a_decl)
+{
+ CRPropList *list = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_prop_name && a_decl, NULL);
+
+ list = cr_prop_list_allocate ();
+ g_return_val_if_fail (list, NULL);
+ PRIVATE (list)->prop = a_prop_name;
+ PRIVATE (list)->decl = a_decl;
+ result = cr_prop_list_prepend (a_this, list);
+ return result;
+}
+
+/**
+ * cr_prop_list_set_prop:
+ *@a_this: the current instance of #CRPropList
+ *@a_prop: the property to set
+ *
+ *Sets the property of a CRPropList
+ */
+enum CRStatus
+cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_prop, CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->prop = a_prop;
+ return CR_OK;
+}
+
+/**
+ * cr_prop_list_get_prop:
+ *@a_this: the current instance of #CRPropList
+ *@a_prop: out parameter. The returned property
+ *
+ *Getter of the property associated to the current instance
+ *of #CRPropList
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_prop_list_get_prop (CRPropList const * a_this, CRString ** a_prop)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_prop, CR_BAD_PARAM_ERROR);
+
+ *a_prop = PRIVATE (a_this)->prop;
+ return CR_OK;
+}
+
+/**
+ * cr_prop_list_set_decl:
+ * @a_this: the current instance of #CRPropList
+ * @a_decl: the new property value.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_decl, CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->decl = a_decl;
+ return CR_OK;
+}
+
+/**
+ * cr_prop_list_get_decl:
+ * @a_this: the current instance of #CRPropList
+ * @a_decl: out parameter. The property value
+ *
+ * Returns CR_OK upon successful completion.
+ */
+enum CRStatus
+cr_prop_list_get_decl (CRPropList const * a_this, CRDeclaration ** a_decl)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_decl, CR_BAD_PARAM_ERROR);
+
+ *a_decl = PRIVATE (a_this)->decl;
+ return CR_OK;
+}
+
+/**
+ * cr_prop_list_lookup_prop:
+ *@a_this: the current instance of #CRPropList
+ *@a_prop: the property to lookup
+ *@a_prop_list: out parameter. The property/declaration
+ *pair found (if and only if the function returned code if CR_OK)
+ *
+ *Lookup a given property/declaration pair
+ *
+ *Returns CR_OK if a prop/decl pair has been found,
+ *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something
+ *bad happens.
+ */
+enum CRStatus
+cr_prop_list_lookup_prop (CRPropList * a_this,
+ CRString * a_prop, CRPropList ** a_pair)
+{
+ CRPropList *cur = NULL;
+
+ g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR);
+
+ if (!a_this)
+ return CR_VALUE_NOT_FOUND_ERROR;
+
+ g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ for (cur = a_this; cur; cur = PRIVATE (cur)->next) {
+ if (PRIVATE (cur)->prop
+ && PRIVATE (cur)->prop->stryng
+ && PRIVATE (cur)->prop->stryng->str
+ && a_prop->stryng
+ && a_prop->stryng->str
+ && !strcmp (PRIVATE (cur)->prop->stryng->str,
+ a_prop->stryng->str))
+ break;
+ }
+
+ if (cur) {
+ *a_pair = cur;
+ return CR_OK;
+ }
+
+ return CR_VALUE_NOT_FOUND_ERROR;
+}
+
+/**
+ * cr_prop_list_get_next:
+ *@a_this: the current instance of CRPropList
+ *
+ *Gets the next prop/decl pair in the list
+ *
+ *Returns the next prop/declaration pair of the list,
+ *or NULL if we reached end of list (or if an error occurs)
+ */
+CRPropList *
+cr_prop_list_get_next (CRPropList * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
+
+ return PRIVATE (a_this)->next;
+}
+
+/**
+ * cr_prop_list_get_prev:
+ *@a_this: the current instance of CRPropList
+ *
+ *Gets the previous prop/decl pair in the list
+ *
+ *Returns the previous prop/declaration pair of the list,
+ *or NULL if we reached end of list (or if an error occurs)
+ */
+CRPropList *
+cr_prop_list_get_prev (CRPropList * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
+
+ return PRIVATE (a_this)->prev;
+}
+
+/**
+ * cr_prop_list_unlink:
+ *@a_this: the current list of prop/decl pairs
+ *@a_pair: the prop/decl pair to unlink.
+ *
+ *Unlinks a prop/decl pair from the list
+ *
+ *Returns the new list or NULL in case of an error.
+ */
+CRPropList *
+cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair)
+{
+ CRPropList *prev = NULL,
+ *next = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL);
+
+ /*some sanity checks */
+ if (PRIVATE (a_pair)->next) {
+ next = PRIVATE (a_pair)->next;
+ g_return_val_if_fail (PRIVATE (next), NULL);
+ g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL);
+ }
+ if (PRIVATE (a_pair)->prev) {
+ prev = PRIVATE (a_pair)->prev;
+ g_return_val_if_fail (PRIVATE (prev), NULL);
+ g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL);
+ }
+ if (prev) {
+ PRIVATE (prev)->next = next;
+ }
+ if (next) {
+ PRIVATE (next)->prev = prev;
+ }
+ PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL;
+ if (a_this == a_pair) {
+ if (next)
+ return next;
+ return NULL;
+ }
+ return a_this;
+}
+
+/**
+ * cr_prop_list_destroy:
+ * @a_this: the current instance of #CRPropList
+ */
+void
+cr_prop_list_destroy (CRPropList * a_this)
+{
+ CRPropList *tail = NULL,
+ *cur = NULL;
+
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ for (tail = a_this;
+ tail && PRIVATE (tail) && PRIVATE (tail)->next;
+ tail = cr_prop_list_get_next (tail)) ;
+ g_return_if_fail (tail);
+
+ cur = tail;
+
+ while (cur) {
+ tail = PRIVATE (cur)->prev;
+ if (tail && PRIVATE (tail))
+ PRIVATE (tail)->next = NULL;
+ PRIVATE (cur)->prev = NULL;
+ g_free (PRIVATE (cur));
+ PRIVATE (cur) = NULL;
+ g_free (cur);
+ cur = tail;
+ }
+}
diff --git a/src/3rdparty/libcroco/src/cr-prop-list.h b/src/3rdparty/libcroco/src/cr-prop-list.h
new file mode 100644
index 0000000..797ba43
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-prop-list.h
@@ -0,0 +1,80 @@
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#ifndef __CR_PROP_LIST_H__
+#define __CR_PROP_LIST_H__
+
+#include "cr-utils.h"
+#include "cr-declaration.h"
+#include "cr-string.h"
+
+G_BEGIN_DECLS
+
+typedef struct _CRPropList CRPropList ;
+typedef struct _CRPropListPriv CRPropListPriv ;
+
+struct _CRPropList
+{
+ CRPropListPriv * priv;
+} ;
+
+CRPropList * cr_prop_list_append (CRPropList *a_this,
+ CRPropList *a_to_append) ;
+
+CRPropList * cr_prop_list_append2 (CRPropList *a_this,
+ CRString *a_prop,
+ CRDeclaration *a_decl) ;
+
+CRPropList * cr_prop_list_prepend (CRPropList *a_this,
+ CRPropList *a_to_append) ;
+
+CRPropList * cr_prop_list_prepend2 (CRPropList *a_this,
+ CRString *a_prop,
+ CRDeclaration *a_decl) ;
+
+enum CRStatus cr_prop_list_set_prop (CRPropList *a_this,
+ CRString *a_prop) ;
+
+enum CRStatus cr_prop_list_get_prop (CRPropList const *a_this,
+ CRString **a_prop) ;
+
+enum CRStatus cr_prop_list_lookup_prop (CRPropList *a_this,
+ CRString *a_prop,
+ CRPropList**a_pair) ;
+
+CRPropList * cr_prop_list_get_next (CRPropList *a_this) ;
+
+CRPropList * cr_prop_list_get_prev (CRPropList *a_this) ;
+
+enum CRStatus cr_prop_list_set_decl (CRPropList *a_this,
+ CRDeclaration *a_decl);
+
+enum CRStatus cr_prop_list_get_decl (CRPropList const *a_this,
+ CRDeclaration **a_decl) ;
+
+CRPropList * cr_prop_list_unlink (CRPropList *a_this,
+ CRPropList *a_pair) ;
+
+void cr_prop_list_destroy (CRPropList *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_PROP_LIST_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-pseudo.c b/src/3rdparty/libcroco/src/cr-pseudo.c
new file mode 100644
index 0000000..3644ab1
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-pseudo.c
@@ -0,0 +1,166 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include "cr-pseudo.h"
+
+/**
+ *@CRPseudo:
+ *The definition of the #CRPseudo class.
+ */
+
+/**
+ * cr_pseudo_new:
+ *Constructor of the #CRPseudo class.
+ *
+ *Returns the newly build instance.
+ */
+CRPseudo *
+cr_pseudo_new (void)
+{
+ CRPseudo *result = NULL;
+
+ result = g_malloc0 (sizeof (CRPseudo));
+
+ return result;
+}
+
+/**
+ * cr_pseudo_to_string:
+ * @a_this: the current instance of #CRPseud.
+ *
+ * Returns the serialized pseudo. Caller must free the returned
+ * string using g_free().
+ */
+guchar *
+cr_pseudo_to_string (CRPseudo const * a_this)
+{
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+
+ if (a_this->type == IDENT_PSEUDO) {
+ gchar const *name = NULL;
+
+ if (a_this->name == NULL) {
+ goto error;
+ }
+
+ name = a_this->name->stryng->str;
+
+ if (name) {
+ g_string_append (str_buf, (const gchar *) name);
+ name = NULL;
+ }
+ } else if (a_this->type == FUNCTION_PSEUDO) {
+ gchar const *name = NULL,
+ *arg = NULL;
+
+ if (a_this->name == NULL)
+ goto error;
+
+ name = a_this->name->stryng->str;
+
+ if (a_this->term && a_this->term->type == TERM_IDENT) {
+ arg = a_this->term->content.str->stryng->str;
+ }
+
+ if (name) {
+ g_string_append_printf (str_buf, "%s(", name);
+ name = NULL;
+
+ if (arg) {
+ g_string_append (str_buf, (const gchar *) arg);
+ arg = NULL;
+ }
+
+ g_string_append_c (str_buf, ')');
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+
+ error:
+ g_string_free (str_buf, TRUE);
+ return NULL;
+}
+
+/**
+ * cr_pseudo_dump:
+ *@a_this: the current instance of pseudo
+ *@a_fp: the destination file pointer.
+ *
+ *Dumps the pseudo to a file.
+ *
+ */
+void
+cr_pseudo_dump (CRPseudo const * a_this, FILE * a_fp)
+{
+ guchar *tmp_str = NULL;
+
+ if (a_this) {
+ tmp_str = cr_pseudo_to_string (a_this);
+ if (tmp_str) {
+ fprintf (a_fp, "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+}
+
+/**
+ * cr_pseudo_destroy:
+ *@a_this: the current instance to destroy.
+ *
+ *destructor of the #CRPseudo class.
+ */
+void
+cr_pseudo_destroy (CRPseudo * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->name) {
+ cr_string_destroy (a_this->name);
+ a_this->name = NULL;
+ }
+
+ if (a_this->sel_name) {
+ cr_string_destroy (a_this->sel_name);
+ a_this->sel_name = NULL;
+ }
+
+ if (a_this->term) {
+ cr_term_destroy (a_this->term);
+ a_this->term = NULL;
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-pseudo.h b/src/3rdparty/libcroco/src/cr-pseudo.h
new file mode 100644
index 0000000..b784350
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-pseudo.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information
+ */
+
+#ifndef __CR_PSEUDO_H__
+#define __CR_PSEUDO_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-attr-sel.h"
+#include "cr-parsing-location.h"
+#include "cr-term.h"
+
+G_BEGIN_DECLS
+
+enum CRPseudoType
+{
+ IDENT_PSEUDO = 0,
+ FUNCTION_PSEUDO
+} ;
+
+typedef struct _CRPseudo CRPseudo ;
+
+/**
+ *The CRPseudo Class.
+ *Abstract a "pseudo" as defined by the css2 spec
+ *in appendix D.1 .
+ */
+struct _CRPseudo
+{
+ enum CRPseudoType type ;
+ CRString *name ;
+ CRString *sel_name;
+ CRTerm *term ;
+ CRParsingLocation location ;
+} ;
+
+CRPseudo * cr_pseudo_new (void) ;
+
+guchar * cr_pseudo_to_string (CRPseudo const *a_this) ;
+
+void cr_pseudo_dump (CRPseudo const *a_this, FILE *a_fp) ;
+
+void cr_pseudo_destroy (CRPseudo *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_PSEUDO_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-rgb.c b/src/3rdparty/libcroco/src/cr-rgb.c
new file mode 100644
index 0000000..e2a1fc8
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-rgb.c
@@ -0,0 +1,686 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "cr-rgb.h"
+#include "cr-term.h"
+#include "cr-parser.h"
+
+static const CRRgb gv_standard_colors[] = {
+ {(const guchar*)"aliceblue", 240, 248, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"antiquewhite", 250, 235, 215, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"aqua", 0, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"aquamarine", 127, 255, 212, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"azure", 240, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"beige", 245, 245, 220, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"bisque", 255, 228, 196, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"black", 0, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"blanchedalmond", 255, 235, 205, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"blue", 0, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"blueviolet", 138, 43, 226, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"brown", 165, 42, 42, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"burlywood", 222, 184, 135, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"cadetblue", 95, 158, 160, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"chartreuse", 127, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"chocolate", 210, 105, 30, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"coral", 255, 127, 80, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"cornflowerblue", 100, 149, 237, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"cornsilk", 255, 248, 220, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"crimson", 220, 20, 60, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"cyan", 0, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkblue", 0, 0, 139, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkcyan", 0, 139, 139, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkgoldenrod", 184, 134, 11, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkgray", 169, 169, 169, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkgreen", 0, 100, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkgrey", 169, 169, 169, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkkhaki", 189, 183, 107, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkmagenta", 139, 0, 139, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkolivegreen", 85, 107, 47, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkorange", 255, 140, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkorchid", 153, 50, 204, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkred", 139, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darksalmon", 233, 150, 122, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkseagreen", 143, 188, 143, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkslateblue", 72, 61, 139, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkslategray", 47, 79, 79, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkslategrey", 47, 79, 79, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkturquoise", 0, 206, 209, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkviolet", 148, 0, 211, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"deeppink", 255, 20, 147, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"deepskyblue", 0, 191, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"dimgray", 105, 105, 105, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"dimgrey", 105, 105, 105, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"dodgerblue", 30, 144, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"firebrick", 178, 34, 34, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"floralwhite", 255, 250, 240, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"forestgreen", 34, 139, 34, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"fuchsia", 255, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"gainsboro", 220, 220, 220, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"ghostwhite", 248, 248, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"gold", 255, 215, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"goldenrod", 218, 165, 32, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"gray", 128, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"green", 0, 128, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"greenyellow", 173, 255, 47, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"grey", 128, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"honeydew", 240, 255, 240, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"hotpink", 255, 105, 180, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"indianred", 205, 92, 92, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"indigo", 75, 0, 130, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"ivory", 255, 255, 240, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"khaki", 240, 230, 140, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lavender", 230, 230, 250, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lavenderblush", 255, 240, 245, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lawngreen", 124, 252, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lemonchiffon", 255, 250, 205, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightblue", 173, 216, 230, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightcoral", 240, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightcyan", 224, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightgoldenrodyellow", 250, 250, 210, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightgray", 211, 211, 211, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightgreen", 144, 238, 144, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightgrey", 211, 211, 211, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightpink", 255, 182, 193, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightsalmon", 255, 160, 122, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightseagreen", 32, 178, 170, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightskyblue", 135, 206, 250, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightslategray", 119, 136, 153, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightslategrey", 119, 136, 153, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightsteelblue", 176, 196, 222, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightyellow", 255, 255, 224, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lime", 0, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"limegreen", 50, 205, 50, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"linen", 250, 240, 230, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"magenta", 255, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"maroon", 128, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumaquamarine", 102, 205, 170, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumblue", 0, 0, 205, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumorchid", 186, 85, 211, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumpurple", 147, 112, 219, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumseagreen", 60, 179, 113, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumslateblue", 123, 104, 238, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumspringgreen", 0, 250, 154, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumturquoise", 72, 209, 204, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumvioletred", 199, 21, 133, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"midnightblue", 25, 25, 112, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mintcream", 245, 255, 250, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mistyrose", 255, 228, 225, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"moccasin", 255, 228, 181, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"navajowhite", 255, 222, 173, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"navy", 0, 0, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"oldlace", 253, 245, 230, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"olive", 128, 128, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"olivedrab", 107, 142, 35, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"orange", 255, 165, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"orangered", 255, 69, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"orchid", 218, 112, 214, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"palegoldenrod", 238, 232, 170, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"palegreen", 152, 251, 152, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"paleturquoise", 175, 238, 238, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"palevioletred", 219, 112, 147, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"papayawhip", 255, 239, 213, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"peachpuff", 255, 218, 185, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"peru", 205, 133, 63, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"pink", 255, 192, 203, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"plum", 221, 160, 221, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"powderblue", 176, 224, 230, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"purple", 128, 0, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"rebeccapurple", 102, 51, 153, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"red", 255, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"rosybrown", 188, 143, 143, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"royalblue", 65, 105, 225, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"saddlebrown", 139, 69, 19, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"salmon", 250, 128, 114, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"sandybrown", 244, 164, 96, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"seagreen", 46, 139, 87, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"seashell", 255, 245, 238, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"sienna", 160, 82, 45, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"silver", 192, 192, 192, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"skyblue", 135, 206, 235, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"slateblue", 106, 90, 205, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"slategray", 112, 128, 144, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"slategrey", 112, 128, 144, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"snow", 255, 250, 250, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"springgreen", 0, 255, 127, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"steelblue", 70, 130, 180, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"tan", 210, 180, 140, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"teal", 0, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"thistle", 216, 191, 216, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"tomato", 255, 99, 71, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"transparent", 255, 255, 255, FALSE, FALSE, TRUE, {0,0,0}},
+ {(const guchar*)"turquoise", 64, 224, 208, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"violet", 238, 130, 238, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"wheat", 245, 222, 179, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"white", 255, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"whitesmoke", 245, 245, 245, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"yellow", 255, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"yellowgreen", 154, 205, 50, FALSE, FALSE, FALSE, {0,0,0}}
+};
+
+/**
+ * cr_rgb_new:
+ *
+ *The default constructor of #CRRgb.
+ *
+ *Returns the newly built instance of #CRRgb
+ */
+CRRgb *
+cr_rgb_new (void)
+{
+ CRRgb *result = NULL;
+
+ result = g_try_malloc (sizeof (CRRgb));
+
+ if (result == NULL) {
+ cr_utils_trace_info ("No more memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRRgb));
+
+ return result;
+}
+
+/**
+ * cr_rgb_new_with_vals:
+ *@a_red: the red component of the color.
+ *@a_green: the green component of the color.
+ *@a_blue: the blue component of the color.
+ *@a_unit: the unit of the rgb values.
+ *(either percentage or integer values)
+ *
+ *A constructor of #CRRgb.
+ *
+ *Returns the newly built instance of #CRRgb.
+ */
+CRRgb *
+cr_rgb_new_with_vals (gulong a_red, gulong a_green,
+ gulong a_blue, gboolean a_is_percentage)
+{
+ CRRgb *result = NULL;
+
+ result = cr_rgb_new ();
+
+ g_return_val_if_fail (result, NULL);
+
+ result->red = a_red;
+ result->green = a_green;
+ result->blue = a_blue;
+ result->is_percentage = a_is_percentage;
+
+ return result;
+}
+
+/**
+ * cr_rgb_to_string:
+ *@a_this: the instance of #CRRgb to serialize.
+ *
+ *Serializes the rgb into a zero terminated string.
+ *
+ *Returns the zero terminated string containing the serialized
+ *rgb. MUST BE FREED by the caller using g_free().
+ */
+guchar *
+cr_rgb_to_string (CRRgb const * a_this)
+{
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+
+ str_buf = g_string_new (NULL);
+ g_return_val_if_fail (str_buf, NULL);
+
+ if (a_this->is_percentage == 1) {
+ g_string_append_printf (str_buf, "%ld", a_this->red);
+
+ g_string_append (str_buf, "%, ");
+
+ g_string_append_printf (str_buf, "%ld", a_this->green);
+ g_string_append (str_buf, "%, ");
+
+ g_string_append_printf (str_buf, "%ld", a_this->blue);
+ g_string_append_c (str_buf, '%');
+ } else {
+ g_string_append_printf (str_buf, "%ld", a_this->red);
+ g_string_append (str_buf, ", ");
+
+ g_string_append_printf (str_buf, "%ld", a_this->green);
+ g_string_append (str_buf, ", ");
+
+ g_string_append_printf (str_buf, "%ld", a_this->blue);
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ }
+
+ return result;
+}
+
+/**
+ * cr_rgb_dump:
+ *@a_this: the "this pointer" of
+ *the current instance of #CRRgb.
+ *@a_fp: the destination file pointer.
+ *
+ *Dumps the current instance of #CRRgb
+ *to a file.
+ */
+void
+cr_rgb_dump (CRRgb const * a_this, FILE * a_fp)
+{
+ guchar *str = NULL;
+
+ g_return_if_fail (a_this);
+
+ str = cr_rgb_to_string (a_this);
+
+ if (str) {
+ fprintf (a_fp, "%s", str);
+ g_free (str);
+ str = NULL;
+ }
+}
+
+/**
+ * cr_rgb_compute_from_percentage:
+ *@a_this: the current instance of #CRRgb
+ *
+ *If the rgb values are expressed in percentage,
+ *compute their real value.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_compute_from_percentage (CRRgb * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ if (a_this->is_percentage == FALSE)
+ return CR_OK;
+ a_this->red = a_this->red * 255 / 100;
+ a_this->green = a_this->green * 255 / 100;
+ a_this->blue = a_this->blue * 255 / 100;
+ a_this->is_percentage = FALSE;
+ return CR_OK;
+}
+
+/**
+ * cr_rgb_set:
+ *@a_this: the current instance of #CRRgb.
+ *@a_red: the red value.
+ *@a_green: the green value.
+ *@a_blue: the blue value.
+ *
+ *Sets rgb values to the RGB.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_rgb_set (CRRgb * a_this, gulong a_red,
+ gulong a_green, gulong a_blue, gboolean a_is_percentage)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ if (a_is_percentage != FALSE) {
+ g_return_val_if_fail (a_red <= 100
+ && a_green <= 100
+ && a_blue <= 100, CR_BAD_PARAM_ERROR);
+ }
+
+ a_this->is_percentage = a_is_percentage;
+
+ a_this->red = a_red;
+ a_this->green = a_green;
+ a_this->blue = a_blue;
+ a_this->inherit = FALSE ;
+ a_this->is_transparent = FALSE ;
+ return CR_OK;
+}
+
+/**
+ * cr_rgb_set_to_inherit:
+ *@a_this: the current instance of #CRRgb
+ *
+ *sets the value of the rgb to inherit.
+ *Look at the css spec from chapter 6.1 to 6.2 to understand
+ *the meaning of "inherit".
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_set_to_inherit (CRRgb *a_this, gboolean a_inherit)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+
+ a_this->inherit = a_inherit ;
+
+ return CR_OK ;
+}
+
+/**
+ * cr_rgb_is_set_to_inherit:
+ *
+ * @a_this: the current instance of #CRRgb.
+ *
+ * Returns TRUE if the rgb is set to the value "inherit", FALSE otherwise.
+ */
+gboolean
+cr_rgb_is_set_to_inherit (CRRgb const *a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+
+ return a_this->inherit ;
+}
+
+/**
+ * cr_rgb_is_set_to_transparent:
+ *@a_this: the current instance of
+ *#CRRgb
+ *
+ *Tests if the rgb is set to the
+ *value "transparent" or not.
+ *
+ *Returns TRUE if the rgb has been set to
+ *transparent, FALSE otherwise.
+ */
+gboolean
+cr_rgb_is_set_to_transparent (CRRgb const *a_this)
+{
+ g_return_val_if_fail (a_this, FALSE) ;
+ return a_this->is_transparent ;
+}
+
+
+/**
+ * cr_rgb_set_to_transparent:
+ *@a_this: the current instance of #CRRgb
+ *@a_is_transparent: set to transparent or not.
+ *
+ *Sets the rgb to the "transparent" value (or not)
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_set_to_transparent (CRRgb *a_this,
+ gboolean a_is_transparent)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+ a_this->is_transparent = a_is_transparent ;
+ return CR_OK ;
+}
+
+/**
+ * cr_rgb_set_from_rgb:
+ *@a_this: the current instance of #CRRgb.
+ *@a_rgb: the rgb to "copy"
+ *
+ *Sets the rgb from an other one.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_set_from_rgb (CRRgb * a_this, CRRgb const * a_rgb)
+{
+ g_return_val_if_fail (a_this && a_rgb, CR_BAD_PARAM_ERROR);
+
+ cr_rgb_copy (a_this, a_rgb) ;
+
+ return CR_OK;
+}
+
+static int
+cr_rgb_color_name_compare (const void *a,
+ const void *b)
+{
+ const char *a_color_name = a;
+ const CRRgb *rgb = b;
+
+ return g_ascii_strcasecmp (a_color_name, (const char *) rgb->name);
+}
+
+/**
+ * cr_rgb_set_from_name:
+ * @a_this: the current instance of #CRRgb
+ * @a_color_name: the color name
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_set_from_name (CRRgb * a_this, const guchar * a_color_name)
+{
+ enum CRStatus status = CR_OK;
+ CRRgb *result;
+
+ g_return_val_if_fail (a_this && a_color_name, CR_BAD_PARAM_ERROR);
+
+ result = bsearch (a_color_name,
+ gv_standard_colors,
+ G_N_ELEMENTS (gv_standard_colors),
+ sizeof (gv_standard_colors[0]),
+ cr_rgb_color_name_compare);
+ if (result != NULL)
+ cr_rgb_set_from_rgb (a_this, result);
+ else
+ status = CR_UNKNOWN_TYPE_ERROR;
+
+ return status;
+}
+
+/**
+ * cr_rgb_set_from_hex_str:
+ * @a_this: the current instance of #CRRgb
+ * @a_hex: the hexadecimal value to set.
+ *
+ * Returns CR_OK upon successful completion.
+ */
+enum CRStatus
+cr_rgb_set_from_hex_str (CRRgb * a_this, const guchar * a_hex)
+{
+ enum CRStatus status = CR_OK;
+ gulong i = 0;
+ guchar colors[3] = { 0 };
+
+ g_return_val_if_fail (a_this && a_hex, CR_BAD_PARAM_ERROR);
+
+ if (strlen ((const char *) a_hex) == 3) {
+ for (i = 0; i < 3; i++) {
+ if (a_hex[i] >= '0' && a_hex[i] <= '9') {
+ colors[i] = a_hex[i] - '0';
+ colors[i] = (colors[i] << 4) | colors[i];
+ } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') {
+ colors[i] = 10 + a_hex[i] - 'a';
+ colors[i] = (colors[i] << 4) | colors[i];
+ } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') {
+ colors[i] = 10 + a_hex[i] - 'A';
+ colors[i] = (colors[i] << 4) | colors[i];
+ } else {
+ status = CR_UNKNOWN_TYPE_ERROR;
+ }
+ }
+ } else if (strlen ((const char *) a_hex) == 6) {
+ for (i = 0; i < 6; i++) {
+ if (a_hex[i] >= '0' && a_hex[i] <= '9') {
+ colors[i / 2] <<= 4;
+ colors[i / 2] |= a_hex[i] - '0';
+ status = CR_OK;
+ } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') {
+ colors[i / 2] <<= 4;
+ colors[i / 2] |= 10 + a_hex[i] - 'a';
+ status = CR_OK;
+ } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') {
+ colors[i / 2] <<= 4;
+ colors[i / 2] |= 10 + a_hex[i] - 'A';
+ status = CR_OK;
+ } else {
+ status = CR_UNKNOWN_TYPE_ERROR;
+ }
+ }
+ } else {
+ status = CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ if (status == CR_OK) {
+ status = cr_rgb_set (a_this, colors[0],
+ colors[1], colors[2], FALSE);
+ cr_rgb_set_to_transparent (a_this, FALSE) ;
+ }
+ return status;
+}
+
+/**
+ * cr_rgb_set_from_term:
+ *@a_this: the instance of #CRRgb to set
+ *@a_value: the terminal from which to set
+ *
+ *Set the rgb from a terminal symbol
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_set_from_term (CRRgb *a_this, const struct _CRTerm *a_value)
+{
+ enum CRStatus status = CR_OK ;
+ g_return_val_if_fail (a_this && a_value,
+ CR_BAD_PARAM_ERROR) ;
+
+ switch(a_value->type) {
+ case TERM_RGB:
+ if (a_value->content.rgb) {
+ cr_rgb_set_from_rgb
+ (a_this, a_value->content.rgb) ;
+ }
+ break ;
+ case TERM_IDENT:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strncmp ("inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ a_this->inherit = TRUE;
+ a_this->is_transparent = FALSE ;
+ } else {
+ status = cr_rgb_set_from_name
+ (a_this,
+ (const guchar *) a_value->content.str->stryng->str) ;
+ }
+ } else {
+ cr_utils_trace_info
+ ("a_value has NULL string value") ;
+ }
+ break ;
+ case TERM_HASH:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ status = cr_rgb_set_from_hex_str
+ (a_this,
+ (const guchar *) a_value->content.str->stryng->str) ;
+ } else {
+ cr_utils_trace_info
+ ("a_value has NULL string value") ;
+ }
+ break ;
+ default:
+ status = CR_UNKNOWN_TYPE_ERROR ;
+ }
+ return status ;
+}
+
+enum CRStatus
+cr_rgb_copy (CRRgb *a_dest, CRRgb const *a_src)
+{
+ g_return_val_if_fail (a_dest && a_src,
+ CR_BAD_PARAM_ERROR) ;
+
+ memcpy (a_dest, a_src, sizeof (CRRgb)) ;
+ return CR_OK ;
+}
+
+/**
+ * cr_rgb_destroy:
+ *@a_this: the "this pointer" of the
+ *current instance of #CRRgb.
+ *
+ *Destructor of #CRRgb.
+ */
+void
+cr_rgb_destroy (CRRgb * a_this)
+{
+ g_return_if_fail (a_this);
+ g_free (a_this);
+}
+
+/**
+ * cr_rgb_parse_from_buf:
+ *@a_str: a string that contains a color description
+ *@a_enc: the encoding of a_str
+ *
+ *Parses a text buffer that contains a rgb color
+ *
+ *Returns the parsed color, or NULL in case of error
+ */
+CRRgb *
+cr_rgb_parse_from_buf (const guchar *a_str,
+ enum CREncoding a_enc)
+{
+ enum CRStatus status = CR_OK ;
+ CRTerm *value = NULL ;
+ CRParser * parser = NULL;
+ CRRgb *result = NULL;
+
+ g_return_val_if_fail (a_str, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar *) a_str, strlen ((const char *) a_str), a_enc, FALSE);
+
+ g_return_val_if_fail (parser, NULL);
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_parse_term (parser, &value);
+ if (status != CR_OK)
+ goto cleanup;
+
+ result = cr_rgb_new ();
+ if (!result)
+ goto cleanup;
+
+ status = cr_rgb_set_from_term (result, value);
+
+cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+ if (value) {
+ cr_term_destroy(value);
+ value = NULL;
+ }
+ return result ;
+}
+
diff --git a/src/3rdparty/libcroco/src/cr-rgb.h b/src/3rdparty/libcroco/src/cr-rgb.h
new file mode 100644
index 0000000..a127a44
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-rgb.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * see COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_RGB_H__
+#define __CR_RGB_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+
+typedef struct _CRRgb CRRgb ;
+struct _CRRgb
+{
+ /*
+ *the unit of the rgb.
+ *Either NO_UNIT (integer) or
+ *UNIT_PERCENTAGE (percentage).
+ */
+ const guchar *name ;
+ glong red ;
+ glong green ;
+ glong blue ;
+ gboolean is_percentage ;
+ gboolean inherit ;
+ gboolean is_transparent ;
+ CRParsingLocation location ;
+} ;
+
+CRRgb * cr_rgb_new (void) ;
+
+CRRgb * cr_rgb_new_with_vals (gulong a_red, gulong a_green,
+ gulong a_blue, gboolean a_is_percentage) ;
+
+CRRgb *cr_rgb_parse_from_buf(const guchar *a_str,
+ enum CREncoding a_enc);
+
+enum CRStatus cr_rgb_compute_from_percentage (CRRgb *a_this) ;
+
+enum CRStatus cr_rgb_set (CRRgb *a_this, gulong a_red,
+ gulong a_green, gulong a_blue,
+ gboolean a_is_percentage) ;
+
+enum CRStatus cr_rgb_copy (CRRgb *a_dest, CRRgb const *a_src) ;
+
+enum CRStatus cr_rgb_set_to_inherit (CRRgb *a_this, gboolean a_inherit) ;
+
+gboolean cr_rgb_is_set_to_inherit (CRRgb const *a_this) ;
+
+gboolean cr_rgb_is_set_to_transparent (CRRgb const *a_this) ;
+
+enum CRStatus cr_rgb_set_to_transparent (CRRgb *a_this,
+ gboolean a_is_transparent) ;
+enum CRStatus cr_rgb_set_from_rgb (CRRgb *a_this, CRRgb const *a_rgb) ;
+
+enum CRStatus cr_rgb_set_from_name (CRRgb *a_this, const guchar *a_color_name) ;
+
+enum CRStatus cr_rgb_set_from_hex_str (CRRgb *a_this, const guchar * a_hex_value) ;
+
+struct _CRTerm;
+
+enum CRStatus cr_rgb_set_from_term (CRRgb *a_this, const struct _CRTerm *a_value);
+
+guchar * cr_rgb_to_string (CRRgb const *a_this) ;
+
+void cr_rgb_dump (CRRgb const *a_this, FILE *a_fp) ;
+
+void cr_rgb_destroy (CRRgb *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_RGB_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-sel-eng.c b/src/3rdparty/libcroco/src/cr-sel-eng.c
new file mode 100644
index 0000000..8ed485d
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-sel-eng.c
@@ -0,0 +1,2236 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser
+ * General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-sel-eng.h"
+#include "cr-node-iface.h"
+
+/**
+ *@CRSelEng:
+ *
+ *The definition of the #CRSelEng class.
+ *The #CRSelEng is actually the "Selection Engine"
+ *class. This is highly experimental for at the moment and
+ *its api is very likely to change in a near future.
+ */
+
+#define PRIVATE(a_this) (a_this)->priv
+
+struct CRPseudoClassSelHandlerEntry {
+ guchar *name;
+ enum CRPseudoType type;
+ CRPseudoClassSelectorHandler handler;
+};
+
+struct _CRSelEngPriv {
+ /*not used yet */
+ gboolean case_sensitive;
+
+ CRNodeIface const *node_iface;
+ CRStyleSheet *sheet;
+ /**
+ *where to store the next statement
+ *to be visited so that we can remember
+ *it from one method call to another.
+ */
+ CRStatement *cur_stmt;
+ GList *pcs_handlers;
+ gint pcs_handlers_size;
+} ;
+
+static gboolean class_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static gboolean id_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static gboolean attr_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static enum CRStatus sel_matches_node_real (CRSelEng * a_this,
+ CRSimpleSel * a_sel,
+ CRXMLNodePtr a_node,
+ gboolean * a_result,
+ gboolean a_eval_sel_list_from_end,
+ gboolean a_recurse);
+
+static enum CRStatus cr_sel_eng_get_matched_rulesets_real (CRSelEng * a_this,
+ CRStyleSheet *
+ a_stylesheet,
+ CRXMLNodePtr a_node,
+ CRStatement ***
+ a_rulesets,
+ gulong * a_len,
+ gulong * a_capacity);
+
+static enum CRStatus put_css_properties_in_props_list (CRPropList ** a_props,
+ CRStatement *
+ a_ruleset);
+
+static gboolean pseudo_class_add_sel_matches_node (CRSelEng * a_this,
+ CRAdditionalSel * a_add_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean empty_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean root_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean lang_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean only_child_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean first_child_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean first_of_type_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean last_child_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean last_of_type_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean nth_child_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean nth_of_type_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean nth_last_child_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean nth_last_of_type_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static CRXMLNodePtr get_next_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static CRXMLNodePtr get_first_child_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static CRXMLNodePtr get_prev_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static CRXMLNodePtr get_next_parent_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static CRArguments get_arguments_from_function (CRAdditionalSel * a_sel);
+
+void
+cr_sel_eng_set_node_iface (CRSelEng *const a_this, CRNodeIface const *const a_node_iface)
+{
+ /* Allow NULL: the caller may be just ensuring that the previous node_iface
+ value doesn't get used until next cr_sel_eng_set_node_iface call. */
+ PRIVATE(a_this)->node_iface = a_node_iface;
+}
+
+/* Quick strcmp. Test only for == 0 or != 0, not < 0 or > 0. */
+#define strqcmp(str,lit,lit_len) \
+ (strlen (str) != (lit_len) || memcmp (str, lit, lit_len))
+
+static gboolean
+root_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "root")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :root only");
+ return FALSE;
+ }
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+
+ // libxml apears to set the parent of the root element to an
+ // element of type 'xml'.
+ return (parent == NULL || !strcmp(node_iface->getLocalName(parent),"xml") );
+}
+
+static gboolean
+empty_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr cur_node = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "empty")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :empty only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+
+ cur_node = node_iface->getFirstChild (a_node);
+
+ return (cur_node == NULL);
+}
+
+static gboolean
+lang_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr a_node)
+{
+ CRNodeIface const *node_iface;
+ CRXMLNodePtr node = a_node;
+ gboolean result = FALSE;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ node_iface = PRIVATE(a_this)->node_iface;
+
+ /* "xml:lang" needed for SVG */
+ if ( (strqcmp (a_sel->content.pseudo->name->stryng->str, "lang", 4 ) &&
+ (strqcmp (a_sel->content.pseudo->name->stryng->str, "xml:lang", 8 ) ) )
+ || a_sel->content.pseudo->type != FUNCTION_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :lang only");
+ return FALSE;
+ }
+ /*lang code should exist and be at least of length 2 */
+ if (!a_sel->content.pseudo->term
+ || a_sel->content.pseudo->term->type != TERM_IDENT
+ || !a_sel->content.pseudo->term->content.str->stryng
+ || a_sel->content.pseudo->term->content.str->stryng->len < 2)
+ return FALSE;
+ for (; node; node = get_next_parent_element_node (node_iface, node)) {
+ char *val = node_iface->getProp (node, "lang");
+ if (!val) val = node_iface->getProp (node, "xml:lang");
+ if (val) {
+ if (!strcasecmp(val, a_sel->content.pseudo->term->content.str->stryng->str)) {
+ result = TRUE;
+ break;
+ }
+ node_iface->freePropVal (val);
+ val = NULL;
+ }
+ }
+
+ return result;
+}
+
+static gboolean
+only_child_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+ CRXMLNodePtr cur_node = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "only-child")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :only-child only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+ return (cur_node == a_node &&
+ !get_next_element_node(node_iface, cur_node) );
+}
+
+static gboolean
+only_of_type_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+ CRXMLNodePtr cur_node = NULL;
+ int m = 0;
+ int child = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "only-of-type")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :only-of-type selector only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) {
+ ++m;
+ }
+ if (cur_node == a_node) {
+ child = m;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+ return (child == m && child == 1);
+}
+
+static gboolean
+first_child_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr node = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "first-child")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :first-child only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+ node = get_first_child_element_node (node_iface, parent);
+ return (node == a_node);
+}
+
+static gboolean
+first_of_type_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ // Count which child no. of type
+ CRXMLNodePtr cur_node = NULL;
+ int child = 0;
+ int found = FALSE;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "first-of-type")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :first-of-type only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ if(!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) {
+ child++;
+ }
+ if (cur_node == a_node) {
+ found = TRUE;
+ break;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+
+ if (!found)
+ return FALSE;
+
+ return (child == 1);
+}
+
+static gboolean
+last_child_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ CRXMLNodePtr cur_node = NULL;
+ int m = 0;
+ int child = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "last-child")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :last-child only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+ while (cur_node) {
+ ++m;
+ if (cur_node == a_node) {
+ child = m;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+
+ }
+ return (m == child);
+}
+
+static gboolean
+last_of_type_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ CRXMLNodePtr cur_node = NULL;
+ int m = 0;
+ int child = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "last-of-type")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :last-of-type only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) {
+ ++m;
+ }
+ if (cur_node == a_node) {
+ child = m;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+
+ return (m == child);
+}
+
+// See https://www.w3.org/TR/selectors/#nth-child-pseudo
+static gboolean
+nth_child_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ /* Count which child this is */
+ CRXMLNodePtr cur_node = NULL;
+ int child = 0;
+ int found = FALSE;
+ int a, b;
+ CRArguments arg;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-child")
+ || a_sel->content.pseudo->type != FUNCTION_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :nth-child only");
+ return FALSE;
+ }
+
+ /*pseude code term should exist */
+ if (!a_sel->content.pseudo->term)
+ return FALSE;
+
+ arg = get_arguments_from_function (a_sel);
+
+ if (arg.a == 0 && arg.b == 0)
+ return FALSE;
+
+ a = arg.a;
+ b = arg.b;
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ ++child;
+ if (cur_node == a_node) {
+ found = TRUE;
+ break;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+
+ if (!found)
+ return FALSE;
+
+ if (a == 0)
+ return (b == child);
+
+ return ((child - b)%a == 0 && (child - b)/a > -1);
+}
+
+static gboolean
+nth_of_type_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ // Count which child no. of required type
+ CRXMLNodePtr cur_node = NULL;
+ int child = 0;
+ int found = FALSE;
+ int a, b;
+ CRArguments arg;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-of-type")
+ || a_sel->content.pseudo->type != FUNCTION_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :nth-of-type only");
+ return FALSE;
+ }
+
+ // pseudo code term should exist
+ if (!a_sel->content.pseudo->term)
+ return FALSE;
+
+ arg = get_arguments_from_function (a_sel);
+
+ if (arg.a == 0 && arg.b == 0)
+ return FALSE;
+
+ a = arg.a;
+ b = arg.b;
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ // check if type match
+ if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str))
+ ++child;
+ if (cur_node == a_node) {
+ found = TRUE;
+ break;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+
+ if (!found)
+ return FALSE;
+
+ if (a == 0)
+ return (b == child);
+
+ return ((child - b)%a == 0 && (child - b)/a > -1);
+}
+
+static gboolean
+nth_last_child_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ /* Count which child this is (child) and total number of children (m). */
+ CRXMLNodePtr cur_node = NULL;
+ int m = 0;
+ int child = 0;
+ int found = FALSE;
+ int a, b;
+ CRArguments arg;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-last-child")) {
+ cr_utils_trace_info ("This handler is for :nth-last-child only");
+ return FALSE;
+ }
+
+ /*pseudo code term should exist */
+ if (!a_sel->content.pseudo->term)
+ return FALSE;
+
+ arg = get_arguments_from_function (a_sel);
+
+ if (arg.a == 0 && arg.b == 0)
+ return FALSE;
+
+ a = arg.a;
+ b = arg.b;
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+
+ if (!parent) {
+ return FALSE;
+ }
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ if (cur_node == a_node) {
+ found = TRUE;
+ child = m;
+ }
+ cur_node = get_next_element_node (node_iface,cur_node);
+ ++m;
+ }
+
+ if (!found)
+ return FALSE;
+
+ if (a == 0)
+ return ((m - b) == child);
+
+ return ((m - child - b)%a == 0 && (m - child - b)/a > -1);
+}
+
+static gboolean
+nth_last_of_type_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+ CRXMLNodePtr cur_node = NULL;
+ int m = 0;
+ int child = 0;
+ int found = FALSE;
+ CRArguments arg;
+ int a, b;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-last-of-type")) {
+ cr_utils_trace_info ("This handler is for :nth-last-of-type only");
+ return FALSE;
+ }
+
+ /*pseude code term should exist */
+ if (!a_sel->content.pseudo->term)
+ return FALSE;
+
+ arg = get_arguments_from_function (a_sel);
+
+ if (arg.a == 0 && arg.b == 0)
+ return FALSE;
+
+ a = arg.a;
+ b = arg.b;
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent) {
+ return FALSE;
+ }
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str))
+ ++m;
+ if (cur_node == a_node) {
+ found = TRUE;
+ child = m;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+
+ if (!found)
+ return FALSE;
+
+ if (a == 0)
+ return ((m - b) == child);
+
+ return ((m - child - b +1)%a == 0 && (m - child - b +1)/a > -1);
+
+}
+
+static gboolean
+pseudo_class_add_sel_matches_node (CRSelEng * a_this,
+ CRAdditionalSel * a_add_sel,
+ CRXMLNodePtr a_node)
+{
+ enum CRStatus status = CR_OK;
+ CRPseudoClassSelectorHandler handler = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_add_sel
+ && a_add_sel->content.pseudo
+ && a_add_sel->content.pseudo->name
+ && a_add_sel->content.pseudo->name->stryng
+ && a_add_sel->content.pseudo->name->stryng->str
+ && a_node, FALSE);
+
+ status = cr_sel_eng_get_pseudo_class_selector_handler
+ (a_this, (guchar *) a_add_sel->content.pseudo->name->stryng->str,
+ a_add_sel->content.pseudo->type, &handler);
+ if (status != CR_OK || !handler)
+ return FALSE;
+
+ return handler (a_this, a_add_sel, a_node);
+}
+
+/**
+ *@param a_add_sel the class additional selector to consider.
+ *@param a_node the xml node to consider.
+ *@return TRUE if the class additional selector matches
+ *the xml node given in argument, FALSE otherwise.
+ */
+static gboolean
+class_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ gboolean result = FALSE;
+ char *klass = NULL;
+
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == CLASS_ADD_SELECTOR
+ && a_add_sel->content.class_name
+ && a_add_sel->content.class_name->stryng
+ && a_add_sel->content.class_name->stryng->str
+ && a_node, FALSE);
+
+ klass = a_node_iface->getProp (a_node, "class");
+ if (klass) {
+ char const *cur;
+ for (cur = klass; cur && *cur; cur++) {
+ while (cur && *cur
+ && cr_utils_is_white_space (*cur)
+ == TRUE)
+ cur++;
+
+ if (!strncmp ((const char *) cur,
+ a_add_sel->content.class_name->stryng->str,
+ a_add_sel->content.class_name->stryng->len)) {
+ cur += a_add_sel->content.class_name->stryng->len;
+ if ((cur && !*cur)
+ || cr_utils_is_white_space (*cur) == TRUE)
+ result = TRUE;
+ } else { /* if it doesn't match, */
+ /* then skip to next whitespace character to try again */
+ while (cur && *cur && !(cr_utils_is_white_space(*cur) == TRUE))
+ cur++;
+ }
+ if (cur && !*cur)
+ break ;
+ }
+ a_node_iface->freePropVal (klass);
+ klass = NULL;
+ }
+ return result;
+
+}
+
+/**
+ *@return TRUE if the additional attribute selector matches
+ *the current xml node given in argument, FALSE otherwise.
+ *@param a_add_sel the additional attribute selector to consider.
+ *@param a_node the xml node to consider.
+ */
+static gboolean
+id_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ gboolean result = FALSE;
+ char *id = NULL;
+
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == ID_ADD_SELECTOR
+ && a_add_sel->content.id_name
+ && a_add_sel->content.id_name->stryng
+ && a_add_sel->content.id_name->stryng->str
+ && a_node, FALSE);
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == ID_ADD_SELECTOR
+ && a_node, FALSE);
+
+ id = a_node_iface->getProp (a_node, "id");
+ if (id) {
+ if (!strqcmp ((const char *) id, a_add_sel->content.id_name->stryng->str,
+ a_add_sel->content.id_name->stryng->len)) {
+ result = TRUE;
+ }
+ a_node_iface->freePropVal (id);
+ id = NULL;
+ }
+ return result;
+}
+
+/**
+ *Returns TRUE if the instance of #CRAdditional selector matches
+ *the node given in parameter, FALSE otherwise.
+ *@param a_add_sel the additional selector to evaluate.
+ *@param a_node the xml node against which the selector is to
+ *be evaluated
+ *return TRUE if the additional selector matches the current xml node
+ *FALSE otherwise.
+ */
+static gboolean
+attr_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ CRAttrSel *cur_sel = NULL;
+
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == ATTRIBUTE_ADD_SELECTOR
+ && a_node, FALSE);
+
+ for (cur_sel = a_add_sel->content.attr_sel;
+ cur_sel; cur_sel = cur_sel->next) {
+ char *value;
+
+ if (!cur_sel->name
+ || !cur_sel->name->stryng
+ || !cur_sel->name->stryng->str)
+ return FALSE;
+
+ value = a_node_iface->getProp (a_node, cur_sel->name->stryng->str);
+ if (!value)
+ goto free_and_return_false;
+
+ switch (cur_sel->match_way) {
+ case SET:
+ break;
+
+ case EQUALS:
+ if (!cur_sel->value
+ || !cur_sel->value->stryng
+ || !cur_sel->value->stryng->str) {
+ goto free_and_return_false;
+ }
+ if (strcmp
+ (value,
+ cur_sel->value->stryng->str)) {
+ goto free_and_return_false;
+ }
+ break;
+
+ case INCLUDES:
+ {
+ char const *ptr1 = NULL,
+ *ptr2 = NULL,
+ *cur = NULL;
+ gboolean found = FALSE;
+
+ /*
+ *here, make sure value is a space
+ *separated list of "words", where one
+ *value is exactly cur_sel->value->str
+ */
+ for (cur = value; *cur; cur++) {
+ /*
+ *set ptr1 to the first non white space
+ *char addr.
+ */
+ while (cr_utils_is_white_space (*cur)
+ && *cur)
+ cur++;
+ if (!*cur)
+ break;
+ ptr1 = cur;
+
+ /*
+ *set ptr2 to the end the word.
+ */
+ while (!cr_utils_is_white_space (*cur)
+ && *cur)
+ cur++;
+ cur--;
+ ptr2 = cur;
+
+ if (!strncmp
+ ((const char *) ptr1,
+ cur_sel->value->stryng->str,
+ ptr2 - ptr1 + 1)) {
+ found = TRUE;
+ break;
+ }
+ ptr1 = ptr2 = NULL;
+ }
+
+ if (!found) {
+ goto free_and_return_false;
+ }
+ }
+ break;
+
+ case DASHMATCH:
+ {
+ char const *ptr1 = NULL,
+ *ptr2 = NULL,
+ *cur = NULL;
+ gboolean found = FALSE;
+
+ /*
+ *here, make sure value is an hyphen
+ *separated list of "words", each of which
+ *starting with "cur_sel->value->str"
+ */
+ for (cur = value; *cur; cur++) {
+ if (*cur == '-')
+ cur++;
+ ptr1 = cur;
+
+ while (*cur != '-' && *cur)
+ cur++;
+ cur--;
+ ptr2 = cur;
+
+ if (g_strstr_len
+ ((const gchar *) ptr1, ptr2 - ptr1 + 1,
+ cur_sel->value->stryng->str)
+ == ptr1) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ goto free_and_return_false;
+ }
+ }
+ break;
+ default:
+ goto free_and_return_false;
+ }
+
+ a_node_iface->freePropVal (value);
+ continue;
+
+ free_and_return_false:
+ a_node_iface->freePropVal (value);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ *Evaluates if a given additional selector matches an xml node.
+ *@param a_add_sel the additional selector to consider.
+ *@param a_node the xml node to consider.
+ *@return TRUE is a_add_sel matches a_node, FALSE otherwise.
+ */
+static gboolean
+additional_selector_matches_node (CRSelEng * a_this,
+ CRAdditionalSel * a_add_sel,
+ CRXMLNodePtr a_node)
+{
+ CRAdditionalSel *cur_add_sel = NULL, *tail = NULL ;
+ gboolean evaluated = FALSE ;
+
+ for (tail = a_add_sel ;
+ tail && tail->next;
+ tail = tail->next) ;
+
+ g_return_val_if_fail (tail, FALSE) ;
+
+ for (cur_add_sel = tail ;
+ cur_add_sel ;
+ cur_add_sel = cur_add_sel->prev) {
+
+ evaluated = TRUE ;
+ if (cur_add_sel->type == NO_ADD_SELECTOR) {
+ return FALSE;
+ }
+
+ if (cur_add_sel->type == CLASS_ADD_SELECTOR
+ && cur_add_sel->content.class_name
+ && cur_add_sel->content.class_name->stryng
+ && cur_add_sel->content.class_name->stryng->str) {
+ if (!class_add_sel_matches_node (cur_add_sel,
+ PRIVATE(a_this)->node_iface,
+ a_node)) {
+ return FALSE;
+ }
+ continue ;
+ } else if (cur_add_sel->type == ID_ADD_SELECTOR
+ && cur_add_sel->content.id_name
+ && cur_add_sel->content.id_name->stryng
+ && cur_add_sel->content.id_name->stryng->str) {
+ if (!id_add_sel_matches_node (cur_add_sel,
+ PRIVATE(a_this)->node_iface,
+ a_node)) {
+ return FALSE;
+ }
+ continue ;
+ } else if (cur_add_sel->type == ATTRIBUTE_ADD_SELECTOR
+ && cur_add_sel->content.attr_sel) {
+ /*
+ *here, call a function that does the match
+ *against an attribute additional selector
+ *and an xml node.
+ */
+ if (!attr_add_sel_matches_node (cur_add_sel,
+ PRIVATE(a_this)->node_iface,
+ a_node)) {
+ return FALSE;
+ }
+ continue ;
+ } else if (cur_add_sel->type == PSEUDO_CLASS_ADD_SELECTOR
+ && cur_add_sel->content.pseudo) {
+ if (!pseudo_class_add_sel_matches_node
+ (a_this, cur_add_sel, a_node)) {
+ return FALSE;
+ }
+ continue ;
+ }
+ }
+ if (evaluated == TRUE)
+ return TRUE;
+ return FALSE ;
+}
+
+static CRXMLNodePtr
+get_next_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ CRXMLNodePtr cur_node = a_node;
+
+ g_return_val_if_fail (a_node, NULL);
+
+ do {
+ cur_node = a_node_iface->getNextSibling (cur_node);
+ } while (cur_node && !a_node_iface->isElementNode(cur_node));
+ return cur_node;
+}
+
+static CRXMLNodePtr
+get_first_child_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ CRXMLNodePtr cur_node = NULL;
+
+ g_return_val_if_fail (a_node, NULL);
+
+ cur_node = a_node_iface->getFirstChild (a_node);
+ if (!cur_node)
+ return cur_node;
+ if (a_node_iface->isElementNode (cur_node))
+ return cur_node;
+ return get_next_element_node (a_node_iface, cur_node);
+}
+
+static CRXMLNodePtr
+get_prev_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ CRXMLNodePtr cur_node = a_node;
+
+ g_return_val_if_fail (a_node, NULL);
+
+ do {
+ cur_node = a_node_iface->getPrevSibling (cur_node);
+ } while (cur_node && !a_node_iface->isElementNode(cur_node));
+ return cur_node;
+}
+
+static CRXMLNodePtr
+get_next_parent_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ CRXMLNodePtr cur_node = a_node;
+
+ g_return_val_if_fail (a_node, NULL);
+
+ do {
+ cur_node = a_node_iface->getParentNode (cur_node);
+ } while (cur_node && !a_node_iface->isElementNode (cur_node));
+ return cur_node;
+}
+
+static CRArguments
+get_arguments_from_function (CRAdditionalSel * a_sel)
+{
+ CRArguments arg;
+ arg.a = 0;
+ arg.b = 0;
+ switch (a_sel->content.pseudo->term->type) {
+ case TERM_NUMBER:
+ if (a_sel->content.pseudo->term->content.num) {
+ arg.b = a_sel->content.pseudo->term->content.num->val;
+ }
+ if (a_sel->content.pseudo->term->n) {
+ arg.a = arg.b;
+ arg.b = 0;
+ }
+ break;
+
+ case TERM_IDENT:
+ if (a_sel->content.pseudo->term->content.str) {
+ if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "even")) {
+ arg.a = 2;
+ arg.b = 0;
+ } else if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "odd")) {
+ arg.a = 2;
+ arg.b = 1;
+ } else if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "n")) {
+ /* 'n' without number */
+ arg.a = 1;
+ } else if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "-n")) {
+ /* '-n' without number */
+ arg.a = -1;
+ } else {
+ /* Unknown string */
+ arg.a = 0;
+ arg.b = 0;
+ return (arg);
+ }
+ }
+ break;
+
+ default:
+ cr_utils_trace_info ("Unknown term in nth style handler");
+ arg.a = 0;
+ arg.b = 0;
+ return (arg);
+ }
+
+ if (arg.a != 0 && a_sel->content.pseudo->term->next) {
+ /* check for b in 'an+b' */
+ if (a_sel->content.pseudo->term->next->type == TERM_NUMBER &&
+ a_sel->content.pseudo->term->next->content.num ) {
+ arg.b = a_sel->content.pseudo->term->next->content.num->val;
+ }
+ }
+
+ return (arg);
+}
+
+/**
+ *Evaluate a selector (a simple selectors list) and says
+ *if it matches the xml node given in parameter.
+ *The algorithm used here is the following:
+ *Walk the combinator separated list of simple selectors backward, starting
+ *from the end of the list. For each simple selector, looks if
+ *if matches the current node.
+ *
+ *@param a_this the selection engine.
+ *@param a_sel the simple selection list.
+ *@param a_node the xml node.
+ *@param a_result out parameter. Set to true if the
+ *selector matches the xml node, FALSE otherwise.
+ *@param a_recurse if set to TRUE, the function will walk to
+ *the next simple selector (after the evaluation of the current one)
+ *and recursively evaluate it. Must be usually set to TRUE unless you
+ *know what you are doing.
+ */
+static enum CRStatus
+sel_matches_node_real (CRSelEng * a_this, CRSimpleSel * a_sel,
+ CRXMLNodePtr a_node, gboolean * a_result,
+ gboolean a_eval_sel_list_from_end,
+ gboolean a_recurse)
+{
+ CRSimpleSel *cur_sel = NULL;
+ CRXMLNodePtr cur_node = NULL;
+ CRNodeIface const *node_iface = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_this && a_node
+ && a_result, CR_BAD_PARAM_ERROR);
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ *a_result = FALSE;
+
+ if (!node_iface->isElementNode(a_node))
+ return CR_OK;
+
+ if (a_eval_sel_list_from_end == TRUE) {
+ /*go and get the last simple selector of the list */
+ for (cur_sel = a_sel;
+ cur_sel && cur_sel->next; cur_sel = cur_sel->next) ;
+ } else {
+ cur_sel = a_sel;
+ }
+
+ for (cur_node = a_node; cur_sel; cur_sel = cur_sel->prev) {
+ if (((cur_sel->type_mask & TYPE_SELECTOR)
+ && (cur_sel->name
+ && cur_sel->name->stryng
+ && cur_sel->name->stryng->str)
+ && (!strcmp (cur_sel->name->stryng->str,
+ (const char *) node_iface->getLocalName(cur_node))))
+ || (cur_sel->type_mask & UNIVERSAL_SELECTOR)) {
+ /*
+ *this simple selector
+ *matches the current xml node
+ *Let's see if the preceding
+ *simple selectors also match
+ *their xml node counterpart.
+ */
+ if (cur_sel->add_sel) {
+ if (additional_selector_matches_node (a_this, cur_sel->add_sel,
+ cur_node) == TRUE) {
+ goto walk_a_step_in_expr;
+ } else {
+ goto done;
+ }
+ } else {
+ goto walk_a_step_in_expr;
+ }
+ }
+ if (!(cur_sel->type_mask & TYPE_SELECTOR)
+ && !(cur_sel->type_mask & UNIVERSAL_SELECTOR)) {
+ if (!cur_sel->add_sel) {
+ goto done;
+ }
+ if (additional_selector_matches_node
+ (a_this, cur_sel->add_sel, cur_node)
+ == TRUE) {
+ goto walk_a_step_in_expr;
+ } else {
+ goto done;
+ }
+ } else {
+ goto done ;
+ }
+
+ walk_a_step_in_expr:
+ if (a_recurse == FALSE) {
+ *a_result = TRUE;
+ goto done;
+ }
+
+ /*
+ *here, depending on the combinator of cur_sel
+ *choose the axis of the xml tree traversal
+ *and walk one step in the xml tree.
+ */
+ if (!cur_sel->prev)
+ break;
+
+ switch (cur_sel->combinator) {
+ case NO_COMBINATOR:
+ break;
+
+ case COMB_WS: /*descendant selector */
+ {
+ CRXMLNodePtr n = NULL;
+ enum CRStatus status = CR_OK;
+ gboolean matches = FALSE;
+
+ /*
+ *walk the xml tree upward looking for a parent
+ *node that matches the preceding selector.
+ */
+ for (n = node_iface->getParentNode (cur_node);
+ n;
+ n = node_iface->getParentNode (n)) {
+ status = sel_matches_node_real
+ (a_this, cur_sel->prev,
+ n, &matches, FALSE, TRUE);
+
+ if (status != CR_OK)
+ goto done;
+
+ if (matches == TRUE) {
+ cur_node = n ;
+ break;
+ }
+ }
+
+ if (!n) {
+ /*
+ *didn't find any ancestor that matches
+ *the previous simple selector.
+ */
+ goto done;
+ }
+ /*
+ *in this case, the preceding simple sel
+ *will have been interpreted twice, which
+ *is a cpu and mem waste ... I need to find
+ *another way to do this. Anyway, this is
+ *my first attempt to write this function and
+ *I am a bit clueless.
+ */
+ break;
+ }
+
+ case COMB_PLUS:
+ cur_node = get_prev_element_node (node_iface, cur_node);
+ if (!cur_node)
+ goto done;
+ break;
+
+ case COMB_TILDE: /* General sibling selector. */
+ {
+ CRXMLNodePtr n = NULL;
+ enum CRStatus status = CR_OK;
+ gboolean matches = FALSE;
+
+ /*
+ * Walk through previous sibing nodes looking for a
+ * node that matches the preceding selector.
+ */
+ for (n = get_prev_element_node (node_iface, cur_node);
+ n;
+ n = get_prev_element_node (node_iface, n)) {
+ status = sel_matches_node_real
+ (a_this, cur_sel->prev,
+ n, &matches, FALSE, TRUE);
+
+ if (status != CR_OK)
+ goto done;
+
+ if (matches == TRUE) {
+ cur_node = n ;
+ break;
+ }
+ }
+
+ if (!n) {
+ /*
+ * Didn't find any previous sibling that matches
+ * the previous simple selector.
+ */
+ goto done;
+ }
+ /*
+ * See note above in COMB_WS section.
+ */
+ break;
+ }
+
+ case COMB_GT:
+ cur_node = get_next_parent_element_node (node_iface, cur_node);
+ if (!cur_node)
+ goto done;
+ break;
+
+ default:
+ goto done;
+ }
+ continue;
+ }
+
+ /*
+ *if we reached this point, it means the selector matches
+ *the xml node.
+ */
+ *a_result = TRUE;
+
+ done:
+ return CR_OK;
+}
+
+
+/**
+ *Returns array of the ruleset statements that matches the
+ *given xml node.
+ *The engine keeps in memory the last statement he
+ *visited during the match. So, the next call
+ *to this function will eventually return a rulesets list starting
+ *from the last ruleset statement visited during the previous call.
+ *The enable users to get matching rulesets in an incremental way.
+ *Note that for each statement returned,
+ *the engine calculates the specificity of the selector
+ *that matched the xml node and stores it in the "specifity" field
+ *of the statement structure.
+ *
+ *@param a_sel_eng the current selection engine
+ *@param a_node the xml node for which the request
+ *is being made.
+ *@param a_sel_list the list of selectors to perform the search in.
+ *@param a_rulesets in/out parameter. A pointer to the
+ *returned array of rulesets statements that match the xml node
+ *given in parameter. The caller allocates the array before calling this
+ *function.
+ *@param a_len in/out parameter the length (in sizeof (#CRStatement*))
+ *of the returned array.
+ *(the length of a_rulesets, more precisely).
+ *The caller must set it to the length of a_ruleset prior to calling this
+ *function. In return, the function sets it to the length
+ *(in sizeof (#CRStatement)) of the actually returned CRStatement array.
+ *@return CR_OUTPUT_TOO_SHORT_ERROR if found more rulesets than the size
+ *of the a_rulesets array. In this case, the first *a_len rulesets found
+ *are put in a_rulesets, and a further call will return the following
+ *ruleset(s) following the same principle.
+ *@return CR_OK if all the rulesets found have been returned. In this
+ *case, *a_len is set to the actual number of ruleset found.
+ *@return CR_BAD_PARAM_ERROR in case any of the given parameter are
+ *bad (e.g null pointer).
+ *@return CR_ERROR if any other error occurred.
+ */
+static enum CRStatus
+cr_sel_eng_get_matched_rulesets_real (CRSelEng * a_this,
+ CRStyleSheet * a_stylesheet,
+ CRXMLNodePtr a_node,
+ CRStatement *** a_rulesets,
+ gulong * a_len,
+ gulong * a_capacity)
+{
+ CRStatement *cur_stmt = NULL;
+ CRSelector *sel_list = NULL,
+ *cur_sel = NULL;
+ gboolean matches = FALSE;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this
+ && a_stylesheet
+ && a_node && a_rulesets, CR_BAD_PARAM_ERROR);
+
+ if (!a_stylesheet->statements) {
+ return CR_OK;
+ }
+
+ /*
+ *if this stylesheet is "new one"
+ *let's remember it for subsequent calls.
+ */
+ if (PRIVATE (a_this)->sheet != a_stylesheet) {
+ PRIVATE (a_this)->sheet = a_stylesheet;
+ PRIVATE (a_this)->cur_stmt = a_stylesheet->statements;
+ }
+
+ /*
+ *walk through the list of statements and,
+ *get the selectors list inside the statements that
+ *contain some, and try to match our xml node in these
+ *selectors lists.
+ */
+ for (cur_stmt = PRIVATE (a_this)->cur_stmt;
+ (PRIVATE (a_this)->cur_stmt = cur_stmt);
+ cur_stmt = cur_stmt->next) {
+ /*
+ *initialize the selector list in which we will
+ *really perform the search.
+ */
+ sel_list = NULL;
+
+ /*
+ *get the damn selector list in
+ *which we have to look
+ */
+ switch (cur_stmt->type) {
+ case RULESET_STMT:
+ if (cur_stmt->kind.ruleset
+ && cur_stmt->kind.ruleset->sel_list) {
+ sel_list = cur_stmt->kind.ruleset->sel_list;
+ }
+ break;
+
+ case AT_MEDIA_RULE_STMT:
+ if (cur_stmt->kind.media_rule
+ && cur_stmt->kind.media_rule->rulesets
+ && cur_stmt->kind.media_rule->rulesets->
+ kind.ruleset
+ && cur_stmt->kind.media_rule->rulesets->
+ kind.ruleset->sel_list) {
+ sel_list =
+ cur_stmt->kind.media_rule->
+ rulesets->kind.ruleset->sel_list;
+ }
+ break;
+
+ case AT_IMPORT_RULE_STMT:
+ if (cur_stmt->kind.import_rule) {
+ g_assert(!cur_stmt->kind.import_rule->sheet ||
+ !cur_stmt->kind.import_rule->sheet->next);
+ cr_sel_eng_get_matched_rulesets_real (
+ a_this, cur_stmt->kind.import_rule->sheet,
+ a_node, a_rulesets,
+ a_len, a_capacity);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!sel_list)
+ continue;
+
+ /*
+ *now, we have a comma separated selector list to look in.
+ *let's walk it and try to match the xml_node
+ *on each item of the list.
+ */
+ for (cur_sel = sel_list; cur_sel; cur_sel = cur_sel->next) {
+ if (!cur_sel->simple_sel)
+ continue;
+
+ status = cr_sel_eng_matches_node
+ (a_this, cur_sel->simple_sel,
+ a_node, &matches);
+
+ if (status == CR_OK && matches == TRUE) {
+ /*
+ *bingo!!! we found one ruleset that
+ *matches that fucking node.
+ *lets put it in the out array.
+ */
+
+ if (*a_len >= *a_capacity) {
+ *a_capacity = (*a_len) + 8;
+ *a_rulesets = (CRStatement **) g_try_realloc (*a_rulesets,
+ (*a_capacity) * sizeof (CRStatement *));
+ if (!*a_rulesets) {
+ cr_utils_trace_info("Out of memory");
+ return CR_ERROR;
+ }
+ }
+
+ {
+ (*a_rulesets)[(*a_len)++] = cur_stmt;
+
+ /*
+ *For the cascade computing algorithm
+ *(which is gonna take place later)
+ *we must compute the specificity
+ *(css2 spec chap 6.4.1) of the selector
+ *that matched the current xml node
+ *and store it in the css2 statement
+ *(statement == ruleset here).
+ */
+ status = cr_simple_sel_compute_specificity (cur_sel->simple_sel);
+
+ g_return_val_if_fail (status == CR_OK,
+ CR_ERROR);
+ cur_stmt->specificity =
+ cur_sel->simple_sel->
+ specificity;
+ }
+ }
+ }
+ }
+
+ /*
+ *if we reached this point, it means
+ *we reached the end of stylesheet.
+ *no need to store any info about the stylesheet
+ *anymore.
+ */
+ g_return_val_if_fail (!PRIVATE (a_this)->cur_stmt, CR_ERROR);
+ PRIVATE (a_this)->sheet = NULL;
+ return CR_OK;
+}
+
+static enum CRStatus
+put_css_properties_in_props_list (CRPropList ** a_props, CRStatement * a_stmt)
+{
+ CRPropList *props = NULL,
+ *pair = NULL,
+ *tmp_props = NULL;
+ CRDeclaration *cur_decl = NULL;
+
+ g_return_val_if_fail (a_props && a_stmt
+ && a_stmt->type == RULESET_STMT
+ && a_stmt->kind.ruleset, CR_BAD_PARAM_ERROR);
+
+ props = *a_props;
+
+ for (cur_decl = a_stmt->kind.ruleset->decl_list;
+ cur_decl; cur_decl = cur_decl->next) {
+ CRDeclaration *decl;
+
+ decl = NULL;
+ pair = NULL;
+
+ if (!cur_decl->property
+ || !cur_decl->property->stryng
+ || !cur_decl->property->stryng->str)
+ continue;
+ /*
+ *First, test if the property is not
+ *already present in our properties list
+ *If yes, apply the cascading rules to
+ *compute the precedence. If not, insert
+ *the property into the list
+ */
+ cr_prop_list_lookup_prop (props,
+ cur_decl->property,
+ &pair);
+
+ if (!pair) {
+ tmp_props = cr_prop_list_append2
+ (props, cur_decl->property, cur_decl);
+ if (tmp_props) {
+ props = tmp_props;
+ tmp_props = NULL;
+ }
+ continue;
+ }
+
+ /*
+ *A property with the same name already exists.
+ *We must apply here
+ *some cascading rules
+ *to compute the precedence.
+ */
+ cr_prop_list_get_decl (pair, &decl);
+ g_return_val_if_fail (decl, CR_ERROR);
+
+ /*
+ *first, look at the origin.
+ *6.4.1 says:
+ *"for normal declarations,
+ *author style sheets override user
+ *style sheets which override
+ *the default style sheet."
+ */
+ if (decl->parent_statement
+ && decl->parent_statement->parent_sheet
+ && (decl->parent_statement->parent_sheet->origin
+ < a_stmt->parent_sheet->origin)) {
+ /*
+ *if the already selected declaration
+ *is marked as being !important the current
+ *declaration must not override it
+ *(unless the already selected declaration
+ *has an UA origin)
+ */
+ if (decl->important == TRUE && cur_decl->important != TRUE
+ && decl->parent_statement->parent_sheet->origin
+ != ORIGIN_UA) {
+ continue;
+ }
+ tmp_props = cr_prop_list_unlink (props, pair);
+ if (props) {
+ cr_prop_list_destroy (pair);
+ }
+ props = tmp_props;
+ tmp_props = NULL;
+ props = cr_prop_list_append2
+ (props, cur_decl->property, cur_decl);
+
+ continue;
+ } else if (decl->parent_statement
+ && decl->parent_statement->parent_sheet
+ && (decl->parent_statement->
+ parent_sheet->origin
+ > a_stmt->parent_sheet->origin)) {
+ cr_utils_trace_info
+ ("We should not reach this line\n");
+ continue;
+ }
+
+ /*
+ *A property with the same
+ *name and the same origin already exists.
+ *shit. This is lasting longer than expected ...
+ *Luckily, the spec says in 6.4.1:
+ *"more specific selectors will override
+ *more general ones"
+ *and
+ *"if two rules have the same weight,
+ *origin and specificity,
+ *the later specified wins"
+ */
+ if (a_stmt->specificity
+ >= decl->parent_statement->specificity) {
+ if (decl->important == TRUE && cur_decl->important != TRUE)
+ continue;
+ props = cr_prop_list_unlink (props, pair);
+ if (pair) {
+ cr_prop_list_destroy (pair);
+ pair = NULL;
+ }
+ props = cr_prop_list_append2 (props,
+ cur_decl->property,
+ cur_decl);
+ }
+ }
+ /*TODO: this may leak. Check this out */
+ *a_props = props;
+
+ return CR_OK;
+}
+
+static void
+set_style_from_props (CRStyle * a_style, CRPropList * a_props)
+{
+ CRPropList *cur = NULL;
+ CRDeclaration *decl = NULL;
+
+ for (cur = a_props; cur; cur = cr_prop_list_get_next (cur)) {
+ cr_prop_list_get_decl (cur, &decl);
+ cr_style_set_style_from_decl (a_style, decl);
+ decl = NULL;
+ }
+}
+
+/****************************************
+ *PUBLIC METHODS
+ ****************************************/
+
+/**
+ * cr_sel_eng_new:
+ *Creates a new instance of #CRSelEng.
+ *
+ *@a_node_iface: Node interface
+ *
+ *Returns the newly built instance of #CRSelEng of
+ *NULL if an error occurs.
+ */
+CRSelEng *
+cr_sel_eng_new (CRNodeIface const * a_node_iface)
+{
+ CRSelEng *result = NULL;
+
+ result = (CRSelEng *) g_try_malloc (sizeof (CRSelEng));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRSelEng));
+
+ PRIVATE (result) = (CRSelEngPriv *) g_try_malloc (sizeof (CRSelEngPriv));
+ if (!PRIVATE (result)) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (PRIVATE (result), 0, sizeof (CRSelEngPriv));
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "root",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ root_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "empty",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ empty_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "lang",
+ FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ lang_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "only-child",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ only_child_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "only-of-type",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ only_of_type_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "first-child",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ first_child_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "first-of-type",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ first_of_type_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "last-child",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ last_child_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "last-of-type",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ last_of_type_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "nth-child",
+ FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ nth_child_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "nth-of-type",
+ FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ nth_of_type_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "nth-last-child",
+ FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ nth_last_child_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "nth-last-of-type",
+ FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ nth_last_of_type_pseudo_class_handler);
+
+ cr_sel_eng_set_node_iface (result, a_node_iface);
+
+ return result;
+}
+
+/**
+ * cr_sel_eng_register_pseudo_class_sel_handler:
+ *@a_this: the current instance of #CRSelEng
+ *@a_pseudo_class_sel_name: the name of the pseudo class selector.
+ *@a_pseudo_class_type: the type of the pseudo class selector.
+ *@a_handler: the actual handler or callback to be called during
+ *the selector evaluation process.
+ *
+ *Adds a new handler entry in the handlers entry table.
+ *
+ *Returns CR_OK, upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_sel_eng_register_pseudo_class_sel_handler (CRSelEng * a_this,
+ guchar * a_name,
+ enum CRPseudoType a_type,
+ CRPseudoClassSelectorHandler
+ a_handler)
+{
+ struct CRPseudoClassSelHandlerEntry *handler_entry = NULL;
+ GList *list = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_handler && a_name, CR_BAD_PARAM_ERROR);
+
+ handler_entry = (struct CRPseudoClassSelHandlerEntry *) g_try_malloc
+ (sizeof (struct CRPseudoClassSelHandlerEntry));
+ if (!handler_entry) {
+ return CR_OUT_OF_MEMORY_ERROR;
+ }
+ memset (handler_entry, 0,
+ sizeof (struct CRPseudoClassSelHandlerEntry));
+ handler_entry->name = (guchar *) g_strdup ((const gchar *) a_name);
+ handler_entry->type = a_type;
+ handler_entry->handler = a_handler;
+ list = g_list_append (PRIVATE (a_this)->pcs_handlers, handler_entry);
+ if (!list) {
+ return CR_OUT_OF_MEMORY_ERROR;
+ }
+ PRIVATE (a_this)->pcs_handlers = list;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_sel_eng_unregister_pseudo_class_sel_handler (CRSelEng * a_this,
+ guchar * a_name,
+ enum CRPseudoType a_type)
+{
+ GList *elem = NULL,
+ *deleted_elem = NULL;
+ gboolean found = FALSE;
+ struct CRPseudoClassSelHandlerEntry *entry = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ for (elem = PRIVATE (a_this)->pcs_handlers;
+ elem; elem = g_list_next (elem)) {
+ entry = (struct CRPseudoClassSelHandlerEntry *) elem->data;
+ if (!strcmp ((const char *) entry->name, (const char *) a_name)
+ && entry->type == a_type) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found == FALSE)
+ return CR_PSEUDO_CLASS_SEL_HANDLER_NOT_FOUND_ERROR;
+ PRIVATE (a_this)->pcs_handlers = g_list_delete_link
+ (PRIVATE (a_this)->pcs_handlers, elem);
+ entry = (struct CRPseudoClassSelHandlerEntry *) elem->data;
+ if (entry->name) {
+ g_free (entry->name);
+ entry->name = NULL;
+ }
+ g_free (elem);
+ g_list_free (deleted_elem);
+
+ return CR_OK;
+}
+
+/**
+ * cr_sel_eng_unregister_all_pseudo_class_sel_handlers:
+ *@a_this: the current instance of #CRSelEng .
+ *
+ *Unregisters all the pseudo class sel handlers
+ *and frees all the associated allocated datastructures.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_sel_eng_unregister_all_pseudo_class_sel_handlers (CRSelEng * a_this)
+{
+ GList *elem = NULL;
+ struct CRPseudoClassSelHandlerEntry *entry = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if (!PRIVATE (a_this)->pcs_handlers)
+ return CR_OK;
+ for (elem = PRIVATE (a_this)->pcs_handlers;
+ elem; elem = g_list_next (elem)) {
+ entry = (struct CRPseudoClassSelHandlerEntry *) elem->data;
+ if (!entry)
+ continue;
+ if (entry->name) {
+ g_free (entry->name);
+ entry->name = NULL;
+ }
+ g_free (entry);
+ elem->data = NULL;
+ }
+ g_list_free (PRIVATE (a_this)->pcs_handlers);
+ PRIVATE (a_this)->pcs_handlers = NULL;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_sel_eng_get_pseudo_class_selector_handler (CRSelEng * a_this,
+ guchar * a_name,
+ enum CRPseudoType a_type,
+ CRPseudoClassSelectorHandler *
+ a_handler)
+{
+ GList *elem = NULL;
+ struct CRPseudoClassSelHandlerEntry *entry = NULL;
+ gboolean found = FALSE;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_name, CR_BAD_PARAM_ERROR);
+
+ for (elem = PRIVATE (a_this)->pcs_handlers;
+ elem; elem = g_list_next (elem)) {
+ entry = (struct CRPseudoClassSelHandlerEntry *) elem->data;
+ if (!strcmp ((const char *) a_name, (const char *) entry->name)
+ && entry->type == a_type) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found == FALSE)
+ return CR_PSEUDO_CLASS_SEL_HANDLER_NOT_FOUND_ERROR;
+ *a_handler = entry->handler;
+ return CR_OK;
+}
+
+/**
+ * cr_sel_eng_matches_node:
+ *@a_this: the selection engine.
+ *@a_sel: the simple selector against which the xml node
+ *is going to be matched.
+ *@a_node: the node against which the selector is going to be matched.
+ *@a_result: out parameter. The result of the match. Is set to
+ *TRUE if the selector matches the node, FALSE otherwise. This value
+ *is considered if and only if this functions returns CR_OK.
+ *
+ *Evaluates a chained list of simple selectors (known as a css2 selector).
+ *Says whether if this selector matches the xml node given in parameter or
+ *not.
+ *
+ *Returns the CR_OK if the selection ran correctly, an error code otherwise.
+ */
+enum CRStatus
+cr_sel_eng_matches_node (CRSelEng * a_this, CRSimpleSel * a_sel,
+ CRXMLNodePtr a_node, gboolean * a_result)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_this && a_node
+ && a_result, CR_BAD_PARAM_ERROR);
+
+ if (!PRIVATE(a_this)->node_iface->isElementNode (a_node)) {
+ *a_result = FALSE;
+ return CR_OK;
+ }
+
+ return sel_matches_node_real (a_this, a_sel,
+ a_node, a_result,
+ TRUE, TRUE);
+}
+
+/**
+ * cr_sel_eng_get_matched_rulesets:
+ *@a_this: the current instance of the selection engine.
+ *@a_sheet: the stylesheet that holds the selectors.
+ *@a_node: the xml node to consider during the walk through
+ *the stylesheet.
+ *@a_rulesets: out parameter. A pointer to an array of
+ *rulesets statement pointers. *a_rulesets is allocated by
+ *this function and must be freed by the caller. However, the caller
+ *must not alter the rulesets statements pointer because they
+ *point to statements that are still in the css stylesheet.
+ *@a_len: the length of *a_ruleset.
+ *
+ *Returns an array of pointers to selectors that matches
+ *the xml node given in parameter.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_sel_eng_get_matched_rulesets (CRSelEng * a_this,
+ CRStyleSheet * a_sheet,
+ CRXMLNodePtr a_node,
+ CRStatement *** a_rulesets, gulong * a_len)
+{
+ CRStatement **stmts_tab = NULL;
+ enum CRStatus status = CR_OK;
+ gulong capacity = 0;
+
+ g_return_val_if_fail (a_this
+ && a_sheet
+ && a_node
+ && a_rulesets && *a_rulesets == NULL
+ && a_len, CR_BAD_PARAM_ERROR);
+
+ *a_len = 0;
+
+ status = cr_sel_eng_get_matched_rulesets_real
+ (a_this, a_sheet, a_node, &stmts_tab, a_len, &capacity);
+ if (status == CR_ERROR)
+ goto error;
+
+ *a_rulesets = stmts_tab;
+
+ return CR_OK;
+
+ error:
+
+ if (stmts_tab) {
+ g_free (stmts_tab);
+ stmts_tab = NULL;
+
+ }
+
+ *a_len = 0;
+ return status;
+}
+
+/**
+ * Like cr_sel_eng_get_matched_rulesets_real, but process an entire (linked)
+ * list of stylesheets, not only a single one.
+ */
+static
+enum CRStatus
+cr_sel_eng_process_stylesheet ( CRSelEng * a_eng,
+ CRXMLNodePtr a_node,
+ CRStyleSheet * a_stylesheet,
+ CRStatement *** stmts_tab,
+ gulong * tab_size,
+ gulong * tab_len,
+ gulong * index)
+{
+ enum CRStatus status = CR_OK;
+ CRStyleSheet *cur = NULL;
+
+ for (cur = a_stylesheet; cur && status == CR_OK; cur = cur->next) {
+ status = cr_sel_eng_get_matched_rulesets_real
+ (a_eng, cur, a_node, stmts_tab, index, tab_size);
+ }
+
+ return status;
+}
+
+enum CRStatus
+cr_sel_eng_get_matched_properties_from_cascade (CRSelEng * a_this,
+ CRCascade * a_cascade,
+ CRXMLNodePtr a_node,
+ CRPropList ** a_props)
+{
+ CRStatement **stmts_tab = NULL;
+ enum CRStatus status = CR_OK;
+ gulong tab_size = 0,
+ tab_len = 0,
+ i = 0,
+ index = 0;
+ enum CRStyleOrigin origin;
+ CRStyleSheet *sheet = NULL;
+
+ g_return_val_if_fail (a_this
+ && a_cascade
+ && a_node && a_props, CR_BAD_PARAM_ERROR);
+
+ for (origin = ORIGIN_UA; origin < NB_ORIGINS; origin = (enum CRStyleOrigin) (origin + 1)) {
+ sheet = cr_cascade_get_sheet (a_cascade, origin);
+ if (!sheet)
+ continue;
+
+ status = cr_sel_eng_process_stylesheet (a_this, a_node, sheet, &stmts_tab, &tab_size, &tab_len, &index);
+ if (status != CR_OK) {
+ cr_utils_trace_info ("Error while running "
+ "selector engine");
+ return status;
+ }
+ }
+
+ /*
+ *TODO, walk down the stmts_tab and build the
+ *property_name/declaration hashtable.
+ *Make sure one can walk from the declaration to
+ *the stylesheet.
+ */
+ for (i = 0; i < index; i++) {
+ CRStatement *stmt = stmts_tab[i];
+ if (!stmt)
+ continue;
+ switch (stmt->type) {
+ case RULESET_STMT:
+ if (!stmt->parent_sheet)
+ continue;
+ status = put_css_properties_in_props_list
+ (a_props, stmt);
+ break;
+ default:
+ break;
+ }
+
+ }
+ status = CR_OK ;
+ if (stmts_tab) {
+ g_free (stmts_tab);
+ stmts_tab = NULL;
+ }
+
+ return status;
+}
+
+enum CRStatus
+cr_sel_eng_get_matched_style (CRSelEng * a_this,
+ CRCascade * a_cascade,
+ CRXMLNodePtr a_node,
+ CRStyle * a_parent_style,
+ CRStyle ** a_style,
+ gboolean a_set_props_to_initial_values)
+{
+ enum CRStatus status = CR_OK;
+
+ CRPropList *props = NULL;
+
+ g_return_val_if_fail (a_this && a_cascade
+ && a_node && a_style, CR_BAD_PARAM_ERROR);
+
+ status = cr_sel_eng_get_matched_properties_from_cascade
+ (a_this, a_cascade, a_node, &props);
+
+ g_return_val_if_fail (status == CR_OK, status);
+ if (props) {
+ if (!*a_style) {
+ *a_style = cr_style_new (a_set_props_to_initial_values) ;
+ g_return_val_if_fail (*a_style, CR_ERROR);
+ } else {
+ if (a_set_props_to_initial_values == TRUE) {
+ cr_style_set_props_to_initial_values (*a_style) ;
+ } else {
+ cr_style_set_props_to_default_values (*a_style);
+ }
+ }
+ (*a_style)->parent_style = a_parent_style;
+
+ set_style_from_props (*a_style, props);
+ if (props) {
+ cr_prop_list_destroy (props);
+ props = NULL;
+ }
+ }
+ return CR_OK;
+}
+
+/**
+ * cr_sel_eng_destroy:
+ *@a_this: the current instance of the selection engine.
+ *
+ *The destructor of #CRSelEng
+ */
+void
+cr_sel_eng_destroy (CRSelEng * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (!PRIVATE (a_this))
+ goto end ;
+ if (PRIVATE (a_this)->pcs_handlers) {
+ cr_sel_eng_unregister_all_pseudo_class_sel_handlers
+ (a_this) ;
+ PRIVATE (a_this)->pcs_handlers = NULL ;
+ }
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ end:
+ if (a_this) {
+ g_free (a_this);
+ }
+}
diff --git a/src/3rdparty/libcroco/src/cr-sel-eng.h b/src/3rdparty/libcroco/src/cr-sel-eng.h
new file mode 100644
index 0000000..c666f48
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-sel-eng.h
@@ -0,0 +1,118 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#ifndef __CR_SEL_ENG_H__
+#define __CR_SEL_ENG_H__
+
+#include "cr-utils.h"
+#include "cr-stylesheet.h"
+#include "cr-cascade.h"
+#include "cr-style.h"
+#include "cr-prop-list.h"
+#include "cr-node-iface.h"
+
+/**
+ *@file:
+ *The declaration of the #CRSelEng class.
+ *The #CRSelEng is actually the "Selection Engine"
+ *class.
+ */
+
+G_BEGIN_DECLS
+
+typedef struct _CRSelEng CRSelEng ;
+typedef struct _CRSelEngPriv CRSelEngPriv ;
+typedef struct _CRArguments CRArguments ;
+
+//stores arguments of function of type an+b
+struct _CRArguments
+{
+ int a;
+ int b;
+} ;
+
+/**
+ *The Selection engine class.
+ *The main service provided by this class, is
+ *the ability to interpret a libcroco implementation
+ *of css2 selectors, and given an xml node, say if
+ *the selector matches the node or not.
+ */
+struct _CRSelEng
+{
+ CRSelEngPriv *priv ;
+} ;
+
+void cr_sel_eng_set_node_iface(CRSelEng *a_this, CRNodeIface const *);
+
+typedef gboolean (*CRPseudoClassSelectorHandler) (CRSelEng* a_this,
+ CRAdditionalSel *a_add_sel,
+ CRXMLNodePtr a_node) ;
+CRSelEng * cr_sel_eng_new (CRNodeIface const *);
+
+enum CRStatus cr_sel_eng_register_pseudo_class_sel_handler (CRSelEng *a_this,
+ guchar *a_pseudo_class_sel_name,
+ enum CRPseudoType a_pseudo_class_type,
+ CRPseudoClassSelectorHandler a_handler) ;
+
+enum CRStatus cr_sel_eng_unregister_pseudo_class_sel_handler (CRSelEng *a_this,
+ guchar *a_pseudo_class_sel_name,
+ enum CRPseudoType a_pseudo_class_type) ;
+
+enum CRStatus cr_sel_eng_unregister_all_pseudo_class_sel_handlers (CRSelEng *a_this) ;
+
+enum CRStatus cr_sel_eng_get_pseudo_class_selector_handler (CRSelEng *a_this,
+ guchar *a_pseudo_class_sel_name,
+ enum CRPseudoType a_pseudo_class_type,
+ CRPseudoClassSelectorHandler *a_handler) ;
+
+enum CRStatus cr_sel_eng_matches_node (CRSelEng *a_this,
+ CRSimpleSel *a_sel,
+ CRXMLNodePtr a_node,
+ gboolean *a_result) ;
+
+enum CRStatus cr_sel_eng_get_matched_rulesets (CRSelEng *a_this,
+ CRStyleSheet *a_sheet,
+ CRXMLNodePtr a_node,
+ CRStatement ***a_rulesets,
+ gulong *a_len) ;
+
+enum CRStatus
+cr_sel_eng_get_matched_properties_from_cascade (CRSelEng *a_this,
+ CRCascade *a_cascade,
+ CRXMLNodePtr a_node,
+ CRPropList **a_props) ;
+
+enum CRStatus cr_sel_eng_get_matched_style (CRSelEng *a_this,
+ CRCascade *a_cascade,
+ CRXMLNodePtr a_node,
+ CRStyle *a_parent_style,
+ CRStyle **a_style,
+ gboolean a_set_props_to_initial_values) ;
+
+void cr_sel_eng_destroy (CRSelEng *a_this) ;
+
+G_END_DECLS
+
+
+#endif/*__CR_SEL_ENG_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-selector.c b/src/3rdparty/libcroco/src/cr-selector.c
new file mode 100644
index 0000000..496b02c
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-selector.c
@@ -0,0 +1,333 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-selector.h"
+#include "cr-parser.h"
+
+/**
+ * cr_selector_new:
+ *
+ *@a_simple_sel: the initial simple selector list
+ *of the current instance of #CRSelector.
+ *
+ *Creates a new instance of #CRSelector.
+ *
+ *Returns the newly built instance of #CRSelector, or
+ *NULL in case of failure.
+ */
+CRSelector *
+cr_selector_new (CRSimpleSel * a_simple_sel)
+{
+ CRSelector *result = NULL;
+
+ result = (CRSelector *) g_try_malloc (sizeof (CRSelector));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRSelector));
+ result->simple_sel = a_simple_sel;
+ return result;
+}
+
+/**
+ * cr_selector_parse_from_buf:
+ *
+ *@a_char_buf: the buffer to parse.
+ *@a_enc: the encoding of the input buffer a_char_buf.
+ *
+ *Parses a buf for selectors.
+ *
+ *Fix Me: parsing will fail for some cases if buf does not end with '{'.
+ *
+ *Returns the newly built instance of #CRSelector, or
+ *NULL in case of failure.
+ */
+CRSelector *
+cr_selector_parse_from_buf (const guchar * a_char_buf, enum CREncoding a_enc)
+{
+ CRParser *parser = NULL;
+ CRSelector *selector = NULL;
+ enum CRStatus status;
+
+ g_return_val_if_fail (a_char_buf, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_char_buf, strlen ((const char *) a_char_buf),
+ a_enc, FALSE);
+ g_return_val_if_fail (parser, NULL);
+
+ status = cr_parser_parse_selector (parser, &selector);
+
+ if (status != CR_OK) {
+ if (selector) {
+ cr_selector_unref (selector);
+ selector = NULL;
+ }
+ }
+
+ cr_parser_destroy(parser);
+
+ return selector;
+}
+
+/**
+ * cr_selector_append:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *@a_new: the instance of #CRSelector to be appended.
+ *
+ *Appends a new instance of #CRSelector to the current selector list.
+ *
+ *Returns the new list.
+ */
+CRSelector *
+cr_selector_append (CRSelector * a_this, CRSelector * a_new)
+{
+ CRSelector *cur = NULL;
+
+ if (!a_this) {
+ return a_new;
+ }
+
+ /*walk forward the list headed by a_this to get the list tail */
+ for (cur = a_this; cur && cur->next; cur = cur->next) ;
+
+ cur->next = a_new;
+ a_new->prev = cur;
+
+ return a_this;
+}
+
+/**
+ * cr_selector_prepend:
+ *
+ *@a_this: the current instance of #CRSelector list.
+ *@a_new: the instance of #CRSelector.
+ *
+ *Prepends an element to the #CRSelector list.
+ *
+ *Returns the new list.
+ */
+CRSelector *
+cr_selector_prepend (CRSelector * a_this, CRSelector * a_new)
+{
+ CRSelector *cur = NULL;
+
+ a_new->next = a_this;
+ a_this->prev = a_new;
+
+ for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
+
+ return cur;
+}
+
+/**
+ * cr_selector_append_simple_sel:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *@a_simple_sel: the simple selector to append.
+ *
+ *append a simple selector to the current #CRSelector list.
+ *
+ *Returns the new list or NULL in case of failure.
+ */
+CRSelector *
+cr_selector_append_simple_sel (CRSelector * a_this,
+ CRSimpleSel * a_simple_sel)
+{
+ CRSelector *selector = NULL;
+
+ selector = cr_selector_new (a_simple_sel);
+ g_return_val_if_fail (selector, NULL);
+
+ return cr_selector_append (a_this, selector);
+}
+
+guchar *
+cr_selector_to_string (CRSelector const * a_this)
+{
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+
+ str_buf = (GString *) g_string_new (NULL);
+ g_return_val_if_fail (str_buf, NULL);
+
+ if (a_this) {
+ CRSelector const *cur = NULL;
+
+ for (cur = a_this; cur; cur = cur->next) {
+ if (cur->simple_sel) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_simple_sel_to_string
+ (cur->simple_sel);
+
+ if (tmp_str) {
+ if (cur->prev)
+ g_string_append (str_buf,
+ ", ");
+
+ g_string_append (str_buf, (const gchar *) tmp_str);
+
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_selector_dump:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *@a_fp: the destination file.
+ *
+ *Serializes the current instance of #CRSelector to a file.
+ */
+void
+cr_selector_dump (CRSelector const * a_this, FILE * a_fp)
+{
+ guchar *tmp_buf = NULL;
+
+ if (a_this) {
+ tmp_buf = cr_selector_to_string (a_this);
+ if (tmp_buf) {
+ fprintf (a_fp, "%s", tmp_buf);
+ g_free (tmp_buf);
+ tmp_buf = NULL;
+ }
+ }
+}
+
+/**
+ * cr_selector_ref:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *
+ *Increments the ref count of the current instance
+ *of #CRSelector.
+ */
+void
+cr_selector_ref (CRSelector * a_this)
+{
+ g_return_if_fail (a_this);
+
+ a_this->ref_count++;
+}
+
+/**
+ * cr_selector_unref:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *
+ *Decrements the ref count of the current instance of
+ *#CRSelector.
+ *If the ref count reaches zero, the current instance of
+ *#CRSelector is destroyed.
+ *
+ *Returns TRUE if this function destroyed the current instance
+ *of #CRSelector, FALSE otherwise.
+ */
+gboolean
+cr_selector_unref (CRSelector * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->ref_count) {
+ a_this->ref_count--;
+ }
+
+ if (a_this->ref_count == 0) {
+ cr_selector_destroy (a_this);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * cr_selector_destroy:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *
+ *Destroys the selector list.
+ */
+void
+cr_selector_destroy (CRSelector * a_this)
+{
+ CRSelector *cur = NULL;
+
+ g_return_if_fail (a_this);
+
+ /*
+ *go and get the list tail. In the same time, free
+ *all the simple selectors contained in the list.
+ */
+ for (cur = a_this; cur && cur->next; cur = cur->next) {
+ if (cur->simple_sel) {
+ cr_simple_sel_destroy (cur->simple_sel);
+ cur->simple_sel = NULL;
+ }
+ }
+
+ if (cur) {
+ if (cur->simple_sel) {
+ cr_simple_sel_destroy (cur->simple_sel);
+ cur->simple_sel = NULL;
+ }
+ }
+
+ /*in case the list has only one element */
+ if (cur && !cur->prev) {
+ g_free (cur);
+ return;
+ }
+
+ /*walk backward the list and free each "next element" */
+ for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
+ if (cur->next) {
+ g_free (cur->next);
+ cur->next = NULL;
+ }
+ }
+
+ if (!cur)
+ return;
+
+ if (cur->next) {
+ g_free (cur->next);
+ cur->next = NULL;
+ }
+
+ g_free (cur);
+}
diff --git a/src/3rdparty/libcroco/src/cr-selector.h b/src/3rdparty/libcroco/src/cr-selector.h
new file mode 100644
index 0000000..a7e0295
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-selector.h
@@ -0,0 +1,95 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_SELECTOR_H__
+#define __CR_SELECTOR_H__
+
+#include <stdio.h>
+#include "cr-utils.h"
+#include "cr-simple-sel.h"
+#include "cr-parsing-location.h"
+
+/**
+ *@file
+ *The declaration file of the #CRSelector file.
+ */
+
+G_BEGIN_DECLS
+
+typedef struct _CRSelector CRSelector ;
+
+/**
+ *Abstracts a CSS2 selector as defined in the right part
+ *of the 'ruleset' production in the appendix D.1 of the
+ *css2 spec.
+ *It is actually the abstraction of a comma separated list
+ *of simple selectors list.
+ *In a css2 file, a selector is a list of simple selectors
+ *separated by a comma.
+ *e.g: sel0, sel1, sel2 ...
+ *Each seln is a simple selector
+ */
+struct _CRSelector
+{
+ /**
+ *A Selection expression.
+ *It is a list of basic selectors.
+ *Each basic selector can be either an element
+ *selector, an id selector, a class selector, an
+ *attribute selector, an universal selector etc ...
+ */
+ CRSimpleSel *simple_sel ;
+
+ /**The next selector list element*/
+ CRSelector *next ;
+ CRSelector *prev ;
+ CRParsingLocation location ;
+ glong ref_count ;
+};
+
+CRSelector* cr_selector_new (CRSimpleSel *a_sel_expr) ;
+
+CRSelector * cr_selector_parse_from_buf (const guchar * a_char_buf,
+ enum CREncoding a_enc) ;
+
+CRSelector* cr_selector_append (CRSelector *a_this, CRSelector *a_new) ;
+
+CRSelector* cr_selector_append_simple_sel (CRSelector *a_this,
+ CRSimpleSel *a_simple_sel) ;
+
+CRSelector* cr_selector_prepend (CRSelector *a_this, CRSelector *a_new) ;
+
+guchar * cr_selector_to_string (CRSelector const *a_this) ;
+
+void cr_selector_dump (CRSelector const *a_this, FILE *a_fp) ;
+
+void cr_selector_ref (CRSelector *a_this) ;
+
+gboolean cr_selector_unref (CRSelector *a_this) ;
+
+void cr_selector_destroy (CRSelector *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_SELECTOR_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-simple-sel.c b/src/3rdparty/libcroco/src/cr-simple-sel.c
new file mode 100644
index 0000000..095c159
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-simple-sel.c
@@ -0,0 +1,322 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include <glib.h>
+#include "cr-simple-sel.h"
+
+/**
+ * cr_simple_sel_new:
+ *
+ *The constructor of #CRSimpleSel.
+ *
+ *Returns the new instance of #CRSimpleSel.
+ */
+CRSimpleSel *
+cr_simple_sel_new (void)
+{
+ CRSimpleSel *result = NULL;
+
+ result = (CRSimpleSel *) g_try_malloc (sizeof (CRSimpleSel));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRSimpleSel));
+
+ return result;
+}
+
+/**
+ * cr_simple_sel_append_simple_sel:
+ *
+ *Appends a simpe selector to the current list of simple selector.
+ *
+ *@a_this: the this pointer of the current instance of #CRSimpleSel.
+ *@a_sel: the simple selector to append.
+ *
+ *Returns: the new list upon successful completion, an error code otherwise.
+ */
+CRSimpleSel *
+cr_simple_sel_append_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
+{
+ CRSimpleSel *cur = NULL;
+
+ g_return_val_if_fail (a_sel, NULL);
+
+ if (a_this == NULL)
+ return a_sel;
+
+ for (cur = a_this; cur->next; cur = cur->next) ;
+
+ cur->next = a_sel;
+ a_sel->prev = cur;
+
+ return a_this;
+}
+
+/**
+ * cr_simple_sel_prepend_simple_sel:
+ *
+ *@a_this: the this pointer of the current instance of #CRSimpleSel.
+ *@a_sel: the simple selector to prepend.
+ *
+ *Prepends a simple selector to the current list of simple selectors.
+ *
+ *Returns the new list upon successful completion, an error code otherwise.
+ */
+CRSimpleSel *
+cr_simple_sel_prepend_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
+{
+ g_return_val_if_fail (a_sel, NULL);
+
+ if (a_this == NULL)
+ return a_sel;
+
+ a_sel->next = a_this;
+ a_this->prev = a_sel;
+
+ return a_sel;
+}
+
+guchar *
+cr_simple_sel_to_string (CRSimpleSel const * a_this)
+{
+ GString *str_buf = NULL;
+ guchar *result = NULL;
+
+ CRSimpleSel const *cur = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+ for (cur = a_this; cur; cur = cur->next) {
+ if (cur->name) {
+ gchar const *str = cur->name->stryng->str;
+
+ if (str) {
+ switch (cur->combinator) {
+ case COMB_WS:
+ g_string_append (str_buf, " ");
+ break;
+
+ case COMB_PLUS:
+ g_string_append (str_buf, "+");
+ break;
+
+ case COMB_TILDE:
+ g_string_append (str_buf, "~");
+ break;
+
+ case COMB_GT:
+ g_string_append (str_buf, ">");
+ break;
+
+ default:
+ break;
+ }
+
+ g_string_append (str_buf, (const gchar *) str);
+ }
+ }
+
+ if (cur->add_sel) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_additional_sel_to_string (cur->add_sel);
+ if (tmp_str) {
+ g_string_append (str_buf, (const gchar *) tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+
+guchar *
+cr_simple_sel_one_to_string (CRSimpleSel const * a_this)
+{
+ GString *str_buf = NULL;
+ guchar *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+ if (a_this->name) {
+ gchar const *str = a_this->name->stryng->str;
+
+ if (str) {
+ g_string_append_printf (str_buf, "%s", str);
+ }
+ }
+
+ if (a_this->add_sel) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_additional_sel_to_string (a_this->add_sel);
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf, "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_simple_sel_dump:
+ *@a_this: the current instance of #CRSimpleSel.
+ *@a_fp: the destination file pointer.
+ *
+ *Dumps the selector to a file.
+ *TODO: add the support of unicode in the dump.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_simple_sel_dump (CRSimpleSel const * a_this, FILE * a_fp)
+{
+ guchar *tmp_str = NULL;
+
+ g_return_val_if_fail (a_fp, CR_BAD_PARAM_ERROR);
+
+ if (a_this) {
+ tmp_str = cr_simple_sel_to_string (a_this);
+ if (tmp_str) {
+ fprintf (a_fp, "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+
+ return CR_OK;
+}
+
+/**
+ * cr_simple_sel_compute_specificity:
+ *
+ *@a_this: the current instance of #CRSimpleSel
+ *
+ *Computes the selector (combinator separated list of simple selectors)
+ *as defined in the css2 spec in chapter 6.4.3
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_simple_sel_compute_specificity (CRSimpleSel * a_this)
+{
+ CRAdditionalSel const *cur_add_sel = NULL;
+ CRSimpleSel const *cur_sel = NULL;
+ gulong a = 0,
+ b = 0,
+ c = 0;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ for (cur_sel = a_this; cur_sel; cur_sel = cur_sel->next) {
+ if (cur_sel->type_mask & TYPE_SELECTOR) {
+ c++; /*hmmh, is this a new language ? */
+ } else if (!cur_sel->name
+ || !cur_sel->name->stryng
+ || !cur_sel->name->stryng->str) {
+ if (cur_sel->add_sel->type ==
+ PSEUDO_CLASS_ADD_SELECTOR) {
+ /*
+ *this is a pseudo element, and
+ *the spec says, "ignore pseudo elements".
+ */
+ continue;
+ }
+ }
+
+ for (cur_add_sel = cur_sel->add_sel;
+ cur_add_sel; cur_add_sel = cur_add_sel->next) {
+ switch (cur_add_sel->type) {
+ case ID_ADD_SELECTOR:
+ a++;
+ break;
+
+ case NO_ADD_SELECTOR:
+ continue;
+
+ default:
+ b++;
+ break;
+ }
+ }
+ }
+
+ /*we suppose a, b and c have 1 to 3 digits */
+ a_this->specificity = a * 1000000 + b * 1000 + c;
+
+ return CR_OK;
+}
+
+/**
+ * cr_simple_sel_destroy:
+ *
+ *@a_this: the this pointer of the current instance of #CRSimpleSel.
+ *
+ *The destructor of the current instance of
+ *#CRSimpleSel. Recursively calls the destructor of #CRSimpleSel->next
+ */
+void
+cr_simple_sel_destroy (CRSimpleSel * const a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->name) {
+ cr_string_destroy (a_this->name);
+ a_this->name = NULL;
+ }
+
+ if (a_this->add_sel) {
+ cr_additional_sel_destroy (a_this->add_sel);
+ a_this->add_sel = NULL;
+ }
+
+ if (a_this->next) {
+ cr_simple_sel_destroy (a_this->next);
+ a_this->next = NULL;
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-simple-sel.h b/src/3rdparty/libcroco/src/cr-simple-sel.h
new file mode 100644
index 0000000..e53f587
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-simple-sel.h
@@ -0,0 +1,131 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+
+#ifndef __CR_SEL_H__
+#define __CR_SEL_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-additional-sel.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *the declaration of the #CRSimpleSel class.
+ *
+ */
+enum Combinator
+{
+ NO_COMBINATOR,
+ COMB_WS, /*whitespace: descendent*/
+ COMB_PLUS, /*'+': immediately preceded by*/
+ COMB_TILDE, /*'~': preceded by, CSS 3*/
+ COMB_GT /*greater than ('>'): child*/
+} ;
+
+enum SimpleSelectorType
+{
+ NO_SELECTOR_TYPE = 0,
+ UNIVERSAL_SELECTOR = 1,
+ TYPE_SELECTOR = 1 << 1
+} ;
+
+typedef struct _CRSimpleSel CRSimpleSel ;
+
+/**
+ *The abstraction of a css2 simple selection list
+ *as defined by the right part of the "selector" production in the
+ *appendix D.1 of the css2 spec.
+ *It is basically a list of simple selector, each
+ *simple selector being separated by a combinator.
+ *
+ *In the libcroco's implementation, each simple selector
+ *is made of at most two parts:
+ *
+ *1/An element name or 'type selector' (which can hold a '*' and
+ *then been called 'universal selector')
+ *
+ *2/An additional selector that "specializes" the preceding type or
+ *universal selector. The additional selector can be either
+ *an id selector, or a class selector, or an attribute selector.
+ */
+struct _CRSimpleSel
+{
+ enum SimpleSelectorType type_mask ;
+ gboolean is_case_sentive ;
+ CRString * name ;
+ /**
+ *The combinator that separates
+ *this simple selector from the previous
+ *one.
+ */
+ enum Combinator combinator ;
+
+ /**
+ *The additional selector list of the
+ *current simple selector.
+ *An additional selector may
+ *be a class selector, an id selector,
+ *or an attribute selector.
+ *Note that this field is a linked list.
+ */
+ CRAdditionalSel *add_sel ;
+
+ /*
+ *the specificity as specified by
+ *chapter 6.4.3 of the spec.
+ */
+ gulong specificity ;
+
+ CRSimpleSel *next ;
+ CRSimpleSel *prev ;
+ CRParsingLocation location ;
+} ;
+
+CRSimpleSel * cr_simple_sel_new (void) ;
+
+CRSimpleSel * cr_simple_sel_append_simple_sel (CRSimpleSel *a_this,
+ CRSimpleSel *a_sel) ;
+
+CRSimpleSel * cr_simple_sel_prepend_simple_sel (CRSimpleSel *a_this,
+ CRSimpleSel *a_sel) ;
+
+guchar * cr_simple_sel_to_string (CRSimpleSel const *a_this) ;
+
+guchar * cr_simple_sel_one_to_string (CRSimpleSel const * a_this) ;
+
+enum CRStatus cr_simple_sel_dump (CRSimpleSel const *a_this, FILE *a_fp) ;
+
+enum CRStatus cr_simple_sel_dump_attr_sel_list (CRSimpleSel const *a_this) ;
+
+enum CRStatus cr_simple_sel_compute_specificity (CRSimpleSel *a_this) ;
+
+void cr_simple_sel_destroy (CRSimpleSel *a_this) ;
+
+G_END_DECLS
+
+
+#endif /*__CR_SIMPLE_SEL_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-statement.c b/src/3rdparty/libcroco/src/cr-statement.c
new file mode 100644
index 0000000..d624e9f
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-statement.c
@@ -0,0 +1,2810 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See COPYRIGHTS files for copyrights information.
+ */
+
+#include <string.h>
+#include "cr-statement.h"
+#include "cr-parser.h"
+
+/**
+ *@file
+ *Definition of the #CRStatement class.
+ */
+
+#define DECLARATION_INDENT_NB 2
+
+static void cr_statement_clear (CRStatement * a_this);
+
+static void
+parse_font_face_start_font_face_cb (CRDocHandler * a_this,
+ CRParsingLocation *a_location)
+{
+ CRStatement *stmt = NULL;
+ enum CRStatus status = CR_OK;
+
+ (void) a_location;
+
+ stmt = cr_statement_new_at_font_face_rule (NULL, NULL);
+ g_return_if_fail (stmt);
+
+ status = cr_doc_handler_set_ctxt (a_this, stmt);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_font_face_unrecoverable_error_cb (CRDocHandler * a_this)
+{
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_if_fail (a_this);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ if (status != CR_OK) {
+ cr_utils_trace_info ("Couldn't get parsing context. "
+ "This may lead to some memory leaks.");
+ return;
+ }
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ cr_doc_handler_set_ctxt (a_this, NULL);
+ return;
+ }
+}
+
+static void
+parse_font_face_property_cb (CRDocHandler * a_this,
+ CRString * a_name,
+ CRTerm * a_value, gboolean a_important)
+{
+ enum CRStatus status = CR_OK;
+ CRString *name = NULL;
+ CRDeclaration *decl = NULL;
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+
+ (void) a_important;
+
+ g_return_if_fail (a_this && a_name);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ g_return_if_fail (status == CR_OK && stmt);
+ g_return_if_fail (stmt->type == AT_FONT_FACE_RULE_STMT);
+
+ name = cr_string_dup (a_name) ;
+ g_return_if_fail (name);
+ decl = cr_declaration_new (stmt, name, a_value);
+ if (!decl) {
+ cr_utils_trace_info ("cr_declaration_new () failed.");
+ goto error;
+ }
+ name = NULL;
+
+ stmt->kind.font_face_rule->decl_list =
+ cr_declaration_append (stmt->kind.font_face_rule->decl_list,
+ decl);
+ if (!stmt->kind.font_face_rule->decl_list)
+ goto error;
+ decl = NULL;
+
+ error:
+ if (decl) {
+ cr_declaration_unref (decl);
+ decl = NULL;
+ }
+ if (name) {
+ cr_string_destroy (name);
+ name = NULL;
+ }
+}
+
+static void
+parse_font_face_end_font_face_cb (CRDocHandler * a_this)
+{
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_if_fail (a_this);
+
+ resultptr = &result;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) resultptr);
+ g_return_if_fail (status == CR_OK && result);
+ g_return_if_fail (result->type == AT_FONT_FACE_RULE_STMT);
+
+ status = cr_doc_handler_set_result (a_this, result);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_page_start_page_cb (CRDocHandler * a_this,
+ CRString * a_name,
+ CRString * a_pseudo_page,
+ CRParsingLocation *a_location)
+{
+ CRStatement *stmt = NULL;
+ enum CRStatus status = CR_OK;
+ CRString *page_name = NULL, *pseudo_name = NULL ;
+
+ (void) a_location;
+
+ if (a_name)
+ page_name = cr_string_dup (a_name) ;
+ if (a_pseudo_page)
+ pseudo_name = cr_string_dup (a_pseudo_page) ;
+
+ stmt = cr_statement_new_at_page_rule (NULL, NULL,
+ page_name,
+ pseudo_name);
+ page_name = NULL ;
+ pseudo_name = NULL ;
+ g_return_if_fail (stmt);
+ status = cr_doc_handler_set_ctxt (a_this, stmt);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_page_unrecoverable_error_cb (CRDocHandler * a_this)
+{
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_if_fail (a_this);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ if (status != CR_OK) {
+ cr_utils_trace_info ("Couldn't get parsing context. "
+ "This may lead to some memory leaks.");
+ return;
+ }
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ cr_doc_handler_set_ctxt (a_this, NULL);
+ }
+}
+
+static void
+parse_page_property_cb (CRDocHandler * a_this,
+ CRString * a_name,
+ CRTerm * a_expression, gboolean a_important)
+{
+ CRString *name = NULL;
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+ CRDeclaration *decl = NULL;
+ enum CRStatus status = CR_OK;
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ g_return_if_fail (status == CR_OK && stmt->type == AT_PAGE_RULE_STMT);
+
+ name = cr_string_dup (a_name);
+ g_return_if_fail (name);
+
+ decl = cr_declaration_new (stmt, name, a_expression);
+ if (!decl)
+ cr_string_destroy(name);
+ g_return_if_fail (decl);
+ decl->important = a_important;
+ stmt->kind.page_rule->decl_list =
+ cr_declaration_append (stmt->kind.page_rule->decl_list, decl);
+ g_return_if_fail (stmt->kind.page_rule->decl_list);
+}
+
+static void
+parse_page_end_page_cb (CRDocHandler * a_this,
+ CRString * a_name,
+ CRString * a_pseudo_page)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+
+ (void) a_name;
+ (void) a_pseudo_page;
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ g_return_if_fail (status == CR_OK && stmt);
+ g_return_if_fail (stmt->type == AT_PAGE_RULE_STMT);
+
+ status = cr_doc_handler_set_result (a_this, stmt);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_at_media_start_media_cb (CRDocHandler * a_this,
+ GList * a_media_list,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *at_media = NULL;
+ GList *media_list = NULL;
+
+ (void) a_location;
+
+ g_return_if_fail (a_this && a_this->priv);
+
+ if (a_media_list) {
+ /*duplicate media list */
+ media_list = cr_utils_dup_glist_of_cr_string
+ (a_media_list);
+ }
+
+ g_return_if_fail (media_list);
+
+ /*make sure cr_statement_new_at_media_rule works in this case. */
+ at_media = cr_statement_new_at_media_rule (NULL, NULL, media_list);
+
+ status = cr_doc_handler_set_ctxt (a_this, at_media);
+ g_return_if_fail (status == CR_OK);
+ status = cr_doc_handler_set_result (a_this, at_media);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_at_media_unrecoverable_error_cb (CRDocHandler * a_this)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+
+ g_return_if_fail (a_this);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_result (a_this, (gpointer *) stmtptr);
+ if (status != CR_OK) {
+ cr_utils_trace_info ("Couldn't get parsing context. "
+ "This may lead to some memory leaks.");
+ return;
+ }
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ cr_doc_handler_set_ctxt (a_this, NULL);
+ cr_doc_handler_set_result (a_this, NULL);
+ }
+}
+
+static void
+parse_at_media_start_selector_cb (CRDocHandler * a_this,
+ CRSelector * a_sellist)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *at_media = NULL;
+ CRStatement **at_media_ptr = NULL;
+ CRStatement *ruleset = NULL;
+
+ g_return_if_fail (a_this && a_this->priv && a_sellist);
+
+ at_media_ptr = &at_media;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) at_media_ptr);
+ g_return_if_fail (status == CR_OK && at_media);
+ g_return_if_fail (at_media->type == AT_MEDIA_RULE_STMT);
+ ruleset = cr_statement_new_ruleset (NULL, a_sellist, NULL, at_media);
+ g_return_if_fail (ruleset);
+ status = cr_doc_handler_set_ctxt (a_this, ruleset);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_at_media_property_cb (CRDocHandler * a_this,
+ CRString * a_name, CRTerm * a_value,
+ gboolean a_important)
+{
+ enum CRStatus status = CR_OK;
+
+ /*
+ *the current ruleset stmt, child of the
+ *current at-media being parsed.
+ */
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+ CRDeclaration *decl = NULL;
+ CRString *name = NULL;
+
+ g_return_if_fail (a_this && a_name);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this,
+ (gpointer *) stmtptr);
+ g_return_if_fail (status == CR_OK && stmt);
+ g_return_if_fail (stmt->type == RULESET_STMT);
+
+ name = cr_string_dup (a_name) ;
+ g_return_if_fail (name);
+
+ decl = cr_declaration_new (stmt, name, a_value);
+ if (!decl)
+ cr_string_destroy(name);
+ g_return_if_fail (decl);
+ decl->important = a_important;
+ status = cr_statement_ruleset_append_decl (stmt, decl);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_at_media_end_selector_cb (CRDocHandler * a_this,
+ CRSelector * a_sellist)
+{
+ enum CRStatus status = CR_OK;
+
+ /*
+ *the current ruleset stmt, child of the
+ *current at-media being parsed.
+ */
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+
+ g_return_if_fail (a_this && a_sellist);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ g_return_if_fail (status == CR_OK && stmt
+ && stmt->type == RULESET_STMT);
+ g_return_if_fail (stmt->kind.ruleset->parent_media_rule);
+
+ status = cr_doc_handler_set_ctxt
+ (a_this, stmt->kind.ruleset->parent_media_rule);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_at_media_end_media_cb (CRDocHandler * a_this,
+ GList * a_media_list)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *at_media = NULL;
+ CRStatement **at_media_ptr = NULL;
+
+ (void) a_media_list;
+
+ g_return_if_fail (a_this && a_this->priv);
+
+ at_media_ptr = &at_media;
+ status = cr_doc_handler_get_ctxt (a_this,
+ (gpointer *) at_media_ptr);
+ g_return_if_fail (status == CR_OK && at_media);
+ status = cr_doc_handler_set_result (a_this, at_media);
+}
+
+static void
+parse_ruleset_start_selector_cb (CRDocHandler * a_this,
+ CRSelector * a_sellist)
+{
+ CRStatement *ruleset = NULL;
+
+ g_return_if_fail (a_this && a_this->priv && a_sellist);
+
+ ruleset = cr_statement_new_ruleset (NULL, a_sellist, NULL, NULL);
+ g_return_if_fail (ruleset);
+
+ cr_doc_handler_set_result (a_this, ruleset);
+}
+
+static void
+parse_ruleset_unrecoverable_error_cb (CRDocHandler * a_this)
+{
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+ enum CRStatus status = CR_OK;
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_result (a_this, (gpointer *) stmtptr);
+ if (status != CR_OK) {
+ cr_utils_trace_info ("Couldn't get parsing context. "
+ "This may lead to some memory leaks.");
+ return;
+ }
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ cr_doc_handler_set_result (a_this, NULL);
+ }
+}
+
+static void
+parse_ruleset_property_cb (CRDocHandler * a_this,
+ CRString * a_name,
+ CRTerm * a_value, gboolean a_important)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *ruleset = NULL;
+ CRStatement **rulesetptr = NULL;
+ CRDeclaration *decl = NULL;
+ CRString *stringue = NULL;
+
+ g_return_if_fail (a_this && a_this->priv && a_name);
+
+ rulesetptr = &ruleset;
+ status = cr_doc_handler_get_result (a_this, (gpointer *) rulesetptr);
+ g_return_if_fail (status == CR_OK
+ && ruleset
+ && ruleset->type == RULESET_STMT);
+
+ stringue = cr_string_dup (a_name);
+ g_return_if_fail (stringue);
+
+ decl = cr_declaration_new (ruleset, stringue, a_value);
+ if (!decl)
+ cr_string_destroy (stringue);
+ g_return_if_fail (decl);
+ decl->important = a_important;
+ status = cr_statement_ruleset_append_decl (ruleset, decl);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_ruleset_end_selector_cb (CRDocHandler * a_this,
+ CRSelector * a_sellist)
+{
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_if_fail (a_this && a_sellist);
+
+ resultptr = &result;
+ status = cr_doc_handler_get_result (a_this, (gpointer *) resultptr);
+
+ g_return_if_fail (status == CR_OK
+ && result
+ && result->type == RULESET_STMT);
+}
+
+static void
+cr_statement_clear (CRStatement * a_this)
+{
+ g_return_if_fail (a_this);
+
+ switch (a_this->type) {
+ case AT_RULE_STMT:
+ break;
+ case RULESET_STMT:
+ if (!a_this->kind.ruleset)
+ return;
+ if (a_this->kind.ruleset->sel_list) {
+ cr_selector_unref (a_this->kind.ruleset->sel_list);
+ a_this->kind.ruleset->sel_list = NULL;
+ }
+ if (a_this->kind.ruleset->decl_list) {
+ cr_declaration_destroy
+ (a_this->kind.ruleset->decl_list);
+ a_this->kind.ruleset->decl_list = NULL;
+ }
+ g_free (a_this->kind.ruleset);
+ a_this->kind.ruleset = NULL;
+ break;
+
+ case AT_IMPORT_RULE_STMT:
+ if (!a_this->kind.import_rule)
+ return;
+ if (a_this->kind.import_rule->url) {
+ cr_string_destroy
+ (a_this->kind.import_rule->url) ;
+ a_this->kind.import_rule->url = NULL;
+ }
+ if (a_this->kind.import_rule->media_list) {
+ g_list_free_full (a_this->kind.import_rule->media_list,
+ (GDestroyNotify) cr_string_destroy);
+ }
+ if (a_this->kind.import_rule->sheet) {
+ cr_stylesheet_unref (a_this->kind.import_rule->sheet);
+ }
+ g_free (a_this->kind.import_rule);
+ a_this->kind.import_rule = NULL;
+ break;
+
+ case AT_MEDIA_RULE_STMT:
+ if (!a_this->kind.media_rule)
+ return;
+ if (a_this->kind.media_rule->rulesets) {
+ cr_statement_destroy
+ (a_this->kind.media_rule->rulesets);
+ a_this->kind.media_rule->rulesets = NULL;
+ }
+ if (a_this->kind.media_rule->media_list) {
+ GList *cur = NULL;
+
+ for (cur = a_this->kind.media_rule->media_list;
+ cur; cur = cur->next) {
+ if (cur->data) {
+ cr_string_destroy ((CRString *) cur->data);
+ cur->data = NULL;
+ }
+
+ }
+ g_list_free (a_this->kind.media_rule->media_list);
+ a_this->kind.media_rule->media_list = NULL;
+ }
+ g_free (a_this->kind.media_rule);
+ a_this->kind.media_rule = NULL;
+ break;
+
+ case AT_PAGE_RULE_STMT:
+ if (!a_this->kind.page_rule)
+ return;
+
+ if (a_this->kind.page_rule->decl_list) {
+ cr_declaration_destroy
+ (a_this->kind.page_rule->decl_list);
+ a_this->kind.page_rule->decl_list = NULL;
+ }
+ if (a_this->kind.page_rule->name) {
+ cr_string_destroy
+ (a_this->kind.page_rule->name);
+ a_this->kind.page_rule->name = NULL;
+ }
+ if (a_this->kind.page_rule->pseudo) {
+ cr_string_destroy
+ (a_this->kind.page_rule->pseudo);
+ a_this->kind.page_rule->pseudo = NULL;
+ }
+ g_free (a_this->kind.page_rule);
+ a_this->kind.page_rule = NULL;
+ break;
+
+ case AT_CHARSET_RULE_STMT:
+ if (!a_this->kind.charset_rule)
+ return;
+
+ if (a_this->kind.charset_rule->charset) {
+ cr_string_destroy
+ (a_this->kind.charset_rule->charset);
+ a_this->kind.charset_rule->charset = NULL;
+ }
+ g_free (a_this->kind.charset_rule);
+ a_this->kind.charset_rule = NULL;
+ break;
+
+ case AT_FONT_FACE_RULE_STMT:
+ if (!a_this->kind.font_face_rule)
+ return;
+
+ if (a_this->kind.font_face_rule->decl_list) {
+ cr_declaration_unref
+ (a_this->kind.font_face_rule->decl_list);
+ a_this->kind.font_face_rule->decl_list = NULL;
+ }
+ g_free (a_this->kind.font_face_rule);
+ a_this->kind.font_face_rule = NULL;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * cr_statement_ruleset_to_string:
+ *
+ *@a_this: the current instance of #CRStatement
+ *@a_indent: the number of whitespace to use for indentation
+ *
+ *Serializes the ruleset statement into a string
+ *
+ *Returns the newly allocated serialised string. Must be freed
+ *by the caller, using g_free().
+ */
+static gchar *
+cr_statement_ruleset_to_string (CRStatement const * a_this, glong a_indent)
+{
+ GString *stringue = NULL;
+ gchar *tmp_str = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT, NULL);
+
+ stringue = (GString *) g_string_new (NULL);
+ if (!stringue) {
+ return result;
+ }
+
+ if (a_this->kind.ruleset->sel_list) {
+ if (a_indent)
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent);
+
+ tmp_str =
+ (gchar *) cr_selector_to_string (a_this->kind.ruleset->
+ sel_list);
+ if (tmp_str) {
+ g_string_append (stringue, tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ g_string_append (stringue, " {\n");
+ if (a_this->kind.ruleset->decl_list) {
+ tmp_str = (gchar *) cr_declaration_list_to_string2
+ (a_this->kind.ruleset->decl_list,
+ a_indent + DECLARATION_INDENT_NB, TRUE);
+ if (tmp_str) {
+ g_string_append (stringue, tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ g_string_append (stringue, "\n");
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent);
+ }
+ g_string_append (stringue, "}");
+ result = stringue->str;
+
+ g_string_free (stringue, FALSE);
+ stringue = NULL;
+
+ if (tmp_str) {
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ return result;
+}
+
+
+/**
+ * cr_statement_font_face_rule_to_string:
+ *
+ *@a_this: the current instance of #CRStatement to consider
+ *It must be a font face rule statement.
+ *@a_indent: the number of white spaces of indentation.
+ *
+ *Serializes a font face rule statement into a string.
+ *
+ *Returns the serialized string. Must be deallocated by the caller
+ *using g_free().
+ */
+static gchar *
+cr_statement_font_face_rule_to_string (CRStatement const * a_this,
+ glong a_indent)
+{
+ gchar *result = NULL, *tmp_str = NULL ;
+ GString *stringue = NULL ;
+
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_FONT_FACE_RULE_STMT,
+ NULL);
+
+ if (a_this->kind.font_face_rule->decl_list) {
+ stringue = (GString *) g_string_new (NULL) ;
+ g_return_val_if_fail (stringue, NULL) ;
+ if (a_indent)
+ cr_utils_dump_n_chars2 (' ', stringue,
+ a_indent);
+ g_string_append (stringue, "@font-face {\n");
+ tmp_str = (gchar *) cr_declaration_list_to_string2
+ (a_this->kind.font_face_rule->decl_list,
+ a_indent + DECLARATION_INDENT_NB, TRUE) ;
+ if (tmp_str) {
+ g_string_append (stringue,
+ tmp_str) ;
+ g_free (tmp_str) ;
+ tmp_str = NULL ;
+ }
+ g_string_append (stringue, "\n}");
+ }
+ if (stringue) {
+ result = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ stringue = NULL ;
+ }
+ return result ;
+}
+
+
+/**
+ * cr_statement_charset_to_string:
+ *
+ *Serialises an \@charset statement into a string.
+ *@a_this: the statement to serialize.
+ *@a_indent: the number of indentation spaces
+ *
+ *Returns the serialized charset statement. Must be
+ *freed by the caller using g_free().
+ */
+static gchar *
+cr_statement_charset_to_string (CRStatement const *a_this,
+ gulong a_indent)
+{
+ gchar *str = NULL ;
+ GString *stringue = NULL ;
+
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_CHARSET_RULE_STMT,
+ NULL) ;
+
+ if (a_this->kind.charset_rule
+ && a_this->kind.charset_rule->charset
+ && a_this->kind.charset_rule->charset->stryng
+ && a_this->kind.charset_rule->charset->stryng->str) {
+ stringue = g_string_new (NULL) ;
+ g_return_val_if_fail (stringue, NULL) ;
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent);
+ g_string_append_printf (stringue,
+ "@charset \"%s\" ;",
+ a_this->kind.charset_rule->charset->stryng->str);
+ }
+ if (stringue) {
+ str = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ }
+ return str ;
+}
+
+
+/**
+ * cr_statement_at_page_rule_to_string:
+ *
+ *Serialises the at page rule statement into a string
+ *@a_this: the current instance of #CRStatement. Must
+ *be an "\@page" rule statement.
+ *
+ *Returns the serialized string. Must be freed by the caller
+ */
+static gchar *
+cr_statement_at_page_rule_to_string (CRStatement const *a_this,
+ gulong a_indent)
+{
+ GString *stringue = NULL;
+ gchar *result = NULL ;
+
+ stringue = (GString *) g_string_new (NULL) ;
+
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent) ;
+ g_string_append (stringue, "@page");
+ if (a_this->kind.page_rule->name
+ && a_this->kind.page_rule->name->stryng) {
+ g_string_append_printf
+ (stringue, " %s",
+ a_this->kind.page_rule->name->stryng->str) ;
+ } else {
+ g_string_append (stringue, " ");
+ }
+ if (a_this->kind.page_rule->pseudo
+ && a_this->kind.page_rule->pseudo->stryng) {
+ g_string_append_printf
+ (stringue, " :%s",
+ a_this->kind.page_rule->pseudo->stryng->str) ;
+ }
+ if (a_this->kind.page_rule->decl_list) {
+ gchar *str = NULL ;
+ g_string_append (stringue, " {\n");
+ str = (gchar *) cr_declaration_list_to_string2
+ (a_this->kind.page_rule->decl_list,
+ a_indent + DECLARATION_INDENT_NB, TRUE) ;
+ if (str) {
+ g_string_append (stringue, str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ g_string_append (stringue, "\n}\n");
+ }
+ result = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ stringue = NULL ;
+ return result ;
+}
+
+
+/**
+ *Serializes an \@media statement.
+ *@param a_this the current instance of #CRStatement
+ *@param a_indent the number of spaces of indentation.
+ *@return the serialized \@media statement. Must be freed
+ *by the caller using g_free().
+ */
+static gchar *
+cr_statement_media_rule_to_string (CRStatement const *a_this,
+ gulong a_indent)
+{
+ gchar *str = NULL ;
+ GString *stringue = NULL ;
+ GList const *cur = NULL;
+
+ g_return_val_if_fail (a_this->type == AT_MEDIA_RULE_STMT,
+ NULL);
+
+ if (a_this->kind.media_rule) {
+ stringue = (GString *) g_string_new (NULL) ;
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent);
+ g_string_append (stringue, "@media");
+
+ for (cur = a_this->kind.media_rule->media_list; cur;
+ cur = cur->next) {
+ CRString const *crstr = cur->data;
+ if (crstr && crstr->stryng) {
+ gchar const *str2 = crstr->stryng->str;
+ if (str2) {
+ if (cur->prev) {
+ g_string_append
+ (stringue,
+ ",");
+ }
+ g_string_append_printf
+ (stringue,
+ " %s", str2);
+ }
+ }
+ }
+ g_string_append (stringue, " {\n");
+ str = cr_statement_list_to_string
+ (a_this->kind.media_rule->rulesets,
+ a_indent + DECLARATION_INDENT_NB) ;
+ if (str) {
+ g_string_append (stringue, str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ g_string_append (stringue, "\n}");
+ }
+ if (stringue) {
+ str = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ }
+ return str ;
+}
+
+
+static gchar *
+cr_statement_import_rule_to_string (CRStatement const *a_this,
+ gulong a_indent)
+{
+ GString *stringue = NULL ;
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_this->kind.import_rule,
+ NULL) ;
+
+ if (a_this->kind.import_rule->url
+ && a_this->kind.import_rule->url->stryng) {
+ stringue = (GString *) g_string_new (NULL) ;
+ g_return_val_if_fail (stringue, NULL) ;
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent);
+ if (a_this->kind.import_rule->url->stryng->str) {
+ g_string_append_printf (stringue,
+ "@import url(\"%s\")",
+ a_this->kind.import_rule->url->stryng->str);
+ } else /*there is no url, so no import rule, get out! */
+ return NULL;
+
+ if (a_this->kind.import_rule->media_list) {
+ GList const *cur = NULL;
+
+ for (cur = a_this->kind.import_rule->media_list;
+ cur; cur = cur->next) {
+ if (cur->data) {
+ CRString const *crstr = cur->data;
+
+ if (cur->prev) {
+ g_string_append
+ (stringue, ", ");
+ }
+ if (crstr
+ && crstr->stryng
+ && crstr->stryng->str) {
+ g_string_append_len
+ (stringue,
+ crstr->stryng->str,
+ crstr->stryng->len) ;
+ }
+ }
+ }
+ }
+ g_string_append (stringue, " ;");
+ }
+ if (stringue) {
+ str = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ stringue = NULL ;
+ }
+ return str ;
+}
+
+
+/*******************
+ *public functions
+ ******************/
+
+/**
+ * cr_statement_does_buf_parses_against_core:
+ *
+ *@a_buf: the buffer to parse.
+ *@a_encoding: the character encoding of a_buf.
+ *
+ *Tries to parse a buffer and says whether if the content of the buffer
+ *is a css statement as defined by the "Core CSS Grammar" (chapter 4 of the
+ *css spec) or not.
+ *
+ *Returns TRUE if the buffer parses against the core grammar, false otherwise.
+ */
+gboolean
+cr_statement_does_buf_parses_against_core (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ CRParser *parser = NULL;
+ enum CRStatus status = CR_OK;
+ gboolean result = FALSE;
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ g_return_val_if_fail (parser, FALSE);
+
+ status = cr_parser_set_use_core_grammar (parser, TRUE);
+ if (status != CR_OK) {
+ goto cleanup;
+ }
+
+ status = cr_parser_parse_statement_core (parser);
+ if (status == CR_OK) {
+ result = TRUE;
+ }
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ }
+
+ return result;
+}
+
+/**
+ * cr_statement_parse_from_buf:
+ *
+ *@a_buf: the buffer to parse.
+ *@a_encoding: the character encoding of a_buf.
+ *
+ *Parses a buffer that contains a css statement and returns
+ *an instance of #CRStatement in case of successful parsing.
+ *TODO: at support of "\@import" rules.
+ *
+ *Returns the newly built instance of #CRStatement in case
+ *of successful parsing, NULL otherwise.
+ */
+CRStatement *
+cr_statement_parse_from_buf (const guchar * a_buf, enum CREncoding a_encoding)
+{
+ CRStatement *result = NULL;
+
+ /*
+ *The strategy of this function is "brute force".
+ *It tries to parse all the types of CRStatement it knows about.
+ *I could do this a smarter way but I don't have the time now.
+ *I think I will revisit this when time of performances and
+ *pull based incremental parsing comes.
+ */
+
+ result = cr_statement_ruleset_parse_from_buf (a_buf, a_encoding);
+ if (!result) {
+ result = cr_statement_at_charset_rule_parse_from_buf
+ (a_buf, a_encoding);
+ } else {
+ goto out;
+ }
+
+ if (!result) {
+ result = cr_statement_at_media_rule_parse_from_buf
+ (a_buf, a_encoding);
+ } else {
+ goto out;
+ }
+
+ if (!result) {
+ result = cr_statement_at_charset_rule_parse_from_buf
+ (a_buf, a_encoding);
+ } else {
+ goto out;
+ }
+
+ if (!result) {
+ result = cr_statement_font_face_rule_parse_from_buf
+ (a_buf, a_encoding);
+
+ } else {
+ goto out;
+ }
+
+ if (!result) {
+ result = cr_statement_at_page_rule_parse_from_buf
+ (a_buf, a_encoding);
+ } else {
+ goto out;
+ }
+
+ if (!result) {
+ result = cr_statement_at_import_rule_parse_from_buf
+ (a_buf, a_encoding);
+ } else {
+ goto out;
+ }
+
+ out:
+ return result;
+}
+
+/**
+ * cr_statement_ruleset_parse_from_buf:
+ *
+ *@a_buf: the buffer to parse.
+ *@a_enc: the character encoding of a_buf.
+ *
+ *Parses a buffer that contains a ruleset statement and instantiates
+ *a #CRStatement of type RULESET_STMT.
+ *
+ *Returns the newly built instance of #CRStatement in case of successful parsing,
+ *NULL otherwise.
+ */
+CRStatement *
+cr_statement_ruleset_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_enc)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+ CRParser *parser = NULL;
+ CRDocHandler *sac_handler = NULL;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_enc, FALSE);
+
+ g_return_val_if_fail (parser, NULL);
+
+ sac_handler = cr_doc_handler_new ();
+ g_return_val_if_fail (sac_handler, NULL);
+
+ sac_handler->start_selector = parse_ruleset_start_selector_cb;
+ sac_handler->end_selector = parse_ruleset_end_selector_cb;
+ sac_handler->property = parse_ruleset_property_cb;
+ sac_handler->unrecoverable_error =
+ parse_ruleset_unrecoverable_error_cb;
+
+ cr_parser_set_sac_handler (parser, sac_handler);
+ cr_parser_try_to_skip_spaces_and_comments (parser);
+ status = cr_parser_parse_ruleset (parser);
+ if (status != CR_OK) {
+ goto cleanup;
+ }
+
+ resultptr = &result;
+ status = cr_doc_handler_get_result (sac_handler,
+ (gpointer *) resultptr);
+ if (!((status == CR_OK) && result)) {
+ if (result) {
+ cr_statement_destroy (result);
+ result = NULL;
+ }
+ }
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ sac_handler = NULL ;
+ }
+ if (sac_handler) {
+ cr_doc_handler_unref (sac_handler);
+ sac_handler = NULL;
+ }
+ return result;
+}
+
+/**
+ * cr_statement_new_ruleset:
+ *
+ *@a_sel_list: the list of #CRSimpleSel (selectors)
+ *the rule applies to.
+ *@a_decl_list: the list of instances of #CRDeclaration
+ *that composes the ruleset.
+ *@a_media_types: a list of instances of GString that
+ *describe the media list this ruleset applies to.
+ *
+ *Creates a new instance of #CRStatement of type
+ *#CRRulSet.
+ *
+ *Returns the new instance of #CRStatement or NULL if something
+ *went wrong.
+ */
+CRStatement *
+cr_statement_new_ruleset (CRStyleSheet * a_sheet,
+ CRSelector * a_sel_list,
+ CRDeclaration * a_decl_list,
+ CRStatement * a_parent_media_rule)
+{
+ CRStatement *result = NULL;
+
+ g_return_val_if_fail (a_sel_list, NULL);
+
+ if (a_parent_media_rule) {
+ g_return_val_if_fail
+ (a_parent_media_rule->type == AT_MEDIA_RULE_STMT,
+ NULL);
+ g_return_val_if_fail (a_parent_media_rule->kind.media_rule,
+ NULL);
+ }
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStatement));
+ result->type = RULESET_STMT;
+ result->kind.ruleset = (CRRuleSet *) g_try_malloc (sizeof (CRRuleSet));
+
+ if (!result->kind.ruleset) {
+ cr_utils_trace_info ("Out of memory");
+ if (result)
+ g_free (result);
+ return NULL;
+ }
+
+ memset (result->kind.ruleset, 0, sizeof (CRRuleSet));
+ result->kind.ruleset->sel_list = a_sel_list;
+ if (a_sel_list)
+ cr_selector_ref (a_sel_list);
+ result->kind.ruleset->decl_list = a_decl_list;
+
+ if (a_parent_media_rule) {
+ result->kind.ruleset->parent_media_rule = a_parent_media_rule;
+ a_parent_media_rule->kind.media_rule->rulesets =
+ cr_statement_append
+ (a_parent_media_rule->kind.media_rule->rulesets,
+ result);
+ }
+
+ cr_statement_set_parent_sheet (result, a_sheet);
+
+ return result;
+}
+
+/**
+ * cr_statement_at_media_rule_parse_from_buf:
+ *
+ *@a_buf: the input to parse.
+ *@a_enc: the encoding of the buffer.
+ *
+ *Parses a buffer that contains an "\@media" declaration
+ *and builds an \@media css statement.
+ *
+ *Returns the \@media statement, or NULL if the buffer could not
+ *be successfully parsed.
+ */
+CRStatement *
+cr_statement_at_media_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_enc)
+{
+ CRParser *parser = NULL;
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+ CRDocHandler *sac_handler = NULL;
+ enum CRStatus status = CR_OK;
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_enc, FALSE);
+ if (!parser) {
+ cr_utils_trace_info ("Instantiation of the parser failed");
+ goto cleanup;
+ }
+
+ sac_handler = cr_doc_handler_new ();
+ if (!sac_handler) {
+ cr_utils_trace_info
+ ("Instantiation of the sac handler failed");
+ goto cleanup;
+ }
+
+ sac_handler->start_media = parse_at_media_start_media_cb;
+ sac_handler->start_selector = parse_at_media_start_selector_cb;
+ sac_handler->property = parse_at_media_property_cb;
+ sac_handler->end_selector = parse_at_media_end_selector_cb;
+ sac_handler->end_media = parse_at_media_end_media_cb;
+ sac_handler->unrecoverable_error =
+ parse_at_media_unrecoverable_error_cb;
+
+ status = cr_parser_set_sac_handler (parser, sac_handler);
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_parse_media (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ resultptr = &result;
+ status = cr_doc_handler_get_result (sac_handler,
+ (gpointer *) resultptr);
+ if (status != CR_OK)
+ goto cleanup;
+
+ cleanup:
+
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ sac_handler = NULL ;
+ }
+ if (sac_handler) {
+ cr_doc_handler_unref (sac_handler);
+ sac_handler = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_statement_new_at_media_rule:
+ *
+ *@a_ruleset: the ruleset statements contained
+ *in the \@media rule.
+ *@a_media: the media string list. A list of GString pointers.
+ *
+ *Instantiates an instance of #CRStatement of type
+ *AT_MEDIA_RULE_STMT (\@media ruleset).
+ *
+ */
+CRStatement *
+cr_statement_new_at_media_rule (CRStyleSheet * a_sheet,
+ CRStatement * a_rulesets, GList * a_media)
+{
+ CRStatement *result = NULL,
+ *cur = NULL;
+
+ if (a_rulesets)
+ g_return_val_if_fail (a_rulesets->type == RULESET_STMT, NULL);
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStatement));
+ result->type = AT_MEDIA_RULE_STMT;
+
+ result->kind.media_rule = (CRAtMediaRule *) g_try_malloc (sizeof (CRAtMediaRule));
+ if (!result->kind.media_rule) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (result->kind.media_rule, 0, sizeof (CRAtMediaRule));
+ result->kind.media_rule->rulesets = a_rulesets;
+ for (cur = a_rulesets; cur; cur = cur->next) {
+ if (cur->type != RULESET_STMT || !cur->kind.ruleset) {
+ cr_utils_trace_info ("Bad parameter a_rulesets. "
+ "It should be a list of "
+ "correct ruleset statement only !");
+ goto error;
+ }
+ cur->kind.ruleset->parent_media_rule = result;
+ }
+
+ result->kind.media_rule->media_list = a_media;
+ if (a_sheet) {
+ cr_statement_set_parent_sheet (result, a_sheet);
+ }
+
+ return result;
+
+ error:
+ g_clear_pointer (&result, cr_statement_destroy);
+ return NULL;
+}
+
+/**
+ * cr_statement_new_at_import_rule:
+ *
+ *@a_url: the url to connect to the get the file
+ *to be imported.
+ *@a_sheet: the imported parsed stylesheet.
+ *
+ *Creates a new instance of #CRStatment of type
+ *#CRAtImportRule.
+ *
+ *Returns the newly built instance of #CRStatement.
+ */
+CRStatement *
+cr_statement_new_at_import_rule (CRStyleSheet * a_container_sheet,
+ CRString * a_url,
+ GList * a_media_list,
+ CRStyleSheet * a_imported_sheet)
+{
+ CRStatement *result = NULL;
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStatement));
+ result->type = AT_IMPORT_RULE_STMT;
+
+ result->kind.import_rule = (CRAtImportRule *) g_try_malloc (sizeof (CRAtImportRule));
+
+ if (!result->kind.import_rule) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+
+ memset (result->kind.import_rule, 0, sizeof (CRAtImportRule));
+ result->kind.import_rule->url = a_url;
+ result->kind.import_rule->media_list = a_media_list;
+ result->kind.import_rule->sheet = a_imported_sheet;
+ if (a_container_sheet)
+ cr_statement_set_parent_sheet (result, a_container_sheet);
+
+ return result;
+}
+
+/**
+ * cr_statement_at_import_rule_parse_from_buf:
+ *
+ *@a_buf: the buffer to parse.
+ *@a_encoding: the encoding of a_buf.
+ *
+ *Parses a buffer that contains an "\@import" rule and
+ *instantiate a #CRStatement of type AT_IMPORT_RULE_STMT
+ *
+ *Returns the newly built instance of #CRStatement in case of
+ *a successful parsing, NULL otherwise.
+ */
+CRStatement *
+cr_statement_at_import_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ enum CRStatus status = CR_OK;
+ CRParser *parser = NULL;
+ CRStatement *result = NULL;
+ GList *media_list = NULL;
+ CRString *import_string = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ if (!parser) {
+ cr_utils_trace_info ("Instantiation of parser failed.");
+ goto cleanup;
+ }
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_parse_import (parser,
+ &media_list,
+ &import_string,
+ &location);
+ if (status != CR_OK || !import_string)
+ goto cleanup;
+
+ result = cr_statement_new_at_import_rule (NULL, import_string,
+ media_list, NULL);
+ if (result) {
+ cr_parsing_location_copy (&result->location,
+ &location) ;
+ import_string = NULL;
+ media_list = NULL;
+ }
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+ if (media_list) {
+ for (; media_list;
+ media_list = g_list_next (media_list)) {
+ if (media_list->data) {
+ cr_string_destroy ((CRString*)media_list->data);
+ media_list->data = NULL;
+ }
+ }
+ g_list_free (media_list);
+ media_list = NULL;
+ }
+ if (import_string) {
+ cr_string_destroy (import_string);
+ import_string = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_statement_new_at_page_rule:
+ *
+ *@a_decl_list: a list of instances of #CRDeclarations
+ *which is actually the list of declarations that applies to
+ *this page rule.
+ *@a_selector: the page rule selector.
+ *
+ *Creates a new instance of #CRStatement of type
+ *#CRAtPageRule.
+ *
+ *Returns the newly built instance of #CRStatement or NULL
+ *in case of error.
+ */
+CRStatement *
+cr_statement_new_at_page_rule (CRStyleSheet * a_sheet,
+ CRDeclaration * a_decl_list,
+ CRString * a_name, CRString * a_pseudo)
+{
+ CRStatement *result = NULL;
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStatement));
+ result->type = AT_PAGE_RULE_STMT;
+
+ result->kind.page_rule = (CRAtPageRule *) g_try_malloc (sizeof (CRAtPageRule));
+
+ if (!result->kind.page_rule) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+
+ memset (result->kind.page_rule, 0, sizeof (CRAtPageRule));
+ if (a_decl_list) {
+ result->kind.page_rule->decl_list = a_decl_list;
+ cr_declaration_ref (a_decl_list);
+ }
+ result->kind.page_rule->name = a_name;
+ result->kind.page_rule->pseudo = a_pseudo;
+ if (a_sheet)
+ cr_statement_set_parent_sheet (result, a_sheet);
+
+ return result;
+}
+
+/**
+ * cr_statement_at_page_rule_parse_from_buf:
+ *
+ *@a_buf: the character buffer to parse.
+ *@a_encoding: the character encoding of a_buf.
+ *
+ *Parses a buffer that contains an "\@page" production and,
+ *if the parsing succeeds, builds the page statement.
+ *
+ *Returns the newly built at page statement in case of successful parsing,
+ *NULL otherwise.
+ */
+CRStatement *
+cr_statement_at_page_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ enum CRStatus status = CR_OK;
+ CRParser *parser = NULL;
+ CRDocHandler *sac_handler = NULL;
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ if (!parser) {
+ cr_utils_trace_info ("Instantiation of the parser failed.");
+ goto cleanup;
+ }
+
+ sac_handler = cr_doc_handler_new ();
+ if (!sac_handler) {
+ cr_utils_trace_info
+ ("Instantiation of the sac handler failed.");
+ goto cleanup;
+ }
+
+ sac_handler->start_page = parse_page_start_page_cb;
+ sac_handler->property = parse_page_property_cb;
+ sac_handler->end_page = parse_page_end_page_cb;
+ sac_handler->unrecoverable_error = parse_page_unrecoverable_error_cb;
+
+ status = cr_parser_set_sac_handler (parser, sac_handler);
+ if (status != CR_OK)
+ goto cleanup;
+
+ /*Now, invoke the parser to parse the "@page production" */
+ cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+ status = cr_parser_parse_page (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ resultptr = &result;
+ status = cr_doc_handler_get_result (sac_handler,
+ (gpointer *) resultptr);
+
+ cleanup:
+
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ sac_handler = NULL ;
+ }
+ if (sac_handler) {
+ cr_doc_handler_unref (sac_handler);
+ sac_handler = NULL;
+ }
+ return result;
+}
+
+/**
+ * cr_statement_new_at_charset_rule:
+ *
+ *@a_charset: the string representing the charset.
+ *Note that the newly built instance of #CRStatement becomes
+ *the owner of a_charset. The caller must not free a_charset !!!.
+ *
+ *Creates a new instance of #CRStatement of type
+ *#CRAtCharsetRule.
+ *
+ *Returns the newly built instance of #CRStatement or NULL
+ *if an error arises.
+ */
+CRStatement *
+cr_statement_new_at_charset_rule (CRStyleSheet * a_sheet,
+ CRString * a_charset)
+{
+ CRStatement *result = NULL;
+
+ g_return_val_if_fail (a_charset, NULL);
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStatement));
+ result->type = AT_CHARSET_RULE_STMT;
+
+ result->kind.charset_rule = (CRAtCharsetRule *) g_try_malloc (sizeof (CRAtCharsetRule));
+
+ if (!result->kind.charset_rule) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (result->kind.charset_rule, 0, sizeof (CRAtCharsetRule));
+ result->kind.charset_rule->charset = a_charset;
+ cr_statement_set_parent_sheet (result, a_sheet);
+
+ return result;
+}
+
+/**
+ * cr_statement_at_charset_rule_parse_from_buf:
+ *
+ *@a_buf: the buffer to parse.
+ *@a_encoding: the character encoding of the buffer.
+ *
+ *Parses a buffer that contains an '\@charset' rule and
+ *creates an instance of #CRStatement of type AT_CHARSET_RULE_STMT.
+ *
+ *Returns the newly built instance of #CRStatement.
+ */
+CRStatement *
+cr_statement_at_charset_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ enum CRStatus status = CR_OK;
+ CRParser *parser = NULL;
+ CRStatement *result = NULL;
+ CRString *charset = NULL;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ if (!parser) {
+ cr_utils_trace_info ("Instantiation of the parser failed.");
+ goto cleanup;
+ }
+
+ /*Now, invoke the parser to parse the "@charset production" */
+ cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+ status = cr_parser_parse_charset (parser, &charset, NULL);
+ if (status != CR_OK || !charset)
+ goto cleanup;
+
+ result = cr_statement_new_at_charset_rule (NULL, charset);
+ if (result)
+ charset = NULL;
+
+ cleanup:
+
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+ if (charset) {
+ cr_string_destroy (charset);
+ }
+
+ return result;
+}
+
+/**
+ * cr_statement_new_at_font_face_rule:
+ *
+ *@a_font_decls: a list of instances of #CRDeclaration. Each declaration
+ *is actually a font declaration.
+ *
+ *Creates an instance of #CRStatement of type #CRAtFontFaceRule.
+ *
+ *Returns the newly built instance of #CRStatement.
+ */
+CRStatement *
+cr_statement_new_at_font_face_rule (CRStyleSheet * a_sheet,
+ CRDeclaration * a_font_decls)
+{
+ CRStatement *result = NULL;
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRStatement));
+ result->type = AT_FONT_FACE_RULE_STMT;
+
+ result->kind.font_face_rule = (CRAtFontFaceRule *) g_try_malloc
+ (sizeof (CRAtFontFaceRule));
+
+ if (!result->kind.font_face_rule) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (result->kind.font_face_rule, 0, sizeof (CRAtFontFaceRule));
+
+ result->kind.font_face_rule->decl_list = a_font_decls;
+ if (a_sheet)
+ cr_statement_set_parent_sheet (result, a_sheet);
+
+ return result;
+}
+
+/**
+ * cr_statement_font_face_rule_parse_from_buf:
+ *
+ *
+ *@a_buf: the buffer to parse.
+ *@a_encoding: the character encoding of a_buf.
+ *
+ *Parses a buffer that contains an "\@font-face" rule and builds
+ *an instance of #CRStatement of type AT_FONT_FACE_RULE_STMT out of it.
+ *
+ *Returns the newly built instance of #CRStatement in case of successufull
+ *parsing, NULL otherwise.
+ */
+CRStatement *
+cr_statement_font_face_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+ CRParser *parser = NULL;
+ CRDocHandler *sac_handler = NULL;
+ enum CRStatus status = CR_OK;
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ if (!parser)
+ goto cleanup;
+
+ sac_handler = cr_doc_handler_new ();
+ if (!sac_handler)
+ goto cleanup;
+
+ /*
+ *set sac callbacks here
+ */
+ sac_handler->start_font_face = parse_font_face_start_font_face_cb;
+ sac_handler->property = parse_font_face_property_cb;
+ sac_handler->end_font_face = parse_font_face_end_font_face_cb;
+ sac_handler->unrecoverable_error =
+ parse_font_face_unrecoverable_error_cb;
+
+ status = cr_parser_set_sac_handler (parser, sac_handler);
+ if (status != CR_OK)
+ goto cleanup;
+
+ /*
+ *cleanup spaces of comment that may be there before the real
+ *"@font-face" thing.
+ */
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_parse_font_face (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ resultptr = &result;
+ status = cr_doc_handler_get_result (sac_handler,
+ (gpointer *) resultptr);
+ if (status != CR_OK || !result)
+ goto cleanup;
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ sac_handler = NULL ;
+ }
+ if (sac_handler) {
+ cr_doc_handler_unref (sac_handler);
+ sac_handler = NULL;
+ }
+ return result;
+}
+
+/**
+ * cr_statement_set_parent_sheet:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@a_sheet: the sheet that contains the current statement.
+ *
+ *Sets the container stylesheet.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_set_parent_sheet (CRStatement * a_this, CRStyleSheet * a_sheet)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ a_this->parent_sheet = a_sheet;
+ return CR_OK;
+}
+
+/**
+ * cr_statement_get_parent_sheet:
+ *
+ *@a_this: the current #CRStatement.
+ *@a_sheet: out parameter. A pointer to the sheets that
+ *
+ *Gets the sheets that contains the current statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_get_parent_sheet (CRStatement * a_this, CRStyleSheet ** a_sheet)
+{
+ g_return_val_if_fail (a_this && a_sheet, CR_BAD_PARAM_ERROR);
+ *a_sheet = a_this->parent_sheet;
+ return CR_OK;
+}
+
+/**
+ * cr_statement_append:
+ *
+ *@a_this: the current instance of the statement list.
+ *@a_new: a_new the new instance of #CRStatement to append.
+ *
+ *Appends a new statement to the statement list.
+ *
+ *Returns the new list statement list, or NULL in case of failure.
+ */
+CRStatement *
+cr_statement_append (CRStatement * a_this, CRStatement * a_new)
+{
+ CRStatement *cur = NULL;
+
+ g_return_val_if_fail (a_new, NULL);
+
+ if (!a_this) {
+ return a_new;
+ }
+
+ /*walk forward in the current list to find the tail list element */
+ for (cur = a_this; cur && cur->next; cur = cur->next) ;
+
+ cur->next = a_new;
+ a_new->prev = cur;
+
+ return a_this;
+}
+
+/**
+ * cr_statement_prepend:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@a_new: the new statement to prepend.
+ *
+ *Prepends the an instance of #CRStatement to
+ *the current statement list.
+ *
+ *Returns the new list with the new statement prepended,
+ *or NULL in case of an error.
+ */
+CRStatement *
+cr_statement_prepend (CRStatement * a_this, CRStatement * a_new)
+{
+ CRStatement *cur = NULL;
+
+ g_return_val_if_fail (a_new, NULL);
+
+ if (!a_this)
+ return a_new;
+
+ a_new->next = a_this;
+ a_this->prev = a_new;
+
+ /*walk backward in the prepended list to find the head list element */
+ for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
+
+ return cur;
+}
+
+/**
+ * cr_statement_unlink:
+ *
+ *@a_this: the current statements list.
+ *@a_to_unlink: the statement to unlink from the list.
+ *
+ *Unlinks a statement from the statements list.
+ *
+ *Returns the new list where a_to_unlink has been unlinked
+ *from, or NULL in case of error.
+ */
+CRStatement *
+cr_statement_unlink (CRStatement * a_stmt)
+{
+ CRStatement *result = a_stmt;
+
+ g_return_val_if_fail (result, NULL);
+
+ /**
+ *Some sanity checks first
+ */
+ if (a_stmt->next) {
+ g_return_val_if_fail (a_stmt->next->prev == a_stmt, NULL);
+ }
+ if (a_stmt->prev) {
+ g_return_val_if_fail (a_stmt->prev->next == a_stmt, NULL);
+ }
+
+ /**
+ *Now, the real unlinking job.
+ */
+ if (a_stmt->next) {
+ a_stmt->next->prev = a_stmt->prev;
+ }
+ if (a_stmt->prev) {
+ a_stmt->prev->next = a_stmt->next;
+ }
+
+ if (a_stmt->parent_sheet
+ && a_stmt->parent_sheet->statements == a_stmt) {
+ a_stmt->parent_sheet->statements =
+ a_stmt->parent_sheet->statements->next;
+ }
+
+ a_stmt->next = NULL;
+ a_stmt->prev = NULL;
+ a_stmt->parent_sheet = NULL;
+
+ return result;
+}
+
+/**
+ * cr_statement_nr_rules:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *
+ *Gets the number of rules in the statement list;
+ *
+ *Returns number of rules in the statement list.
+ */
+gint
+cr_statement_nr_rules (CRStatement const * a_this)
+{
+ CRStatement const *cur = NULL;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, -1);
+
+ for (cur = a_this; cur; cur = cur->next)
+ nr++;
+ return nr;
+}
+
+/**
+ * cr_statement_get_from_list:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@itemnr: the index into the statement list.
+ *
+ *Use an index to get a CRStatement from the statement list.
+ *
+ *Returns CRStatement at position itemnr, if itemnr > number of statements - 1,
+ *it will return NULL.
+ */
+CRStatement *
+cr_statement_get_from_list (CRStatement * a_this, int itemnr)
+{
+ CRStatement *cur = NULL;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ for (cur = a_this; cur; cur = cur->next)
+ if (nr++ == itemnr)
+ return cur;
+ return NULL;
+}
+
+/**
+ * cr_statement_ruleset_set_sel_list:
+ *
+ *@a_this: the current ruleset statement.
+ *@a_sel_list: the selector list to set. Note
+ *that this function increments the ref count of a_sel_list.
+ *The sel list will be destroyed at the destruction of the
+ *current instance of #CRStatement.
+ *
+ *Sets a selector list to a ruleset statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_ruleset_set_sel_list (CRStatement * a_this,
+ CRSelector * a_sel_list)
+{
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT,
+ CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.ruleset->sel_list)
+ cr_selector_unref (a_this->kind.ruleset->sel_list);
+
+ a_this->kind.ruleset->sel_list = a_sel_list;
+
+ if (a_sel_list)
+ cr_selector_ref (a_sel_list);
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_ruleset_get_declarations:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@a_decl_list: out parameter. A pointer to the returned
+ *list of declaration. Must not be NULL.
+ *
+ *Gets a pointer to the list of declaration contained
+ *in the ruleset statement.
+ *
+ *Returns CR_OK upon successful completion, an error code if something
+ *bad happened.
+ */
+enum CRStatus
+cr_statement_ruleset_get_declarations (CRStatement * a_this,
+ CRDeclaration ** a_decl_list)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == RULESET_STMT
+ && a_this->kind.ruleset
+ && a_decl_list, CR_BAD_PARAM_ERROR);
+
+ *a_decl_list = a_this->kind.ruleset->decl_list;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_ruleset_get_sel_list:
+ *
+ *@a_this: the current ruleset statement.
+ *@a_list: out parameter. The returned selector list,
+ *if and only if the function returned CR_OK.
+ *
+ *Gets a pointer to the selector list contained in
+ *the current ruleset statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_ruleset_get_sel_list (CRStatement const * a_this, CRSelector ** a_list)
+{
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
+ && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
+
+ *a_list = a_this->kind.ruleset->sel_list;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_ruleset_set_decl_list:
+ *
+ *@a_this: the current ruleset statement.
+ *@a_list: the declaration list to be added to the current
+ *ruleset statement.
+ *
+ *Sets a declaration list to the current ruleset statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_ruleset_set_decl_list (CRStatement * a_this,
+ CRDeclaration * a_list)
+{
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
+ && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.ruleset->decl_list == a_list)
+ return CR_OK;
+
+ if (a_this->kind.ruleset->sel_list) {
+ cr_declaration_destroy (a_this->kind.ruleset->decl_list);
+ }
+
+ a_this->kind.ruleset->sel_list = NULL;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_ruleset_append_decl2:
+ *
+ *@a_this: the current statement.
+ *@a_prop: the property of the declaration.
+ *@a_value: the value of the declaration.
+ *
+ *Appends a declaration to the current ruleset statement.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_statement_ruleset_append_decl2 (CRStatement * a_this,
+ CRString * a_prop,
+ CRTerm * a_value)
+{
+ CRDeclaration *new_decls = NULL;
+
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
+ && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
+
+ new_decls = cr_declaration_append2
+ (a_this->kind.ruleset->decl_list,
+ a_prop, a_value);
+ g_return_val_if_fail (new_decls, CR_ERROR);
+ a_this->kind.ruleset->decl_list = new_decls;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_ruleset_append_decl:
+ *
+ *Appends a declaration to the current statement.
+ *
+ *@a_this: the current statement.
+ *@a_declaration: the declaration to append.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_statement_ruleset_append_decl (CRStatement * a_this,
+ CRDeclaration * a_decl)
+{
+ CRDeclaration *new_decls = NULL;
+
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
+ && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
+
+ new_decls = cr_declaration_append
+ (a_this->kind.ruleset->decl_list, a_decl);
+ g_return_val_if_fail (new_decls, CR_ERROR);
+ a_this->kind.ruleset->decl_list = new_decls;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_import_rule_set_imported_sheet:
+ *
+ *Sets a stylesheet to the current \@import rule.
+ *@a_this: the current \@import rule.
+ *@a_sheet: the stylesheet. The stylesheet is owned
+ *by the current instance of #CRStatement, that is, the
+ *stylesheet will be destroyed when the current instance
+ *of #CRStatement is destroyed.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_import_rule_set_imported_sheet (CRStatement * a_this,
+ CRStyleSheet * a_sheet)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_this->kind.import_rule,
+ CR_BAD_PARAM_ERROR);
+
+ a_this->kind.import_rule->sheet = a_sheet;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_import_rule_get_imported_sheet:
+ *
+ *@a_this: the current \@import rule statement.
+ *@a_sheet: out parameter. The returned stylesheet if and
+ *only if the function returns CR_OK.
+ *
+ *Gets the stylesheet contained by the \@import rule statement.
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_import_rule_get_imported_sheet (CRStatement * a_this,
+ CRStyleSheet ** a_sheet)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_this->kind.import_rule,
+ CR_BAD_PARAM_ERROR);
+ *a_sheet = a_this->kind.import_rule->sheet;
+ return CR_OK;
+
+}
+
+/**
+ * cr_statement_at_import_rule_set_url:
+ *
+ *@a_this: the current \@import rule statement.
+ *@a_url: the url to set.
+ *
+ *Sets an url to the current \@import rule statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_import_rule_set_url (CRStatement * a_this,
+ CRString * a_url)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_this->kind.import_rule,
+ CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.import_rule->url) {
+ cr_string_destroy (a_this->kind.import_rule->url);
+ }
+
+ a_this->kind.import_rule->url = a_url;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_import_rule_get_url:
+ *
+ *@a_this: the current \@import rule statement.
+ *@a_url: out parameter. The returned url if
+ *and only if the function returned CR_OK.
+ *
+ *Gets the url of the \@import rule statement.
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_import_rule_get_url (CRStatement const * a_this,
+ CRString ** a_url)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_this->kind.import_rule,
+ CR_BAD_PARAM_ERROR);
+
+ *a_url = a_this->kind.import_rule->url;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_media_nr_rules:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *
+ *Returns the number of rules in the media rule;
+ */
+int
+cr_statement_at_media_nr_rules (CRStatement const * a_this)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_MEDIA_RULE_STMT
+ && a_this->kind.media_rule, CR_BAD_PARAM_ERROR);
+
+ return cr_statement_nr_rules (a_this->kind.media_rule->rulesets);
+}
+
+/**
+ * cr_statement_at_media_get_from_list:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@itemnr: the index into the media rule list of rules.
+ *
+ *Use an index to get a CRStatement from the media rule list of rules.
+ *
+ *Returns CRStatement at position itemnr, if itemnr > number of rules - 1,
+ *it will return NULL.
+ */
+CRStatement *
+cr_statement_at_media_get_from_list (CRStatement * a_this, int itemnr)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_MEDIA_RULE_STMT
+ && a_this->kind.media_rule, NULL);
+
+ return cr_statement_get_from_list (a_this->kind.media_rule->rulesets,
+ itemnr);
+}
+
+/**
+ * cr_statement_at_page_rule_set_declarations:
+ *
+ *@a_this: the current \@page rule statement.
+ *@a_decl_list: the declaration list to add. Will be freed
+ *by the current instance of #CRStatement when it is destroyed.
+ *
+ *Sets a declaration list to the current \@page rule statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_page_rule_set_declarations (CRStatement * a_this,
+ CRDeclaration * a_decl_list)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_PAGE_RULE_STMT
+ && a_this->kind.page_rule, CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.page_rule->decl_list) {
+ cr_declaration_unref (a_this->kind.page_rule->decl_list);
+ }
+
+ a_this->kind.page_rule->decl_list = a_decl_list;
+
+ if (a_decl_list) {
+ cr_declaration_ref (a_decl_list);
+ }
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_page_rule_get_declarations:
+ *
+ *@a_this: the current \@page rule statement.
+ *@a_decl_list: out parameter. The returned declaration list.
+ *
+ *Gets the declaration list associated to the current \@page rule
+ *statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_page_rule_get_declarations (CRStatement * a_this,
+ CRDeclaration ** a_decl_list)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_PAGE_RULE_STMT
+ && a_this->kind.page_rule, CR_BAD_PARAM_ERROR);
+
+ *a_decl_list = a_this->kind.page_rule->decl_list;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_charset_rule_set_charset:
+ *
+ *
+ *@a_this: the current \@charset rule statement.
+ *@a_charset: the charset to set.
+ *
+ *Sets the charset of the current \@charset rule statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_charset_rule_set_charset (CRStatement * a_this,
+ CRString * a_charset)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_CHARSET_RULE_STMT
+ && a_this->kind.charset_rule,
+ CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.charset_rule->charset) {
+ cr_string_destroy (a_this->kind.charset_rule->charset);
+ }
+ a_this->kind.charset_rule->charset = a_charset;
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_charset_rule_get_charset:
+ *@a_this: the current \@charset rule statement.
+ *@a_charset: out parameter. The returned charset string if
+ *and only if the function returned CR_OK.
+ *
+ *Gets the charset string associated to the current
+ *\@charset rule statement.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_charset_rule_get_charset (CRStatement const * a_this,
+ CRString ** a_charset)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_CHARSET_RULE_STMT
+ && a_this->kind.charset_rule,
+ CR_BAD_PARAM_ERROR);
+
+ *a_charset = a_this->kind.charset_rule->charset;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_font_face_rule_set_decls:
+ *
+ *@a_this: the current \@font-face rule statement.
+ *@a_decls: the declarations list to set.
+ *
+ *Sets a declaration list to the current \@font-face rule statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_font_face_rule_set_decls (CRStatement * a_this,
+ CRDeclaration * a_decls)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_FONT_FACE_RULE_STMT
+ && a_this->kind.font_face_rule,
+ CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.font_face_rule->decl_list) {
+ cr_declaration_unref (a_this->kind.font_face_rule->decl_list);
+ }
+
+ a_this->kind.font_face_rule->decl_list = a_decls;
+ cr_declaration_ref (a_decls);
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_font_face_rule_get_decls:
+ *
+ *@a_this: the current \@font-face rule statement.
+ *@a_decls: out parameter. The returned declaration list if
+ *and only if this function returns CR_OK.
+ *
+ *Gets the declaration list associated to the current instance
+ *of \@font-face rule statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_font_face_rule_get_decls (CRStatement * a_this,
+ CRDeclaration ** a_decls)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_FONT_FACE_RULE_STMT
+ && a_this->kind.font_face_rule,
+ CR_BAD_PARAM_ERROR);
+
+ *a_decls = a_this->kind.font_face_rule->decl_list;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_font_face_rule_add_decl:
+ *
+ *@a_this: the current \@font-face rule statement.
+ *@a_prop: the property of the declaration.
+ *@a_value: the value of the declaration.
+ *
+ *Adds a declaration to the current \@font-face rule
+ *statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_font_face_rule_add_decl (CRStatement * a_this,
+ CRString * a_prop, CRTerm * a_value)
+{
+ CRDeclaration *decls = NULL;
+
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_FONT_FACE_RULE_STMT
+ && a_this->kind.font_face_rule,
+ CR_BAD_PARAM_ERROR);
+
+ decls = cr_declaration_append2
+ (a_this->kind.font_face_rule->decl_list,
+ a_prop, a_value);
+
+ g_return_val_if_fail (decls, CR_ERROR);
+
+ if (a_this->kind.font_face_rule->decl_list == NULL)
+ cr_declaration_ref (decls);
+
+ a_this->kind.font_face_rule->decl_list = decls;
+
+ return CR_OK;
+}
+
+
+/**
+ * cr_statement_to_string:
+ *
+ *@a_this: the current statement to serialize
+ *@a_indent: the number of white space of indentation.
+ *
+ *Serializes a css statement into a string
+ *
+ *Returns the serialized statement. Must be freed by the caller
+ *using g_free().
+ */
+gchar *
+cr_statement_to_string (CRStatement const * a_this, gulong a_indent)
+{
+ gchar *str = NULL ;
+
+ if (!a_this)
+ return NULL;
+
+ switch (a_this->type) {
+ case RULESET_STMT:
+ str = cr_statement_ruleset_to_string
+ (a_this, a_indent);
+ break;
+
+ case AT_FONT_FACE_RULE_STMT:
+ str = cr_statement_font_face_rule_to_string
+ (a_this, a_indent) ;
+ break;
+
+ case AT_CHARSET_RULE_STMT:
+ str = cr_statement_charset_to_string
+ (a_this, a_indent);
+ break;
+
+ case AT_PAGE_RULE_STMT:
+ str = cr_statement_at_page_rule_to_string
+ (a_this, a_indent);
+ break;
+
+ case AT_MEDIA_RULE_STMT:
+ str = cr_statement_media_rule_to_string
+ (a_this, a_indent);
+ break;
+
+ case AT_IMPORT_RULE_STMT:
+ str = cr_statement_import_rule_to_string
+ (a_this, a_indent);
+ break;
+
+ default:
+ cr_utils_trace_info ("Statement unrecognized");
+ break;
+ }
+ return str ;
+}
+
+gchar*
+cr_statement_list_to_string (CRStatement const *a_this, gulong a_indent)
+{
+ CRStatement const *cur_stmt = NULL ;
+ GString *stringue = NULL ;
+ gchar *str = NULL ;
+
+ g_return_val_if_fail (a_this, NULL) ;
+
+ stringue = g_string_new (NULL) ;
+ if (!stringue) {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ for (cur_stmt = a_this ; cur_stmt;
+ cur_stmt = cur_stmt->next) {
+ str = cr_statement_to_string (cur_stmt, a_indent) ;
+ if (str) {
+ if (!cur_stmt->prev) {
+ g_string_append (stringue, str) ;
+ } else {
+ g_string_append_printf
+ (stringue, "\n%s", str) ;
+ }
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+ str = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ return str ;
+}
+
+/**
+ * cr_statement_dump:
+ *
+ *@a_this: the current css2 statement.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of white space indentation characters.
+ *
+ *Dumps the css2 statement to a file.
+ */
+void
+cr_statement_dump (CRStatement const * a_this, FILE * a_fp, gulong a_indent)
+{
+ gchar *str = NULL ;
+
+ if (!a_this)
+ return;
+
+ str = cr_statement_to_string (a_this, a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s",str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ * cr_statement_dump_ruleset:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of indentation white spaces to add.
+ *
+ *Dumps a ruleset statement to a file.
+ */
+void
+cr_statement_dump_ruleset (CRStatement const * a_this, FILE * a_fp, glong a_indent)
+{
+ gchar *str = NULL;
+
+ g_return_if_fail (a_fp && a_this);
+ str = cr_statement_ruleset_to_string (a_this, a_indent);
+ if (str) {
+ fprintf (a_fp, "%s", str);
+ g_free (str);
+ str = NULL;
+ }
+}
+
+/**
+ * cr_statement_dump_font_face_rule:
+ *
+ *@a_this: the current instance of font face rule statement.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of white space indentation.
+ *
+ *Dumps a font face rule statement to a file.
+ */
+void
+cr_statement_dump_font_face_rule (CRStatement const * a_this, FILE * a_fp,
+ glong a_indent)
+{
+ gchar *str = NULL ;
+ g_return_if_fail (a_this
+ && a_this->type == AT_FONT_FACE_RULE_STMT);
+
+ str = cr_statement_font_face_rule_to_string (a_this,
+ a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ * cr_statement_dump_charset:
+ *
+ *@a_this: the current instance of the \@charset rule statement.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of indentation white spaces.
+ *
+ *Dumps an \@charset rule statement to a file.
+ */
+void
+cr_statement_dump_charset (CRStatement const * a_this, FILE * a_fp, gulong a_indent)
+{
+ gchar *str = NULL;
+
+ g_return_if_fail (a_this && a_this->type == AT_CHARSET_RULE_STMT);
+
+ str = cr_statement_charset_to_string (a_this,
+ a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+
+/**
+ * cr_statement_dump_page:
+ *
+ *@a_this: the statement to dump on stdout.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of indentation white spaces.
+ *
+ *Dumps an \@page rule statement on stdout.
+ */
+void
+cr_statement_dump_page (CRStatement const * a_this, FILE * a_fp, gulong a_indent)
+{
+ gchar *str = NULL;
+
+ g_return_if_fail (a_this
+ && a_this->type == AT_PAGE_RULE_STMT
+ && a_this->kind.page_rule);
+
+ str = cr_statement_at_page_rule_to_string (a_this, a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s", str);
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+
+/**
+ * cr_statement_dump_media_rule:
+ *
+ *@a_this: the statement to dump.
+ *@a_fp: the destination file pointer
+ *@a_indent: the number of white spaces indentation.
+ *
+ *Dumps an \@media rule statement to a file.
+ */
+void
+cr_statement_dump_media_rule (CRStatement const * a_this,
+ FILE * a_fp,
+ gulong a_indent)
+{
+ gchar *str = NULL ;
+ g_return_if_fail (a_this->type == AT_MEDIA_RULE_STMT);
+
+ str = cr_statement_media_rule_to_string (a_this, a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ * cr_statement_dump_import_rule:
+ *
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of white space indentations.
+ *
+ *Dumps an \@import rule statement to a file.
+ */
+void
+cr_statement_dump_import_rule (CRStatement const * a_this, FILE * a_fp,
+ gulong a_indent)
+{
+ gchar *str = NULL ;
+ g_return_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_fp
+ && a_this->kind.import_rule);
+
+ str = cr_statement_import_rule_to_string (a_this, a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ * cr_statement_destroy:
+ *
+ * @a_this: the current instance of #CRStatement.
+ *
+ *Destructor of #CRStatement.
+ */
+void
+cr_statement_destroy (CRStatement * a_this)
+{
+ CRStatement *cur = NULL;
+
+ g_return_if_fail (a_this);
+
+ /*go get the tail of the list */
+ for (cur = a_this; cur && cur->next; cur = cur->next) {
+ cr_statement_clear (cur);
+ }
+
+ if (cur)
+ cr_statement_clear (cur);
+
+ if (cur->prev == NULL) {
+ g_free (a_this);
+ return;
+ }
+
+ /*walk backward and free next element */
+ for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
+ if (cur->next) {
+ g_free (cur->next);
+ cur->next = NULL;
+ }
+ }
+
+ if (!cur)
+ return;
+
+ /*free the one remaining list */
+ if (cur->next) {
+ g_free (cur->next);
+ cur->next = NULL;
+ }
+
+ g_free (cur);
+ cur = NULL;
+}
diff --git a/src/3rdparty/libcroco/src/cr-statement.h b/src/3rdparty/libcroco/src/cr-statement.h
new file mode 100644
index 0000000..06538d0
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-statement.h
@@ -0,0 +1,440 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <stdio.h>
+#include "cr-utils.h"
+#include "cr-term.h"
+#include "cr-selector.h"
+#include "cr-declaration.h"
+
+#ifndef __CR_STATEMENT_H__
+#define __CR_STATEMENT_H__
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *Declaration of the #CRStatement class.
+ */
+
+/*
+ *forward declaration of CRStyleSheet which is defined in
+ *cr-stylesheet.h
+ */
+
+struct _CRStatement ;
+
+/*
+ *typedef struct _CRStatement CRStatement ;
+ *this is forward declared in
+ *cr-declaration.h already.
+ */
+
+struct _CRAtMediaRule ;
+typedef struct _CRAtMediaRule CRAtMediaRule ;
+
+typedef struct _CRRuleSet CRRuleSet ;
+
+/**
+ *The abstraction of a css ruleset.
+ *A ruleset is made of a list of selectors,
+ *followed by a list of declarations.
+ */
+struct _CRRuleSet
+{
+ /**A list of instances of #CRSimpeSel*/
+ CRSelector *sel_list ;
+
+ /**A list of instances of #CRDeclaration*/
+ CRDeclaration *decl_list ;
+
+ /**
+ *The parent media rule, or NULL if
+ *no parent media rule exists.
+ */
+ CRStatement *parent_media_rule ;
+} ;
+
+/*
+ *a forward declaration of CRStylesheet.
+ *CRStylesheet is actually declared in
+ *cr-stylesheet.h
+ */
+struct _CRStyleSheet ;
+typedef struct _CRStyleSheet CRStyleSheet;
+
+
+/**The \@import rule abstraction.*/
+typedef struct _CRAtImportRule CRAtImportRule ;
+struct _CRAtImportRule
+{
+ /**the url of the import rule*/
+ CRString *url ;
+
+ GList *media_list ;
+
+ /**
+ *the stylesheet fetched from the url, if any.
+ *this is not "owned" by #CRAtImportRule which means
+ *it is not destroyed by the destructor of #CRAtImportRule.
+ */
+ CRStyleSheet * sheet;
+};
+
+
+/**abstraction of an \@media rule*/
+struct _CRAtMediaRule
+{
+ GList *media_list ;
+ CRStatement *rulesets ;
+} ;
+
+
+typedef struct _CRAtPageRule CRAtPageRule ;
+/**The \@page rule abstraction*/
+struct _CRAtPageRule
+{
+ /**a list of instances of #CRDeclaration*/
+ CRDeclaration *decl_list ;
+
+ /**page selector. Is a pseudo selector*/
+ CRString *name ;
+ CRString *pseudo ;
+} ;
+
+/**The \@charset rule abstraction*/
+typedef struct _CRAtCharsetRule CRAtCharsetRule ;
+struct _CRAtCharsetRule
+{
+ CRString * charset ;
+};
+
+/**The abstraction of the \@font-face rule.*/
+typedef struct _CRAtFontFaceRule CRAtFontFaceRule ;
+struct _CRAtFontFaceRule
+{
+ /*a list of instanaces of #CRDeclaration*/
+ CRDeclaration *decl_list ;
+} ;
+
+
+/**
+ *The possible types of css2 statements.
+ */
+enum CRStatementType
+{
+ /**
+ *A generic css at-rule
+ *each unknown at-rule will
+ *be of this type.
+ */
+
+ /**A css at-rule*/
+ AT_RULE_STMT = 0,
+
+ /*A css ruleset*/
+ RULESET_STMT,
+
+ /**A css2 import rule*/
+ AT_IMPORT_RULE_STMT,
+
+ /**A css2 media rule*/
+ AT_MEDIA_RULE_STMT,
+
+ /**A css2 page rule*/
+ AT_PAGE_RULE_STMT,
+
+ /**A css2 charset rule*/
+ AT_CHARSET_RULE_STMT,
+
+ /**A css2 font face rule*/
+ AT_FONT_FACE_RULE_STMT
+} ;
+
+
+/**
+ *The abstraction of css statement as defined
+ *in the chapter 4 and appendix D.1 of the css2 spec.
+ *A statement is actually a double chained list of
+ *statements.A statement can be a ruleset, an \@import
+ *rule, an \@page rule etc ...
+ */
+struct _CRStatement
+{
+ /**
+ *The type of the statement.
+ */
+ enum CRStatementType type ;
+
+ union
+ {
+ CRRuleSet *ruleset ;
+ CRAtImportRule *import_rule ;
+ CRAtMediaRule *media_rule ;
+ CRAtPageRule *page_rule ;
+ CRAtCharsetRule *charset_rule ;
+ CRAtFontFaceRule *font_face_rule ;
+ } kind ;
+
+ /*
+ *the specificity of the selector
+ *that matched this statement.
+ *This is only used by the cascading
+ *order determination algorithm.
+ */
+ gulong specificity ;
+
+ /*
+ *the style sheet that contains
+ *this css statement.
+ */
+ CRStyleSheet *parent_sheet ;
+ CRStatement *next ;
+ CRStatement *prev ;
+
+ CRParsingLocation location ;
+
+ /**
+ *a custom pointer usable by
+ *applications that use libcroco.
+ *libcroco itself will never modify
+ *this pointer.
+ */
+ gpointer app_data ;
+
+ /**
+ *a custom pointer used
+ *by the upper layers of libcroco.
+ *application should never use this
+ *pointer.
+ */
+ gpointer croco_data ;
+
+} ;
+
+
+gboolean
+cr_statement_does_buf_parses_against_core (const guchar *a_buf,
+ enum CREncoding a_encoding) ;
+CRStatement *
+cr_statement_parse_from_buf (const guchar *a_buf,
+ enum CREncoding a_encoding) ;
+CRStatement*
+cr_statement_new_ruleset (CRStyleSheet *a_sheet,
+ CRSelector *a_sel_list,
+ CRDeclaration *a_decl_list,
+ CRStatement *a_media_rule) ;
+CRStatement *
+cr_statement_ruleset_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_enc) ;
+
+CRStatement*
+cr_statement_new_at_import_rule (CRStyleSheet *a_container_sheet,
+ CRString *a_url,
+ GList *a_media_list,
+ CRStyleSheet *a_imported_sheet) ;
+
+CRStatement *
+cr_statement_at_import_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding) ;
+
+CRStatement *
+cr_statement_new_at_media_rule (CRStyleSheet *a_sheet,
+ CRStatement *a_ruleset,
+ GList *a_media) ;
+CRStatement *
+cr_statement_at_media_rule_parse_from_buf (const guchar *a_buf,
+ enum CREncoding a_enc) ;
+
+CRStatement *
+cr_statement_new_at_charset_rule (CRStyleSheet *a_sheet,
+ CRString *a_charset) ;
+CRStatement *
+cr_statement_at_charset_rule_parse_from_buf (const guchar *a_buf,
+ enum CREncoding a_encoding);
+
+
+CRStatement *
+cr_statement_new_at_font_face_rule (CRStyleSheet *a_sheet,
+ CRDeclaration *a_font_decls) ;
+CRStatement *
+cr_statement_font_face_rule_parse_from_buf (const guchar *a_buf,
+ enum CREncoding a_encoding) ;
+
+CRStatement *
+cr_statement_new_at_page_rule (CRStyleSheet *a_sheet,
+ CRDeclaration *a_decl_list,
+ CRString *a_name,
+ CRString *a_pseudo) ;
+CRStatement *
+cr_statement_at_page_rule_parse_from_buf (const guchar *a_buf,
+ enum CREncoding a_encoding) ;
+
+enum CRStatus
+cr_statement_set_parent_sheet (CRStatement *a_this,
+ CRStyleSheet *a_sheet) ;
+
+enum CRStatus
+cr_statement_get_parent_sheet (CRStatement *a_this,
+ CRStyleSheet **a_sheet) ;
+
+CRStatement *
+cr_statement_append (CRStatement *a_this,
+ CRStatement *a_new) ;
+
+CRStatement*
+cr_statement_prepend (CRStatement *a_this,
+ CRStatement *a_new) ;
+
+CRStatement *
+cr_statement_unlink (CRStatement *a_stmt) ;
+
+enum CRStatus
+cr_statement_ruleset_set_sel_list (CRStatement *a_this,
+ CRSelector *a_sel_list) ;
+
+enum CRStatus
+cr_statement_ruleset_get_sel_list (CRStatement const *a_this,
+ CRSelector **a_list) ;
+
+enum CRStatus
+cr_statement_ruleset_set_decl_list (CRStatement *a_this,
+ CRDeclaration *a_list) ;
+
+enum CRStatus
+cr_statement_ruleset_get_declarations (CRStatement *a_this,
+ CRDeclaration **a_decl_list) ;
+
+enum CRStatus
+cr_statement_ruleset_append_decl2 (CRStatement *a_this,
+ CRString *a_prop, CRTerm *a_value) ;
+
+enum CRStatus
+cr_statement_ruleset_append_decl (CRStatement *a_this,
+ CRDeclaration *a_decl) ;
+
+enum CRStatus
+cr_statement_at_import_rule_set_imported_sheet (CRStatement *a_this,
+ CRStyleSheet *a_sheet) ;
+
+enum CRStatus
+cr_statement_at_import_rule_get_imported_sheet (CRStatement *a_this,
+ CRStyleSheet **a_sheet) ;
+
+enum CRStatus
+cr_statement_at_import_rule_set_url (CRStatement *a_this,
+ CRString *a_url) ;
+
+enum CRStatus
+cr_statement_at_import_rule_get_url (CRStatement const *a_this,
+ CRString **a_url) ;
+
+gint
+cr_statement_at_media_nr_rules (CRStatement const *a_this) ;
+
+CRStatement *
+cr_statement_at_media_get_from_list (CRStatement *a_this, int itemnr) ;
+
+enum CRStatus
+cr_statement_at_page_rule_set_sel (CRStatement *a_this,
+ CRSelector *a_sel) ;
+
+enum CRStatus
+cr_statement_at_page_rule_get_sel (CRStatement const *a_this,
+ CRSelector **a_sel) ;
+
+enum CRStatus
+cr_statement_at_page_rule_set_declarations (CRStatement *a_this,
+ CRDeclaration *a_decl_list) ;
+
+enum CRStatus
+cr_statement_at_page_rule_get_declarations (CRStatement *a_this,
+ CRDeclaration **a_decl_list) ;
+
+enum CRStatus
+cr_statement_at_charset_rule_set_charset (CRStatement *a_this,
+ CRString *a_charset) ;
+
+enum CRStatus
+cr_statement_at_charset_rule_get_charset (CRStatement const *a_this,
+ CRString **a_charset) ;
+
+enum CRStatus
+cr_statement_at_font_face_rule_set_decls (CRStatement *a_this,
+ CRDeclaration *a_decls) ;
+
+enum CRStatus
+cr_statement_at_font_face_rule_get_decls (CRStatement *a_this,
+ CRDeclaration **a_decls) ;
+
+enum CRStatus
+cr_statement_at_font_face_rule_add_decl (CRStatement *a_this,
+ CRString *a_prop,
+ CRTerm *a_value) ;
+
+gchar *
+cr_statement_to_string (CRStatement const * a_this, gulong a_indent) ;
+
+gchar*
+cr_statement_list_to_string (CRStatement const *a_this, gulong a_indent) ;
+
+void
+cr_statement_dump (CRStatement const *a_this, FILE *a_fp, gulong a_indent) ;
+
+void
+cr_statement_dump_ruleset (CRStatement const * a_this, FILE * a_fp,
+ glong a_indent) ;
+
+void
+cr_statement_dump_font_face_rule (CRStatement const * a_this,
+ FILE * a_fp,
+ glong a_indent) ;
+
+void
+cr_statement_dump_page (CRStatement const * a_this, FILE * a_fp,
+ gulong a_indent) ;
+
+
+void
+cr_statement_dump_media_rule (CRStatement const * a_this,
+ FILE * a_fp,
+ gulong a_indent) ;
+
+void
+cr_statement_dump_import_rule (CRStatement const * a_this, FILE * a_fp,
+ gulong a_indent) ;
+void
+cr_statement_dump_charset (CRStatement const * a_this, FILE * a_fp,
+ gulong a_indent) ;
+gint
+cr_statement_nr_rules (CRStatement const *a_this) ;
+
+CRStatement *
+cr_statement_get_from_list (CRStatement *a_this, int itemnr) ;
+
+void
+cr_statement_destroy (CRStatement *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_STATEMENT_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-string.c b/src/3rdparty/libcroco/src/cr-string.c
new file mode 100644
index 0000000..ec5840e
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-string.c
@@ -0,0 +1,170 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-string.h"
+
+/**
+ *Instantiates a #CRString
+ *@return the newly instantiated #CRString
+ *Must be freed with cr_string_destroy().
+ */
+CRString *
+cr_string_new (void)
+{
+ CRString *result = NULL ;
+
+ result = (CRString *) g_try_malloc (sizeof (CRString)) ;
+ if (!result) {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ memset (result, 0, sizeof (CRString)) ;
+ result->stryng = g_string_new (NULL) ;
+ return result ;
+}
+
+/**
+ *Instantiate a string and initialise it to
+ *a_string.
+ *@param a_string the initial string
+ *@return the newly instantiated string.
+ */
+CRString *
+cr_string_new_from_string (const gchar * a_string)
+{
+ CRString *result = NULL ;
+
+ result = cr_string_new () ;
+ if (!result) {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ if (a_string)
+ g_string_append (result->stryng, a_string) ;
+ return result ;
+}
+
+/**
+ *Instantiates a #CRString from an instance of GString.
+ *@param a_string the input string that will be copied into
+ *the newly instantiated #CRString
+ *@return the newly instantiated #CRString.
+ */
+CRString *
+cr_string_new_from_gstring (GString const *a_string)
+{
+ CRString *result = NULL ;
+
+ result = cr_string_new () ;
+ if (!result) {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ if (a_string) {
+ g_string_append_len (result->stryng,
+ a_string->str,
+ a_string->len);
+
+ }
+ return result ;
+}
+
+CRString *
+cr_string_dup (CRString const *a_this)
+{
+ CRString *result = NULL ;
+ g_return_val_if_fail (a_this, NULL) ;
+
+ result = cr_string_new_from_gstring (a_this->stryng) ;
+ if (!result) {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ cr_parsing_location_copy (&result->location,
+ &a_this->location) ;
+ return result ;
+}
+
+gchar *
+cr_string_dup2 (CRString const *a_this)
+{
+ gchar *result = NULL ;
+
+ g_return_val_if_fail (a_this, NULL) ;
+
+ if (a_this
+ && a_this->stryng
+ && a_this->stryng->str) {
+ result = g_strndup (a_this->stryng->str,
+ a_this->stryng->len) ;
+ }
+ return result ;
+}
+
+/**
+ *Returns a pointer to the internal raw NULL terminated string
+ *of the current instance of #CRString.
+ *@param a_this the current instance of #CRString
+ */
+const gchar *
+cr_string_peek_raw_str (CRString const *a_this)
+{
+ g_return_val_if_fail (a_this, NULL) ;
+
+ if (a_this->stryng && a_this->stryng->str)
+ return a_this->stryng->str ;
+ return NULL ;
+}
+
+/**
+ *Returns the length of the internal raw NULL terminated
+ *string of the current instance of #CRString.
+ *@param a_this the current instance of #CRString.
+ *@return the len of the internal raw NULL termninated string,
+ *of -1 if no length can be returned.
+ */
+gint
+cr_string_peek_raw_str_len (CRString const *a_this)
+{
+ g_return_val_if_fail (a_this && a_this->stryng,
+ -1) ;
+ return a_this->stryng->len ;
+}
+
+/**
+ *@param a_this the #CRString to destroy.
+ */
+void
+cr_string_destroy (CRString *a_this)
+{
+ if (!a_this) {
+ return;
+ }
+
+ if (a_this->stryng) {
+ g_string_free (a_this->stryng, TRUE) ;
+ a_this->stryng = NULL ;
+ }
+ g_free (a_this) ;
+}
diff --git a/src/3rdparty/libcroco/src/cr-string.h b/src/3rdparty/libcroco/src/cr-string.h
new file mode 100644
index 0000000..2700f0e
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-string.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information.
+ */
+
+/**
+ *@file
+ *Declaration file of the #CRString class.
+ */
+
+#ifndef __CR_STRING_H__
+#define __CR_STRING_H__
+
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+typedef struct _CRString CRString ;
+
+/**
+ *This is a ship implementation of string based on GString.
+ *Actually, the aim of CRString is to store the parsing location
+ *(line,column,byte offset) at which a given string has been parsed
+ *in the input CSS.
+ *So this class has a gstring field of type GString that users can
+ *freely manipulate, and also a CRParginLocation type where the
+ *parsing location is store. If you don't want to deal with parsing
+ *location stuffs, then use GString instead. If we were in C++ for example,
+ *CRString would just inherit GString and just add accessors to
+ *the CRParsingLocation data ... but we are not and we still have
+ *to provide the parsing location information.
+ */
+struct _CRString {
+ /**
+ *The GString where all the string
+ *operation happen.
+ */
+ GString *stryng ;
+ /**
+ *The parsing location storage area.
+ */
+ CRParsingLocation location ;
+} ;
+
+CRString * cr_string_new (void) ;
+
+CRString *cr_string_new_from_string (const gchar * a_string) ;
+CRString * cr_string_new_from_gstring (GString const *a_string) ;
+CRString *cr_string_dup (CRString const *a_this) ;
+gchar *cr_string_dup2 (CRString const *a_this) ;
+const gchar *cr_string_peek_raw_str (CRString const *a_this) ;
+gint cr_string_peek_raw_str_len (CRString const *a_this) ;
+void cr_string_destroy (CRString *a_this) ;
+
+G_END_DECLS
+
+#endif
diff --git a/src/3rdparty/libcroco/src/cr-style.c b/src/3rdparty/libcroco/src/cr-style.c
new file mode 100644
index 0000000..9653c50
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-style.c
@@ -0,0 +1,2852 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of
+ * the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * see COPYRIGHTS file for copyright information
+ */
+
+#include <string.h>
+#include "cr-style.h"
+
+/**
+ *@file
+ *The definition of the #CRStyle class.
+ */
+
+/**
+ *A property ID.
+ *Each supported css property has an ID which is
+ *an entry into a property "population" jump table.
+ *each entry of the property population jump table
+ *contains code to transform the literal form of
+ *a property value into a strongly typed value.
+ */
+enum CRPropertyID {
+ PROP_ID_NOT_KNOWN = 0,
+ PROP_ID_PADDING_TOP,
+ PROP_ID_PADDING_RIGHT,
+ PROP_ID_PADDING_BOTTOM,
+ PROP_ID_PADDING_LEFT,
+ PROP_ID_PADDING,
+ PROP_ID_BORDER_TOP_WIDTH,
+ PROP_ID_BORDER_RIGHT_WIDTH,
+ PROP_ID_BORDER_BOTTOM_WIDTH,
+ PROP_ID_BORDER_LEFT_WIDTH,
+ PROP_ID_BORDER_WIDTH,
+ PROP_ID_BORDER_TOP_STYLE,
+ PROP_ID_BORDER_RIGHT_STYLE,
+ PROP_ID_BORDER_BOTTOM_STYLE,
+ PROP_ID_BORDER_LEFT_STYLE,
+ PROP_ID_BORDER_STYLE,
+ PROP_ID_BORDER_TOP_COLOR,
+ PROP_ID_BORDER_RIGHT_COLOR,
+ PROP_ID_BORDER_BOTTOM_COLOR,
+ PROP_ID_BORDER_LEFT_COLOR,
+ PROP_ID_BORDER_TOP,
+ PROP_ID_BORDER_RIGHT,
+ PROP_ID_BORDER_BOTTOM,
+ PROP_ID_BORDER_LEFT,
+ PROP_ID_BORDER,
+ PROP_ID_MARGIN_TOP,
+ PROP_ID_MARGIN_RIGHT,
+ PROP_ID_MARGIN_BOTTOM,
+ PROP_ID_MARGIN_LEFT,
+ PROP_ID_MARGIN,
+ PROP_ID_DISPLAY,
+ PROP_ID_POSITION,
+ PROP_ID_TOP,
+ PROP_ID_RIGHT,
+ PROP_ID_BOTTOM,
+ PROP_ID_LEFT,
+ PROP_ID_FLOAT,
+ PROP_ID_WIDTH,
+ PROP_ID_COLOR,
+ PROP_ID_BACKGROUND_COLOR,
+ PROP_ID_FONT_FAMILY,
+ PROP_ID_FONT_SIZE,
+ PROP_ID_FONT_STYLE,
+ PROP_ID_FONT_WEIGHT,
+ PROP_ID_WHITE_SPACE,
+ /*should be the last one. */
+ NB_PROP_IDS
+};
+
+typedef struct _CRPropertyDesc CRPropertyDesc;
+
+struct _CRPropertyDesc {
+ const gchar *name;
+ enum CRPropertyID prop_id;
+};
+
+static CRPropertyDesc gv_prop_table[] = {
+ {"padding-top", PROP_ID_PADDING_TOP},
+ {"padding-right", PROP_ID_PADDING_RIGHT},
+ {"padding-bottom", PROP_ID_PADDING_BOTTOM},
+ {"padding-left", PROP_ID_PADDING_LEFT},
+ {"padding", PROP_ID_PADDING},
+ {"border-top-width", PROP_ID_BORDER_TOP_WIDTH},
+ {"border-right-width", PROP_ID_BORDER_RIGHT_WIDTH},
+ {"border-bottom-width", PROP_ID_BORDER_BOTTOM_WIDTH},
+ {"border-left-width", PROP_ID_BORDER_LEFT_WIDTH},
+ {"border-width", PROP_ID_BORDER_WIDTH},
+ {"border-top-style", PROP_ID_BORDER_TOP_STYLE},
+ {"border-right-style", PROP_ID_BORDER_RIGHT_STYLE},
+ {"border-bottom-style", PROP_ID_BORDER_BOTTOM_STYLE},
+ {"border-left-style", PROP_ID_BORDER_LEFT_STYLE},
+ {"border-style", PROP_ID_BORDER_STYLE},
+ {"border-top", PROP_ID_BORDER_TOP},
+ {"border-right", PROP_ID_BORDER_RIGHT},
+ {"border-bottom", PROP_ID_BORDER_BOTTOM},
+ {"border-left", PROP_ID_BORDER_LEFT},
+ {"border", PROP_ID_BORDER},
+ {"margin-top", PROP_ID_MARGIN_TOP},
+ {"margin-right", PROP_ID_MARGIN_RIGHT},
+ {"margin-bottom", PROP_ID_MARGIN_BOTTOM},
+ {"margin-left", PROP_ID_MARGIN_LEFT},
+ {"margin", PROP_ID_MARGIN},
+ {"display", PROP_ID_DISPLAY},
+ {"position", PROP_ID_POSITION},
+ {"top", PROP_ID_TOP},
+ {"right", PROP_ID_RIGHT},
+ {"bottom", PROP_ID_BOTTOM},
+ {"left", PROP_ID_LEFT},
+ {"float", PROP_ID_FLOAT},
+ {"width", PROP_ID_WIDTH},
+ {"color", PROP_ID_COLOR},
+ {"border-top-color", PROP_ID_BORDER_TOP_COLOR},
+ {"border-right-color", PROP_ID_BORDER_RIGHT_COLOR},
+ {"border-bottom-color", PROP_ID_BORDER_BOTTOM_COLOR},
+ {"border-left-color", PROP_ID_BORDER_LEFT_COLOR},
+ {"background-color", PROP_ID_BACKGROUND_COLOR},
+ {"font-family", PROP_ID_FONT_FAMILY},
+ {"font-size", PROP_ID_FONT_SIZE},
+ {"font-style", PROP_ID_FONT_STYLE},
+ {"font-weight", PROP_ID_FONT_WEIGHT},
+ {"white-space", PROP_ID_WHITE_SPACE},
+ /*must be the last one */
+ {NULL, (enum CRPropertyID) 0}
+};
+
+/**
+ *A the key/value pair of this hash table
+ *are:
+ *key => name of the css property found in gv_prop_table
+ *value => matching property id found in gv_prop_table.
+ *So this hash table is here just to retrieval of a property id
+ *from a property name.
+ */
+static GHashTable *gv_prop_hash = NULL;
+
+/**
+ *incremented by each new instance of #CRStyle
+ *and decremented at the it destroy time.
+ *When this reaches zero, gv_prop_hash is destroyed.
+ */
+static gulong gv_prop_hash_ref_count = 0;
+
+struct CRNumPropEnumDumpInfo {
+ enum CRNumProp code;
+ const gchar *str;
+};
+
+static struct CRNumPropEnumDumpInfo gv_num_props_dump_infos[] = {
+ {NUM_PROP_TOP, "top"},
+ {NUM_PROP_RIGHT, "right"},
+ {NUM_PROP_BOTTOM, "bottom"},
+ {NUM_PROP_LEFT, "left"},
+ {NUM_PROP_PADDING_TOP, "padding-top"},
+ {NUM_PROP_PADDING_RIGHT, "padding-right"},
+ {NUM_PROP_PADDING_BOTTOM, "padding-bottom"},
+ {NUM_PROP_PADDING_LEFT, "padding-left"},
+ {NUM_PROP_BORDER_TOP, "border-top"},
+ {NUM_PROP_BORDER_RIGHT, "border-right"},
+ {NUM_PROP_BORDER_BOTTOM, "border-bottom"},
+ {NUM_PROP_BORDER_LEFT, "border-left"},
+ {NUM_PROP_MARGIN_TOP, "margin-top"},
+ {NUM_PROP_MARGIN_RIGHT, "margin-right"},
+ {NUM_PROP_MARGIN_BOTTOM, "margin-bottom"},
+ {NUM_PROP_MARGIN_LEFT, "margin-left"},
+ {NUM_PROP_WIDTH, "width"},
+ {(enum CRNumProp) 0, NULL}
+};
+
+struct CRRgbPropEnumDumpInfo {
+ enum CRRgbProp code;
+ const gchar *str;
+};
+
+static struct CRRgbPropEnumDumpInfo gv_rgb_props_dump_infos[] = {
+ {RGB_PROP_BORDER_TOP_COLOR, "border-top-color"},
+ {RGB_PROP_BORDER_RIGHT_COLOR, "border-right-color"},
+ {RGB_PROP_BORDER_BOTTOM_COLOR, "bottom-color"},
+ {RGB_PROP_BORDER_LEFT_COLOR, "left-color"},
+ {RGB_PROP_COLOR, "color"},
+ {RGB_PROP_BACKGROUND_COLOR, "background-color"},
+ {(enum CRRgbProp) 0, NULL}
+};
+
+struct CRBorderStylePropEnumDumpInfo {
+ enum CRBorderStyleProp code;
+ const gchar *str;
+
+};
+
+static struct CRBorderStylePropEnumDumpInfo gv_border_style_props_dump_infos[]
+ = {
+ {BORDER_STYLE_PROP_TOP, "border-style-top"},
+ {BORDER_STYLE_PROP_RIGHT, "border-style-right"},
+ {BORDER_STYLE_PROP_BOTTOM, "boder-style-bottom"},
+ {BORDER_STYLE_PROP_LEFT, "border-style-left"},
+ {(enum CRBorderStyleProp) 0, NULL}
+};
+
+static enum CRStatus
+ cr_style_init_properties (void);
+
+enum CRDirection {
+ DIR_TOP = 0,
+ DIR_RIGHT,
+ DIR_BOTTOM,
+ DIR_LEFT,
+
+ /*must be the last one */
+ NB_DIRS
+};
+
+static const gchar *num_prop_code_to_string (enum CRNumProp a_code);
+
+static const gchar *rgb_prop_code_to_string (enum CRRgbProp a_code);
+
+static const gchar *border_style_prop_code_to_string (enum CRBorderStyleProp
+ a_code);
+
+static enum CRStatus
+set_prop_padding_x_from_value (CRStyle * a_style,
+ CRTerm * a_value, enum CRDirection a_dir);
+
+static enum CRStatus
+set_prop_border_x_width_from_value (CRStyle * a_style,
+ CRTerm * a_value,
+ enum CRDirection a_dir);
+static enum CRStatus
+set_prop_border_width_from_value (CRStyle *a_style,
+ CRTerm *a_value) ;
+
+static enum CRStatus
+set_prop_border_x_style_from_value (CRStyle * a_style,
+ CRTerm * a_value,
+ enum CRDirection a_dir);
+static enum CRStatus
+set_prop_border_style_from_value (CRStyle *a_style,
+ CRTerm *a_value) ;
+
+static enum CRStatus
+set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir);
+
+static enum CRStatus
+set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir);
+
+static enum CRStatus
+set_prop_float (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_width (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_color (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_background_color (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir);
+
+static enum CRStatus
+set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir);
+
+static enum CRStatus
+set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+init_style_font_size_field (CRStyle * a_style);
+
+static enum CRStatus
+set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static const gchar *
+num_prop_code_to_string (enum CRNumProp a_code)
+{
+ guint len = sizeof (gv_num_props_dump_infos) /
+ sizeof (struct CRNumPropEnumDumpInfo);
+ if (a_code >= len) {
+ cr_utils_trace_info ("A field has been added "
+ "to 'enum CRNumProp' and no matching"
+ " entry has been "
+ "added to gv_num_prop_dump_infos table.\n"
+ "Please add the missing matching entry");
+ return NULL;
+ }
+ if (gv_num_props_dump_infos[a_code].code != a_code) {
+ cr_utils_trace_info ("mismatch between the order of fields in"
+ " 'enum CRNumProp' and "
+ "the order of entries in "
+ "the gv_num_prop_dump_infos table");
+ return NULL;
+ }
+ return gv_num_props_dump_infos[a_code].str;
+}
+
+static const gchar *
+rgb_prop_code_to_string (enum CRRgbProp a_code)
+{
+ guint len = sizeof (gv_rgb_props_dump_infos) /
+ sizeof (struct CRRgbPropEnumDumpInfo);
+
+ if (a_code >= len) {
+ cr_utils_trace_info ("A field has been added "
+ "to 'enum CRRgbProp' and no matching"
+ " entry has been "
+ "added to gv_rgb_prop_dump_infos table.\n"
+ "Please add the missing matching entry");
+ return NULL;
+ }
+ if (gv_rgb_props_dump_infos[a_code].code != a_code) {
+ cr_utils_trace_info ("mismatch between the order of fields in"
+ " 'enum CRRgbProp' and "
+ "the order of entries in "
+ "the gv_rgb_props_dump_infos table");
+ return NULL;
+ }
+ return gv_rgb_props_dump_infos[a_code].str;
+}
+
+static const gchar *
+border_style_prop_code_to_string (enum CRBorderStyleProp a_code)
+{
+ guint len = sizeof (gv_border_style_props_dump_infos) /
+ sizeof (struct CRBorderStylePropEnumDumpInfo);
+
+ if (a_code >= len) {
+ cr_utils_trace_info ("A field has been added "
+ "to 'enum CRBorderStyleProp' and no matching"
+ " entry has been "
+ "added to gv_border_style_prop_dump_infos table.\n"
+ "Please add the missing matching entry");
+ return NULL;
+ }
+ if (gv_border_style_props_dump_infos[a_code].code != a_code) {
+ cr_utils_trace_info ("mismatch between the order of fields in"
+ " 'enum CRBorderStyleProp' and "
+ "the order of entries in "
+ "the gv_border_style_props_dump_infos table");
+ return NULL;
+ }
+ return gv_border_style_props_dump_infos[a_code].str;
+}
+
+static enum CRStatus
+cr_style_init_properties (void)
+{
+
+ if (!gv_prop_hash) {
+ gulong i = 0;
+
+ gv_prop_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ if (!gv_prop_hash) {
+ cr_utils_trace_info ("Out of memory");
+ return CR_ERROR;
+ }
+
+ /*load gv_prop_hash from gv_prop_table */
+ for (i = 0; gv_prop_table[i].name; i++) {
+ g_hash_table_insert
+ (gv_prop_hash,
+ (gpointer) gv_prop_table[i].name,
+ GINT_TO_POINTER (gv_prop_table[i].prop_id));
+ }
+ }
+
+ return CR_OK;
+}
+
+static enum CRPropertyID
+cr_style_get_prop_id (const guchar * a_prop)
+{
+ gpointer *raw_id = NULL;
+
+ if (!gv_prop_hash) {
+ cr_style_init_properties ();
+ }
+
+ raw_id = (gpointer *) g_hash_table_lookup (gv_prop_hash, a_prop);
+ if (!raw_id) {
+ return PROP_ID_NOT_KNOWN;
+ }
+ return (enum CRPropertyID)GPOINTER_TO_INT (raw_id);
+}
+
+static enum CRStatus
+set_prop_padding_x_from_value (CRStyle * a_style,
+ CRTerm * a_value, enum CRDirection a_dir)
+{
+ enum CRStatus status = CR_OK;
+ CRNum *num_val = NULL;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ if (a_value->type != TERM_NUMBER && a_value->type != TERM_IDENT)
+ return CR_BAD_PARAM_ERROR;
+
+ switch (a_dir) {
+ case DIR_TOP:
+ num_val = &a_style->num_props[NUM_PROP_PADDING_TOP].sv;
+ break;
+
+ case DIR_RIGHT:
+ num_val = &a_style->num_props[NUM_PROP_PADDING_RIGHT].sv;
+ break;
+
+ case DIR_BOTTOM:
+ num_val = &a_style->num_props[NUM_PROP_PADDING_BOTTOM].sv;
+ break;
+
+ case DIR_LEFT:
+ num_val = &a_style->num_props[NUM_PROP_PADDING_LEFT].sv;
+ break;
+
+ default:
+ return CR_BAD_PARAM_ERROR;
+ }
+
+ if (a_value->type == TERM_IDENT) {
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strncmp ((const char *) "inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ status = cr_num_set (num_val, 0.0, NUM_INHERIT);
+ return CR_OK;
+ } else
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ g_return_val_if_fail (a_value->type == TERM_NUMBER
+ && a_value->content.num, CR_UNKNOWN_TYPE_ERROR);
+
+ switch (a_value->content.num->type) {
+ case NUM_LENGTH_EM:
+ case NUM_LENGTH_EX:
+ case NUM_LENGTH_PX:
+ case NUM_LENGTH_IN:
+ case NUM_LENGTH_CM:
+ case NUM_LENGTH_MM:
+ case NUM_LENGTH_PT:
+ case NUM_LENGTH_PC:
+ case NUM_PERCENTAGE:
+ status = cr_num_copy (num_val, a_value->content.num);
+ break;
+ default:
+ status = CR_UNKNOWN_TYPE_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_border_x_width_from_value (CRStyle * a_style,
+ CRTerm * a_value,
+ enum CRDirection a_dir)
+{
+ enum CRStatus status = CR_OK;
+ CRNum *num_val = NULL;
+
+ g_return_val_if_fail (a_value && a_style, CR_BAD_PARAM_ERROR);
+
+ switch (a_dir) {
+ case DIR_TOP:
+ num_val = &a_style->num_props[NUM_PROP_BORDER_TOP].sv;
+ break;
+
+ case DIR_RIGHT:
+ num_val = &a_style->num_props[NUM_PROP_BORDER_RIGHT].sv;
+ break;
+
+ case DIR_BOTTOM:
+ num_val = &a_style->num_props[NUM_PROP_BORDER_BOTTOM].sv;
+ break;
+
+ case DIR_LEFT:
+ num_val = &a_style->num_props[NUM_PROP_BORDER_LEFT].sv;
+ break;
+
+ default:
+ return CR_BAD_PARAM_ERROR;
+ break;
+ }
+
+ if (a_value->type == TERM_IDENT) {
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strncmp ("thin",
+ a_value->content.str->stryng->str,
+ sizeof ("thin")-1)) {
+ cr_num_set (num_val, BORDER_THIN,
+ NUM_LENGTH_PX);
+ } else if (!strncmp
+ ("medium",
+ a_value->content.str->stryng->str,
+ sizeof ("medium")-1)) {
+ cr_num_set (num_val, BORDER_MEDIUM,
+ NUM_LENGTH_PX);
+ } else if (!strncmp ("thick",
+ a_value->content.str->stryng->str,
+ sizeof ("thick")-1)) {
+ cr_num_set (num_val, BORDER_THICK,
+ NUM_LENGTH_PX);
+ } else {
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+ }
+ } else if (a_value->type == TERM_NUMBER) {
+ if (a_value->content.num) {
+ cr_num_copy (num_val, a_value->content.num);
+ }
+ } else if (a_value->type != TERM_NUMBER
+ || a_value->content.num == NULL) {
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_border_width_from_value (CRStyle *a_style,
+ CRTerm *a_value)
+{
+ CRTerm *cur_term = NULL ;
+ int dir;
+
+ g_return_val_if_fail (a_style && a_value,
+ CR_BAD_PARAM_ERROR) ;
+ cur_term = a_value ;
+
+ if (!cur_term)
+ return CR_ERROR ;
+
+ for (dir = (int) DIR_TOP ; dir < (int)NB_DIRS ; dir++) {
+ enum CRDirection direction = (enum CRDirection)dir;
+ set_prop_border_x_width_from_value (a_style,
+ cur_term,
+ direction) ;
+ }
+
+ cur_term = cur_term->next ;
+ if (!cur_term)
+ return CR_OK ;
+ set_prop_border_x_width_from_value (a_style, cur_term,
+ DIR_RIGHT) ;
+ set_prop_border_x_width_from_value (a_style, cur_term,
+ DIR_LEFT) ;
+
+ cur_term = cur_term->next ;
+ if (!cur_term)
+ return CR_OK ;
+ set_prop_border_x_width_from_value (a_style, cur_term,
+ DIR_BOTTOM) ;
+
+ cur_term = cur_term->next ;
+ if (!cur_term)
+ return CR_OK ;
+ set_prop_border_x_width_from_value (a_style, cur_term,
+ DIR_LEFT) ;
+
+ return CR_OK ;
+}
+
+static enum CRStatus
+set_prop_border_x_style_from_value (CRStyle * a_style,
+ CRTerm * a_value, enum CRDirection a_dir)
+{
+ enum CRStatus status = CR_OK;
+ enum CRBorderStyle *border_style_ptr = NULL;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_dir) {
+ case DIR_TOP:
+ border_style_ptr = &a_style->
+ border_style_props[BORDER_STYLE_PROP_TOP];
+ break;
+
+ case DIR_RIGHT:
+ border_style_ptr =
+ &a_style->border_style_props[BORDER_STYLE_PROP_RIGHT];
+ break;
+
+ case DIR_BOTTOM:
+ border_style_ptr = &a_style->
+ border_style_props[BORDER_STYLE_PROP_BOTTOM];
+ break;
+
+ case DIR_LEFT:
+ border_style_ptr = &a_style->
+ border_style_props[BORDER_STYLE_PROP_LEFT];
+ break;
+
+ default:
+ break;
+ }
+
+ if (a_value->type != TERM_IDENT || !a_value->content.str) {
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ if (!strncmp ("none",
+ a_value->content.str->stryng->str,
+ sizeof ("none")-1)) {
+ *border_style_ptr = BORDER_STYLE_NONE;
+ } else if (!strncmp ("hidden",
+ a_value->content.str->stryng->str,
+ sizeof ("hidden")-1)) {
+ *border_style_ptr = BORDER_STYLE_HIDDEN;
+ } else if (!strncmp ("dotted",
+ a_value->content.str->stryng->str,
+ sizeof ("dotted")-1)) {
+ *border_style_ptr = BORDER_STYLE_DOTTED;
+ } else if (!strncmp ("dashed",
+ a_value->content.str->stryng->str, sizeof ("dashed")-1)) {
+ *border_style_ptr = BORDER_STYLE_DASHED;
+ } else if (!strncmp ("solid",
+ a_value->content.str->stryng->str, sizeof ("solid")-1)) {
+ *border_style_ptr = BORDER_STYLE_SOLID;
+ } else if (!strncmp ("double",
+ a_value->content.str->stryng->str, sizeof ("double")-1)) {
+ *border_style_ptr = BORDER_STYLE_DOUBLE;
+ } else if (!strncmp ("groove",
+ a_value->content.str->stryng->str, sizeof ("groove")-1)) {
+ *border_style_ptr = BORDER_STYLE_GROOVE;
+ } else if (!strncmp ("ridge",
+ a_value->content.str->stryng->str,
+ sizeof ("ridge")-1)) {
+ *border_style_ptr = BORDER_STYLE_RIDGE;
+ } else if (!strncmp ("inset",
+ a_value->content.str->stryng->str,
+ sizeof ("inset")-1)) {
+ *border_style_ptr = BORDER_STYLE_INSET;
+ } else if (!strncmp ("outset",
+ a_value->content.str->stryng->str,
+ sizeof ("outset")-1)) {
+ *border_style_ptr = BORDER_STYLE_OUTSET;
+ } else if (!strncmp ("inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ *border_style_ptr = BORDER_STYLE_INHERIT;
+ } else {
+ status = CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_border_style_from_value (CRStyle *a_style,
+ CRTerm *a_value)
+{
+ CRTerm *cur_term = NULL ;
+ int dir;
+
+ g_return_val_if_fail (a_style && a_value,
+ CR_BAD_PARAM_ERROR) ;
+
+ cur_term = a_value ;
+ if (!cur_term || cur_term->type != TERM_IDENT) {
+ return CR_ERROR ;
+ }
+
+ for (dir = (int)DIR_TOP ; dir < (int)NB_DIRS ; dir++) {
+ enum CRDirection direction = (enum CRDirection)dir;
+ set_prop_border_x_style_from_value (a_style,
+ cur_term,
+ direction) ;
+ }
+
+ cur_term = cur_term->next ;
+ if (!cur_term || cur_term->type != TERM_IDENT) {
+ return CR_OK ;
+ }
+
+ set_prop_border_x_style_from_value (a_style, cur_term,
+ DIR_RIGHT) ;
+ set_prop_border_x_style_from_value (a_style, cur_term,
+ DIR_LEFT) ;
+
+ cur_term = cur_term->next ;
+ if (!cur_term || cur_term->type != TERM_IDENT) {
+ return CR_OK ;
+ }
+ set_prop_border_x_style_from_value (a_style, cur_term,
+ DIR_BOTTOM) ;
+
+ cur_term = cur_term->next ;
+ if (!cur_term || cur_term->type != TERM_IDENT) {
+ return CR_OK ;
+ }
+ set_prop_border_x_style_from_value (a_style, cur_term,
+ DIR_LEFT) ;
+ return CR_OK ;
+}
+
+static enum CRStatus
+set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir)
+{
+ enum CRStatus status = CR_OK;
+ CRNum *num_val = NULL;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_dir) {
+ case DIR_TOP:
+ num_val = &a_style->num_props[NUM_PROP_MARGIN_TOP].sv;
+ break;
+
+ case DIR_RIGHT:
+ num_val = &a_style->num_props[NUM_PROP_MARGIN_RIGHT].sv;
+ break;
+
+ case DIR_BOTTOM:
+ num_val = &a_style->num_props[NUM_PROP_MARGIN_BOTTOM].sv;
+ break;
+
+ case DIR_LEFT:
+ num_val = &a_style->num_props[NUM_PROP_MARGIN_LEFT].sv;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "inherit")) {
+ status = cr_num_set (num_val, 0.0, NUM_INHERIT);
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && !strcmp (a_value->content.str->stryng->str,
+ "auto")) {
+ status = cr_num_set (num_val, 0.0, NUM_AUTO);
+ } else {
+ status = CR_UNKNOWN_TYPE_ERROR;
+ }
+ break ;
+
+ case TERM_NUMBER:
+ status = cr_num_copy (num_val, a_value->content.num);
+ break;
+
+ default:
+ status = CR_UNKNOWN_TYPE_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+struct CRPropDisplayValPair {
+ const gchar *prop_name;
+ enum CRDisplayType type;
+};
+
+static enum CRStatus
+set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ static const struct CRPropDisplayValPair disp_vals_map[] = {
+ {"none", DISPLAY_NONE},
+ {"inline", DISPLAY_INLINE},
+ {"block", DISPLAY_BLOCK},
+ {"run-in", DISPLAY_RUN_IN},
+ {"compact", DISPLAY_COMPACT},
+ {"marker", DISPLAY_MARKER},
+ {"table", DISPLAY_TABLE},
+ {"inline-table", DISPLAY_INLINE_TABLE},
+ {"table-row-group", DISPLAY_TABLE_ROW_GROUP},
+ {"table-header-group", DISPLAY_TABLE_HEADER_GROUP},
+ {"table-footer-group", DISPLAY_TABLE_FOOTER_GROUP},
+ {"table-row", DISPLAY_TABLE_ROW},
+ {"table-column-group", DISPLAY_TABLE_COLUMN_GROUP},
+ {"table-column", DISPLAY_TABLE_COLUMN},
+ {"table-cell", DISPLAY_TABLE_CELL},
+ {"table-caption", DISPLAY_TABLE_CAPTION},
+ {"inherit", DISPLAY_INHERIT},
+ {NULL, DISPLAY_NONE}
+ };
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ {
+ int i = 0;
+
+ if (!a_value->content.str
+ || !a_value->content.str->stryng
+ || !a_value->content.str->stryng->str)
+ break;
+
+ for (i = 0; disp_vals_map[i].prop_name; i++) {
+ if (!strncmp
+ (disp_vals_map[i].prop_name,
+ a_value->content.str->stryng->str,
+ strlen (disp_vals_map[i].prop_name))) {
+ a_style->display =
+ disp_vals_map[i].type;
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return CR_OK;
+}
+
+struct CRPropPositionValPair {
+ const gchar *name;
+ enum CRPositionType type;
+};
+
+static enum CRStatus
+set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_UNKNOWN_PROP_VAL_ERROR;
+ static const struct CRPropPositionValPair position_vals_map[] = {
+ {"static", POSITION_STATIC},
+ {"relative", POSITION_RELATIVE},
+ {"absolute", POSITION_ABSOLUTE},
+ {"fixed", POSITION_FIXED},
+ {"inherit", POSITION_INHERIT},
+ {NULL, POSITION_STATIC}
+ /*must alwas be the last one */
+ };
+
+ g_return_val_if_fail (a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ {
+ int i = 0;
+
+ if (!a_value->content.str
+ || !a_value->content.str->stryng
+ || !a_value->content.str->stryng->str)
+ break;
+
+ for (i = 0; position_vals_map[i].name; i++) {
+ if (!strncmp (position_vals_map[i].name,
+ a_value->content.str->stryng->str,
+ strlen (position_vals_map[i].
+ name))) {
+ a_style->position =
+ position_vals_map[i].type;
+ status = CR_OK;
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir)
+{
+ CRNum *box_offset = NULL;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ if (!(a_value->type == TERM_NUMBER)
+ && !(a_value->type == TERM_IDENT)) {
+ return CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+
+ switch (a_dir) {
+ case DIR_TOP:
+ box_offset = &a_style->num_props[NUM_PROP_TOP].sv;
+ break;
+
+ case DIR_RIGHT:
+ box_offset = &a_style->num_props[NUM_PROP_RIGHT].sv;
+ break;
+
+ case DIR_BOTTOM:
+ box_offset = &a_style->num_props[NUM_PROP_BOTTOM].sv;
+ break;
+ case DIR_LEFT:
+ box_offset = &a_style->num_props[NUM_PROP_LEFT].sv;
+ break;
+
+ default:
+ break;
+ }
+
+ box_offset->type = NUM_AUTO;
+
+ if (a_value->type == TERM_NUMBER && a_value->content.num) {
+ cr_num_copy (box_offset, a_value->content.num);
+ } else if (a_value->type == TERM_IDENT
+ && a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strncmp ("inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ cr_num_set (box_offset, 0.0, NUM_INHERIT);
+ } else if (!strncmp ("auto",
+ a_value->content.str->stryng->str,
+ sizeof ("auto")-1)) {
+ box_offset->type = NUM_AUTO;
+ }
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_float (CRStyle * a_style, CRTerm * a_value)
+{
+ g_return_val_if_fail (a_style && a_value,
+ CR_BAD_PARAM_ERROR);
+
+ /*the default float type as specified by the css2 spec */
+ a_style->float_type = FLOAT_NONE;
+
+ if (a_value->type != TERM_IDENT
+ || !a_value->content.str
+ || !a_value->content.str->stryng
+ || !a_value->content.str->stryng->str) {
+ /*unknown type, the float type is set to it's default value */
+ return CR_OK;
+ }
+
+ if (!strncmp ("none",
+ a_value->content.str->stryng->str,
+ sizeof ("none")-1)) {
+ a_style->float_type = FLOAT_NONE;
+ } else if (!strncmp ("left",
+ a_value->content.str->stryng->str,
+ sizeof ("left")-1)) {
+ a_style->float_type = FLOAT_LEFT;
+ } else if (!strncmp ("right",
+ a_value->content.str->stryng->str,
+ sizeof ("right")-1)) {
+ a_style->float_type = FLOAT_RIGHT;
+ } else if (!strncmp ("inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ a_style->float_type = FLOAT_INHERIT;
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_width (CRStyle * a_style, CRTerm * a_value)
+{
+ CRNum *width = NULL;
+ g_return_val_if_fail (a_style
+ && a_value,
+ CR_BAD_PARAM_ERROR);
+
+ width = &a_style->num_props[NUM_PROP_WIDTH].sv;
+ cr_num_set (width, 0.0, NUM_AUTO);
+
+ if (a_value->type == TERM_IDENT) {
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strncmp ("auto",
+ a_value->content.str->stryng->str,
+ sizeof ("auto")-1)) {
+ cr_num_set (width, 0.0, NUM_AUTO);
+ } else if (!strncmp ("inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ cr_num_set (width, 0.0, NUM_INHERIT);
+ }
+ }
+ } else if (a_value->type == TERM_NUMBER) {
+ if (a_value->content.num) {
+ cr_num_copy (&a_style->num_props[NUM_PROP_WIDTH].sv,
+ a_value->content.num);
+ }
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_color (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+ CRRgb *a_rgb = &a_style->rgb_props[RGB_PROP_COLOR].sv;
+
+ g_return_val_if_fail (a_style
+ && a_value, CR_BAD_PARAM_ERROR);
+
+ status = cr_rgb_set_from_term (a_rgb, a_value);
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_background_color (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+ CRRgb *rgb = &a_style->rgb_props[RGB_PROP_BACKGROUND_COLOR].sv;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ status = cr_rgb_set_from_term (rgb, a_value);
+ return status;
+}
+
+/**
+ *Sets border-top-color, border-right-color,
+ *border-bottom-color or border-left-color properties
+ *in the style structure. The value is taken from a
+ *css2 term of type IDENT or RGB.
+ *@param a_style the style structure to set.
+ *@param a_value the css2 term to take the color information from.
+ *@param a_dir the direction (TOP, LEFT, RIGHT, or BOTTOM).
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir)
+{
+ CRRgb *rgb_color = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_dir) {
+ case DIR_TOP:
+ rgb_color = &a_style->rgb_props[RGB_PROP_BORDER_TOP_COLOR].sv;
+ break;
+
+ case DIR_RIGHT:
+ rgb_color =
+ &a_style->rgb_props[RGB_PROP_BORDER_RIGHT_COLOR].sv;
+ break;
+
+ case DIR_BOTTOM:
+ rgb_color =
+ &a_style->rgb_props[RGB_PROP_BORDER_BOTTOM_COLOR].sv;
+ break;
+
+ case DIR_LEFT:
+ rgb_color =
+ &a_style->rgb_props[RGB_PROP_BORDER_LEFT_COLOR].sv;
+ break;
+
+ default:
+ cr_utils_trace_info ("unknown DIR type");
+ return CR_BAD_PARAM_ERROR;
+ }
+
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+
+ if (a_value->type == TERM_IDENT) {
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ status = cr_rgb_set_from_name
+ (rgb_color,
+ (const guchar *) a_value->content.str->stryng->str);
+
+ }
+ if (status != CR_OK) {
+ cr_rgb_set_from_name (rgb_color, (const guchar *) "black");
+ }
+ } else if (a_value->type == TERM_RGB) {
+ if (a_value->content.rgb) {
+ status = cr_rgb_set_from_rgb
+ (rgb_color, a_value->content.rgb);
+ }
+ }
+ return status;
+}
+
+static enum CRStatus
+set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir)
+{
+ CRTerm *cur_term = NULL;
+
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ for (cur_term = a_value;
+ cur_term;
+ cur_term = cur_term->next) {
+ status = set_prop_border_x_width_from_value (a_style,
+ cur_term, a_dir);
+
+ if (status != CR_OK) {
+ status = set_prop_border_x_style_from_value
+ (a_style, cur_term, a_dir);
+ }
+ if (status != CR_OK) {
+ status = set_prop_border_x_color_from_value
+ (a_style, cur_term, a_dir);
+ }
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ int dir;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ for (dir = 0; dir < (int)NB_DIRS; dir++) {
+ set_prop_border_x_from_value (a_style,
+ a_value,
+ (enum CRDirection)dir);
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ CRTerm *cur_term = NULL;
+ int dir;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ cur_term = a_value;
+
+ /*filter the eventual non NUMBER terms some user can have written here*/
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_ERROR ;
+
+ for (dir = 0; dir < (int)NB_DIRS; dir++) {
+ set_prop_padding_x_from_value (a_style,
+ cur_term, (enum CRDirection)dir);
+ }
+ cur_term = cur_term->next;
+
+ /*filter non NUMBER terms that some users can have written here...*/
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ /*the user can have just written padding: 1px*/
+ if (!cur_term)
+ return CR_OK;
+
+ set_prop_padding_x_from_value (a_style, cur_term, DIR_RIGHT);
+ set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT);
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_OK;
+
+ set_prop_padding_x_from_value (a_style, cur_term, DIR_BOTTOM);
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_OK;
+ status = set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT);
+ return status;
+}
+
+static enum CRStatus
+set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ CRTerm *cur_term = NULL;
+ int dir;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ cur_term = a_value;
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+
+ if (!cur_term)
+ return CR_OK;
+
+ for (dir = 0; dir < (int)NB_DIRS; dir++) {
+ set_prop_margin_x_from_value(a_style,
+ cur_term, (enum CRDirection)dir);
+ }
+ cur_term = cur_term->next;
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_OK;
+
+ set_prop_margin_x_from_value (a_style, cur_term, DIR_RIGHT);
+ set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT);
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_OK;
+
+ set_prop_margin_x_from_value (a_style, cur_term, DIR_BOTTOM);
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_OK;
+
+ status = set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT);
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ CRTerm *cur_term = NULL;
+ CRFontFamily *font_family = NULL,
+ *cur_ff = NULL,
+ *cur_ff2 = NULL;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ if (a_value->type == TERM_IDENT &&
+ a_value->content.str &&
+ a_value->content.str->stryng &&
+ a_value->content.str->stryng->str &&
+ !strcmp ("inherit", a_value->content.str->stryng->str))
+ {
+ font_family = cr_font_family_new (FONT_FAMILY_INHERIT, NULL);
+ goto out;
+ }
+
+ for (cur_term = a_value; cur_term; cur_term = cur_term->next) {
+ switch (cur_term->type) {
+ case TERM_IDENT:
+ {
+ enum CRFontFamilyType font_type;
+
+ if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str
+ && !strcmp
+ (cur_term->content.str->stryng->str,
+ "sans-serif")) {
+ font_type = FONT_FAMILY_SANS_SERIF;
+ } else if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str
+ && !strcmp
+ (cur_term->content.str->stryng->str,
+ "serif")) {
+ font_type = FONT_FAMILY_SERIF;
+ } else if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str
+ && !strcmp (cur_term->content.str->stryng->str,
+ "cursive")) {
+ font_type = FONT_FAMILY_CURSIVE;
+ } else if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str
+ && !strcmp (cur_term->content.str->stryng->str,
+ "fantasy")) {
+ font_type = FONT_FAMILY_FANTASY;
+ } else if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str
+ && !strcmp (cur_term->content.str->stryng->str,
+ "monospace")) {
+ font_type = FONT_FAMILY_MONOSPACE;
+ } else {
+ /*
+ *unknown property value.
+ *ignore it.
+ */
+ continue;
+ }
+
+ cur_ff = cr_font_family_new (font_type, NULL);
+ }
+ break;
+
+ case TERM_STRING:
+ {
+ if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str) {
+ cur_ff = cr_font_family_new
+ (FONT_FAMILY_NON_GENERIC,
+ (guchar *) cur_term->content.str->stryng->str);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ cur_ff2 = cr_font_family_append (font_family, cur_ff);
+ if (cur_ff2) {
+ font_family = cur_ff2;
+ }
+ }
+
+ out:
+ if (font_family) {
+ if (a_style->font_family) {
+ cr_font_family_destroy (a_style->font_family);
+ a_style->font_family = NULL ;
+ }
+ a_style->font_family = font_family;
+ font_family = NULL ;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+init_style_font_size_field (CRStyle * a_style)
+{
+ g_return_val_if_fail (a_style, CR_BAD_PARAM_ERROR);
+
+ memset (&a_style->font_size, 0,
+ sizeof (CRFontSizeVal)) ;
+ /*
+ if (!a_style->font_size) {
+ a_style->font_size = cr_font_size_new ();
+ if (!a_style->font_size) {
+ return CR_INSTANCIATION_FAILED_ERROR;
+ }
+ } else {
+ cr_font_size_clear (a_style->font_size);
+ }
+ */
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "xx-small")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_XX_SMALL;
+
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "x-small")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_X_SMALL;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "small")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_SMALL;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str, "medium")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_MEDIUM;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "large")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_LARGE;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "x-large")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_X_LARGE;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "xx-large")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_XX_LARGE;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "larger")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type = RELATIVE_FONT_SIZE;
+ a_style->font_size.sv.value.relative = FONT_SIZE_LARGER;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "smaller")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type = RELATIVE_FONT_SIZE;
+ a_style->font_size.sv.value.relative =
+ FONT_SIZE_SMALLER;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str, "inherit")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+ a_style->font_size.sv.type = INHERITED_FONT_SIZE;
+
+ } else {
+ cr_utils_trace_info ("Unknown value of font-size") ;
+ status = init_style_font_size_field (a_style);
+ return CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+ break;
+
+ case TERM_NUMBER:
+ if (a_value->content.num) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type = ABSOLUTE_FONT_SIZE;
+ cr_num_copy (&a_style->font_size.sv.value.absolute,
+ a_value->content.num) ;
+ }
+ break;
+
+ default:
+ status = init_style_font_size_field (a_style);
+ return CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strcmp (a_value->content.str->stryng->str, "normal")) {
+ a_style->font_style = FONT_STYLE_NORMAL;
+ } else if (!strcmp
+ (a_value->content.str->stryng->str,
+ "italic")) {
+ a_style->font_style = FONT_STYLE_ITALIC;
+ } else if (!strcmp
+ (a_value->content.str->stryng->str,
+ "oblique")) {
+ a_style->font_style = FONT_STYLE_OBLIQUE;
+ } else if (!strcmp
+ (a_value->content.str->stryng->str,
+ "inherit")) {
+ a_style->font_style = FONT_STYLE_INHERIT;
+ } else {
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+ }
+ break;
+
+ default:
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strcmp (a_value->content.str->stryng->str,
+ "normal")) {
+ a_style->font_weight = FONT_WEIGHT_NORMAL;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "bold")) {
+ a_style->font_weight = FONT_WEIGHT_BOLD;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "bolder")) {
+ a_style->font_weight = FONT_WEIGHT_BOLDER;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "lighter")) {
+ a_style->font_weight = FONT_WEIGHT_LIGHTER;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "inherit")) {
+ a_style->font_weight = FONT_WEIGHT_INHERIT;
+
+ } else {
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+
+ }
+ break;
+
+ case TERM_NUMBER:
+ if (a_value->content.num
+ && (a_value->content.num->type == NUM_GENERIC
+ || a_value->content.num->type == NUM_AUTO)) {
+ if (a_value->content.num->val <= 150) {
+ a_style->font_weight = FONT_WEIGHT_100;
+ } else if (a_value->content.num->val <= 250) {
+ a_style->font_weight = FONT_WEIGHT_200;
+ } else if (a_value->content.num->val <= 350) {
+ a_style->font_weight = FONT_WEIGHT_300;
+ } else if (a_value->content.num->val <= 450) {
+ a_style->font_weight = FONT_WEIGHT_400;
+ } else if (a_value->content.num->val <= 550) {
+ a_style->font_weight = FONT_WEIGHT_500;
+ } else if (a_value->content.num->val <= 650) {
+ a_style->font_weight = FONT_WEIGHT_600;
+ } else if (a_value->content.num->val <= 750) {
+ a_style->font_weight = FONT_WEIGHT_700;
+ } else if (a_value->content.num->val <= 850) {
+ a_style->font_weight = FONT_WEIGHT_800;
+ } else {
+ a_style->font_weight = FONT_WEIGHT_900;
+ }
+ }
+ break;
+
+ default:
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_white_space_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ if (a_value->content.str && a_value->content.str->stryng) {
+ if (!strcmp (a_value->content.str->stryng->str, "normal")) {
+ a_style->white_space = WHITE_SPACE_NORMAL;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "pre")) {
+ a_style->white_space = WHITE_SPACE_PRE;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "nowrap")) {
+ a_style->white_space = WHITE_SPACE_NOWRAP;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "inherit")) {
+ a_style->white_space = WHITE_SPACE_INHERIT;
+ } else {
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+ }
+ break;
+ default:
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+/******************
+ *Public methods
+ ******************/
+
+/**
+ *Default constructor of #CRStyle.
+ *@param a_set_props_to_initial_values if TRUE, the style properties
+ *will be set to the default values. Only the style properties of the
+ *root box should be set to their initial values.
+ *Otherwise, the style values are set to their default value.
+ *Read the CSS2 spec, chapters 6.1.1 to 6.2.
+ */
+CRStyle *
+cr_style_new (gboolean a_set_props_to_initial_values)
+{
+ CRStyle *result = NULL;
+
+ result = (CRStyle *) g_try_malloc (sizeof (CRStyle));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRStyle));
+ gv_prop_hash_ref_count++;
+
+ if (a_set_props_to_initial_values == TRUE) {
+ cr_style_set_props_to_initial_values (result);
+ } else {
+ cr_style_set_props_to_default_values (result);
+ }
+
+ return result;
+}
+
+/**
+ *Sets the style properties to their default values according to the css2 spec
+ * i.e inherit if the property is inherited, its initial value otherwise.
+ *@param a_this the current instance of #CRStyle.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_style_set_props_to_default_values (CRStyle * a_this)
+{
+ glong i = 0;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ for (i = 0; i < NB_NUM_PROPS; i++)
+ {
+ switch (i)
+ {
+ case NUM_PROP_WIDTH:
+ case NUM_PROP_TOP:
+ case NUM_PROP_RIGHT:
+ case NUM_PROP_BOTTOM:
+ case NUM_PROP_LEFT:
+ cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO);
+ break;
+
+ case NUM_PROP_PADDING_TOP:
+ case NUM_PROP_PADDING_RIGHT:
+ case NUM_PROP_PADDING_BOTTOM:
+ case NUM_PROP_PADDING_LEFT:
+ case NUM_PROP_BORDER_TOP:
+ case NUM_PROP_BORDER_RIGHT:
+ case NUM_PROP_BORDER_BOTTOM:
+ case NUM_PROP_BORDER_LEFT:
+ case NUM_PROP_MARGIN_TOP:
+ case NUM_PROP_MARGIN_RIGHT:
+ case NUM_PROP_MARGIN_BOTTOM:
+ case NUM_PROP_MARGIN_LEFT:
+ cr_num_set (&a_this->num_props[i].sv,
+ 0, NUM_LENGTH_PX);
+ break;
+
+ default:
+ cr_utils_trace_info ("Unknown property");
+ break;
+ }
+ }
+
+ for (i = 0; i < NB_RGB_PROPS; i++) {
+
+ switch (i) {
+ /*default foreground color is black */
+ case RGB_PROP_COLOR:
+ /*
+ *REVIEW: color is inherited and the default value is
+ *ua dependent.
+ */
+ cr_rgb_set_to_inherit (&a_this->rgb_props[i].sv,
+ TRUE) ;
+ break;
+
+ /*default background color is white */
+ case RGB_PROP_BACKGROUND_COLOR:
+ /* TODO: the default value should be transparent */
+ cr_rgb_set (&a_this->rgb_props[i].sv,
+ 255, 255, 255, FALSE);
+ cr_rgb_set_to_transparent (&a_this->rgb_props[i].sv,
+ TRUE) ;
+ break;
+
+ default:
+ /*
+ *TODO: for BORDER_COLOR the initial value should
+ * be the same as COLOR
+ */
+ cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0,
+ FALSE);
+ break;
+ }
+ }
+
+ for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
+ a_this->border_style_props[i] = BORDER_STYLE_NONE;
+ }
+
+ a_this->display = DISPLAY_INLINE;
+ a_this->position = POSITION_STATIC;
+ a_this->float_type = FLOAT_NONE;
+ a_this->parent_style = NULL;
+ a_this->font_style = FONT_STYLE_INHERIT;
+ a_this->font_variant = FONT_VARIANT_INHERIT;
+ a_this->font_weight = FONT_WEIGHT_INHERIT;
+ a_this->font_family = NULL;
+
+ cr_font_size_set_to_inherit (&a_this->font_size.sv) ;
+ cr_font_size_clear (&a_this->font_size.cv) ;
+ cr_font_size_clear (&a_this->font_size.av) ;
+
+ /* To make the inheritance resolution possible and efficient */
+ a_this->inherited_props_resolved = FALSE ;
+ return CR_OK;
+}
+
+/**
+ *Sets the style properties to their initial value according to the css2 spec.
+ *This function should be used to initialize the style of the root element
+ *of an xml tree.
+ *Some properties are user agent dependent like font-family, and
+ *are not initialized, read the spec to make you renderer compliant.
+ *@param a_this the current instance of #CRStyle.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_style_set_props_to_initial_values (CRStyle *a_this)
+{
+ glong i = 0;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ for (i = 0; i < NB_NUM_PROPS; i++) {
+ switch (i) {
+ case NUM_PROP_WIDTH:
+ cr_num_set (&a_this->num_props[i].sv, 800,
+ NUM_LENGTH_PX) ;
+ break ;
+ case NUM_PROP_TOP:
+ case NUM_PROP_RIGHT:
+ case NUM_PROP_BOTTOM:
+ case NUM_PROP_LEFT:
+ cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO);
+ break;
+
+ case NUM_PROP_PADDING_TOP:
+ case NUM_PROP_PADDING_RIGHT:
+ case NUM_PROP_PADDING_BOTTOM:
+ case NUM_PROP_PADDING_LEFT:
+ case NUM_PROP_BORDER_TOP:
+ case NUM_PROP_BORDER_RIGHT:
+ case NUM_PROP_BORDER_BOTTOM:
+ case NUM_PROP_BORDER_LEFT:
+ case NUM_PROP_MARGIN_TOP:
+ case NUM_PROP_MARGIN_RIGHT:
+ case NUM_PROP_MARGIN_BOTTOM:
+ case NUM_PROP_MARGIN_LEFT:
+ cr_num_set (&a_this->num_props[i].sv,
+ 0, NUM_LENGTH_PX);
+ break;
+
+ default:
+ cr_utils_trace_info ("Unknown property");
+ break;
+ }
+ }
+
+ for (i = 0; i < NB_RGB_PROPS; i++) {
+
+ switch (i) {
+ /*default foreground color is black */
+ case RGB_PROP_COLOR:
+ cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE);
+ break;
+
+ /*default background color is white */
+ case RGB_PROP_BACKGROUND_COLOR:
+ cr_rgb_set (&a_this->rgb_props[i].sv,
+ 255, 255, 255, FALSE);
+ cr_rgb_set_to_transparent (&a_this->rgb_props[i].sv,
+ TRUE) ;
+ break;
+ default:
+ cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE);
+ break;
+ }
+ }
+
+ for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
+ a_this->border_style_props[i] = BORDER_STYLE_NONE;
+ }
+
+ a_this->display = DISPLAY_BLOCK;
+ a_this->position = POSITION_STATIC;
+ a_this->float_type = FLOAT_NONE;
+ a_this->font_style = FONT_STYLE_NORMAL;
+ a_this->font_variant = FONT_VARIANT_NORMAL;
+ a_this->font_weight = FONT_WEIGHT_NORMAL;
+ a_this->font_stretch = FONT_STRETCH_NORMAL;
+ a_this->white_space = WHITE_SPACE_NORMAL;
+ cr_font_size_set_predefined_absolute_font_size
+ (&a_this->font_size.sv, FONT_SIZE_MEDIUM) ;
+ a_this->inherited_props_resolved = FALSE ;
+
+ return CR_OK;
+}
+
+/**
+ *Resolves the inherited properties.
+ *The function sets the "inherited" properties to either the value of
+ *their parent properties.
+ *This function is *NOT* recursive. So the inherited properties of
+ *the parent style must have been resolved prior to calling this function.
+ *@param a_this the instance where
+ *@return CR_OK if a root node is found and the propagation is successful,
+ *an error code otherwise
+ */
+enum CRStatus
+cr_style_resolve_inherited_properties (CRStyle *a_this)
+{
+ enum CRStatus ret = CR_OK;
+ glong i = 0;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ g_return_val_if_fail (a_this->parent_style, CR_BAD_PARAM_ERROR) ;
+
+ if (a_this->inherited_props_resolved == TRUE)
+ return CR_OK ;
+
+ for (i=0 ; i < NB_NUM_PROPS ;i++) {
+ if (a_this->num_props[i].sv.type == NUM_INHERIT) {
+ cr_num_copy (&a_this->num_props[i].cv,
+ &a_this->parent_style->num_props[i].cv);
+ }
+ }
+ for (i=0; i < NB_RGB_PROPS; i++) {
+ if (cr_rgb_is_set_to_inherit (&a_this->rgb_props[i].sv) == TRUE) {
+ cr_rgb_copy (
+ &a_this->rgb_props[i].cv,
+ &a_this->parent_style->rgb_props[i].cv);
+ }
+ }
+ for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
+ if (a_this->border_style_props[i] == BORDER_STYLE_INHERIT) {
+ a_this->border_style_props[i] =
+ a_this->parent_style->border_style_props[i];
+ }
+ }
+
+ if (a_this->display == DISPLAY_INHERIT) {
+ a_this->display = a_this->parent_style->display;
+ }
+ if (a_this->position == POSITION_INHERIT) {
+ a_this->position = a_this->parent_style->position;
+ }
+ if (a_this->float_type == FLOAT_INHERIT) {
+ a_this->float_type = a_this->parent_style->float_type;
+ }
+ if (a_this->font_style == FONT_STYLE_INHERIT) {
+ a_this->font_style = a_this->parent_style->font_style;
+ }
+ if (a_this->font_variant == FONT_VARIANT_INHERIT) {
+ a_this->font_variant = a_this->parent_style->font_variant;
+ }
+ if (a_this->font_weight == FONT_WEIGHT_INHERIT) {
+ a_this->font_weight = a_this->parent_style->font_weight;
+ }
+ if (a_this->font_stretch == FONT_STRETCH_INHERIT) {
+ a_this->font_stretch = a_this->parent_style->font_stretch;
+ }
+ /*NULL is inherit marker for font_famiy*/
+ if (a_this->font_family == NULL) {
+ a_this->font_family = a_this->parent_style->font_family;
+ }
+ if (a_this->font_size.sv.type == INHERITED_FONT_SIZE) {
+ cr_font_size_copy (&a_this->font_size.cv,
+ &a_this->parent_style->font_size.cv) ;
+ }
+ a_this->inherited_props_resolved = TRUE ;
+ return ret;
+}
+
+/**
+ *Walks through a css2 property declaration, and populated the
+ *according field(s) in the #CRStyle structure.
+ *If the properties or their value(s) are/is not known,
+ *sets the corresponding field(s) of #CRStyle to its/their default
+ *value(s)
+ *@param a_this the instance of #CRStyle to set.
+ *@param a_decl the declaration from which the #CRStyle fields are set.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_style_set_style_from_decl (CRStyle * a_this, CRDeclaration * a_decl)
+{
+ CRTerm *value = NULL;
+ enum CRStatus status = CR_OK;
+
+ enum CRPropertyID prop_id = PROP_ID_NOT_KNOWN;
+
+ g_return_val_if_fail (a_this && a_decl
+ && a_decl
+ && a_decl->property
+ && a_decl->property->stryng
+ && a_decl->property->stryng->str,
+ CR_BAD_PARAM_ERROR);
+
+ prop_id = cr_style_get_prop_id
+ ((const guchar *) a_decl->property->stryng->str);
+
+ value = a_decl->value;
+ switch (prop_id) {
+ case PROP_ID_PADDING_TOP:
+ status = set_prop_padding_x_from_value
+ (a_this, value, DIR_TOP);
+ break;
+
+ case PROP_ID_PADDING_RIGHT:
+ status = set_prop_padding_x_from_value
+ (a_this, value, DIR_RIGHT);
+ break;
+ case PROP_ID_PADDING_BOTTOM:
+ status = set_prop_padding_x_from_value
+ (a_this, value, DIR_BOTTOM);
+ break;
+
+ case PROP_ID_PADDING_LEFT:
+ status = set_prop_padding_x_from_value
+ (a_this, value, DIR_LEFT);
+ break;
+
+ case PROP_ID_PADDING:
+ status = set_prop_padding_from_value (a_this, value) ;
+ break;
+
+ case PROP_ID_BORDER_TOP_WIDTH:
+ status = set_prop_border_x_width_from_value (a_this, value,
+ DIR_TOP);
+ break;
+
+ case PROP_ID_BORDER_RIGHT_WIDTH:
+ status = set_prop_border_x_width_from_value (a_this, value,
+ DIR_RIGHT);
+ break;
+
+ case PROP_ID_BORDER_BOTTOM_WIDTH:
+ status = set_prop_border_x_width_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_BORDER_LEFT_WIDTH:
+ status = set_prop_border_x_width_from_value (a_this, value,
+ DIR_LEFT);
+ break;
+
+ case PROP_ID_BORDER_WIDTH:
+ status = set_prop_border_width_from_value (a_this, value) ;
+ break ;
+
+ case PROP_ID_BORDER_TOP_STYLE:
+ status = set_prop_border_x_style_from_value (a_this, value,
+ DIR_TOP);
+ break;
+
+ case PROP_ID_BORDER_RIGHT_STYLE:
+ status = set_prop_border_x_style_from_value (a_this, value,
+ DIR_RIGHT);
+ break;
+
+ case PROP_ID_BORDER_BOTTOM_STYLE:
+ status = set_prop_border_x_style_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_BORDER_LEFT_STYLE:
+ status = set_prop_border_x_style_from_value (a_this, value,
+ DIR_LEFT);
+ break;
+
+ case PROP_ID_BORDER_STYLE:
+ status = set_prop_border_style_from_value (a_this, value) ;
+ break ;
+
+ case PROP_ID_BORDER_TOP_COLOR:
+ status = set_prop_border_x_color_from_value (a_this, value,
+ DIR_TOP);
+ break;
+
+ case PROP_ID_BORDER_RIGHT_COLOR:
+ status = set_prop_border_x_color_from_value (a_this, value,
+ DIR_RIGHT);
+ break;
+
+ case PROP_ID_BORDER_BOTTOM_COLOR:
+ status = set_prop_border_x_color_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_BORDER_LEFT_COLOR:
+ status = set_prop_border_x_color_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_BORDER_TOP:
+ status = set_prop_border_x_from_value (a_this, value,
+ DIR_TOP);
+ break;
+
+ case PROP_ID_BORDER_RIGHT:
+ status = set_prop_border_x_from_value (a_this, value,
+ DIR_RIGHT);
+ break;
+
+ case PROP_ID_BORDER_BOTTOM:
+ status = set_prop_border_x_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_BORDER_LEFT:
+ status = set_prop_border_x_from_value (a_this, value,
+ DIR_LEFT);
+ break;
+
+ case PROP_ID_MARGIN_TOP:
+ status = set_prop_margin_x_from_value (a_this, value,
+ DIR_TOP);
+ break;
+
+ case PROP_ID_BORDER:
+ status = set_prop_border_from_value (a_this, value);
+ break;
+
+ case PROP_ID_MARGIN_RIGHT:
+ status = set_prop_margin_x_from_value (a_this, value,
+ DIR_RIGHT);
+ break;
+
+ case PROP_ID_MARGIN_BOTTOM:
+ status = set_prop_margin_x_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_MARGIN_LEFT:
+ status = set_prop_margin_x_from_value (a_this, value,
+ DIR_LEFT);
+ break;
+
+ case PROP_ID_MARGIN:
+ status = set_prop_margin_from_value (a_this, value);
+ break;
+
+ case PROP_ID_DISPLAY:
+ status = set_prop_display_from_value (a_this, value);
+ break;
+
+ case PROP_ID_POSITION:
+ status = set_prop_position_from_value (a_this, value);
+ break;
+
+ case PROP_ID_TOP:
+ status = set_prop_x_from_value (a_this, value, DIR_TOP);
+ break;
+
+ case PROP_ID_RIGHT:
+ status = set_prop_x_from_value (a_this, value, DIR_RIGHT);
+ break;
+
+ case PROP_ID_BOTTOM:
+ status = set_prop_x_from_value (a_this, value, DIR_BOTTOM);
+ break;
+
+ case PROP_ID_LEFT:
+ status = set_prop_x_from_value (a_this, value, DIR_LEFT);
+ break;
+
+ case PROP_ID_FLOAT:
+ status = set_prop_float (a_this, value);
+ break;
+
+ case PROP_ID_WIDTH:
+ status = set_prop_width (a_this, value);
+ break;
+
+ case PROP_ID_COLOR:
+ status = set_prop_color (a_this, value);
+ break;
+
+ case PROP_ID_BACKGROUND_COLOR:
+ status = set_prop_background_color (a_this, value);
+ break;
+
+ case PROP_ID_FONT_FAMILY:
+ status = set_prop_font_family_from_value (a_this, value);
+ break;
+
+ case PROP_ID_FONT_SIZE:
+ status = set_prop_font_size_from_value (a_this, value);
+ break;
+
+ case PROP_ID_FONT_STYLE:
+ status = set_prop_font_style_from_value (a_this, value);
+ break;
+
+ case PROP_ID_FONT_WEIGHT:
+ status = set_prop_font_weight_from_value (a_this, value);
+ break;
+
+ case PROP_ID_WHITE_SPACE:
+ status = set_prop_white_space_from_value(a_this, value);
+ break;
+
+ default:
+ return CR_UNKNOWN_TYPE_ERROR;
+
+ }
+
+ return status;
+}
+
+/**
+ *Increases the reference count
+ *of the current instance of #CRStyle.
+ *@param a_this the current instance of #CRStyle.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_style_ref (CRStyle * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ a_this->ref_count++;
+ return CR_OK;
+}
+
+/**
+ *Decreases the reference count of
+ *the current instance of #CRStyle.
+ *If the reference count reaches 0, the
+ *instance of #CRStyle is destoyed.
+ *@param a_this the current instance of #CRStyle.
+ *@return TRUE if the instance has been destroyed, FALSE
+ *otherwise.
+ */
+gboolean
+cr_style_unref (CRStyle * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->ref_count)
+ a_this->ref_count--;
+
+ if (!a_this->ref_count) {
+ cr_style_destroy (a_this);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ *Duplicates the current instance of #CRStyle .
+ *The newly created instance of #CRStyle must be
+ *freed using cr_style_destroy ().
+ *@param a_this the current instance of #CRStyle.
+ *@return the newly duplicated instance of #CRStyle.
+ */
+CRStyle *
+cr_style_dup (CRStyle * a_this)
+{
+ CRStyle *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ result = cr_style_new (FALSE);
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ cr_style_copy (result, a_this);
+ return result;
+}
+
+/**
+ *Copies a style data structure into another.
+ *TODO: this is actually broken because it's based
+ *on memcpy although some data structures of CRStyle should
+ *be properly duplicated.
+ *@param a_dest the destination style datastructure
+ *@param a_src the source style datastructure.
+ *@return CR_OK upon successful completion, an error code otherwise
+ */
+enum CRStatus
+cr_style_copy (CRStyle * a_dest, CRStyle * a_src)
+{
+ g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
+
+ memcpy (a_dest, a_src, sizeof (CRStyle));
+ return CR_OK;
+}
+
+/**
+ *dump a CRNumpPropVal in a string.
+ *@param a_prop_val the numerical property value to dump
+ *@param a_str the string to dump the numerical property into.
+ *Note that the string value is appended to a_str.
+ *@param a_nb_indent the number white chars of indentation.
+ */
+enum CRStatus
+cr_style_num_prop_val_to_string (CRNumPropVal * a_prop_val,
+ GString * a_str, guint a_nb_indent)
+{
+ enum CRStatus status = CR_OK;
+ guchar *tmp_str = NULL;
+ GString *str = NULL;
+
+ g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR);
+
+ str = g_string_new (NULL);
+ cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
+ g_string_append (str, "NumPropVal {");
+ tmp_str = cr_num_to_string (&a_prop_val->sv);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "sv: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+
+ tmp_str = cr_num_to_string (&a_prop_val->cv);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "cv: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+
+ tmp_str = cr_num_to_string (&a_prop_val->av);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "av: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ g_string_append (str, "}");
+ g_string_append (a_str, str->str);
+ status = CR_OK;
+ cleanup:
+
+ if (tmp_str) {
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ if (str) {
+ g_string_free (str, TRUE);
+ }
+ return status;
+}
+
+enum CRStatus
+cr_style_rgb_prop_val_to_string (CRRgbPropVal * a_prop_val,
+ GString * a_str, guint a_nb_indent)
+{
+ enum CRStatus status = CR_OK;
+ guchar *tmp_str = NULL;
+ GString *str = NULL;
+
+ g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR);
+
+ str = g_string_new (NULL);
+
+ cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
+ g_string_append (str, "RGBPropVal {");
+ tmp_str = cr_rgb_to_string (&a_prop_val->sv);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "sv: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ tmp_str = cr_rgb_to_string (&a_prop_val->cv);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "cv: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ tmp_str = cr_rgb_to_string (&a_prop_val->av);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "av: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+
+ g_string_append (str, "}");
+ g_string_append (a_str, str->str);
+ status = CR_OK;
+ cleanup:
+
+ if (tmp_str) {
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ if (str) {
+ g_string_free (str, TRUE);
+ }
+ return status;
+}
+
+enum CRStatus
+cr_style_border_style_to_string (enum CRBorderStyle a_prop,
+ GString * a_str, guint a_nb_indent)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
+
+ switch (a_prop) {
+ case BORDER_STYLE_NONE:
+ str = (gchar *) "border-style-none";
+ break;
+ case BORDER_STYLE_HIDDEN:
+ str = (gchar *) "border-style-hidden";
+ break;
+ case BORDER_STYLE_DOTTED:
+ str = (gchar *) "border-style-dotted";
+ break;
+ case BORDER_STYLE_DASHED:
+ str = (gchar *) "border-style-dashed";
+ break;
+ case BORDER_STYLE_SOLID:
+ str = (gchar *) "border-style-solid";
+ break;
+ case BORDER_STYLE_DOUBLE:
+ str = (gchar *) "border-style-double";
+ break;
+ case BORDER_STYLE_GROOVE:
+ str = (gchar *) "border-style-groove";
+ break;
+ case BORDER_STYLE_RIDGE:
+ str = (gchar *) "border-style-ridge";
+ break;
+ case BORDER_STYLE_INSET:
+ str = (gchar *) "border-style-inset";
+ break;
+ case BORDER_STYLE_OUTSET:
+ str = (gchar *) "border-style-outset";
+ break;
+ default:
+ str = (gchar *) "unknown border style";
+ break;
+ }
+ cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
+ g_string_append (a_str, str);
+ return CR_OK;
+}
+
+enum CRStatus
+cr_style_display_type_to_string (enum CRDisplayType a_code,
+ GString * a_str, guint a_nb_indent)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
+
+ switch (a_code) {
+ case DISPLAY_NONE:
+ str = (gchar *) "display-none";
+ break;
+ case DISPLAY_INLINE:
+ str = (gchar *) "display-inline";
+ break;
+ case DISPLAY_BLOCK:
+ str = (gchar *) "display-block";
+ break;
+ case DISPLAY_LIST_ITEM:
+ str = (gchar *) "display-list-item";
+ break;
+ case DISPLAY_RUN_IN:
+ str = (gchar *) "display-run-in";
+ break;
+ case DISPLAY_COMPACT:
+ str = (gchar *) "display-compact";
+ break;
+ case DISPLAY_MARKER:
+ str = (gchar *) "display-marker";
+ break;
+ case DISPLAY_TABLE:
+ str = (gchar *) "display-table";
+ break;
+ case DISPLAY_INLINE_TABLE:
+ str = (gchar *) "display-inline-table";
+ break;
+ case DISPLAY_TABLE_ROW_GROUP:
+ str = (gchar *) "display-table-row-group";
+ break;
+ case DISPLAY_TABLE_HEADER_GROUP:
+ str = (gchar *) "display-table-header-group";
+ break;
+ case DISPLAY_TABLE_FOOTER_GROUP:
+ str = (gchar *) "display-table-footer-group";
+ break;
+ case DISPLAY_TABLE_ROW:
+ str = (gchar *) "display-table-row";
+ break;
+ case DISPLAY_TABLE_COLUMN_GROUP:
+ str = (gchar *) "display-table-column-group";
+ break;
+ case DISPLAY_TABLE_COLUMN:
+ str = (gchar *) "display-table-column";
+ break;
+ case DISPLAY_TABLE_CELL:
+ str = (gchar *) "display-table-cell";
+ break;
+ case DISPLAY_TABLE_CAPTION:
+ str = (gchar *) "display-table-caption";
+ break;
+ case DISPLAY_INHERIT:
+ str = (gchar *) "display-inherit";
+ break;
+ default:
+ str = (gchar *) "unknown display property";
+ break;
+ }
+ cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
+ g_string_append (a_str, str);
+ return CR_OK;
+
+}
+
+enum CRStatus
+cr_style_position_type_to_string (enum CRPositionType a_code,
+ GString * a_str, guint a_nb_indent)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
+
+ switch (a_code) {
+ case POSITION_STATIC:
+ str = (gchar *) "position-static";
+ break;
+ case POSITION_RELATIVE:
+ str = (gchar *) "position-relative";
+ break;
+ case POSITION_ABSOLUTE:
+ str = (gchar *) "position-absolute";
+ break;
+ case POSITION_FIXED:
+ str = (gchar *) "position-fixed";
+ break;
+ case POSITION_INHERIT:
+ str = (gchar *) "position-inherit";
+ break;
+ default:
+ str = (gchar *) "unknown static property";
+ }
+ cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
+ g_string_append (a_str, str);
+ return CR_OK;
+}
+
+enum CRStatus
+cr_style_float_type_to_string (enum CRFloatType a_code,
+ GString * a_str, guint a_nb_indent)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
+
+ switch (a_code) {
+ case FLOAT_NONE:
+ str = (gchar *) "float-none";
+ break;
+ case FLOAT_LEFT:
+ str = (gchar *) "float-left";
+ break;
+ case FLOAT_RIGHT:
+ str = (gchar *) "float-right";
+ break;
+ case FLOAT_INHERIT:
+ str = (gchar *) "float-inherit";
+ break;
+ default:
+ str = (gchar *) "unknown float property value";
+ break;
+ }
+ cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
+ g_string_append (a_str, str);
+ return CR_OK;
+}
+
+enum CRStatus
+cr_style_white_space_type_to_string (enum CRWhiteSpaceType a_code,
+ GString * a_str, guint a_nb_indent)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
+
+ switch (a_code) {
+ case WHITE_SPACE_NORMAL:
+ str = (gchar *) "normal";
+ break;
+ case WHITE_SPACE_PRE:
+ str = (gchar *) "pre";
+ break;
+ case WHITE_SPACE_NOWRAP:
+ str = (gchar *) "nowrap";
+ break;
+ case WHITE_SPACE_INHERIT:
+ str = (gchar *) "inherited";
+ break;
+ default:
+ str = (gchar *) "unknown white space property value";
+ break;
+ }
+ cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
+ g_string_append (a_str, str);
+ return CR_OK;
+}
+
+/**
+ *Serializes in instance of #CRStyle into
+ *a string
+ *@param a_this the instance of #CRStyle to serialize
+ *@param a_str the string to serialise the style into.
+ *if *a_str is NULL, a new GString is instantiated, otherwise
+ *the style serialisation is appended to the existed *a_str
+ *@param the number of white space char to use for indentation.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_style_to_string (CRStyle * a_this, GString ** a_str, guint a_nb_indent)
+{
+ const gint INTERNAL_INDENT = 2;
+ gint indent = a_nb_indent + INTERNAL_INDENT;
+ gchar *tmp_str = NULL;
+ GString *str = NULL;
+ gint i = 0;
+
+ g_return_val_if_fail (a_this && a_str, CR_BAD_PARAM_ERROR);
+
+ if (!*a_str) {
+ str = g_string_new (NULL);
+ } else {
+ str = *a_str;
+ }
+ cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
+ g_string_append (str, "style {\n");
+
+ /*loop over the num_props and to_string() them */
+ for (i = NUM_PROP_TOP; i < NB_NUM_PROPS; i++) {
+ /*
+ *to_string() the name of the num_prop
+ *(using num_prop_code_to_string)
+ *before outputting it value
+ */
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = (gchar *) num_prop_code_to_string ((enum CRNumProp) i);
+ if (tmp_str) {
+ g_string_append_printf (str, "%s: ", tmp_str);
+ } else {
+ g_string_append (str, "NULL");
+ }
+ tmp_str = NULL;
+ cr_style_num_prop_val_to_string (&a_this->num_props[i], str,
+ a_nb_indent +
+ INTERNAL_INDENT);
+ g_string_append (str, "\n");
+ }
+ /*loop over the rgb_props and to_string() them all */
+ for (i = RGB_PROP_BORDER_TOP_COLOR; i < NB_RGB_PROPS; i++) {
+ tmp_str = (gchar *) rgb_prop_code_to_string ((enum CRRgbProp) i);
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ if (tmp_str) {
+ g_string_append_printf (str, "%s: ", tmp_str);
+ } else {
+ g_string_append (str, "NULL: ");
+ }
+ tmp_str = NULL;
+ cr_style_rgb_prop_val_to_string (&a_this->rgb_props[i], str,
+ a_nb_indent +
+ INTERNAL_INDENT);
+ g_string_append (str, "\n");
+ }
+ /*loop over the border_style_props and to_string() them */
+ for (i = BORDER_STYLE_PROP_TOP; i < NB_BORDER_STYLE_PROPS; i++) {
+ tmp_str = (gchar *) border_style_prop_code_to_string ((enum CRBorderStyleProp) i);
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ if (tmp_str) {
+ g_string_append_printf (str, "%s: ", tmp_str);
+ } else {
+ g_string_append (str, "NULL: ");
+ }
+ tmp_str = NULL;
+ cr_style_border_style_to_string (a_this->
+ border_style_props[i], str,
+ 0);
+ g_string_append (str, "\n");
+ }
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ g_string_append (str, "display: ");
+ cr_style_display_type_to_string (a_this->display, str, 0);
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ g_string_append (str, "position: ");
+ cr_style_position_type_to_string (a_this->position, str, 0);
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ g_string_append (str, "float-type: ");
+ cr_style_float_type_to_string (a_this->float_type, str, 0);
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ g_string_append (str, "white-space: ");
+ cr_style_white_space_type_to_string (a_this->white_space, str, 0);
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ g_string_append (str, "font-family: ");
+ tmp_str = (gchar *) cr_font_family_to_string (a_this->font_family, TRUE);
+ if (tmp_str) {
+ g_string_append (str, tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ } else {
+ g_string_append (str, "NULL");
+ }
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = cr_font_size_to_string (&a_this->font_size.sv);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-size {sv:%s, ",
+ tmp_str) ;
+ } else {
+ g_string_append (str, "font-size {sv:NULL, ");
+ }
+ tmp_str = cr_font_size_to_string (&a_this->font_size.cv);
+ if (tmp_str) {
+ g_string_append_printf (str, "cv:%s, ", tmp_str);
+ } else {
+ g_string_append (str, "cv:NULL, ");
+ }
+ tmp_str = cr_font_size_to_string (&a_this->font_size.av);
+ if (tmp_str) {
+ g_string_append_printf (str, "av:%s}", tmp_str);
+ } else {
+ g_string_append (str, "av:NULL}");
+ }
+
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = cr_font_size_adjust_to_string (a_this->font_size_adjust);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-size-adjust: %s", tmp_str);
+ } else {
+ g_string_append (str, "font-size-adjust: NULL");
+ }
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = (gchar *) cr_font_style_to_string (a_this->font_style);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-style: %s", tmp_str);
+ } else {
+ g_string_append (str, "font-style: NULL");
+ }
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = (gchar *) cr_font_variant_to_string (a_this->font_variant);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-variant: %s", tmp_str);
+ } else {
+ g_string_append (str, "font-variant: NULL");
+ }
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = (gchar *) cr_font_weight_to_string (a_this->font_weight);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-weight: %s", tmp_str);
+ } else {
+ g_string_append (str, "font-weight: NULL");
+ }
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = (gchar *) cr_font_stretch_to_string (a_this->font_stretch);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-stretch: %s", tmp_str);
+ } else {
+ g_string_append (str, "font-stretch: NULL");
+ }
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+
+ cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
+ g_string_append (str, "}");
+
+ return CR_OK;
+}
+
+/**
+ *Destructor of the #CRStyle class.
+ *@param a_this the instance to destroy.
+ */
+void
+cr_style_destroy (CRStyle * a_this)
+{
+ g_return_if_fail (a_this);
+
+ g_free (a_this);
+}
+
diff --git a/src/3rdparty/libcroco/src/cr-style.h b/src/3rdparty/libcroco/src/cr-style.h
new file mode 100644
index 0000000..18aeaad
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-style.h
@@ -0,0 +1,339 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_STYLE_H__
+#define __CR_STYLE_H__
+
+#include "cr-utils.h"
+#include "cr-statement.h"
+#include "cr-fonts.h"
+
+/**
+ *@file
+ *The declaration of the #CRStyle class.
+ */
+G_BEGIN_DECLS
+
+typedef struct _CRStyle CRStyle ;
+
+enum CRBorderStyle
+{
+ BORDER_STYLE_NONE = 0,
+ BORDER_STYLE_HIDDEN,
+ BORDER_STYLE_DOTTED,
+ BORDER_STYLE_DASHED,
+ BORDER_STYLE_SOLID,
+ BORDER_STYLE_DOUBLE,
+ BORDER_STYLE_GROOVE,
+ BORDER_STYLE_RIDGE,
+ BORDER_STYLE_INSET,
+ BORDER_STYLE_OUTSET,
+ BORDER_STYLE_INHERIT
+} ;
+
+enum CRDisplayType
+{
+ DISPLAY_NONE,
+ DISPLAY_INLINE,
+ DISPLAY_BLOCK,
+ DISPLAY_LIST_ITEM,
+ DISPLAY_RUN_IN,
+ DISPLAY_COMPACT,
+ DISPLAY_MARKER,
+ DISPLAY_TABLE,
+ DISPLAY_INLINE_TABLE,
+ DISPLAY_TABLE_ROW_GROUP,
+ DISPLAY_TABLE_HEADER_GROUP,
+ DISPLAY_TABLE_FOOTER_GROUP,
+ DISPLAY_TABLE_ROW,
+ DISPLAY_TABLE_COLUMN_GROUP,
+ DISPLAY_TABLE_COLUMN,
+ DISPLAY_TABLE_CELL,
+ DISPLAY_TABLE_CAPTION,
+ DISPLAY_INHERIT
+} ;
+
+enum CRPositionType
+{
+ POSITION_STATIC,
+ POSITION_RELATIVE,
+ POSITION_ABSOLUTE,
+ POSITION_FIXED,
+ POSITION_INHERIT
+} ;
+
+enum CRFloatType
+{
+ FLOAT_NONE,
+ FLOAT_LEFT,
+ FLOAT_RIGHT,
+ FLOAT_INHERIT
+} ;
+
+enum CRWhiteSpaceType
+{
+ WHITE_SPACE_NORMAL,
+ WHITE_SPACE_PRE,
+ WHITE_SPACE_NOWRAP,
+ WHITE_SPACE_INHERIT
+} ;
+
+
+#define BORDER_THIN 2
+#define BORDER_MEDIUM 4
+#define BORDER_THICK 6
+
+
+/**
+ *A numerical css property value.
+ *This data type is actually split in 3 parts:
+ *1/the specified value
+ *2/the computed value
+ *3/the actual value.
+ *To understand the semantic of these three parts,
+ *see css2 spec chap 6.1 ("Specified, computed and actual values.").
+ */
+typedef struct _CRNumPropVal CRNumPropVal ;
+struct _CRNumPropVal
+{
+ /**specified value*/
+ CRNum sv ;
+ /**computed value*/
+ CRNum cv ;
+ /**actual value*/
+ CRNum av ;
+} ;
+
+/**
+ *An rgb css property value.
+ *This data type is actually split in 3 parts:
+ *1/the specified value
+ *2/the computed value
+ *3/the actual value.
+ *To understand the semantic of these three parts,
+ *see css2 spec chap 6.1 ("Specified, computed and actual values.").
+ */
+typedef struct _CRRgbPropVal CRRgbPropVal ;
+struct _CRRgbPropVal
+{
+ /**specified value*/
+ CRRgb sv ;
+ /**computed value*/
+ CRRgb cv ;
+ /**actual value*/
+ CRRgb av ;
+} ;
+
+
+enum CRNumProp
+{
+ NUM_PROP_TOP=0,
+ NUM_PROP_RIGHT,
+ NUM_PROP_BOTTOM,
+ NUM_PROP_LEFT,/*3*/
+
+ NUM_PROP_PADDING_TOP,
+ NUM_PROP_PADDING_RIGHT,
+ NUM_PROP_PADDING_BOTTOM,
+ NUM_PROP_PADDING_LEFT,/*7*/
+
+ NUM_PROP_BORDER_TOP,
+ NUM_PROP_BORDER_RIGHT,
+ NUM_PROP_BORDER_BOTTOM,
+ NUM_PROP_BORDER_LEFT,/*11*/
+
+ NUM_PROP_MARGIN_TOP,
+ NUM_PROP_MARGIN_RIGHT,
+ NUM_PROP_MARGIN_BOTTOM,
+ NUM_PROP_MARGIN_LEFT,/*15*/
+
+ NUM_PROP_WIDTH,
+
+ /*must be last*/
+ NB_NUM_PROPS
+} ;
+
+enum CRRgbProp
+{
+ RGB_PROP_BORDER_TOP_COLOR = 0,
+ RGB_PROP_BORDER_RIGHT_COLOR,
+ RGB_PROP_BORDER_BOTTOM_COLOR,
+ RGB_PROP_BORDER_LEFT_COLOR,
+ RGB_PROP_COLOR,
+ RGB_PROP_BACKGROUND_COLOR,
+
+ /*must be last*/
+ NB_RGB_PROPS
+} ;
+
+
+enum CRBorderStyleProp
+{
+ BORDER_STYLE_PROP_TOP = 0,
+ BORDER_STYLE_PROP_RIGHT,
+ BORDER_STYLE_PROP_BOTTOM,
+ BORDER_STYLE_PROP_LEFT,
+
+ /*must be last*/
+ NB_BORDER_STYLE_PROPS
+} ;
+
+enum CRBoxOffsetProp
+{
+ BOX_OFFSET_PROP_TOP = 0,
+ BOX_OFFSET_PROP_RIGHT,
+ BOX_OFFSET_PROP_BOTTOM,
+ BOX_OFFSET_PROP_LEFT,
+
+ /*must be last*/
+ NB_BOX_OFFSET_PROPS
+} ;
+
+typedef struct _CRFontSizeVal CRFontSizeVal ;
+struct _CRFontSizeVal {
+ /*specified value*/
+ CRFontSize sv ;
+ /*computed value*/
+ CRFontSize cv ;
+ /*actual value*/
+ CRFontSize av ;
+} ;
+
+/**
+ *The css2 style class.
+ *Contains computed and actual values
+ *inferred from the declarations found
+ *in the stylesheets.
+ *See css2 spec chapter 6.
+ */
+struct _CRStyle
+{
+ /**
+ *numerical properties.
+ *the properties are indexed by
+ *enum #CRNumProp.
+ */
+ CRNumPropVal num_props[NB_NUM_PROPS] ;
+
+ /**
+ *color properties.
+ *They are indexed by enum #CRRgbProp .
+ */
+ CRRgbPropVal rgb_props[NB_RGB_PROPS] ;
+
+ /**
+ *border style properties.
+ *They are indexed by enum #CRBorderStyleProp .
+ */
+ enum CRBorderStyle border_style_props[NB_BORDER_STYLE_PROPS] ;
+
+ /**box display type*/
+ enum CRDisplayType display ;
+
+ /**the positioning scheme*/
+ enum CRPositionType position ;
+
+ /**the float property*/
+ enum CRFloatType float_type ;
+
+ /*
+ *the 'font-family' property.
+ */
+ CRFontFamily *font_family ;
+
+ /**
+ *the 'font-size' property.
+ */
+ CRFontSizeVal font_size ;
+ CRFontSizeAdjust *font_size_adjust ;
+ enum CRFontStyle font_style ;
+ enum CRFontVariant font_variant ;
+ enum CRFontWeight font_weight ;
+ enum CRFontStretch font_stretch ;
+
+ /**
+ * the 'tex' properties
+ */
+ enum CRWhiteSpaceType white_space;
+
+ gboolean inherited_props_resolved ;
+ CRStyle *parent_style ;
+ gulong ref_count ;
+} ;
+
+enum CRStatus cr_style_white_space_type_to_string (enum CRWhiteSpaceType a_code,
+ GString * a_str, guint a_nb_indent) ;
+
+enum CRStatus cr_style_num_prop_val_to_string (CRNumPropVal *a_prop_val,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+enum CRStatus cr_style_rgb_prop_val_to_string (CRRgbPropVal *a_prop_val,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+enum CRStatus cr_style_border_style_to_string (enum CRBorderStyle a_prop,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+enum CRStatus cr_style_display_type_to_string (enum CRDisplayType a_code,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+enum CRStatus cr_style_position_type_to_string (enum CRPositionType a_code,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+enum CRStatus cr_style_float_type_to_string (enum CRFloatType a_code,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+CRStyle * cr_style_new (gboolean a_set_props_to_initial_values) ;
+
+enum CRStatus cr_style_set_props_to_default_values (CRStyle *a_this) ;
+enum CRStatus cr_style_set_props_to_initial_values (CRStyle *a_this) ;
+enum CRStatus cr_style_resolve_inherited_properties (CRStyle *a_this) ;
+enum CRStatus cr_style_propagate_from_parent (CRStyle *a_this);
+
+enum CRStatus cr_style_set_style_from_decl (CRStyle *a_this,
+ CRDeclaration *a_decl) ;
+
+
+enum CRStatus cr_style_copy (CRStyle *a_dest, CRStyle *a_src) ;
+
+enum CRStatus cr_style_ref (CRStyle *a_this) ;
+
+gboolean cr_style_unref (CRStyle *a_this) ;
+
+void cr_style_destroy (CRStyle *a_this) ;
+
+CRStyle * cr_style_dup (CRStyle *a_this) ;
+
+enum CRStatus cr_style_to_string (CRStyle *a_this,
+ GString **a_str,
+ guint a_nb_indent) ;
+
+G_END_DECLS
+
+#endif /*__CR_STYLE_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-stylesheet.c b/src/3rdparty/libcroco/src/cr-stylesheet.c
new file mode 100644
index 0000000..2ea0fa6
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-stylesheet.c
@@ -0,0 +1,268 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2004 Dodji Seketeli
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include "string.h"
+#include "cr-stylesheet.h"
+
+/**
+ *@file
+ *The definition of the #CRStyleSheet class
+ */
+
+/**
+ *Constructor of the #CRStyleSheet class.
+ *@param the initial list of css statements.
+ *@return the newly built css2 stylesheet, or NULL in case of error.
+ */
+CRStyleSheet *
+cr_stylesheet_new (CRStatement * a_stmts)
+{
+ CRStyleSheet *result;
+
+ result = (CRStyleSheet *) g_try_malloc (sizeof (CRStyleSheet));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStyleSheet));
+
+ if (a_stmts)
+ result->statements = a_stmts;
+
+ result->ref_count = 1;
+
+ return result;
+}
+
+/**
+ *@param a_this the current instance of #CRStyleSheet
+ *@return the serialized stylesheet.
+ */
+gchar *
+cr_stylesheet_to_string (CRStyleSheet const *a_this)
+{
+ gchar *str = NULL;
+ GString *stringue = NULL;
+ CRStatement const *cur_stmt = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ stringue = g_string_new (NULL) ;
+ g_return_val_if_fail (stringue, NULL) ;
+
+ for (cur_stmt = a_this->statements;
+ cur_stmt; cur_stmt = cur_stmt->next) {
+ if (cur_stmt->prev) {
+ g_string_append (stringue, "\n\n") ;
+ }
+ str = cr_statement_to_string (cur_stmt, 0) ;
+ if (str) {
+ g_string_append (stringue, str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+
+ if (a_this->next) {
+ str = cr_stylesheet_to_string (a_this->next);
+ if (str) {
+ g_string_append (stringue, "\n") ;
+ g_string_append (stringue, str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+
+ if (stringue) {
+ str = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ stringue = NULL ;
+ }
+ return str ;
+}
+
+/**
+ *Dumps the current css2 stylesheet to a file.
+ *@param a_this the current instance of #CRStyleSheet.
+ *@param a_fp the destination file
+ */
+void
+cr_stylesheet_dump (CRStyleSheet const * a_this, FILE * a_fp)
+{
+ gchar *str = NULL ;
+
+ g_return_if_fail (a_this);
+
+ str = cr_stylesheet_to_string (a_this) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ *Return the number of rules in the stylesheet.
+ *@param a_this the current instance of #CRStyleSheet.
+ *@return number of rules in the stylesheet.
+ */
+gint
+cr_stylesheet_nr_rules (CRStyleSheet const * a_this)
+{
+ g_return_val_if_fail (a_this, -1);
+
+ return cr_statement_nr_rules (a_this->statements);
+}
+
+/**
+ *Use an index to get a CRStatement from the rules in a given stylesheet.
+ *@param a_this the current instance of #CRStatement.
+ *@param itemnr the index into the rules.
+ *@return CRStatement at position itemnr, if itemnr > number of rules - 1,
+ *it will return NULL.
+ */
+CRStatement *
+cr_stylesheet_statement_get_from_list (CRStyleSheet * a_this, int itemnr)
+{
+ g_return_val_if_fail (a_this, NULL);
+
+ return cr_statement_get_from_list (a_this->statements, itemnr);
+}
+
+/**
+ *Appends a new stylesheet to the current list of #CRStylesheet, setting
+ *the "origin" of the new stylesheet to be the same as the others in list.
+ *
+ *@param a_this the "this pointer" of the current instance
+ *of #CRStylesheet .
+ *@param a_new_stylesheet the stylesheet to append.
+ *@return the list of stylesheets with the a_new_stylesheet appended to it.
+ */
+CRStyleSheet *
+cr_stylesheet_append_stylesheet (CRStyleSheet * a_this, CRStyleSheet * a_new_stylesheet)
+{
+ CRStyleSheet *cur = NULL;
+
+ g_return_val_if_fail (a_new_stylesheet, NULL);
+
+ if (a_this == NULL)
+ return a_new_stylesheet;
+
+ for (cur = a_this; cur->next; cur = cur->next) ;
+
+ cur->next = a_new_stylesheet;
+ a_new_stylesheet->prev = cur;
+
+ /* The "origin" must apriori be the same for all stylesheets
+ in a list. We must set it correctly or errors will occur in
+ put_css_properties_in_props_list(). The "origin" of the initial
+ stylesheet in the list is set in cr_cascade_set_sheet(). */
+ a_new_stylesheet->origin = cur->origin;
+
+ return a_this;
+}
+
+/**
+ * cr_stylesheet_unlink:
+ *@a_this: the stylesheet to unlink.
+ *
+ *Unlinks the stylesheet from the stylesheet list.
+ *
+ *Returns a pointer to the unlinked stylesheet in
+ *case of a successfull completion, NULL otherwise.
+ */
+CRStyleSheet *
+cr_stylesheet_unlink (CRStyleSheet * a_this)
+{
+ CRStyleSheet *result = a_this;
+
+ g_return_val_if_fail (result, NULL);
+
+ /*
+ *some sanity checks first
+ */
+ if (a_this->prev) {
+ g_return_val_if_fail (a_this->prev->next == a_this, NULL);
+
+ }
+ if (a_this->next) {
+ g_return_val_if_fail (a_this->next->prev == a_this, NULL);
+ }
+
+ /*
+ *now, the real unlinking job.
+ */
+ if (a_this->prev) {
+ a_this->prev->next = a_this->next;
+ }
+ if (a_this->next) {
+ a_this->next->prev = a_this->prev;
+ }
+
+ a_this->next = NULL;
+ a_this->prev = NULL;
+
+ return a_this;
+}
+
+void
+cr_stylesheet_ref (CRStyleSheet * a_this)
+{
+ g_return_if_fail (a_this);
+
+ a_this->ref_count++;
+}
+
+gboolean
+cr_stylesheet_unref (CRStyleSheet * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (!--a_this->ref_count) {
+ cr_stylesheet_destroy (a_this);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ *Destructor of the #CRStyleSheet class.
+ *@param a_this the current instance of the #CRStyleSheet class.
+ */
+void
+cr_stylesheet_destroy (CRStyleSheet * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->statements) {
+ cr_statement_destroy (a_this->statements);
+ a_this->statements = NULL;
+ }
+
+ if (a_this->next) {
+ cr_stylesheet_destroy (a_this->next);
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-stylesheet.h b/src/3rdparty/libcroco/src/cr-stylesheet.h
new file mode 100644
index 0000000..cf7b093
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-stylesheet.h
@@ -0,0 +1,117 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * see COPYRIGHTS file for copyright information.
+ */
+
+
+#ifndef __CR_STYLESHEET_H__
+#define __CR_STYLESHEET_H__
+
+#include "cr-utils.h"
+#include "cr-statement.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The declaration of the #CRStyleSheet class.
+ */
+
+
+enum CRStyleOrigin
+{
+ /*Please don't change the order of
+ *the values enumerated here ...
+ *New values should be added at the end,
+ *just before ORIGIN_END.
+ */
+ ORIGIN_UA = 0,
+ ORIGIN_USER,
+ ORIGIN_AUTHOR,
+
+ /*must always be the last one*/
+ NB_ORIGINS
+} ;
+
+/**
+ *An abstraction of a css stylesheet as defined
+ *by the css2 spec in chapter 4.
+ */
+struct _CRStyleSheet
+{
+ /**The css statements list*/
+ CRStatement *statements ;
+
+ enum CRStyleOrigin origin ;
+
+ /*the parent import rule, if any.*/
+ CRStatement *parent_import_rule ;
+
+ /**custom data used by libcroco*/
+ gpointer croco_data ;
+
+ /**
+ *custom application data pointer
+ *Can be used by applications.
+ */
+ gpointer app_data ;
+
+ /**
+ *the reference count of this insance
+ *Please, don't never ever modify it
+ *directly. Use cr_stylesheet_ref()
+ *and cr_stylesheet_unref() instead.
+ */
+ gulong ref_count ;
+
+ /**
+ * A link to the next stylesheet.
+ */
+ CRStyleSheet *next;
+
+ /**
+ * A link to the previous stylesheet.
+ */
+ CRStyleSheet *prev;
+} ;
+
+CRStyleSheet * cr_stylesheet_new (CRStatement *a_stmts) ;
+
+gchar * cr_stylesheet_to_string (CRStyleSheet const *a_this) ;
+
+void cr_stylesheet_dump (CRStyleSheet const *a_this, FILE *a_fp) ;
+
+gint cr_stylesheet_nr_rules (CRStyleSheet const *a_this) ;
+
+CRStatement * cr_stylesheet_statement_get_from_list (CRStyleSheet *a_this, int itemnr) ;
+
+CRStyleSheet * cr_stylesheet_append_stylesheet (CRStyleSheet *a_this, CRStyleSheet *a_new_stylesheet) ;
+
+CRStyleSheet * cr_stylesheet_unlink (CRStyleSheet *a_this) ;
+
+void cr_stylesheet_ref (CRStyleSheet *a_this) ;
+
+gboolean cr_stylesheet_unref (CRStyleSheet *a_this) ;
+
+void cr_stylesheet_destroy (CRStyleSheet *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_STYLESHEET_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-term.c b/src/3rdparty/libcroco/src/cr-term.c
new file mode 100644
index 0000000..e370103
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-term.c
@@ -0,0 +1,744 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "cr-term.h"
+#include "cr-num.h"
+#include "cr-parser.h"
+
+/**
+ * Adds a quoted string onto the end of a GString, expanding it if necessary.
+ * Uses either single or double quotes.
+ *
+ * @pre val is not NULL and is null-terminated. Note that this is true for all
+ * GString::str values.
+ */
+static void
+_string_append_quoted (GString *string, const gchar *val)
+{
+ gchar quote = '\'';
+
+ if (!val) {
+ g_assert_not_reached ();
+ val = "";
+ }
+
+ if (strchr (val, '\'') && !strchr (val, '"')) {
+ quote = '"';
+ }
+
+ g_string_append_c (string, quote);
+
+ for (; *val; ++val) {
+ if (*val == quote || *val == '\\') {
+ g_string_append_c (string, '\\');
+ }
+ g_string_append_c (string, *val);
+ }
+
+ g_string_append_c (string, quote);
+}
+
+/**
+ *@file
+ *Definition of the #CRTem class.
+ */
+
+static void
+cr_term_clear (CRTerm * a_this)
+{
+ g_return_if_fail (a_this);
+
+ switch (a_this->type) {
+ case TERM_NUMBER:
+ if (a_this->content.num) {
+ cr_num_destroy (a_this->content.num);
+ a_this->content.num = NULL;
+ }
+ break;
+
+ case TERM_FUNCTION:
+ if (a_this->ext_content.func_param) {
+ cr_term_destroy (a_this->ext_content.func_param);
+ a_this->ext_content.func_param = NULL;
+ }
+ // fall through
+ case TERM_STRING:
+ case TERM_IDENT:
+ case TERM_URI:
+ case TERM_HASH:
+ if (a_this->content.str) {
+ cr_string_destroy (a_this->content.str);
+ a_this->content.str = NULL;
+ }
+ break;
+
+ case TERM_RGB:
+ if (a_this->content.rgb) {
+ cr_rgb_destroy (a_this->content.rgb);
+ a_this->content.rgb = NULL;
+ }
+ break;
+
+ case TERM_UNICODERANGE:
+ case TERM_NO_TYPE:
+ default:
+ break;
+ }
+
+ a_this->type = TERM_NO_TYPE;
+ a_this->n = FALSE;
+}
+
+/**
+ *Instantiate a #CRTerm.
+ *@return the newly build instance
+ *of #CRTerm.
+ */
+CRTerm *
+cr_term_new (void)
+{
+ CRTerm *result = NULL;
+
+ result = (CRTerm *) g_try_malloc (sizeof (CRTerm));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRTerm));
+ return result;
+}
+
+/**
+ *Parses an expression as defined by the css2 spec
+ *and builds the expression as a list of terms.
+ *@param a_buf the buffer to parse.
+ *@return a pointer to the first term of the expression or
+ *NULL if parsing failed.
+ */
+CRTerm *
+cr_term_parse_expression_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ CRParser *parser = NULL;
+ CRTerm *result = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ g_return_val_if_fail (parser, NULL);
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK) {
+ goto cleanup;
+ }
+ status = cr_parser_parse_expr (parser, &result);
+ if (status != CR_OK) {
+ if (result) {
+ cr_term_destroy (result);
+ result = NULL;
+ }
+ }
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ return result;
+}
+
+enum CRStatus
+cr_term_set_number (CRTerm * a_this, CRNum * a_num)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_NUMBER;
+ a_this->content.num = a_num;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_function (CRTerm * a_this, CRString * a_func_name,
+ CRTerm * a_func_param)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_FUNCTION;
+ a_this->content.str = a_func_name;
+ a_this->ext_content.func_param = a_func_param;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_string (CRTerm * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_STRING;
+ a_this->content.str = a_str;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_ident (CRTerm * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_IDENT;
+ a_this->content.str = a_str;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_uri (CRTerm * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_URI;
+ a_this->content.str = a_str;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_rgb (CRTerm * a_this, CRRgb * a_rgb)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_RGB;
+ a_this->content.rgb = a_rgb;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_hash (CRTerm * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_HASH;
+ a_this->content.str = a_str;
+ return CR_OK;
+}
+
+/**
+ *Appends a new term to the current list of #CRTerm.
+ *
+ *@param a_this the "this pointer" of the current instance
+ *of #CRTerm .
+ *@param a_new_term the term to append.
+ *@return the list of terms with the a_new_term appended to it.
+ */
+CRTerm *
+cr_term_append_term (CRTerm * a_this, CRTerm * a_new_term)
+{
+ CRTerm *cur = NULL;
+
+ g_return_val_if_fail (a_new_term, NULL);
+
+ if (a_this == NULL)
+ return a_new_term;
+
+ for (cur = a_this; cur->next; cur = cur->next) ;
+
+ cur->next = a_new_term;
+ a_new_term->prev = cur;
+
+ return a_this;
+}
+
+/**
+ *Prepends a term to the list of terms represented by a_this.
+ *
+ *@param a_this the "this pointer" of the current instance of
+ *#CRTerm .
+ *@param a_new_term the term to prepend.
+ *@return the head of the new list.
+ */
+CRTerm *
+cr_term_prepend_term (CRTerm * a_this, CRTerm * a_new_term)
+{
+ g_return_val_if_fail (a_this && a_new_term, NULL);
+
+ a_new_term->next = a_this;
+ a_this->prev = a_new_term;
+
+ return a_new_term;
+}
+
+/**
+ *Serializes the expression represented by
+ *the chained instances of #CRterm.
+ *@param a_this the current instance of #CRTerm
+ *@return the zero terminated string containing the serialized
+ *form of #CRTerm. MUST BE FREED BY THE CALLER using g_free().
+ */
+guchar *
+cr_term_to_string (CRTerm const * a_this)
+{
+ GString *str_buf = NULL;
+ CRTerm const *cur = NULL;
+ guchar *result = NULL,
+ *content = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+ g_return_val_if_fail (str_buf, NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ if ((cur->content.str == NULL)
+ && (cur->content.num == NULL)
+ && (cur->content.str == NULL)
+ && (cur->content.rgb == NULL))
+ continue;
+
+ switch (cur->the_operator) {
+ case DIVIDE:
+ g_string_append (str_buf, " / ");
+ break;
+
+ case COMMA:
+ g_string_append (str_buf, ", ");
+ break;
+
+ case NO_OP:
+ if (cur->prev) {
+ g_string_append (str_buf, " ");
+ }
+ break;
+ default:
+
+ break;
+ }
+
+ switch (cur->unary_op) {
+ case PLUS_UOP:
+ g_string_append (str_buf, "+");
+ break;
+
+ case MINUS_UOP:
+ g_string_append (str_buf, "-");
+ break;
+
+ default:
+ break;
+ }
+
+ switch (cur->type) {
+ case TERM_NUMBER:
+ if (cur->content.num) {
+ content = cr_num_to_string (cur->content.num);
+ }
+
+ if (content) {
+ g_string_append (str_buf, (const gchar *) content);
+ g_free (content);
+ content = NULL;
+ }
+
+ break;
+
+ case TERM_FUNCTION:
+ if (cur->content.str) {
+ g_string_append_printf (str_buf, "%s(",
+ cur->content.str->stryng->str);
+
+ if (cur->ext_content.func_param) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_term_to_string
+ (cur->
+ ext_content.func_param);
+
+ if (tmp_str) {
+ g_string_append (str_buf,
+ (const gchar *) tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ g_string_append (str_buf, ")");
+ }
+
+ break;
+
+ case TERM_STRING:
+ if (cur->content.str) {
+ _string_append_quoted (str_buf,
+ cur->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_IDENT:
+ if (cur->content.str && cur->content.str->stryng->str) {
+ g_string_append (str_buf, cur->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_URI:
+ if (cur->content.str) {
+ g_string_append_printf
+ (str_buf, "url(%s)", cur->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_RGB:
+ if (cur->content.rgb) {
+ guchar *tmp_str = NULL;
+
+ g_string_append (str_buf, "rgb(");
+ tmp_str = cr_rgb_to_string (cur->content.rgb);
+
+ if (tmp_str) {
+ g_string_append (str_buf, (const gchar *) tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ g_string_append (str_buf, ")");
+ }
+
+ break;
+
+ case TERM_UNICODERANGE:
+ g_string_append
+ (str_buf,
+ "?found unicoderange: dump not supported yet?");
+ break;
+
+ case TERM_HASH:
+ if (cur->content.str) {
+ g_string_append_printf (str_buf,
+ "#%s", cur->content.str->stryng->str);
+ }
+ break;
+
+ default:
+ g_string_append (str_buf,
+ "Unrecognized Term type");
+ break;
+ }
+ }
+
+ if (str_buf) {
+ result =(guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+guchar *
+cr_term_one_to_string (CRTerm const * a_this)
+{
+ GString *str_buf = NULL;
+ guchar *result = NULL,
+ *content = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+ g_return_val_if_fail (str_buf, NULL);
+
+ if ((a_this->content.str == NULL)
+ && (a_this->content.num == NULL)
+ && (a_this->content.str == NULL)
+ && (a_this->content.rgb == NULL))
+ return NULL ;
+
+ switch (a_this->the_operator) {
+ case DIVIDE:
+ g_string_append_printf (str_buf, " / ");
+ break;
+
+ case COMMA:
+ g_string_append_printf (str_buf, ", ");
+ break;
+
+ case NO_OP:
+ if (a_this->prev) {
+ g_string_append_printf (str_buf, " ");
+ }
+ break;
+ default:
+
+ break;
+ }
+
+ switch (a_this->unary_op) {
+ case PLUS_UOP:
+ g_string_append_printf (str_buf, "+");
+ break;
+
+ case MINUS_UOP:
+ g_string_append_printf (str_buf, "-");
+ break;
+
+ default:
+ break;
+ }
+
+ switch (a_this->type) {
+ case TERM_NUMBER:
+ if (a_this->content.num) {
+ content = cr_num_to_string (a_this->content.num);
+ }
+
+ if (content) {
+ g_string_append (str_buf, (const gchar *) content);
+ g_free (content);
+ content = NULL;
+ }
+
+ break;
+
+ case TERM_FUNCTION:
+ if (a_this->content.str) {
+ g_string_append_printf (str_buf, "%s(",
+ a_this->content.str->stryng->str);
+
+ if (a_this->ext_content.func_param) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_term_to_string
+ (a_this->
+ ext_content.func_param);
+
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf,
+ "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+
+ g_string_append_printf (str_buf, ")");
+ }
+ }
+
+ break;
+
+ case TERM_STRING:
+ if (a_this->content.str) {
+ _string_append_quoted (str_buf,
+ a_this->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_IDENT:
+ if (a_this->content.str && a_this->content.str->stryng->str) {
+ g_string_append (str_buf, a_this->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_URI:
+ if (a_this->content.str) {
+ g_string_append_printf
+ (str_buf, "url(%s)", a_this->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_RGB:
+ if (a_this->content.rgb) {
+ guchar *tmp_str = NULL;
+
+ g_string_append_printf (str_buf, "rgb(");
+ tmp_str = cr_rgb_to_string (a_this->content.rgb);
+
+ if (tmp_str) {
+ g_string_append (str_buf, (const gchar *) tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ g_string_append_printf (str_buf, ")");
+ }
+
+ break;
+
+ case TERM_UNICODERANGE:
+ g_string_append_printf
+ (str_buf,
+ "?found unicoderange: dump not supported yet?");
+ break;
+
+ case TERM_HASH:
+ if (a_this->content.str) {
+ g_string_append_printf (str_buf,
+ "#%s", a_this->content.str->stryng->str);
+ }
+ break;
+
+ default:
+ g_string_append_printf (str_buf,
+ "%s",
+ "Unrecognized Term type");
+ break;
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+/**
+ *Dumps the expression (a list of terms connected by operators)
+ *to a file.
+ *TODO: finish the dump. The dump of some type of terms have not yet been
+ *implemented.
+ *@param a_this the current instance of #CRTerm.
+ *@param a_fp the destination file pointer.
+ */
+void
+cr_term_dump (CRTerm const * a_this, FILE * a_fp)
+{
+ guchar *content = NULL;
+
+ g_return_if_fail (a_this);
+
+ content = cr_term_to_string (a_this);
+
+ if (content) {
+ fprintf (a_fp, "%s", content);
+ g_free (content);
+ }
+}
+
+/**
+ *Return the number of terms in the expression.
+ *@param a_this the current instance of #CRTerm.
+ *@return number of terms in the expression.
+ */
+int
+cr_term_nr_values (CRTerm const *a_this)
+{
+ CRTerm const *cur = NULL ;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, -1) ;
+
+ for (cur = a_this ; cur ; cur = cur->next)
+ nr ++;
+ return nr;
+}
+
+/**
+ *Use an index to get a CRTerm from the expression.
+ *@param a_this the current instance of #CRTerm.
+ *@param itemnr the index into the expression.
+ *@return CRTerm at position itemnr, if itemnr > number of terms - 1,
+ *it will return NULL.
+ */
+CRTerm *
+cr_term_get_from_list (CRTerm *a_this, int itemnr)
+{
+ CRTerm *cur = NULL ;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, NULL) ;
+
+ for (cur = a_this ; cur ; cur = cur->next)
+ if (nr++ == itemnr)
+ return cur;
+ return NULL;
+}
+
+/**
+ *Increments the reference counter of the current instance
+ *of #CRTerm.*
+ *@param a_this the current instance of #CRTerm.
+ */
+void
+cr_term_ref (CRTerm * a_this)
+{
+ g_return_if_fail (a_this);
+
+ a_this->ref_count++;
+}
+
+/**
+ *Decrements the ref count of the current instance of
+ *#CRTerm. If the ref count reaches zero, the instance is
+ *destroyed.
+ *@param a_this the current instance of #CRTerm.
+ *@return TRUE if the current instance has been destroyed, FALSE otherwise.
+ */
+gboolean
+cr_term_unref (CRTerm * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->ref_count) {
+ a_this->ref_count--;
+ }
+
+ if (a_this->ref_count == 0) {
+ cr_term_destroy (a_this);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ *The destructor of the #CRTerm class.
+ *@param a_this the "this pointer" of the current instance
+ *of #CRTerm.
+ */
+void
+cr_term_destroy (CRTerm * const a_this)
+{
+ g_return_if_fail (a_this);
+
+ cr_term_clear (a_this);
+
+ if (a_this->next) {
+ cr_term_destroy (a_this->next);
+ a_this->next = NULL;
+ }
+
+ g_free (a_this);
+}
+
+// vi:sw=8:ts=8
diff --git a/src/3rdparty/libcroco/src/cr-term.h b/src/3rdparty/libcroco/src/cr-term.h
new file mode 100644
index 0000000..39b9c6a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-term.h
@@ -0,0 +1,195 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-rgb.h"
+#include "cr-num.h"
+#include "cr-string.h"
+
+#ifndef __CR_TERM_H__
+#define __CR_TERM_H__
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *Declaration of the #CRTerm class.
+ */
+
+enum CRTermType
+{
+ TERM_NO_TYPE = 0,
+ TERM_NUMBER,
+ TERM_FUNCTION,
+ TERM_STRING,
+ TERM_IDENT,
+ TERM_URI,
+ TERM_RGB,
+ TERM_UNICODERANGE,
+ TERM_HASH
+} ;
+
+
+enum UnaryOperator
+{
+ NO_UNARY_UOP = 0,
+ PLUS_UOP,
+ MINUS_UOP,
+ EMPTY_UNARY_UOP
+} ;
+
+enum Operator
+{
+ NO_OP = 0,
+ DIVIDE,
+ COMMA
+} ;
+
+struct _CRTerm ;
+typedef struct _CRTerm CRTerm ;
+
+/**
+ *An abstraction of a css2 term as
+ *defined in the CSS2 spec in appendix D.1:
+ *term ::=
+ *[ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S*
+ *| ANGLE S* | TIME S* | FREQ S* | function ]
+ * | STRING S* | IDENT S* | URI S* | RGB S*
+ *| UNICODERANGE S* | hexcolor
+ */
+struct _CRTerm
+{
+ /**
+ *The type of the term.
+ */
+ enum CRTermType type ;
+
+ /**
+ *The unary operator associated to
+ *the current term.
+ */
+ enum UnaryOperator unary_op ;
+
+ /**
+ *The operator associated to the current term.
+ */
+ enum Operator the_operator ;
+
+
+ /**
+ *The content of the term.
+ *Depending of the type of the term,
+ *this holds either a number, a percentage ...
+ */
+ union
+ {
+ CRNum *num ;
+ CRString * str ;
+ CRRgb * rgb ;
+ } content ;
+
+ /**
+ *If the term is of type UNICODERANGE,
+ *this field holds the upper bound of the range.
+ *if the term is of type FUNCTION, this holds
+ *an instance of CRTerm that represents
+ * the expression which is the argument of the function.
+ */
+ union
+ {
+ CRTerm *func_param ;
+ } ext_content ;
+
+ /**
+ *A flag to indicate if there is an n as in the nth child expression 'an+b'.
+ */
+ gboolean n;
+
+ /**
+ *A spare pointer, just in case.
+ *Can be used by the application.
+ */
+ gpointer app_data ;
+
+ glong ref_count ;
+
+ /**
+ *A pointer to the next term,
+ *just in case this term is part of
+ *an expression.
+ */
+ CRTerm *next ;
+
+ /**
+ *A pointer to the previous
+ *term.
+ */
+ CRTerm *prev ;
+ CRParsingLocation location ;
+} ;
+
+CRTerm * cr_term_parse_expression_from_buf (const guchar *a_buf,
+ enum CREncoding a_encoding) ;
+CRTerm * cr_term_new (void) ;
+
+enum CRStatus cr_term_set_number (CRTerm *a_this, CRNum *a_num) ;
+
+enum CRStatus cr_term_set_function (CRTerm *a_this,
+ CRString *a_func_name,
+ CRTerm *a_func_param) ;
+
+enum CRStatus cr_term_set_string (CRTerm *a_this, CRString *a_str) ;
+
+enum CRStatus cr_term_set_ident (CRTerm *a_this, CRString *a_str) ;
+
+enum CRStatus cr_term_set_uri (CRTerm *a_this, CRString *a_str) ;
+
+enum CRStatus cr_term_set_rgb (CRTerm *a_this, CRRgb *a_rgb) ;
+
+enum CRStatus cr_term_set_hash (CRTerm *a_this, CRString *a_str) ;
+
+CRTerm * cr_term_append_term (CRTerm *a_this, CRTerm *a_new_term) ;
+
+CRTerm * cr_term_prepend_term (CRTerm *a_this, CRTerm *a_new_term) ;
+
+guchar * cr_term_to_string (CRTerm const *a_this) ;
+
+guchar * cr_term_one_to_string (CRTerm const * a_this) ;
+
+void cr_term_dump (CRTerm const *a_this, FILE *a_fp) ;
+
+int cr_term_nr_values (CRTerm const *a_this) ;
+
+CRTerm * cr_term_get_from_list (CRTerm *a_this, int itemnr) ;
+
+void cr_term_ref (CRTerm *a_this) ;
+
+gboolean cr_term_unref (CRTerm *a_this) ;
+
+void cr_term_destroy (CRTerm * a_term) ;
+
+G_END_DECLS
+
+#endif /*__CR_TERM_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-tknzr.c b/src/3rdparty/libcroco/src/cr-tknzr.c
new file mode 100644
index 0000000..821f89a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-tknzr.c
@@ -0,0 +1,2777 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See the COPYRIGHTS file for copyrights information.
+ */
+
+/**
+ *@file
+ *The definition of the #CRTknzr (tokenizer)
+ *class.
+ */
+
+#include "string.h"
+#include "math.h"
+#include "cr-tknzr.h"
+#include "cr-doc-handler.h"
+
+struct _CRTknzrPriv {
+ /**The parser input stream of bytes*/
+ CRInput *input;
+
+ /**
+ *A cache where tknzr_unget_token()
+ *puts back the token. tknzr_get_next_token()
+ *first look in this cache, and if and
+ *only if it's empty, fetches the next token
+ *from the input stream.
+ */
+ CRToken *token_cache;
+
+ /**
+ *The position of the end of the previous token
+ *or char fetched.
+ */
+ CRInputPos prev_pos;
+
+ CRDocHandler *sac_handler;
+
+ /**
+ *The reference count of the current instance
+ *of #CRTknzr. Is manipulated by cr_tknzr_ref()
+ *and cr_tknzr_unref().
+ */
+ glong ref_count;
+};
+
+#define PRIVATE(obj) ((obj)->priv)
+
+/**
+ *return TRUE if the character is a number ([0-9]), FALSE otherwise
+ *@param a_char the char to test.
+ */
+#define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE)
+
+/**
+ *Checks if 'status' equals CR_OK. If not, goto the 'error' label.
+ *
+ *@param status the status (of type enum CRStatus) to test.
+ *@param is_exception if set to FALSE, the final status returned the
+ *current function will be CR_PARSING_ERROR. If set to TRUE, the
+ *current status will be the current value of the 'status' variable.
+ *
+ */
+#define CHECK_PARSING_STATUS(status, is_exception) \
+if ((status) != CR_OK) \
+{ \
+ if (is_exception == FALSE) \
+ { \
+ status = CR_PARSING_ERROR ; \
+ } \
+ goto error ; \
+}
+
+/**
+ *Peeks the next char from the input stream of the current tokenizer.
+ *invokes CHECK_PARSING_STATUS on the status returned by
+ *cr_tknzr_input_peek_char().
+ *
+ *@param the current instance of #CRTkzr.
+ *@param to_char a pointer to the char where to store the
+ *char peeked.
+ */
+#define PEEK_NEXT_CHAR(a_tknzr, a_to_char) \
+{\
+status = cr_tknzr_peek_char (a_tknzr, a_to_char) ; \
+CHECK_PARSING_STATUS (status, TRUE) \
+}
+
+/**
+ *Reads the next char from the input stream of the current parser.
+ *In case of error, jumps to the "error:" label located in the
+ *function where this macro is called.
+ *@param parser the current instance of #CRTknzr
+ *@param to_char a pointer to the guint32 char where to store
+ *the character read.
+ */
+#define READ_NEXT_CHAR(a_tknzr, to_char) \
+status = cr_tknzr_read_char (a_tknzr, to_char) ;\
+CHECK_PARSING_STATUS (status, TRUE)
+
+/**
+ *Gets information about the current position in
+ *the input of the parser.
+ *In case of failure, this macro returns from the
+ *calling function and
+ *returns a status code of type enum #CRStatus.
+ *@param parser the current instance of #CRTknzr.
+ *@param pos out parameter. A pointer to the position
+ *inside the current parser input. Must
+ */
+#define RECORD_INITIAL_POS(a_tknzr, a_pos) \
+status = cr_input_get_cur_pos (PRIVATE \
+(a_tknzr)->input, a_pos) ; \
+g_return_val_if_fail (status == CR_OK, status)
+
+/**
+ *Gets the address of the current byte inside the
+ *parser input.
+ *@param parser the current instance of #CRTknzr.
+ *@param addr out parameter a pointer (guchar*)
+ *to where the address must be put.
+ */
+#define RECORD_CUR_BYTE_ADDR(a_tknzr, a_addr) \
+status = cr_input_get_cur_byte_addr \
+ (PRIVATE (a_tknzr)->input, a_addr) ; \
+CHECK_PARSING_STATUS (status, TRUE)
+
+/**
+ *Peeks a byte from the topmost parser input at
+ *a given offset from the current position.
+ *If it fails, goto the "error:" label.
+ *
+ *@param a_parser the current instance of #CRTknzr.
+ *@param a_offset the offset of the byte to peek, the
+ *current byte having the offset '0'.
+ *@param a_byte_ptr out parameter a pointer (guchar*) to
+ *where the peeked char is to be stored.
+ */
+#define PEEK_BYTE(a_tknzr, a_offset, a_byte_ptr) \
+status = cr_tknzr_peek_byte (a_tknzr, \
+ a_offset, \
+ a_byte_ptr) ; \
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+#define BYTE(a_input, a_n, a_eof) \
+cr_input_peek_byte2 (a_input, a_n, a_eof)
+
+/**
+ *Reads a byte from the topmost parser input
+ *steam.
+ *If it fails, goto the "error" label.
+ *@param a_parser the current instance of #CRTknzr.
+ *@param a_byte_ptr the guchar * where to put the read char.
+ */
+#define READ_NEXT_BYTE(a_tknzr, a_byte_ptr) \
+status = \
+cr_input_read_byte (PRIVATE (a_tknzr)->input, a_byte_ptr) ;\
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+/**
+ *Skips a given number of byte in the topmost
+ *parser input. Don't update line and column number.
+ *In case of error, jumps to the "error:" label
+ *of the surrounding function.
+ *@param a_parser the current instance of #CRTknzr.
+ *@param a_nb_bytes the number of bytes to skip.
+ */
+#define SKIP_BYTES(a_tknzr, a_nb_bytes) \
+status = cr_input_seek_index (PRIVATE (a_tknzr)->input, \
+ CR_SEEK_CUR, a_nb_bytes) ; \
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+/**
+ *Skip utf8 encoded characters.
+ *Updates line and column numbers.
+ *@param a_parser the current instance of #CRTknzr.
+ *@param a_nb_chars the number of chars to skip. Must be of
+ *type glong.
+ */
+#define SKIP_CHARS(a_tknzr, a_nb_chars) \
+{ \
+gulong nb_chars = a_nb_chars ; \
+status = cr_input_consume_chars \
+ (PRIVATE (a_tknzr)->input,0, &nb_chars) ; \
+CHECK_PARSING_STATUS (status, TRUE) ; \
+}
+
+/**
+ *Tests the condition and if it is false, sets
+ *status to "CR_PARSING_ERROR" and goto the 'error'
+ *label.
+ *@param condition the condition to test.
+ */
+#define ENSURE_PARSING_COND(condition) \
+if (! (condition)) {status = CR_PARSING_ERROR; goto error ;}
+
+static enum CRStatus cr_tknzr_parse_nl (CRTknzr * a_this,
+ guchar ** a_start,
+ guchar ** a_end,
+ CRParsingLocation *a_location);
+
+static enum CRStatus cr_tknzr_parse_w (CRTknzr * a_this,
+ guchar ** a_start,
+ guchar ** a_end,
+ CRParsingLocation *a_location) ;
+
+static enum CRStatus cr_tknzr_parse_unicode_escape (CRTknzr * a_this,
+ guint32 * a_unicode,
+ CRParsingLocation *a_location) ;
+
+static enum CRStatus cr_tknzr_parse_escape (CRTknzr * a_this,
+ guint32 * a_esc_code,
+ CRParsingLocation *a_location);
+
+static enum CRStatus cr_tknzr_parse_string (CRTknzr * a_this,
+ CRString ** a_str);
+
+static enum CRStatus cr_tknzr_parse_comment (CRTknzr * a_this,
+ CRString ** a_comment);
+
+static enum CRStatus cr_tknzr_parse_nmstart (CRTknzr * a_this,
+ guint32 * a_char,
+ CRParsingLocation *a_location);
+
+static enum CRStatus cr_tknzr_parse_num (CRTknzr * a_this,
+ CRNum ** a_num);
+
+/**********************************
+ *PRIVATE methods
+ **********************************/
+
+/**
+ *Parses a "w" as defined by the css spec at [4.1.1]:
+ * w ::= [ \t\r\n\f]*
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_start out param. Upon successful completion, points
+ *to the beginning of the parsed white space, points to NULL otherwise.
+ *Can also point to NULL is there is no white space actually.
+ *@param a_end out param. Upon successful completion, points
+ *to the end of the parsed white space, points to NULL otherwise.
+ *Can also point to NULL is there is no white space actually.
+ */
+static enum CRStatus
+cr_tknzr_parse_w (CRTknzr * a_this,
+ guchar ** a_start,
+ guchar ** a_end,
+ CRParsingLocation *a_location)
+{
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_start && a_end,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ *a_start = NULL;
+ *a_end = NULL;
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cr_utils_is_white_space (cur_char) == FALSE) {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ if (a_location) {
+ cr_tknzr_get_parsing_location (a_this,
+ a_location) ;
+ }
+ RECORD_CUR_BYTE_ADDR (a_this, a_start);
+ *a_end = *a_start;
+
+ for (;;) {
+ gboolean is_eof = FALSE;
+
+ cr_input_get_end_of_file (PRIVATE (a_this)->input, &is_eof);
+ if (is_eof)
+ break;
+
+ status = cr_tknzr_peek_char (a_this, &cur_char);
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ break;
+ } else if (status != CR_OK) {
+ goto error;
+ }
+
+ if (cr_utils_is_white_space (cur_char) == TRUE) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ RECORD_CUR_BYTE_ADDR (a_this, a_end);
+ } else {
+ break;
+ }
+ }
+
+ return CR_OK;
+
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a newline as defined in the css2 spec:
+ * nl ::= \n|\r\n|\r|\f
+ *
+ *@param a_this the "this pointer" of the current instance of #CRTknzr.
+ *@param a_start a pointer to the first character of the successfully
+ *parsed string.
+ *@param a_end a pointer to the last character of the successfully parsed
+ *string.
+ *@result CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_nl (CRTknzr * a_this,
+ guchar ** a_start,
+ guchar ** a_end,
+ CRParsingLocation *a_location)
+{
+ CRInputPos init_pos;
+ guchar next_chars[2] = { 0 };
+ enum CRStatus status = CR_PARSING_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_start && a_end, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PEEK_BYTE (a_this, 1, &next_chars[0]);
+ PEEK_BYTE (a_this, 2, &next_chars[1]);
+
+ if ((next_chars[0] == '\r' && next_chars[1] == '\n')) {
+ SKIP_BYTES (a_this, 1);
+ if (a_location) {
+ cr_tknzr_get_parsing_location
+ (a_this, a_location) ;
+ }
+ SKIP_CHARS (a_this, 1);
+
+ RECORD_CUR_BYTE_ADDR (a_this, a_end);
+
+ status = CR_OK;
+ } else if (next_chars[0] == '\n'
+ || next_chars[0] == '\r' || next_chars[0] == '\f') {
+ SKIP_CHARS (a_this, 1);
+ if (a_location) {
+ cr_tknzr_get_parsing_location
+ (a_this, a_location) ;
+ }
+ RECORD_CUR_BYTE_ADDR (a_this, a_start);
+ *a_end = *a_start;
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ return CR_OK ;
+
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos) ;
+ return status;
+}
+
+/**
+ *Go ahead in the parser input, skipping all the spaces.
+ *If the next char if not a white space, this function does nothing.
+ *In any cases, it stops when it encounters a non white space character.
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_try_to_skip_spaces (CRTknzr * a_this)
+{
+ enum CRStatus status = CR_ERROR;
+ guint32 cur_char = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+
+ status = cr_input_peek_char (PRIVATE (a_this)->input, &cur_char);
+
+ if (status != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR)
+ return CR_OK;
+ return status;
+ }
+
+ if (cr_utils_is_white_space (cur_char) == TRUE) {
+ gulong nb_chars = -1; /*consume all spaces */
+
+ status = cr_input_consume_white_spaces
+ (PRIVATE (a_this)->input, &nb_chars);
+ }
+
+ return status;
+}
+
+/**
+ *Parses a "comment" as defined in the css spec at [4.1.1]:
+ *COMMENT ::= \/\*[^*]*\*+([^/][^*]*\*+)*\/ .
+ *This complex regexp is just to say that comments start
+ *with the two chars '/''*' and ends with the two chars '*''/'.
+ *It also means that comments cannot be nested.
+ *So based on that, I've just tried to implement the parsing function
+ *simply and in a straight forward manner.
+ */
+static enum CRStatus
+cr_tknzr_parse_comment (CRTknzr * a_this,
+ CRString ** a_comment)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ guint32 cur_char = 0, next_char= 0;
+ CRString *comment = NULL;
+ CRParsingLocation loc = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ READ_NEXT_CHAR (a_this, &cur_char) ;
+ ENSURE_PARSING_COND (cur_char == '/');
+ cr_tknzr_get_parsing_location (a_this, &loc) ;
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == '*');
+ comment = cr_string_new ();
+ for (;;) { /* [^*]* */
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char == '*')
+ break;
+ READ_NEXT_CHAR (a_this, &cur_char);
+ g_string_append_unichar (comment->stryng, cur_char);
+ }
+ /* Stop condition: next_char == '*' */
+ for (;;) { /* \*+ */
+ READ_NEXT_CHAR(a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == '*');
+ g_string_append_unichar (comment->stryng, cur_char);
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char != '*')
+ break;
+ }
+ /* Stop condition: next_char != '*' */
+ for (;;) { /* ([^/][^*]*\*+)* */
+ if (next_char == '/')
+ break;
+ READ_NEXT_CHAR(a_this, &cur_char);
+ g_string_append_unichar (comment->stryng, cur_char);
+ for (;;) { /* [^*]* */
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char == '*')
+ break;
+ READ_NEXT_CHAR (a_this, &cur_char);
+ g_string_append_unichar (comment->stryng, cur_char);
+ }
+ /* Stop condition: next_char = '*', no need to verify, because peek and read exit to error anyway */
+ for (;;) { /* \*+ */
+ READ_NEXT_CHAR(a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == '*');
+ g_string_append_unichar (comment->stryng, cur_char);
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char != '*')
+ break;
+ }
+ /* Continue condition: next_char != '*' */
+ }
+ /* Stop condition: next_char == '\/' */
+ READ_NEXT_CHAR(a_this, &cur_char);
+ g_string_append_unichar (comment->stryng, cur_char);
+
+ if (status == CR_OK) {
+ cr_parsing_location_copy (&comment->location,
+ &loc) ;
+ *a_comment = comment;
+ return CR_OK;
+ }
+ error:
+
+ if (comment) {
+ cr_string_destroy (comment);
+ comment = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses an 'unicode' escape sequence defined
+ *in css spec at chap 4.1.1:
+ *unicode ::= \\[0-9a-f]{1,6}[ \n\r\t\f]?
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_start out parameter. A pointer to the start
+ *of the unicode escape sequence. Must *NOT* be deleted by
+ *the caller.
+ *@param a_end out parameter. A pointer to the last character
+ *of the unicode escape sequence. Must *NOT* be deleted by the caller.
+ *@return CR_OK if parsing succeeded, an error code otherwise.
+ *Error code can be either CR_PARSING_ERROR if the string
+ *parsed just doesn't
+ *respect the production or another error if a
+ *lower level error occurred.
+ */
+static enum CRStatus
+cr_tknzr_parse_unicode_escape (CRTknzr * a_this,
+ guint32 * a_unicode,
+ CRParsingLocation *a_location)
+{
+ guint32 cur_char;
+ CRInputPos init_pos;
+ glong occur = 0;
+ guint32 unicode = 0;
+ guchar *tmp_char_ptr1 = NULL,
+ *tmp_char_ptr2 = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_unicode, CR_BAD_PARAM_ERROR);
+
+ /*first, let's backup the current position pointer */
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char != '\\') {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ if (a_location) {
+ cr_tknzr_get_parsing_location
+ (a_this, a_location) ;
+ }
+ PEEK_NEXT_CHAR (a_this, &cur_char);
+
+ for (occur = 0, unicode = 0; ((cur_char >= '0' && cur_char <= '9')
+ || (cur_char >= 'a' && cur_char <= 'f')
+ || (cur_char >= 'A' && cur_char <= 'F'))
+ && occur < 6; occur++) {
+ gint cur_char_val = 0;
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if ((cur_char >= '0' && cur_char <= '9')) {
+ cur_char_val = (cur_char - '0');
+ } else if ((cur_char >= 'a' && cur_char <= 'f')) {
+ cur_char_val = 10 + (cur_char - 'a');
+ } else if ((cur_char >= 'A' && cur_char <= 'F')) {
+ cur_char_val = 10 + (cur_char - 'A');
+ }
+
+ unicode = unicode * 16 + cur_char_val;
+
+ PEEK_NEXT_CHAR (a_this, &cur_char);
+ }
+
+ /* Eat a whitespace if possible. */
+ cr_tknzr_parse_w (a_this, &tmp_char_ptr1,
+ &tmp_char_ptr2, NULL);
+ *a_unicode = unicode;
+ return CR_OK;
+
+ error:
+ /*
+ *restore the initial position pointer backuped at
+ *the beginning of this function.
+ */
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+}
+
+/**
+ *parses an escape sequence as defined by the css spec:
+ *escape ::= {unicode}|\\[ -~\200-\4177777]
+ *@param a_this the current instance of #CRTknzr .
+ */
+static enum CRStatus
+cr_tknzr_parse_escape (CRTknzr * a_this, guint32 * a_esc_code,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ guchar next_chars[2];
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_esc_code, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PEEK_BYTE (a_this, 1, &next_chars[0]);
+ PEEK_BYTE (a_this, 2, &next_chars[1]);
+
+ if (next_chars[0] != '\\') {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ if ((next_chars[1] >= '0' && next_chars[1] <= '9')
+ || (next_chars[1] >= 'a' && next_chars[1] <= 'f')
+ || (next_chars[1] >= 'A' && next_chars[1] <= 'F')) {
+ status = cr_tknzr_parse_unicode_escape (a_this, a_esc_code,
+ a_location);
+ } else {
+ /*consume the '\' char */
+ READ_NEXT_CHAR (a_this, &cur_char);
+ if (a_location) {
+ cr_tknzr_get_parsing_location (a_this,
+ a_location) ;
+ }
+ /*then read the char after the '\' */
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char != ' ' && (cur_char < 200 || cur_char > 4177777)) {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ *a_esc_code = cur_char;
+
+ }
+ if (status == CR_OK) {
+ return CR_OK;
+ }
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+/**
+ *Parses a string type as defined in css spec [4.1.1]:
+ *
+ *string ::= {string1}|{string2}
+ *string1 ::= \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"
+ *string2 ::= \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_start out parameter. Upon successful completion,
+ *points to the beginning of the string, points to an undefined value
+ *otherwise.
+ *@param a_end out parameter. Upon successful completion, points to
+ *the beginning of the string, points to an undefined value otherwise.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_string (CRTknzr * a_this, CRString ** a_str)
+{
+ guint32 cur_char = 0,
+ delim = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ CRString *str = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_str, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char == '"')
+ delim = '"';
+ else if (cur_char == '\'')
+ delim = '\'';
+ else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ str = cr_string_new ();
+ if (str) {
+ cr_tknzr_get_parsing_location
+ (a_this, &str->location) ;
+ }
+ for (;;) {
+ guchar next_chars[2] = { 0 };
+
+ PEEK_BYTE (a_this, 1, &next_chars[0]);
+
+ if (next_chars[0] == '\\') {
+ guchar *tmp_char_ptr1 = NULL,
+ *tmp_char_ptr2 = NULL;
+ guint32 esc_code = 0;
+
+ PEEK_BYTE (a_this, 2, &next_chars[1]);
+
+ if (next_chars[1] == '\'' || next_chars[1] == '"' || next_chars[1] == '\\') {
+ g_string_append_unichar (str->stryng,
+ next_chars[1]);
+ SKIP_BYTES (a_this, 2);
+ status = CR_OK;
+ } else {
+ status = cr_tknzr_parse_escape
+ (a_this, &esc_code, NULL);
+
+ if (status == CR_OK) {
+ g_string_append_unichar
+ (str->stryng,
+ esc_code);
+ }
+ }
+
+ if (status != CR_OK) {
+ /*
+ *consume the '\' char, and try to parse
+ *a newline.
+ */
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ status = cr_tknzr_parse_nl
+ (a_this, &tmp_char_ptr1,
+ &tmp_char_ptr2, NULL);
+ }
+
+ CHECK_PARSING_STATUS (status, FALSE);
+ } else if (next_chars[0] == delim) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ break;
+ } else if (next_chars[0] == '\t'
+ || (next_chars[0] >= ' ' && next_chars[0] <= '~')) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ g_string_append_unichar (str->stryng,
+ cur_char);
+ status = CR_OK;
+ }
+
+ else if (cr_utils_is_nonascii (next_chars[0])) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ g_string_append_unichar (str->stryng, cur_char);
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ }
+
+ if (status == CR_OK) {
+ if (*a_str == NULL) {
+ *a_str = str;
+ str = NULL;
+ } else {
+ (*a_str)->stryng = g_string_append_len
+ ((*a_str)->stryng,
+ str->stryng->str,
+ str->stryng->len);
+ cr_string_destroy (str);
+ }
+ return CR_OK;
+ }
+
+ error:
+
+ if (str) {
+ cr_string_destroy (str) ;
+ str = NULL;
+ }
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+/**
+ *Parses the an nmstart as defined by the css2 spec [4.1.1]:
+ * nmstart [a-zA-Z]|{nonascii}|{escape}
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_start out param. A pointer to the starting point of
+ *the token.
+ *@param a_end out param. A pointer to the ending point of the
+ *token.
+ *@param a_char out param. The actual parsed nmchar.
+ *@return CR_OK upon successful completion,
+ *an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_nmstart (CRTknzr * a_this,
+ guint32 * a_char,
+ CRParsingLocation *a_location)
+{
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ guint32 cur_char = 0,
+ next_char = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_char, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PEEK_NEXT_CHAR (a_this, &next_char);
+
+ if (next_char == '\\') {
+ status = cr_tknzr_parse_escape (a_this, a_char,
+ a_location);
+
+ if (status != CR_OK)
+ goto error;
+
+ } else if (cr_utils_is_nonascii (next_char) == TRUE
+ || ((next_char >= 'a') && (next_char <= 'z'))
+ || ((next_char >= 'A') && (next_char <= 'Z'))
+ ) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ if (a_location) {
+ cr_tknzr_get_parsing_location (a_this,
+ a_location) ;
+ }
+ *a_char = cur_char;
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ return CR_OK;
+
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+
+}
+
+/**
+ *Parses an nmchar as described in the css spec at
+ *chap 4.1.1:
+ *nmchar ::= [a-z0-9-]|{nonascii}|{escape}
+ *
+ *Humm, I have added the possibility for nmchar to
+ *contain upper case letters.
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_start out param. A pointer to the starting point of
+ *the token.
+ *@param a_end out param. A pointer to the ending point of the
+ *token.
+ *@param a_char out param. The actual parsed nmchar.
+ *@return CR_OK upon successful completion,
+ *an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_nmchar (CRTknzr * a_this, guint32 * a_char,
+ CRParsingLocation *a_location)
+{
+ guint32 cur_char = 0,
+ next_char = 0;
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_input_peek_char (PRIVATE (a_this)->input,
+ &next_char) ;
+ if (status != CR_OK)
+ goto error;
+
+ if (next_char == '\\') {
+ status = cr_tknzr_parse_escape (a_this, a_char,
+ a_location);
+
+ if (status != CR_OK)
+ goto error;
+
+ } else if (cr_utils_is_nonascii (next_char) == TRUE
+ || ((next_char >= 'a') && (next_char <= 'z'))
+ || ((next_char >= 'A') && (next_char <= 'Z'))
+ || ((next_char >= '0') && (next_char <= '9'))
+ || (next_char == '-')
+ || (next_char == '_') /*'_' not allowed by the spec. */
+ ) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ *a_char = cur_char;
+ status = CR_OK;
+ if (a_location) {
+ cr_tknzr_get_parsing_location
+ (a_this, a_location) ;
+ }
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ return CR_OK;
+
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+/**
+ *Parses an "ident" as defined in css spec [4.1.1]:
+ *ident ::= {nmstart}{nmchar}*
+ *
+ *Actually parses it using the css3 grammar:
+ *ident ::= -?{nmstart}{nmchar}*
+ *@param a_this the currens instance of #CRTknzr.
+ *
+ *@param a_str a pointer to parsed ident. If *a_str is NULL,
+ *this function allocates a new instance of CRString. If not,
+ *the function just appends the parsed string to the one passed.
+ *In both cases it is up to the caller to free *a_str.
+ *
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_ident (CRTknzr * a_this, CRString ** a_str)
+{
+ guint32 tmp_char = 0;
+ CRString *stringue = NULL ;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ gboolean location_is_set = FALSE ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_str, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ PEEK_NEXT_CHAR (a_this, &tmp_char) ;
+ stringue = cr_string_new () ;
+ g_return_val_if_fail (stringue,
+ CR_OUT_OF_MEMORY_ERROR) ;
+
+ if (tmp_char == '-') {
+ READ_NEXT_CHAR (a_this, &tmp_char) ;
+ cr_tknzr_get_parsing_location
+ (a_this, &stringue->location) ;
+ location_is_set = TRUE ;
+ g_string_append_unichar (stringue->stryng,
+ tmp_char) ;
+ }
+ status = cr_tknzr_parse_nmstart (a_this, &tmp_char, NULL);
+ if (status != CR_OK) {
+ status = CR_PARSING_ERROR;
+ goto end ;
+ }
+ if (location_is_set == FALSE) {
+ cr_tknzr_get_parsing_location
+ (a_this, &stringue->location) ;
+ location_is_set = TRUE ;
+ }
+ g_string_append_unichar (stringue->stryng, tmp_char);
+ for (;;) {
+ status = cr_tknzr_parse_nmchar (a_this,
+ &tmp_char,
+ NULL);
+ if (status != CR_OK) {
+ status = CR_OK ;
+ break;
+ }
+ g_string_append_unichar (stringue->stryng, tmp_char);
+ }
+ if (status == CR_OK) {
+ if (!*a_str) {
+ *a_str = stringue ;
+
+ } else {
+ g_string_append_len ((*a_str)->stryng,
+ stringue->stryng->str,
+ stringue->stryng->len) ;
+ cr_string_destroy (stringue) ;
+ }
+ stringue = NULL ;
+ }
+
+ error:
+ end:
+ if (stringue) {
+ cr_string_destroy (stringue) ;
+ stringue = NULL ;
+ }
+ if (status != CR_OK ) {
+ cr_tknzr_set_cur_pos (a_this, &init_pos) ;
+ }
+ return status ;
+}
+
+
+/**
+ *Parses a "name" as defined by css spec [4.1.1]:
+ *name ::= {nmchar}+
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *
+ *@param a_str out parameter. A pointer to the successfully parsed
+ *name. If *a_str is set to NULL, this function allocates a new instance
+ *of CRString. If not, it just appends the parsed name to the passed *a_str.
+ *In both cases, it is up to the caller to free *a_str.
+ *
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_name (CRTknzr * a_this,
+ CRString ** a_str)
+{
+ guint32 tmp_char = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ gboolean str_needs_free = FALSE,
+ is_first_nmchar=TRUE ;
+ glong i = 0;
+ CRParsingLocation loc = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_str,
+ CR_BAD_PARAM_ERROR) ;
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ if (*a_str == NULL) {
+ *a_str = cr_string_new ();
+ str_needs_free = TRUE;
+ }
+ for (i = 0;; i++) {
+ if (is_first_nmchar == TRUE) {
+ status = cr_tknzr_parse_nmchar
+ (a_this, &tmp_char,
+ &loc) ;
+ is_first_nmchar = FALSE ;
+ } else {
+ status = cr_tknzr_parse_nmchar
+ (a_this, &tmp_char, NULL) ;
+ }
+ if (status != CR_OK)
+ break;
+ g_string_append_unichar ((*a_str)->stryng,
+ tmp_char);
+ }
+ if (i > 0) {
+ cr_parsing_location_copy
+ (&(*a_str)->location, &loc) ;
+ return CR_OK;
+ }
+ if (str_needs_free == TRUE && *a_str) {
+ cr_string_destroy (*a_str);
+ *a_str = NULL;
+ }
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return CR_PARSING_ERROR;
+}
+
+/**
+ *Parses a "hash" as defined by the css spec in [4.1.1]:
+ *HASH ::= #{name}
+ */
+static enum CRStatus
+cr_tknzr_parse_hash (CRTknzr * a_this, CRString ** a_str)
+{
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ gboolean str_needs_free = FALSE;
+ CRParsingLocation loc = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ if (cur_char != '#') {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ if (*a_str == NULL) {
+ *a_str = cr_string_new ();
+ str_needs_free = TRUE;
+ }
+ cr_tknzr_get_parsing_location (a_this,
+ &loc) ;
+ status = cr_tknzr_parse_name (a_this, a_str);
+ cr_parsing_location_copy (&(*a_str)->location, &loc) ;
+ if (status != CR_OK) {
+ goto error;
+ }
+ return CR_OK;
+
+ error:
+ if (str_needs_free == TRUE && *a_str) {
+ cr_string_destroy (*a_str);
+ *a_str = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+/**
+ *Parses an uri as defined by the css spec [4.1.1]:
+ * URI ::= url\({w}{string}{w}\)
+ * |url\({w}([!#$%&*-~]|{nonascii}|{escape})*{w}\)
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_str the successfully parsed url.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_uri (CRTknzr * a_this,
+ CRString ** a_str)
+{
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_PARSING_ERROR;
+ guchar tab[4] = { 0 }, *tmp_ptr1 = NULL, *tmp_ptr2 = NULL;
+ CRString *str = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_str,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PEEK_BYTE (a_this, 1, &tab[0]);
+ PEEK_BYTE (a_this, 2, &tab[1]);
+ PEEK_BYTE (a_this, 3, &tab[2]);
+ PEEK_BYTE (a_this, 4, &tab[3]);
+
+ if (tab[0] != 'u' || tab[1] != 'r' || tab[2] != 'l' || tab[3] != '(') {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ /*
+ *Here, we want to skip 4 bytes ('u''r''l''(').
+ *But we also need to keep track of the parsing location
+ *of the 'u'. So, we skip 1 byte, we record the parsing
+ *location, then we skip the 3 remaining bytes.
+ */
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this, &location) ;
+ SKIP_CHARS (a_this, 3);
+ cr_tknzr_try_to_skip_spaces (a_this);
+ status = cr_tknzr_parse_string (a_this, a_str);
+
+ if (status == CR_OK) {
+ guint32 next_char = 0;
+ status = cr_tknzr_parse_w (a_this, &tmp_ptr1,
+ &tmp_ptr2, NULL);
+ cr_tknzr_try_to_skip_spaces (a_this);
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char == ')') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ }
+ }
+ if (status != CR_OK) {
+ str = cr_string_new ();
+ for (;;) {
+ guint32 next_char = 0;
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (strchr ("!#$%&", next_char)
+ || (next_char >= '*' && next_char <= '~')
+ || (cr_utils_is_nonascii (next_char) == TRUE)) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ g_string_append_unichar
+ (str->stryng, cur_char);
+ status = CR_OK;
+ } else {
+ guint32 esc_code = 0;
+ status = cr_tknzr_parse_escape
+ (a_this, &esc_code, NULL);
+ if (status == CR_OK) {
+ g_string_append_unichar
+ (str->stryng,
+ esc_code);
+ } else {
+ status = CR_OK;
+ break;
+ }
+ }
+ }
+ cr_tknzr_try_to_skip_spaces (a_this);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ if (cur_char == ')') {
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ if (str) {
+ if (*a_str == NULL) {
+ *a_str = str;
+ str = NULL;
+ } else {
+ g_string_append_len
+ ((*a_str)->stryng,
+ str->stryng->str,
+ str->stryng->len);
+ cr_string_destroy (str);
+ }
+ }
+ }
+
+ cr_parsing_location_copy
+ (&(*a_str)->location,
+ &location) ;
+ return CR_OK ;
+ error:
+ if (str) {
+ cr_string_destroy (str);
+ str = NULL;
+ }
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+/**
+ *parses an RGB as defined in the css2 spec.
+ *rgb: rgb '('S*{num}%?S* ',' {num}#?S*,S*{num}#?S*')'
+ *
+ *@param a_this the "this pointer" of the current instance of
+ *@param a_rgb out parameter the parsed rgb.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_rgb (CRTknzr * a_this, CRRgb ** a_rgb)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRNum *num = NULL;
+ guchar next_bytes[3] = { 0 }, cur_byte = 0;
+ glong red = 0,
+ green = 0,
+ blue = 0,
+ i = 0;
+ gboolean is_percentage = FALSE;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PEEK_BYTE (a_this, 1, &next_bytes[0]);
+ PEEK_BYTE (a_this, 2, &next_bytes[1]);
+ PEEK_BYTE (a_this, 3, &next_bytes[2]);
+
+ if (((next_bytes[0] == 'r') || (next_bytes[0] == 'R'))
+ && ((next_bytes[1] == 'g') || (next_bytes[1] == 'G'))
+ && ((next_bytes[2] == 'b') || (next_bytes[2] == 'B'))) {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this, &location) ;
+ SKIP_CHARS (a_this, 2);
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ READ_NEXT_BYTE (a_this, &cur_byte);
+ ENSURE_PARSING_COND (cur_byte == '(');
+
+ cr_tknzr_try_to_skip_spaces (a_this);
+ status = cr_tknzr_parse_num (a_this, &num);
+ ENSURE_PARSING_COND ((status == CR_OK) && (num != NULL));
+
+ red = (glong)num->val;
+ cr_num_destroy (num);
+ num = NULL;
+
+ PEEK_BYTE (a_this, 1, &next_bytes[0]);
+ if (next_bytes[0] == '%') {
+ SKIP_CHARS (a_this, 1);
+ is_percentage = TRUE;
+ }
+ cr_tknzr_try_to_skip_spaces (a_this);
+
+ for (i = 0; i < 2; i++) {
+ READ_NEXT_BYTE (a_this, &cur_byte);
+ ENSURE_PARSING_COND (cur_byte == ',');
+
+ cr_tknzr_try_to_skip_spaces (a_this);
+ status = cr_tknzr_parse_num (a_this, &num);
+ ENSURE_PARSING_COND ((status == CR_OK) && (num != NULL));
+
+ PEEK_BYTE (a_this, 1, &next_bytes[0]);
+ if (next_bytes[0] == '%') {
+ SKIP_CHARS (a_this, 1);
+ is_percentage = 1;
+ }
+
+ if (i == 0) {
+ green = (glong)num->val;
+ } else if (i == 1) {
+ blue = (glong)num->val;
+ }
+
+ if (num) {
+ cr_num_destroy (num);
+ num = NULL;
+ }
+ cr_tknzr_try_to_skip_spaces (a_this);
+ }
+
+ READ_NEXT_BYTE (a_this, &cur_byte);
+ if (*a_rgb == NULL) {
+ *a_rgb = cr_rgb_new_with_vals (red, green, blue,
+ is_percentage);
+
+ if (*a_rgb == NULL) {
+ status = CR_ERROR;
+ goto error;
+ }
+ status = CR_OK;
+ } else {
+ (*a_rgb)->red = red;
+ (*a_rgb)->green = green;
+ (*a_rgb)->blue = blue;
+ (*a_rgb)->is_percentage = is_percentage;
+
+ status = CR_OK;
+ }
+
+ if (status == CR_OK) {
+ if (a_rgb && *a_rgb) {
+ cr_parsing_location_copy
+ (&(*a_rgb)->location,
+ &location) ;
+ }
+ return CR_OK;
+ }
+
+ error:
+ if (num) {
+ cr_num_destroy (num);
+ num = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return CR_OK;
+}
+
+/**
+ *Parses a atkeyword as defined by the css spec in [4.1.1]:
+ *ATKEYWORD ::= @{ident}
+ *
+ *@param a_this the "this pointer" of the current instance of
+ *#CRTknzr.
+ *
+ *@param a_str out parameter. The parsed atkeyword. If *a_str is
+ *set to NULL this function allocates a new instance of CRString and
+ *sets it to the parsed atkeyword. If not, this function just appends
+ *the parsed atkeyword to the end of *a_str. In both cases it is up to
+ *the caller to free *a_str.
+ *
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_atkeyword (CRTknzr * a_this,
+ CRString ** a_str)
+{
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ gboolean str_needs_free = FALSE;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_str, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char != '@') {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ if (*a_str == NULL) {
+ *a_str = cr_string_new ();
+ str_needs_free = TRUE;
+ }
+ status = cr_tknzr_parse_ident (a_this, a_str);
+ if (status != CR_OK) {
+ goto error;
+ }
+ return CR_OK;
+ error:
+
+ if (str_needs_free == TRUE && *a_str) {
+ cr_string_destroy (*a_str);
+ *a_str = NULL;
+ }
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+static enum CRStatus
+cr_tknzr_parse_important (CRTknzr * a_this,
+ CRParsingLocation *a_location)
+{
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == '!');
+ if (a_location) {
+ cr_tknzr_get_parsing_location (a_this,
+ a_location) ;
+ }
+ cr_tknzr_try_to_skip_spaces (a_this);
+
+ if (BYTE (PRIVATE (a_this)->input, 1, NULL) == 'i'
+ && BYTE (PRIVATE (a_this)->input, 2, NULL) == 'm'
+ && BYTE (PRIVATE (a_this)->input, 3, NULL) == 'p'
+ && BYTE (PRIVATE (a_this)->input, 4, NULL) == 'o'
+ && BYTE (PRIVATE (a_this)->input, 5, NULL) == 'r'
+ && BYTE (PRIVATE (a_this)->input, 6, NULL) == 't'
+ && BYTE (PRIVATE (a_this)->input, 7, NULL) == 'a'
+ && BYTE (PRIVATE (a_this)->input, 8, NULL) == 'n'
+ && BYTE (PRIVATE (a_this)->input, 9, NULL) == 't') {
+ SKIP_BYTES (a_this, 9);
+ if (a_location) {
+ cr_tknzr_get_parsing_location (a_this,
+ a_location) ;
+ }
+ return CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ }
+
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a num as defined in the css spec [4.1.1]:
+ *[0-9]+|[0-9]*\.[0-9]+
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_num out parameter. The parsed number.
+ *@return CR_OK upon successful completion,
+ *an error code otherwise.
+ *
+ *The CSS specification says that numbers may be
+ *preceded by '+' or '-' to indicate the sign.
+ *Technically, the "num" construction as defined
+ *by the tokenizer doesn't allow this, but we parse
+ *it here for simplicity.
+ */
+static enum CRStatus
+cr_tknzr_parse_num (CRTknzr * a_this,
+ CRNum ** a_num)
+{
+ enum CRStatus status = CR_PARSING_ERROR;
+ enum CRNumType val_type = NUM_GENERIC;
+ gboolean parsing_dec, /* true iff seen decimal point. */
+ parsed, /* true iff the substring seen so far is a valid CSS
+ number, i.e. `[0-9]+|[0-9]*\.[0-9]+'. */
+ parsing_exp = FALSE; /* true if seen an exponential */
+ gdouble exponent = 0; /* Start off the exponent at 0 */
+ int exp_sign = 1;
+ guint32 cur_char = 0,
+ next_char = 0;
+ gdouble numerator, denominator = 1;
+ CRInputPos init_pos;
+ CRParsingLocation location = {0,0,0};
+ int sign = 1;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char == '+' || cur_char == '-') {
+ if (cur_char == '-') {
+ sign = -1;
+ }
+ READ_NEXT_CHAR (a_this, &cur_char);
+ }
+
+ if (IS_NUM (cur_char)) {
+ numerator = (cur_char - '0');
+ parsing_dec = FALSE;
+ parsed = TRUE;
+ } else if (cur_char == '.') {
+ numerator = 0;
+ parsing_dec = TRUE;
+ parsed = FALSE;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ cr_tknzr_get_parsing_location (a_this, &location) ;
+
+ for (;;) {
+ status = cr_tknzr_peek_char (a_this, &next_char);
+ if (status != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR)
+ status = CR_OK;
+ break;
+ }
+ if (next_char == '.') {
+ if (parsing_dec) {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+ parsing_dec = TRUE;
+ parsed = FALSE; /* In CSS, there must be at least
+ one digit after `.'. */
+ } else if (!parsing_exp && (next_char == 'E' || next_char == 'e') && parsed) {
+ guchar next_byte;
+ PEEK_BYTE (a_this, 2, &next_byte)
+ if (next_byte == '+') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ } else if (next_byte == '-') {
+ exp_sign = -1;
+ READ_NEXT_CHAR (a_this, &cur_char);
+ } else if (!IS_NUM (next_byte)) {
+ break;
+ }
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+ parsing_exp = TRUE;
+ parsed = FALSE;
+ } else if (IS_NUM (next_char)) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ parsed = TRUE;
+
+ if (parsing_exp) {
+ exponent = exponent * 10 + (cur_char - '0');
+ } else {
+ numerator = numerator * 10 + (cur_char - '0');
+ if (parsing_dec) {
+ denominator *= 10;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (!parsed) {
+ status = CR_PARSING_ERROR;
+ }
+
+ /*
+ *Now, set the output param values.
+ */
+ if (status == CR_OK) {
+ gdouble val = ((numerator / denominator) * sign) * pow(10, exponent * exp_sign);
+ if (*a_num == NULL) {
+ *a_num = cr_num_new_with_val (val, val_type);
+
+ if (*a_num == NULL) {
+ status = CR_ERROR;
+ goto error;
+ }
+ } else {
+ (*a_num)->val = val;
+ (*a_num)->type = val_type;
+ }
+ cr_parsing_location_copy (&(*a_num)->location,
+ &location) ;
+ return CR_OK;
+ }
+
+ error:
+
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+}
+
+/*********************************************
+ *PUBLIC methods
+ ********************************************/
+
+CRTknzr *
+cr_tknzr_new (CRInput * a_input)
+{
+ CRTknzr *result = NULL;
+
+ result = (CRTknzr *) g_try_malloc (sizeof (CRTknzr));
+
+ if (result == NULL) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRTknzr));
+
+ result->priv = (CRTknzrPriv *)g_try_malloc (sizeof (CRTknzrPriv));
+
+ if (result->priv == NULL) {
+ cr_utils_trace_info ("Out of memory");
+
+ if (result) {
+ g_free (result);
+ result = NULL;
+ }
+
+ return NULL;
+ }
+ memset (result->priv, 0, sizeof (CRTknzrPriv));
+ if (a_input)
+ cr_tknzr_set_input (result, a_input);
+ return result;
+}
+
+CRTknzr *
+cr_tknzr_new_from_buf (guchar * a_buf, gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_at_destroy)
+{
+ CRTknzr *result = NULL;
+ CRInput *input = NULL;
+
+ input = cr_input_new_from_buf (a_buf, a_len, a_enc,
+ a_free_at_destroy);
+
+ g_return_val_if_fail (input != NULL, NULL);
+
+ result = cr_tknzr_new (input);
+
+ return result;
+}
+
+CRTknzr *
+cr_tknzr_new_from_uri (const guchar * a_file_uri,
+ enum CREncoding a_enc)
+{
+ CRTknzr *result = NULL;
+ CRInput *input = NULL;
+
+ input = cr_input_new_from_uri ((const gchar *) a_file_uri, a_enc);
+ g_return_val_if_fail (input != NULL, NULL);
+
+ result = cr_tknzr_new (input);
+
+ return result;
+}
+
+void
+cr_tknzr_ref (CRTknzr * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ PRIVATE (a_this)->ref_count++;
+}
+
+gboolean
+cr_tknzr_unref (CRTknzr * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE);
+
+ if (PRIVATE (a_this)->ref_count > 0) {
+ PRIVATE (a_this)->ref_count--;
+ }
+
+ if (PRIVATE (a_this)->ref_count == 0) {
+ cr_tknzr_destroy (a_this);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+enum CRStatus
+cr_tknzr_set_input (CRTknzr * a_this, CRInput * a_input)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->input) {
+ cr_input_unref (PRIVATE (a_this)->input);
+ }
+
+ PRIVATE (a_this)->input = a_input;
+
+ cr_input_ref (PRIVATE (a_this)->input);
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_tknzr_get_input (CRTknzr * a_this, CRInput ** a_input)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ *a_input = PRIVATE (a_this)->input;
+
+ return CR_OK;
+}
+
+/*********************************
+ *Tokenizer input handling routines
+ *********************************/
+
+/**
+ *Reads the next byte from the parser input stream.
+ *@param a_this the "this pointer" of the current instance of
+ *#CRParser.
+ *@param a_byte out parameter the place where to store the byte
+ *read.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_tknzr_read_byte (CRTknzr * a_this, guchar * a_byte)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ return cr_input_read_byte (PRIVATE (a_this)->input, a_byte);
+
+}
+
+/**
+ *Reads the next char from the parser input stream.
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_char out parameter. The read char.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_tknzr_read_char (CRTknzr * a_this, guint32 * a_char)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_char, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_read_char (PRIVATE (a_this)->input, a_char);
+}
+
+/**
+ *Peeks a char from the parser input stream.
+ *To "peek a char" means reads the next char without consuming it.
+ *Subsequent calls to this function return the same char.
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_char out parameter. The peeked char upon successful completion.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_tknzr_peek_char (CRTknzr * a_this, guint32 * a_char)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_char, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_peek_char (PRIVATE (a_this)->input, a_char);
+}
+
+/**
+ *Peeks a byte ahead at a given position in the parser input stream.
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_offset the offset of the peeked byte starting from the current
+ *byte in the parser input stream.
+ *@param a_byte out parameter. The peeked byte upon
+ *successful completion.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_tknzr_peek_byte (CRTknzr * a_this, gulong a_offset, guchar * a_byte)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input && a_byte,
+ CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_peek_byte (PRIVATE (a_this)->input,
+ CR_SEEK_CUR, a_offset, a_byte);
+}
+
+/**
+ *Same as cr_tknzr_peek_byte() but this api returns the byte peeked.
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_offset the offset of the peeked byte starting from the current
+ *byte in the parser input stream.
+ *@param a_eof out parameter. If not NULL, is set to TRUE if we reached end of
+ *file, FALE otherwise. If the caller sets it to NULL, this parameter
+ *is just ignored.
+ *@return the peeked byte.
+ */
+guchar
+cr_tknzr_peek_byte2 (CRTknzr * a_this, gulong a_offset, gboolean * a_eof)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, 0);
+
+ return cr_input_peek_byte2 (PRIVATE (a_this)->input, a_offset, a_eof);
+}
+
+/**
+ *Gets the number of bytes left in the topmost input stream
+ *associated to this parser.
+ *@param a_this the current instance of #CRTknzr
+ *@return the number of bytes left or -1 in case of error.
+ */
+glong
+cr_tknzr_get_nb_bytes_left (CRTknzr * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_get_nb_bytes_left (PRIVATE (a_this)->input);
+}
+
+enum CRStatus
+cr_tknzr_get_cur_pos (CRTknzr * a_this, CRInputPos * a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_pos, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_get_cur_pos (PRIVATE (a_this)->input, a_pos);
+}
+
+enum CRStatus
+cr_tknzr_get_parsing_location (CRTknzr *a_this,
+ CRParsingLocation *a_loc)
+{
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && a_loc,
+ CR_BAD_PARAM_ERROR) ;
+
+ return cr_input_get_parsing_location
+ (PRIVATE (a_this)->input, a_loc) ;
+}
+
+enum CRStatus
+cr_tknzr_get_cur_byte_addr (CRTknzr * a_this, guchar ** a_addr)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_get_cur_byte_addr (PRIVATE (a_this)->input, a_addr);
+}
+
+enum CRStatus
+cr_tknzr_seek_index (CRTknzr * a_this, enum CRSeekPos a_origin, gint a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_seek_index (PRIVATE (a_this)->input, a_origin, a_pos);
+}
+
+enum CRStatus
+cr_tknzr_consume_chars (CRTknzr * a_this, guint32 a_char, glong * a_nb_char)
+{
+ gulong consumed = *(gulong *) a_nb_char;
+ enum CRStatus status;
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ status = cr_input_consume_chars (PRIVATE (a_this)->input,
+ a_char, &consumed);
+ *a_nb_char = (glong) consumed;
+ return status;
+}
+
+enum CRStatus
+cr_tknzr_set_cur_pos (CRTknzr * a_this, CRInputPos * a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_set_cur_pos (PRIVATE (a_this)->input, a_pos);
+}
+
+enum CRStatus
+cr_tknzr_unget_token (CRTknzr * a_this, CRToken * a_token)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->token_cache == NULL,
+ CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->token_cache = a_token;
+
+ return CR_OK;
+}
+
+/**
+ *Returns the next token of the input stream.
+ *This method is really central. Each parsing
+ *method calls it.
+ *@param a_this the current tokenizer.
+ *@param a_tk out parameter. The returned token.
+ *for the sake of mem leak avoidance, *a_tk must
+ *be NULL.
+ *@param CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_tknzr_get_next_token (CRTknzr * a_this, CRToken ** a_tk)
+{
+ enum CRStatus status = CR_OK;
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ guint32 next_char = 0;
+ guchar next_bytes[4] = { 0 };
+ gboolean reached_eof = FALSE;
+ CRInput *input = NULL;
+ CRString *str = NULL;
+ CRRgb *rgb = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_tk && *a_tk == NULL
+ && PRIVATE (a_this)->input,
+ CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ *a_tk = PRIVATE (a_this)->token_cache;
+ PRIVATE (a_this)->token_cache = NULL;
+ return CR_OK;
+ }
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_input_get_end_of_file
+ (PRIVATE (a_this)->input, &reached_eof);
+ ENSURE_PARSING_COND (status == CR_OK);
+
+ if (reached_eof == TRUE) {
+ status = CR_END_OF_INPUT_ERROR;
+ goto error;
+ }
+
+ input = PRIVATE (a_this)->input;
+
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ token = cr_token_new ();
+ ENSURE_PARSING_COND (token);
+
+ switch (next_char) {
+ case '@':
+ {
+ if (BYTE (input, 2, NULL) == 'f'
+ && BYTE (input, 3, NULL) == 'o'
+ && BYTE (input, 4, NULL) == 'n'
+ && BYTE (input, 5, NULL) == 't'
+ && BYTE (input, 6, NULL) == '-'
+ && BYTE (input, 7, NULL) == 'f'
+ && BYTE (input, 8, NULL) == 'a'
+ && BYTE (input, 9, NULL) == 'c'
+ && BYTE (input, 10, NULL) == 'e') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location
+ (a_this, &location) ;
+ SKIP_CHARS (a_this, 9);
+ status = cr_token_set_font_face_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+
+ if (BYTE (input, 2, NULL) == 'c'
+ && BYTE (input, 3, NULL) == 'h'
+ && BYTE (input, 4, NULL) == 'a'
+ && BYTE (input, 5, NULL) == 'r'
+ && BYTE (input, 6, NULL) == 's'
+ && BYTE (input, 7, NULL) == 'e'
+ && BYTE (input, 8, NULL) == 't') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location
+ (a_this, &location) ;
+ SKIP_CHARS (a_this, 7);
+ status = cr_token_set_charset_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+
+ if (BYTE (input, 2, NULL) == 'i'
+ && BYTE (input, 3, NULL) == 'm'
+ && BYTE (input, 4, NULL) == 'p'
+ && BYTE (input, 5, NULL) == 'o'
+ && BYTE (input, 6, NULL) == 'r'
+ && BYTE (input, 7, NULL) == 't') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location
+ (a_this, &location) ;
+ SKIP_CHARS (a_this, 6);
+ status = cr_token_set_import_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+
+ if (BYTE (input, 2, NULL) == 'm'
+ && BYTE (input, 3, NULL) == 'e'
+ && BYTE (input, 4, NULL) == 'd'
+ && BYTE (input, 5, NULL) == 'i'
+ && BYTE (input, 6, NULL) == 'a') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 5);
+ status = cr_token_set_media_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+
+ if (BYTE (input, 2, NULL) == 'p'
+ && BYTE (input, 3, NULL) == 'a'
+ && BYTE (input, 4, NULL) == 'g'
+ && BYTE (input, 5, NULL) == 'e') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 4);
+ status = cr_token_set_page_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+ status = cr_tknzr_parse_atkeyword (a_this, &str);
+ if (status == CR_OK) {
+ status = cr_token_set_atkeyword (token, str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ goto done;
+ }
+ }
+ break;
+
+ case 'u':
+
+ if (BYTE (input, 2, NULL) == 'r'
+ && BYTE (input, 3, NULL) == 'l'
+ && BYTE (input, 4, NULL) == '(') {
+ CRString *str2 = NULL;
+
+ status = cr_tknzr_parse_uri (a_this, &str2);
+ if (status == CR_OK) {
+ status = cr_token_set_uri (token, str2);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str2) {
+ cr_parsing_location_copy (&token->location,
+ &str2->location) ;
+ }
+ goto done;
+ }
+ }
+ goto fallback;
+ break;
+
+ case 'r':
+ if (BYTE (input, 2, NULL) == 'g'
+ && BYTE (input, 3, NULL) == 'b'
+ && BYTE (input, 4, NULL) == '(') {
+ status = cr_tknzr_parse_rgb (a_this, &rgb);
+ if (status == CR_OK && rgb) {
+ status = cr_token_set_rgb (token, rgb);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (rgb) {
+ cr_parsing_location_copy (&token->location,
+ &rgb->location) ;
+ }
+ rgb = NULL;
+ goto done;
+ }
+
+ }
+ goto fallback;
+ break;
+
+ case '<':
+ if (BYTE (input, 2, NULL) == '!'
+ && BYTE (input, 3, NULL) == '-'
+ && BYTE (input, 4, NULL) == '-') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 3);
+ status = cr_token_set_cdo (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+ break;
+
+ case '-':
+ if (BYTE (input, 2, NULL) == '-'
+ && BYTE (input, 3, NULL) == '>') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 2);
+ status = cr_token_set_cdc (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ } else {
+ status = cr_tknzr_parse_ident
+ (a_this, &str);
+ if (status == CR_OK) {
+ cr_token_set_ident
+ (token, str);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ goto done;
+ } else {
+ goto parse_number;
+ }
+ }
+ break;
+
+ case '~':
+ if (BYTE (input, 2, NULL) == '=') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 1);
+ status = cr_token_set_includes (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+ break;
+
+ case '|':
+ if (BYTE (input, 2, NULL) == '=') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 1);
+ status = cr_token_set_dashmatch (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+ break;
+
+ case '/':
+ if (BYTE (input, 2, NULL) == '*') {
+ status = cr_tknzr_parse_comment (a_this, &str);
+
+ if (status == CR_OK) {
+ status = cr_token_set_comment (token, str);
+ str = NULL;
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ goto done;
+ }
+ }
+ break ;
+
+ case ';':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_semicolon (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case '{':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_cbo (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ goto done;
+
+ case '}':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_cbc (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case '(':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_po (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case ')':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_pc (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case '[':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_bo (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case ']':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_bc (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ {
+ guchar *start = NULL,
+ *end = NULL;
+
+ status = cr_tknzr_parse_w (a_this, &start,
+ &end, &location);
+ if (status == CR_OK) {
+ status = cr_token_set_s (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ goto done;
+ }
+ }
+ break;
+
+ case '#':
+ {
+ status = cr_tknzr_parse_hash (a_this, &str);
+ if (status == CR_OK && str) {
+ status = cr_token_set_hash (token, str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ str = NULL;
+ goto done;
+ }
+ }
+ break;
+
+ case '\'':
+ case '"':
+ status = cr_tknzr_parse_string (a_this, &str);
+ if (status == CR_OK && str) {
+ status = cr_token_set_string (token, str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ str = NULL;
+ goto done;
+ }
+ break;
+
+ case '!':
+ status = cr_tknzr_parse_important (a_this, &location);
+ if (status == CR_OK) {
+ status = cr_token_set_important_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '.':
+ case '+':
+ /* '-' case is handled separately above for --> comments */
+ parse_number:
+ {
+ CRNum *num = NULL;
+
+ status = cr_tknzr_parse_num (a_this, &num);
+ if (status == CR_OK && num) {
+ next_bytes[0] = BYTE (input, 1, NULL);
+ next_bytes[1] = BYTE (input, 2, NULL);
+ next_bytes[2] = BYTE (input, 3, NULL);
+ next_bytes[3] = BYTE (input, 4, NULL);
+
+ if (next_bytes[0] == 'e'
+ && next_bytes[1] == 'm') {
+ num->type = NUM_LENGTH_EM;
+ status = cr_token_set_ems (token,
+ num);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'e'
+ && next_bytes[1] == 'x') {
+ num->type = NUM_LENGTH_EX;
+ status = cr_token_set_exs (token,
+ num);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'p'
+ && next_bytes[1] == 'x') {
+ num->type = NUM_LENGTH_PX;
+ status = cr_token_set_length
+ (token, num, LENGTH_PX_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'c'
+ && next_bytes[1] == 'm') {
+ num->type = NUM_LENGTH_CM;
+ status = cr_token_set_length
+ (token, num, LENGTH_CM_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'm'
+ && next_bytes[1] == 'm') {
+ num->type = NUM_LENGTH_MM;
+ status = cr_token_set_length
+ (token, num, LENGTH_MM_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'i'
+ && next_bytes[1] == 'n') {
+ num->type = NUM_LENGTH_IN;
+ status = cr_token_set_length
+ (token, num, LENGTH_IN_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'p'
+ && next_bytes[1] == 't') {
+ num->type = NUM_LENGTH_PT;
+ status = cr_token_set_length
+ (token, num, LENGTH_PT_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'p'
+ && next_bytes[1] == 'c') {
+ num->type = NUM_LENGTH_PC;
+ status = cr_token_set_length
+ (token, num, LENGTH_PC_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'd'
+ && next_bytes[1] == 'e'
+ && next_bytes[2] == 'g') {
+ num->type = NUM_ANGLE_DEG;
+ status = cr_token_set_angle
+ (token, num, ANGLE_DEG_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 3);
+ } else if (next_bytes[0] == 'r'
+ && next_bytes[1] == 'a'
+ && next_bytes[2] == 'd') {
+ num->type = NUM_ANGLE_RAD;
+ status = cr_token_set_angle
+ (token, num, ANGLE_RAD_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 3);
+ } else if (next_bytes[0] == 'g'
+ && next_bytes[1] == 'r'
+ && next_bytes[2] == 'a'
+ && next_bytes[3] == 'd') {
+ num->type = NUM_ANGLE_GRAD;
+ status = cr_token_set_angle
+ (token, num, ANGLE_GRAD_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 4);
+ } else if (next_bytes[0] == 'm'
+ && next_bytes[1] == 's') {
+ num->type = NUM_TIME_MS;
+ status = cr_token_set_time
+ (token, num, TIME_MS_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 's') {
+ num->type = NUM_TIME_S;
+ status = cr_token_set_time
+ (token, num, TIME_S_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 1);
+ } else if (next_bytes[0] == 'H'
+ && next_bytes[1] == 'z') {
+ num->type = NUM_FREQ_HZ;
+ status = cr_token_set_freq
+ (token, num, FREQ_HZ_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'k'
+ && next_bytes[1] == 'H'
+ && next_bytes[2] == 'z') {
+ num->type = NUM_FREQ_KHZ;
+ status = cr_token_set_freq
+ (token, num, FREQ_KHZ_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 3);
+ } else if (next_bytes[0] == '%') {
+ num->type = NUM_PERCENTAGE;
+ status = cr_token_set_percentage
+ (token, num);
+ num = NULL;
+ SKIP_CHARS (a_this, 1);
+ } else {
+ status = cr_tknzr_parse_ident (a_this,
+ &str);
+ if (status == CR_OK && str) {
+ num->type = NUM_UNKNOWN_TYPE;
+ status = cr_token_set_dimen
+ (token, num, str);
+ num = NULL;
+ CHECK_PARSING_STATUS (status,
+ TRUE);
+ str = NULL;
+ } else {
+ status = cr_token_set_number
+ (token, num);
+ num = NULL;
+ CHECK_PARSING_STATUS (status, CR_OK);
+ str = NULL;
+ }
+ }
+ if (token && token->u.num) {
+ cr_parsing_location_copy (&token->location,
+ &token->u.num->location) ;
+ } else {
+ status = CR_ERROR ;
+ }
+ goto done ;
+ }
+ }
+ break;
+
+ default:
+ fallback:
+ /*process the fallback cases here */
+
+ if (next_char == '\\'
+ || (cr_utils_is_nonascii (next_char) == TRUE)
+ || ((next_char >= 'a') && (next_char <= 'z'))
+ || ((next_char >= 'A') && (next_char <= 'Z'))) {
+ status = cr_tknzr_parse_ident (a_this, &str);
+ if (status == CR_OK && str) {
+ guint32 next_c = 0;
+
+ status = cr_input_peek_char
+ (PRIVATE (a_this)->input, &next_c);
+
+ if (status == CR_OK && next_c == '(') {
+
+ SKIP_CHARS (a_this, 1);
+ status = cr_token_set_function
+ (token, str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ /*ownership is transferred
+ *to token by cr_token_set_function.
+ */
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ str = NULL;
+ } else {
+ status = cr_token_set_ident (token,
+ str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ str = NULL;
+ }
+ goto done;
+ } else {
+ if (str) {
+ cr_string_destroy (str);
+ str = NULL;
+ }
+ }
+ }
+ break;
+ }
+
+ READ_NEXT_CHAR (a_this, &next_char);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_delim (token, next_char);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ done:
+
+ if (status == CR_OK && token) {
+ *a_tk = token;
+ /*
+ *store the previous position input stream pos.
+ */
+ memmove (&PRIVATE (a_this)->prev_pos,
+ &init_pos, sizeof (CRInputPos));
+ return CR_OK;
+ }
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (str) {
+ cr_string_destroy (str);
+ str = NULL;
+ }
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+
+}
+
+enum CRStatus
+cr_tknzr_parse_token (CRTknzr * a_this, enum CRTokenType a_type,
+ enum CRTokenExtraType a_et, gpointer a_res,
+ gpointer a_extra_res)
+{
+ enum CRStatus status = CR_OK;
+ CRToken *token = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_res, CR_BAD_PARAM_ERROR);
+
+ status = cr_tknzr_get_next_token (a_this, &token);
+ if (status != CR_OK)
+ return status;
+ if (token == NULL)
+ return CR_PARSING_ERROR;
+
+ if (token->type == a_type) {
+ switch (a_type) {
+ case NO_TK:
+ case S_TK:
+ case CDO_TK:
+ case CDC_TK:
+ case INCLUDES_TK:
+ case DASHMATCH_TK:
+ case IMPORT_SYM_TK:
+ case PAGE_SYM_TK:
+ case MEDIA_SYM_TK:
+ case FONT_FACE_SYM_TK:
+ case CHARSET_SYM_TK:
+ case IMPORTANT_SYM_TK:
+ status = CR_OK;
+ break;
+
+ case STRING_TK:
+ case IDENT_TK:
+ case HASH_TK:
+ case ATKEYWORD_TK:
+ case FUNCTION_TK:
+ case COMMENT_TK:
+ case URI_TK:
+ *((CRString **) a_res) = token->u.str;
+ token->u.str = NULL;
+ status = CR_OK;
+ break;
+
+ case EMS_TK:
+ case EXS_TK:
+ case PERCENTAGE_TK:
+ case NUMBER_TK:
+ *((CRNum **) a_res) = token->u.num;
+ token->u.num = NULL;
+ status = CR_OK;
+ break;
+
+ case LENGTH_TK:
+ case ANGLE_TK:
+ case TIME_TK:
+ case FREQ_TK:
+ if (token->extra_type == a_et) {
+ *((CRNum **) a_res) = token->u.num;
+ token->u.num = NULL;
+ status = CR_OK;
+ }
+ break;
+
+ case DIMEN_TK:
+ *((CRNum **) a_res) = token->u.num;
+ if (a_extra_res == NULL) {
+ status = CR_BAD_PARAM_ERROR;
+ goto error;
+ }
+
+ *((CRString **) a_extra_res) = token->dimen;
+ token->u.num = NULL;
+ token->dimen = NULL;
+ status = CR_OK;
+ break;
+
+ case DELIM_TK:
+ *((guint32 *) a_res) = token->u.unichar;
+ status = CR_OK;
+ break;
+
+ case UNICODERANGE_TK:
+ default:
+ status = CR_PARSING_ERROR;
+ break;
+ }
+
+ cr_token_destroy (token);
+ token = NULL;
+ } else {
+ cr_tknzr_unget_token (a_this, token);
+ token = NULL;
+ status = CR_PARSING_ERROR;
+ }
+
+ return status;
+
+ error:
+
+ if (token) {
+ cr_tknzr_unget_token (a_this, token);
+ token = NULL;
+ }
+
+ return status;
+}
+
+void
+cr_tknzr_destroy (CRTknzr * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (PRIVATE (a_this) && PRIVATE (a_this)->input) {
+ if (cr_input_unref (PRIVATE (a_this)->input)
+ == TRUE) {
+ PRIVATE (a_this)->input = NULL;
+ }
+ }
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ if (PRIVATE (a_this)) {
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-tknzr.h b/src/3rdparty/libcroco/src/cr-tknzr.h
new file mode 100644
index 0000000..13985b3
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-tknzr.h
@@ -0,0 +1,115 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for coypyright information.
+ */
+
+/**
+ *@file
+ *The declaration of the #CRTknzr (tokenizer)
+ *class.
+ */
+
+#ifndef __CR_TKNZR_H__
+#define __CR_TKNZR_H__
+
+#include "cr-utils.h"
+#include "cr-input.h"
+#include "cr-token.h"
+
+G_BEGIN_DECLS
+
+
+typedef struct _CRTknzr CRTknzr ;
+typedef struct _CRTknzrPriv CRTknzrPriv ;
+
+/**
+ *The tokenizer is the class that knows
+ *about all the css token. Its main job is
+ *to return the next token found in the character
+ *input stream.
+ */
+struct _CRTknzr
+{
+ /*the private data of the tokenizer.*/
+ CRTknzrPriv *priv ;
+} ;
+
+CRTknzr * cr_tknzr_new (CRInput *a_input) ;
+
+CRTknzr * cr_tknzr_new_from_uri (const guchar *a_file_uri,
+ enum CREncoding a_enc) ;
+
+CRTknzr * cr_tknzr_new_from_buf (guchar *a_buf, gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_at_destroy) ;
+
+gboolean cr_tknzr_unref (CRTknzr *a_this) ;
+
+void cr_tknzr_ref (CRTknzr *a_this) ;
+
+enum CRStatus cr_tknzr_read_byte (CRTknzr *a_this, guchar *a_byte) ;
+
+enum CRStatus cr_tknzr_read_char (CRTknzr *a_this, guint32 *a_char);
+
+enum CRStatus cr_tknzr_peek_char (CRTknzr *a_this, guint32 *a_char) ;
+
+enum CRStatus cr_tknzr_peek_byte (CRTknzr *a_this, gulong a_offset,
+ guchar *a_byte) ;
+
+guchar cr_tknzr_peek_byte2 (CRTknzr *a_this, gulong a_offset,
+ gboolean *a_eof) ;
+
+enum CRStatus cr_tknzr_set_cur_pos (CRTknzr *a_this, CRInputPos *a_pos) ;
+
+glong cr_tknzr_get_nb_bytes_left (CRTknzr *a_this) ;
+
+enum CRStatus cr_tknzr_get_cur_pos (CRTknzr *a_this, CRInputPos *a_pos) ;
+
+enum CRStatus cr_tknzr_get_parsing_location (CRTknzr *a_this,
+ CRParsingLocation *a_loc) ;
+
+enum CRStatus cr_tknzr_seek_index (CRTknzr *a_this,
+ enum CRSeekPos a_origin,
+ gint a_pos) ;
+
+enum CRStatus cr_tknzr_get_cur_byte_addr (CRTknzr *a_this, guchar **a_addr) ;
+
+
+enum CRStatus cr_tknzr_consume_chars (CRTknzr *a_this, guint32 a_char,
+ glong *a_nb_char) ;
+
+enum CRStatus cr_tknzr_get_next_token (CRTknzr *a_this, CRToken ** a_tk) ;
+
+enum CRStatus cr_tknzr_unget_token (CRTknzr *a_this, CRToken *a_token) ;
+
+
+enum CRStatus cr_tknzr_parse_token (CRTknzr *a_this, enum CRTokenType a_type,
+ enum CRTokenExtraType a_et, gpointer a_res,
+ gpointer a_extra_res) ;
+enum CRStatus cr_tknzr_set_input (CRTknzr *a_this, CRInput *a_input) ;
+
+enum CRStatus cr_tknzr_get_input (CRTknzr *a_this, CRInput **a_input) ;
+
+void cr_tknzr_destroy (CRTknzr *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_TKZNR_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-token.c b/src/3rdparty/libcroco/src/cr-token.c
new file mode 100644
index 0000000..95226d7
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-token.c
@@ -0,0 +1,636 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * see COPYRIGHTS file for copyright information.
+ */
+
+/**
+ *@file
+ *The definition of the #CRToken class.
+ *Abstracts a css2 token.
+ */
+#include <string.h>
+#include "cr-token.h"
+
+/*
+ *TODO: write a CRToken::to_string() method.
+ */
+
+/**
+ *Frees the attributes of the current instance
+ *of #CRtoken.
+ *@param a_this the current instance of #CRToken.
+ */
+static void
+cr_token_clear (CRToken * a_this)
+{
+ g_return_if_fail (a_this);
+
+ switch (a_this->type) {
+ case S_TK:
+ case CDO_TK:
+ case CDC_TK:
+ case INCLUDES_TK:
+ case DASHMATCH_TK:
+ case PAGE_SYM_TK:
+ case MEDIA_SYM_TK:
+ case FONT_FACE_SYM_TK:
+ case CHARSET_SYM_TK:
+ case IMPORT_SYM_TK:
+ case IMPORTANT_SYM_TK:
+ case SEMICOLON_TK:
+ case NO_TK:
+ case DELIM_TK:
+ case CBO_TK:
+ case CBC_TK:
+ case BO_TK:
+ case BC_TK:
+ break;
+
+ case STRING_TK:
+ case IDENT_TK:
+ case HASH_TK:
+ case URI_TK:
+ case FUNCTION_TK:
+ case COMMENT_TK:
+ case ATKEYWORD_TK:
+ if (a_this->u.str) {
+ cr_string_destroy (a_this->u.str);
+ a_this->u.str = NULL;
+ }
+ break;
+
+ case EMS_TK:
+ case EXS_TK:
+ case LENGTH_TK:
+ case ANGLE_TK:
+ case TIME_TK:
+ case FREQ_TK:
+ case PERCENTAGE_TK:
+ case NUMBER_TK:
+ case PO_TK:
+ case PC_TK:
+ if (a_this->u.num) {
+ cr_num_destroy (a_this->u.num);
+ a_this->u.num = NULL;
+ }
+ break;
+
+ case DIMEN_TK:
+ if (a_this->u.num) {
+ cr_num_destroy (a_this->u.num);
+ a_this->u.num = NULL;
+ }
+
+ if (a_this->dimen) {
+ cr_string_destroy (a_this->dimen);
+ a_this->dimen = NULL;
+ }
+
+ break;
+
+ case RGB_TK:
+ if (a_this->u.rgb) {
+ cr_rgb_destroy (a_this->u.rgb) ;
+ a_this->u.rgb = NULL ;
+ }
+ break ;
+
+ case UNICODERANGE_TK:
+ /*not supported yet. */
+ break;
+
+ default:
+ cr_utils_trace_info ("I don't know how to clear this token\n") ;
+ break;
+ }
+
+ a_this->type = NO_TK;
+}
+
+/**
+ *Default constructor of
+ *the #CRToken class.
+ *@return the newly built instance of #CRToken.
+ */
+CRToken *
+cr_token_new (void)
+{
+ CRToken *result = NULL;
+
+ result = (CRToken *) g_try_malloc (sizeof (CRToken));
+
+ if (result == NULL) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRToken));
+
+ return result;
+}
+
+/**
+ *Sets the type of curren instance of
+ *#CRToken to 'S_TK' (S in the css2 spec)
+ *@param a_this the current instance of #CRToken.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_token_set_s (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = S_TK;
+
+ return CR_OK;
+}
+
+/**
+ *Sets the type of the current instance of
+ *#CRToken to 'CDO_TK' (CDO as said by the css2 spec)
+ *@param a_this the current instance of #CRToken.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_token_set_cdo (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = CDO_TK;
+
+ return CR_OK;
+}
+
+/**
+ *Sets the type of the current token to
+ *CDC_TK (CDC as said by the css2 spec).
+ *@param a_this the current instance of #CRToken.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_token_set_cdc (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = CDC_TK;
+
+ return CR_OK;
+}
+
+/**
+ *Sets the type of the current instance of
+ *#CRToken to INCLUDES_TK (INCLUDES as said by the css2 spec).
+ *@param a_this the current instance of #CRToken.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_token_set_includes (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = INCLUDES_TK;
+
+ return CR_OK;
+}
+
+/**
+ *Sets the type of the current instance of
+ *#CRToken to DASHMATCH_TK (DASHMATCH as said by the css2 spec).
+ *@param a_this the current instance of #CRToken.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_token_set_dashmatch (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = DASHMATCH_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_comment (CRToken * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = COMMENT_TK;
+ a_this->u.str = a_str ;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_string (CRToken * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = STRING_TK;
+
+ a_this->u.str = a_str ;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_ident (CRToken * a_this, CRString * a_ident)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = IDENT_TK;
+ a_this->u.str = a_ident;
+ return CR_OK;
+}
+
+
+enum CRStatus
+cr_token_set_function (CRToken * a_this, CRString * a_fun_name)
+{
+ g_return_val_if_fail (a_this,
+ CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = FUNCTION_TK;
+ a_this->u.str = a_fun_name;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_hash (CRToken * a_this, CRString * a_hash)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = HASH_TK;
+ a_this->u.str = a_hash;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_rgb (CRToken * a_this, CRRgb * a_rgb)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = RGB_TK;
+ a_this->u.rgb = a_rgb;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_import_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = IMPORT_SYM_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_page_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = PAGE_SYM_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_media_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = MEDIA_SYM_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_font_face_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = FONT_FACE_SYM_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_charset_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = CHARSET_SYM_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_atkeyword (CRToken * a_this, CRString * a_atname)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = ATKEYWORD_TK;
+ a_this->u.str = a_atname;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_important_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ cr_token_clear (a_this);
+ a_this->type = IMPORTANT_SYM_TK;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_ems (CRToken * a_this, CRNum * a_num)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ cr_token_clear (a_this);
+ a_this->type = EMS_TK;
+ a_this->u.num = a_num;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_exs (CRToken * a_this, CRNum * a_num)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ cr_token_clear (a_this);
+ a_this->type = EXS_TK;
+ a_this->u.num = a_num;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_length (CRToken * a_this, CRNum * a_num,
+ enum CRTokenExtraType a_et)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = LENGTH_TK;
+ a_this->extra_type = a_et;
+ a_this->u.num = a_num;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_angle (CRToken * a_this, CRNum * a_num,
+ enum CRTokenExtraType a_et)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = ANGLE_TK;
+ a_this->extra_type = a_et;
+ a_this->u.num = a_num;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_time (CRToken * a_this, CRNum * a_num,
+ enum CRTokenExtraType a_et)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = TIME_TK;
+ a_this->extra_type = a_et;
+ a_this->u.num = a_num;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_freq (CRToken * a_this, CRNum * a_num,
+ enum CRTokenExtraType a_et)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = FREQ_TK;
+ a_this->extra_type = a_et;
+ a_this->u.num = a_num;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_dimen (CRToken * a_this, CRNum * a_num,
+ CRString * a_dim)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ cr_token_clear (a_this);
+ a_this->type = DIMEN_TK;
+ a_this->u.num = a_num;
+ a_this->dimen = a_dim;
+ return CR_OK;
+
+}
+
+enum CRStatus
+cr_token_set_percentage (CRToken * a_this, CRNum * a_num)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = PERCENTAGE_TK;
+ a_this->u.num = a_num;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_number (CRToken * a_this, CRNum * a_num)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = NUMBER_TK;
+ a_this->u.num = a_num;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_uri (CRToken * a_this, CRString * a_uri)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = URI_TK;
+ a_this->u.str = a_uri;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_delim (CRToken * a_this, guint32 a_char)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = DELIM_TK;
+ a_this->u.unichar = a_char;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_semicolon (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = SEMICOLON_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_cbo (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = CBO_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_cbc (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = CBC_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_po (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = PO_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_pc (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = PC_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_bo (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = BO_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_bc (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = BC_TK;
+
+ return CR_OK;
+}
+
+/**
+ *The destructor of the #CRToken class.
+ *@param a_this the current instance of #CRToken.
+ */
+void
+cr_token_destroy (CRToken * a_this)
+{
+ g_return_if_fail (a_this);
+
+ cr_token_clear (a_this);
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-token.h b/src/3rdparty/libcroco/src/cr-token.h
new file mode 100644
index 0000000..35e914d
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-token.h
@@ -0,0 +1,212 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_TOKEN_H__
+#define __CR_TOKEN_H__
+
+#include "cr-utils.h"
+#include "cr-input.h"
+#include "cr-num.h"
+#include "cr-rgb.h"
+#include "cr-string.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+enum CRTokenType
+{
+ NO_TK, // 0
+ S_TK,
+ CDO_TK,
+ CDC_TK,
+ INCLUDES_TK,
+ DASHMATCH_TK, // 5
+ COMMENT_TK,
+ STRING_TK,
+ IDENT_TK,
+ HASH_TK,
+ IMPORT_SYM_TK, // 10
+ PAGE_SYM_TK,
+ MEDIA_SYM_TK,
+ FONT_FACE_SYM_TK,
+ CHARSET_SYM_TK,
+ ATKEYWORD_TK, // 15
+ IMPORTANT_SYM_TK,
+ EMS_TK,
+ EXS_TK,
+ LENGTH_TK,
+ ANGLE_TK, // 20
+ TIME_TK,
+ FREQ_TK,
+ DIMEN_TK,
+ PERCENTAGE_TK,
+ NUMBER_TK, // 25
+ RGB_TK,
+ URI_TK,
+ FUNCTION_TK,
+ UNICODERANGE_TK,
+ SEMICOLON_TK, // 30
+ CBO_TK, /*opening curly bracket*/
+ CBC_TK, /*closing curly bracket*/
+ PO_TK, /*opening parenthesis*/
+ PC_TK, /*closing parenthesis*/
+ BO_TK, /*opening bracket*/
+ BC_TK, /*closing bracket*/
+ DELIM_TK
+} ;
+
+enum CRTokenExtraType
+{
+ NO_ET = 0,
+ LENGTH_PX_ET,
+ LENGTH_CM_ET,
+ LENGTH_MM_ET,
+ LENGTH_IN_ET,
+ LENGTH_PT_ET,
+ LENGTH_PC_ET,
+ ANGLE_DEG_ET,
+ ANGLE_RAD_ET,
+ ANGLE_GRAD_ET,
+ TIME_MS_ET,
+ TIME_S_ET,
+ FREQ_HZ_ET,
+ FREQ_KHZ_ET
+} ;
+
+typedef struct _CRToken CRToken ;
+
+/**
+ *This class abstracts a css2 token.
+ */
+struct _CRToken
+{
+ enum CRTokenType type ;
+ enum CRTokenExtraType extra_type ;
+ CRInputPos pos ;
+
+ union
+ {
+ CRString *str ;
+ CRRgb *rgb ;
+ CRNum *num ;
+ guint32 unichar ;
+ } u ;
+
+ CRString * dimen ;
+ CRParsingLocation location ;
+} ;
+
+CRToken* cr_token_new (void) ;
+
+enum CRStatus cr_token_set_s (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_cdo (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_cdc (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_includes (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_dashmatch (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_comment (CRToken *a_this, CRString *a_str) ;
+
+enum CRStatus cr_token_set_string (CRToken *a_this, CRString *a_str) ;
+
+enum CRStatus cr_token_set_ident (CRToken *a_this, CRString * a_ident) ;
+
+enum CRStatus cr_token_set_hash (CRToken *a_this, CRString *a_hash) ;
+
+enum CRStatus cr_token_set_rgb (CRToken *a_this, CRRgb *a_rgb) ;
+
+enum CRStatus cr_token_set_import_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_page_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_media_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_font_face_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_charset_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_atkeyword (CRToken *a_this, CRString *a_atname) ;
+
+enum CRStatus cr_token_set_important_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_ems (CRToken *a_this, CRNum *a_num) ;
+
+enum CRStatus cr_token_set_exs (CRToken *a_this, CRNum *a_num) ;
+
+enum CRStatus cr_token_set_length (CRToken *a_this, CRNum *a_num,
+ enum CRTokenExtraType a_et) ;
+
+enum CRStatus cr_token_set_angle (CRToken *a_this, CRNum *a_num,
+ enum CRTokenExtraType a_et) ;
+
+enum CRStatus cr_token_set_time (CRToken *a_this, CRNum *a_num,
+ enum CRTokenExtraType a_et) ;
+
+enum CRStatus cr_token_set_freq (CRToken *a_this, CRNum *a_num,
+ enum CRTokenExtraType a_et) ;
+
+enum CRStatus cr_token_set_dimen (CRToken *a_this, CRNum *a_num,
+ CRString *a_dim) ;
+
+enum CRStatus cr_token_set_percentage (CRToken *a_this, CRNum *a_num) ;
+
+enum CRStatus cr_token_set_number (CRToken *a_this, CRNum *a_num) ;
+
+enum CRStatus cr_token_set_uri (CRToken *a_this, CRString *a_uri) ;
+
+enum CRStatus cr_token_set_function (CRToken *a_this,
+ CRString *a_fun_name) ;
+
+enum CRStatus cr_token_set_bc (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_bo (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_po (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_pc (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_cbc (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_cbo (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_semicolon (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_delim (CRToken *a_this, guint32 a_char) ;
+
+
+/*
+ enum CRStatus
+ cr_token_set_unicoderange (CRToken *a_this,
+ CRUnicodeRange *a_range) ;
+*/
+
+void
+cr_token_destroy (CRToken *a_this) ;
+
+
+G_END_DECLS
+
+#endif /*__CR_TOKEN_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-utils.c b/src/3rdparty/libcroco/src/cr-utils.c
new file mode 100644
index 0000000..523362a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-utils.c
@@ -0,0 +1,1330 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include "cr-utils.h"
+#include "cr-string.h"
+
+/**
+ *@file:
+ *Some misc utility functions used
+ *in the libcroco.
+ *Note that troughout this file I will
+ *refer to the CSS SPECIFICATIONS DOCUMENTATION
+ *written by the w3c guys. You can find that document
+ *at http://www.w3.org/TR/REC-CSS2/ .
+ */
+
+/****************************
+ *Encoding transformations and
+ *encoding helpers
+ ****************************/
+
+/*
+ *Here is the correspondence between the ucs-4 charactere codes
+ *and there matching utf-8 encoding pattern as dscribed by RFC 2279:
+ *
+ *UCS-4 range (hex.) UTF-8 octet sequence (binary)
+ *------------------ -----------------------------
+ *0000 0000-0000 007F 0xxxxxxx
+ *0000 0080-0000 07FF 110xxxxx 10xxxxxx
+ *0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
+ *0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ *0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ *0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx
+ */
+
+/**
+ *Given an utf8 string buffer, calculates
+ *the length of this string if it was encoded
+ *in ucs4.
+ *@param a_in_start a pointer to the beginning of
+ *the input utf8 string.
+ *@param a_in_end a pointre to the end of the input
+ *utf8 string (points to the last byte of the buffer)
+ *@param a_len out parameter the calculated length.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_utils_utf8_str_len_as_ucs4 (const guchar * a_in_start,
+ const guchar * a_in_end, gulong * a_len)
+{
+ guchar *byte_ptr = NULL;
+ gint len = 0;
+
+ /*
+ *to store the final decoded
+ *unicode char
+ */
+ guint c = 0;
+
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
+ CR_BAD_PARAM_ERROR);
+ *a_len = 0;
+
+ for (byte_ptr = (guchar *) a_in_start;
+ byte_ptr <= a_in_end; byte_ptr++) {
+ gint nb_bytes_2_decode = 0;
+
+ if (*byte_ptr <= 0x7F) {
+ /*
+ *7 bits long char
+ *encoded over 1 byte:
+ * 0xxx xxxx
+ */
+ c = *byte_ptr;
+ nb_bytes_2_decode = 1;
+
+ } else if ((*byte_ptr & 0xE0) == 0xC0) {
+ /*
+ *up to 11 bits long char.
+ *encoded over 2 bytes:
+ *110x xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x1F;
+ nb_bytes_2_decode = 2;
+
+ } else if ((*byte_ptr & 0xF0) == 0xE0) {
+ /*
+ *up to 16 bit long char
+ *encoded over 3 bytes:
+ *1110 xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x0F;
+ nb_bytes_2_decode = 3;
+
+ } else if ((*byte_ptr & 0xF8) == 0xF0) {
+ /*
+ *up to 21 bits long char
+ *encoded over 4 bytes:
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x7;
+ nb_bytes_2_decode = 4;
+
+ } else if ((*byte_ptr & 0xFC) == 0xF8) {
+ /*
+ *up to 26 bits long char
+ *encoded over 5 bytes.
+ *1111 10xx 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 3;
+ nb_bytes_2_decode = 5;
+
+ } else if ((*byte_ptr & 0xFE) == 0xFC) {
+ /*
+ *up to 31 bits long char
+ *encoded over 6 bytes:
+ *1111 110x 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 1;
+ nb_bytes_2_decode = 6;
+
+ } else {
+ /*
+ *BAD ENCODING
+ */
+ return CR_ENCODING_ERROR;
+ }
+
+ /*
+ *Go and decode the remaining byte(s)
+ *(if any) to get the current character.
+ */
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
+ /*decode the next byte */
+ byte_ptr++;
+
+ /*byte pattern must be: 10xx xxxx */
+ if ((*byte_ptr & 0xC0) != 0x80) {
+ return CR_ENCODING_ERROR;
+ }
+
+ c = (c << 6) | (*byte_ptr & 0x3F);
+ }
+
+ len++;
+ }
+
+ *a_len = len;
+
+ return CR_OK;
+}
+
+/**
+ *Given an ucs4 string, this function
+ *returns the size (in bytes) this string
+ *would have occupied if it was encoded in utf-8.
+ *@param a_in_start a pointer to the beginning of the input
+ *buffer.
+ *@param a_in_end a pointer to the end of the input buffer.
+ *@param a_len out parameter. The computed length.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_ucs4_str_len_as_utf8 (const guint32 * a_in_start,
+ const guint32 * a_in_end, gulong * a_len)
+{
+ gint len = 0;
+ guint32 *char_ptr = NULL;
+
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
+ CR_BAD_PARAM_ERROR);
+
+ for (char_ptr = (guint32 *) a_in_start;
+ char_ptr <= a_in_end; char_ptr++) {
+ if (*char_ptr <= 0x7F) {
+ /*the utf-8 char would take 1 byte */
+ len += 1;
+ } else if (*char_ptr <= 0x7FF) {
+ /*the utf-8 char would take 2 bytes */
+ len += 2;
+ } else if (*char_ptr <= 0xFFFF) {
+ len += 3;
+ } else if (*char_ptr <= 0x1FFFFF) {
+ len += 4;
+ } else if (*char_ptr <= 0x3FFFFFF) {
+ len += 5;
+ } else if (*char_ptr <= 0x7FFFFFFF) {
+ len += 6;
+ }
+ }
+
+ *a_len = len;
+ return CR_OK;
+}
+
+/**
+ *Given an ucsA string, this function
+ *returns the size (in bytes) this string
+ *would have occupied if it was encoded in utf-8.
+ *@param a_in_start a pointer to the beginning of the input
+ *buffer.
+ *@param a_in_end a pointer to the end of the input buffer.
+ *@param a_len out parameter. The computed length.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_ucs1_str_len_as_utf8 (const guchar * a_in_start,
+ const guchar * a_in_end, gulong * a_len)
+{
+ gint len = 0;
+ guchar *char_ptr = NULL;
+
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
+ CR_BAD_PARAM_ERROR);
+
+ for (char_ptr = (guchar *) a_in_start;
+ char_ptr <= a_in_end; char_ptr++) {
+ if (*char_ptr <= 0x7F) {
+ /*the utf-8 char would take 1 byte */
+ len += 1;
+ } else {
+ /*the utf-8 char would take 2 bytes */
+ len += 2;
+ }
+ }
+
+ *a_len = len;
+ return CR_OK;
+}
+
+/**
+ *Converts an utf8 buffer into an ucs4 buffer.
+ *
+ *@param a_in the input utf8 buffer to convert.
+ *@param a_in_len in/out parameter. The size of the
+ *input buffer to convert. After return, this parameter contains
+ *the actual number of bytes consumed.
+ *@param a_out the output converted ucs4 buffer. Must be allocated by
+ *the caller.
+ *@param a_out_len in/out parameter. The size of the output buffer.
+ *If this size is actually smaller than the real needed size, the function
+ *just converts what it can and returns a success status. After return,
+ *this param points to the actual number of characters decoded.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_utf8_to_ucs4 (const guchar * a_in,
+ gulong * a_in_len, guint32 * a_out, gulong * a_out_len)
+{
+ gulong in_len = 0,
+ out_len = 0,
+ in_index = 0,
+ out_index = 0;
+ enum CRStatus status = CR_OK;
+
+ /*
+ *to store the final decoded
+ *unicode char
+ */
+ guint c = 0;
+
+ g_return_val_if_fail (a_in && a_in_len
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len < 1) {
+ status = CR_OK;
+ goto end;
+ }
+
+ in_len = *a_in_len;
+ out_len = *a_out_len;
+
+ for (in_index = 0, out_index = 0;
+ (in_index < in_len) && (out_index < out_len);
+ in_index++, out_index++) {
+ gint nb_bytes_2_decode = 0;
+
+ if (a_in[in_index] <= 0x7F) {
+ /*
+ *7 bits long char
+ *encoded over 1 byte:
+ * 0xxx xxxx
+ */
+ c = a_in[in_index];
+ nb_bytes_2_decode = 1;
+
+ } else if ((a_in[in_index] & 0xE0) == 0xC0) {
+ /*
+ *up to 11 bits long char.
+ *encoded over 2 bytes:
+ *110x xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x1F;
+ nb_bytes_2_decode = 2;
+
+ } else if ((a_in[in_index] & 0xF0) == 0xE0) {
+ /*
+ *up to 16 bit long char
+ *encoded over 3 bytes:
+ *1110 xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x0F;
+ nb_bytes_2_decode = 3;
+
+ } else if ((a_in[in_index] & 0xF8) == 0xF0) {
+ /*
+ *up to 21 bits long char
+ *encoded over 4 bytes:
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x7;
+ nb_bytes_2_decode = 4;
+
+ } else if ((a_in[in_index] & 0xFC) == 0xF8) {
+ /*
+ *up to 26 bits long char
+ *encoded over 5 bytes.
+ *1111 10xx 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 3;
+ nb_bytes_2_decode = 5;
+
+ } else if ((a_in[in_index] & 0xFE) == 0xFC) {
+ /*
+ *up to 31 bits long char
+ *encoded over 6 bytes:
+ *1111 110x 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 1;
+ nb_bytes_2_decode = 6;
+
+ } else {
+ /*BAD ENCODING */
+ goto end;
+ }
+
+ /*
+ *Go and decode the remaining byte(s)
+ *(if any) to get the current character.
+ */
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
+ /*decode the next byte */
+ in_index++;
+
+ /*byte pattern must be: 10xx xxxx */
+ if ((a_in[in_index] & 0xC0) != 0x80) {
+ goto end;
+ }
+
+ c = (c << 6) | (a_in[in_index] & 0x3F);
+ }
+
+ /*
+ *The decoded ucs4 char is now
+ *in c.
+ */
+
+ /************************
+ *Some security tests
+ ***********************/
+
+ /*be sure c is a char */
+ if (c == 0xFFFF || c == 0xFFFE)
+ goto end;
+
+ /*be sure c is inferior to the max ucs4 char value */
+ if (c > 0x10FFFF)
+ goto end;
+
+ /*
+ *c must be less than UTF16 "lower surrogate begin"
+ *or higher than UTF16 "High surrogate end"
+ */
+ if (c >= 0xD800 && c <= 0xDFFF)
+ goto end;
+
+ /*Avoid characters that equals zero */
+ if (c == 0)
+ goto end;
+
+ a_out[out_index] = c;
+ }
+
+ end:
+ *a_out_len = out_index + 1;
+ *a_in_len = in_index + 1;
+
+ return status;
+}
+
+/**
+ *Reads a character from an utf8 buffer.
+ *Actually decode the next character code (unicode character code)
+ *and returns it.
+ *@param a_in the starting address of the utf8 buffer.
+ *@param a_in_len the length of the utf8 buffer.
+ *@param a_out output parameter. The resulting read char.
+ *@param a_consumed the number of the bytes consumed to
+ *decode the returned character code.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_read_char_from_utf8_buf (const guchar * a_in,
+ gulong a_in_len,
+ guint32 * a_out, gulong * a_consumed)
+{
+ gulong in_index = 0,
+ nb_bytes_2_decode = 0;
+ enum CRStatus status = CR_OK;
+
+ /*
+ *to store the final decoded
+ *unicode char
+ */
+ guint32 c = 0;
+
+ g_return_val_if_fail (a_in && a_out && a_out
+ && a_consumed, CR_BAD_PARAM_ERROR);
+
+ if (a_in_len < 1) {
+ status = CR_OK;
+ goto end;
+ }
+
+ if (*a_in <= 0x7F) {
+ /*
+ *7 bits long char
+ *encoded over 1 byte:
+ * 0xxx xxxx
+ */
+ c = *a_in;
+ nb_bytes_2_decode = 1;
+
+ } else if ((*a_in & 0xE0) == 0xC0) {
+ /*
+ *up to 11 bits long char.
+ *encoded over 2 bytes:
+ *110x xxxx 10xx xxxx
+ */
+ c = *a_in & 0x1F;
+ nb_bytes_2_decode = 2;
+
+ } else if ((*a_in & 0xF0) == 0xE0) {
+ /*
+ *up to 16 bit long char
+ *encoded over 3 bytes:
+ *1110 xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *a_in & 0x0F;
+ nb_bytes_2_decode = 3;
+
+ } else if ((*a_in & 0xF8) == 0xF0) {
+ /*
+ *up to 21 bits long char
+ *encoded over 4 bytes:
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *a_in & 0x7;
+ nb_bytes_2_decode = 4;
+
+ } else if ((*a_in & 0xFC) == 0xF8) {
+ /*
+ *up to 26 bits long char
+ *encoded over 5 bytes.
+ *1111 10xx 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx
+ */
+ c = *a_in & 3;
+ nb_bytes_2_decode = 5;
+
+ } else if ((*a_in & 0xFE) == 0xFC) {
+ /*
+ *up to 31 bits long char
+ *encoded over 6 bytes:
+ *1111 110x 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *a_in & 1;
+ nb_bytes_2_decode = 6;
+
+ } else {
+ /*BAD ENCODING */
+ goto end;
+ }
+
+ if (nb_bytes_2_decode > a_in_len) {
+ status = CR_END_OF_INPUT_ERROR;
+ goto end;
+ }
+
+ /*
+ *Go and decode the remaining byte(s)
+ *(if any) to get the current character.
+ */
+ for (in_index = 1; in_index < nb_bytes_2_decode; in_index++) {
+ /*byte pattern must be: 10xx xxxx */
+ if ((a_in[in_index] & 0xC0) != 0x80) {
+ goto end;
+ }
+
+ c = (c << 6) | (a_in[in_index] & 0x3F);
+ }
+
+ /*
+ *The decoded ucs4 char is now
+ *in c.
+ */
+
+ /************************
+ *Some security tests
+ ***********************/
+
+ /*be sure c is a char */
+ if (c == 0xFFFF || c == 0xFFFE)
+ goto end;
+
+ /*be sure c is inferior to the max ucs4 char value */
+ if (c > 0x10FFFF)
+ goto end;
+
+ /*
+ *c must be less than UTF16 "lower surrogate begin"
+ *or higher than UTF16 "High surrogate end"
+ */
+ if (c >= 0xD800 && c <= 0xDFFF)
+ goto end;
+
+ /*Avoid characters that equals zero */
+ if (c == 0)
+ goto end;
+
+ *a_out = c;
+
+ end:
+ *a_consumed = nb_bytes_2_decode;
+
+ return status;
+}
+
+/**
+ *
+ */
+enum CRStatus
+cr_utils_utf8_str_len_as_ucs1 (const guchar * a_in_start,
+ const guchar * a_in_end, gulong * a_len)
+{
+ /*
+ *Note: this function can be made shorter
+ *but it considers all the cases of the utf8 encoding
+ *to ease further extensions ...
+ */
+
+ guchar *byte_ptr = NULL;
+ gint len = 0;
+
+ /*
+ *to store the final decoded
+ *unicode char
+ */
+ guint c = 0;
+
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
+ CR_BAD_PARAM_ERROR);
+ *a_len = 0;
+
+ for (byte_ptr = (guchar *) a_in_start;
+ byte_ptr <= a_in_end; byte_ptr++) {
+ gint nb_bytes_2_decode = 0;
+
+ if (*byte_ptr <= 0x7F) {
+ /*
+ *7 bits long char
+ *encoded over 1 byte:
+ * 0xxx xxxx
+ */
+ c = *byte_ptr;
+ nb_bytes_2_decode = 1;
+
+ } else if ((*byte_ptr & 0xE0) == 0xC0) {
+ /*
+ *up to 11 bits long char.
+ *encoded over 2 bytes:
+ *110x xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x1F;
+ nb_bytes_2_decode = 2;
+
+ } else if ((*byte_ptr & 0xF0) == 0xE0) {
+ /*
+ *up to 16 bit long char
+ *encoded over 3 bytes:
+ *1110 xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x0F;
+ nb_bytes_2_decode = 3;
+
+ } else if ((*byte_ptr & 0xF8) == 0xF0) {
+ /*
+ *up to 21 bits long char
+ *encoded over 4 bytes:
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x7;
+ nb_bytes_2_decode = 4;
+
+ } else if ((*byte_ptr & 0xFC) == 0xF8) {
+ /*
+ *up to 26 bits long char
+ *encoded over 5 bytes.
+ *1111 10xx 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 3;
+ nb_bytes_2_decode = 5;
+
+ } else if ((*byte_ptr & 0xFE) == 0xFC) {
+ /*
+ *up to 31 bits long char
+ *encoded over 6 bytes:
+ *1111 110x 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 1;
+ nb_bytes_2_decode = 6;
+
+ } else {
+ /*
+ *BAD ENCODING
+ */
+ return CR_ENCODING_ERROR;
+ }
+
+ /*
+ *Go and decode the remaining byte(s)
+ *(if any) to get the current character.
+ */
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
+ /*decode the next byte */
+ byte_ptr++;
+
+ /*byte pattern must be: 10xx xxxx */
+ if ((*byte_ptr & 0xC0) != 0x80) {
+ return CR_ENCODING_ERROR;
+ }
+
+ c = (c << 6) | (*byte_ptr & 0x3F);
+ }
+
+ /*
+ *The decoded ucs4 char is now
+ *in c.
+ */
+
+ if (c <= 0xFF) { /*Add other conditions to support
+ *other char sets (ucs2, ucs3, ucs4).
+ */
+ len++;
+ } else {
+ /*the char is too long to fit
+ *into the supposed charset len.
+ */
+ return CR_ENCODING_ERROR;
+ }
+ }
+
+ *a_len = len;
+
+ return CR_OK;
+}
+
+/**
+ *Converts an utf8 string into an ucs4 string.
+ *@param a_in the input string to convert.
+ *@param a_in_len in/out parameter. The length of the input
+ *string. After return, points to the actual number of bytes
+ *consumed. This can be useful to debug the input stream in case
+ *of encoding error.
+ *@param a_out out parameter. Points to the output string. It is allocated
+ *by this function and must be freed by the caller.
+ *@param a_out_len out parameter. The length of the output string.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ *
+ */
+enum CRStatus
+cr_utils_utf8_str_to_ucs4 (const guchar * a_in,
+ gulong * a_in_len,
+ guint32 ** a_out, gulong * a_out_len)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
+
+ status = cr_utils_utf8_str_len_as_ucs4 (a_in,
+ &a_in[*a_in_len - 1],
+ a_out_len);
+
+ g_return_val_if_fail (status == CR_OK, status);
+
+ *a_out = (guint32 *) g_malloc0 (*a_out_len * sizeof (guint32));
+
+ status = cr_utils_utf8_to_ucs4 (a_in, a_in_len, *a_out, a_out_len);
+
+ return status;
+}
+
+/**
+ *Converts an ucs4 buffer into an utf8 buffer.
+ *
+ *@param a_in the input ucs4 buffer to convert.
+ *@param a_in_len in/out parameter. The size of the
+ *input buffer to convert. After return, this parameter contains
+ *the actual number of characters consumed.
+ *@param a_out the output converted utf8 buffer. Must be allocated by
+ *the caller.
+ *@param a_out_len in/out parameter. The size of the output buffer.
+ *If this size is actually smaller than the real needed size, the function
+ *just converts what it can and returns a success status. After return,
+ *this param points to the actual number of bytes in the buffer.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_ucs4_to_utf8 (const guint32 * a_in,
+ gulong * a_in_len, guchar * a_out, gulong * a_out_len)
+{
+ gulong in_len = 0,
+ in_index = 0,
+ out_index = 0;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len && a_out && a_out_len,
+ CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len < 1) {
+ status = CR_OK;
+ goto end;
+ }
+
+ in_len = *a_in_len;
+
+ for (in_index = 0; in_index < in_len; in_index++) {
+ /*
+ *FIXME: return whenever we encounter forbidden char values.
+ */
+
+ if (a_in[in_index] <= 0x7F) {
+ a_out[out_index] = a_in[in_index];
+ out_index++;
+ } else if (a_in[in_index] <= 0x7FF) {
+ a_out[out_index] = (0xC0 | (a_in[in_index] >> 6));
+ a_out[out_index + 1] =
+ (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 2;
+ } else if (a_in[in_index] <= 0xFFFF) {
+ a_out[out_index] = (0xE0 | (a_in[in_index] >> 12));
+ a_out[out_index + 1] =
+ (0x80 | ((a_in[in_index] >> 6) & 0x3F));
+ a_out[out_index + 2] =
+ (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 3;
+ } else if (a_in[in_index] <= 0x1FFFFF) {
+ a_out[out_index] = (0xF0 | (a_in[in_index] >> 18));
+ a_out[out_index + 1]
+ = (0x80 | ((a_in[in_index] >> 12) & 0x3F));
+ a_out[out_index + 2]
+ = (0x80 | ((a_in[in_index] >> 6) & 0x3F));
+ a_out[out_index + 3]
+ = (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 4;
+ } else if (a_in[in_index] <= 0x3FFFFFF) {
+ a_out[out_index] = (0xF8 | (a_in[in_index] >> 24));
+ a_out[out_index + 1] =
+ (0x80 | (a_in[in_index] >> 18));
+ a_out[out_index + 2]
+ = (0x80 | ((a_in[in_index] >> 12) & 0x3F));
+ a_out[out_index + 3]
+ = (0x80 | ((a_in[in_index] >> 6) & 0x3F));
+ a_out[out_index + 4]
+ = (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 5;
+ } else if (a_in[in_index] <= 0x7FFFFFFF) {
+ a_out[out_index] = (0xFC | (a_in[in_index] >> 30));
+ a_out[out_index + 1] =
+ (0x80 | (a_in[in_index] >> 24));
+ a_out[out_index + 2]
+ = (0x80 | ((a_in[in_index] >> 18) & 0x3F));
+ a_out[out_index + 3]
+ = (0x80 | ((a_in[in_index] >> 12) & 0x3F));
+ a_out[out_index + 4]
+ = (0x80 | ((a_in[in_index] >> 6) & 0x3F));
+ a_out[out_index + 4]
+ = (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 6;
+ } else {
+ status = CR_ENCODING_ERROR;
+ goto end;
+ }
+ } /*end for */
+
+ end:
+ *a_in_len = in_index + 1;
+ *a_out_len = out_index + 1;
+
+ return status;
+}
+
+/**
+ *Converts an ucs4 string into an utf8 string.
+ *@param a_in the input string to convert.
+ *@param a_in_len in/out parameter. The length of the input
+ *string. After return, points to the actual number of characters
+ *consumed. This can be useful to debug the input string in case
+ *of encoding error.
+ *@param a_out out parameter. Points to the output string. It is allocated
+ *by this function and must be freed by the caller.
+ *@param a_out_len out parameter. The length (in bytes) of the output string.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_ucs4_str_to_utf8 (const guint32 * a_in,
+ gulong * a_in_len,
+ guchar ** a_out, gulong * a_out_len)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len && a_out
+ && a_out_len, CR_BAD_PARAM_ERROR);
+
+ status = cr_utils_ucs4_str_len_as_utf8 (a_in,
+ &a_in[*a_out_len - 1],
+ a_out_len);
+
+ g_return_val_if_fail (status == CR_OK, status);
+
+ status = cr_utils_ucs4_to_utf8 (a_in, a_in_len, *a_out, a_out_len);
+
+ return status;
+}
+
+/**
+ *Converts an ucs1 buffer into an utf8 buffer.
+ *The caller must know the size of the resulting buffer and
+ *allocate it prior to calling this function.
+ *
+ *@param a_in the input ucs1 buffer.
+ *
+ *@param a_in_len in/out parameter. The length of the input buffer.
+ *After return, points to the number of bytes actually consumed even
+ *in case of encoding error.
+ *
+ *@param a_out out parameter. The output utf8 converted buffer.
+ *
+ *@param a_out_len in/out parameter. The size of the output buffer.
+ *If the output buffer size is shorter than the actual needed size,
+ *this function just convert what it can.
+ *
+ *@return CR_OK upon successful completion, an error code otherwise.
+ *
+ */
+enum CRStatus
+cr_utils_ucs1_to_utf8 (const guchar * a_in,
+ gulong * a_in_len, guchar * a_out, gulong * a_out_len)
+{
+ gulong out_index = 0,
+ in_index = 0,
+ in_len = 0,
+ out_len = 0;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len
+ && a_out_len,
+ CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len == 0) {
+ *a_out_len = 0 ;
+ return status;
+ }
+ g_return_val_if_fail (a_out, CR_BAD_PARAM_ERROR) ;
+
+ in_len = *a_in_len;
+ out_len = *a_out_len;
+
+ for (in_index = 0, out_index = 0;
+ (in_index < in_len) && (out_index < out_len); in_index++) {
+ /*
+ *FIXME: return whenever we encounter forbidden char values.
+ */
+
+ if (a_in[in_index] <= 0x7F) {
+ a_out[out_index] = a_in[in_index];
+ out_index++;
+ } else {
+ a_out[out_index] = (0xC0 | (a_in[in_index] >> 6));
+ a_out[out_index + 1] =
+ (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 2;
+ }
+ } /*end for */
+
+ *a_in_len = in_index;
+ *a_out_len = out_index;
+
+ return status;
+}
+
+/**
+ *Converts an ucs1 string into an utf8 string.
+ *@param a_in_start the beginning of the input string to convert.
+ *@param a_in_end the end of the input string to convert.
+ *@param a_out out parameter. The converted string.
+ *@param a_out out parameter. The length of the converted string.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ *
+ */
+enum CRStatus
+cr_utils_ucs1_str_to_utf8 (const guchar * a_in,
+ gulong * a_in_len,
+ guchar ** a_out, gulong * a_out_len)
+{
+ gulong out_len = 0;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len && a_out
+ && a_out_len, CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len < 1) {
+ *a_out_len = 0;
+ *a_out = NULL;
+ return CR_OK;
+ }
+
+ status = cr_utils_ucs1_str_len_as_utf8 (a_in, &a_in[*a_in_len - 1],
+ &out_len);
+
+ g_return_val_if_fail (status == CR_OK, status);
+
+ *a_out = (guchar *) g_malloc0 (out_len);
+
+ status = cr_utils_ucs1_to_utf8 (a_in, a_in_len, *a_out, &out_len);
+
+ *a_out_len = out_len;
+
+ return status;
+}
+
+/**
+ *Converts an utf8 buffer into an ucs1 buffer.
+ *The caller must know the size of the resulting
+ *converted buffer, and allocated it prior to calling this
+ *function.
+ *
+ *@param a_in the input utf8 buffer to convert.
+ *
+ *@param a_in_len in/out parameter. The size of the input utf8 buffer.
+ *After return, points to the number of bytes consumed
+ *by the function even in case of encoding error.
+ *
+ *@param a_out out parameter. Points to the resulting buffer.
+ *Must be allocated by the caller. If the size of a_out is shorter
+ *than its required size, this function converts what it can and return
+ *a successful status.
+ *
+ *@param a_out_len in/out parameter. The size of the output buffer.
+ *After return, points to the number of bytes consumed even in case of
+ *encoding error.
+ *
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_utf8_to_ucs1 (const guchar * a_in,
+ gulong * a_in_len, guchar * a_out, gulong * a_out_len)
+{
+ gulong in_index = 0,
+ out_index = 0,
+ in_len = 0,
+ out_len = 0;
+ enum CRStatus status = CR_OK;
+
+ /*
+ *to store the final decoded
+ *unicode char
+ */
+ guint32 c = 0;
+
+ g_return_val_if_fail (a_in && a_in_len
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len < 1) {
+ goto end;
+ }
+
+ in_len = *a_in_len;
+ out_len = *a_out_len;
+
+ for (in_index = 0, out_index = 0;
+ (in_index < in_len) && (out_index < out_len);
+ in_index++, out_index++) {
+ gint nb_bytes_2_decode = 0;
+
+ if (a_in[in_index] <= 0x7F) {
+ /*
+ *7 bits long char
+ *encoded over 1 byte:
+ * 0xxx xxxx
+ */
+ c = a_in[in_index];
+ nb_bytes_2_decode = 1;
+
+ } else if ((a_in[in_index] & 0xE0) == 0xC0) {
+ /*
+ *up to 11 bits long char.
+ *encoded over 2 bytes:
+ *110x xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x1F;
+ nb_bytes_2_decode = 2;
+
+ } else if ((a_in[in_index] & 0xF0) == 0xE0) {
+ /*
+ *up to 16 bit long char
+ *encoded over 3 bytes:
+ *1110 xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x0F;
+ nb_bytes_2_decode = 3;
+
+ } else if ((a_in[in_index] & 0xF8) == 0xF0) {
+ /*
+ *up to 21 bits long char
+ *encoded over 4 bytes:
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x7;
+ nb_bytes_2_decode = 4;
+
+ } else if ((a_in[in_index] & 0xFC) == 0xF8) {
+ /*
+ *up to 26 bits long char
+ *encoded over 5 bytes.
+ *1111 10xx 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 3;
+ nb_bytes_2_decode = 5;
+
+ } else if ((a_in[in_index] & 0xFE) == 0xFC) {
+ /*
+ *up to 31 bits long char
+ *encoded over 6 bytes:
+ *1111 110x 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 1;
+ nb_bytes_2_decode = 6;
+
+ } else {
+ /*BAD ENCODING */
+ status = CR_ENCODING_ERROR;
+ goto end;
+ }
+
+ /*
+ *Go and decode the remaining byte(s)
+ *(if any) to get the current character.
+ */
+ if (in_index + nb_bytes_2_decode - 1 >= in_len) {
+ goto end;
+ }
+
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
+ /*decode the next byte */
+ in_index++;
+
+ /*byte pattern must be: 10xx xxxx */
+ if ((a_in[in_index] & 0xC0) != 0x80) {
+ status = CR_ENCODING_ERROR;
+ goto end;
+ }
+
+ c = (c << 6) | (a_in[in_index] & 0x3F);
+ }
+
+ /*
+ *The decoded ucs4 char is now
+ *in c.
+ */
+
+ if (c > 0xFF) {
+ status = CR_ENCODING_ERROR;
+ goto end;
+ }
+
+ a_out[out_index] = c;
+ }
+
+ end:
+ *a_out_len = out_index;
+ *a_in_len = in_index;
+
+ return status;
+}
+
+/**
+ *Converts an utf8 buffer into an
+ *ucs1 buffer.
+ *@param a_in_start the start of the input buffer.
+ *@param a_in_end the end of the input buffer.
+ *@param a_out out parameter. The resulting converted ucs4 buffer.
+ *Must be freed by the caller.
+ *@param a_out_len out parameter. The length of the converted buffer.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ *Note that out parameters are valid if and only if this function
+ *returns CR_OK.
+ */
+enum CRStatus
+cr_utils_utf8_str_to_ucs1 (const guchar * a_in,
+ gulong * a_in_len,
+ guchar ** a_out, gulong * a_out_len)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len < 1) {
+ *a_out_len = 0;
+ *a_out = NULL;
+ return CR_OK;
+ }
+
+ status = cr_utils_utf8_str_len_as_ucs4 (a_in, &a_in[*a_in_len - 1],
+ a_out_len);
+
+ g_return_val_if_fail (status == CR_OK, status);
+
+ *a_out = (guchar *) g_malloc0 (*a_out_len * sizeof (guint32));
+
+ status = cr_utils_utf8_to_ucs1 (a_in, a_in_len, *a_out, a_out_len);
+ return status;
+}
+
+/*****************************************
+ *CSS basic types identification utilities
+ *****************************************/
+
+/**
+ *Returns TRUE if a_char is a white space as
+ *defined in the css spec in chap 4.1.1.
+ *
+ *white-space ::= ' '| \t|\r|\n|\f
+ *
+ *@param a_char the character to test.
+ *return TRUE if is a white space, false otherwise.
+ */
+gboolean
+cr_utils_is_white_space (guint32 a_char)
+{
+ switch (a_char) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ case '\f':
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ *Returns true if the character is a newline
+ *as defined in the css spec in the chap 4.1.1.
+ *
+ *nl ::= \n|\r\n|\r|\f
+ *
+ *@param a_char the character to test.
+ *@return TRUE if the character is a newline, FALSE otherwise.
+ */
+gboolean
+cr_utils_is_newline (guint32 a_char)
+{
+ switch (a_char) {
+ case '\n':
+ case '\r':
+ case '\f':
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ *returns TRUE if the char is part of an hexa num char:
+ *i.e hexa_char ::= [0-9A-F]
+ */
+gboolean
+cr_utils_is_hexa_char (guint32 a_char)
+{
+ if ((a_char >= '0' && a_char <= '9')
+ || (a_char >= 'A' && a_char <= 'F')) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ *Returns true if the character is a nonascii
+ *character (as defined in the css spec chap 4.1.1):
+ *
+ *nonascii ::= [^\0-\177]
+ *
+ *@param a_char the character to test.
+ *@return TRUE if the character is a nonascii char,
+ *FALSE otherwise.
+ */
+gboolean
+cr_utils_is_nonascii (guint32 a_char)
+{
+ if (a_char <= 177) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ *Dumps a character a_nb times on a file.
+ *@param a_char the char to dump
+ *@param a_fp the destination file pointer
+ *@param a_nb the number of times a_char is to be dumped.
+ */
+void
+cr_utils_dump_n_chars (guchar a_char, FILE * a_fp, glong a_nb)
+{
+ glong i = 0;
+
+ for (i = 0; i < a_nb; i++) {
+ fprintf (a_fp, "%c", a_char);
+ }
+}
+
+void
+cr_utils_dump_n_chars2 (guchar a_char, GString * a_string, glong a_nb)
+{
+ glong i = 0;
+
+ g_return_if_fail (a_string);
+
+ for (i = 0; i < a_nb; i++) {
+ g_string_append_printf (a_string, "%c", a_char);
+ }
+}
+
+/**
+ *Duplicates a list of GString instances.
+ *@return the duplicated list of GString instances or NULL if
+ *something bad happened.
+ *@param a_list_of_strings the list of strings to be duplicated.
+ */
+GList *
+cr_utils_dup_glist_of_string (GList const * a_list_of_strings)
+{
+ GList const *cur = NULL;
+ GList *result = NULL;
+
+ g_return_val_if_fail (a_list_of_strings, NULL);
+
+ for (cur = a_list_of_strings; cur; cur = cur->next) {
+ GString *str = NULL;
+
+ str = g_string_new_len (((GString *) cur->data)->str,
+ ((GString *) cur->data)->len);
+ if (str)
+ result = g_list_append (result, str);
+ }
+
+ return result;
+}
+
+/**
+ *Duplicate a GList where the GList::data is a CRString.
+ *@param a_list_of_strings the list to duplicate
+ *@return the duplicated list, or NULL if something bad
+ *happened.
+ */
+GList *
+cr_utils_dup_glist_of_cr_string (GList const * a_list_of_strings)
+{
+ GList const *cur = NULL;
+ GList *result = NULL;
+
+ g_return_val_if_fail (a_list_of_strings, NULL);
+
+ for (cur = a_list_of_strings; cur; cur = cur->next) {
+ CRString *str = NULL;
+
+ str = cr_string_dup ((CRString const *) cur->data) ;
+ if (str)
+ result = g_list_append (result, str);
+ }
+
+ return result;
+}
diff --git a/src/3rdparty/libcroco/src/cr-utils.h b/src/3rdparty/libcroco/src/cr-utils.h
new file mode 100644
index 0000000..cff9c80
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-utils.h
@@ -0,0 +1,245 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * Look at file COPYRIGHTS for copyright information
+ */
+
+#ifndef __CR_DEFS_H__
+#define __CR_DEFS_H__
+
+#include <stdio.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The Croco library basic types definitions
+ *And global definitions.
+ */
+
+/**
+ *The status type returned
+ *by the methods of the croco library.
+ */
+enum CRStatus {
+ CR_OK,
+ CR_BAD_PARAM_ERROR,
+ CR_INSTANCIATION_FAILED_ERROR,
+ CR_UNKNOWN_TYPE_ERROR,
+ CR_UNKNOWN_PROP_ERROR,
+ CR_UNKNOWN_PROP_VAL_ERROR,
+ CR_UNEXPECTED_POSITION_SCHEME,
+ CR_START_OF_INPUT_ERROR,
+ CR_END_OF_INPUT_ERROR,
+ CR_OUTPUT_TOO_SHORT_ERROR,
+ CR_INPUT_TOO_SHORT_ERROR,
+ CR_OUT_OF_BOUNDS_ERROR,
+ CR_EMPTY_PARSER_INPUT_ERROR,
+ CR_ENCODING_ERROR,
+ CR_ENCODING_NOT_FOUND_ERROR,
+ CR_PARSING_ERROR,
+ CR_SYNTAX_ERROR,
+ CR_NO_ROOT_NODE_ERROR,
+ CR_NO_TOKEN,
+ CR_OUT_OF_MEMORY_ERROR,
+ CR_PSEUDO_CLASS_SEL_HANDLER_NOT_FOUND_ERROR,
+ CR_BAD_PSEUDO_CLASS_SEL_HANDLER_ERROR,
+ CR_ERROR,
+ CR_FILE_NOT_FOUND_ERROR,
+ CR_VALUE_NOT_FOUND_ERROR
+} ;
+
+/**
+ *Values used by
+ *cr_input_seek_position() ;
+ */
+enum CRSeekPos {
+ CR_SEEK_CUR,
+ CR_SEEK_BEGIN,
+ CR_SEEK_END
+} ;
+
+/**
+ *Encoding values.
+ */
+enum CREncoding
+{
+ CR_UCS_4 = 1/*Must be not NULL*/,
+ CR_UCS_1,
+ CR_ISO_8859_1,
+ CR_ASCII,
+ CR_UTF_8,
+ CR_UTF_16,
+ CR_AUTO/*should be the last one*/
+} ;
+
+
+
+
+#define CROCO_LOG_DOMAIN "LIBCROCO"
+
+#ifdef __GNUC__
+#define cr_utils_trace(a_log_level, a_msg) \
+g_log (CROCO_LOG_DOMAIN, \
+ G_LOG_LEVEL_CRITICAL, \
+ "file %s: line %d (%s): %s\n", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ a_msg)
+#else /*__GNUC__*/
+
+#define cr_utils_trace(a_log_level, a_msg) \
+g_log (CROCO_LOG_DOMAIN, \
+ G_LOG_LEVEL_CRITICAL, \
+ "file %s: line %d: %s\n", \
+ __FILE__, \
+ __LINE__, \
+ a_msg)
+#endif
+
+/**
+ *Traces an info message.
+ *The file, line and enclosing function
+ *of the message will be automatically
+ *added to the message.
+ *@param a_msg the msg to trace.
+ */
+#define cr_utils_trace_info(a_msg) \
+cr_utils_trace (G_LOG_LEVEL_INFO, a_msg)
+
+/**
+ *Trace a debug message.
+ *The file, line and enclosing function
+ *of the message will be automatically
+ *added to the message.
+ *@param a_msg the msg to trace.
+ */
+#define cr_utils_trace_debug(a_msg) \
+cr_utils_trace (G_LOG_LEVEL_DEBUG, a_msg) ;
+
+
+/****************************
+ *Encoding transformations and
+ *encoding helpers
+ ****************************/
+
+enum CRStatus
+cr_utils_read_char_from_utf8_buf (const guchar * a_in, gulong a_in_len,
+ guint32 *a_out, gulong *a_consumed) ;
+
+enum CRStatus
+cr_utils_ucs1_to_utf8 (const guchar *a_in, gulong *a_in_len,
+ guchar *a_out, gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_utf8_to_ucs1 (const guchar * a_in, gulong * a_in_len,
+ guchar *a_out, gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_ucs4_to_utf8 (const guint32 *a_in, gulong *a_in_len,
+ guchar *a_out, gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_utf8_str_len_as_ucs4 (const guchar *a_in_start,
+ const guchar *a_in_end,
+ gulong *a_len) ;
+enum CRStatus
+cr_utils_ucs1_str_len_as_utf8 (const guchar *a_in_start,
+ const guchar *a_in_end,
+ gulong *a_len) ;
+enum CRStatus
+cr_utils_utf8_str_len_as_ucs1 (const guchar *a_in_start,
+ const guchar *a_in_end,
+ gulong *a_len) ;
+enum CRStatus
+cr_utils_ucs4_str_len_as_utf8 (const guint32 *a_in_start,
+ const guint32 *a_in_end,
+ gulong *a_len) ;
+
+enum CRStatus
+cr_utils_ucs1_str_to_utf8 (const guchar *a_in_start,
+ gulong *a_in_len,
+ guchar **a_out,
+ gulong *a_len) ;
+
+enum CRStatus
+cr_utils_utf8_str_to_ucs1 (const guchar * a_in_start,
+ gulong * a_in_len,
+ guchar **a_out,
+ gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_utf8_to_ucs4 (const guchar * a_in,
+ gulong * a_in_len,
+ guint32 *a_out, gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_ucs4_str_to_utf8 (const guint32 *a_in,
+ gulong *a_in_len,
+ guchar **a_out, gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_utf8_str_to_ucs4 (const guchar * a_in,
+ gulong *a_in_len,
+ guint32 **a_out,
+ gulong *a_out_len) ;
+
+
+/*****************************************
+ *CSS basic types identification utilities
+ *****************************************/
+
+gboolean
+cr_utils_is_newline (guint32 a_char) ;
+
+gboolean
+cr_utils_is_white_space (guint32 a_char) ;
+
+gboolean
+cr_utils_is_nonascii (guint32 a_char) ;
+
+gboolean
+cr_utils_is_hexa_char (guint32 a_char) ;
+
+
+/**********************************
+ *Miscellaneous utility functions
+ ***********************************/
+
+void
+cr_utils_dump_n_chars (guchar a_char,
+ FILE *a_fp,
+ glong a_nb) ;
+
+void
+cr_utils_dump_n_chars2 (guchar a_char,
+ GString *a_string,
+ glong a_nb) ;
+GList *
+cr_utils_dup_glist_of_string (GList const *a_list) ;
+
+GList *
+cr_utils_dup_glist_of_cr_string (GList const * a_list_of_strings) ;
+
+G_END_DECLS
+
+#endif /*__CR_DEFS_H__*/
diff --git a/src/3rdparty/libcroco/src/libcroco-config.h.in b/src/3rdparty/libcroco/src/libcroco-config.h.in
new file mode 100644
index 0000000..7f2e217
--- /dev/null
+++ b/src/3rdparty/libcroco/src/libcroco-config.h.in
@@ -0,0 +1,17 @@
+#ifndef LIBCROCO_VERSION_NUMBER
+#define LIBCROCO_VERSION_NUMBER @LIBCROCO_VERSION_NUMBER@
+#endif
+
+#ifndef LIBCROCO_VERSION
+#define LIBCROCO_VERSION "@LIBCROCO_VERSION@"
+#endif
+
+#ifndef G_DISABLE_CHECKS
+#if @G_DISABLE_CHECKS@
+#define G_DISABLE_CHECKS @G_DISABLE_CHECKS@
+#endif
+#endif
+
+#ifndef CROCO_HAVE_LIBXML2
+#define CROCO_HAVE_LIBXML2 (1)
+#endif
diff --git a/src/3rdparty/libcroco/src/libcroco.h b/src/3rdparty/libcroco/src/libcroco.h
new file mode 100644
index 0000000..eabc596
--- /dev/null
+++ b/src/3rdparty/libcroco/src/libcroco.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef __LIBCROCO_H__
+#define __LIBCROCO_H__
+
+#include "libcroco-config.h"
+
+#include "cr-utils.h"
+#include "cr-pseudo.h"
+#include "cr-term.h"
+#include "cr-attr-sel.h"
+#include "cr-simple-sel.h"
+#include "cr-selector.h"
+#include "cr-enc-handler.h"
+#include "cr-doc-handler.h"
+#include "cr-input.h"
+#include "cr-parser.h"
+#include "cr-statement.h"
+#include "cr-stylesheet.h"
+#include "cr-om-parser.h"
+#include "cr-prop-list.h"
+#include "cr-sel-eng.h"
+#include "cr-style.h"
+#include "cr-string.h"
+
+#endif /*__LIBCROCO_H__*/
diff --git a/src/3rdparty/libcroco/src/libcroco.symbols b/src/3rdparty/libcroco/src/libcroco.symbols
new file mode 100644
index 0000000..c201652
--- /dev/null
+++ b/src/3rdparty/libcroco/src/libcroco.symbols
@@ -0,0 +1,538 @@
+;This file is part of The Croco Library
+;This program is free software; you can redistribute it and/or
+;modify it under the terms of version 2.1 of the GNU Lesser General Public
+;License as published by the Free Software Foundation.
+
+;This program is distributed in the hope that it will be useful,
+;but WITHOUT ANY WARRANTY; without even the implied warranty of
+;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;GNU General Public License for more details.
+
+;You should have received a copy of the GNU Lesser General Public License
+;along with this program; if not, write to the Free Software
+;Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+;USA
+
+;Author: Fan, Chun-wei
+;See COPYRIGHTS file for copyright information.
+
+;----------------------------
+;libcroco/cr-additional-sel.h
+;----------------------------
+cr_additional_sel_append
+cr_additional_sel_destroy
+cr_additional_sel_dump
+cr_additional_sel_new
+cr_additional_sel_new_with_type
+cr_additional_sel_one_to_string
+cr_additional_sel_prepend
+cr_additional_sel_set_attr_sel
+cr_additional_sel_set_class_name
+cr_additional_sel_set_id_name
+cr_additional_sel_set_pseudo
+cr_additional_sel_to_string
+
+;----------------------
+;libcroco/cr-attr-sel.h
+;----------------------
+cr_attr_sel_append_attr_sel
+cr_attr_sel_destroy
+cr_attr_sel_dump
+cr_attr_sel_new
+cr_attr_sel_prepend_attr_sel
+cr_attr_sel_to_string
+
+;---------------------
+;libcroco/cr-cascade.h
+;---------------------
+cr_cascade_destroy
+cr_cascade_get_sheet
+cr_cascade_new
+cr_cascade_ref
+cr_cascade_set_sheet
+cr_cascade_unref
+
+;-------------------------
+;libcroco/cr-declaration.h
+;-------------------------
+cr_declaration_append
+cr_declaration_append2
+cr_declaration_destroy
+cr_declaration_dump
+cr_declaration_dump_one
+cr_declaration_get_by_prop_name
+cr_declaration_get_from_list
+cr_declaration_list_to_string
+cr_declaration_list_to_string2
+cr_declaration_new
+cr_declaration_nr_props
+cr_declaration_parse_from_buf
+cr_declaration_parse_list_from_buf
+cr_declaration_prepend
+cr_declaration_ref
+cr_declaration_to_string
+cr_declaration_unlink
+cr_declaration_unref
+
+;-------------------------
+;libcroco/cr-doc-handler.h
+;-------------------------
+cr_doc_handler_associate_a_parser
+cr_doc_handler_destroy
+cr_doc_handler_get_ctxt
+cr_doc_handler_get_result
+cr_doc_handler_new
+cr_doc_handler_ref
+cr_doc_handler_set_ctxt
+cr_doc_handler_set_default_sac_handler
+cr_doc_handler_set_result
+cr_doc_handler_unref
+
+;-------------------------
+;libcroco/cr-enc-handler.h
+;-------------------------
+cr_enc_handler_convert_input
+cr_enc_handler_get_instance
+cr_enc_handler_resolve_enc_alias
+
+;-------------------
+;libcroco/cr-fonts.h
+;-------------------
+cr_font_family_append
+cr_font_family_destroy
+cr_font_family_new
+cr_font_family_prepend
+cr_font_family_set_name
+cr_font_family_to_string
+cr_font_size_adjust_destroy
+cr_font_size_adjust_new
+cr_font_size_adjust_to_string
+cr_font_size_clear
+cr_font_size_copy
+cr_font_size_destroy
+cr_font_size_get_larger_predefined_font_size
+cr_font_size_get_smaller_predefined_font_size
+cr_font_size_is_predefined_absolute_font_size
+cr_font_size_is_set_to_inherit
+cr_font_size_new
+cr_font_size_set_absolute_font_size
+cr_font_size_set_predefined_absolute_font_size
+cr_font_size_set_relative_font_size
+cr_font_size_set_to_inherit
+cr_font_size_to_string
+cr_font_stretch_to_string
+cr_font_style_to_string
+cr_font_variant_to_string
+cr_font_weight_get_bolder
+cr_font_weight_to_string
+
+;-------------------
+;libcroco/cr-input.h
+;-------------------
+cr_input_consume_char
+cr_input_consume_chars
+cr_input_consume_white_spaces
+cr_input_destroy
+cr_input_end_of_input
+cr_input_get_byte_addr
+cr_input_get_column_num
+cr_input_get_cur_pos
+cr_input_get_cur_byte_addr
+cr_input_get_cur_index
+cr_input_get_end_of_file
+cr_input_get_end_of_line
+cr_input_get_line_num
+cr_input_get_nb_bytes_left
+cr_input_get_parsing_location
+cr_input_increment_col_num
+cr_input_increment_line_num
+cr_input_new_from_buf
+cr_input_new_from_uri
+cr_input_peek_byte
+cr_input_peek_byte2
+cr_input_peek_char
+cr_input_read_byte
+cr_input_read_char
+cr_input_ref
+cr_input_seek_index
+cr_input_set_column_num
+cr_input_set_cur_index
+cr_input_set_cur_pos
+cr_input_set_end_of_file
+cr_input_set_end_of_line
+cr_input_set_line_num
+cr_input_unref
+
+;-----------------
+;libcroco/cr-num.h
+;-----------------
+cr_num_copy
+cr_num_destroy
+cr_num_dup
+cr_num_is_fixed_length
+cr_num_new
+cr_num_new_with_val
+cr_num_set
+cr_num_to_string
+
+;-----------------------
+;libcroco/cr-om-parser.h
+;-----------------------
+cr_om_parser_destroy
+cr_om_parser_new
+cr_om_parser_parse_buf
+cr_om_parser_parse_file
+cr_om_parser_parse_paths_to_cascade
+cr_om_parser_simply_parse_buf
+cr_om_parser_simply_parse_file
+cr_om_parser_simply_parse_paths_to_cascade
+
+;--------------------
+;libcroco/cr-parser.h
+;--------------------
+cr_parser_destroy
+cr_parser_get_sac_handler
+cr_parser_get_tknzr
+cr_parser_get_use_core_grammar
+cr_parser_get_parsing_location
+cr_parser_new
+cr_parser_new_from_buf
+cr_parser_new_from_file
+cr_parser_new_from_input
+cr_parser_parse
+cr_parser_parse_buf
+cr_parser_parse_charset
+cr_parser_parse_declaration
+cr_parser_parse_expr
+cr_parser_parse_file
+cr_parser_parse_font_face
+cr_parser_parse_import
+cr_parser_parse_media
+cr_parser_parse_page
+cr_parser_parse_prio
+cr_parser_parse_ruleset
+cr_parser_parse_statement_core
+cr_parser_parse_term
+cr_parser_set_default_sac_handler
+cr_parser_set_sac_handler
+cr_parser_set_use_core_grammar
+cr_parser_set_tknzr
+cr_parser_try_to_skip_spaces_and_comments
+
+;------------------------------
+;libcroco/cr-parsing-location.h
+;------------------------------
+cr_parsing_location_copy
+cr_parsing_location_destroy
+cr_parsing_location_dump
+cr_parsing_location_init
+cr_parsing_location_new
+cr_parsing_location_to_string
+
+;-----------------------
+;libcroco/cr-prop-list.h
+;-----------------------
+cr_prop_list_append
+cr_prop_list_append2
+cr_prop_list_destroy
+cr_prop_list_get_decl
+cr_prop_list_get_next
+cr_prop_list_get_prev
+cr_prop_list_get_prop
+cr_prop_list_lookup_prop
+cr_prop_list_prepend
+cr_prop_list_prepend2
+cr_prop_list_set_decl
+cr_prop_list_set_prop
+cr_prop_list_unlink
+
+;--------------------
+;libcroco/cr-pseudo.h
+;--------------------
+cr_pseudo_destroy
+cr_pseudo_dump
+cr_pseudo_new
+cr_pseudo_to_string
+
+;-----------------
+;libcroco/cr-rgb.h
+;-----------------
+cr_rgb_compute_from_percentage
+cr_rgb_copy
+cr_rgb_destroy
+cr_rgb_dump
+cr_rgb_is_set_to_inherit
+cr_rgb_is_set_to_transparent
+cr_rgb_new
+cr_rgb_new_with_vals
+cr_rgb_parse_from_buf
+cr_rgb_set
+cr_rgb_set_from_hex_str
+cr_rgb_set_from_name
+cr_rgb_set_from_rgb
+cr_rgb_set_from_term
+cr_rgb_set_to_inherit
+cr_rgb_set_to_transparent
+cr_rgb_to_string
+
+;----------------------
+;libcroco/cr-selector.h
+;----------------------
+cr_selector_append
+cr_selector_append_simple_sel
+cr_selector_destroy
+cr_selector_dump
+cr_selector_new
+cr_selector_parse_from_buf
+cr_selector_prepend
+cr_selector_ref
+cr_selector_to_string
+cr_selector_unref
+
+;---------------------
+;libcroco/cr-sel-eng.h
+;---------------------
+cr_sel_eng_destroy
+cr_sel_eng_get_matched_properties_from_cascade
+cr_sel_eng_get_matched_rulesets
+cr_sel_eng_get_matched_style
+cr_sel_eng_get_pseudo_class_selector_handler
+cr_sel_eng_matches_node
+cr_sel_eng_new
+cr_sel_eng_register_pseudo_class_sel_handler
+cr_sel_eng_unregister_all_pseudo_class_sel_handlers
+cr_sel_eng_unregister_pseudo_class_sel_handler
+
+;------------------------
+;libcroco/cr-simple-sel.h
+;------------------------
+cr_simple_sel_append_simple_sel
+cr_simple_sel_compute_specificity
+cr_simple_sel_destroy
+cr_simple_sel_dump
+;cr_simple_sel_dump_attr_sel_list ;no implementation!
+cr_simple_sel_new
+cr_simple_sel_one_to_string
+cr_simple_sel_prepend_simple_sel
+cr_simple_sel_to_string
+
+;-----------------------
+;libcroco/cr-statement.h
+;-----------------------
+cr_statement_append
+cr_statement_at_charset_rule_get_charset
+cr_statement_at_charset_rule_parse_from_buf
+cr_statement_at_charset_rule_set_charset
+cr_statement_at_font_face_rule_add_decl
+cr_statement_at_font_face_rule_get_decls
+cr_statement_at_font_face_rule_set_decls
+cr_statement_at_import_rule_get_imported_sheet
+cr_statement_at_import_rule_get_url
+cr_statement_at_import_rule_parse_from_buf
+cr_statement_at_import_rule_set_imported_sheet
+cr_statement_at_import_rule_set_url
+cr_statement_at_media_get_from_list
+cr_statement_at_media_nr_rules
+cr_statement_at_media_rule_parse_from_buf
+cr_statement_at_page_rule_get_declarations
+;cr_statement_at_page_rule_get_sel ;no implementation!
+cr_statement_at_page_rule_parse_from_buf
+cr_statement_at_page_rule_set_declarations
+;cr_statement_at_page_rule_set_sel ;no implementation!
+cr_statement_destroy
+cr_statement_does_buf_parses_against_core
+cr_statement_dump
+cr_statement_dump_charset
+cr_statement_dump_font_face_rule
+cr_statement_dump_import_rule
+cr_statement_dump_media_rule
+cr_statement_dump_page
+cr_statement_dump_ruleset
+cr_statement_font_face_rule_parse_from_buf
+cr_statement_get_from_list
+cr_statement_get_parent_sheet
+cr_statement_list_to_string
+cr_statement_new_at_charset_rule
+cr_statement_new_at_font_face_rule
+cr_statement_new_at_import_rule
+cr_statement_new_at_media_rule
+cr_statement_new_at_page_rule
+cr_statement_new_ruleset
+cr_statement_nr_rules
+cr_statement_parse_from_buf
+cr_statement_prepend
+cr_statement_ruleset_append_decl
+cr_statement_ruleset_append_decl2
+cr_statement_ruleset_get_declarations
+cr_statement_ruleset_set_decl_list
+cr_statement_ruleset_get_sel_list
+cr_statement_ruleset_parse_from_buf
+cr_statement_ruleset_set_sel_list
+cr_statement_set_parent_sheet
+cr_statement_to_string
+cr_statement_unlink
+
+;--------------------
+;libcroco/cr-string.h
+;--------------------
+cr_string_destroy
+cr_string_dup
+cr_string_dup2
+cr_string_new
+cr_string_new_from_gstring
+cr_string_new_from_string
+cr_string_peek_raw_str
+cr_string_peek_raw_str_len
+
+;------------------------
+;libcroco/cr-stylesheet.h
+;------------------------
+cr_stylesheet_destroy
+cr_stylesheet_dump
+cr_stylesheet_new
+cr_stylesheet_nr_rules
+cr_stylesheet_ref
+cr_stylesheet_statement_get_from_list
+cr_stylesheet_to_string
+cr_stylesheet_unref
+
+;-------------------
+;libcroco/cr-style.h
+;-------------------
+cr_style_border_style_to_string
+cr_style_copy
+cr_style_destroy
+cr_style_display_type_to_string
+cr_style_dup
+cr_style_float_type_to_string
+cr_style_new
+cr_style_num_prop_val_to_string
+cr_style_position_type_to_string
+;cr_style_propagate_from_parent ;no implementation!
+cr_style_ref
+cr_style_resolve_inherited_properties
+cr_style_rgb_prop_val_to_string
+cr_style_set_props_to_default_values
+cr_style_set_props_to_initial_values
+cr_style_set_style_from_decl
+cr_style_to_string
+cr_style_unref
+cr_style_white_space_type_to_string
+
+;------------------
+;libcroco/cr-term.h
+;------------------
+cr_term_append_term
+cr_term_destroy
+cr_term_dump
+cr_term_get_from_list
+cr_term_new
+cr_term_nr_values
+cr_term_one_to_string
+cr_term_parse_expression_from_buf
+cr_term_prepend_term
+cr_term_ref
+cr_term_set_function
+cr_term_set_hash
+cr_term_set_ident
+cr_term_set_number
+cr_term_set_rgb
+cr_term_set_string
+cr_term_set_uri
+cr_term_to_string
+cr_term_unref
+
+;-------------------
+;libcroco/cr-tknzr.h
+;-------------------
+cr_tknzr_consume_chars
+cr_tknzr_destroy
+cr_tknzr_get_cur_byte_addr
+cr_tknzr_get_cur_pos
+cr_tknzr_get_input
+cr_tknzr_get_nb_bytes_left
+cr_tknzr_get_next_token
+cr_tknzr_get_parsing_location
+cr_tknzr_new
+cr_tknzr_new_from_buf
+cr_tknzr_new_from_uri
+cr_tknzr_parse_token
+cr_tknzr_peek_byte
+cr_tknzr_peek_byte2
+cr_tknzr_peek_char
+cr_tknzr_read_byte
+cr_tknzr_read_char
+cr_tknzr_ref
+cr_tknzr_seek_index
+cr_tknzr_set_cur_pos
+cr_tknzr_set_input
+cr_tknzr_unget_token
+cr_tknzr_unref
+
+;-------------------
+;libcroco/cr-token.h
+;-------------------
+cr_token_destroy
+cr_token_new
+cr_token_set_angle
+cr_token_set_atkeyword
+cr_token_set_bc
+cr_token_set_bo
+cr_token_set_cbc
+cr_token_set_cbo
+cr_token_set_cdc
+cr_token_set_cdo
+cr_token_set_charset_sym
+cr_token_set_comment
+cr_token_set_dashmatch
+cr_token_set_delim
+cr_token_set_dimen
+cr_token_set_ems
+cr_token_set_exs
+cr_token_set_font_face_sym
+cr_token_set_freq
+cr_token_set_function
+cr_token_set_hash
+cr_token_set_important_sym
+cr_token_set_import_sym
+cr_token_set_includes
+cr_token_set_ident
+cr_token_set_length
+cr_token_set_media_sym
+cr_token_set_number
+cr_token_set_page_sym
+cr_token_set_pc
+cr_token_set_percentage
+cr_token_set_po
+cr_token_set_rgb
+cr_token_set_s
+cr_token_set_semicolon
+cr_token_set_string
+cr_token_set_time
+;cr_token_set_unicoderange ;commented out in the header!
+cr_token_set_uri
+
+;-------------------
+;libcroco/cr-utils.h
+;-------------------
+cr_utils_dump_n_chars
+cr_utils_dump_n_chars2
+cr_utils_dup_glist_of_cr_string
+cr_utils_dup_glist_of_string
+cr_utils_is_hexa_char
+cr_utils_is_newline
+cr_utils_is_nonascii
+cr_utils_is_white_space
+cr_utils_read_char_from_utf8_buf
+cr_utils_ucs1_str_len_as_utf8
+cr_utils_ucs1_str_to_utf8
+cr_utils_ucs1_to_utf8
+cr_utils_ucs4_str_len_as_utf8
+cr_utils_ucs4_str_to_utf8
+cr_utils_ucs4_to_utf8
+cr_utils_utf8_str_len_as_ucs4
+cr_utils_utf8_to_ucs1
+cr_utils_utf8_to_ucs4
+cr_utils_utf8_str_len_as_ucs1
+cr_utils_utf8_str_to_ucs1
+cr_utils_utf8_str_to_ucs4 \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/CMakeLists.txt b/src/3rdparty/libcroco/tests/CMakeLists.txt
new file mode 100644
index 0000000..1ffb908
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/CMakeLists.txt
@@ -0,0 +1,69 @@
+set(testprogs
+ test0
+ test1
+ test2
+ test3
+ test4
+ test5
+ test6
+ test7
+ test8
+)
+
+foreach(source ${testprogs})
+ add_executable(${source} ${source}-main.c cr-test-utils.c cr-test-utils.h)
+
+ target_include_directories(${source}
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/src
+ ${CMAKE_BINARY_DIR}/src
+ ${GLIB_INCLUDE_DIRS}
+ ${LIBXML_INCLUDE_DIRS}
+ )
+
+ target_link_libraries(${source}
+ croco_LIB
+ )
+endforeach()
+
+if(1)
+ # Run each test separately
+
+ set(testscripts
+ test-functional-notation.sh
+ test-lots-of-comments.sh
+ test-parsing-location.sh
+ test-prop-ident.sh
+ test-sel-child-class.sh
+ test-several-media.sh
+ test-unknown-at-rule2.sh
+ test-unknown-at-rule.sh
+ )
+
+ add_test(NAME cleantest
+ COMMAND ${CMAKE_SOURCE_DIR}/tests/testctl cleanup
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+
+ foreach(source ${testprogs} ${testscripts})
+ add_test(NAME ${source}
+ COMMAND ${CMAKE_SOURCE_DIR}/tests/testctl run --test-and-report ${source}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+ set_tests_properties(${source} PROPERTIES DEPENDS "cleantest")
+ endforeach()
+else()
+ # Run all tests at once
+ add_test(NAME all-tests
+ COMMAND ${CMAKE_SOURCE_DIR}/tests/testctl run
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+endif()
+
+get_property(test_names DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY TESTS)
+set_property(TEST ${test_names} PROPERTY ENVIRONMENT
+ "TEST_OUT_DIR=${CMAKE_CURRENT_BINARY_DIR}"
+ "TEST_SOURCE_DIR=${CMAKE_SOURCE_DIR}/tests"
+ "TEST_INPUTS_DIR=${CMAKE_SOURCE_DIR}/tests/test-inputs"
+ "CSSLINT=${CMAKE_BINARY_DIR}/csslint/csslint"
+)
diff --git a/src/3rdparty/libcroco/tests/Makefile.am b/src/3rdparty/libcroco/tests/Makefile.am
new file mode 100644
index 0000000..666eff8
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/Makefile.am
@@ -0,0 +1,36 @@
+SUBDIRS = test-inputs test-output-refs
+EXTRA_DIST = testctl vg.supp global-vars.sh.in valgrind-version.sh \
+test-prop-ident.sh test-unknown-at-rule.sh test-unknown-at-rule2.sh \
+test-several-media.sh
+
+
+#the list of all possible tests goes here.
+
+EXTRALDFLAGS = $(CROCO_LIBS)
+testprogs=test0 test1 test2 test3 test4 test5 test6 test7 test8
+noinst_PROGRAMS = $(testprogs)
+test0_SOURCES = test0-main.c
+test0_LDFLAGS = $(EXTRALDFLAGS)
+test1_SOURCES = test1-main.c
+test1_LDFLAGS = $(EXTRALDFLAGS)
+test2_SOURCES = test2-main.c cr-test-utils.c cr-test-utils.h
+test2_LDFLAGS = $(EXTRALDFLAGS)
+test3_SOURCES = test3-main.c cr-test-utils.c cr-test-utils.h
+test3_LDFLAGS = $(EXTRALDFLAGS)
+test4_SOURCES = test4-main.c cr-test-utils.c cr-test-utils.h
+test4_LDFLAGS = $(EXTRALDFLAGS)
+test5_SOURCES = test5-main.c cr-test-utils.c cr-test-utils.h
+test5_LDFLAGS = $(EXTRALDFLAGS)
+test6_SOURCES = test6-main.c cr-test-utils.c cr-test-utils.h
+test6_LDFLAGS = $(EXTRALDFLAGS)
+test7_SOURCES = test7-main.c cr-test-utils.c cr-test-utils.h
+test7_LDFLAGS = $(EXTRALDFLAGS)
+test8_SOURCES = test8-main.c
+test8_LDFLAGS = $(EXTRALDFLAGS)
+
+croco_lib = $(top_builddir)/src/@CROCO_LIB@
+LDADD = $(croco_lib)
+
+AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/src -I$(top_builddir)/src
+
+AM_CFLAGS = -I. $(CROCO_CFLAGS)
diff --git a/src/3rdparty/libcroco/tests/README-description.txt b/src/3rdparty/libcroco/tests/README-description.txt
new file mode 100644
index 0000000..a81336f
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/README-description.txt
@@ -0,0 +1,125 @@
+This file describes the tests present in the libcroro tests directory.
+=====================================================================
+
+Initial author: Dodji Seketeli <dodji@seketeli.org>
+
+Each entry of this file is orgnised as follows:
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: name-of-the-test-binary-file
+
+source-file: name-of-the-test-source-file
+
+purpose: purpose of the test.
+
+description: description of the test
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+And, in the words of RMS, happy hacking !
+
+ Dodji
+##################################################################
+
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test0
+
+source-file: test0-main.c
+
+purpose: Tests the cr_input_read_byte() method of the CRInput class.
+
+description: opens the file located at the path in parameter and
+loads it into an input stream using the cr_input_new_from_uri()
+method of the CRInput class.
+Then, reads the bytes from the input stream using the cr_input_read_byte()
+method and dumps each byte read to stdout.
+Note that the input file must be encoded in utf8.
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test1
+
+source-file: test1-main.c
+
+purpose: Test the read_char() method of the CRInput class.
+
+description: opens the file located at the path in parameter and
+loads it into an input stream using the cr_input_new_from_uri()
+method of the CRInput class.
+Then, reads characters from the input stream using the cr_input_read_char()
+method and dumps each character on stdout.
+Note that the input file must be encoded in utf8.
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test2
+
+source-file: test2-main.c
+
+purpose: tests the sac api of the parser.
+
+description: it loads the file located at the path given
+in argument, instantiates a sac parser, set document
+handlers and parses the file.
+The doc handlers simply dump the name name of the callback
+which is being called and some basic additional information.
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test3
+
+source-file: test3-main.c
+
+purpose: Test the SAC api core css grammar parsing
+
+description: it loads the file located at the path given
+in argument, instantiates a sac parser, set document
+handlers and parses the file using the css2 core syntax.
+The doc handlers simply dump the name name of the callback
+which is being called and some basic additional information.
+Here, the goal is that nothing is dump on screen because
+during the parsing using the core grammar syntax, no callback
+should be called.
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test4
+
+source-file: test4-main.c
+
+purpose: tests the cssom parser interface (cr-om-parser.c)
+
+description: parses the file located at the path given in
+parameter and dumps the result of the parsing (the object model)
+on stdout.
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test5
+
+source-file: test5-main.c
+
+purpose: tests the selector cr-sel-eng.c basic functionalities.
+
+description: parses an in memory xml document hardwired in the
+test5-main.c file; parses the stylesheet given in parameter to
+the test5 binary.
+Walks down the xml document tree and runs the selector engine
+on each xml document node to get the css rule that matches it.
+Displays a report that basically say: "this xml node was matched
+by this set of css rules"
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test6
+
+source-file: test6-main.c
+
+purpose: tests the "in memory" css2 parsing capabilities. (cr_om_parser_parse_buf)
+
+
+description: parses an "in memory" hardwired css2 stylesheet
+and dumps it on stdout.
+""""""""""""""""""""""""""""""""""""""""""""""""" \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/cr-test-utils.c b/src/3rdparty/libcroco/tests/cr-test-utils.c
new file mode 100644
index 0000000..9435ef7
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/cr-test-utils.c
@@ -0,0 +1,59 @@
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <string.h>
+#include "cr-test-utils.h"
+
+/**
+ *Parses the command line.
+ *@param a_argc the argc parameter of the main routine.
+ *@param the argv parameter of the main routine.
+ *@param a_options out parameter the parsed options.
+ */
+void
+cr_test_utils_parse_cmd_line (int a_argc, char **a_argv,
+ struct Options *a_options)
+{
+ int i = 0;
+
+ g_return_if_fail (a_options);
+
+ memset (a_options, 0, sizeof (struct Options));
+
+ for (i = 1; i < a_argc; i++) {
+ if (a_argv[i][0] != '-')
+ break;
+
+ if (!strcmp (a_argv[i], "-h")
+ || !strcmp (a_argv[i], "--help")) {
+ a_options->display_help = TRUE;
+ }
+ if (!strcmp (a_argv[i], "--about")) {
+ a_options->display_about = TRUE;
+ }
+ }
+
+ if (i >= a_argc) {
+ /*No file parameter where given */
+ a_options->files_list = NULL;
+ } else {
+ a_options->files_list = &a_argv[i];
+ }
+}
diff --git a/src/3rdparty/libcroco/tests/cr-test-utils.h b/src/3rdparty/libcroco/tests/cr-test-utils.h
new file mode 100644
index 0000000..9219b93
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/cr-test-utils.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+#ifndef __CR_TEST_UTILS_H__
+#define __CR_TEST_UTILS_H__
+
+#include <stdio.h>
+#include <glib.h>
+
+/**
+ *The options data structure.
+ *The variable of this data structure are set
+ *during the parsing the command line by the
+ *parse_command_line() function.
+ */
+struct Options
+{
+ gboolean display_help ;
+ gboolean display_about ;
+ gchar ** files_list ;
+};
+
+
+void
+cr_test_utils_parse_cmd_line (int a_argc, char **a_argv,
+ struct Options *a_options) ;
+
+#endif /*__CR_TEST_UTILS_H__*/
diff --git a/src/3rdparty/libcroco/tests/global-vars.sh.in b/src/3rdparty/libcroco/tests/global-vars.sh.in
new file mode 100644
index 0000000..e291459
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/global-vars.sh.in
@@ -0,0 +1,10 @@
+TEST_INPUTS_DIR=$HERE_DIR/test-inputs
+CSSLINT=$HERE_DIR/../csslint/.libs/csslint-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
+if ! test -x $CSSLINT ; then
+ echo "Aarg Could not find an executable csslint. I was looking for $CSSLINT"
+ echo $
+fi
+
+if ! test x"$VALGRIND" = x ; then
+ CSSLINT="$VALGRIND $CSSLINT"
+fi
diff --git a/src/3rdparty/libcroco/tests/test-functional-notation.sh b/src/3rdparty/libcroco/tests/test-functional-notation.sh
new file mode 100755
index 0000000..2860092
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-functional-notation.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT $TEST_INPUTS_DIR/functional-notation.css
diff --git a/src/3rdparty/libcroco/tests/test-inputs/Makefile.am b/src/3rdparty/libcroco/tests/test-inputs/Makefile.am
new file mode 100644
index 0000000..3c93d8f
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/Makefile.am
@@ -0,0 +1,16 @@
+EXTRA_DIST= prop-vendor-ident.css \
+test0.1.css \
+test1.css \
+test2.1.css \
+test2.2.css \
+test2.css \
+test3.1.css \
+test3.2.css \
+test3.css \
+test4.1.css \
+test4.2.css \
+test5.1.css \
+unknown-at-rule2.css \
+unknown-at-rule.css \
+several-media.css
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/functional-notation.css b/src/3rdparty/libcroco/tests/test-inputs/functional-notation.css
new file mode 100644
index 0000000..cd80f18
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/functional-notation.css
@@ -0,0 +1,2 @@
+foo { bar: attr(width, length, calc(70% - 5px)) }
+foo {bar: attr(x,y) }
diff --git a/src/3rdparty/libcroco/tests/test-inputs/lots-of-comments.css b/src/3rdparty/libcroco/tests/test-inputs/lots-of-comments.css
new file mode 100644
index 0000000..87a6e4a
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/lots-of-comments.css
@@ -0,0 +1,198 @@
+
+
+@charset "utf8";
+
+/********************************************
+ * Parsing location information of the @charset rule
+ ********************************************/
+ /*@charset*/
+ /*line:1 column:1 byte offset:0 */
+ /*utf8*/
+ /*line:1 column:10 byte offset:9 */
+
+@import url("http://pouet.com") screen, paper, aural;
+
+/*****************************************************
+ *Parsing location information for the @import rule
+ ******************************************************/
+
+ /*@import*/
+ /*line:3 column:1 byte offset:19 */
+
+ /*http://pouet.com*/
+ /*line:3 column:13 byte offset:31 */
+
+ /*screen*/
+ /*line:3 column:33 byte offset:51 */
+
+ /*paper*/
+ /*line:3 column:41 byte offset:59 */
+
+ /*aural*/
+ /*line:3 column:48 byte offset:66 */
+
+@page coin :pseudo-page
+
+ /*@page*/
+ /*line:5 column:1 byte offset:75 */
+ /*coin*/
+ /*line:5 column:7 byte offset:81 */
+ /*pseudo-page*/
+ /*line:5 column:13 byte offset:87 */
+
+{
+
+
+page-prop0 : page-val0;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*page-prop0*/
+ /*line:6 column:7 byte offset:107 */
+ /*page-val0*/
+ /*line:6 column:19 byte offset:119 */
+
+
+page-prop1 : page-val1;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*page-prop1*/
+ /*line:7 column:7 byte offset:137 */
+ /*page-val1*/
+ /*line:7 column:19 byte offset:149 */
+}
+@media paper, aural
+ /*@media*/
+ /*line:10 column:1 byte offset:164 */
+ /*paper*/
+ /*line:10 column:8 byte offset:171 */
+ /*aural*/
+ /*line:10 column:15 byte offset:178 */
+
+{
+x {
+/************************************************
+ *Parsing location information of the selector
+ ************************************************/
+/*x*/
+/*line:11 column:5 byte offset:190 */
+ /*x*/
+ /*line:11 column:5 byte offset:190 */
+
+
+foo : fooval;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*foo*/
+ /*line:12 column:7 byte offset:200 */
+ /*fooval*/
+ /*line:12 column:12 byte offset:205 */
+
+
+bar : barval;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*bar*/
+ /*line:13 column:7 byte offset:220 */
+ /*barval*/
+ /*line:13 column:12 byte offset:225 */
+ }
+
+}
+@font-face {
+/******************************************************
+ Parsing location information for the @font-face rule
+ ******************************************************/
+
+ /*@font-face*/
+ /*line:17 column:1 byte offset:243 */
+
+
+font-prop1 : font1;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*font-prop1*/
+ /*line:18 column:2 byte offset:257 */
+ /*font1*/
+ /*line:18 column:14 byte offset:269 */
+
+
+font-prop2 : font2;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*font-prop2*/
+ /*line:19 column:2 byte offset:278 */
+ /*font2*/
+ /*line:19 column:14 byte offset:290 */
+}
+x>y[attr="val"].class#tatati z+toto {
+/************************************************
+ *Parsing location information of the selector
+ ************************************************/
+/*x*/
+/*line:21 column:1 byte offset:300 */
+ /*x*/
+ /*line:21 column:1 byte offset:300 */
+/*y[attr="val"].class#tatati*/
+/*line:21 column:5 byte offset:304 */
+ /*y*/
+ /*line:21 column:5 byte offset:304 */
+
+ /*[attr="val"]*/
+ /*line:21 column:6 byte offset:305 */
+
+ /*.class*/
+ /*line:21 column:17 byte offset:316 */
+
+ /*#tatati*/
+ /*line:21 column:22 byte offset:321 */
+/*z*/
+/*line:21 column:30 byte offset:329 */
+ /*z*/
+ /*line:21 column:30 byte offset:329 */
+/*toto*/
+/*line:21 column:34 byte offset:333 */
+ /*toto*/
+ /*line:21 column:34 byte offset:333 */
+
+
+prop1 : function(a);
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*prop1*/
+ /*line:22 column:2 byte offset:340 */
+ /*function(a)*/
+ /*line:22 column:9 byte offset:347 */
+
+
+prop2 : val2;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*prop2*/
+ /*line:23 column:2 byte offset:362 */
+ /*val2*/
+ /*line:23 column:9 byte offset:369 */
+ }
diff --git a/src/3rdparty/libcroco/tests/test-inputs/parsing-location.css b/src/3rdparty/libcroco/tests/test-inputs/parsing-location.css
new file mode 100644
index 0000000..f760b07
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/parsing-location.css
@@ -0,0 +1,26 @@
+@charset "utf8" ;
+
+@import url("http://pouet.com") screen, paper, aural ;
+@import url(http://pouet.com) screen2, paper2, aural2 ;
+
+@page coin :pseudo-page {
+ page-prop0: page-val0 ;
+ page-prop1: page-val1 ;
+}
+
+@media paper, aural {
+ x {
+ foo: fooval ;
+ bar: barval ;
+ }
+}
+
+@font-face {
+ font-prop1: font1 ;
+ font-prop2: font2 ;
+}
+x > y[attr=val].class#tatati z + toto{
+ prop1: function(a) ;
+ prop2: val2
+}
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/prop-vendor-ident.css b/src/3rdparty/libcroco/tests/test-inputs/prop-vendor-ident.css
new file mode 100644
index 0000000..f7aa8b5
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/prop-vendor-ident.css
@@ -0,0 +1,3 @@
+:-foo-pseudo {
+ -foo-bar-prop: -foobar-value
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.css b/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.css
new file mode 100644
index 0000000..a6ea36b
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.css
@@ -0,0 +1 @@
+body > div p.process { color: aqua; }
diff --git a/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.xml b/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.xml
new file mode 100644
index 0000000..ee5e23d
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.xml
@@ -0,0 +1,10 @@
+<test>
+ <body>
+ <div>
+ <div>
+ <p class="process">This should be aqua</p>
+ </div>
+ </div>
+ </body>
+</test>
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/several-media.css b/src/3rdparty/libcroco/tests/test-inputs/several-media.css
new file mode 100644
index 0000000..79dc336
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/several-media.css
@@ -0,0 +1,10 @@
+@media screen {
+a:link { text-decoration: none; }
+div { width: 50%; }
+}
+
+@media print {
+a { color: red; }
+div { width: 57%; }
+}
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test0.1.css b/src/3rdparty/libcroco/tests/test-inputs/test0.1.css
new file mode 100644
index 0000000..f8e842e
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test0.1.css
@@ -0,0 +1,258 @@
+body {
+ margin : 0px 0px 20px 0px;
+ height : 100%;
+ background : #FFF
+}
+
+A {
+ color : #003366;
+ text-decoration : underline
+}
+
+A:link {
+ color : #003366;
+ text-decoration : underline
+}
+
+A:visited {
+ color : #003366;
+ text-decoration : underline
+}
+
+A:active {
+ color : #999999
+}
+
+A:hover {
+ color : #999999
+}
+
+h1, h2, h3 {
+ margin : 0px;
+ padding : 0px
+}
+
+#banner {
+ font-family : palatino, georgia, verdana, arial, sans-serif;
+ color : #333;
+ top:0;
+ font-size : normal;
+ font-weight : normal;
+}
+
+#banner a, #banner a:link, #banner a:visited, #banner a:active, #banner a:hover {
+ font-family : verdana, arial, sans-serif;
+ font-size : xx-large;
+ color : #333;
+ text-decoration : none
+}
+
+.description {
+ font-family : verdana, arial, sans-serif;
+ color : #333;
+ font-size : small;
+ text-transform : none
+}
+
+#content {
+ position : absolute;
+ background : #FFF;
+ top: 20%;
+ left: 20%;
+ border : 1px solid #FFF
+}
+
+#container {
+ background : #FFF;
+ border : 1px solid #FFF
+}
+
+#links {
+ padding : 15px;
+ border : 1px solid #FFF;
+ width : 200px
+}
+
+.blog {
+ padding : 20px;
+ background : #FFF
+}
+
+.blogbody {
+ font-family : verdana, arial, sans-serif;
+ color : #333;
+ font-size : small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 150%
+}
+
+.blogbody a, .blogbody a:link, .blogbody a:visited, .blogbody a:active, .blogbody a:hover {
+ font-weight : normal;
+ text-decoration : underline
+}
+
+.title {
+ font-family : verdana, arial, sans-serif;
+ font-size : medium;
+ color : #666
+}
+
+.date {
+ font-family : verdana, arial, serif;
+ font-size : large;
+ color : #333;
+ border-bottom : 1px solid #999;
+ margin-bottom : 10px;
+ font-weight : bold
+}
+
+.posted {
+ font-family : verdana, arial, sans-serif;
+ font-size : x-small;
+ color : #000000;
+ margin-bottom : 25px
+}
+
+.calendar {
+ font-family : verdana, arial, sans-serif;
+ color : #333;
+ font-size : x-small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 140%;
+ padding : 2px;
+ text-align : left
+}
+
+.calendarhead {
+ font-family : palatino, georgia, times new roman, serif;
+ color : #666600;
+ font-size : small;
+ font-weight : normal;
+ padding : 2px;
+ letter-spacing : 0.3em;
+ background : #FFF;
+ text-transform : uppercase;
+ text-align : left
+}
+
+.side {
+ font-family : verdana, arial, sans-serif;
+ color : #333;
+ font-size : x-small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 140%;
+ padding : 2px
+}
+
+#menubar {
+ font-family : verdana, arial, sans-serif;
+ color : #333;
+ font-size : small;
+ font-weight : normal;
+ position:absolute;
+ top:20%;
+ padding: 2px;
+ letter-spacing : 0.1em;
+ background : #FFF;
+ text-transform : uppercase
+}
+
+.syndicate {
+ font-family : verdana, arial, sans-serif;
+ font-size : xx-small;
+ line-height : 140%;
+ padding : 2px;
+ margin-top : 15px;
+ background : #FFF
+}
+
+.powered {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : x-small;
+ line-height : 140%;
+ text-transform : uppercase;
+ padding : 2px;
+ margin-top : 50px;
+ letter-spacing : 0.2em;
+ background : #FFF
+}
+
+.comments-body {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 140%;
+ padding-bottom : 10px;
+ padding-top : 10px;
+ border-bottom : 1px dotted #999
+}
+
+.comments-post {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : x-small;
+ font-weight : normal;
+ background : #FFF
+}
+
+.trackback-url {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 140%;
+ padding : 5px;
+ border : 1px dotted #999
+}
+
+.trackback-body {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 140%;
+ padding-bottom : 10px;
+ padding-top : 10px;
+ border-bottom : 1px dotted #999
+}
+
+.trackback-post {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : x-small;
+ font-weight : normal;
+ background : #FFF
+}
+
+.comments-head {
+ font-family : verdana, arial, sans-serif;
+ font-size : small;
+ color : #666;
+ border-bottom : 1px solid #999;
+ margin-top : 20px;
+ font-weight : bold;
+ background : #FFF
+}
+
+#banner-commentspop {
+ font-family : verdana, arial, sans-serif;
+ color : #FFF;
+ font-size : large;
+ font-weight : bold;
+ border-left : 1px solid #FFF;
+ border-right : 1px solid #FFF;
+ border-top : 1px solid #FFF;
+ background : #003366;
+ padding-left : 15px;
+ padding-right : 15px;
+ padding-top : 5px;
+ padding-bottom : 5px
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test1.css b/src/3rdparty/libcroco/tests/test-inputs/test1.css
new file mode 100644
index 0000000..b03c8a4
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test1.css
@@ -0,0 +1,316 @@
+body {
+
+ background-color: #E5E5E5;
+
+ scrollbar-face-color: #CCCCCC;
+
+ scrollbar-highlight-color: #FFFFFF;
+
+ scrollbar-shadow-color: #CCCCCC;
+
+ scrollbar-3dlight-color: #D1D7DC;
+
+ scrollbar-arrow-color: #000000;
+
+ scrollbar-track-color: #FFFFFF;
+
+ scrollbar-darkshadow-color: #000000;
+
+}
+
+
+
+font, th, td, p {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+}
+
+
+
+h1, h2 { font-size: 11px; color: #000000; font-weight: bold; }
+
+
+
+a:link, a:active, a:visited { color: #000000; }
+
+
+
+a:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+hr { height: 0px; border: solid #CCCCCC 0px; border-top-width: 1px; }
+
+
+
+small { font-size: 10px; }
+
+
+
+input, textarea, select {
+
+ font: normal 11px Verdana, Arial, Helvetica, sans-serif;
+
+ color: #000000;
+
+ border-color: #000000;
+
+}
+
+
+
+input { text-indent: 2px; }
+
+
+
+
+input.post, textarea.post, select {
+
+ background-color: #FFFFFF;
+
+}
+
+
+
+
+th {
+
+ font-size: 11px; color: #CCCCCC; font-weight: bold;
+
+ background-color: #000000; height: 25px;
+
+ background-image: url(/~wiceyto/test/templates/blacknwhite/images/cellpic3.gif);
+
+}
+
+
+
+
+.fontspec, .tablefont {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+}
+
+
+
+.navbartext, .navbarfont {
+
+ font-size: 11px; color: #000000; font-weight: bold;
+
+}
+
+
+
+.navbartext a, .navbarfont a {
+
+ color: #000000; font-weight: bold; text-decoration: none;
+
+}
+
+
+
+.navbartext a:hover, .navbarfont a:hover {
+
+ color: #CC0000; text-decoration: none;
+
+}
+
+
+
+.tablespec, .guestbook { background-color: #FFFFFF; border: 2px #000000 solid; }
+
+.tablespec th, .tablespec td { color: #000000; background-color: #CCCCCC; }
+
+.tablespec th { background-image: none; }
+
+
+
+.messageblock {
+
+ border: dashed 1px;
+
+ margin-right: 4em; margin-left: 4em;
+
+ padding: 3em;
+
+}
+
+
+
+/* $MessageOpenCode - the body of text of the posts */
+
+.messagebody { font-size: 12px; line-height: 18px; }
+
+.messagebody a { color: #000000; text-decoration: underline; }
+
+.messagebody a:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+
+.newcode { font-size: 11px; color: #CC0000; font-weight: bold; }
+
+.admincode { font-size: 11px; color: #990000; font-style: bold; }
+
+
+
+
+.bodyline { background-color: #FFFFFF; border: 1px #000000 solid; }
+
+
+
+
+.quote, .code {
+
+ background-color: #FAFAFA; border: #D1D7DC; border-style: solid;
+
+ border-top-width: 1px; border-right-width: 1px;
+
+ border-bottom-width: 1px; border-left-width: 1px;
+
+}
+
+
+
+.quote {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+ color: #444444; line-height: 125%;
+
+}
+
+
+
+.code {
+
+ font-family: Courier, 'Courier New', sans-serif;
+
+ font-size: 11px;
+
+ color: #CC0000;
+
+}
+
+
+
+
+input.button {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+ color: #000000;
+
+ background-color: #FFFFFF;
+
+}
+
+
+
+/* Format button rollover help line. Actually it's a text box
+
+ set to the same color as the background so no one will know. */
+
+.helpline { background-color: #CCCCCC; border-style: none; }
+
+
+
+/* additional table cell colors and backgrounds */
+
+td.row2 { background-color: #CCCCCC; }
+
+td.row1 { background-color: #CCCCCC; }
+
+td.row3 { background-color: #D1D7DC; }
+
+
+
+/* additional general text */
+
+.gen { font-size: 12px; }
+
+.genmed { font-size: 11px; }
+
+.gensmall { font-size: 10px; }
+
+.gen, .genmed, .gensmall { color: #000000; }
+
+a.gen, a.genmed, a.gensmall { color: #000000; text-decoration: none; }
+
+a.gen:hover, a.genmed:hover, a.gensmall:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+/* import fancy styles. For IE only. NS4.x doesn't use the @import function */
+
+@import url("/your.site/webbbs/themes/formIE.css");
+
+
+
+/* END of blacknwhite.css */
+
+
+
+
+
+
+
+/* Appendix.2-2: Example fancy styles CSS file
+
+Paste these into a text file and save as formIE.css */
+
+
+
+/* Fancy form styles for IE */
+
+
+
+input, textarea, select {
+
+border-top-width : 1px;
+
+border-right-width : 1px;
+
+border-bottom-width : 1px;
+
+border-left-width : 1px;
+
+}
+
+
+
+input { text-indent : 2px; }
+
+
+
+input.button {
+
+border-top-width : 1px;
+
+border-right-width : 1px;
+
+border-bottom-width : 1px;
+
+border-left-width : 1px;
+
+}
+
+
+
+.postbody { line-height: 18px}
+
+.magic {
+ margin-left: -20px;
+}
+
+/* END of formIE.css */
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test2.1.css b/src/3rdparty/libcroco/tests/test-inputs/test2.1.css
new file mode 100644
index 0000000..ba447fb
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test2.1.css
@@ -0,0 +1,47 @@
+
+/*simple Attribute set selectors*/
+s1[foo] {prop1 : "\53 tring"}
+
+/* line break is invalid */
+s2[foo] {prop1 : "
+tring"}
+
+/*simple exact attribute selector, simple ruleset*/
+s3[foo="warning"] {prop1 : value1}
+
+/**
+ *"space separated value list"
+ *attribute selector, simple ruleset
+ */
+s4[foo~="warning"] {prop1 :value1}
+
+/**
+ *"hyphen separated value list" attribute selector,
+ * simple ruleset
+ */
+
+ /*simple class selector, simple ruleset*/
+ s5.warning {prop1 : value}
+
+ E#myid {prop1 : value1}
+
+
+/*below are tests that we know are working*/
+
+/*simple ident pseudo class selector, simple ruleset test*/
+S6:first-child {prop1 : value1 ; prop2 : value2}
+
+/*function pseudo class selector, simple ruleset test*/
+S7:lang(c) {prop1 : value1}
+
+/*Adjacent selectors, simple ruleset test*/
+S8 + s2 {prop1: value1}
+
+/* quoted strings */
+.quotedstrings {
+ -test-string1: "foo'bar";
+ -test-string2: 'foo\'bar';
+ -test-string3: 'foo"bar';
+ -test-string4: "foo\"bar";
+ -test-string5: 'foo\\bar';
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test2.2.css b/src/3rdparty/libcroco/tests/test-inputs/test2.2.css
new file mode 100644
index 0000000..0a58bbe
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test2.2.css
@@ -0,0 +1,686 @@
+p.commentsbody {
+ border-left-style: solid;
+ border-width: 1px;
+ border-color: rgb(0, 0, 0);
+ padding-left: 10px;
+ margin-right: 20px;
+ text-align: justify;
+}
+
+* {
+ font-family: Verdana, Arial, Helvetica, sans-serif, monospace;
+}
+
+body {
+ background: #606060;
+ color: #000000;
+}
+
+a:link {
+ color: #0000FF;
+ background: transparent;
+ text-decoration: none;
+}
+
+a:visited {
+ color: #990099;
+ background: transparent;
+ text-decoration: none;
+}
+
+
+a:active {
+ color: #000000;
+ background: #ADD8E6;
+ text-decoration: none;
+}
+
+
+h1.rubrique_info {
+ color: #990033;
+ margin: 0px 0px 0px 0px;
+ padding: 0em;
+ border: 0px;
+ font-size: 12px;
+}
+
+
+h1.connexe {
+ font-size: 12px;
+ padding: 0em;
+ margin: 0px 0px 0px 0px;
+ color: #990033;
+}
+
+a.rubrique_infolink {
+ text-decoration: none;
+}
+
+ul.rubrique_infoul {
+ display: inline;
+ list-style-type: square;
+}
+ul.rubrique_infoul * {
+ width: 100%;
+}
+li.rubrique_infoul {
+ margin-left: 15px;
+}
+h1 {
+ color: #990033;
+}
+
+div.main {
+ background: white;
+ color: #000000;
+ margin-left: 5px;
+ margin-right: 5px;
+ border: 1px black solid;
+ text-align: left;
+ font-size: 12px;
+}
+div.lsfnbanner {
+ margin-left: 150px;
+ margin-right: 170px;
+ border-top: none;
+ padding-left: 10px;
+ padding-right: 10px;
+ border-bottom: 1px black solid;
+ border-right: 1px black solid;
+ border-left: 1px black solid;
+ text-align: left;
+ font-size: 11px;
+ padding-top: 2px;
+ background-color: #eeeae6;
+}
+div.footer {
+ padding-top: 5px;
+ padding-bottom: 3px;
+ border-top: 1px black solid;
+ border-left: 1px black solid;
+ border-right: 1px black solid;
+ text-align: left;
+ font-size: 9px;
+ background: #dcdff4;
+ width: 600px;
+ margin-top: 40px;
+ margin-left: 20px;
+}
+div.footer p {
+ margin-left: 10px;
+ margin-top: 2px;
+ margin-bottom: 2px;
+}
+
+a.lsfnlink:link,a.lsfnlink:visited,a.lsfnlink:active {
+ text-decoration: none;
+ color: #333333;
+ font-size: 10px;
+}
+a.lsfnlink:hover {
+ text-decoration: underline;
+ color: black;
+}
+div.menubartop {
+ margin-bottom: 10px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ font-size: 13px;
+}
+div.smallmenubar {
+ background: white;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ font-weight:bold;
+ font-size: 10px;
+ text-align: right;
+}
+div.menuevent {
+ float: left;
+ width: 350px;
+ font-size: 11px;
+ text-align: left;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ font-weight: bold;
+ margin: 0px;
+}
+div.menubar {
+ background: #cac2a8;
+ border-top: 1px black solid;
+ border-bottom: 1px black solid;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 3px;
+ padding-bottom: 2px;
+ font-weight:bold;
+ font-size: 13px;
+}
+div.menubar a {
+ text-decoration: none;
+}
+div.menudate {
+ float: left;
+ width: 130px;
+ padding-top: 5px;
+}
+div.menuaccroche {
+ margin-left: 30px;
+ float: left;
+ text-decoration: underline;
+ font-size: 14px;
+}
+div.menusearch {
+ float: right;
+ text-align: right;
+ padding-top: 5px;
+ width: 170px;
+}
+div.menusearch p {
+ margin: 0px 0px 0px 0px;
+}
+.searchinput {
+ border: solid 1px black;
+}
+a#menulinkselect {
+ color: #ed7e00;
+}
+
+div.leftbox {
+ width: 200px;
+ float: left;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-bottom: 5px;
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ background: white;
+ margin-bottom: 10px;
+}
+div.leftbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.leftbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.leftbox ul {
+ list-style-type: square;
+ margin-bottom: 10px;
+ margin-left: 0em;
+ padding-left: 0em;
+}
+div.leftbox li {
+ margin-left: 10px;
+}
+
+div.rightbox {
+ width: 150px;
+ float: right;
+ padding-top: 10px;
+ padding-left: 5px;
+ padding-right: 15px;
+ padding-bottom: 5px;
+ border-left: 1px black solid;
+ border-bottom: 1px black solid;
+ text-align: left;
+}
+div.newjournaldiv {
+ text-align: justify;
+ margin-left: 10%;
+ font-size: 12px;
+ width: 600px;
+}
+div.newjournaldiv p {
+ margin-bottom: 0px;
+ margin-top: 20px;
+}
+div.journaldiv {
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 1px black solid;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ background-color: #eef;
+}
+div.journaldiv p {
+ margin-top: 10px;
+ margin-bottom: 0px;
+}
+div.journaldiv h1 {
+ color: #990033;
+ font-size: 14px;
+ margin: 0px;
+}
+div.journaldiv h2 {
+ font-size: 10px;
+ margin: 0px;
+}
+div.tipdiv {
+ margin-left: 220px;
+ margin-right: 50px;
+ margin-top: 20px;
+ padding-top: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ text-align: justify;
+ background-color: #eee;
+ border: black solid 1px;
+}
+div.tipdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ color: black;
+ margin-top: 0px;
+ margin-bottom: 20px;
+}
+div.tipdiv h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 12px;
+ margin: 0px;
+}
+
+div.newsdiv {
+ margin-left: 220px;
+ margin-right: 180px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+ text-align: justify;
+}
+div.newsdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.newsdiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.newsdiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.objdiv {
+ margin-left: 220px;
+ margin-right: 20px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+}
+
+h1.newstitle {
+ text-align: left;
+ font-size: 14px;
+ margin: 0px 0px 0px 0px;
+ color: black;
+}
+div.titlediv {
+ border-top: solid #cac2a8 2px;
+ margin-top: 20px;
+ background-color: #eeeae6;
+ padding-left: 10px;
+ font-size: 11px;
+}
+div.bodydiv {
+ border: solid #9e9784 1px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 10px;
+ padding-bottom: 5px;
+ margin-top: 2px;
+ text-align: justify;
+}
+
+div.comments {
+ padding: 10px;
+ border-top: solid 2px #d37537;
+ border-bottom: solid 2px #d37537;
+ margin-top: 20px;
+ margin-bottom: 10px;
+ background-color: #cacaca;
+ font-size: 12px;
+ line-height: 1.3em;
+}
+
+p.commentsbody {
+ border-left-style: solid;
+ border-width: 1px;
+ border-color: rgb(0, 0, 0);
+ padding-left: 10px;
+ text-align: justify;
+ margin-right: 20px;
+}
+
+div.commentsreply {
+ margin-left: 220px;
+ text-align: center;
+ margin-top: 50px;
+}
+
+ul.commentsul {
+ list-style-type: none;
+ margin-bottom: 10px;
+ margin-left: 1.25em;
+ padding-left: 0em;
+ border-left: 1px solid black;
+}
+ul.commentsli {
+ margin: 10px;
+}
+div.comments li {
+ margin-top: 20px;
+ margin-left: 2px;
+}
+
+div.comments h1 {
+ font-size: 12px;
+ color: black;
+ margin: 0px 20px 3px 0px;
+ background-color: rgb(226, 226, 226);
+ padding-left: 1px;
+ font-weight: none;
+}
+
+div.articlediv {
+ padding-left: 20px;
+ padding-right: 20px;
+ padding-top: 10px;
+ padding-bottom: 20px;
+ margin-right: 10px;
+ margin-left: 220px;
+ border: solid 1px black;
+ margin-top: 10px;
+ text-align: justify;
+ background-color: #E2E2E2;
+}
+img {
+ border: 0px;
+}
+div.sectionimg {
+ float: left;
+ margin-right: 10px;
+ margin-top: 5px;
+}
+p.hautpage {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ margin-left: 10px;
+}
+div.leftcol {
+ width: 202px;
+ width: 202px;
+ float: left;
+ padding: 0px;
+}
+div.logodiv {
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ padding: 0px;
+ line-height: 0px
+}
+div.loginbox {
+ margin-left: 4px;
+ border: solid #a59f8b 1px;
+ margin-top: 2px;
+ padding: 5px;
+ background-color: #fff2e8;
+ font-size: 10px;
+}
+div.loginbox p {
+ margin: 0px;
+ padding: 0px;
+}
+div.loginbox ul {
+ margin-left: 10px;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.loginbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.loginbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.loginbox h3 {
+ margin-top: 0px;
+ margin-bottom: 5px;
+ font-size: 12px;
+}
+div.polldivtitle {
+ margin-bottom: 1px;
+ background-color: #cac2a8;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ font-size: 10px;
+ border-top: solid #a59f8b 1px;
+ border-bottom: solid #a59f8b 1px;
+ text-transform: uppercase;
+}
+div.polldiv {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ background: #fff2e8;
+}
+div.polldiv p {
+margin: 5px; padding: 0px;
+}
+div.polldiv ul {
+ margin-left: 5px;
+ margin-top: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.otherboxtitle {
+ margin-bottom: 2px;
+ background-color: #e3dabc;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ padding-top: 2px;
+ font-size: 11px;
+ border-top: solid #777364 1px;
+ border-bottom: solid #777364 1px;
+ text-transform: uppercase;
+ font-weight: bold;
+}
+div.otherbox {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 10px;
+}
+div.otherbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.otherbox h2 {
+ font-weight: bold;
+ font-size: 11px;
+ margin: 0px;
+}
+div.otherbox p {
+ margin-top: 5px;
+ margin-bottom: 10px;
+}
+div.rightlogo {
+ width: 90px;
+ float: right;
+ margin-right: 0px;
+ padding-top: 0px;
+ padding-left: 0px;
+ padding-bottom: 0px;
+}
+div.centraldiv {
+ margin-left: 220px;
+ margin-right: 10px;
+ margin-bottom: 20px;
+ margin-top: 10px;
+}
+div.centraldiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.centraldiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.centraldiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.centralinfo {
+ position:relative;
+ height:160px;
+}
+div.lefttopbox {
+ position:relative;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-top: 5px;
+ border: 1px #a59f8b solid;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 12px;
+ width: 47%;
+ float: left;
+}
+div.lefttopbox p {
+ margin-top: 5px; margin-bottom: 10px;
+}
+div.lefttopbox h1 {
+ font-size: 13px;
+ font-weight: bold;
+ margin: 0px;
+ text-align: right;
+}
+div.lefttopbox h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.lefttopbox h3 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.righttopbox {
+ position:relative;
+ border: 1px #a59f8b solid;
+ background: white;
+ padding: 5px;
+ text-align: justify;
+ font-size: 12px;
+ width: 47%;
+ float: right;
+}
+div.righttopbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.righttopbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.boardindex {
+ text-align: justify;
+ font-size: 11px;
+ padding: 10px;
+ margin-left: 20px;
+ margin-right: 20px;
+}
+a.boardindex:link,a.boardindex:visited,a.boardindex:active {
+ text-decoration:none;
+ color: red;
+}
+div.boardleftmsg {
+ float: left;
+ margin-top: 3px;
+}
+div.boardrightmsg {
+ margin-left: 130px;
+ margin-top: 3px;
+ padding-left: 5px;
+}
+div.journalbody {
+ margin-left: 40px;
+ margin-top: 40px;
+}
+div.journalbody h1 {
+ font-size: 15px;
+ font-weight: bold;
+}
+div.journalbody p {
+ margin-bottom: 20px;
+}
+.formulaire {
+ border: solid 1px black;
+font-size: 12px;
+background-color: #eef;
+color: #000000;
+}
+.newcomments {
+ color: red;
+ font-weight: bold;
+}
+div.commentsreplythanks {
+ margin-left: 100px;
+ margin-top: 50px;
+ margin-right: 100px;
+ background-color: #eee;
+ border: black solid 1px;
+ padding: 10px;
+}
+div.archivediv {
+ margin-right: 20px;
+}
+.archivedate {
+ color:#f30;
+}
+.archivelink {
+ font-size: 14px;
+ font-weight: bold;
+ text-decoration: underline;
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test2.css b/src/3rdparty/libcroco/tests/test-inputs/test2.css
new file mode 100644
index 0000000..2442048
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test2.css
@@ -0,0 +1,9 @@
+
+/*simple selector and simple rulset test*/
+S1 {prop1 : value1}
+
+/*Simple selector list and simple ruleset test*/
+s1,s2 {color: black ; background: white}
+
+/*descendants and child selector list, simple ruleset test*/
+s1 s2, S3 > s4 {prop1 : value1 ; prop2 : value2}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test3.1.css b/src/3rdparty/libcroco/tests/test-inputs/test3.1.css
new file mode 100644
index 0000000..9c53843
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test3.1.css
@@ -0,0 +1,36 @@
+S1:lang(c) {prop1 : value1}
+
+/*simple Attribute set selectors*/
+s1[foo] {prop1 : value1}
+
+/*simple exact attribute selector, simple ruleset*/
+s1[foo="warning"] {prop1 : value1}
+
+/**
+ *"space separated value list"
+ *attribute selector, simple ruleset
+ */
+s1[foo~="warning"] {prop1 :value1}
+
+/**
+ *"hyphen separated value list" attribute selector,
+ * simple ruleset
+ */
+
+ /*simple class selector, simple ruleset*/
+ s1.warning {prop1 : value}
+
+ E#myid {prop1 : value1}
+
+
+/*below are tests that we know are working*/
+
+/*simple ident pseudo class selector, simple ruleset test*/
+S1:first-child {prop1 : value1 ; prop2 : value2}
+
+/*function pseudo class selector, simple ruleset test => merdoie*/
+S1:lang(c) {prop1 : value1}
+
+/*Adjacent selectors, simple ruleset test*/
+S1 + s2 {prop1: value1}
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test3.2.css b/src/3rdparty/libcroco/tests/test-inputs/test3.2.css
new file mode 100644
index 0000000..2857fc4
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test3.2.css
@@ -0,0 +1,693 @@
+h1.rubrique_info {
+ color: #990033;
+ margin: 0px 0px 0px 0px;
+ padding: 0em;
+ border: 0px;
+ font-size: 12px;
+}
+
+* {
+ font-family: Verdana, Arial, Helvetica, sans-serif, monospace;
+}
+
+body {
+ background: #606060;
+ color: #000000;
+}
+
+a:link {
+ color: #0000FF;
+ background: transparent;
+ text-decoration: none;
+}
+
+a:visited {
+ color: #990099;
+ background: transparent;
+ text-decoration: none;
+}
+
+
+a:active {
+ color: #000000;
+ background: #ADD8E6;
+ text-decoration: none;
+}
+
+
+h1.rubrique_info {
+ color: #990033;
+ margin: 0px 0px 0px 0px;
+ padding: 0em;
+ border: 0px;
+ font-size: 12px;
+}
+
+/*
+h1.connexe {
+ font-size: 12px;
+ padding: 0em;
+ margin: 0px 0px 0px 0px;
+ color: #990033;
+}
+
+
+a.rubrique_infolink {
+ text-decoration: none;
+}
+
+
+ul.rubrique_infoul {
+ display: inline;
+ list-style-type: square;
+}
+
+
+ul.rubrique_infoul * {
+ width: 100%;
+}
+
+li.rubrique_infoul {
+ margin-left: 15px;
+}
+h1 {
+ color: #990033;
+}
+
+div.main {
+ background: white;
+ color: #000000;
+ margin-left: 5px;
+ margin-right: 5px;
+ border: 1px black solid;
+ text-align: left;
+ font-size: 12px;
+}
+div.lsfnbanner {
+ margin-left: 150px;
+ margin-right: 170px;
+ border-top: none;
+ padding-left: 10px;
+ padding-right: 10px;
+ border-bottom: 1px black solid;
+ border-right: 1px black solid;
+ border-left: 1px black solid;
+ text-align: left;
+ font-size: 11px;
+ padding-top: 2px;
+ background-color: #eeeae6;
+}
+div.footer {
+ padding-top: 5px;
+ padding-bottom: 3px;
+ border-top: 1px black solid;
+ border-left: 1px black solid;
+ border-right: 1px black solid;
+ text-align: left;
+ font-size: 9px;
+ background: #dcdff4;
+ width: 600px;
+ margin-top: 40px;
+ margin-left: 20px;
+}
+div.footer p {
+ margin-left: 10px;
+ margin-top: 2px;
+ margin-bottom: 2px;
+}
+
+a.lsfnlink:link,a.lsfnlink:visited,a.lsfnlink:active {
+ text-decoration: none;
+ color: #333333;
+ font-size: 10px;
+}
+a.lsfnlink:hover {
+ text-decoration: underline;
+ color: black;
+}
+div.menubartop {
+ margin-bottom: 10px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ font-size: 13px;
+}
+div.smallmenubar {
+ background: white;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ font-weight:bold;
+ font-size: 10px;
+ text-align: right;
+}
+
+div.menuevent {
+ float: left;
+ width: 350px;
+ font-size: 11px;
+ text-align: left;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ font-weight: bold;
+ margin: 0px;
+}
+div.menubar {
+ background: #cac2a8;
+ border-top: 1px black solid;
+ border-bottom: 1px black solid;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 3px;
+ padding-bottom: 2px;
+ font-weight:bold;
+ font-size: 13px;
+}
+div.menubar a {
+ text-decoration: none;
+}
+div.menudate {
+ float: left;
+ width: 130px;
+ padding-top: 5px;
+}
+div.menuaccroche {
+ margin-left: 30px;
+ float: left;
+ text-decoration: underline;
+ font-size: 14px;
+}
+div.menusearch {
+ float: right;
+ text-align: right;
+ padding-top: 5px;
+ width: 170px;
+}
+div.menusearch p {
+ margin: 0px 0px 0px 0px;
+}
+.searchinput {
+ border: solid 1px black;
+}
+a#menulinkselect {
+ color: #ed7e00;
+}
+
+div.leftbox {
+ width: 200px;
+ float: left;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-bottom: 5px;
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ background: white;
+ margin-bottom: 10px;
+}
+div.leftbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.leftbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.leftbox ul {
+ list-style-type: square;
+ margin-bottom: 10px;
+ margin-left: 0em;
+ padding-left: 0em;
+}
+div.leftbox li {
+ margin-left: 10px;
+}
+
+div.rightbox {
+ width: 150px;
+ float: right;
+ padding-top: 10px;
+ padding-left: 5px;
+ padding-right: 15px;
+ padding-bottom: 5px;
+ border-left: 1px black solid;
+ border-bottom: 1px black solid;
+ text-align: left;
+}
+div.newjournaldiv {
+ text-align: justify;
+ margin-left: 10%;
+ font-size: 12px;
+ width: 600px;
+}
+div.newjournaldiv p {
+ margin-bottom: 0px;
+ margin-top: 20px;
+}
+div.journaldiv {
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 1px black solid;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ background-color: #eef;
+}
+div.journaldiv p {
+ margin-top: 10px;
+ margin-bottom: 0px;
+}
+div.journaldiv h1 {
+ color: #990033;
+ font-size: 14px;
+ margin: 0px;
+}
+div.journaldiv h2 {
+ font-size: 10px;
+ margin: 0px;
+}
+div.tipdiv {
+ margin-left: 220px;
+ margin-right: 50px;
+ margin-top: 20px;
+ padding-top: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ text-align: justify;
+ background-color: #eee;
+ border: black solid 1px;
+}
+div.tipdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ color: black;
+ margin-top: 0px;
+ margin-bottom: 20px;
+}
+div.tipdiv h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 12px;
+ margin: 0px;
+}
+
+div.newsdiv {
+ margin-left: 220px;
+ margin-right: 180px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+ text-align: justify;
+}
+div.newsdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.newsdiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.newsdiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.objdiv {
+ margin-left: 220px;
+ margin-right: 20px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+}
+
+h1.newstitle {
+ text-align: left;
+ font-size: 14px;
+ margin: 0px 0px 0px 0px;
+ color: black;
+}
+div.titlediv {
+ border-top: solid #cac2a8 2px;
+ margin-top: 20px;
+ background-color: #eeeae6;
+ padding-left: 10px;
+ font-size: 11px;
+}
+div.bodydiv {
+ border: solid #9e9784 1px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 10px;
+ padding-bottom: 5px;
+ margin-top: 2px;
+ text-align: justify;
+}
+
+div.comments {
+ padding: 10px;
+ border-top: solid 2px #d37537;
+ border-bottom: solid 2px #d37537;
+ margin-top: 20px;
+ margin-bottom: 10px;
+ background-color: #cacaca;
+ font-size: 12px;
+ line-height: 1.3em;
+}
+
+p.commentsbody {
+ border-left-style: solid;
+ border-width: 1px;
+ border-color: rgb(0, 0, 0);
+ padding-left: 10px;
+ text-align: justify;
+ margin-right: 20px;
+}
+
+div.commentsreply {
+ margin-left: 220px;
+ text-align: center;
+ margin-top: 50px;
+}
+
+ul.commentsul {
+ list-style-type: none;
+ margin-bottom: 10px;
+ margin-left: 1.25em;
+ padding-left: 0em;
+ border-left: 1px solid black;
+}
+ul.commentsli {
+ margin: 10px;
+}
+div.comments li {
+ margin-top: 20px;
+ margin-left: 2px;
+}
+
+div.comments h1 {
+ font-size: 12px;
+ color: black;
+ margin: 0px 20px 3px 0px;
+ background-color: rgb(226, 226, 226);
+ padding-left: 1px;
+ font-weight: none;
+}
+
+div.articlediv {
+ padding-left: 20px;
+ padding-right: 20px;
+ padding-top: 10px;
+ padding-bottom: 20px;
+ margin-right: 10px;
+ margin-left: 220px;
+ border: solid 1px black;
+ margin-top: 10px;
+ text-align: justify;
+ background-color: #E2E2E2;
+}
+img {
+ border: 0px;
+}
+div.sectionimg {
+ float: left;
+ margin-right: 10px;
+ margin-top: 5px;
+}
+p.hautpage {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ margin-left: 10px;
+}
+div.leftcol {
+ width: 202px;
+ width: 202px;
+ float: left;
+ padding: 0px;
+}
+div.logodiv {
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ padding: 0px;
+ line-height: 0px
+}
+div.loginbox {
+ margin-left: 4px;
+ border: solid #a59f8b 1px;
+ margin-top: 2px;
+ padding: 5px;
+ background-color: #fff2e8;
+ font-size: 10px;
+}
+div.loginbox p {
+ margin: 0px;
+ padding: 0px;
+}
+div.loginbox ul {
+ margin-left: 10px;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.loginbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.loginbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.loginbox h3 {
+ margin-top: 0px;
+ margin-bottom: 5px;
+ font-size: 12px;
+}
+div.polldivtitle {
+ margin-bottom: 1px;
+ background-color: #cac2a8;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ font-size: 10px;
+ border-top: solid #a59f8b 1px;
+ border-bottom: solid #a59f8b 1px;
+ text-transform: uppercase;
+}
+div.polldiv {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ background: #fff2e8;
+}
+div.polldiv p {
+margin: 5px; padding: 0px;
+}
+div.polldiv ul {
+ margin-left: 5px;
+ margin-top: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.otherboxtitle {
+ margin-bottom: 2px;
+ background-color: #e3dabc;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ padding-top: 2px;
+ font-size: 11px;
+ border-top: solid #777364 1px;
+ border-bottom: solid #777364 1px;
+ text-transform: uppercase;
+ font-weight: bold;
+}
+div.otherbox {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 10px;
+}
+div.otherbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.otherbox h2 {
+ font-weight: bold;
+ font-size: 11px;
+ margin: 0px;
+}
+div.otherbox p {
+ margin-top: 5px;
+ margin-bottom: 10px;
+}
+div.rightlogo {
+ width: 90px;
+ float: right;
+ margin-right: 0px;
+ padding-top: 0px;
+ padding-left: 0px;
+ padding-bottom: 0px;
+}
+div.centraldiv {
+ margin-left: 220px;
+ margin-right: 10px;
+ margin-bottom: 20px;
+ margin-top: 10px;
+}
+div.centraldiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.centraldiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.centraldiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.centralinfo {
+ position:relative;
+ height:160px;
+}
+div.lefttopbox {
+ position:relative;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-top: 5px;
+ border: 1px #a59f8b solid;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 12px;
+ width: 47%;
+ float: left;
+}
+div.lefttopbox p {
+ margin-top: 5px; margin-bottom: 10px;
+}
+div.lefttopbox h1 {
+ font-size: 13px;
+ font-weight: bold;
+ margin: 0px;
+ text-align: right;
+}
+div.lefttopbox h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.lefttopbox h3 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.righttopbox {
+ position:relative;
+ border: 1px #a59f8b solid;
+ background: white;
+ padding: 5px;
+ text-align: justify;
+ font-size: 12px;
+ width: 47%;
+ float: right;
+}
+div.righttopbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.righttopbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.boardindex {
+ text-align: justify;
+ font-size: 11px;
+ padding: 10px;
+ margin-left: 20px;
+ margin-right: 20px;
+}
+a.boardindex:link,a.boardindex:visited,a.boardindex:active {
+ text-decoration:none;
+ color: red;
+}
+div.boardleftmsg {
+ float: left;
+ margin-top: 3px;
+}
+div.boardrightmsg {
+ margin-left: 130px;
+ margin-top: 3px;
+ padding-left: 5px;
+}
+div.journalbody {
+ margin-left: 40px;
+ margin-top: 40px;
+}
+div.journalbody h1 {
+ font-size: 15px;
+ font-weight: bold;
+}
+div.journalbody p {
+ margin-bottom: 20px;
+}
+
+.formulaire {
+ border: solid 1px black;
+font-size: 12px;
+background-color: #eef;
+color: #000000;
+}
+.newcomments {
+ color: red;
+ font-weight: bold;
+}
+div.commentsreplythanks {
+ margin-left: 100px;
+ margin-top: 50px;
+ margin-right: 100px;
+ background-color: #eee;
+ border: black solid 1px;
+ padding: 10px;
+}
+div.archivediv {
+ margin-right: 20px;
+}
+.archivedate {
+ color:#f30;
+}
+.archivelink {
+ font-size: 14px;
+ font-weight: bold;
+ text-decoration: underline;
+}
+*/ \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test3.css b/src/3rdparty/libcroco/tests/test-inputs/test3.css
new file mode 100644
index 0000000..2442048
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test3.css
@@ -0,0 +1,9 @@
+
+/*simple selector and simple rulset test*/
+S1 {prop1 : value1}
+
+/*Simple selector list and simple ruleset test*/
+s1,s2 {color: black ; background: white}
+
+/*descendants and child selector list, simple ruleset test*/
+s1 s2, S3 > s4 {prop1 : value1 ; prop2 : value2}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test4.1.css b/src/3rdparty/libcroco/tests/test-inputs/test4.1.css
new file mode 100644
index 0000000..01bd9d4
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test4.1.css
@@ -0,0 +1,682 @@
+* {
+ font-family: Verdana, Arial, Helvetica, sans-serif, monospace !important;
+}
+
+tutu:class1:class2 {
+ test:ok ;
+}
+
+body {
+ background: #606060;
+ color: #000000;
+}
+
+
+a:link {
+ color: #0000FF;
+ background: transparent;
+ text-decoration: none;
+}
+
+
+a:visited {
+ color: #990099;
+ background: transparent;
+ text-decoration: none;
+}
+
+
+a:active {
+ color: #000000;
+ background: #ADD8E6;
+ text-decoration: none;
+}
+
+h1.rubrique_info {
+ color: #990033;
+ margin: 0px 0px 0px 0px;
+ padding: 0.4em;
+ border: 0px;
+ font-size: 12px;
+}
+h1.connexe {
+ font-size: 12px;
+ padding: 0.9em;
+ margin: 0px 0px 0px 0px;
+ color: #990033;
+}
+
+a.rubrique_infolink {
+ text-decoration: none;
+}
+
+ul.rubrique_infoul {
+ display: inline;
+ list-style-type: square;
+}
+ul.rubrique_infoul * {
+ width: 100%;
+}
+li.rubrique_infoul {
+ margin-left: 15px;
+}
+h1 {
+ color: #990033;
+}
+
+div.main {
+ background: white;
+ color: #000000;
+ margin-left: 5px;
+ margin-right: 5px;
+ border: 1px black solid;
+ text-align: left;
+ font-size: 12px;
+}
+div.lsfnbanner {
+ margin-left: 150px;
+ margin-right: 170px;
+ border-top: none;
+ padding-left: 10px;
+ padding-right: 10px;
+ border-bottom: 1px black solid;
+ border-right: 1px black solid;
+ border-left: 1px black solid;
+ text-align: left;
+ font-size: 11px;
+ padding-top: 2px;
+ background-color: #eeeae6;
+}
+div.footer {
+ padding-top: 5px;
+ padding-bottom: 3px;
+ border-top: 1px black solid;
+ border-left: 1px black solid;
+ border-right: 1px black solid;
+ text-align: left;
+ font-size: 9px;
+ background: #dcdff4;
+ width: 600px;
+ margin-top: 40px;
+ margin-left: 20px;
+}
+div.footer p {
+ margin-left: 10px;
+ margin-top: 2px;
+ margin-bottom: 2px;
+}
+
+a.lsfnlink:link,a.lsfnlink:visited,a.lsfnlink:active {
+ text-decoration: none;
+ color: #333333;
+ font-size: 10px;
+}
+a.lsfnlink:hover {
+ text-decoration: underline;
+ color: black;
+}
+div.menubartop {
+ margin-bottom: 10px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ font-size: 13px;
+}
+div.smallmenubar {
+ background: white;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ font-weight:bold;
+ font-size: 10px;
+ text-align: right;
+}
+div.menuevent {
+ float: left;
+ width: 350px;
+ font-size: 11px;
+ text-align: left;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ font-weight: bold;
+ margin: 0px;
+}
+div.menubar {
+ background: #cac2a8;
+ border-top: 1px black solid;
+ border-bottom: 1px black solid;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 3px;
+ padding-bottom: 2px;
+ font-weight:bold;
+ font-size: 13px;
+}
+div.menubar a {
+ text-decoration: none;
+}
+div.menudate {
+ float: left;
+ width: 130px;
+ padding-top: 5px;
+}
+div.menuaccroche {
+ margin-left: 30px;
+ float: left;
+ text-decoration: underline;
+ font-size: 14px;
+}
+div.menusearch {
+ float: right;
+ text-align: right;
+ padding-top: 5px;
+ width: 170px;
+}
+div.menusearch p {
+ margin: 0px 0px 0px 0px;
+}
+.searchinput {
+ border: solid 1px black;
+}
+a#menulinkselect {
+ color: #ed7e00;
+}
+
+div.leftbox {
+ width: 200px;
+ float: left;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-bottom: 5px;
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ background: white;
+ margin-bottom: 10px;
+}
+div.leftbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.leftbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.leftbox ul {
+ list-style-type: square;
+ margin-bottom: 10px;
+ margin-left: 0.3em;
+ padding-left: 0.2em;
+}
+div.leftbox li {
+ margin-left: 10px;
+}
+
+div.rightbox {
+ width: 150px;
+ float: right;
+ padding-top: 10px;
+ padding-left: 5px;
+ padding-right: 15px;
+ padding-bottom: 5px;
+ border-left: 1px black solid;
+ border-bottom: 1px black solid;
+ text-align: left;
+}
+div.newjournaldiv {
+ text-align: justify;
+ margin-left: 10%;
+ font-size: 12px;
+ width: 600px;
+}
+div.newjournaldiv p {
+ margin-bottom: 0px;
+ margin-top: 20px;
+}
+div.journaldiv {
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 1px black solid;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ background-color: #eef;
+}
+div.journaldiv p {
+ margin-top: 10px;
+ margin-bottom: 0px;
+}
+div.journaldiv h1 {
+ color: #990033;
+ font-size: 14px;
+ margin: 0px;
+}
+div.journaldiv h2 {
+ font-size: 10px;
+ margin: 0px;
+}
+div.tipdiv {
+ margin-left: 220px;
+ margin-right: 50px;
+ margin-top: 20px;
+ padding-top: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ text-align: justify;
+ background-color: #eee;
+ border: black solid 1px;
+}
+div.tipdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ color: black;
+ margin-top: 0px;
+ margin-bottom: 20px;
+}
+div.tipdiv h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 12px;
+ margin: 0px;
+}
+
+div.newsdiv {
+ margin-left: 220px;
+ margin-right: 180px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+ text-align: justify;
+}
+div.newsdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.newsdiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.newsdiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.objdiv {
+ margin-left: 220px;
+ margin-right: 20px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+}
+
+h1.newstitle {
+ text-align: left;
+ font-size: 14px;
+ margin: 0px 0px 0px 0px;
+ color: black;
+}
+div.titlediv {
+ border-top: solid #cac2a8 2px;
+ margin-top: 20px;
+ background-color: #eeeae6;
+ padding-left: 10px;
+ font-size: 11px;
+}
+div.bodydiv {
+ border: solid #9e9784 1px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 10px;
+ padding-bottom: 5px;
+ margin-top: 2px;
+ text-align: justify;
+}
+
+div.comments {
+ padding: 10px;
+ border-top: solid 2px #d37537;
+ border-bottom: solid 2px #d37537;
+ margin-top: 20px;
+ margin-bottom: 10px;
+ background-color: #cacaca;
+ font-size: 12px;
+ line-height: 1.3em;
+}
+
+
+p.commentsbody {
+ border-left-style: solid;
+ border-width: 1px;
+ border-color: rgb(0, 0, 0);
+ padding-left: 10px;
+ text-align: justify;
+ margin-right: 20px;
+}
+
+
+div.commentsreply {
+ margin-left: 220px;
+ text-align: center;
+ margin-top: 50px;
+}
+
+ul.commentsul {
+ list-style-type: none;
+ margin-bottom: 10px;
+ margin-left: 1.25em;
+ padding-left: 0em;
+ border-left: 1px solid black;
+}
+ul.commentsli {
+ margin: 10px;
+}
+div.comments li {
+ margin-top: 20px;
+ margin-left: 2px;
+}
+
+div.comments h1 {
+ font-size: 12px;
+ color: black;
+ margin: 0px 20px 3px 0px;
+ background-color: rgb(226, 226, 226);
+ padding-left: 1px;
+ font-weight: none;
+}
+
+div.articlediv {
+ padding-left: 20px;
+ padding-right: 20px;
+ padding-top: 10px;
+ padding-bottom: 20px;
+ margin-right: 10px;
+ margin-left: 220px;
+ border: solid 1px black;
+ margin-top: 10px;
+ text-align: justify;
+ background-color: #E2E2E2;
+}
+img {
+ border: 0px;
+}
+div.sectionimg {
+ float: left;
+ margin-right: 10px;
+ margin-top: 5px;
+}
+p.hautpage {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ margin-left: 10px;
+}
+div.leftcol {
+ width: 202px;
+ width: 202px;
+ float: left;
+ padding: 0px;
+}
+div.logodiv {
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ padding: 0px;
+ line-height: 0px
+}
+div.loginbox {
+ margin-left: 4px;
+ border: solid #a59f8b 1px;
+ margin-top: 2px;
+ padding: 5px;
+ background-color: #fff2e8;
+ font-size: 10px;
+}
+div.loginbox p {
+ margin: 0px;
+ padding: 0px;
+}
+div.loginbox ul {
+ margin-left: 10px;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.loginbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.loginbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.loginbox h3 {
+ margin-top: 0px;
+ margin-bottom: 5px;
+ font-size: 12px;
+}
+div.polldivtitle {
+ margin-bottom: 1px;
+ background-color: #cac2a8;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ font-size: 10px;
+ border-top: solid #a59f8b 1px;
+ border-bottom: solid #a59f8b 1px;
+ text-transform: uppercase;
+}
+div.polldiv {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ background: #fff2e8;
+}
+div.polldiv p {
+margin: 5px; padding: 0px;
+}
+div.polldiv ul {
+ margin-left: 5px;
+ margin-top: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.otherboxtitle {
+ margin-bottom: 2px;
+ background-color: #e3dabc;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ padding-top: 2px;
+ font-size: 11px;
+ border-top: solid #777364 1px;
+ border-bottom: solid #777364 1px;
+ text-transform: uppercase;
+ font-weight: bold;
+}
+div.otherbox {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 10px;
+}
+div.otherbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.otherbox h2 {
+ font-weight: bold;
+ font-size: 11px;
+ margin: 0px;
+}
+div.otherbox p {
+ margin-top: 5px;
+ margin-bottom: 10px;
+}
+div.rightlogo {
+ width: 90px;
+ float: right;
+ margin-right: 0px;
+ padding-top: 0px;
+ padding-left: 0px;
+ padding-bottom: 0px;
+}
+div.centraldiv {
+ margin-left: 220px;
+ margin-right: 10px;
+ margin-bottom: 20px;
+ margin-top: 10px;
+}
+div.centraldiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.centraldiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.centraldiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.centralinfo {
+ position:relative;
+ height:160px;
+}
+div.lefttopbox {
+ position:relative;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-top: 5px;
+ border: 1px #a59f8b solid;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 12px;
+ width: 47%;
+ float: left;
+}
+div.lefttopbox p {
+ margin-top: 5px; margin-bottom: 10px;
+}
+div.lefttopbox h1 {
+ font-size: 13px;
+ font-weight: bold;
+ margin: 0px;
+ text-align: right;
+}
+div.lefttopbox h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.lefttopbox h3 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.righttopbox {
+ position:relative;
+ border: 1px #a59f8b solid;
+ background: white;
+ padding: 5px;
+ text-align: justify;
+ font-size: 12px;
+ width: 47%;
+ float: right;
+}
+div.righttopbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.righttopbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.boardindex {
+ text-align: justify;
+ font-size: 11px;
+ padding: 10px;
+ margin-left: 20px;
+ margin-right: 20px;
+}
+a.boardindex:link,a.boardindex:visited,a.boardindex:active {
+ text-decoration:none;
+ color: red;
+}
+div.boardleftmsg {
+ float: left;
+ margin-top: 3px;
+}
+div.boardrightmsg {
+ margin-left: 130px;
+ margin-top: 3px;
+ padding-left: 5px;
+}
+div.journalbody {
+ margin-left: 40px;
+ margin-top: 40px;
+}
+div.journalbody h1 {
+ font-size: 15px;
+ font-weight: bold;
+}
+div.journalbody p {
+ margin-bottom: 20px;
+}
+.formulaire {
+ border: solid 1px black;
+font-size: 12px;
+background-color: #eef;
+color: #000000;
+}
+.newcomments {
+ color: red;
+ font-weight: bold;
+}
+div.commentsreplythanks {
+ margin-left: 100px;
+ margin-top: 50px;
+ margin-right: 100px;
+ background-color: #eee;
+ border: black solid 1px;
+ padding: 10px;
+}
+div.archivediv {
+ margin-right: 20px;
+}
+.archivedate {
+ color:#f30;
+}
+.archivelink {
+ font-size: 14px;
+ font-weight: bold;
+ text-decoration: underline;
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test4.2.css b/src/3rdparty/libcroco/tests/test-inputs/test4.2.css
new file mode 100644
index 0000000..2dafbef
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test4.2.css
@@ -0,0 +1,24 @@
+@charset "ISO-8859-1" ;
+
+@import url("http://www.yahoo.com/css") print , screen ;
+
+@font-face {
+ font-family: "Robson Celtic";
+ src: url("http://site/fonts/rob-celt")
+}
+
+
+
+@page left:one-two {
+ margin: 10pt;
+ border:none
+}
+
+@media print , screen , projection {
+ H1 { font-family: "Robson Celtic", serif }
+
+ P {
+ background: black ;
+ foreground: white ;
+ }
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test5.1.css b/src/3rdparty/libcroco/tests/test-inputs/test5.1.css
new file mode 100644
index 0000000..26c3627
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test5.1.css
@@ -0,0 +1,14 @@
+.class5 {prop8: val8}
+#id6 {prop9: val9}
+[attr4|=val4] {prop7: val7}
+[attr3~=val3_2] {prop6: val6}
+[attr2=val2] {prop5: val5}
+:first-child {first-child-prop: first-child-value}
+:lang(fr) {lang-prop: lang-value}
+E2[attr2=val2] {prop8: val8}
+E0 {prop0: val0}
+E0+E1{pro1:val1}
+E1 E1-1 {prop2: val2}
+E1 > E1-1 {prop3: val3}
+document E1-1 {prop4: val4}
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule.css b/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule.css
new file mode 100644
index 0000000..7680999
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule.css
@@ -0,0 +1,3 @@
+@namespace url(http://www.w3.org/1999/xhtml); /* set default namespace
+to
+HTML */ \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule2.css b/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule2.css
new file mode 100644
index 0000000..0c4a191
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule2.css
@@ -0,0 +1,3 @@
+@namespace url(http://www.w3.org/1999/xhtml); dummyrule { } /* set
+default
+namespace to HTML */ \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-lots-of-comments.sh b/src/3rdparty/libcroco/tests/test-lots-of-comments.sh
new file mode 100755
index 0000000..f2eae9b
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-lots-of-comments.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT $TEST_INPUTS_DIR/lots-of-comments.css
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/Makefile.am b/src/3rdparty/libcroco/tests/test-output-refs/Makefile.am
new file mode 100644
index 0000000..b113e7f
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/Makefile.am
@@ -0,0 +1,16 @@
+EXTRA_DIST=test0.1.css.out \
+test1.css.out \
+test2.1.css.out \
+test2.2.css.out \
+test2.css.out \
+test3.1.css.out \
+test3.2.css.out \
+test3.css.out \
+test4.1.css.out \
+test4.2.css.out \
+test6.out \
+test-prop-ident.out \
+test-unknown-at-rule.out \
+test-unknown-at-rule2.out \
+test-several-media.out \
+test5.1.css.out
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-functional-notation.out b/src/3rdparty/libcroco/tests/test-output-refs/test-functional-notation.out
new file mode 100644
index 0000000..7fa05fd
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-functional-notation.out
@@ -0,0 +1,7 @@
+foo {
+ bar : attr(width, length, calc(70% -5px))
+}
+
+foo {
+ bar : attr(x, y)
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-lots-of-comments.out b/src/3rdparty/libcroco/tests/test-output-refs/test-lots-of-comments.out
new file mode 100644
index 0000000..59b08ef
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-lots-of-comments.out
@@ -0,0 +1,26 @@
+@charset "utf8" ;
+
+@import url("http://pouet.com")screen, paper, aural ;
+
+@page coin :pseudo-page {
+ page-prop0 : page-val0;
+ page-prop1 : page-val1
+}
+
+
+@media paper, aural {
+ x {
+ foo : fooval;
+ bar : barval
+ }
+}
+
+@font-face {
+ font-prop1 : font1;
+ font-prop2 : font2
+}
+
+x>y[attr="val"].class#tatati z+toto {
+ prop1 : function(a);
+ prop2 : val2
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-parsing-location.out b/src/3rdparty/libcroco/tests/test-output-refs/test-parsing-location.out
new file mode 100644
index 0000000..7be4584
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-parsing-location.out
@@ -0,0 +1,219 @@
+
+
+@charset "utf8";
+
+/********************************************
+ * Parsing location information of the @charset rule
+ ********************************************/
+ /*@charset*/
+ /*line:1 column:1 byte offset:0 */
+ /*utf8*/
+ /*line:1 column:10 byte offset:9 */
+
+@import url("http://pouet.com") screen, paper, aural;
+
+/*****************************************************
+ *Parsing location information for the @import rule
+ ******************************************************/
+
+ /*@import*/
+ /*line:3 column:1 byte offset:19 */
+
+ /*http://pouet.com*/
+ /*line:3 column:9 byte offset:27 */
+
+ /*screen*/
+ /*line:3 column:33 byte offset:51 */
+
+ /*paper*/
+ /*line:3 column:41 byte offset:59 */
+
+ /*aural*/
+ /*line:3 column:48 byte offset:66 */
+
+@import url("http://pouet.com") screen2, paper2, aural2;
+
+/*****************************************************
+ *Parsing location information for the @import rule
+ ******************************************************/
+
+ /*@import*/
+ /*line:4 column:1 byte offset:74 */
+
+ /*http://pouet.com*/
+ /*line:4 column:9 byte offset:82 */
+
+ /*screen2*/
+ /*line:4 column:31 byte offset:104 */
+
+ /*paper2*/
+ /*line:4 column:40 byte offset:113 */
+
+ /*aural2*/
+ /*line:4 column:48 byte offset:121 */
+
+@page coin :pseudo-page
+
+ /*@page*/
+ /*line:6 column:1 byte offset:131 */
+ /*coin*/
+ /*line:6 column:7 byte offset:137 */
+ /*pseudo-page*/
+ /*line:6 column:13 byte offset:143 */
+
+{
+
+
+page-prop0 : page-val0;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*page-prop0*/
+ /*line:7 column:7 byte offset:163 */
+ /*page-val0*/
+ /*line:7 column:19 byte offset:175 */
+
+
+page-prop1 : page-val1;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*page-prop1*/
+ /*line:8 column:7 byte offset:193 */
+ /*page-val1*/
+ /*line:8 column:19 byte offset:205 */
+}
+@media paper, aural
+ /*@media*/
+ /*line:11 column:1 byte offset:220 */
+ /*paper*/
+ /*line:11 column:8 byte offset:227 */
+ /*aural*/
+ /*line:11 column:15 byte offset:234 */
+
+{
+x {
+/************************************************
+ *Parsing location information of the selector
+ ************************************************/
+/*x*/
+/*line:12 column:5 byte offset:246 */
+ /*x*/
+ /*line:12 column:5 byte offset:246 */
+
+
+foo : fooval;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*foo*/
+ /*line:13 column:7 byte offset:256 */
+ /*fooval*/
+ /*line:13 column:12 byte offset:261 */
+
+
+bar : barval;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*bar*/
+ /*line:14 column:7 byte offset:276 */
+ /*barval*/
+ /*line:14 column:12 byte offset:281 */
+ }
+
+}
+@font-face {
+/******************************************************
+ Parsing location information for the @font-face rule
+ ******************************************************/
+
+ /*@font-face*/
+ /*line:18 column:1 byte offset:299 */
+
+
+font-prop1 : font1;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*font-prop1*/
+ /*line:19 column:2 byte offset:313 */
+ /*font1*/
+ /*line:19 column:14 byte offset:325 */
+
+
+font-prop2 : font2;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*font-prop2*/
+ /*line:20 column:2 byte offset:334 */
+ /*font2*/
+ /*line:20 column:14 byte offset:346 */
+}
+x>y[attr="val"].class#tatati z+toto {
+/************************************************
+ *Parsing location information of the selector
+ ************************************************/
+/*x*/
+/*line:22 column:1 byte offset:356 */
+ /*x*/
+ /*line:22 column:1 byte offset:356 */
+/*y[attr="val"].class#tatati*/
+/*line:22 column:5 byte offset:360 */
+ /*y*/
+ /*line:22 column:5 byte offset:360 */
+
+ /*[attr="val"]*/
+ /*line:22 column:6 byte offset:361 */
+
+ /*.class*/
+ /*line:22 column:17 byte offset:372 */
+
+ /*#tatati*/
+ /*line:22 column:22 byte offset:377 */
+/*z*/
+/*line:22 column:30 byte offset:385 */
+ /*z*/
+ /*line:22 column:30 byte offset:385 */
+/*toto*/
+/*line:22 column:34 byte offset:389 */
+ /*toto*/
+ /*line:22 column:34 byte offset:389 */
+
+
+prop1 : function(a);
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*prop1*/
+ /*line:23 column:2 byte offset:396 */
+ /*function(a)*/
+ /*line:23 column:9 byte offset:403 */
+
+
+prop2 : val2;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*prop2*/
+ /*line:24 column:2 byte offset:418 */
+ /*val2*/
+ /*line:24 column:9 byte offset:425 */
+ }
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-prop-ident.out b/src/3rdparty/libcroco/tests/test-output-refs/test-prop-ident.out
new file mode 100644
index 0000000..149e8f5
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-prop-ident.out
@@ -0,0 +1,3 @@
+:-foo-pseudo {
+ -foo-bar-prop : -foobar-value
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-sel-child-class.out b/src/3rdparty/libcroco/tests/test-output-refs/test-sel-child-class.out
new file mode 100644
index 0000000..aadd508
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-sel-child-class.out
@@ -0,0 +1,4 @@
+Properties of xml element p are:
+ color : aqua
+=====================
+
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-several-media.out b/src/3rdparty/libcroco/tests/test-output-refs/test-several-media.out
new file mode 100644
index 0000000..4b3cbdd
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-several-media.out
@@ -0,0 +1,17 @@
+@media screen {
+ a:link {
+ text-decoration : none
+ }
+ div {
+ width : 50%
+ }
+}
+
+@media print {
+ a {
+ color : red
+ }
+ div {
+ width : 57%
+ }
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule.out b/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule.out
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule.out
@@ -0,0 +1 @@
+
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule2.out b/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule2.out
new file mode 100644
index 0000000..a356a7d
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule2.out
@@ -0,0 +1,2 @@
+dummyrule {
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test0.1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test0.1.css.out
new file mode 100644
index 0000000..16475bd
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test0.1.css.out
@@ -0,0 +1 @@
+9811110012132123103232109971141031051103258324811212032481121203250481121203248112120591032321041011051031041163258324948483759103232989799107103114111117110100325832357070701012510106532123103232991111081111143258323548485151545459103232116101120116451001019911111497116105111110325832117110100101114108105110101101251010655810810511010732123103232991111081111143258323548485151545459103232116101120116451001019911111497116105111110325832117110100101114108105110101101251010655811810511510511610110032123103232991111081111143258323548485151545459103232116101120116451001019911111497116105111110325832117110100101114108105110101101251010655897991161051181013212310323299111108111114325832355757575757571012510106558104111118101114321231032329911110811111432583235575757575757101251010104494432104504432104513212310323210997114103105110325832481121205910323211297100100105110103325832481121201012510103598971101101011143212310323210211111011645102971091051081213258321129710897116105110111443210310111111410310597443211810111410097110974432971141059710844321159711011545115101114105102591032329911110811111432583235515151591032321161111125848591032321021111101164511510512210132583211011111410997108591032321021111101164511910110510310411632583211011111410997108591012510103598971101101011143297443235989711011010111432975810810511010744323598971101101011143297581181051151051161011004432359897110110101114329758979911610511810144323598971101101011143297581041111181011143212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232102111110116451151051221013258321201204510897114103101591032329911110811111432583235515151591032321161011201164510010199111114971161051111103258321101111101011012510104610010111599114105112116105111110321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323299111108111114325832355151515910323210211111011645115105122101325832115109971081085910323211610112011645116114971101151021111141093258321101111101011012510103599111110116101110116321231032321121111151051161051111103258329798115111108117116101591032329897991071031141111171101003258323570707059103232116111112583250483759321032321081011021165832504837591032329811111410010111432583249112120321151111081051003235707070101251010359911111011697105110101114321231032329897991071031141111171101003258323570707059103232981111141001011143258324911212032115111108105100323570707010125101035108105110107115321231032321129710010010511010332583249531121205910323298111114100101114325832491121203211511110810510032357070705910323211910510011610432583250484811212010125101046981081111033212310323211297100100105110103325832504811212059103232989799107103114111117110100325832357070701012510104698108111103981111001213212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232991111081111143258323551515159103232102111110116451151051221013258321151099710810859103232102111110116451191011051031041163258321101111141099710859103232989799107103114111117110100325832357070705910323210810511010145104101105103104116325832495348371012510104698108111103981111001213297443246981081111039811110012132975810810511010744324698108111103981111001213297581181051151051161011004432469810811110398111100121329758979911610511810144324698108111103981111001213297581041111181011143212310323210211111011645119101105103104116325832110111114109971085910323211610112011645100101991111149711610511111032583211711010010111410810511010110125101046116105116108101321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323210211111011645115105122101325832109101100105117109591032329911110811111432583235545454101251010461009711610132123103232102111110116451029710910510812132583211810111410097110974432971141059710844321151011141051025910323210211111011645115105122101325832108971141031015910323299111108111114325832355151515910323298111114100101114459811111611611110932583249112120321151111081051003235575757591032321099711410310511045981111161161111093258324948112120591032321021111101164511910110510310411632583298111108100101251010461121111151161011003212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232102111110116451151051221013258321204511510997108108591032329911110811111432583235484848484848591032321099711410310511045981111161161111093258325053112120101251010469997108101110100971143212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232991111081111143258323551515159103232102111110116451151051221013258321204511510997108108591032321021111101164511910110510310411632583211011111410997108591032329897991071031141111171101003258323570707059103232108105110101451041011051031041163258324952483759103232112971001001051101033258325011212059103232116101120116459710810510311032583210810110211610125101046999710810111010097114104101971003212310323210211111011645102971091051081213258321129710897116105110111443210310111111410310597443211610510910111532110101119321141111099711044321151011141051025910323299111108111114325832355454545448485910323210211111011645115105122101325832115109971081085910323210211111011645119101105103104116325832110111114109971085910323211297100100105110103325832501121205910323210810111611610111445115112979910511010332583248465110110959103232989799107103114111117110100325832357070705910323211610112011645116114971101151021111141093258321171121121011149997115101591032321161011201164597108105103110325832108101102116101251010461151051001013212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232991111081111143258323551515159103232102111110116451151051221013258321204511510997108108591032321021111101164511910110510310411632583211011111410997108591032329897991071031141111171101003258323570707059103232108105110101451041011051031041163258324952483759103232112971001001051101033258325011212010125101035109101110117989711432123103232102111110116451029710910510812132583211810111410097110974432971141059710844321159711011545115101114105102591032329911110811111432583235515151591032321021111101164511510512210132583211510997108108591032321021111101164511910110510310411632583211011111410997108591032321121111151051161051111105897981151111081171161015910323211611111258504837591032321129710010010511010358325011212059103232108101116116101114451151129799105110103325832484649101109591032329897991071031141111171101003258323570707059103232116101120116451161149711011510211111410932583211711211210111499971151011012510104611512111010010599971161013212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232102111110116451151051221013258321201204511510997108108591032321081051101014510410110510310411632583249524837591032321129710010010511010332583250112120591032321099711410310511045116111112325832495311212059103232989799107103114111117110100325832357070701012510104611211111910111410110032123103232102111110116451029710910510812132583211810111410097110974432971141059710844321159711011545115101114105102591032329911110811111432583235545454591032321021111101164511510512210132583212045115109971081085910323210810511010145104101105103104116325832495248375910323211610112011645116114971101151021111141093258321171121121011149997115101591032321129710010010511010332583250112120591032321099711410310511045116111112325832534811212059103232108101116116101114451151129799105110103325832484650101109591032329897991071031141111171101003258323570707010125101046991111091091011101161154598111100121321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323299111108111114325832355454545910323210211111011645115105122101325832115109971081085910323210211111011645119101105103104116325832110111114109971085910323298979910710311411111711010032583235707070591032321081051101014510410110510310411632583249524837591032321129710010010511010345981111161161111093258324948112120591032321129710010010511010345116111112325832494811212059103232981111141001011144598111116116111109325832491121203210011111611610110032355757571012510104699111109109101110116115451121111151163212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232991111081111143258323554545459103232102111110116451151051221013258321204511510997108108591032321021111101164511910110510310411632583211011111410997108591032329897991071031141111171101003258323570707010125101046116114979910798979910745117114108321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323299111108111114325832355454545910323210211111011645115105122101325832115109971081085910323210211111011645119101105103104116325832110111114109971085910323298979910710311411111711010032583235707070591032321081051101014510410110510310411632583249524837591032321129710010010511010332583253112120591032329811111410010111432583249112120321001111161161011003235575757101251010461161149799107989799107459811110012132123103232102111110116451029710910510812132583211810111410097110974432971141059710844321159711011545115101114105102591032329911110811111432583235545454591032321021111101164511510512210132583211510997108108591032321021111101164511910110510310411632583211011111410997108591032329897991071031141111171101003258323570707059103232108105110101451041011051031041163258324952483759103232112971001001051101034598111116116111109325832494811212059103232112971001001051101034511611111232583249481121205910323298111114100101114459811111611611110932583249112120321001111161161011003235575757101251010461161149799107989799107451121111151163212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232991111081111143258323554545459103232102111110116451151051221013258321204511510997108108591032321021111101164511910110510310411632583211011111410997108591032329897991071031141111171101003258323570707010125101046991111091091011101161154510410197100321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323210211111011645115105122101325832115109971081085910323299111108111114325832355454545910323298111114100101114459811111611611110932583249112120321151111081051003235575757591032321099711410310511045116111112325832504811212059103232102111110116451191011051031041163258329811110810059103232989799107103114111117110100325832357070701012510103598971101101011144599111109109101110116115112111112321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323299111108111114325832357070705910323210211111011645115105122101325832108971141031015910323210211111011645119101105103104116325832981111081005910323298111114100101114451081011021163258324911212032115111108105100323570707059103232981111141001011144511410510310411632583249112120321151111081051003235707070591032329811111410010111445116111112325832491121203211511110810510032357070705910323298979910710311411111711010032583235484851515454591032321129710010010511010345108101102116325832495311212059103232112971001001051101034511410510310411632583249531121205910323211297100100105110103451161111123258325311212059103232112971001001051101034598111116116111109325832531121201012510 \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test1.css.out
new file mode 100644
index 0000000..b03c8a4
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test1.css.out
@@ -0,0 +1,316 @@
+body {
+
+ background-color: #E5E5E5;
+
+ scrollbar-face-color: #CCCCCC;
+
+ scrollbar-highlight-color: #FFFFFF;
+
+ scrollbar-shadow-color: #CCCCCC;
+
+ scrollbar-3dlight-color: #D1D7DC;
+
+ scrollbar-arrow-color: #000000;
+
+ scrollbar-track-color: #FFFFFF;
+
+ scrollbar-darkshadow-color: #000000;
+
+}
+
+
+
+font, th, td, p {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+}
+
+
+
+h1, h2 { font-size: 11px; color: #000000; font-weight: bold; }
+
+
+
+a:link, a:active, a:visited { color: #000000; }
+
+
+
+a:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+hr { height: 0px; border: solid #CCCCCC 0px; border-top-width: 1px; }
+
+
+
+small { font-size: 10px; }
+
+
+
+input, textarea, select {
+
+ font: normal 11px Verdana, Arial, Helvetica, sans-serif;
+
+ color: #000000;
+
+ border-color: #000000;
+
+}
+
+
+
+input { text-indent: 2px; }
+
+
+
+
+input.post, textarea.post, select {
+
+ background-color: #FFFFFF;
+
+}
+
+
+
+
+th {
+
+ font-size: 11px; color: #CCCCCC; font-weight: bold;
+
+ background-color: #000000; height: 25px;
+
+ background-image: url(/~wiceyto/test/templates/blacknwhite/images/cellpic3.gif);
+
+}
+
+
+
+
+.fontspec, .tablefont {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+}
+
+
+
+.navbartext, .navbarfont {
+
+ font-size: 11px; color: #000000; font-weight: bold;
+
+}
+
+
+
+.navbartext a, .navbarfont a {
+
+ color: #000000; font-weight: bold; text-decoration: none;
+
+}
+
+
+
+.navbartext a:hover, .navbarfont a:hover {
+
+ color: #CC0000; text-decoration: none;
+
+}
+
+
+
+.tablespec, .guestbook { background-color: #FFFFFF; border: 2px #000000 solid; }
+
+.tablespec th, .tablespec td { color: #000000; background-color: #CCCCCC; }
+
+.tablespec th { background-image: none; }
+
+
+
+.messageblock {
+
+ border: dashed 1px;
+
+ margin-right: 4em; margin-left: 4em;
+
+ padding: 3em;
+
+}
+
+
+
+/* $MessageOpenCode - the body of text of the posts */
+
+.messagebody { font-size: 12px; line-height: 18px; }
+
+.messagebody a { color: #000000; text-decoration: underline; }
+
+.messagebody a:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+
+.newcode { font-size: 11px; color: #CC0000; font-weight: bold; }
+
+.admincode { font-size: 11px; color: #990000; font-style: bold; }
+
+
+
+
+.bodyline { background-color: #FFFFFF; border: 1px #000000 solid; }
+
+
+
+
+.quote, .code {
+
+ background-color: #FAFAFA; border: #D1D7DC; border-style: solid;
+
+ border-top-width: 1px; border-right-width: 1px;
+
+ border-bottom-width: 1px; border-left-width: 1px;
+
+}
+
+
+
+.quote {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+ color: #444444; line-height: 125%;
+
+}
+
+
+
+.code {
+
+ font-family: Courier, 'Courier New', sans-serif;
+
+ font-size: 11px;
+
+ color: #CC0000;
+
+}
+
+
+
+
+input.button {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+ color: #000000;
+
+ background-color: #FFFFFF;
+
+}
+
+
+
+/* Format button rollover help line. Actually it's a text box
+
+ set to the same color as the background so no one will know. */
+
+.helpline { background-color: #CCCCCC; border-style: none; }
+
+
+
+/* additional table cell colors and backgrounds */
+
+td.row2 { background-color: #CCCCCC; }
+
+td.row1 { background-color: #CCCCCC; }
+
+td.row3 { background-color: #D1D7DC; }
+
+
+
+/* additional general text */
+
+.gen { font-size: 12px; }
+
+.genmed { font-size: 11px; }
+
+.gensmall { font-size: 10px; }
+
+.gen, .genmed, .gensmall { color: #000000; }
+
+a.gen, a.genmed, a.gensmall { color: #000000; text-decoration: none; }
+
+a.gen:hover, a.genmed:hover, a.gensmall:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+/* import fancy styles. For IE only. NS4.x doesn't use the @import function */
+
+@import url("/your.site/webbbs/themes/formIE.css");
+
+
+
+/* END of blacknwhite.css */
+
+
+
+
+
+
+
+/* Appendix.2-2: Example fancy styles CSS file
+
+Paste these into a text file and save as formIE.css */
+
+
+
+/* Fancy form styles for IE */
+
+
+
+input, textarea, select {
+
+border-top-width : 1px;
+
+border-right-width : 1px;
+
+border-bottom-width : 1px;
+
+border-left-width : 1px;
+
+}
+
+
+
+input { text-indent : 2px; }
+
+
+
+input.button {
+
+border-top-width : 1px;
+
+border-right-width : 1px;
+
+border-bottom-width : 1px;
+
+border-left-width : 1px;
+
+}
+
+
+
+.postbody { line-height: 18px}
+
+.magic {
+ margin-left: -20px;
+}
+
+/* END of formIE.css */
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test2.1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test2.1.css.out
new file mode 100644
index 0000000..4874e68
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test2.1.css.out
@@ -0,0 +1,173 @@
+***************
+start_document
+***************
+
+***************
+start_selector
+s1[foo]
+***************
+
+***************
+property
+prop1: 'String'
+***************
+
+***************
+end_selector
+s1[foo]
+***************
+
+***************
+start_selector
+s2[foo]
+***************
+
+***************
+start_selector
+s3[foo="warning"]
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+s3[foo="warning"]
+***************
+
+***************
+start_selector
+s4[foo~="warning"]
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+s4[foo~="warning"]
+***************
+
+***************
+start_selector
+s5.warning
+***************
+
+***************
+property
+prop1: value
+***************
+
+***************
+end_selector
+s5.warning
+***************
+
+***************
+start_selector
+E#myid
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+E#myid
+***************
+
+***************
+start_selector
+S6:first-child
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+property
+prop2: value2
+***************
+
+***************
+end_selector
+S6:first-child
+***************
+
+***************
+start_selector
+S7:lang(c)
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+S7:lang(c)
+***************
+
+***************
+start_selector
+S8+s2
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+S8+s2
+***************
+
+***************
+start_selector
+.quotedstrings
+***************
+
+***************
+property
+-test-string1: "foo'bar"
+***************
+
+***************
+property
+-test-string2: "foo'bar"
+***************
+
+***************
+property
+-test-string3: 'foo"bar'
+***************
+
+***************
+property
+-test-string4: 'foo"bar'
+***************
+
+***************
+property
+-test-string5: 'foo\\bar'
+***************
+
+***************
+end_selector
+.quotedstrings
+***************
+
+***************
+end_document
+***************
+
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test2.2.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test2.2.css.out
new file mode 100644
index 0000000..f0d631a
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test2.2.css.out
@@ -0,0 +1,3328 @@
+***************
+start_document
+***************
+
+***************
+start_selector
+p.commentsbody
+***************
+
+***************
+property
+border-left-style: solid
+***************
+
+***************
+property
+border-width: 1px
+***************
+
+***************
+property
+border-color: rgb(0, 0, 0)
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+margin-right: 20px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+end_selector
+p.commentsbody
+***************
+
+***************
+start_selector
+*
+***************
+
+***************
+property
+font-family: Verdana, Arial, Helvetica, sans-serif, monospace
+***************
+
+***************
+end_selector
+*
+***************
+
+***************
+start_selector
+body
+***************
+
+***************
+property
+background: #606060
+***************
+
+***************
+property
+color: #000000
+***************
+
+***************
+end_selector
+body
+***************
+
+***************
+start_selector
+a:link
+***************
+
+***************
+property
+color: #0000FF
+***************
+
+***************
+property
+background: transparent
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+end_selector
+a:link
+***************
+
+***************
+start_selector
+a:visited
+***************
+
+***************
+property
+color: #990099
+***************
+
+***************
+property
+background: transparent
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+end_selector
+a:visited
+***************
+
+***************
+start_selector
+a:active
+***************
+
+***************
+property
+color: #000000
+***************
+
+***************
+property
+background: #ADD8E6
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+end_selector
+a:active
+***************
+
+***************
+start_selector
+h1.rubrique_info
+***************
+
+***************
+property
+color: #990033
+***************
+
+***************
+property
+margin: 0px 0px 0px 0px
+***************
+
+***************
+property
+padding: 0em
+***************
+
+***************
+property
+border: 0px
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+end_selector
+h1.rubrique_info
+***************
+
+***************
+start_selector
+h1.connexe
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+padding: 0em
+***************
+
+***************
+property
+margin: 0px 0px 0px 0px
+***************
+
+***************
+property
+color: #990033
+***************
+
+***************
+end_selector
+h1.connexe
+***************
+
+***************
+start_selector
+a.rubrique_infolink
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+end_selector
+a.rubrique_infolink
+***************
+
+***************
+start_selector
+ul.rubrique_infoul
+***************
+
+***************
+property
+display: inline
+***************
+
+***************
+property
+list-style-type: square
+***************
+
+***************
+end_selector
+ul.rubrique_infoul
+***************
+
+***************
+start_selector
+ul.rubrique_infoul *
+***************
+
+***************
+property
+width: 100%
+***************
+
+***************
+end_selector
+ul.rubrique_infoul *
+***************
+
+***************
+start_selector
+li.rubrique_infoul
+***************
+
+***************
+property
+margin-left: 15px
+***************
+
+***************
+end_selector
+li.rubrique_infoul
+***************
+
+***************
+start_selector
+h1
+***************
+
+***************
+property
+color: #990033
+***************
+
+***************
+end_selector
+h1
+***************
+
+***************
+start_selector
+div.main
+***************
+
+***************
+property
+background: white
+***************
+
+***************
+property
+color: #000000
+***************
+
+***************
+property
+margin-left: 5px
+***************
+
+***************
+property
+margin-right: 5px
+***************
+
+***************
+property
+border: 1px black solid
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+end_selector
+div.main
+***************
+
+***************
+start_selector
+div.lsfnbanner
+***************
+
+***************
+property
+margin-left: 150px
+***************
+
+***************
+property
+margin-right: 170px
+***************
+
+***************
+property
+border-top: none
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+border-bottom: 1px black solid
+***************
+
+***************
+property
+border-right: 1px black solid
+***************
+
+***************
+property
+border-left: 1px black solid
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+property
+padding-top: 2px
+***************
+
+***************
+property
+background-color: #eeeae6
+***************
+
+***************
+end_selector
+div.lsfnbanner
+***************
+
+***************
+start_selector
+div.footer
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+property
+padding-bottom: 3px
+***************
+
+***************
+property
+border-top: 1px black solid
+***************
+
+***************
+property
+border-left: 1px black solid
+***************
+
+***************
+property
+border-right: 1px black solid
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+property
+font-size: 9px
+***************
+
+***************
+property
+background: #dcdff4
+***************
+
+***************
+property
+width: 600px
+***************
+
+***************
+property
+margin-top: 40px
+***************
+
+***************
+property
+margin-left: 20px
+***************
+
+***************
+end_selector
+div.footer
+***************
+
+***************
+start_selector
+div.footer p
+***************
+
+***************
+property
+margin-left: 10px
+***************
+
+***************
+property
+margin-top: 2px
+***************
+
+***************
+property
+margin-bottom: 2px
+***************
+
+***************
+end_selector
+div.footer p
+***************
+
+***************
+start_selector
+a.lsfnlink:link, a.lsfnlink:visited, a.lsfnlink:active
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+property
+color: #333333
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+end_selector
+a.lsfnlink:link, a.lsfnlink:visited, a.lsfnlink:active
+***************
+
+***************
+start_selector
+a.lsfnlink:hover
+***************
+
+***************
+property
+text-decoration: underline
+***************
+
+***************
+property
+color: black
+***************
+
+***************
+end_selector
+a.lsfnlink:hover
+***************
+
+***************
+start_selector
+div.menubartop
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-top: 0px
+***************
+
+***************
+property
+font-size: 13px
+***************
+
+***************
+end_selector
+div.menubartop
+***************
+
+***************
+start_selector
+div.smallmenubar
+***************
+
+***************
+property
+background: white
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-top: 0px
+***************
+
+***************
+property
+padding-bottom: 0px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+text-align: right
+***************
+
+***************
+end_selector
+div.smallmenubar
+***************
+
+***************
+start_selector
+div.menuevent
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+width: 350px
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+property
+padding-top: 0px
+***************
+
+***************
+property
+padding-bottom: 0px
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.menuevent
+***************
+
+***************
+start_selector
+div.menubar
+***************
+
+***************
+property
+background: #cac2a8
+***************
+
+***************
+property
+border-top: 1px black solid
+***************
+
+***************
+property
+border-bottom: 1px black solid
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-top: 3px
+***************
+
+***************
+property
+padding-bottom: 2px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 13px
+***************
+
+***************
+end_selector
+div.menubar
+***************
+
+***************
+start_selector
+div.menubar a
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+end_selector
+div.menubar a
+***************
+
+***************
+start_selector
+div.menudate
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+width: 130px
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+end_selector
+div.menudate
+***************
+
+***************
+start_selector
+div.menuaccroche
+***************
+
+***************
+property
+margin-left: 30px
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+text-decoration: underline
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+end_selector
+div.menuaccroche
+***************
+
+***************
+start_selector
+div.menusearch
+***************
+
+***************
+property
+float: right
+***************
+
+***************
+property
+text-align: right
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+property
+width: 170px
+***************
+
+***************
+end_selector
+div.menusearch
+***************
+
+***************
+start_selector
+div.menusearch p
+***************
+
+***************
+property
+margin: 0px 0px 0px 0px
+***************
+
+***************
+end_selector
+div.menusearch p
+***************
+
+***************
+start_selector
+.searchinput
+***************
+
+***************
+property
+border: solid 1px black
+***************
+
+***************
+end_selector
+.searchinput
+***************
+
+***************
+start_selector
+a#menulinkselect
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+end_selector
+a#menulinkselect
+***************
+
+***************
+start_selector
+div.leftbox
+***************
+
+***************
+property
+width: 200px
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+property
+padding-right: 5px
+***************
+
+***************
+property
+padding-bottom: 5px
+***************
+
+***************
+property
+border-right: 1px black solid
+***************
+
+***************
+property
+border-bottom: 1px black solid
+***************
+
+***************
+property
+background: white
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+end_selector
+div.leftbox
+***************
+
+***************
+start_selector
+div.leftbox h1
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.leftbox h1
+***************
+
+***************
+start_selector
+div.leftbox h2
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.leftbox h2
+***************
+
+***************
+start_selector
+div.leftbox ul
+***************
+
+***************
+property
+list-style-type: square
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+property
+margin-left: 0em
+***************
+
+***************
+property
+padding-left: 0em
+***************
+
+***************
+end_selector
+div.leftbox ul
+***************
+
+***************
+start_selector
+div.leftbox li
+***************
+
+***************
+property
+margin-left: 10px
+***************
+
+***************
+end_selector
+div.leftbox li
+***************
+
+***************
+start_selector
+div.rightbox
+***************
+
+***************
+property
+width: 150px
+***************
+
+***************
+property
+float: right
+***************
+
+***************
+property
+padding-top: 10px
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+property
+padding-right: 15px
+***************
+
+***************
+property
+padding-bottom: 5px
+***************
+
+***************
+property
+border-left: 1px black solid
+***************
+
+***************
+property
+border-bottom: 1px black solid
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+end_selector
+div.rightbox
+***************
+
+***************
+start_selector
+div.newjournaldiv
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+margin-left: 10%
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+width: 600px
+***************
+
+***************
+end_selector
+div.newjournaldiv
+***************
+
+***************
+start_selector
+div.newjournaldiv p
+***************
+
+***************
+property
+margin-bottom: 0px
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+end_selector
+div.newjournaldiv p
+***************
+
+***************
+start_selector
+div.journaldiv
+***************
+
+***************
+property
+margin-left: 0px
+***************
+
+***************
+property
+margin-right: 0px
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+property
+border: 1px black solid
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+property
+padding-bottom: 5px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+background-color: #eef
+***************
+
+***************
+end_selector
+div.journaldiv
+***************
+
+***************
+start_selector
+div.journaldiv p
+***************
+
+***************
+property
+margin-top: 10px
+***************
+
+***************
+property
+margin-bottom: 0px
+***************
+
+***************
+end_selector
+div.journaldiv p
+***************
+
+***************
+start_selector
+div.journaldiv h1
+***************
+
+***************
+property
+color: #990033
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.journaldiv h1
+***************
+
+***************
+start_selector
+div.journaldiv h2
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.journaldiv h2
+***************
+
+***************
+start_selector
+div.tipdiv
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+margin-right: 50px
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+background-color: #eee
+***************
+
+***************
+property
+border: black solid 1px
+***************
+
+***************
+end_selector
+div.tipdiv
+***************
+
+***************
+start_selector
+div.tipdiv h1
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+color: black
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+end_selector
+div.tipdiv h1
+***************
+
+***************
+start_selector
+div.tipdiv h2
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.tipdiv h2
+***************
+
+***************
+start_selector
+div.newsdiv
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+margin-right: 180px
+***************
+
+***************
+property
+margin-top: 10px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+end_selector
+div.newsdiv
+***************
+
+***************
+start_selector
+div.newsdiv h1
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.newsdiv h1
+***************
+
+***************
+start_selector
+div.newsdiv h2
+***************
+
+***************
+property
+font-weight: normal
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.newsdiv h2
+***************
+
+***************
+start_selector
+div.newsdiv h3
+***************
+
+***************
+property
+font-weight: normal
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+end_selector
+div.newsdiv h3
+***************
+
+***************
+start_selector
+div.objdiv
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+margin-right: 20px
+***************
+
+***************
+property
+margin-top: 10px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+end_selector
+div.objdiv
+***************
+
+***************
+start_selector
+h1.newstitle
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+margin: 0px 0px 0px 0px
+***************
+
+***************
+property
+color: black
+***************
+
+***************
+end_selector
+h1.newstitle
+***************
+
+***************
+start_selector
+div.titlediv
+***************
+
+***************
+property
+border-top: solid #cac2a8 2px
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+background-color: #eeeae6
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+end_selector
+div.titlediv
+***************
+
+***************
+start_selector
+div.bodydiv
+***************
+
+***************
+property
+border: solid #9e9784 1px
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-top: 10px
+***************
+
+***************
+property
+padding-bottom: 5px
+***************
+
+***************
+property
+margin-top: 2px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+end_selector
+div.bodydiv
+***************
+
+***************
+start_selector
+div.comments
+***************
+
+***************
+property
+padding: 10px
+***************
+
+***************
+property
+border-top: solid 2px #d37537
+***************
+
+***************
+property
+border-bottom: solid 2px #d37537
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+property
+background-color: #cacaca
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+line-height: 1.3em
+***************
+
+***************
+end_selector
+div.comments
+***************
+
+***************
+start_selector
+p.commentsbody
+***************
+
+***************
+property
+border-left-style: solid
+***************
+
+***************
+property
+border-width: 1px
+***************
+
+***************
+property
+border-color: rgb(0, 0, 0)
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+margin-right: 20px
+***************
+
+***************
+end_selector
+p.commentsbody
+***************
+
+***************
+start_selector
+div.commentsreply
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+text-align: center
+***************
+
+***************
+property
+margin-top: 50px
+***************
+
+***************
+end_selector
+div.commentsreply
+***************
+
+***************
+start_selector
+ul.commentsul
+***************
+
+***************
+property
+list-style-type: none
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+property
+margin-left: 1.25em
+***************
+
+***************
+property
+padding-left: 0em
+***************
+
+***************
+property
+border-left: 1px solid black
+***************
+
+***************
+end_selector
+ul.commentsul
+***************
+
+***************
+start_selector
+ul.commentsli
+***************
+
+***************
+property
+margin: 10px
+***************
+
+***************
+end_selector
+ul.commentsli
+***************
+
+***************
+start_selector
+div.comments li
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+margin-left: 2px
+***************
+
+***************
+end_selector
+div.comments li
+***************
+
+***************
+start_selector
+div.comments h1
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+color: black
+***************
+
+***************
+property
+margin: 0px 20px 3px 0px
+***************
+
+***************
+property
+background-color: rgb(226, 226, 226)
+***************
+
+***************
+property
+padding-left: 1px
+***************
+
+***************
+property
+font-weight: none
+***************
+
+***************
+end_selector
+div.comments h1
+***************
+
+***************
+start_selector
+div.articlediv
+***************
+
+***************
+property
+padding-left: 20px
+***************
+
+***************
+property
+padding-right: 20px
+***************
+
+***************
+property
+padding-top: 10px
+***************
+
+***************
+property
+padding-bottom: 20px
+***************
+
+***************
+property
+margin-right: 10px
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+border: solid 1px black
+***************
+
+***************
+property
+margin-top: 10px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+background-color: #E2E2E2
+***************
+
+***************
+end_selector
+div.articlediv
+***************
+
+***************
+start_selector
+img
+***************
+
+***************
+property
+border: 0px
+***************
+
+***************
+end_selector
+img
+***************
+
+***************
+start_selector
+div.sectionimg
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+margin-right: 10px
+***************
+
+***************
+property
+margin-top: 5px
+***************
+
+***************
+end_selector
+div.sectionimg
+***************
+
+***************
+start_selector
+p.hautpage
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+property
+margin-left: 10px
+***************
+
+***************
+end_selector
+p.hautpage
+***************
+
+***************
+start_selector
+div.leftcol
+***************
+
+***************
+property
+width: 202px
+***************
+
+***************
+property
+width: 202px
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+end_selector
+div.leftcol
+***************
+
+***************
+start_selector
+div.logodiv
+***************
+
+***************
+property
+border-right: 1px black solid
+***************
+
+***************
+property
+border-bottom: 1px black solid
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+property
+line-height: 0px
+***************
+
+***************
+end_selector
+div.logodiv
+***************
+
+***************
+start_selector
+div.loginbox
+***************
+
+***************
+property
+margin-left: 4px
+***************
+
+***************
+property
+border: solid #a59f8b 1px
+***************
+
+***************
+property
+margin-top: 2px
+***************
+
+***************
+property
+padding: 5px
+***************
+
+***************
+property
+background-color: #fff2e8
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+end_selector
+div.loginbox
+***************
+
+***************
+start_selector
+div.loginbox p
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+end_selector
+div.loginbox p
+***************
+
+***************
+start_selector
+div.loginbox ul
+***************
+
+***************
+property
+margin-left: 10px
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+margin-bottom: 0px
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+property
+list-style-type: none
+***************
+
+***************
+end_selector
+div.loginbox ul
+***************
+
+***************
+start_selector
+div.loginbox h1
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.loginbox h1
+***************
+
+***************
+start_selector
+div.loginbox h2
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.loginbox h2
+***************
+
+***************
+start_selector
+div.loginbox h3
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+margin-bottom: 5px
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+end_selector
+div.loginbox h3
+***************
+
+***************
+start_selector
+div.polldivtitle
+***************
+
+***************
+property
+margin-bottom: 1px
+***************
+
+***************
+property
+background-color: #cac2a8
+***************
+
+***************
+property
+margin-left: 4px
+***************
+
+***************
+property
+margin-top: 15px
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+border-top: solid #a59f8b 1px
+***************
+
+***************
+property
+border-bottom: solid #a59f8b 1px
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+end_selector
+div.polldivtitle
+***************
+
+***************
+start_selector
+div.polldiv
+***************
+
+***************
+property
+margin-left: 4px
+***************
+
+***************
+property
+border: 1px #a59f8b solid
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+padding: 5px
+***************
+
+***************
+property
+background: #fff2e8
+***************
+
+***************
+end_selector
+div.polldiv
+***************
+
+***************
+start_selector
+div.polldiv p
+***************
+
+***************
+property
+margin: 5px
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+end_selector
+div.polldiv p
+***************
+
+***************
+start_selector
+div.polldiv ul
+***************
+
+***************
+property
+margin-left: 5px
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+property
+list-style-type: none
+***************
+
+***************
+end_selector
+div.polldiv ul
+***************
+
+***************
+start_selector
+div.otherboxtitle
+***************
+
+***************
+property
+margin-bottom: 2px
+***************
+
+***************
+property
+background-color: #e3dabc
+***************
+
+***************
+property
+margin-left: 4px
+***************
+
+***************
+property
+margin-top: 15px
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+property
+padding-top: 2px
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+property
+border-top: solid #777364 1px
+***************
+
+***************
+property
+border-bottom: solid #777364 1px
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+end_selector
+div.otherboxtitle
+***************
+
+***************
+start_selector
+div.otherbox
+***************
+
+***************
+property
+margin-left: 4px
+***************
+
+***************
+property
+border: 1px #a59f8b solid
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+padding: 5px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+background: #fff2e8
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+end_selector
+div.otherbox
+***************
+
+***************
+start_selector
+div.otherbox h1
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.otherbox h1
+***************
+
+***************
+start_selector
+div.otherbox h2
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.otherbox h2
+***************
+
+***************
+start_selector
+div.otherbox p
+***************
+
+***************
+property
+margin-top: 5px
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+end_selector
+div.otherbox p
+***************
+
+***************
+start_selector
+div.rightlogo
+***************
+
+***************
+property
+width: 90px
+***************
+
+***************
+property
+float: right
+***************
+
+***************
+property
+margin-right: 0px
+***************
+
+***************
+property
+padding-top: 0px
+***************
+
+***************
+property
+padding-left: 0px
+***************
+
+***************
+property
+padding-bottom: 0px
+***************
+
+***************
+end_selector
+div.rightlogo
+***************
+
+***************
+start_selector
+div.centraldiv
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+margin-right: 10px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+property
+margin-top: 10px
+***************
+
+***************
+end_selector
+div.centraldiv
+***************
+
+***************
+start_selector
+div.centraldiv h1
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.centraldiv h1
+***************
+
+***************
+start_selector
+div.centraldiv h2
+***************
+
+***************
+property
+font-weight: normal
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.centraldiv h2
+***************
+
+***************
+start_selector
+div.centraldiv h3
+***************
+
+***************
+property
+font-weight: normal
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+end_selector
+div.centraldiv h3
+***************
+
+***************
+start_selector
+div.centralinfo
+***************
+
+***************
+property
+position: relative
+***************
+
+***************
+property
+height: 160px
+***************
+
+***************
+end_selector
+div.centralinfo
+***************
+
+***************
+start_selector
+div.lefttopbox
+***************
+
+***************
+property
+position: relative
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+property
+padding-right: 5px
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+property
+border: 1px #a59f8b solid
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+background: #fff2e8
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+width: 47%
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+end_selector
+div.lefttopbox
+***************
+
+***************
+start_selector
+div.lefttopbox p
+***************
+
+***************
+property
+margin-top: 5px
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+end_selector
+div.lefttopbox p
+***************
+
+***************
+start_selector
+div.lefttopbox h1
+***************
+
+***************
+property
+font-size: 13px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+property
+text-align: right
+***************
+
+***************
+end_selector
+div.lefttopbox h1
+***************
+
+***************
+start_selector
+div.lefttopbox h2
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.lefttopbox h2
+***************
+
+***************
+start_selector
+div.lefttopbox h3
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.lefttopbox h3
+***************
+
+***************
+start_selector
+div.righttopbox
+***************
+
+***************
+property
+position: relative
+***************
+
+***************
+property
+border: 1px #a59f8b solid
+***************
+
+***************
+property
+background: white
+***************
+
+***************
+property
+padding: 5px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+width: 47%
+***************
+
+***************
+property
+float: right
+***************
+
+***************
+end_selector
+div.righttopbox
+***************
+
+***************
+start_selector
+div.righttopbox h1
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.righttopbox h1
+***************
+
+***************
+start_selector
+div.righttopbox h2
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.righttopbox h2
+***************
+
+***************
+start_selector
+div.boardindex
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+property
+padding: 10px
+***************
+
+***************
+property
+margin-left: 20px
+***************
+
+***************
+property
+margin-right: 20px
+***************
+
+***************
+end_selector
+div.boardindex
+***************
+
+***************
+start_selector
+a.boardindex:link, a.boardindex:visited, a.boardindex:active
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+property
+color: red
+***************
+
+***************
+end_selector
+a.boardindex:link, a.boardindex:visited, a.boardindex:active
+***************
+
+***************
+start_selector
+div.boardleftmsg
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+margin-top: 3px
+***************
+
+***************
+end_selector
+div.boardleftmsg
+***************
+
+***************
+start_selector
+div.boardrightmsg
+***************
+
+***************
+property
+margin-left: 130px
+***************
+
+***************
+property
+margin-top: 3px
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+end_selector
+div.boardrightmsg
+***************
+
+***************
+start_selector
+div.journalbody
+***************
+
+***************
+property
+margin-left: 40px
+***************
+
+***************
+property
+margin-top: 40px
+***************
+
+***************
+end_selector
+div.journalbody
+***************
+
+***************
+start_selector
+div.journalbody h1
+***************
+
+***************
+property
+font-size: 15px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+end_selector
+div.journalbody h1
+***************
+
+***************
+start_selector
+div.journalbody p
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+end_selector
+div.journalbody p
+***************
+
+***************
+start_selector
+.formulaire
+***************
+
+***************
+property
+border: solid 1px black
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+background-color: #eef
+***************
+
+***************
+property
+color: #000000
+***************
+
+***************
+end_selector
+.formulaire
+***************
+
+***************
+start_selector
+.newcomments
+***************
+
+***************
+property
+color: red
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+end_selector
+.newcomments
+***************
+
+***************
+start_selector
+div.commentsreplythanks
+***************
+
+***************
+property
+margin-left: 100px
+***************
+
+***************
+property
+margin-top: 50px
+***************
+
+***************
+property
+margin-right: 100px
+***************
+
+***************
+property
+background-color: #eee
+***************
+
+***************
+property
+border: black solid 1px
+***************
+
+***************
+property
+padding: 10px
+***************
+
+***************
+end_selector
+div.commentsreplythanks
+***************
+
+***************
+start_selector
+div.archivediv
+***************
+
+***************
+property
+margin-right: 20px
+***************
+
+***************
+end_selector
+div.archivediv
+***************
+
+***************
+start_selector
+.archivedate
+***************
+
+***************
+property
+color: #f30
+***************
+
+***************
+end_selector
+.archivedate
+***************
+
+***************
+start_selector
+.archivelink
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+text-decoration: underline
+***************
+
+***************
+end_selector
+.archivelink
+***************
+
+***************
+end_document
+***************
+
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test2.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test2.css.out
new file mode 100644
index 0000000..f989353
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test2.css.out
@@ -0,0 +1,63 @@
+***************
+start_document
+***************
+
+***************
+start_selector
+S1
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+S1
+***************
+
+***************
+start_selector
+s1, s2
+***************
+
+***************
+property
+color: black
+***************
+
+***************
+property
+background: white
+***************
+
+***************
+end_selector
+s1, s2
+***************
+
+***************
+start_selector
+s1 s2, S3>s4
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+property
+prop2: value2
+***************
+
+***************
+end_selector
+s1 s2, S3>s4
+***************
+
+***************
+end_document
+***************
+
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test3.1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test3.1.css.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test3.1.css.out
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test3.2.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test3.2.css.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test3.2.css.out
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test3.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test3.css.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test3.css.out
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test4.1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test4.1.css.out
new file mode 100644
index 0000000..95aa7b7
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test4.1.css.out
@@ -0,0 +1,766 @@
+* {
+ font-family : Verdana, Arial, Helvetica, sans-serif, monospace !important
+}
+
+tutu:class1:class2 {
+ test : ok
+}
+
+body {
+ background : #606060;
+ color : #000000
+}
+
+a:link {
+ color : #0000FF;
+ background : transparent;
+ text-decoration : none
+}
+
+a:visited {
+ color : #990099;
+ background : transparent;
+ text-decoration : none
+}
+
+a:active {
+ color : #000000;
+ background : #ADD8E6;
+ text-decoration : none
+}
+
+h1.rubrique_info {
+ color : #990033;
+ margin : 0px 0px 0px 0px;
+ padding : 0.4em;
+ border : 0px;
+ font-size : 12px
+}
+
+h1.connexe {
+ font-size : 12px;
+ padding : 0.9em;
+ margin : 0px 0px 0px 0px;
+ color : #990033
+}
+
+a.rubrique_infolink {
+ text-decoration : none
+}
+
+ul.rubrique_infoul {
+ display : inline;
+ list-style-type : square
+}
+
+ul.rubrique_infoul * {
+ width : 100%
+}
+
+li.rubrique_infoul {
+ margin-left : 15px
+}
+
+h1 {
+ color : #990033
+}
+
+div.main {
+ background : white;
+ color : #000000;
+ margin-left : 5px;
+ margin-right : 5px;
+ border : 1px black solid;
+ text-align : left;
+ font-size : 12px
+}
+
+div.lsfnbanner {
+ margin-left : 150px;
+ margin-right : 170px;
+ border-top : none;
+ padding-left : 10px;
+ padding-right : 10px;
+ border-bottom : 1px black solid;
+ border-right : 1px black solid;
+ border-left : 1px black solid;
+ text-align : left;
+ font-size : 11px;
+ padding-top : 2px;
+ background-color : #eeeae6
+}
+
+div.footer {
+ padding-top : 5px;
+ padding-bottom : 3px;
+ border-top : 1px black solid;
+ border-left : 1px black solid;
+ border-right : 1px black solid;
+ text-align : left;
+ font-size : 9px;
+ background : #dcdff4;
+ width : 600px;
+ margin-top : 40px;
+ margin-left : 20px
+}
+
+div.footer p {
+ margin-left : 10px;
+ margin-top : 2px;
+ margin-bottom : 2px
+}
+
+a.lsfnlink:link, a.lsfnlink:visited, a.lsfnlink:active {
+ text-decoration : none;
+ color : #333333;
+ font-size : 10px
+}
+
+a.lsfnlink:hover {
+ text-decoration : underline;
+ color : black
+}
+
+div.menubartop {
+ margin-bottom : 10px;
+ padding-left : 10px;
+ padding-right : 10px;
+ padding-top : 0px;
+ font-size : 13px
+}
+
+div.smallmenubar {
+ background : white;
+ padding-left : 10px;
+ padding-right : 10px;
+ padding-top : 0px;
+ padding-bottom : 0px;
+ font-weight : bold;
+ font-size : 10px;
+ text-align : right
+}
+
+div.menuevent {
+ float : left;
+ width : 350px;
+ font-size : 11px;
+ text-align : left;
+ padding-top : 0px;
+ padding-bottom : 0px;
+ padding-left : 10px;
+ font-weight : bold;
+ margin : 0px
+}
+
+div.menubar {
+ background : #cac2a8;
+ border-top : 1px black solid;
+ border-bottom : 1px black solid;
+ padding-left : 10px;
+ padding-right : 10px;
+ padding-top : 3px;
+ padding-bottom : 2px;
+ font-weight : bold;
+ font-size : 13px
+}
+
+div.menubar a {
+ text-decoration : none
+}
+
+div.menudate {
+ float : left;
+ width : 130px;
+ padding-top : 5px
+}
+
+div.menuaccroche {
+ margin-left : 30px;
+ float : left;
+ text-decoration : underline;
+ font-size : 14px
+}
+
+div.menusearch {
+ float : right;
+ text-align : right;
+ padding-top : 5px;
+ width : 170px
+}
+
+div.menusearch p {
+ margin : 0px 0px 0px 0px
+}
+
+.searchinput {
+ border : solid 1px black
+}
+
+a#menulinkselect {
+ color : #ed7e00
+}
+
+div.leftbox {
+ width : 200px;
+ float : left;
+ padding-left : 5px;
+ padding-right : 5px;
+ padding-bottom : 5px;
+ border-right : 1px black solid;
+ border-bottom : 1px black solid;
+ background : white;
+ margin-bottom : 10px
+}
+
+div.leftbox h1 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 10px;
+ margin : 0px
+}
+
+div.leftbox h2 {
+ font-weight : bold;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.leftbox ul {
+ list-style-type : square;
+ margin-bottom : 10px;
+ margin-left : 0.3em;
+ padding-left : 0.2em
+}
+
+div.leftbox li {
+ margin-left : 10px
+}
+
+div.rightbox {
+ width : 150px;
+ float : right;
+ padding-top : 10px;
+ padding-left : 5px;
+ padding-right : 15px;
+ padding-bottom : 5px;
+ border-left : 1px black solid;
+ border-bottom : 1px black solid;
+ text-align : left
+}
+
+div.newjournaldiv {
+ text-align : justify;
+ margin-left : 10%;
+ font-size : 12px;
+ width : 600px
+}
+
+div.newjournaldiv p {
+ margin-bottom : 0px;
+ margin-top : 20px
+}
+
+div.journaldiv {
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 20px;
+ margin-bottom : 20px;
+ border : 1px black solid;
+ padding-top : 5px;
+ padding-bottom : 5px;
+ padding-right : 10px;
+ padding-left : 10px;
+ background-color : #eef
+}
+
+div.journaldiv p {
+ margin-top : 10px;
+ margin-bottom : 0px
+}
+
+div.journaldiv h1 {
+ color : #990033;
+ font-size : 14px;
+ margin : 0px
+}
+
+div.journaldiv h2 {
+ font-size : 10px;
+ margin : 0px
+}
+
+div.tipdiv {
+ margin-left : 220px;
+ margin-right : 50px;
+ margin-top : 20px;
+ padding-top : 5px;
+ padding-right : 10px;
+ padding-left : 10px;
+ text-align : justify;
+ background-color : #eee;
+ border : black solid 1px
+}
+
+div.tipdiv h1 {
+ font-weight : bold;
+ font-size : 14px;
+ color : black;
+ margin-top : 0px;
+ margin-bottom : 20px
+}
+
+div.tipdiv h2 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.newsdiv {
+ margin-left : 220px;
+ margin-right : 180px;
+ margin-top : 10px;
+ margin-bottom : 20px;
+ text-align : justify
+}
+
+div.newsdiv h1 {
+ font-weight : bold;
+ font-size : 14px;
+ margin : 0px
+}
+
+div.newsdiv h2 {
+ font-weight : normal;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.newsdiv h3 {
+ font-weight : normal;
+ font-size : 12px;
+ margin-bottom : 20px
+}
+
+div.objdiv {
+ margin-left : 220px;
+ margin-right : 20px;
+ margin-top : 10px;
+ margin-bottom : 20px
+}
+
+h1.newstitle {
+ text-align : left;
+ font-size : 14px;
+ margin : 0px 0px 0px 0px;
+ color : black
+}
+
+div.titlediv {
+ border-top : solid #cac2a8 2px;
+ margin-top : 20px;
+ background-color : #eeeae6;
+ padding-left : 10px;
+ font-size : 11px
+}
+
+div.bodydiv {
+ border : solid #9e9784 1px;
+ padding-left : 10px;
+ padding-right : 10px;
+ padding-top : 10px;
+ padding-bottom : 5px;
+ margin-top : 2px;
+ text-align : justify
+}
+
+div.comments {
+ padding : 10px;
+ border-top : solid 2px #d37537;
+ border-bottom : solid 2px #d37537;
+ margin-top : 20px;
+ margin-bottom : 10px;
+ background-color : #cacaca;
+ font-size : 12px;
+ line-height : 1.3em
+}
+
+p.commentsbody {
+ border-left-style : solid;
+ border-width : 1px;
+ border-color : rgb(0, 0, 0);
+ padding-left : 10px;
+ text-align : justify;
+ margin-right : 20px
+}
+
+div.commentsreply {
+ margin-left : 220px;
+ text-align : center;
+ margin-top : 50px
+}
+
+ul.commentsul {
+ list-style-type : none;
+ margin-bottom : 10px;
+ margin-left : 1.25em;
+ padding-left : 0em;
+ border-left : 1px solid black
+}
+
+ul.commentsli {
+ margin : 10px
+}
+
+div.comments li {
+ margin-top : 20px;
+ margin-left : 2px
+}
+
+div.comments h1 {
+ font-size : 12px;
+ color : black;
+ margin : 0px 20px 3px 0px;
+ background-color : rgb(226, 226, 226);
+ padding-left : 1px;
+ font-weight : none
+}
+
+div.articlediv {
+ padding-left : 20px;
+ padding-right : 20px;
+ padding-top : 10px;
+ padding-bottom : 20px;
+ margin-right : 10px;
+ margin-left : 220px;
+ border : solid 1px black;
+ margin-top : 10px;
+ text-align : justify;
+ background-color : #E2E2E2
+}
+
+img {
+ border : 0px
+}
+
+div.sectionimg {
+ float : left;
+ margin-right : 10px;
+ margin-top : 5px
+}
+
+p.hautpage {
+ margin-top : 20px;
+ margin-bottom : 20px;
+ margin-left : 10px
+}
+
+div.leftcol {
+ width : 202px;
+ width : 202px;
+ float : left;
+ padding : 0px
+}
+
+div.logodiv {
+ border-right : 1px black solid;
+ border-bottom : 1px black solid;
+ padding : 0px;
+ line-height : 0px
+}
+
+div.loginbox {
+ margin-left : 4px;
+ border : solid #a59f8b 1px;
+ margin-top : 2px;
+ padding : 5px;
+ background-color : #fff2e8;
+ font-size : 10px
+}
+
+div.loginbox p {
+ margin : 0px;
+ padding : 0px
+}
+
+div.loginbox ul {
+ margin-left : 10px;
+ margin-top : 0px;
+ margin-bottom : 0px;
+ padding : 0px;
+ list-style-type : none
+}
+
+div.loginbox h1 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 10px;
+ margin : 0px
+}
+
+div.loginbox h2 {
+ font-weight : bold;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.loginbox h3 {
+ margin-top : 0px;
+ margin-bottom : 5px;
+ font-size : 12px
+}
+
+div.polldivtitle {
+ margin-bottom : 1px;
+ background-color : #cac2a8;
+ margin-left : 4px;
+ margin-top : 15px;
+ padding-left : 5px;
+ font-size : 10px;
+ border-top : solid #a59f8b 1px;
+ border-bottom : solid #a59f8b 1px;
+ text-transform : uppercase
+}
+
+div.polldiv {
+ margin-left : 4px;
+ border : 1px #a59f8b solid;
+ margin-top : 0px;
+ padding : 5px;
+ background : #fff2e8
+}
+
+div.polldiv p {
+ margin : 5px;
+ padding : 0px
+}
+
+div.polldiv ul {
+ margin-left : 5px;
+ margin-top : 0px;
+ margin-bottom : 10px;
+ padding : 0px;
+ list-style-type : none
+}
+
+div.otherboxtitle {
+ margin-bottom : 2px;
+ background-color : #e3dabc;
+ margin-left : 4px;
+ margin-top : 15px;
+ padding-left : 5px;
+ padding-top : 2px;
+ font-size : 11px;
+ border-top : solid #777364 1px;
+ border-bottom : solid #777364 1px;
+ text-transform : uppercase;
+ font-weight : bold
+}
+
+div.otherbox {
+ margin-left : 4px;
+ border : 1px #a59f8b solid;
+ margin-top : 0px;
+ padding : 5px;
+ text-align : justify;
+ background : #fff2e8;
+ font-size : 10px
+}
+
+div.otherbox h1 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 10px;
+ margin : 0px
+}
+
+div.otherbox h2 {
+ font-weight : bold;
+ font-size : 11px;
+ margin : 0px
+}
+
+div.otherbox p {
+ margin-top : 5px;
+ margin-bottom : 10px
+}
+
+div.rightlogo {
+ width : 90px;
+ float : right;
+ margin-right : 0px;
+ padding-top : 0px;
+ padding-left : 0px;
+ padding-bottom : 0px
+}
+
+div.centraldiv {
+ margin-left : 220px;
+ margin-right : 10px;
+ margin-bottom : 20px;
+ margin-top : 10px
+}
+
+div.centraldiv h1 {
+ font-weight : bold;
+ font-size : 14px;
+ margin : 0px
+}
+
+div.centraldiv h2 {
+ font-weight : normal;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.centraldiv h3 {
+ font-weight : normal;
+ font-size : 12px;
+ margin-bottom : 20px
+}
+
+div.centralinfo {
+ position : relative;
+ height : 160px
+}
+
+div.lefttopbox {
+ position : relative;
+ padding-left : 5px;
+ padding-right : 5px;
+ padding-top : 5px;
+ border : 1px #a59f8b solid;
+ text-align : justify;
+ background : #fff2e8;
+ font-size : 12px;
+ width : 47%;
+ float : left
+}
+
+div.lefttopbox p {
+ margin-top : 5px;
+ margin-bottom : 10px
+}
+
+div.lefttopbox h1 {
+ font-size : 13px;
+ font-weight : bold;
+ margin : 0px;
+ text-align : right
+}
+
+div.lefttopbox h2 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 10px;
+ margin : 0px
+}
+
+div.lefttopbox h3 {
+ font-weight : bold;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.righttopbox {
+ position : relative;
+ border : 1px #a59f8b solid;
+ background : white;
+ padding : 5px;
+ text-align : justify;
+ font-size : 12px;
+ width : 47%;
+ float : right
+}
+
+div.righttopbox h1 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 10px;
+ margin : 0px
+}
+
+div.righttopbox h2 {
+ font-weight : bold;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.boardindex {
+ text-align : justify;
+ font-size : 11px;
+ padding : 10px;
+ margin-left : 20px;
+ margin-right : 20px
+}
+
+a.boardindex:link, a.boardindex:visited, a.boardindex:active {
+ text-decoration : none;
+ color : red
+}
+
+div.boardleftmsg {
+ float : left;
+ margin-top : 3px
+}
+
+div.boardrightmsg {
+ margin-left : 130px;
+ margin-top : 3px;
+ padding-left : 5px
+}
+
+div.journalbody {
+ margin-left : 40px;
+ margin-top : 40px
+}
+
+div.journalbody h1 {
+ font-size : 15px;
+ font-weight : bold
+}
+
+div.journalbody p {
+ margin-bottom : 20px
+}
+
+.formulaire {
+ border : solid 1px black;
+ font-size : 12px;
+ background-color : #eef;
+ color : #000000
+}
+
+.newcomments {
+ color : red;
+ font-weight : bold
+}
+
+div.commentsreplythanks {
+ margin-left : 100px;
+ margin-top : 50px;
+ margin-right : 100px;
+ background-color : #eee;
+ border : black solid 1px;
+ padding : 10px
+}
+
+div.archivediv {
+ margin-right : 20px
+}
+
+.archivedate {
+ color : #f30
+}
+
+.archivelink {
+ font-size : 14px;
+ font-weight : bold;
+ text-decoration : underline
+} \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test4.2.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test4.2.css.out
new file mode 100644
index 0000000..b67ae23
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test4.2.css.out
@@ -0,0 +1,24 @@
+@charset "ISO-8859-1" ;
+
+@import url("http://www.yahoo.com/css")print, screen ;
+
+@font-face {
+ font-family : 'Robson Celtic';
+ src : url(http://site/fonts/rob-celt)
+}
+
+@page left :one-two {
+ margin : 10pt;
+ border : none
+}
+
+
+@media print, screen, projection {
+ H1 {
+ font-family : 'Robson Celtic', serif
+ }
+ P {
+ background : black;
+ foreground : white
+ }
+} \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test5.1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test5.1.css.out
new file mode 100644
index 0000000..2f0bc54
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test5.1.css.out
@@ -0,0 +1,105 @@
+'''''''''''''''''''''''''
+xml start element: document
+
+ :first-child {
+ first-child-prop : first-child-value
+ }
+
+xml end element: document
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E0
+
+ :first-child {
+ first-child-prop : first-child-value
+ }
+ E0 {
+ prop0 : val0
+ }
+
+xml end element: E0
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E1
+
+ E0+E1 {
+ pro1 : val1
+ }
+
+xml end element: E1
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E1-1
+
+ :first-child {
+ first-child-prop : first-child-value
+ }
+ E1 E1-1 {
+ prop2 : val2
+ }
+ E1>E1-1 {
+ prop3 : val3
+ }
+ document E1-1 {
+ prop4 : val4
+ }
+
+xml end element: E1-1
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E2
+
+ [attr2="val2"] {
+ prop5 : val5
+ }
+ E2[attr2="val2"] {
+ prop8 : val8
+ }
+
+xml end element: E2
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E3
+
+ [attr3~="val3_2"] {
+ prop6 : val6
+ }
+
+xml end element: E3
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E4
+
+ [attr4|="val4"] {
+ prop7 : val7
+ }
+
+xml end element: E4
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E5
+
+ .class5 {
+ prop8 : val8
+ }
+
+xml end element: E5
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E6
+
+ #id6 {
+ prop9 : val9
+ }
+
+xml end element: E6
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E7
+
+ :lang(fr) {
+ lang-prop : lang-value
+ }
+
+xml end element: E7
+'''''''''''''''''''''''''
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test6.out b/src/3rdparty/libcroco/tests/test-output-refs/test6.out
new file mode 100644
index 0000000..cdc81db
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test6.out
@@ -0,0 +1,8 @@
+.str0 {
+ stroke : #007844;
+ stroke-width : 44
+}
+
+.fil0 {
+ fill : url(#id0)
+} \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test7.out b/src/3rdparty/libcroco/tests/test-output-refs/test7.out
new file mode 100644
index 0000000..21d10d7
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test7.out
@@ -0,0 +1,43 @@
+.exp1n1 {
+ stroke-width : 4000000
+}
+
+.exp1n2 {
+ stroke-width : 4000000
+}
+
+.exp1n3 {
+ stroke-width : 4000000
+}
+
+.exp2n1 {
+ stroke-width : 0.000004
+}
+
+.exp2n2 {
+ stroke-width : 0.000004
+}
+
+.exp3n1 {
+ stroke-width : 4000000em
+}
+
+.exp3n2 {
+ stroke-width : 4000000ex
+}
+
+.exp3n3 {
+ stroke-width : 4000000in
+}
+
+.exp4n1 {
+ stroke-width : 31400
+}
+
+.exp4n2 {
+ stroke-width : 0.000314
+}
+
+.e4n2 {
+ stroke-width : 0.000024
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test8.out b/src/3rdparty/libcroco/tests/test-output-refs/test8.out
new file mode 100644
index 0000000..9e25188
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test8.out
@@ -0,0 +1,15 @@
+****************
+Parsing 'foo'
+foo
+****************
+Parsing 'foo,bar'
+foo, bar
+****************
+Parsing 'foo , bar '
+foo, bar
+****************
+Parsing 'foo > bar'
+foo>bar
+****************
+Parsing '.foo .bar'
+.foo.bar
diff --git a/src/3rdparty/libcroco/tests/test-parsing-location.sh b/src/3rdparty/libcroco/tests/test-parsing-location.sh
new file mode 100755
index 0000000..4d7af34
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-parsing-location.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT --dump-location $TEST_INPUTS_DIR/parsing-location.css
diff --git a/src/3rdparty/libcroco/tests/test-prop-ident.sh b/src/3rdparty/libcroco/tests/test-prop-ident.sh
new file mode 100755
index 0000000..31e6127
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-prop-ident.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT "$TEST_INPUTS_DIR"/prop-vendor-ident.css
diff --git a/src/3rdparty/libcroco/tests/test-sel-child-class.sh b/src/3rdparty/libcroco/tests/test-sel-child-class.sh
new file mode 100755
index 0000000..ebfbb96
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-sel-child-class.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT -e --user-sheet $TEST_INPUTS_DIR/sel-child-class.css --xml $TEST_INPUTS_DIR/sel-child-class.xml --xpath /test/body/div/div/p
diff --git a/src/3rdparty/libcroco/tests/test-several-media.sh b/src/3rdparty/libcroco/tests/test-several-media.sh
new file mode 100755
index 0000000..c0a0c9d
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-several-media.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT "$TEST_INPUTS_DIR"/several-media.css
diff --git a/src/3rdparty/libcroco/tests/test-unknown-at-rule.sh b/src/3rdparty/libcroco/tests/test-unknown-at-rule.sh
new file mode 100755
index 0000000..08ceff6
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-unknown-at-rule.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT "$TEST_INPUTS_DIR"/unknown-at-rule.css
diff --git a/src/3rdparty/libcroco/tests/test-unknown-at-rule2.sh b/src/3rdparty/libcroco/tests/test-unknown-at-rule2.sh
new file mode 100755
index 0000000..fe58731
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-unknown-at-rule2.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT "$TEST_INPUTS_DIR"/unknown-at-rule2.css
diff --git a/src/3rdparty/libcroco/tests/test0-main.c b/src/3rdparty/libcroco/tests/test0-main.c
new file mode 100644
index 0000000..993c983
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test0-main.c
@@ -0,0 +1,203 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+#include <stdio.h>
+#include "cr-input.h"
+#include "string.h"
+
+/**
+ *@file
+ *Some test facilities for the #CRInput class.
+ */
+
+/**
+ *The options data structure.
+ *The variable of this data structure are set
+ *during the parsing the command line by the
+ *parse_command_line() function.
+ */
+struct Options {
+ gboolean display_help;
+ gboolean display_about;
+ gchar **files_list;
+};
+
+static void
+ display_help (char *prg_name);
+
+static void
+ display_about (char *prg_name);
+
+static void
+ parse_command_line (int a_argc, char **a_argv, struct Options *a_options);
+
+static enum CRStatus
+ test_cr_input_read_byte (guchar * a_file_uri);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("usage: %s <file-to-parse>\n", prg_name);
+ g_print ("\t <file-to-parse>: the file to parse\n");
+ g_print ("\n\n");
+ g_print ("This test just reads the file byte per byte\nand sends each byte to stdout\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("%s is a libcroco CRInput class test program.\n", prg_name);
+ g_print ("It should run on GNU compliants systems.\n");
+ g_print ("\n\n");
+ g_print ("Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Parses the command line and updates an abstract "options" data structure.
+ *@param a_argc the argc variable passed to the main function by the OS.
+ *@param a_argv the argv variable passed to the main function by the OS.
+ *@param a_options out parameter. The abstraction of the parsed the options.
+ */
+static void
+parse_command_line (int a_argc, char **a_argv, struct Options *a_options)
+{
+ int i = 0;
+
+ g_return_if_fail (a_options);
+
+ memset (a_options, 0, sizeof (struct Options));
+
+ for (i = 1; i < a_argc; i++) {
+ if (a_argv[i][0] != '-')
+ break;
+
+ if (!strcmp (a_argv[i], "-h")
+ || !strcmp (a_argv[i], "--help")) {
+ a_options->display_help = TRUE;
+ }
+ if (!strcmp (a_argv[i], "--about")) {
+ a_options->display_about = TRUE;
+ }
+ }
+
+ if (i >= a_argc) {
+ /*No file parameter where given */
+ a_options->files_list = NULL;
+ } else {
+ a_options->files_list = &a_argv[i];
+ }
+}
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_input_read_byte (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CRInput *input = NULL;
+ guchar byte = 0;
+ guint c = 0;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ input = cr_input_new_from_uri ((const gchar *) a_file_uri, CR_UTF_8);
+
+ if (!input) {
+ cr_utils_trace_debug ("Input Stream creation failed.");
+ return CR_ERROR;
+ }
+
+ for (status = CR_OK; status == CR_OK;) {
+ status = cr_input_read_byte (input, &byte);
+
+ if (status == CR_OK) {
+ c = byte;
+ printf ("%d", c);
+ fflush (stdout);
+ }
+ }
+
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ }
+
+ cr_input_destroy (input);
+ input = NULL;
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+
+ parse_command_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ test_cr_input_read_byte ((guchar *) options.files_list[0]);
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test1-main.c b/src/3rdparty/libcroco/tests/test1-main.c
new file mode 100644
index 0000000..1c5f127
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test1-main.c
@@ -0,0 +1,197 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information
+ */
+
+#include <stdio.h>
+#include "cr-input.h"
+#include "string.h"
+
+/**
+ *@file
+ *Some test facilities for the #CRInput class.
+ */
+
+/**
+ *The options data structure.
+ *The variable of this data structure are set
+ *during the parsing the command line by the
+ *parse_command_line() function.
+ */
+struct Options {
+ gboolean display_help;
+ gboolean display_about;
+ gchar **files_list;
+};
+
+static void
+ display_help (char *prg_name);
+
+static void
+ display_about (char *prg_name);
+
+static void
+ parse_command_line (int a_argc, char **a_argv, struct Options *a_options);
+
+static enum CRStatus
+ test_cr_input_read_char (guchar * a_file_uri);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("usage: %s <file-to-parse>\n", prg_name);
+ g_print ("\t <file-to-parse>: the file to parse\n");
+ g_print ("\n\n");
+ g_print ("This test just reads the file character per character\nand sends each character to stdout\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("%s is a libcroco CRInput class test program.\n", prg_name);
+ g_print ("It should run on GNU compliants systems.\n");
+ g_print ("\n\n");
+ g_print ("Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Parses the command line and updates an abstract "options" data structure.
+ *@param a_argc the argc variable passed to the main function by the OS.
+ *@param a_argv the argv variable passed to the main function by the OS.
+ *@param a_options out parameter. The abstraction of the parsed the options.
+ */
+static void
+parse_command_line (int a_argc, char **a_argv, struct Options *a_options)
+{
+ int i = 0;
+
+ g_return_if_fail (a_options);
+
+ memset (a_options, 0, sizeof (struct Options));
+
+ for (i = 1; i < a_argc; i++) {
+ if (a_argv[i][0] != '-')
+ break;
+
+ if (!strcmp (a_argv[i], "-h")
+ || !strcmp (a_argv[i], "--help")) {
+ a_options->display_help = TRUE;
+ }
+ if (!strcmp (a_argv[i], "--about")) {
+ a_options->display_about = TRUE;
+ }
+ }
+
+ if (i >= a_argc) {
+ /*No file parameter where given */
+ a_options->files_list = NULL;
+ } else {
+ a_options->files_list = &a_argv[i];
+ }
+}
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+enum CRStatus
+test_cr_input_read_char (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CRInput *input = NULL;
+ guint32 c = 0;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ input = cr_input_new_from_uri ((const gchar *) a_file_uri, CR_UTF_8);
+
+ if (!input) {
+ cr_utils_trace_debug ("Input Stream creation failed.");
+ return CR_ERROR;
+ }
+
+ for (status = CR_OK; status == CR_OK;) {
+ status = cr_input_read_char (input, &c);
+
+ if (status == CR_OK) {
+ printf ("%c", c);
+ fflush (stdout);
+ }
+ }
+
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ }
+
+ cr_input_destroy (input);
+ input = NULL;
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+
+ parse_command_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ test_cr_input_read_char ((guchar *) options.files_list[0]);
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test2-main.c b/src/3rdparty/libcroco/tests/test2-main.c
new file mode 100644
index 0000000..5268ed3
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test2-main.c
@@ -0,0 +1,564 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms
+ * of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "cr-test-utils.h"
+#include "cr-parser.h"
+
+/**
+ *@file
+ *Some test facilities for the #CRParser class.
+ */
+
+CRDocHandler *gv_test_handler = { 0 };
+
+static void
+ display_help (char *prg_name);
+
+static void
+ display_about (char *prg_name);
+
+static enum CRStatus
+ test_cr_parser_parse (guchar * a_file_uri);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "usage: %s <file-to-parse>\n", prg_name);
+ fprintf (stdout, "\t <file-to-parse>: the file to parse\n");
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "Tests the cr_parser_parse () method.\n");
+ fprintf (stdout, "Returns OK if the status is CR_OK, KO otherwise\n");
+ fprintf (stdout, "\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "%s is a libcroco CRParser class test program.\n",
+ prg_name);
+ fprintf (stdout, "It should run on GNU compliants systems.\n");
+ fprintf (stdout, "\n\n");
+ fprintf (stdout,
+ "Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ fprintf (stdout, "\n\n");
+}
+
+/***************************
+ *Some SAC document handlers
+ *for TEST PURPOSES.
+ ***************************/
+
+static void
+test_start_document (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_document\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_document (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_document\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_import_style (CRDocHandler * a_handler,
+ GList * a_media_list,
+ CRString * a_uri,
+ CRString * a_uri_default_ns,
+ CRParsingLocation *a_location)
+{
+ (void) a_uri;
+
+ g_return_if_fail (a_handler) ;
+
+ fprintf (stdout, "****************\n");
+ fprintf (stdout, "import_style\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+
+ fprintf (stdout, "\nmedia list:\n");
+ fprintf (stdout, "-------------\n");
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data) {
+ gchar *str =
+ g_strndup
+ (((CRString *) cur->data)->stryng->str,
+ ((CRString *) cur->data)->stryng->len);
+
+ if (str) {
+ fprintf (stdout, "%s\n", str);
+ g_free (str);
+ str = NULL;
+ }
+ }
+ }
+
+ fprintf (stdout, "\ndefault namespace:\n");
+ fprintf (stdout, "--------------------\n");
+
+ if (a_uri_default_ns) {
+ guchar *str = (guchar *) cr_string_dup2
+ (a_uri_default_ns) ;
+ if (str) {
+ fprintf (stdout, "%s\n", str);
+ g_free (str);
+ str = NULL;
+ }
+ }
+ }
+
+ fprintf (stdout, "******************\n\n");
+ a_uri = NULL; /*keep compiler happy */
+}
+
+static void
+test_namespace_declaration (CRDocHandler * a_handler,
+ CRString * a_prefix,
+ CRString * a_uri,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "namespace_declaration:\n");
+
+ if (a_prefix) {
+ gchar *prefix = NULL;
+
+ prefix = cr_string_dup2 (a_prefix) ;
+ if (prefix) {
+ fprintf (stdout, "prefix: %s\n", prefix);
+ g_free (prefix);
+ prefix = NULL;
+ }
+ }
+ if (a_uri) {
+ gchar *uri = NULL;
+
+ uri = cr_string_dup2 (a_uri) ;
+ if (uri) {
+ fprintf (stdout, "uri: %s\n", uri);
+ g_free (uri);
+ uri = NULL;
+ }
+ }
+ fprintf (stdout, "\n");
+
+ fprintf (stdout, "***************\n\n");
+
+}
+
+static void
+test_comment (CRDocHandler * a_handler,
+ CRString * a_comment)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "comment:\n");
+ if (a_comment) {
+ gchar *comment = NULL;
+
+ comment = cr_string_dup2 (a_comment);
+
+ if (comment) {
+ fprintf (stdout, "\n/*----------------------\n");
+ fprintf (stdout, "%s\n", comment);
+ fprintf (stdout, "-------------------------*/\n");
+ g_free (comment);
+ comment = NULL;
+ }
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_selector (CRDocHandler * a_handler,
+ CRSelector * a_selector_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_selector\n");
+
+ if (a_selector_list) {
+ cr_selector_dump (a_selector_list, stdout);
+ fprintf (stdout, "\n");
+ }
+
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_selector (CRDocHandler * a_handler,
+ CRSelector * a_selector_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_selector\n");
+
+ if (a_selector_list) {
+ cr_selector_dump (a_selector_list, stdout);
+ fprintf (stdout, "\n");
+ }
+
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_property (CRDocHandler * a_handler,
+ CRString * a_name,
+ CRTerm * a_expr,
+ gboolean a_important)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "property\n");
+
+ if (a_name
+ && a_name->stryng
+ && a_name->stryng->str) {
+ gchar *name = g_strndup
+ (a_name->stryng->str,
+ a_name->stryng->len);
+
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (a_expr) {
+ fprintf (stdout, ": ");
+ cr_term_dump (a_expr, stdout);
+ }
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ fprintf (stdout, "\n");
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_font_face (CRDocHandler * a_handler,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_font_face\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_font_face (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_font_face\n");
+ fprintf (stdout, "***************\n\n");
+
+}
+
+static void
+test_start_media (CRDocHandler * a_handler,
+ GList * a_media_list,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_media\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+ gchar *medium = NULL;
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data == NULL)
+ continue;
+ medium = cr_string_dup2
+ ((CRString *) cur->data);
+ if (medium == NULL)
+ continue;
+ fprintf (stdout, "medium: %s\n", medium);
+ if (medium) {
+ g_free (medium);
+ medium = NULL;
+ }
+ }
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_media (CRDocHandler * a_handler,
+ GList * a_media_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_media\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+ gchar *medium = NULL;
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data == NULL)
+ continue;
+
+ medium = g_strndup (((CRString *) cur->data)->stryng->str,
+ ((CRString *) cur->data)->stryng->len);
+ if (medium == NULL)
+ continue;
+ fprintf (stdout, "medium: %s\n", medium);
+ if (medium) {
+ g_free (medium);
+ medium = NULL;
+ }
+ }
+ }
+
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_page (CRDocHandler * a_handler,
+ CRString * a_name,
+ CRString * a_pseudo_page,
+ CRParsingLocation *a_location)
+{
+ gchar *name = NULL,
+ *pseudo_page = NULL;
+
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_page\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name) ;
+ }
+ if (a_pseudo_page) {
+ pseudo_page = cr_string_dup2 (a_pseudo_page);
+ }
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (pseudo_page) {
+ fprintf (stdout, ": %s\n", pseudo_page);
+ }
+ fprintf (stdout, "***************\n\n");
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ if (pseudo_page) {
+ g_free (pseudo_page);
+ pseudo_page = NULL;
+ }
+}
+
+static void
+test_end_page (CRDocHandler * a_handler,
+ CRString * a_name,
+ CRString * a_pseudo_page)
+{
+ gchar *name = NULL,
+ *pseudo_page = NULL;
+
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_page\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name) ;
+ }
+ if (a_pseudo_page) {
+ pseudo_page = cr_string_dup2 (a_pseudo_page) ;
+ }
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (pseudo_page) {
+ fprintf (stdout, ": %s\n", pseudo_page);
+
+ }
+ fprintf (stdout, "***************\n\n");
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ if (pseudo_page) {
+ g_free (pseudo_page);
+ pseudo_page = NULL;
+ }
+}
+
+static void
+test_ignorable_at_rule (CRDocHandler * a_handler,
+ CRString * a_name)
+{
+ gchar *name = NULL;
+
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "*********************\n");
+ fprintf (stdout, "ignorable_at_rule\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name);
+ }
+ if (name) {
+ fprintf (stdout, "%s\n", name);
+ }
+ fprintf (stdout, "*********************\n\n");
+}
+
+static void
+init_test_sac_handler (CRDocHandler * a_handler)
+{
+ a_handler->start_document = test_start_document;
+ a_handler->end_document = test_end_document;
+ a_handler->import_style = test_import_style;
+ a_handler->namespace_declaration = test_namespace_declaration;
+ a_handler->comment = test_comment;
+ a_handler->start_selector = test_start_selector;
+ a_handler->end_selector = test_end_selector;
+ a_handler->property = test_property;
+ a_handler->start_font_face = test_start_font_face;
+ a_handler->end_font_face = test_end_font_face;
+ a_handler->start_media = test_start_media;
+ a_handler->end_media = test_end_media;
+ a_handler->start_page = test_start_page;
+ a_handler->end_page = test_end_page;
+ a_handler->ignorable_at_rule = test_ignorable_at_rule;
+}
+
+/***************************
+ *END of TEST SAC document
+ *handlers.
+ ***************************/
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_parser_parse (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CRParser *parser = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ gv_test_handler = cr_doc_handler_new ();
+ init_test_sac_handler (gv_test_handler);
+
+ parser = cr_parser_new (NULL);
+
+ status = cr_parser_set_sac_handler (parser, gv_test_handler);
+
+ if (status != CR_OK) {
+ cr_parser_destroy (parser);
+ g_return_val_if_fail (status == CR_OK, CR_ERROR);
+ }
+
+ status = cr_parser_parse_file (parser, a_file_uri, CR_ASCII);
+
+ cr_parser_destroy (parser);
+
+ gv_test_handler = NULL;
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+ enum CRStatus status = CR_OK;
+
+ cr_test_utils_parse_cmd_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ status = test_cr_parser_parse ((guchar *) options.files_list[0]);
+
+ if (status != CR_OK) {
+ fprintf (stdout, "KO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test3-main.c b/src/3rdparty/libcroco/tests/test3-main.c
new file mode 100644
index 0000000..1979778
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test3-main.c
@@ -0,0 +1,545 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "cr-test-utils.h"
+#include "cr-parser.h"
+
+/**
+ *@file
+ *Some test facilities for the #CRParser class.
+ */
+
+CRDocHandler *gv_test_handler = { 0 };
+
+static void display_help (char *prg_name);
+
+static void display_about (char *prg_name);
+
+static enum CRStatus test_cr_parser_parse (guchar * a_file_uri);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "usage: %s <file-to-parse>\n", prg_name);
+ fprintf (stdout, "\t <file-to-parse>: the file to parse\n");
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "Tests the cr_parser_parse () method.\n");
+ fprintf (stdout, "Tests the parsing following the css core syntax\n");
+ fprintf (stdout, "Returns OK if the status is CR_OK, KO otherwise\n");
+ fprintf (stdout, "\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "%s is a libcroco CRParser class test program.\n",
+ prg_name);
+ fprintf (stdout, "It should run on GNU compliants systems.\n");
+ fprintf (stdout, "\n\n");
+ fprintf (stdout,
+ "Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ fprintf (stdout, "\n\n");
+}
+
+/***************************
+ *Some SAC document handlers
+ *for TEST PURPOSES.
+ ***************************/
+
+static void
+test_start_document (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_document\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_document (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_document\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_import_style (CRDocHandler * a_handler,
+ GList * a_media_list, CRString * a_uri,
+ CRString * a_uri_default_ns,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ (void) a_uri;
+
+ fprintf (stdout, "****************\n");
+ fprintf (stdout, "import_style\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+
+ fprintf (stdout, "\nmedia list:\n");
+ fprintf (stdout, "-------------\n");
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data) {
+ gchar *str =
+ cr_string_dup2 ((CRString *) cur->data);
+ if (str) {
+ fprintf (stdout, "%s\n", str);
+ g_free (str);
+ str = NULL;
+ }
+ }
+ }
+ fprintf (stdout, "\ndefault namespace:\n");
+ fprintf (stdout, "--------------------\n");
+
+ if (a_uri_default_ns) {
+ gchar *str = cr_string_dup2 (a_uri_default_ns) ;
+ if (str) {
+ fprintf (stdout, "%s\n", str);
+ g_free (str);
+ str = NULL;
+ }
+ }
+ }
+
+ fprintf (stdout, "******************\n\n");
+ a_uri = NULL; /*keep compiler happy */
+}
+
+static void
+test_namespace_declaration (CRDocHandler * a_handler,
+ CRString * a_prefix,
+ CRString * a_uri,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "namespace_declaration:\n");
+
+ if (a_prefix) {
+ gchar *prefix = NULL;
+
+ prefix = cr_string_dup2 (a_prefix);
+ if (prefix) {
+ fprintf (stdout, "prefix: %s\n", prefix);
+ g_free (prefix);
+ prefix = NULL;
+ }
+ }
+
+ if (a_uri) {
+ gchar *uri = NULL;
+ uri = cr_string_dup2 (a_uri) ;
+ if (uri) {
+ fprintf (stdout, "uri: %s\n", uri);
+ g_free (uri);
+ uri = NULL;
+ }
+ }
+ fprintf (stdout, "\n");
+
+ fprintf (stdout, "***************\n\n");
+
+}
+
+static void
+test_comment (CRDocHandler * a_handler,
+ CRString * a_comment)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "comment:\n");
+
+ if (a_comment) {
+ gchar *comment = NULL;
+
+ comment = cr_string_dup2 (a_comment);
+
+ if (comment) {
+ fprintf (stdout, "\n/*----------------------\n");
+ fprintf (stdout, "%s\n", comment);
+ fprintf (stdout, "-------------------------*/\n");
+ g_free (comment);
+ comment = NULL;
+ }
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_selector (CRDocHandler * a_handler,
+ CRSelector * a_selector_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_selector\n");
+
+ if (a_selector_list) {
+ cr_selector_dump (a_selector_list, stdout);
+ fprintf (stdout, "\n");
+ }
+
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_selector (CRDocHandler * a_handler,
+ CRSelector * a_selector_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_selector\n");
+
+ if (a_selector_list) {
+ cr_selector_dump (a_selector_list, stdout);
+ fprintf (stdout, "\n");
+ }
+
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_property (CRDocHandler * a_handler, CRString * a_name,
+ CRTerm * a_expr, gboolean a_important)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "property\n");
+
+ if (a_name) {
+ gchar *name = cr_string_dup2 (a_name);
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (a_expr) {
+ fprintf (stdout, ": ");
+ cr_term_dump (a_expr, stdout);
+ }
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ fprintf (stdout, "\n");
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_font_face (CRDocHandler * a_handler,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_font_face\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_font_face (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_font_face\n");
+ fprintf (stdout, "***************\n\n");
+
+}
+
+static void
+test_start_media (CRDocHandler * a_handler,
+ GList * a_media_list,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_media\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+ gchar *medium = NULL;
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data == NULL)
+ continue;
+ medium = cr_string_dup2 ((CRString *) cur->data);
+ if (medium == NULL)
+ continue;
+ fprintf (stdout, "medium: %s\n", medium);
+ if (medium) {
+ g_free (medium);
+ medium = NULL;
+ }
+ }
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_media (CRDocHandler * a_handler,
+ GList * a_media_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_media\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+ gchar *medium = NULL;
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data == NULL)
+ continue;
+ medium = cr_string_dup2 ((CRString *) cur->data);
+ if (medium == NULL)
+ continue;
+ fprintf (stdout, "medium: %s\n", medium);
+ if (medium) {
+ g_free (medium);
+ medium = NULL;
+ }
+ }
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_page (CRDocHandler * a_handler,
+ CRString * a_name,
+ CRString * a_pseudo_page,
+ CRParsingLocation *a_location)
+{
+ gchar *name = NULL,
+ *pseudo_page = NULL;
+
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_page\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name);
+ }
+ if (a_pseudo_page) {
+ pseudo_page = cr_string_dup2 (a_pseudo_page);
+ }
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (pseudo_page) {
+ fprintf (stdout, ": %s\n", pseudo_page);
+ }
+ fprintf (stdout, "***************\n\n");
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ if (pseudo_page) {
+ g_free (pseudo_page);
+ pseudo_page = NULL;
+ }
+}
+
+static void
+test_end_page (CRDocHandler * a_handler,
+ CRString * a_name,
+ CRString * a_pseudo_page)
+{
+ gchar *name = NULL,
+ *pseudo_page = NULL;
+
+ g_return_if_fail (a_handler);
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_page\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name);
+ }
+ if (a_pseudo_page) {
+ pseudo_page = cr_string_dup2 (a_pseudo_page) ;
+ }
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (pseudo_page) {
+ fprintf (stdout, ": %s\n", pseudo_page);
+
+ }
+ fprintf (stdout, "***************\n\n");
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ if (pseudo_page) {
+ g_free (pseudo_page);
+ pseudo_page = NULL;
+ }
+}
+
+static void
+test_ignorable_at_rule (CRDocHandler * a_handler,
+ CRString * a_name)
+{
+ gchar *name = NULL;
+
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "*********************\n");
+ fprintf (stdout, "ignorable_at_rule\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name);
+ }
+ if (name) {
+ fprintf (stdout, "%s\n", name);
+ }
+ fprintf (stdout, "*********************\n\n");
+}
+
+static void
+init_test_sac_handler (CRDocHandler * a_handler)
+{
+ a_handler->start_document = test_start_document;
+ a_handler->end_document = test_end_document;
+ a_handler->import_style = test_import_style;
+ a_handler->namespace_declaration = test_namespace_declaration;
+ a_handler->comment = test_comment;
+ a_handler->start_selector = test_start_selector;
+ a_handler->end_selector = test_end_selector;
+ a_handler->property = test_property;
+ a_handler->start_font_face = test_start_font_face;
+ a_handler->end_font_face = test_end_font_face;
+ a_handler->start_media = test_start_media;
+ a_handler->end_media = test_end_media;
+ a_handler->start_page = test_start_page;
+ a_handler->end_page = test_end_page;
+ a_handler->ignorable_at_rule = test_ignorable_at_rule;
+}
+
+/***************************
+ *END of TEST SAC document
+ *handlers.
+ ***************************/
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_parser_parse (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CRParser *parser = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ gv_test_handler = cr_doc_handler_new ();
+ init_test_sac_handler (gv_test_handler);
+
+ parser = cr_parser_new (NULL);
+
+ status = cr_parser_set_sac_handler (parser, gv_test_handler);
+
+ if (status != CR_OK) {
+ cr_parser_destroy (parser);
+ g_return_val_if_fail (status == CR_OK, CR_ERROR);
+ }
+
+ status = cr_parser_set_use_core_grammar (parser, TRUE);
+ status = cr_parser_parse_file (parser, a_file_uri, CR_ASCII);
+
+ cr_parser_destroy (parser);
+
+ gv_test_handler = NULL;
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+ enum CRStatus status = CR_OK;
+
+ cr_test_utils_parse_cmd_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ status = test_cr_parser_parse ((guchar *) options.files_list[0]);
+
+ if (status != CR_OK) {
+ fprintf (stdout, "KO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test4-main.c b/src/3rdparty/libcroco/tests/test4-main.c
new file mode 100644
index 0000000..5cca6ef
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test4-main.c
@@ -0,0 +1,435 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+
+#include "cr-test-utils.h"
+#include "libcroco.h"
+
+/**
+ *@file
+ *Some test facilities for the #CROMParser class.
+ */
+
+CRDocHandler *gv_test_handler = { 0 };
+
+const guchar *gv_term_buf = (const guchar *) "106";
+
+const guchar *gv_decl_buf = (const guchar *) "toto: tutu, tata";
+
+const guchar *gv_decl_list_buf = (const guchar *) "toto: titi; prop1:val1 ; prop2:val2;";
+
+const guchar *gv_ruleset_buf = (const guchar *) "s1 > s2 {toto: tutu, tata} ";
+
+const guchar *gv_at_media_buf =
+ (const guchar *) "@media print, toto {" " BODY { font-size: 10pt }" " }";
+
+const guchar *gv_at_page_buf = (const guchar *) "@page { size :8.5in 11in; margin: 2cm }";
+
+const guchar *gv_at_charset_buf = (const guchar *) "@charset \"ISO-8859-1\" ; ";
+
+const guchar *gv_at_font_face_buf =
+ (const guchar *) "@font-face {"
+ " font-family: \"Robson Celtic\";"
+ " src: url(\"http://site/fonts/rob-celt\")" "}";
+
+const guchar *gv_at_import_buf = (const guchar *) "@import \"subs.css\";";
+
+static void display_help (char *prg_name);
+
+static void display_about (char *prg_name);
+
+static enum CRStatus test_cr_parser_parse (guchar * a_file_uri);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("usage: %s <file-to-parse>\n", prg_name);
+ g_print ("\t <file-to-parse>: the file to parse\n");
+ g_print ("\n\n");
+ g_print ("Tests the cr_parser_parse () method.\n");
+ g_print ("Tests the parsing following the css core syntax\n");
+ g_print ("Returns OK if the status is CR_OK, KO otherwise\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("%s is a libcroco CROMParser class test program.\n",
+ prg_name);
+ g_print ("%s Parses a file and builds a CSS object model", prg_name);
+ g_print ("It should run on GNU compliants systems.\n");
+ g_print ("\n\n");
+ g_print ("Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ g_print ("\n\n");
+}
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_parser_parse (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+ CRStyleSheet *stylesheet = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ parser = cr_om_parser_new (NULL);
+ status = cr_om_parser_parse_file (parser, a_file_uri, CR_ASCII,
+ &stylesheet);
+ if (status == CR_OK && stylesheet) {
+ cr_stylesheet_dump (stylesheet, stdout);
+ cr_stylesheet_destroy (stylesheet);
+ }
+ cr_om_parser_destroy (parser);
+
+ return status;
+}
+
+static enum CRStatus
+test_cr_statement_at_page_rule_parse_from_buf (void)
+{
+ CRStatement *stmt = NULL ;
+
+ stmt = cr_statement_at_page_rule_parse_from_buf
+ (gv_at_page_buf, CR_UTF_8) ;
+ if (!stmt) {
+ return CR_ERROR ;
+ }
+ cr_statement_destroy (stmt) ;
+ return CR_OK ;
+}
+
+static enum CRStatus
+test_cr_term_parse_expression_from_buf (void)
+{
+ guchar *tmp_str = NULL;
+ CRTerm *term = NULL;
+
+ term = cr_term_parse_expression_from_buf (gv_term_buf, CR_UTF_8);
+
+ if (!term)
+ return CR_ERROR;
+ tmp_str = cr_term_to_string (term);
+ if (term) {
+ cr_term_destroy (term);
+ term = NULL;
+ }
+ if (tmp_str) {
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_declaration_parse (void)
+{
+ gchar *tmp_str = NULL;
+ CRDeclaration *decl = NULL;
+
+ decl = cr_declaration_parse_from_buf (NULL, gv_decl_buf, CR_UTF_8);
+ if (!decl)
+ return CR_ERROR;
+ tmp_str = cr_declaration_to_string (decl, 2);
+
+ if (decl) {
+ cr_declaration_destroy (decl);
+ }
+
+ if (tmp_str) {
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_declaration_parse_list (void)
+{
+ GString *str = NULL;
+ gchar *tmp_str = NULL;
+ CRDeclaration *decl = NULL,
+ *cur_decl = NULL;
+
+ decl = cr_declaration_parse_list_from_buf (gv_decl_list_buf,
+ CR_UTF_8);
+ if (!decl)
+ return CR_ERROR;
+ str = g_string_new (NULL);
+ for (cur_decl = decl; cur_decl; cur_decl = cur_decl->next) {
+ tmp_str = cr_declaration_to_string (cur_decl, 2);
+ if (tmp_str) {
+ g_string_append_printf (str, "%s;", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+
+ }
+ if (decl) {
+ cr_declaration_destroy (decl);
+ }
+
+ if (str) {
+ g_string_free (str, TRUE);
+ str = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_statement_ruleset_parse (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_ruleset_parse_from_buf (gv_ruleset_buf, CR_UTF_8);
+ g_return_val_if_fail (stmt, CR_ERROR);
+
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_statement_at_media_rule_parse (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_at_media_rule_parse_from_buf (gv_at_media_buf,
+ CR_UTF_8);
+ g_return_val_if_fail (stmt, CR_ERROR);
+
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+
+ return CR_OK;
+}
+
+
+static enum CRStatus
+test_cr_statement_at_charset_rule_parse (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_at_charset_rule_parse_from_buf (gv_at_charset_buf,
+ CR_UTF_8);
+ g_return_val_if_fail (stmt, CR_ERROR);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_statement_font_face_rule_parse_from_buf (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_font_face_rule_parse_from_buf
+ (gv_at_font_face_buf, CR_UTF_8);
+ g_return_val_if_fail (stmt, CR_ERROR);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_statement_at_import_rule_parse_from_buf (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_at_import_rule_parse_from_buf (gv_at_import_buf,
+ CR_UTF_8);
+ g_return_val_if_fail (stmt, CR_ERROR);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_statement_parse_from_buf (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_parse_from_buf (gv_ruleset_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+ stmt = cr_statement_parse_from_buf (gv_at_media_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+ stmt = cr_statement_parse_from_buf (gv_at_page_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+ stmt = cr_statement_parse_from_buf (gv_at_charset_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+ stmt = cr_statement_parse_from_buf (gv_at_font_face_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+ stmt = cr_statement_parse_from_buf (gv_at_import_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+
+ return CR_OK;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+ enum CRStatus status = CR_OK;
+
+ status = test_cr_term_parse_expression_from_buf ();
+ if (status != CR_OK) {
+ g_print ("\ntest \"cr_term_parse_expression_from_buf failed\"");
+ }
+ status = test_cr_declaration_parse ();
+ if (status != CR_OK) {
+ g_print ("\n test \"cr_declaration_parse() failed\"\n");
+ }
+
+ status = test_cr_declaration_parse_list ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_declaration_parse_list() failed\n");
+ }
+ status = test_cr_statement_ruleset_parse ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_ruleset_parse() failed\n");
+ }
+
+ status = test_cr_statement_at_media_rule_parse ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_at_media_rule_parse() failed\n");
+ }
+ test_cr_statement_at_page_rule_parse_from_buf ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_at_page_rule_parse() failed\n");
+ return 0;
+ }
+
+ status = test_cr_statement_at_charset_rule_parse ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_at_charset_rule_parse() failed\n");
+ }
+
+ status = test_cr_statement_font_face_rule_parse_from_buf ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_font_face_rule_parse_from_buf() failed\n");
+ }
+
+ test_cr_statement_at_import_rule_parse_from_buf ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_at_import_rule() failed\n");
+ }
+
+ status = test_cr_statement_parse_from_buf ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_parse_from_buf() failed\n");
+ }
+
+ cr_test_utils_parse_cmd_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ status = test_cr_parser_parse ((guchar *) options.files_list[0]);
+ if (status != CR_OK) {
+ g_print ("\nKO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test5-main.c b/src/3rdparty/libcroco/tests/test5-main.c
new file mode 100644
index 0000000..b10d0b8
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test5-main.c
@@ -0,0 +1,255 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include "cr-test-utils.h"
+#include "cr-libxml-node-iface.h"
+#include "libcroco.h"
+
+#include <libxml/tree.h>
+#include <string.h>
+
+/**
+ *@file
+ *Some test facilities for the #CRParser class.
+ */
+
+CRDocHandler *gv_test_handler = { 0 };
+
+const guchar *xml_content =
+ (const guchar *) "<document>"
+ "<E0>text0</E0> "
+ "<E1><E1-1>text1</E1-1></E1>"
+ "<E2 attr2=\"val2\">text2</E2>"
+ "<E3 attr3=\"val3_1 val3_2 val3_3\">text3</E3>"
+ "<E4 attr4=\"val4_1-val4_2-val4_3\">text4</E4>"
+ "<E5 class=\"class5\">text5</E5>"
+ "<E6 id=\"id6\">text6</E6>"
+ "<E7 lang=\"fr\">text7</E7>" "</document>";
+
+static void
+ display_help (char *prg_name);
+
+static void
+ display_about (char *prg_name);
+static enum CRStatus
+ test_sel_eng (guchar * a_file_uri);
+
+static void
+ walk_xml_tree_and_lookup_rules (CRSelEng * a_sel_eng,
+ CRStyleSheet * a_sheet, xmlNode * a_node);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("usage: %s <file-to-parse>\n", prg_name);
+ g_print ("\t <file-to-parse>: the file to parse\n");
+ g_print ("\n\n");
+ g_print ("Test the selection engine");
+ g_print ("Returns OK if the status is CR_OK, KO otherwise\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("%s is a libcroco CROMParser class test program.\n",
+ prg_name);
+ g_print ("%s Parses a file and builds a CSS object model", prg_name);
+ g_print ("It should run on GNU compliants systems.\n");
+ g_print ("\n\n");
+ g_print ("Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ g_print ("\n\n");
+}
+
+static void
+walk_xml_tree_and_lookup_rules (CRSelEng * a_sel_eng,
+ CRStyleSheet * a_sheet, xmlNode * a_node)
+{
+ CRStatement **stmts_tab = NULL;
+ gulong tab_len = 0,
+ i = 0;
+ enum CRStatus status = CR_OK;
+
+ xmlNode *cur_node = a_node;
+
+ for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+ status = cr_sel_eng_get_matched_rulesets
+ (a_sel_eng, a_sheet, cur_node, &stmts_tab, &tab_len);
+
+ if (status == CR_OK && tab_len) {
+ g_print ("'''''''''''''''''''''''''\n");
+ g_print ("xml start element: %s\n", cur_node->name);
+
+ for (i = 0; i < tab_len; i++) {
+ if (stmts_tab[i]) {
+ g_print ("\n");
+ cr_statement_dump (stmts_tab[i],
+ stdout, 2);
+ }
+ }
+ g_print ("\n\nxml end element: %s\n", cur_node->name);
+ g_print ("'''''''''''''''''''''''''\n");
+ }
+
+ if (stmts_tab) {
+ g_free (stmts_tab);
+ stmts_tab = NULL;
+ }
+ if (cur_node->children) {
+ walk_xml_tree_and_lookup_rules
+ (a_sel_eng, a_sheet, cur_node->children);
+ }
+ }
+}
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_sel_eng (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+ CRStyleSheet *stylesheet = NULL;
+ xmlDoc *xml_doc = NULL;
+ xmlNode *cur_node = NULL;
+ CRSelEng *selection_engine = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ parser = cr_om_parser_new (NULL);
+ status = cr_om_parser_parse_file (parser, a_file_uri, CR_ASCII,
+ &stylesheet);
+ if (status != CR_OK || !stylesheet) {
+ cr_utils_trace_info ("Could not parse xml content");
+ goto error;
+ }
+
+ xml_doc = xmlParseMemory ((const char *) xml_content, strlen ((const char *) xml_content));
+ if (!xml_doc) {
+ cr_utils_trace_info ("Could not parse xml content");
+ goto error;
+
+ }
+
+ selection_engine = cr_sel_eng_new (&cr_libxml_node_iface);
+
+ cur_node = xml_doc->children;
+
+ walk_xml_tree_and_lookup_rules (selection_engine,
+ stylesheet, cur_node);
+
+ if (parser) {
+ cr_om_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ if (xml_doc) {
+ xmlFreeDoc (xml_doc);
+ xml_doc = NULL;
+ }
+
+ if (stylesheet) {
+ cr_stylesheet_destroy (stylesheet);
+ stylesheet = NULL;
+ }
+ if (selection_engine) {
+ cr_sel_eng_destroy (selection_engine) ;
+ selection_engine = NULL ;
+ }
+ xmlCleanupParser ();
+ return status;
+
+ error:
+
+ if (parser) {
+ cr_om_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ if (xml_doc) {
+ xmlFreeDoc (xml_doc);
+ xml_doc = NULL;
+ }
+
+ if (stylesheet) {
+ cr_stylesheet_destroy (stylesheet);
+ stylesheet = NULL;
+ }
+
+ xmlCleanupParser ();
+ return CR_ERROR;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+ enum CRStatus status = CR_OK;
+
+ cr_test_utils_parse_cmd_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ status = test_sel_eng ((guchar *) options.files_list[0]);
+
+ if (status != CR_OK) {
+ g_print ("\nKO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test6-main.c b/src/3rdparty/libcroco/tests/test6-main.c
new file mode 100644
index 0000000..4372c5d
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test6-main.c
@@ -0,0 +1,84 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms
+ * of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+#include <string.h>
+#include "libcroco.h"
+#include "cr-test-utils.h"
+
+const guchar *gv_cssbuf =
+ (const guchar *) ".str0 {stroke:#007844;stroke-width:44}" ".fil0 {fill:url(#id0)}";
+
+static enum CRStatus
+ test_cr_parser_parse (void);
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_parser_parse (void)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+ CRStyleSheet *stylesheet = NULL;
+
+ parser = cr_om_parser_new (NULL);
+ status = cr_om_parser_parse_buf (parser, (guchar *) gv_cssbuf,
+ strlen ((const char *) gv_cssbuf),
+ CR_ASCII, &stylesheet);
+
+ if (status == CR_OK && stylesheet) {
+ cr_stylesheet_dump (stylesheet, stdout);
+ cr_stylesheet_destroy (stylesheet);
+ }
+ cr_om_parser_destroy (parser);
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ enum CRStatus status = CR_OK;
+
+ status = test_cr_parser_parse ();
+
+ if (status != CR_OK) {
+ g_print ("\nKO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test7-main.c b/src/3rdparty/libcroco/tests/test7-main.c
new file mode 100644
index 0000000..f740bea
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test7-main.c
@@ -0,0 +1,95 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms
+ * of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <string.h>
+#include "libcroco.h"
+#include "cr-test-utils.h"
+
+const guchar *gv_cssbuf =
+ (const guchar *) ".exp1n1 {stroke-width:4E6}"
+ ".exp1n2 {stroke-width:4e6}"
+ ".exp1n3 {stroke-width:4e+6}"
+ ".exp2n1 {stroke-width:4E-6}"
+ ".exp2n2 {stroke-width:4e-6}"
+ ".exp3n1 {stroke-width:4e6em}"
+ ".exp3n2 {stroke-width:4e6ex}"
+ ".exp3n3 {stroke-width:4e6in}"
+ ".exp4n1 {stroke-width:3.14e4}"
+ ".exp4n2 {stroke-width:3.14e-4}"
+ ".e4n2 {stroke-width:.24e-4}"
+ ".e4n3 {stroke-width:1.e1}"; // This one should be ignored
+
+static enum CRStatus
+ test_cr_parser_parse (void);
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_parser_parse (void)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+ CRStyleSheet *stylesheet = NULL;
+
+ parser = cr_om_parser_new (NULL);
+ status = cr_om_parser_parse_buf (parser, (guchar *) gv_cssbuf,
+ strlen ((const char *) gv_cssbuf),
+ CR_ASCII, &stylesheet);
+
+ if (status == CR_OK && stylesheet) {
+ cr_stylesheet_dump (stylesheet, stdout);
+ // Adding this because my test editor adds a newline character
+ // at the last line, whereas cr_stylesheet_dump doesn't, which
+ // results in a diff error/warning.
+ printf("\n");
+ cr_stylesheet_destroy (stylesheet);
+ }
+ cr_om_parser_destroy (parser);
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ enum CRStatus status = CR_OK;
+
+ status = test_cr_parser_parse ();
+
+ if (status != CR_OK) {
+ g_print ("\nKO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test8-main.c b/src/3rdparty/libcroco/tests/test8-main.c
new file mode 100644
index 0000000..b57c2e4
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test8-main.c
@@ -0,0 +1,44 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2022 Thomas Holder
+ *
+ * SPDX-License-Identifier: GPL-2.1-or-later
+ */
+
+#include "libcroco.h"
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ unsigned i = 0;
+ CRSelector *selector;
+
+ char const *selector_strings[] = {
+ // must not have leading whitespace!?
+ "foo", "foo,bar", "foo , bar ", "foo > bar", ".foo .bar",
+ };
+
+ for (i = 0; i < G_N_ELEMENTS (selector_strings); ++i) {
+ printf ("****************\n");
+ printf ("Parsing '%s'\n", selector_strings[i]);
+
+ selector = cr_selector_parse_from_buf (
+ (guchar const *) selector_strings[i], CR_UTF_8);
+
+ if (!selector) {
+ printf ("is NULL\n");
+ } else {
+ cr_selector_dump (selector, stdout);
+ cr_selector_unref (selector);
+ printf ("\n");
+ }
+ }
+
+ return 0;
+}
+
+// vi:sw=8:expandtab
diff --git a/src/3rdparty/libcroco/tests/testctl b/src/3rdparty/libcroco/tests/testctl
new file mode 100755
index 0000000..205112b
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/testctl
@@ -0,0 +1,462 @@
+#! /bin/sh
+
+#####################################
+#This script just runs the tests of
+#libcroco, saves their result, diff them
+#against a set of reference results and
+#displays OK/KO.
+#To use it as a tester, the best way is
+#just to run 'testctl run' and see the result.
+####################################
+
+#the directory that contains the tests sources is:
+#$TEST_SOURCE_DIR. User can set this var in the environment
+#before calling this script. Otherwise, we set it to a default value
+if test x$TEST_SOURCE_DIR = x ; then
+ TEST_SOURCE_DIR=`dirname "$0"`
+fi
+
+#the directory that contains the test outputs is:
+#$TEST_OUT_DIR
+#User can set this var in the environment before
+#calling this script. Otherwise, we set it to a default value.
+if test x$TEST_OUT_DIR = x ; then
+ TEST_OUT_DIR=tests
+fi
+
+if [ -d "$TEST_OUT_DIR/.libs" ]; then
+ TEST_BIN_DIR="$TEST_OUT_DIR/.libs"
+else
+ TEST_BIN_DIR="$TEST_OUT_DIR"
+fi
+
+#the list of tests to be run
+TEST_PROG_LIST=
+
+#the test input dirs.
+TEST_INPUT_DIR=test-inputs
+
+#the reference test output dirs.
+TEST_OUT_REF_DIR=test-output-refs
+
+#temporary test result dir
+TEST_OUTPUT_DIR=test-outputs
+
+ERROR_REPORT_FILE=tests-error.log
+COMMAND_LIST=
+COMMAND=
+if test x$RUN_VALGRIND = x ; then
+ RUN_VALGRIND=no
+else
+ RUN_VALGRIND=yes
+fi
+if test "x$CHECKER" = "x" ; then
+ CHECKER="valgrind --tool=memcheck"
+fi
+
+VALGRIND_LOGS_DIR=valgrind-logs
+VALGRIND=
+TEST_PROG=
+EGREP="grep -E"
+
+DIFF=`which diff`
+if test "empty$DIFF" = "empty" ; then
+ echo "You don't have the diff program installed"
+ echo "Please, install is first"
+fi
+
+display_usage ()
+{
+ echo ""
+ echo "usage: $0 [general options] <command> [command option]"
+ echo ""
+ echo "where general options are:"
+ echo "===================="
+ echo "-h|--help displays this help"
+ echo ""
+ echo "commands are:"
+ echo "=============="
+ echo "run run the tests and display their result"
+ echo "ref run the tests but saves their output as a reference"
+ echo "cleanup removes the tmp directories that may have been created"
+ echo ""
+ echo "run command options:"
+ echo "--valgrind runs the test using valgrind"
+ echo "--testprog <test program>"
+}
+
+parse_command_line ()
+{
+ if test "empty$1" = "empty" ; then
+ display_usage ;
+ exit -1
+ fi
+
+ while true ; do
+ arg=$1
+
+ if test "empty$arg" = "empty" ; then
+ break ;
+ fi
+
+ case "$arg" in
+ -h|--help)
+ display_usage $@
+ exit 0
+ ;;
+
+ -*)
+ echo "$0: unknown option: $arg"
+ display_usage $@
+ exit 0
+ ;;
+
+ run|ref|cleanup)
+ COMMAND_LIST=$arg
+ REMAINING_ARGS=$@
+ echo "REMAINING_ARGS=$REMAINING_ARGS"
+ break ;
+ ;;
+
+ *)
+ display_usage $@
+ exit 0
+ ;;
+ esac
+ done
+}
+
+
+#builds the list of available test functions.
+build_tests_list ()
+{
+ for TEST_PROG in "$TEST_SOURCE_DIR"/test*.sh "$TEST_OUT_DIR"/test?; do
+ TEST_PROG=`basename $TEST_PROG`
+ echo "run test: $TEST_PROG"
+ TEST_PROG_LIST="$TEST_PROG_LIST $TEST_PROG"
+ done
+}
+
+#runs a test programs.
+#usage run_test_prog <test-name> <reference> <display-on-stdout>
+#where "test-name" is the name of the test program to run
+#"reference" is a boolean value: yes/no. (the string "yes" or the string no)
+#if yes, means that the output of the test is to be saved as a reference.
+#if no, means that the output of the test is to be saved as a result of a test.
+run_test_prog ()
+{
+ TEST_PROG="$1"
+ REFERENCE="$2"
+ DISPLAY_ON_STDOUT="$3"
+ OUTPUT_DIR=
+ OUTPUT_SUFFIX=
+ TEST_INPUT_LIST=
+ VALGRIND_OPTIONS="--error-limit=no --num-callers=100 --logfile=$TEST_OUT_DIR/$VALGRIND_LOGS_DIR/$TEST_PROG-valgrind.log --leak-check=yes --show-reachable=yes --quiet --suppressions=$TEST_SOURCE_DIR/vg.supp"
+ if test x$RUN_VALGRIND = xno ; then
+ VALGRIND=
+ else
+ if ! test -x "$TEST_SOURCE_DIR"/valgrind-version.sh ; then
+ echo "Argh! Could not find file $TEST_SOURCE_DIR/valgrind-version.sh"
+ exit -1 ;
+ fi
+ version=`"$TEST_SOURCE_DIR"/valgrind-version.sh`
+ if ! test "x$version" = "xokay" ; then
+ echo "You must install a valgrind version greater than 2.1.1"
+ echo "version=$version"
+ exit -1
+ fi
+ if test "x$CHECKER" = "x" ; then
+ VALGRIND=`which valgrind`
+ if test "x$VALGRIND" = x ; then
+ echo "Could not find valgrind in your path"
+ else
+ VALGRIND="$VALGRIND $VALGRIND_OPTIONS"
+ echo "Gonna run the tests with valgrind, using the following options: $VALGRIND_OPTIONS"
+ fi
+ else
+ VALGRIND="$CHECKER $VALGRIND_OPTIONS"
+ echo "Gonna run the tests with valgrind, using the cmd line: $VALGRIND"
+ fi
+ fi
+ export VALGRIND
+ case "$TEST_PROG" in
+ *.sh) is_shell_script=yes ;;
+ *) is_shell_script=no ;;
+ esac
+
+ if ! test -d "$TEST_OUT_DIR/$VALGRIND_LOGS_DIR" ; then
+ mkdir "$TEST_OUT_DIR/$VALGRIND_LOGS_DIR"
+ fi
+
+ for TEST_INPUT in `ls -1 "$TEST_SOURCE_DIR/$TEST_INPUT_DIR" | $EGREP "^${TEST_PROG}"'[.0-9]+css$'` ; do
+ TEST_INPUT_LIST="$TEST_INPUT_LIST $TEST_INPUT"
+ done
+
+ if test "$REFERENCE" = "yes" ; then
+ OUTPUT_DIR="$TEST_SOURCE_DIR/$TEST_OUT_REF_DIR"
+ OUTPUT_SUFFIX=.out
+ else
+ OUTPUT_DIR="$TEST_OUT_DIR/$TEST_OUTPUT_DIR"
+ OUTPUT_SUFFIX=.out
+ if test ! -d "$OUTPUT_DIR" ; then
+ echo "creating tmp directory $OUTPUT_DIR ..."
+ mkdir "$OUTPUT_DIR"
+ echo "done"
+ fi
+ fi
+
+ if test "empty$TEST_INPUT_LIST" != "empty" ; then
+ for TEST_INPUT in $TEST_INPUT_LIST ; do
+ TEST_INPUT_NAME=`basename $TEST_INPUT .sh`
+ if test "$DISPLAY_ON_STDOUT" = "yes" ; then
+ echo "###############################################"
+ echo "launching $VALGRIND $TEST_PROG $TEST_SOURCE_DIR/$TEST_INPUT_DIR/$TEST_INPUT"....
+ echo "###############################################"
+ if test x$is_shell_script = xyes ; then
+ "$TEST_SOURCE_DIR/$TEST_PROG" "$TEST_SOURCE_DIR/$TEST_INPUT_DIR/$TEST_INPUT"
+ else
+ $VALGRIND "$TEST_BIN_DIR/$TEST_PROG" "$TEST_SOURCE_DIR/$TEST_INPUT_DIR/$TEST_INPUT"
+ fi
+ echo "###############################################"
+ echo "done"
+ echo "###############################################"
+ echo ""
+ else
+ echo "executing $VALGRIND $TEST_PROG $TEST_SOURCE_DIR/$TEST_INPUT_DIR/$TEST_INPUT > $OUTPUT_DIR/${TEST_INPUT_NAME}${OUTPUT_SUFFIX} ..."
+ $VALGRIND "$TEST_BIN_DIR/$TEST_PROG" "$TEST_SOURCE_DIR/$TEST_INPUT_DIR/$TEST_INPUT" > "$OUTPUT_DIR/${TEST_INPUT_NAME}${OUTPUT_SUFFIX}"
+ echo "done"
+ fi
+ done
+ else
+ if test "$DISPLAY_ON_STDOUT" = "yes" ; then
+ echo "####################################################"
+ echo "launching $VALGRIND $TEST_PROG ..."
+ echo "####################################################"
+ if test x$is_shell_script = xyes ; then
+ "$TEST_SOURCE_DIR/$TEST_PROG"
+ else
+ $VALGRIND "$TEST_BIN_DIR/$TEST_PROG"
+ fi
+ echo "####################################################"
+ echo "done"
+ echo "####################################################"
+ echo ""
+ else
+ TEST_INPUT_NAME=`basename "$TEST_PROG" .sh`
+ echo "executing $VALGRIND $TEST_PROG > $OUTPUT_DIR/${TEST_PROG}${OUTPUT_SUFFIX} ..."
+ if test x$is_shell_script = xyes ; then
+ "$TEST_SOURCE_DIR/$TEST_PROG" > "$OUTPUT_DIR/${TEST_INPUT_NAME}${OUTPUT_SUFFIX}"
+ else
+ $VALGRIND "$TEST_BIN_DIR/$TEST_PROG" > "$OUTPUT_DIR/${TEST_INPUT_NAME}${OUTPUT_SUFFIX}"
+ fi
+ echo "done"
+ fi
+ fi
+ unset VALGRIND
+}
+
+cleanup_tests ()
+{
+ if test -d "$TEST_OUT_DIR/$TEST_OUTPUT_DIR" ; then
+ echo "removing $TEST_OUT_DIR/$TEST_OUTPUT_DIR/*"
+ rm -rf "$TEST_OUT_DIR/$TEST_OUTPUT_DIR"
+ rm -rf "$TEST_OUT_DIR/$VALGRIND_LOGS_DIR"
+ fi
+ if test -f "$TEST_OUT_DIR/$ERROR_REPORT_FILE" ; then
+ rm "$TEST_OUT_DIR/$ERROR_REPORT_FILE"
+ fi
+ return 0
+}
+
+run_test_report ()
+{
+ code=0
+ diff -ur --exclude='*CVS*' --exclude='*cvs*' --exclude='Makefile*' --exclude=.arch-ids "$TEST_SOURCE_DIR/$TEST_OUT_REF_DIR" "$TEST_OUT_DIR/$TEST_OUTPUT_DIR" > "$TEST_OUT_DIR/tmpdiff.$$"
+ NB_DIFF=`wc -l < "$TEST_OUT_DIR/tmpdiff.$$"`
+
+ if test "$NB_DIFF" -eq 0 ; then
+ echo "/////////////ALL THE TESTS ARE OK :) //////////////////"
+ rm "$TEST_OUT_DIR/tmpdiff.$$"
+ else
+ echo "SOME TESTS ARE KO :("
+ mv "$TEST_OUT_DIR/tmpdiff.$$" "$TEST_OUT_DIR/$ERROR_REPORT_FILE"
+ echo "See $TEST_OUT_DIR/$ERROR_REPORT_FILE to see what's going on"
+ code=1
+ fi
+
+ ###################
+ #Valgrind errors #
+ ###################
+ memleaks=no
+ for vg_log in `find "$TEST_OUT_DIR/$VALGRIND_LOGS_DIR" -name '*-valgrind.log*' -print` ; do
+ if test -s "$vg_log" ; then
+ leaks=`cat "$vg_log" | grep -i leak | grep -v no`
+ errors=`cat "$vg_log" | grep -w Invalid`
+ if test "x$leaks" = "x" -a "x$errors" = "x" ; then
+ rm -f "$vg_log" ;
+ else
+ echo "valgrind reported some memory leaks/corruptions in $vg_log"
+ memleaks=yes
+ fi
+ else
+ rm "$vg_log"
+ fi
+ done
+ if test "x$RUN_VALGRIND" = "xyes" ; then
+ if test "x$memleaks" = "xno" ; then
+ echo "Oh, YESSSSSS!, VALGRIND DID NOT DETECT ANY MEMLEAK !! You can go have a beer."
+ else
+ echo "Please report these leaks by sending the valgrind logs to the authors of libcroco."
+ code=2
+ fi
+ fi
+ return $code
+}
+
+run_test_report_single ()
+{
+ TEST_BASE=`basename "$1" .sh`
+ code=0
+ for reffile in "$TEST_SOURCE_DIR/$TEST_OUT_REF_DIR/$TEST_BASE".*; do
+ outfile="$TEST_OUT_DIR/$TEST_OUTPUT_DIR/`basename "$reffile"`"
+ diff -u "$reffile" "$outfile" || code=1
+ done
+ if [ $code -ne 0 ]; then
+ echo "TEST $TEST_BASE IS KO :("
+ fi
+ return $code
+}
+
+############################
+#Executes the "run" command along with
+#its command options.
+#For the sake of safety checking
+############################
+execute_run_cmd ()
+{
+ args=$@
+ test_and_report=no
+
+ if test "$1" != "run" ; then
+ echo "internal error: first argument should be \'run\'"
+ return
+ fi
+ shift
+
+ while true ; do
+ cur_arg=$1
+ echo "cur_arg=$cur_arg"
+
+ case $cur_arg in
+ --valgrind)
+ RUN_VALGRIND=yes
+ shift
+ ;;
+
+ "--testprog")
+ shift
+ if test "empty$1" = "empty" ; then
+ echo "--testprog should be followed by a prog name"
+ display_usage
+ exit
+ fi
+ TEST_PROG=$1
+ echo "TEST_PROG=$TEST_PROG"
+ shift
+ ;;
+
+ "--test-and-report")
+ test_and_report=yes
+ shift
+ TEST_PROG="$1"
+ shift
+ if test -z "$TEST_PROG"; then
+ echo "--test-and-report must be followed by a prog name"
+ exit
+ fi
+ ;;
+
+ *)
+ break
+ ;;
+ esac
+ done
+
+ if test "empty$TEST_PROG" = "empty"; then
+
+ cleanup_tests
+
+ build_tests_list ;
+ if test "empty$TEST_PROG_LIST" = "empty" ; then
+ echo "could not find any test to run"
+ exit
+ fi
+
+ for TEST in $TEST_PROG_LIST ; do
+ run_test_prog "$TEST" no no;
+ done
+ run_test_report ;
+ elif test "$test_and_report" = "yes"; then
+ run_test_prog "$TEST_PROG"
+ run_test_report_single "$TEST_PROG"
+ else
+ #run the test and display result on stdout
+ run_test_prog "$TEST_PROG" no yes ;
+ fi
+}
+
+##############################
+#Analyzes a command string "<command> [command option]"
+#and runs the necessary commands.
+#
+#Must be called with the command line
+#starting with a command name.
+#all the previous general argument must
+#have been stripped away.
+#############################
+execute_command ()
+{
+ arg="$1" ;
+
+ case "$arg" in
+
+ run)
+ execute_run_cmd "$@"
+ ;;
+
+ ref)
+ build_tests_list ;
+ if test "empty$TEST_PROG_LIST" = "empty" ; then
+ echo "could not find any test to run"
+ exit
+ fi
+
+ for TEST in $TEST_PROG_LIST ; do
+ run_test_prog "$TEST" yes no;
+ done
+ ;;
+
+ cleanup)
+ cleanup_tests
+ ;;
+
+ *)
+ echo "unknown command"
+ exit ;
+ esac
+
+}
+
+main ()
+{
+ parse_command_line $@
+
+ if test "empty$COMMAND_LIST" = "empty" ; then
+ echo "no test command to execute"
+ exit
+ fi
+
+ execute_command $REMAINING_ARGS
+}
+
+main $@
diff --git a/src/3rdparty/libcroco/tests/valgrind-version.sh b/src/3rdparty/libcroco/tests/valgrind-version.sh
new file mode 100755
index 0000000..55cbfc2
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/valgrind-version.sh
@@ -0,0 +1,48 @@
+#! /bin/sh
+
+valgrind=`which valgrind`
+awk=`which awk`
+if test "x$valgrind" = "x" ; then
+ echo "valgrind-not-present" ;
+ exit ;
+fi
+
+
+valgrind_version=`$valgrind --version`
+if test "x$valgrind_version" = x ; then
+ echo "not-present" ;
+ exit
+fi
+
+if test "x$awk" = x ; then
+ echo "awk-not-present"
+ exit
+fi
+
+string_version=`echo $valgrind_version | $awk -F '-' '{print $2}'`
+
+if test "x$string_version" = "x" ; then
+ echo "valgrind-version-unknown"
+ exit
+fi
+
+major=`echo $string_version | $awk -F '.' '{print $1}'`
+minor=`echo $string_version | $awk -F '.' '{print $2}'`
+micro=`echo $string_version | $awk -F '.' '{print $3}'`
+
+version=`expr $major \* 10000 + $minor \* 100 + $micro`
+
+if test "x$version" = "x" ; then
+ echo "valgrind-version-unknown"
+ exit ;
+fi
+
+if test "$version" -ge "20101" ; then
+ echo "okay"
+ exit ;
+else
+ echo "valgrind-version-lower"
+ exit ;
+fi
+
+
diff --git a/src/3rdparty/libcroco/tests/valgrind.log b/src/3rdparty/libcroco/tests/valgrind.log
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/valgrind.log
diff --git a/src/3rdparty/libcroco/tests/vg b/src/3rdparty/libcroco/tests/vg
new file mode 100755
index 0000000..b1f2c00
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/vg
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+###
+#
+###
+
+OUTPUT_FILE=valgrind.log
+VG=`which valgrind`
+VG_OPTIONS="-q --num-callers=100 --leak-check=yes --show-reachable=yes"
+
+#Some sanity checks
+if test "empty$VG" = "empty" ; then
+ echo "You should install valgrind and set it binary into your"
+ echo "\$PATH env variable"
+ echo "go to http://developer.kde.org/~sewardj/ to download valgrind"
+ exit
+fi
+
+
+if test "empty$1" != "empty" ; then
+ OUTPUT_FILE="$1".vg
+fi
+
+exec $VG $VG_OPTIONS $@ 2>"$OUTPUT_FILE" \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/vg.supp b/src/3rdparty/libcroco/tests/vg.supp
new file mode 100644
index 0000000..5a3d109
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/vg.supp
@@ -0,0 +1,57 @@
+{
+ g_print_ALLOC_LEAK
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:g_realloc
+ fun:g_array_maybe_expand
+ fun:g_array_set_size
+ fun:g_static_private_set
+ fun:g_get_charset
+ fun:g_print
+}
+
+{
+ g_slist_prepend_LEAK
+ Memcheck:Leak
+ fun:calloc
+ fun:g_malloc0
+ fun:g_allocator_new
+ fun:_g_slist_alloc
+ fun:g_slist_prepend
+}
+
+{
+ g_print_CONVERT_LEAK
+ Memcheck:Leak
+ fun:malloc
+ obj:*libc-2.3.3.so
+ fun:iconv_open
+ fun:try_conversion
+ fun:g_iconv_open
+ fun:open_converter
+ fun:g_convert
+ fun:g_convert_with_fallback
+ fun:strdup_convert
+ fun:g_print
+}
+
+{
+ g_string_new_CHUNCK_LEAK
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_mem_chunk_new
+ fun:g_string_sized_new
+ fun:g_string_new
+}
+
+{
+ g_list_prepend_LEAK
+ Memcheck:Leak
+ fun:calloc
+ fun:g_malloc0
+ fun:g_allocator_new
+ fun:_g_list_alloc
+ fun:g_list_prepend
+}
diff --git a/src/3rdparty/libcroco/win32/Makefile-newvs.am b/src/3rdparty/libcroco/win32/Makefile-newvs.am
new file mode 100644
index 0000000..3a91862
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/Makefile-newvs.am
@@ -0,0 +1,55 @@
+# Centralized autotools file
+# Create the Visual Studio 2012/2013/2015 project files
+# from the Visual Studio 2010 project files
+
+# This autotools file, from GLib, can be used in other projects
+# that have Visual Studio build support.
+
+# Author: Fan, Chun-wei
+# November 05, 2012
+
+# MSVC_BASE_VER: Baseline MSVC 201x version to copy/process project files from (100 for 2010, 120 for 2013)
+# MSVC_BASE_VER_LONG: Long Version of baseline Visual Studio 201x version (2010, 2012, 2013, 14, 15)
+# MSVC_BASE_TOOLSET: Use if baseline MSVC toolset is not in the form v$(MSVC_BASE_VER)0, meaning v$(MSVC_BASE_TOOLSET)
+# MSVC_VER_LONG: Long Version of target Visual Studio (2012, 2013, 14 and so on)
+# MSVC_VER: Short Version of target Visual Studio (110 for 2012, 120 for 2013, 140 for 2015, 141 for 2017)
+# MSVC_TOOLSET: Use if target MSVC toolsett is not in the form v $(MSVC_VER)0, meaning v$(MSVC_TOOLSET)
+
+if MSVC_BASE_NO_TOOLSET_SET
+MSVC_BASE_TOOLSET = $(MSVC_BASE_VER)0
+endif
+
+if MSVC_NO_TOOLSET_SET
+MSVC_TOOLSET = $(MSVC_VER)0
+endif
+
+%.sln:
+ sed 's/11\.00/12\.00/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp
+ sed 's/$(MSVC_BASE_VER_LONG)/$(MSVC_VER_LONG)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@
+ rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp
+
+%.txt:
+ sed 's/vs$(MSVC_BASE_VER)/vs$(MSVC_VER)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp
+ sed 's/VS$(MSVC_BASE_VER)/VS$(MSVC_VER)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@
+ rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp
+
+%.vcxproj:
+ if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \
+ sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ else \
+ sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ fi
+
+%.props: $(top_builddir)/win32/vs$(MSVC_BASE_VER)/Makefile
+ if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \
+ sed 's/<VSVer>$(MSVC_BASE_VER)<\/VSVer>/<VSVer>$(MSVC_VER)<\/VSVer>/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ else \
+ sed 's/<VSVer>$(MSVC_BASE_VER)<\/VSVer>/<VSVer>$(MSVC_VER)<\/VSVer>/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ fi
+
+%.vcxproj.filters:
+ if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \
+ cp $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ else \
+ cp $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ fi
diff --git a/src/3rdparty/libcroco/win32/Makefile.am b/src/3rdparty/libcroco/win32/Makefile.am
new file mode 100644
index 0000000..d3cb159
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/Makefile.am
@@ -0,0 +1,22 @@
+#This file is part of The Croco Library
+#This program is free software; you can redistribute it and/or
+#modify it under the terms of version 2.1 of the GNU Lesser General Public
+#License as published by the Free Software Foundation.
+
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU Lesser General Public License
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+#USA
+
+#Author: Fan, Chun-wei
+#See COPYRIGHTS file for copyright information.
+
+SUBDIRS = vs9 vs10 vs11 vs12 vs14 vs15 vs16
+
+EXTRA_DIST = crocopc.py pc_base.py replace.py
+
diff --git a/src/3rdparty/libcroco/win32/Makefile.msvcproj b/src/3rdparty/libcroco/win32/Makefile.msvcproj
new file mode 100644
index 0000000..5224ba0
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/Makefile.msvcproj
@@ -0,0 +1,153 @@
+# Author: Fan, Chun-wei
+# Common Autotools file used to generate Visual Studio 2008+
+# Projects from their templates
+
+# This autotools file, from GLib, can be used in other projects
+# that have Visual Studio build support.
+
+# * Input variables:
+#
+# MSVCPROJS - List of Projects that should be generated
+#
+# * Simple tutorial
+#
+# Add this to Makefile.am where your library/program is built:
+# include <this Makefile.msvcproj>
+# MSVCPROJS = YourProject (can be multiple projects in a single srcdir)
+# YourProject_FILES = $(libyourlib_1_0_SOURCES)
+# YourProject_EXCLUDES = ... # list of sources to exclude, separated by '|', wildcards allowed; use random unused value if none
+# (the following 3 lines if headers need to be installed)
+# YourProject_HEADERS_DIR = $(libyourlibincludedir)
+# YourProject_HEADERS_INST = $(libyourlib_1_0_HEADERS)
+# YourProject_HEADERS_EXCLUDES = ... # <list of headers to exclude from installation, separated by '|', wildcards allowed; use random unused value if none>
+#
+# dist-hook: \ # (or add to it if it is already there, note the vs9 items will also call the vs10 items in the process)
+# $(top_builddir)/win32/vs9/YourProject.vcproj \
+# $(top_builddir)/win32/vs9/YourProject.headers # if headers need to be installed
+#
+# --or, if Visual Studio 2013 or later is required--
+# dist-hook: \ # (or add to it if it is already there, this does -not- call other vs items in the process)
+# $(top_builddir)/win32/vs12/YourProject.vcxproj \
+# $(top_builddir)/win32/vs12/YourProject.vs12.headers # if headers need to be installed
+
+# Private functions
+
+## Transform the MSVC project filename (no filename extensions) to something which can reference through a variable
+## without automake/make complaining, eg Gtk-2.0 -> Gtk_2_0
+_proj_name=$(subst /,_,$(subst -,_,$(subst .,_,$(1))))
+_proj_path_raw:=$(subst $(abs_top_srcdir),,$(abs_srcdir))
+_proj_path=$(subst /,\\,$(_proj_path_raw))
+_proj_subdir_int=$(subst \\\\,\\,\\$(_proj_path)\\)
+_proj_subdir=$(subst \\.\\,\\,$(_proj_subdir_int))
+
+_proj_files_raw=$(subst /,\\,$($(_proj_name)_FILES))
+_proj_files=$(subst $(srcdir)\\,,$(subst $(builddir)\\,,$(subst $(top_builddir)\\$(_proj_path)\\,\\,$(_proj_files_raw))))
+_proj_filters=$($(_proj_name)_EXCLUDES)
+
+_proj_headers_raw=$(subst /,\\,$($(_proj_name)_HEADERS_INST))
+_proj_headers=$(subst $(srcdir)\\,,$(subst $(builddir)\\,,$(subst $(top_builddir)\\$(_proj_path)\\,\\,$(_proj_headers_raw))))
+_proj_headers_excludes=$($(_proj_name)_HEADERS_EXCLUDES)
+
+_headers_dest_posix=$(subst $(includedir),,$($(_proj_name)_HEADERS_DIR))
+_headers_destdir=$(subst /,\\,$(_headers_dest_posix))
+
+#
+# Creates Visual Studio 2008/2010 projects from items passed in from autotools files
+# $(1) - Base Name of the MSVC project files (outputs)
+#
+
+define msvcproj-builder
+
+$(top_builddir)/win32/vs10/$(1).vcxproj: $(top_builddir)/win32/vs9/$(1).vcproj
+$(top_builddir)/win32/vs10/$(1).vcxproj.filters: $(top_builddir)/win32/vs9/$(1).vcproj
+$(1).sourcefiles: $(top_builddir)/win32/vs9/$(1).vcproj
+$(1).vs10.sourcefiles: $(top_builddir)/win32/vs9/$(1).vcproj
+$(1).vs10.sourcefiles.filters: $(top_builddir)/win32/vs9/$(1).vcproj
+
+$(top_builddir)/win32/vs9/$(1).vcproj: Makefile
+ -$(RM) $(top_builddir)/win32/vs9/$(1).vcproj
+ -$(RM) $(top_builddir)/win32/vs10/$(1).vcxproj
+ -$(RM) $(top_builddir)/win32/vs10/$(1).vcxproj.filters
+ -$(RM) $(top_builddir)/win32/vs11/$(1).vcxproj
+ -$(RM) $(top_builddir)/win32/vs11/$(1).vcxproj.filters
+ -$(RM) $(top_builddir)/win32/vs12/$(1).vcxproj
+ -$(RM) $(top_builddir)/win32/vs12/$(1).vcxproj.filters
+ -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj
+ -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj.filters
+
+
+ for F in $(_proj_files); do \
+ case $$$$F in \
+ $(_proj_filters)) \
+ ;; \
+ *.c|*.cpp|*.cc|*.cxx) \
+ echo ' <File RelativePath="..\..'$(_proj_subdir)$$$$F'" />' >>$(1).sourcefiles && \
+ echo ' <ClCompile Include="..\..'$(_proj_subdir)$$$$F'" />' >>$(1).vs10.sourcefiles && \
+ echo ' <ClCompile Include="..\..'$(_proj_subdir)$$$$F'"><Filter>Source Files</Filter></ClCompile>' >>$(1).vs10.sourcefiles.filters \
+ ;; \
+ esac; \
+ done
+
+
+ $(CPP) -P - <$(top_srcdir)/win32/vs9/$(1).vcprojin >$(top_builddir)/win32/vs9/$(1).vcproj
+ $(CPP) -P - <$(top_srcdir)/win32/vs10/$(1).vcxprojin >$(top_builddir)/win32/vs10/$(1).vcxproj
+ $(CPP) -P - <$(top_srcdir)/win32/vs10/$(1).vcxproj.filtersin >$(top_builddir)/win32/vs10/$(1).vcxproj.filters
+ $(RM) $(1).sourcefiles
+ $(RM) $(1).vs10.sourcefiles
+ $(RM) $(1).vs10.sourcefiles.filters
+
+$(top_builddir)/win32/vs10/$(1).vs10.headers: $(top_builddir)/win32/vs9/$(1).headers
+
+$(top_builddir)/win32/vs9/$(1).headers: Makefile
+ -$(RM) $(top_builddir)/win32/vs9/$(1).headers
+ -$(RM) $(top_builddir)/win32/vs10/$(1).vs10.headers
+
+ for F in $(_proj_headers); do \
+ case $$$$F in \
+ $(_proj_headers_excludes)) \
+ ;; \
+ *.h|*.hpp|*.hh|*.hxx) \
+ echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F'&#x0D;&#x0A;' >>$(top_builddir)/win32/vs9/$(1).headers && \
+ echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F >>$(top_builddir)/win32/vs10/$(1).vs10.headers \
+ ;; \
+ esac; \
+ done
+
+$(top_builddir)/win32/vs12/$(1).vcxproj.filters: $(top_builddir)/win32/vs12/$(1).vcxproj
+
+$(top_builddir)/win32/vs12/$(1).vcxproj: Makefile
+ -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj
+ -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj.filters
+
+ for F in $(_proj_files); do \
+ case $$$$F in \
+ $(_proj_filters)) \
+ ;; \
+ *.c|*.cpp|*.cc|*.cxx) \
+ echo ' <ClCompile Include="..\..'$(_proj_subdir)$$$$F'" />' >>$(1).vs12.sourcefiles && \
+ echo ' <ClCompile Include="..\..'$(_proj_subdir)$$$$F'"><Filter>Source Files</Filter></ClCompile>' >>$(1).vs12.sourcefiles.filters \
+ ;; \
+ esac; \
+ done
+
+ $(CPP) -P - <$(top_srcdir)/win32/vs12/$(1).vcxprojin >$(top_builddir)/win32/vs12/$(1).vcxproj
+ $(CPP) -P - <$(top_srcdir)/win32/vs12/$(1).vcxproj.filtersin >$(top_builddir)/win32/vs12/$(1).vcxproj.filters
+ $(RM) $(1).vs12.sourcefiles
+ $(RM) $(1).vs12.sourcefiles.filters
+
+$(top_builddir)/win32/vs12/$(1).vs12.headers: Makefile
+ -$(RM) $(top_builddir)/win32/vs12/$(1).vs12.headers
+
+ for F in $(_proj_headers); do \
+ case $$$$F in \
+ $(_proj_headers_excludes)) \
+ ;; \
+ *.h|*.hpp|*.hh|*.hxx) \
+ echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F >>$(top_builddir)/win32/vs12/$(1).vs12.headers \
+ ;; \
+ esac; \
+ done
+
+endef
+
+$(foreach proj,$(MSVCPROJS),$(eval $(call msvcproj-builder,$(proj))))
diff --git a/src/3rdparty/libcroco/win32/crocopc.py b/src/3rdparty/libcroco/win32/crocopc.py
new file mode 100644
index 0000000..9263ac4
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/crocopc.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+#
+# Utility script to generate .pc files for GLib
+# for Visual Studio builds, to be used for
+# building introspection files
+
+# Author: Fan, Chun-wei
+# Date: March 10, 2016
+
+import os
+import sys
+
+from replace import replace_multi
+from pc_base import BasePCItems
+
+def main(argv):
+ base_pc = BasePCItems()
+
+ base_pc.setup(argv)
+ croco_version = base_pc.version.split('.')
+ pkg_replace_items = {'@LIBCROCO_MAJOR_VERSION@': croco_version[0],
+ '@LIBCROCO_MINOR_VERSION@': croco_version[1]}
+
+ pkg_replace_items.update(base_pc.base_replace_items)
+
+ # Generate libcroco-x.y.pc
+ replace_multi(base_pc.top_srcdir + '/libcroco.pc.in',
+ base_pc.srcdir + '/libcroco-' + croco_version[0] +
+ '.' + croco_version[1] + '.pc',
+ pkg_replace_items)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/src/3rdparty/libcroco/win32/pc_base.py b/src/3rdparty/libcroco/win32/pc_base.py
new file mode 100644
index 0000000..f7976e8
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/pc_base.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+#
+# Simple utility script to generate the basic info
+# needed in a .pc (pkg-config) file, used especially
+# for introspection purposes
+
+# This can be used in various projects where
+# there is the need to generate .pc files,
+# and is copied from GLib's $(srcroot)/win32
+
+# Author: Fan, Chun-wei
+# Date: March 10, 2016
+
+import os
+import sys
+import argparse
+
+class BasePCItems:
+ def __init__(self):
+ self.base_replace_items = {}
+ self.exec_prefix = ''
+ self.includedir = ''
+ self.libdir = ''
+ self.prefix = ''
+ self.srcdir = os.path.dirname(__file__)
+ self.top_srcdir = self.srcdir + '\\..'
+ self.version = ''
+
+ def setup(self, argv, parser=None):
+ if parser is None:
+ parser = argparse.ArgumentParser(description='Setup basic .pc file info')
+ parser.add_argument('--prefix', help='prefix of the installed library',
+ required=True)
+ parser.add_argument('--exec-prefix',
+ help='prefix of the installed programs, \
+ if different from the prefix')
+ parser.add_argument('--includedir',
+ help='includedir of the installed library, \
+ if different from ${prefix}/include')
+ parser.add_argument('--libdir',
+ help='libdir of the installed library, \
+ if different from ${prefix}/lib')
+ parser.add_argument('--version', help='Version of the package',
+ required=True)
+ args = parser.parse_args()
+
+ self.version = args.version
+
+ # check whether the prefix and exec_prefix are valid
+ if not os.path.exists(args.prefix):
+ raise SystemExit('Specified prefix \'%s\' is invalid' % args.prefix)
+
+ # use absolute paths for prefix
+ self.prefix = os.path.abspath(args.prefix).replace('\\','/')
+
+ # check and setup the exec_prefix
+ if getattr(args, 'exec_prefix', None) is None:
+ exec_prefix_use_shorthand = True
+ self.exec_prefix = '${prefix}'
+ else:
+ if args.exec_prefix.startswith('${prefix}'):
+ exec_prefix_use_shorthand = True
+ input_exec_prefix = args.prefix + args.exec_prefix[len('${prefix}'):]
+ else:
+ exec_prefix_use_shorthand = False
+ input_exec_prefix = args.exec_prefix
+ if not os.path.exists(input_exec_prefix):
+ raise SystemExit('Specified exec_prefix \'%s\' is invalid' %
+ args.exec_prefix)
+ if exec_prefix_use_shorthand is True:
+ self.exec_prefix = args.exec_prefix.replace('\\','/')
+ else:
+ self.exec_prefix = os.path.abspath(input_exec_prefix).replace('\\','/')
+
+ # check and setup the includedir
+ if getattr(args, 'includedir', None) is None:
+ self.includedir = '${prefix}/include'
+ else:
+ if args.includedir.startswith('${prefix}'):
+ includedir_use_shorthand = True
+ input_includedir = args.prefix + args.includedir[len('${prefix}'):]
+ else:
+ if args.includedir.startswith('${exec_prefix}'):
+ includedir_use_shorthand = True
+ input_includedir = input_exec_prefix + args.includedir[len('${exec_prefix}'):]
+ else:
+ includedir_use_shorthand = False
+ input_includedir = args.includedir
+ if not os.path.exists(input_includedir):
+ raise SystemExit('Specified includedir \'%s\' is invalid' %
+ args.includedir)
+ if includedir_use_shorthand is True:
+ self.includedir = args.includedir.replace('\\','/')
+ else:
+ self.includedir = os.path.abspath(input_includedir).replace('\\','/')
+
+ # check and setup the libdir
+ if getattr(args, 'libdir', None) is None:
+ self.libdir = '${prefix}/lib'
+ else:
+ if args.libdir.startswith('${prefix}'):
+ libdir_use_shorthand = True
+ input_libdir = args.prefix + args.libdir[len('${prefix}'):]
+ else:
+ if args.libdir.startswith('${exec_prefix}'):
+ libdir_use_shorthand = True
+ input_libdir = input_exec_prefix + args.libdir[len('${exec_prefix}'):]
+ else:
+ libdir_use_shorthand = False
+ input_libdir = args.libdir
+ if not os.path.exists(input_libdir):
+ raise SystemExit('Specified libdir \'%s\' is invalid' %
+ args.libdir)
+ if libdir_use_shorthand is True:
+ self.libdir = args.libdir.replace('\\','/')
+ else:
+ self.libdir = os.path.abspath(input_libdir).replace('\\','/')
+
+ # setup dictionary for replacing items in *.pc.in
+ self.base_replace_items.update({'@VERSION@': self.version})
+ self.base_replace_items.update({'@prefix@': self.prefix})
+ self.base_replace_items.update({'@exec_prefix@': self.exec_prefix})
+ self.base_replace_items.update({'@libdir@': self.libdir})
+ self.base_replace_items.update({'@includedir@': self.includedir})
diff --git a/src/3rdparty/libcroco/win32/replace.py b/src/3rdparty/libcroco/win32/replace.py
new file mode 100644
index 0000000..3aeceb1
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/replace.py
@@ -0,0 +1,115 @@
+#!/usr/bin/python
+#
+# Simple utility script to manipulate
+# certain types of strings in a file
+
+# This can be used in various projects where
+# there is the need to replace strings in files,
+# and is copied from GLib's $(srcroot)/win32
+
+# Author: Fan, Chun-wei
+# Date: September 03, 2014
+
+import os
+import sys
+import re
+import string
+import argparse
+
+valid_actions = ['remove-prefix',
+ 'replace-var',
+ 'replace-str',
+ 'remove-str']
+
+def open_file(filename, mode):
+ if sys.version_info[0] < 3:
+ return open(filename, mode=mode)
+ else:
+ return open(filename, mode=mode, encoding='utf-8')
+
+def replace_multi(src, dest, replace_items):
+ with open_file(src, 'r') as s:
+ with open_file(dest, 'w') as d:
+ for line in s:
+ replace_dict = dict((re.escape(key), value) \
+ for key, value in replace_items.items())
+ replace_pattern = re.compile("|".join(replace_dict.keys()))
+ d.write(replace_pattern.sub(lambda m: \
+ replace_dict[re.escape(m.group(0))], line))
+
+def replace(src, dest, instring, outstring):
+ replace_item = {instring: outstring}
+ replace_multi(src, dest, replace_item)
+
+def check_required_args(args, params):
+ for param in params:
+ if getattr(args, param, None) is None:
+ raise SystemExit('%s: error: --%s argument is required' % (__file__, param))
+
+def warn_ignored_args(args, params):
+ for param in params:
+ if getattr(args, param, None) is not None:
+ print('%s: warning: --%s argument is ignored' % (__file__, param))
+
+def main(argv):
+
+ parser = argparse.ArgumentParser(description='Process strings in a file.')
+ parser.add_argument('-a',
+ '--action',
+ help='Action to carry out. Can be one of:\n'
+ 'remove-prefix\n'
+ 'replace-var\n'
+ 'replace-str\n'
+ 'remove-str',
+ choices=valid_actions)
+ parser.add_argument('-i', '--input', help='Input file')
+ parser.add_argument('-o', '--output', help='Output file')
+ parser.add_argument('--instring', help='String to replace or remove')
+ parser.add_argument('--var', help='Autotools variable name to replace')
+ parser.add_argument('--outstring',
+ help='New String to replace specified string or variable')
+ parser.add_argument('--removeprefix', help='Prefix of string to remove')
+
+ args = parser.parse_args()
+
+ input_string = ''
+ output_string = ''
+
+ # We must have action, input, output for all operations
+ check_required_args(args, ['action','input','output'])
+
+ # Build the arguments by the operation that is to be done,
+ # to be fed into replace()
+
+ # Get rid of prefixes from a string
+ if args.action == 'remove-prefix':
+ check_required_args(args, ['instring','removeprefix'])
+ warn_ignored_args(args, ['outstring','var'])
+ input_string = args.removeprefix + args.instring
+ output_string = args.instring
+
+ # Replace an m4-style variable (those surrounded by @...@)
+ if args.action == 'replace-var':
+ check_required_args(args, ['var','outstring'])
+ warn_ignored_args(args, ['instring','removeprefix'])
+ input_string = '@' + args.var + '@'
+ output_string = args.outstring
+
+ # Replace a string
+ if args.action == 'replace-str':
+ check_required_args(args, ['instring','outstring'])
+ warn_ignored_args(args, ['var','removeprefix'])
+ input_string = args.instring
+ output_string = args.outstring
+
+ # Remove a string
+ if args.action == 'remove-str':
+ check_required_args(args, ['instring'])
+ warn_ignored_args(args, ['var','outstring','removeprefix'])
+ input_string = args.instring
+ output_string = ''
+
+ replace(args.input, args.output, input_string, output_string)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/src/3rdparty/libcroco/win32/vs10/Makefile.am b/src/3rdparty/libcroco/win32/vs10/Makefile.am
new file mode 100644
index 0000000..fcdd2f8
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/Makefile.am
@@ -0,0 +1,48 @@
+#This file is part of The Croco Library
+#This program is free software; you can redistribute it and/or
+#modify it under the terms of version 2.1 of the GNU Lesser General Public
+#License as published by the Free Software Foundation.
+
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU Lesser General Public License
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+#USA
+
+#Author: Fan, Chun-wei
+#See COPYRIGHTS file for copyright information.
+
+GENERATED_ITEMS = \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ croco-install.props \
+ croco-version-paths.props
+
+EXTRA_DIST = \
+ croco.vcxprojin \
+ croco.vcxproj.filtersin \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ libcroco.sln \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.propsin \
+ croco-version-paths.props.in \
+ $(GENERATED_ITEMS)
+
+croco-install.props: $(top_srcdir)/win32/vs10/croco-install.propsin croco.vs10.headers
+ -$(RM) $(top_builddir)/win32/vs11/croco-install.props
+ -$(RM) $(top_builddir)/win32/vs12/croco-install.props
+ -$(RM) $(top_builddir)/win32/vs14/croco-install.props
+ -$(RM) $(top_builddir)/win32/vs15/croco-install.props
+ $(CPP) -P - <$(top_srcdir)/win32/vs10/croco-install.propsin > $@
+ rm croco.vs10.headers
+
+DISTCLEANFILES = $(GENERATED_ITEMS)
+
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-build-defines.props b/src/3rdparty/libcroco/win32/vs10/croco-build-defines.props
new file mode 100644
index 0000000..f02e467
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-build-defines.props
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ImportGroup Label="PropertySheets">
+ <Import Project="croco-version-paths.props" />
+ </ImportGroup>
+ <PropertyGroup>
+ <_PropertySheetDisplayName>crocobuilddefinesprops</_PropertySheetDisplayName>
+ <OutDir>$(SolutionDir)$(Configuration)\$(PlatformName)\bin\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)\$(PlatformName)\obj\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\src;..\..;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\libxml2;$(GlibEtcInstallRoot)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>HAVE_CONFIG_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ForcedIncludeFiles>msvc_recommended_pragmas.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>libxml2.lib;glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(GlibEtcInstallRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions Condition="'$(VisualStudioVersion)|$(Platform)'=='11.0|x64'">/HIGHENTROPYVA %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions Condition="'$(VisualStudioVersion)|$(Platform)'=='12.0|x64'">/HIGHENTROPYVA %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions Condition="'$(VisualStudioVersion)|$(Platform)'=='14.0|x64'">/HIGHENTROPYVA %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions Condition="'$(VisualStudioVersion)|$(Platform)'=='15.0|x64'">/HIGHENTROPYVA %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions Condition="'$(VisualStudioVersion)|$(Platform)'=='16.0|x64'">/HIGHENTROPYVA %(AdditionalOptions)</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-gen-srcs.props b/src/3rdparty/libcroco/win32/vs10/croco-gen-srcs.props
new file mode 100644
index 0000000..83f7d30
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-gen-srcs.props
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ImportGroup Label="PropertySheets">
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros">
+ <CopyConfigH>copy ..\..\config.h.win32 ..\..\config.h</CopyConfigH>
+ <GenerateLibCrocoDef>
+echo EXPORTS &gt; $(DefDir)libcroco.def
+
+cl /EP ..\..\src\libcroco.symbols &gt;&gt; $(DefDir)libcroco.def
+ </GenerateLibCrocoDef>
+ </PropertyGroup>
+ <PropertyGroup>
+ <_PropertySheetDisplayName>crocogensrcsprops</_PropertySheetDisplayName>
+ </PropertyGroup>
+ <ItemGroup>
+ <BuildMacro Include="CopyConfigH">
+ <Value>$(CopyConfigH)</Value>
+ </BuildMacro>
+ <BuildMacro Include="GenerateLibCrocoDef">
+ <Value>$(GenerateLibCrocoDef)</Value>
+ </BuildMacro>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-install.propsin b/src/3rdparty/libcroco/win32/vs10/croco-install.propsin
new file mode 100644
index 0000000..ccce87e
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-install.propsin
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ImportGroup Label="PropertySheets">
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros">
+ <BinDir>$(SolutionDir)$(Configuration)\$(Platform)\bin</BinDir>
+ <LibCrocoDoInstall>
+mkdir $(CopyDir)
+mkdir $(CopyDir)\bin
+copy $(BinDir)\$(LibCrocoDllPrefix)croco$(LibCrocoDllSuffix).dll $(CopyDir)\bin
+copy $(BinDir)\$(LibCrocoDllPrefix)croco$(LibCrocoDllSuffix).pdb $(CopyDir)\bin
+copy $(BinDir)\csslint.exe $(CopyDir)\bin
+copy $(BinDir)\csslint.pdb $(CopyDir)\bin
+
+mkdir $(CopyDir)\include\libcroco-$(ApiVersion)\libcroco
+#include "croco.vs10.headers"
+
+mkdir $(CopyDir)\lib\pkgconfig
+copy $(BinDir)\croco-$(ApiVersion).lib $(CopyDir)\lib
+copy ..\libcroco-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig
+ </LibCrocoDoInstall>
+ <LibcrocoPCFiles>..\libcroco-$(ApiVersion).pc</LibcrocoPCFiles>
+ <LibcrocoGenPC>(if not exist $(CopyDir) mkdir $(CopyDir)) &amp; (if exist $(PythonPath)\python.exe $(PythonPath)\python.exe ..\crocopc.py --prefix=$(CopyDir) --version=$(CrocoMajorVersion).$(CrocoMinorVersion).$(CrocoMicroVersion))</LibcrocoGenPC>
+ </PropertyGroup>
+ <PropertyGroup>
+ <_PropertySheetDisplayName>crocoinstallprops</_PropertySheetDisplayName>
+ </PropertyGroup>
+ <ItemGroup>
+ <BuildMacro Include="BinDir">
+ <Value>$(BinDir)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoDoInstall">
+ <Value>$(LibCrocoDoInstall)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibcrocoPCFiles">
+ <Value>$(LibcrocoPCFiles)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibcrocoGenPC">
+ <Value>$(LibcrocoGenPC)</Value>
+ </BuildMacro>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj b/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj
new file mode 100644
index 0000000..0cda335
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{00702787-1566-484D-991F-4E7E459BB909}</ProjectGuid>
+ <RootNamespace>crocoinstall</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-install.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-install.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-install.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-install.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <OutDir Condition="'$(Configuration)'=='Debug'">$(GlibEtcInstallRoot)\</OutDir>
+ <ExtensionsToDeleteOnClean Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <OutDir Condition="'$(Configuration)'=='Release'">$(GlibEtcInstallRoot)\</OutDir>
+ <ExtensionsToDeleteOnClean Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\..\libcroco.pc.in">
+ <Message Condition="'$(Configuration)'=='Debug'">Generating .pc files...</Message>
+ <Command Condition="'$(Configuration)'=='Debug'">$(LibcrocoGenPC)</Command>
+ <Outputs Condition="'$(Configuration)'=='Debug'">$(LibcrocoPCFiles);%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)'=='Release'">Generating .pc files...</Message>
+ <Command Condition="'$(Configuration)'=='Release'">$(LibcrocoGenPC)</Command>
+ <Outputs Condition="'$(Configuration)'=='Release'">$(LibcrocoPCFiles);%(Outputs)</Outputs>
+ </CustomBuild>
+ <CustomBuild Include="..\..\config.h.win32">
+ <Message Condition="'$(Configuration)'=='Debug'">Installing Build Results...</Message>
+ <AdditionalInputs Condition="'$(Configuration)'=='Debug'">$(LibcrocoPCFiles)</AdditionalInputs>
+ <Command Condition="'$(Configuration)'=='Debug'">$(LibCrocoDoInstall)</Command>
+ <Outputs Condition="'$(Configuration)'=='Debug'">blah;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)'=='Release'">Installing Build Results...</Message>
+ <AdditionalInputs Condition="'$(Configuration)'=='Release'">$(LibcrocoPCFiles)</AdditionalInputs>
+ <Command Condition="'$(Configuration)'=='Release'">$(LibCrocoDoInstall)</Command>
+ <Outputs Condition="'$(Configuration)'=='Release'">blah;%(Outputs)</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="croco.vcxproj">
+ <Project>{4afe9f9b-7f78-41a8-b066-c7ca89938aba}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="csslint.vcxproj">
+ <Project>{345080b1-9c5b-44b8-98d7-7381d50f3e13}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj.filters b/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj.filters
new file mode 100644
index 0000000..9386b54
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj.filters
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\..\config.h.win32"><Filter>Resource Files</Filter></CustomBuild>
+ <CustomBuild Include="..\..\libcroco.pc.in"><Filter>Resource Files</Filter></CustomBuild>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-version-paths.props.in b/src/3rdparty/libcroco/win32/vs10/croco-version-paths.props.in
new file mode 100644
index 0000000..eb4000f
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-version-paths.props.in
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="UserMacros">
+ <CrocoMajorVersion>@LIBCROCO_MAJOR_VERSION@</CrocoMajorVersion>
+ <CrocoMinorVersion>@LIBCROCO_MINOR_VERSION@</CrocoMinorVersion>
+ <CrocoMicroVersion>@LIBCROCO_MICRO_VERSION@</CrocoMicroVersion>
+ <ApiVersion>$(CrocoMajorVersion).$(CrocoMinorVersion)</ApiVersion>
+ <VSVer>10</VSVer>
+ <GlibEtcInstallRoot>$(SolutionDir)\..\..\..\vs$(VSVer)\$(Platform)</GlibEtcInstallRoot>
+ <CopyDir>$(GlibEtcInstallRoot)</CopyDir>
+ <DefDir>$(SolutionDir)$(Configuration)\$(PlatformName)\obj\$(ProjectName)\</DefDir>
+ <LibCrocoLibtoolCompatibleDllPrefix>lib</LibCrocoLibtoolCompatibleDllPrefix>
+ <LibCrocoLibtoolCompatibleDllSuffix>-$(ApiVersion)-0</LibCrocoLibtoolCompatibleDllSuffix>
+ <LibCrocoSeparateVSDllPrefix />
+ <LibCrocoSeparateVSDllSuffix>-$(ApiVersion)-vs$(VSVer)</LibCrocoSeparateVSDllSuffix>
+ <LibCrocoDllPrefix>$(LibCrocoSeparateVSDllPrefix)</LibCrocoDllPrefix>
+ <LibCrocoDllSuffix>$(LibCrocoSeparateVSDllSuffix)</LibCrocoDllSuffix>
+ <PythonPath>c:\python34</PythonPath>
+ </PropertyGroup>
+ <PropertyGroup>
+ <_PropertySheetDisplayName>crocoversionpathsprops</_PropertySheetDisplayName>
+ </PropertyGroup>
+ <ItemGroup>
+ <BuildMacro Include="CrocoMajorVersion">
+ <Value>$(CrocoMajorVersion)</Value>
+ </BuildMacro>
+ <BuildMacro Include="CrocoMinorVersion">
+ <Value>$(CrocoMinorVersion)</Value>
+ </BuildMacro>
+ <BuildMacro Include="CrocoMicroVersion">
+ <Value>$(CrocoMicroVersion)</Value>
+ </BuildMacro>
+ <BuildMacro Include="ApiVersion">
+ <Value>$(ApiVersion)</Value>
+ </BuildMacro>
+ <BuildMacro Include="VSVer">
+ <Value>$(VSVer)</Value>
+ </BuildMacro>
+ <BuildMacro Include="GlibEtcInstallRoot">
+ <Value>$(GlibEtcInstallRoot)</Value>
+ </BuildMacro>
+ <BuildMacro Include="CopyDir">
+ <Value>$(CopyDir)</Value>
+ </BuildMacro>
+ <BuildMacro Include="DefDir">
+ <Value>$(DefDir)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoLibtoolCompatibleDllPrefix">
+ <Value>$(LibCrocoLibtoolCompatibleDllPrefix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoLibtoolCompatibleDllSuffix">
+ <Value>$(LibCrocoLibtoolCompatibleDllSuffix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoSeparateVSDllPrefix">
+ <Value>$(LibCrocoSeparateVSDllPrefix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoSeparateVSDllSuffix">
+ <Value>$(LibCrocoSeparateVSDllSuffix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoDllPrefix">
+ <Value>$(LibCrocoDllPrefix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoDllSuffix">
+ <Value>$(LibCrocoDllSuffix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="PythonPath">
+ <Value>$(PythonPath)</Value>
+ </BuildMacro>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco.vcxproj.filtersin b/src/3rdparty/libcroco/win32/vs10/croco.vcxproj.filtersin
new file mode 100644
index 0000000..4cce25f
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco.vcxproj.filtersin
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Sources">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Headers">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+#include "croco.vs10.sourcefiles.filters"
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\..\config.h.win32"><Filter>Resource Files</Filter></CustomBuild>
+ <CustomBuild Include="..\..\src\libcroco.symbols"><Filter>Resource Files</Filter></CustomBuild>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco.vcxprojin b/src/3rdparty/libcroco/win32/vs10/croco.vcxprojin
new file mode 100644
index 0000000..e81481b
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco.vcxprojin
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}</ProjectGuid>
+ <RootNamespace>libcroco</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-gen-srcs.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-gen-srcs.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-gen-srcs.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-gen-srcs.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <LinkIncremental Condition="'$(Configuration)'=='Debug'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)'=='Release'">false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <ForcedIncludeFiles>%(ForcedIncludeFiles)</ForcedIncludeFiles>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll</OutputFile>
+ <ModuleDefinitionFile>$(IntDir)libcroco.def</ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <ImportLibrary>$(TargetDir)$(ProjectName)-$(ApiVersion).lib</ImportLibrary>
+ <ProgramDatabaseFile>$(TargetDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).pdb</ProgramDatabaseFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ForcedIncludeFiles>%(ForcedIncludeFiles)</ForcedIncludeFiles>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll</OutputFile>
+ <ModuleDefinitionFile>$(IntDir)libcroco.def</ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(TargetDir)$(ProjectName)-$(ApiVersion).lib</ImportLibrary>
+ <ProgramDatabaseFile>$(TargetDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).pdb</ProgramDatabaseFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ForcedIncludeFiles>%(ForcedIncludeFiles)</ForcedIncludeFiles>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll</OutputFile>
+ <ModuleDefinitionFile>$(IntDir)libcroco.def</ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <ImportLibrary>$(TargetDir)$(ProjectName)-$(ApiVersion).lib</ImportLibrary>
+ <ProgramDatabaseFile>$(TargetDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).pdb</ProgramDatabaseFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ForcedIncludeFiles>%(ForcedIncludeFiles)</ForcedIncludeFiles>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll</OutputFile>
+ <ModuleDefinitionFile>$(IntDir)libcroco.def</ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(TargetDir)$(ProjectName)-$(ApiVersion).lib</ImportLibrary>
+ <ProgramDatabaseFile>$(TargetDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).pdb</ProgramDatabaseFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+#include "croco.vs10.sourcefiles"
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\..\config.h.win32">
+ <Message Condition="'$(Configuration)'=='Debug'">Copying config.h from config.h.win32...</Message>
+ <Command Condition="'$(Configuration)'=='Debug'">$(CopyConfigH)</Command>
+ <Outputs Condition="'$(Configuration)'=='Debug'">..\..\config.h;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)'=='Release'">Copying config.h from config.h.win32...</Message>
+ <Command Condition="'$(Configuration)'=='Release'">$(CopyConfigH)</Command>
+ <Outputs Condition="'$(Configuration)'=='Release'">..\..\config.h;%(Outputs)</Outputs>
+ </CustomBuild>
+ <CustomBuild Include="..\..\src\libcroco.symbols">
+ <Message Condition="'$(Configuration)'=='Debug'">Generating libcroco.def...</Message>
+ <Command Condition="'$(Configuration)'=='Debug'">$(GenerateLibCrocoDef)</Command>
+ <Outputs Condition="'$(Configuration)'=='Debug'">$(IntDir)\libcroco.def;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)'=='Release'">Generating libcroco.def...</Message>
+ <Command Condition="'$(Configuration)'=='Release'">$(GenerateLibCrocoDef)</Command>
+ <Outputs Condition="'$(Configuration)'=='Release'">$(IntDir)\libcroco.def;%(Outputs)</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj b/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj
new file mode 100644
index 0000000..452aa4a
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{345080B1-9C5B-44B8-98D7-7381D50F3E13}</ProjectGuid>
+ <RootNamespace>csslint</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <LinkIncremental Condition="'$(Configuration)'=='Debug'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)'=='Release'">false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\csslint\csslint.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="croco.vcxproj">
+ <Project>{4afe9f9b-7f78-41a8-b066-c7ca89938aba}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj.filters b/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj.filters
new file mode 100644
index 0000000..1145315
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj.filters
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Sources">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\csslint\csslint.c">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/libcroco.sln b/src/3rdparty/libcroco/win32/vs10/libcroco.sln
new file mode 100644
index 0000000..2077ef1
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/libcroco.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "croco", "croco.vcxproj", "{4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csslint", "csslint.vcxproj", "{345080B1-9C5B-44B8-98D7-7381D50F3E13}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "croco-install", "croco-install.vcxproj", "{00702787-1566-484D-991F-4E7E459BB909}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|Win32.Build.0 = Debug|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|x64.ActiveCfg = Debug|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|x64.Build.0 = Debug|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|Win32.ActiveCfg = Release|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|Win32.Build.0 = Release|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|x64.ActiveCfg = Release|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|x64.Build.0 = Release|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|Win32.ActiveCfg = Debug|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|Win32.Build.0 = Debug|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|x64.ActiveCfg = Debug|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|x64.Build.0 = Debug|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|Win32.ActiveCfg = Release|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|Win32.Build.0 = Release|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|x64.ActiveCfg = Release|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|x64.Build.0 = Release|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|Win32.ActiveCfg = Debug|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|Win32.Build.0 = Debug|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|x64.ActiveCfg = Debug|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|x64.Build.0 = Debug|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|Win32.ActiveCfg = Release|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|Win32.Build.0 = Release|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|x64.ActiveCfg = Release|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/3rdparty/libcroco/win32/vs11/Makefile.am b/src/3rdparty/libcroco/win32/vs11/Makefile.am
new file mode 100644
index 0000000..b5f9ea9
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs11/Makefile.am
@@ -0,0 +1,39 @@
+# This file is part of The Croco Library
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+# Author: Fan, Chun-wei
+# See COPYRIGHTS file for copyright information.
+
+EXTRA_DIST = \
+ libcroco.sln \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.props \
+ croco-version-paths.props
+
+DISTCLEANFILES = $(EXTRA_DIST)
+
+MSVC_BASE_VER = 10
+MSVC_BASE_VER_LONG = 2010
+MSVC_VER = 11
+MSVC_VER_LONG = 2012
+
+include $(top_srcdir)/win32/Makefile-newvs.am
diff --git a/src/3rdparty/libcroco/win32/vs12/Makefile.am b/src/3rdparty/libcroco/win32/vs12/Makefile.am
new file mode 100644
index 0000000..a3d6db1
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs12/Makefile.am
@@ -0,0 +1,39 @@
+# This file is part of The Croco Library
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+# Author: Fan, Chun-wei
+# See COPYRIGHTS file for copyright information.
+
+EXTRA_DIST = \
+ libcroco.sln \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.props \
+ croco-version-paths.props
+
+DISTCLEANFILES = $(EXTRA_DIST)
+
+MSVC_BASE_VER = 10
+MSVC_BASE_VER_LONG = 2010
+MSVC_VER = 12
+MSVC_VER_LONG = 2013
+
+include $(top_srcdir)/win32/Makefile-newvs.am
diff --git a/src/3rdparty/libcroco/win32/vs14/Makefile.am b/src/3rdparty/libcroco/win32/vs14/Makefile.am
new file mode 100644
index 0000000..d68e3bf
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs14/Makefile.am
@@ -0,0 +1,39 @@
+# This file is part of The Croco Library
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+# Author: Fan, Chun-wei
+# See COPYRIGHTS file for copyright information.
+
+EXTRA_DIST = \
+ libcroco.sln \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.props \
+ croco-version-paths.props
+
+DISTCLEANFILES = $(EXTRA_DIST)
+
+MSVC_BASE_VER = 10
+MSVC_BASE_VER_LONG = 2010
+MSVC_VER = 14
+MSVC_VER_LONG = 14
+
+include $(top_srcdir)/win32/Makefile-newvs.am
diff --git a/src/3rdparty/libcroco/win32/vs15/Makefile.am b/src/3rdparty/libcroco/win32/vs15/Makefile.am
new file mode 100644
index 0000000..0a4afa0
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs15/Makefile.am
@@ -0,0 +1,40 @@
+# This file is part of The Croco Library
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+# Author: Fan, Chun-wei
+# See COPYRIGHTS file for copyright information.
+
+EXTRA_DIST = \
+ libcroco.sln \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.props \
+ croco-version-paths.props
+
+DISTCLEANFILES = $(EXTRA_DIST)
+
+MSVC_BASE_VER = 10
+MSVC_BASE_VER_LONG = 2010
+MSVC_VER = 15
+MSVC_VER_LONG = 15
+MSVC_TOOLSET = 141
+
+include $(top_srcdir)/win32/Makefile-newvs.am
diff --git a/src/3rdparty/libcroco/win32/vs16/Makefile.am b/src/3rdparty/libcroco/win32/vs16/Makefile.am
new file mode 100644
index 0000000..a622c19
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs16/Makefile.am
@@ -0,0 +1,40 @@
+# This file is part of The Croco Library
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+# Author: Fan, Chun-wei
+# See COPYRIGHTS file for copyright information.
+
+EXTRA_DIST = \
+ libcroco.sln \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.props \
+ croco-version-paths.props
+
+DISTCLEANFILES = $(EXTRA_DIST)
+
+MSVC_BASE_VER = 10
+MSVC_BASE_VER_LONG = 2010
+MSVC_VER = 16
+MSVC_VER_LONG = 16
+MSVC_TOOLSET = 142
+
+include $(top_srcdir)/win32/Makefile-newvs.am
diff --git a/src/3rdparty/libcroco/win32/vs9/Makefile.am b/src/3rdparty/libcroco/win32/vs9/Makefile.am
new file mode 100644
index 0000000..9128036
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/Makefile.am
@@ -0,0 +1,39 @@
+#This file is part of The Croco Library
+#This program is free software; you can redistribute it and/or
+#modify it under the terms of version 2.1 of the GNU Lesser General Public
+#License as published by the Free Software Foundation.
+
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU Lesser General Public License
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+#USA
+
+#Author: Fan, Chun-wei
+#See COPYRIGHTS file for copyright information.
+
+GENERATED_ITEMS = \
+ croco.vcproj \
+ croco-install.vsprops \
+ croco-version-paths.vsprops
+
+EXTRA_DIST = \
+ croco.vcprojin \
+ csslint.vcproj \
+ croco-install.vcproj \
+ libcroco.sln \
+ croco-build-defines.vsprops \
+ croco-gen-srcs.vsprops \
+ croco-install.vspropsin \
+ croco-version-paths.vsprops.in \
+ $(GENERATED_ITEMS)
+
+croco-install.vsprops: $(top_srcdir)/win32/vs9/croco-install.vspropsin croco.headers
+ $(CPP) -P - <$(top_srcdir)/win32/vs9/croco-install.vspropsin >$@
+ rm croco.headers
+
+DISTCLEANFILES = $(GENERATED_ITEMS)
diff --git a/src/3rdparty/libcroco/win32/vs9/croco-build-defines.vsprops b/src/3rdparty/libcroco/win32/vs9/croco-build-defines.vsprops
new file mode 100644
index 0000000..a081b7b
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco-build-defines.vsprops
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="crocobuilddefinesprops"
+ InheritedPropertySheets=".\croco-version-paths.vsprops"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)\$(PlatformName)\obj\$(ProjectName)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src;..\..;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\libxml2;$(GlibEtcInstallRoot)\include"
+ PreprocessorDefinitions="HAVE_CONFIG_H"
+ ForcedIncludeFiles="msvc_recommended_pragmas.h"
+ AdditionalOptions="/MP"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="libxml2.lib glib-2.0.lib"
+ AdditionalLibraryDirectories="$(GlibEtcInstallRoot)\lib"
+ />
+</VisualStudioPropertySheet>
diff --git a/src/3rdparty/libcroco/win32/vs9/croco-gen-srcs.vsprops b/src/3rdparty/libcroco/win32/vs9/croco-gen-srcs.vsprops
new file mode 100644
index 0000000..5be8fe7
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco-gen-srcs.vsprops
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="crocogensrcsprops"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ >
+ <UserMacro
+ Name="CopyConfigH"
+ Value="copy ..\..\config.h.win32 ..\..\config.h"
+ />
+ <UserMacro
+ Name="GenerateLibCrocoDef"
+ Value="
+echo EXPORTS &gt; $(DefDir)\libcroco.def&#x0D;&#x0A;
+cl /EP ..\..\src\libcroco.symbols &gt;&gt; $(DefDir)\libcroco.def&#x0D;&#x0A;
+ "
+ />
+</VisualStudioPropertySheet>
diff --git a/src/3rdparty/libcroco/win32/vs9/croco-install.vcproj b/src/3rdparty/libcroco/win32/vs9/croco-install.vcproj
new file mode 100644
index 0000000..a48547c
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco-install.vcproj
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="big5"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="croco-install"
+ ProjectGUID="{00702787-1566-484D-991F-4E7E459BB909}"
+ RootNamespace="crocoinstall"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(GlibEtcInstallRoot)"
+ ConfigurationType="10"
+ InheritedPropertySheets=".\croco-install.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(LibCrocoDoInstall)"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(GlibEtcInstallRoot)"
+ InheritedPropertySheets=".\croco-install.vsprops"
+ ConfigurationType="10"
+ CharacterSet="2"
+ DeleteExtensionsOnClean=""
+ >
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(LibCrocoDoInstall)"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(GlibEtcInstallRoot)"
+ ConfigurationType="10"
+ InheritedPropertySheets=".\croco-install.vsprops"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(LibCrocoDoInstall)"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(GlibEtcInstallRoot)"
+ InheritedPropertySheets=".\croco-install.vsprops"
+ ConfigurationType="10"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ DeleteExtensionsOnClean=""
+ >
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(LibCrocoDoInstall)"
+ />
+ </Configuration>
+ </Configurations>
+ <Files>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File RelativePath="..\..\libcroco.pc.in">
+ <FileConfiguration Name="Debug|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating .pc files..."
+ CommandLine="$(LibcrocoGenPC)"
+ Outputs="..\libcroco-0.6.pc"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating .pc files..."
+ CommandLine="$(LibcrocoGenPC)"
+ Outputs="..\libcroco-0.6.pc"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Debug|x64">
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating .pc files..."
+ CommandLine="$(LibcrocoGenPC)"
+ Outputs="..\libcroco-0.6.pc"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|x64">
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating .pc files..."
+ CommandLine="$(LibcrocoGenPC)"
+ Outputs="..\libcroco-0.6.pc"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/3rdparty/libcroco/win32/vs9/croco-install.vspropsin b/src/3rdparty/libcroco/win32/vs9/croco-install.vspropsin
new file mode 100644
index 0000000..63a8afb
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco-install.vspropsin
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="crocoinstallprops"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ >
+ <UserMacro
+ Name="LibCrocoDoInstall"
+ Value="
+mkdir $(GlibEtcInstallRoot)&#x0D;&#x0A;
+mkdir $(GlibEtcInstallRoot)\bin&#x0D;&#x0A;
+copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(LibCrocoDllPrefix)croco$(LibCrocoDllSuffix).dll $(CopyDir)\bin&#x0D;&#x0A;
+copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(LibCrocoDllPrefix)croco$(LibCrocoDllSuffix).pdb $(CopyDir)\bin&#x0D;&#x0A;
+copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\csslint.exe $(CopyDir)\bin&#x0D;&#x0A;
+copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\csslint.pdb $(CopyDir)\bin&#x0D;&#x0A;
+
+mkdir $(CopyDir)\lib\pkgconfig&#x0D;&#x0A;
+copy ..\libcroco-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig&#x0D;&#x0A;
+
+mkdir $(CopyDir)\include\libcroco-$(ApiVersion)\libcroco&#x0D;&#x0A;
+#include "croco.headers"
+
+mkdir $(CopyDir)\lib&#x0D;&#x0A;
+copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\croco-$(ApiVersion).lib $(CopyDir)\lib&#x0D;&#x0A;
+"
+ />
+ <UserMacro
+ Name="LibcrocoGenPC"
+ Value="(if not exist $(CopyDir) mkdir $(CopyDir)) &amp; (if exist $(PythonPath)\python.exe $(PythonPath)\python.exe ..\crocopc.py --prefix=$(CopyDir) --version=$(CrocoMajorVersion).$(CrocoMinorVersion).$(CrocoMicroVersion))"
+ />
+</VisualStudioPropertySheet>
diff --git a/src/3rdparty/libcroco/win32/vs9/croco-version-paths.vsprops.in b/src/3rdparty/libcroco/win32/vs9/croco-version-paths.vsprops.in
new file mode 100644
index 0000000..d03f5e8
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco-version-paths.vsprops.in
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="crocoversionpathsprops"
+ >
+ <UserMacro
+ Name="CrocoMajorVersion"
+ Value="@LIBCROCO_MAJOR_VERSION@"
+ />
+ <UserMacro
+ Name="CrocoMinorVersion"
+ Value="@LIBCROCO_MINOR_VERSION@"
+ />
+ <UserMacro
+ Name="CrocoMicroVersion"
+ Value="@LIBCROCO_MICRO_VERSION@"
+ />
+ <UserMacro
+ Name="ApiVersion"
+ Value="$(CrocoMajorVersion).$(CrocoMinorVersion)"
+ />
+ <UserMacro
+ Name="VSVer"
+ Value="9"
+ />
+ <UserMacro
+ Name="GlibEtcInstallRoot"
+ Value="$(SolutionDir)\..\..\..\vs$(VSVer)\$(PlatformName)"
+ />
+ <UserMacro
+ Name="CopyDir"
+ Value="$(GlibEtcInstallRoot)"
+ />
+ <UserMacro
+ Name="DefDir"
+ Value="$(SolutionDir)$(ConfigurationName)\$(PlatformName)\obj\$(ProjectName)"
+ />
+ <UserMacro
+ Name="LibCrocoLibtoolCompatibleDllPrefix"
+ Value="lib"
+ />
+ <UserMacro
+ Name="LibCrocoLibtoolCompatibleDllSuffix"
+ Value="-$(ApiVersion)-0"
+ />
+ <UserMacro
+ Name="LibCrocoSeparateVSDllPrefix"
+ Value=""
+ />
+ <UserMacro
+ Name="LibCrocoSeparateVSDllSuffix"
+ Value="-$(ApiVersion)-vs$(VSVer)"
+ />
+ <!-- Change these two to LibCrocoLibtoolCompatibleDllPrefix and
+ LibCrocoLibtoolCompatibleDllSuffix if that is what you want -->
+ <UserMacro
+ Name="LibCrocoDllPrefix"
+ Value="$(LibCrocoSeparateVSDllPrefix)"
+ />
+ <UserMacro
+ Name="LibCrocoDllSuffix"
+ Value="$(LibCrocoSeparateVSDllSuffix)"
+ />
+ <UserMacro
+ Name="PythonPath"
+ Value="c:\python27"
+ />
+</VisualStudioPropertySheet>
diff --git a/src/3rdparty/libcroco/win32/vs9/croco.vcprojin b/src/3rdparty/libcroco/win32/vs9/croco.vcprojin
new file mode 100644
index 0000000..82df5a8
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco.vcprojin
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="big5"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="croco"
+ ProjectGUID="{4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}"
+ RootNamespace="libcroco"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ InheritedPropertySheets=".\croco-gen-srcs.vsprops"
+ ConfigurationType="2"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="_DEBUG"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ ForcedIncludeFiles=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ OutputFile="$(OutDir)\$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll"
+ LinkIncremental="2"
+ ModuleDefinitionFile="$(IntDir)\libcroco.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ ImportLibrary="$(TargetDir)$(ProjectName)-$(ApiVersion).lib"
+ TargetMachine="1"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ InheritedPropertySheets=".\croco-gen-srcs.vsprops"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions=""
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ ForcedIncludeFiles=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ OutputFile="$(OutDir)\$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll"
+ LinkIncremental="1"
+ ModuleDefinitionFile="$(IntDir)\libcroco.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(TargetDir)$(ProjectName)-$(ApiVersion).lib"
+ TargetMachine="1"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ InheritedPropertySheets=".\croco-gen-srcs.vsprops"
+ ConfigurationType="2"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="_DEBUG"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ ForcedIncludeFiles=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ OutputFile="$(OutDir)\$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll"
+ LinkIncremental="2"
+ ModuleDefinitionFile="$(IntDir)\libcroco.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ ImportLibrary="$(TargetDir)$(ProjectName)-$(ApiVersion).lib"
+ TargetMachine="17"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ InheritedPropertySheets=".\croco-gen-srcs.vsprops"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions=""
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ ForcedIncludeFiles=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ OutputFile="$(OutDir)\$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll"
+ LinkIncremental="1"
+ ModuleDefinitionFile="$(IntDir)\libcroco.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(TargetDir)$(ProjectName)-$(ApiVersion).lib"
+ TargetMachine="17"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Sources"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+#include "croco.sourcefiles"
+ </Filter>
+ <Filter
+ Name="Headers"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File RelativePath="..\..\config.h.win32">
+ <FileConfiguration Name="Debug|Win32">
+ <Tool Name="VCCustomBuildTool"
+ Description="Copying config.h from config.h.win32..."
+ CommandLine="$(CopyConfigH)"
+ Outputs="..\..\config.h"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|Win32">
+ <Tool Name="VCCustomBuildTool"
+ Description="Copying config.h from config.h.win32..."
+ CommandLine="$(CopyConfigH)"
+ Outputs="..\..\config.h"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Debug|x64">
+ <Tool Name="VCCustomBuildTool"
+ Description="Copying config.h from config.h.win32..."
+ CommandLine="$(CopyConfigH)"
+ Outputs="..\..\config.h"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|x64">
+ <Tool Name="VCCustomBuildTool"
+ Description="Copying config.h from config.h.win32..."
+ CommandLine="$(CopyConfigH)"
+ Outputs="..\..\config.h"
+ />
+ </FileConfiguration>
+ </File>
+ <File RelativePath="..\..\src\libcroco.symbols">
+ <FileConfiguration Name="Debug|Win32">
+ <Tool Name="VCCustomBuildTool"
+ Description="Generating libcroco.def..."
+ CommandLine="$(GenerateLibCrocoDef)"
+ Outputs="$(IntDir)\libcroco.def"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|Win32">
+ <Tool Name="VCCustomBuildTool"
+ Description="Generating libcroco.def..."
+ CommandLine="$(GenerateLibCrocoDef)"
+ Outputs="$(IntDir)\libcroco.def"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Debug|x64">
+ <Tool Name="VCCustomBuildTool"
+ Description="Generating libcroco.def..."
+ CommandLine="$(GenerateLibCrocoDef)"
+ Outputs="$(IntDir)\libcroco.def"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|x64">
+ <Tool Name="VCCustomBuildTool"
+ Description="Generating libcroco.def..."
+ CommandLine="$(GenerateLibCrocoDef)"
+ Outputs="$(IntDir)\libcroco.def"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/3rdparty/libcroco/win32/vs9/csslint.vcproj b/src/3rdparty/libcroco/win32/vs9/csslint.vcproj
new file mode 100644
index 0000000..20ede16
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/csslint.vcproj
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="big5"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="csslint"
+ ProjectGUID="{345080B1-9C5B-44B8-98D7-7381D50F3E13}"
+ RootNamespace="csslint"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Sources"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File RelativePath="..\..\csslint\csslint.c" />
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/3rdparty/libcroco/win32/vs9/libcroco.sln b/src/3rdparty/libcroco/win32/vs9/libcroco.sln
new file mode 100644
index 0000000..71e1b2f
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/libcroco.sln
@@ -0,0 +1,53 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "croco", "croco.vcproj", "{4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csslint", "csslint.vcproj", "{345080B1-9C5B-44B8-98D7-7381D50F3E13}"
+ ProjectSection(ProjectDependencies) = postProject
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA} = {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "croco-install", "croco-install.vcproj", "{00702787-1566-484D-991F-4E7E459BB909}"
+ ProjectSection(ProjectDependencies) = postProject
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA} = {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13} = {345080B1-9C5B-44B8-98D7-7381D50F3E13}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|Win32.Build.0 = Debug|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|x64.ActiveCfg = Debug|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|x64.Build.0 = Debug|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|Win32.ActiveCfg = Release|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|Win32.Build.0 = Release|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|x64.ActiveCfg = Release|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|x64.Build.0 = Release|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|Win32.ActiveCfg = Debug|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|Win32.Build.0 = Debug|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|x64.ActiveCfg = Debug|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|x64.Build.0 = Debug|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|Win32.ActiveCfg = Release|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|Win32.Build.0 = Release|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|x64.ActiveCfg = Release|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|x64.Build.0 = Release|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|Win32.ActiveCfg = Debug|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|Win32.Build.0 = Debug|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|x64.ActiveCfg = Debug|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|x64.Build.0 = Debug|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|Win32.ActiveCfg = Release|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|Win32.Build.0 = Release|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|x64.ActiveCfg = Release|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal