gtk-css-engine r42 - in branches/bzr: . libccd libccd/ccd libccd/doc libccd/examples src themes themes/gtk-css-test themes/gtk-css-test/gtk-2.0



Author: robsta
Date: Fri Sep  5 11:32:51 2008
New Revision: 42
URL: http://svn.gnome.org/viewvc/gtk-css-engine?rev=42&view=rev

Log:
Initial import.

Added:
   branches/bzr/   (props changed)
   branches/bzr/AUTHORS
   branches/bzr/COPYING
   branches/bzr/ChangeLog
   branches/bzr/HACKING
   branches/bzr/MAINTAINERS
   branches/bzr/Makefile.am
   branches/bzr/NEWS
   branches/bzr/README
   branches/bzr/TODO
   branches/bzr/autogen.sh   (contents, props changed)
   branches/bzr/configure.in
   branches/bzr/libccd/
   branches/bzr/libccd/Makefile.am
   branches/bzr/libccd/ccd/
   branches/bzr/libccd/ccd/Makefile.am
   branches/bzr/libccd/ccd/ccd-background.c
   branches/bzr/libccd/ccd/ccd-background.h
   branches/bzr/libccd/ccd/ccd-block.c
   branches/bzr/libccd/ccd/ccd-block.h
   branches/bzr/libccd/ccd/ccd-border.c
   branches/bzr/libccd/ccd/ccd-border.h
   branches/bzr/libccd/ccd/ccd-color.c
   branches/bzr/libccd/ccd/ccd-color.h
   branches/bzr/libccd/ccd/ccd-features.h.in
   branches/bzr/libccd/ccd/ccd-gtk-style.c
   branches/bzr/libccd/ccd/ccd-gtk-style.h
   branches/bzr/libccd/ccd/ccd-image.c
   branches/bzr/libccd/ccd/ccd-image.h
   branches/bzr/libccd/ccd/ccd-node.c
   branches/bzr/libccd/ccd/ccd-node.h
   branches/bzr/libccd/ccd/ccd-parser.c
   branches/bzr/libccd/ccd/ccd-parser.h
   branches/bzr/libccd/ccd/ccd-property.c
   branches/bzr/libccd/ccd/ccd-property.h
   branches/bzr/libccd/ccd/ccd-selector-group-priv.h
   branches/bzr/libccd/ccd/ccd-selector-group.c
   branches/bzr/libccd/ccd/ccd-selector-group.h
   branches/bzr/libccd/ccd/ccd-selector.c
   branches/bzr/libccd/ccd/ccd-selector.h
   branches/bzr/libccd/ccd/ccd-style.c
   branches/bzr/libccd/ccd/ccd-style.h
   branches/bzr/libccd/ccd/ccd-stylesheet.c
   branches/bzr/libccd/ccd/ccd-stylesheet.h
   branches/bzr/libccd/ccd/ccd-utils.h
   branches/bzr/libccd/ccd/ccd.c
   branches/bzr/libccd/ccd/ccd.h
   branches/bzr/libccd/doc/
   branches/bzr/libccd/doc/Makefile.am
   branches/bzr/libccd/doc/ccd-docs.sgml
   branches/bzr/libccd/doc/ccd-sections.txt
   branches/bzr/libccd/doc/version.xml.in
   branches/bzr/libccd/examples/
   branches/bzr/libccd/examples/Makefile.am
   branches/bzr/libccd/examples/example1.c
   branches/bzr/libccd/examples/example1.css
   branches/bzr/libccd/examples/internal.c
   branches/bzr/src/
   branches/bzr/src/Makefile.am
   branches/bzr/src/gce-maps.c
   branches/bzr/src/gce-maps.h
   branches/bzr/src/gce-rc-style.c
   branches/bzr/src/gce-rc-style.h
   branches/bzr/src/gce-style.c
   branches/bzr/src/gce-style.h
   branches/bzr/src/gce-theme.c
   branches/bzr/themes/
   branches/bzr/themes/Makefile.am
   branches/bzr/themes/gtk-css-test/
   branches/bzr/themes/gtk-css-test/Makefile.am
   branches/bzr/themes/gtk-css-test/gtk-2.0/
   branches/bzr/themes/gtk-css-test/gtk-2.0/Makefile.am
   branches/bzr/themes/gtk-css-test/gtk-2.0/gtkrc
   branches/bzr/themes/gtk-css-test/gtk-2.0/styles.css

Added: branches/bzr/AUTHORS
==============================================================================
--- (empty file)
+++ branches/bzr/AUTHORS	Fri Sep  5 11:32:51 2008
@@ -0,0 +1 @@
+Robert Staudinger <robsta gnome org>

Added: branches/bzr/COPYING
==============================================================================
--- (empty file)
+++ branches/bzr/COPYING	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,502 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  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 Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    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 Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+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 other code 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.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  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, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser 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 combine 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) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) 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.
+
+    d) 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.
+
+    e) 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 materials to be 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 with
+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 Lesser 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
+
+           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 Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+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!

Added: branches/bzr/HACKING
==============================================================================
--- (empty file)
+++ branches/bzr/HACKING	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,45 @@
+
+HACKING
+=======
+
+General remarks
+---------------
+
+* Code is a maximum of 80 characters wide. This keeps it readable also where
+  the original screen width limitations do not apply any more.
+
+* Use C99, in particular stdint and stdbool, except that variables go at the 
+  beginning of the block. You may use embedded counters in `for' loops though.
+
+* Do not initialise variables, pointers in particular, where they are declared.
+  Initialise immediately before usage and read compiler warnings to find out
+  whether any variables are being used without initialisation.
+
+* Use variable names in `sizeof()' statements rather than type names. Otherwise
+  refactorings including changing the datatype can render those broken. Example:
+
+    foo_t *f;
+    memset (f, 0, sizeof (*f));
+
+Including files
+---------------
+
+* Always include files in the following order:
+    (1) C headers, in alphabetical order.
+    (2) Dependency libraries' headers, in alphabetical order.
+    (3) Project headers, in alphabetical order.
+
+* In header files only ever include using pointy brackets and directory prefix.
+  This makes sure that installed headers work correctly and facilitates 
+  installation of multiple incompatible library versions in the same prefix.
+  Example foo.h:
+
+  #include <bar/bar.h>
+
+  In C files plain inclusion of headers from the project is encouraged, just
+  give the header's file name and leave setting of directories to the build
+  system. Example foo.c:
+  
+  #include "foo.h"
+
+

Added: branches/bzr/MAINTAINERS
==============================================================================
--- (empty file)
+++ branches/bzr/MAINTAINERS	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,4 @@
+Robert Staudinger
+E-mail: robsta gnome org
+Userid: robsta
+

Added: branches/bzr/Makefile.am
==============================================================================
--- (empty file)
+++ branches/bzr/Makefile.am	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,19 @@
+
+ACLOCAL_AMFLAGS = -I .
+DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
+
+SUBDIRS = libccd src themes
+
+EXTRA_DIST = \
+	AUTHORS \
+	ChangeLog \
+	COPYING \
+	INSTALL \
+	MAINTAINERS \
+	NEWS \
+	README \
+	autogen.sh
+
+distclean-local:
+	rm -rf *.cache *~
+

Added: branches/bzr/NEWS
==============================================================================

Added: branches/bzr/README
==============================================================================
--- (empty file)
+++ branches/bzr/README	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,211 @@
+
+CSS Theme Engine for GTK+
+=========================
+
+Putting stuff together for a gtk theme engine that would be configured using CSS rather than gtkrc syntax.
+
+Bzr repository at:
+  http://www.gnome.org/~robsta/bzr/gtk-css-engine/
+  bzr+ssh://bzr-playground.gnome.org/bzr/robsta/gtk-css-engine
+
+Previously available from:
+  sftp://robsta window gnome org/home/users/robsta/public_html/bzr/gtk-css-engine/
+
+Primitives
+----------
+
+Attributes are canonicalised, i.e. s/_/-/g.
+Comments are enclosed in ().
+Optionality is expressed through [].
+pseudo class "normal" will be default.
+
+* hline
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - detail: NULL | handlebox | hseparator | menuitem | tearoffmenuitem | toolbar
+
+* vline
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - detail: NULL | handlebox | toolbar | vseparator
+
+* shadow
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - detail: NULL | calendar | combobox | dnd | entry | frame | handle |
+		scrolled-window | text | viewport
+
+* arrow
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - arrow: up | down | left | right | none
+    - detail: NULL | arrow | calendar | menu-scroll-arrow-up | menu-scroll-arrow-down | 
+		menuitem | notebook | spinbutton | tearoffmenuitem |
+		hscrollbar | vscrollbar
+
+* diamond
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - No predefined detail strings for `diamond'.
+
+* DEPRECATED: string
+
+* box
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - detail: NULL | buttondefault | button | bar (cellrendererprogress) | 
+		handlebox-bin | hruler | hseparator (in `wide-separators' mode) |
+		menubar | menu | menu-scroll-arrow-up | menu-scroll-arrow-down | 
+		menuitem | hseparator | notebook | optionmenu | 
+		bar (progress-bar) | trough (progress-bar | range) | hscrollbar | 
+		vscrollbar | trough-upper | trough-lower | trough-fill-level-full | 
+		trough-fill-level | spinbutton | spinbutton-up | spinbutton-down | 
+		toolbar | vseparator | vruler | base (window)
+
+* flat-box
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - detail: NULL | checkbutton | curve-bg | entry-bg | eventbox | expander | tooltip | 
+		listitem | trough (progress) | checkbutton | text | treeitem | 
+		viewportbin | base (window) |
+		cell-odd[-start | -end | -middle] | 
+		cell-even[-start | -end | -middle] | 
+		cell-odd-ruled-sorted[-start | -end | -middle] | 
+		cell-even-ruled-sorted[-start | -end | -middle] | 
+		cell-odd-ruled[-start | -end | -middle] | 
+		cell-even-ruled[-start | -end | -middle] | 
+		cell-odd-sorted[-start | -end | -middle] | 
+		cell-even-sorted[-start | -end | -middle]
+
+* check
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - detail: NULL | cellcheck | checkbutton | check (menuitem)
+
+* option
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - detail: NULL | cellradio | option (menuitem) | radiobutton
+
+* tab
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - detail: NULL | optionmenutab
+
+* extension
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - position: left | right | top | bottom
+    - detail: NULL | tab (notebook)
+
+* focus
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - detail: NULL | button | calendar-day | checkbutton | entry | expander | 
+		colorwheel-light | colorwheel-dark | iconview-drop-indicator | 
+		icon-view | add-mode (listitem) | tab | button (gtkoptionmenu) | 
+		trough (gtkrange) | text | textview | tray-icon | treeitem | 
+		treeview-drop-indicator[-left | -right | -middle] | 
+		treeview[-left | -right | -middle]
+
+* slider
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - detail: NULL | hscale | vscale
+
+* handle
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - orientation: horizontal | vertical
+    - detail: NULL | handlebox | paned
+
+* expander
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - style: collapsed | semi-collapsed | semi-expanded | expanded
+    - detail: NULL | expander | treeview
+
+* layout
+  Styling of text will not be considered for now.
+
+* resize-grip
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - edge: north-west | north | north-east | west | east | south-west | south | south-east
+    - detail: NULL | statusbar
+
+* shadow-gap
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - position: left | right | top | bottom
+    - detail: NULL | frame
+
+* box-gap
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+    - position: left | right | top | bottom
+    - detail: NULL | notebook
+
+* polygon
+  Pseudo classes: normal | active | prelight | selected | insensitive
+  Selectors:
+    - Arbitrary widget properties that can be represented as a string.
+    - shadow: none | in | out | etched-in | etched-out
+
+Widgets
+-------
+
+Support for widgets will probably be implemented by aliases on primitives, e.g. GtkButton might be matched to "box[class=GtkButton]" internally. 
+
+The widget's name property is special cased and used as ID, thus it can be matched by '#foo { ... }'.
+
+
+Composite Widgets
+-----------------
+
+Composite widgets will probably be supported through selectors, e.g. "GtkComboBoxEntry > GtkEntry" (child selector) or "GtkComboBoxEntry GtkEntry" (descendant selector).
+
+
+Brainstorming
+-------------
+
+* Should the detail string act as a counterpart to what `class' is in html? Then one could write "hline.toolbar { color: black; }".
+
+* Multiple classes per element, a la <a class="foo bar baz">. Does this buy anything? Could possibly be matched on the widget name.
+
+* Application matching, possibly something like "application#gimp { ... }", match on g_get_prgname(). This could probably also be done with a custom `@' rule, e.g. "@application gimp { stylesheet goes here }"
+
+* CSS Variables ( http://disruptive-innovations.com/zoo/cssvariables/ ). Named colours could be implemented as built-in variables.
+
+* Easy to use when faking the gtk style (firefox, openoffice). We can provide custom hierarchy matching through a proxy in ccd.

Added: branches/bzr/TODO
==============================================================================
--- (empty file)
+++ branches/bzr/TODO	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,95 @@
+
+TODO
+====
+
+0.1 "Infrastructure"
+--------------------
+
+* Matching.
+* Background color.
+* Basic border styles.
+* Single background image, repeating, tiling.
+* Prototypical default theme.
+* Bugzilla module.
+
+Code review:
+  + Check all list iterators for const-ness.
+  + Make all string comparisons case insensitive?
+  + Get rid of the _match() functions all toghether?
+  + Check 80 column code width.
+
+0.2 "Correctness"
+-----------------
+
+* Border images.
+* Unit tests.
+* Test using the theme torturer.
+* Test using valgrind.
+
+0.3 "Features"
+--------------
+
+* Multiple background images.
+* Additional border features, e.g. `collapsed', `none'.
+* Implement `inherit' as per CSS spec. Do we need our own set of attributed 
+  inherited by default?
+* Support per-object style attributes in libccd (and maybe also the engine, but how?).
+  The node-class interface would have to be extended to support a `get_style()'
+  method.
+* Application-specific theming, someting like "@import "gimp.css" gimp;".
+
+0.4 "Performance"
+-----------------
+
+* Profile using the theme torturer.
+* Can selectors and blocks be merged at theme load time?
+* Can computed styles be attached to widgets using g_object_set_data()?
+* Use a string pool for the lookup tables?
+* Can we use binary search in the lookup tables?
+* Cache the type name inside the node?
+* Implement "is_a(ccd_node_t *node, char const *type_name)" rather than
+  recursing base types manually?
+
+0.5 "Compliance"
+----------------
+
+* Support widget mimicking by creating Gtk[Rc]Style style information and
+  feeding it back into gtk, e.g. using gtk_rc_parse(). Maybe we would end up
+  with two drawing modes, the `normal' one and the GtkStyle based one. In any
+  case gtk_rc_get_style_by_paths() should work.
+
+More 0. releases go here if needed ...
+
+1.0 "Rejoicing"
+---------------
+
+* Implement additional CSS pseudo classes like ":first", ":last", ":top", 
+  ":bottom". Those will be queried on the container and can e.g. be used to
+  make the outer corners of buttons in a button box rounded.
+
+  GtkHButtonBox GtkButton:first {
+    border-top-left-radius: 3px;
+    border-bottom-left-radius: 3px;
+  }
+  GtkHButtonBox GtkButton:last {
+    border-top-right-radius: 3px;
+    border-bottom-right-radius: 3px;
+  }
+
+1.2 "Fonts"
+-----------
+
+* Implement font effects.
+
+2.0 "Canvas"
+------------
+
+* Implement a WHATWG canvas and let the theme draw on it using ECMAScript.
+
+Out of band
+-----------
+
+* Create a spiffy website, possibly on http://gnome.org/projects. 
+  Any volunteers?
+* Evaluate alternative SVG renderers as they become available.
+

Added: branches/bzr/autogen.sh
==============================================================================
--- (empty file)
+++ branches/bzr/autogen.sh	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+olddir=`pwd`
+cd $srcdir
+
+(gtkdocize --version) < /dev/null > /dev/null 2>&1 || {
+	echo
+	echo "You must have gtk-doc installed to compile ."
+	echo "Install the appropriate package for your distribution,"
+	echo "or get the source tarball at http://ftp.gnome.org/pub/GNOME/sources/gtk-doc/";
+	DIE=1
+}
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+	echo
+	echo "You must have autoconf installed to compile $PROJECT."
+	echo "Install the appropriate package for your distribution,"
+	echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/";
+	DIE=1
+}
+
+if test "$DIE" = "1"; then
+	exit 1
+fi
+
+gtkdocize || exit $?
+autoreconf --force --install --symlink || exit $?
+
+cd $olddir
+
+conf_flags="--enable-maintainer-mode"
+
+if test x$NOCONFIGURE = x; then
+  echo Running $srcdir/configure $conf_flags "$@" ...
+  $srcdir/configure $conf_flags "$@" \
+  && echo Now type \`make\' to compile. || exit 1
+else
+  echo Skipping configure process.
+fi
+

Added: branches/bzr/configure.in
==============================================================================
--- (empty file)
+++ branches/bzr/configure.in	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,91 @@
+
+AC_PREREQ(2.61)
+AC_INIT([gtk-css-engine], [0.1])
+AC_CONFIG_SRCDIR([config.h.in])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_HEADERS([libccd/ccd/ccd-features.h])
+
+AM_INIT_AUTOMAKE
+AM_MAINTAINER_MODE
+
+### Checks for configure arguments
+
+AC_ARG_ENABLE([debug], 
+	[AS_HELP_STRING([--enable-debug], [enable debug code])], 
+[
+	if test "$enableval" == "yes"; then
+		AC_DEFINE([CCD_DEBUG], [1], [Enable debug code])
+	fi
+])
+
+### Checks for programs.
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+
+# gtk-doc
+gtk_doc_installed=true
+#ifdef([GTK_DOC_CHECK],[GTK_DOC_CHECK([1.0])],[gtk_doc_installed=false])
+# I would have liked to conditionalize this, but 
+# that appears to break other things http://bugzilla.gnome.org/show_bug.cgi?id=156399
+GTK_DOC_CHECK([1.0])
+AM_CONDITIONAL(GTK_DOC_INSTALLED, $gtk_doc_installed)
+
+
+### Checks for libraries.
+# gtk >= 2.12 is needed for GtkBuilder
+PKG_CHECK_MODULES(GCE, gtk+-2.0 >= 2.12.0 libcroco-0.6)
+
+AC_SUBST([GCE_CFLAGS])
+AC_SUBST([GCE_LIBS])
+
+AC_DEFINE([CCD_WITH_GTK], [1], [Support for drawing Gtk+ primitives like `box-gap'])
+AM_CONDITIONAL([CCD_WITH_GTK], [test "yes" = "yes"])
+
+AC_SUBST([CCD_CFLAGS], [$GCE_CFLAGS])
+AC_SUBST([CCD_LIBS], [$GCE_LIBS])
+
+### Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([stdbool.h stdint.h stdio.h stdlib.h string.h])
+
+### Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+
+set_more_warnings=yes
+if test "$GCC" = "yes" -a "$CC" != 'g++' -a "x$set_more_warnings" != "xno"; then
+	for option in -std=c99 -pedantic -Wall -Wsign-compare -Wpointer-arith -Wnested-externs -Wchar-subscripts -Wwrite-strings -Wdeclaration-after-statement -Wnested-externs -Wmissing-noreturn -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-pointer-sign \
+	-Wbitwise -Wcast-to-as -Wdefault-bitfield-sign -Wdo-while -Wparen-string -Wptr-subtraction-blows -Wreturn-void -Wtypesign ; do
+		SAVE_CFLAGS="$CFLAGS"
+		CFLAGS="$CFLAGS $option"
+		AC_MSG_CHECKING([whether gcc understands $option])
+		AC_TRY_COMPILE([], [],
+			has_option=yes,
+			has_option=no,)
+		if test $has_option = no; then
+		  CFLAGS="$SAVE_CFLAGS"
+		fi
+		AC_MSG_RESULT($has_option)
+		unset has_option
+		unset SAVE_CFLAGS
+	done
+	unset option
+fi
+
+AC_CONFIG_FILES([
+	Makefile
+	libccd/Makefile
+	libccd/ccd/Makefile
+	libccd/doc/Makefile
+	libccd/doc/version.xml
+	libccd/examples/Makefile
+	src/Makefile
+	themes/Makefile
+	themes/gtk-css-test/Makefile
+	themes/gtk-css-test/gtk-2.0/Makefile])
+AC_OUTPUT
+

Added: branches/bzr/libccd/Makefile.am
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/Makefile.am	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,7 @@
+
+SUBDIRS = ccd doc
+
+if CCD_WITH_GTK
+SUBDIRS += examples
+endif
+

Added: branches/bzr/libccd/ccd/Makefile.am
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/Makefile.am	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,48 @@
+
+AM_CPPFLAGS = \
+	$(CCD_CFLAGS) \
+	-I$(top_srcdir)/libccd \
+	-I$(top_builddir)/libccd
+
+noinst_LTLIBRARIES = libccd.la
+
+libccd_la_SOURCES = \
+	ccd-background.c \
+	ccd-background.h \
+	ccd-block.c \
+	ccd-block.h \
+	ccd-border.c \
+	ccd-border.h \
+	ccd-color.c \
+	ccd-color.h \
+	ccd-features.h \
+	ccd.c \
+	ccd.h \
+	ccd-image.c \
+	ccd-image.h \
+	ccd-node.c \
+	ccd-node.h \
+	ccd-parser.c \
+	ccd-parser.h \
+	ccd-property.c \
+	ccd-property.h \
+	ccd-selector-group.c \
+	ccd-selector-group.h \
+	ccd-selector-group-priv.h \
+	ccd-selector.c \
+	ccd-selector.h \
+	ccd-style.c \
+	ccd-style.h \
+	ccd-stylesheet.c \
+	ccd-stylesheet.h \
+	ccd-utils.h
+
+if CCD_WITH_GTK
+libccd_la_SOURCES += \
+	ccd-gtk-style.c \
+	ccd-gtk-style.h
+endif
+
+EXTRA_DIST = \
+	ccd-features.h.in
+

Added: branches/bzr/libccd/ccd/ccd-background.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-background.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,96 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "ccd-background.h"
+
+ccd_background_t * 
+ccd_background_new (void)
+{
+	return g_new0 (ccd_background_t, 1);
+}
+
+void
+ccd_background_free (ccd_background_t *self)
+{
+	g_free (self);
+}
+
+bool
+ccd_background_parse (ccd_background_t	*self,
+		      char const	*property,
+		      CRTerm const	*values)
+{
+	ccd_property_spec_t type;
+
+	type = CCD_PROPERTY_SPEC_UNKNOWN;
+	if (0 == strcmp ("background-color", property)) {
+		type = ccd_color_parse (&self->color, values);
+		g_return_val_if_fail (type != CCD_PROPERTY_SPEC_UNKNOWN, false);
+		self->color_type = type;
+		return true;
+	} else if (0 == strcmp ("background-image", property)) {
+		type = ccd_image_parse (&self->image, values);
+		g_return_val_if_fail (type != CCD_PROPERTY_SPEC_UNKNOWN, false);
+		self->image_type = type;
+		return true;
+	}
+
+	return false;
+}
+
+void
+ccd_background_draw (ccd_background_t const	*self,
+		     cairo_t			*cr,
+		     int32_t			 x,
+		     int32_t			 y,
+		     int32_t			 width,
+		     int32_t			 height)
+{
+	g_assert (self);
+
+	if (self->color_type != CCD_PROPERTY_SPEC_UNKNOWN) {
+		cairo_rectangle (cr, x, y, width, height);
+		cairo_set_source_rgb (cr, self->color.red, self->color.green, self->color.blue);
+		cairo_fill (cr);
+	}
+}
+
+void
+ccd_background_dump (ccd_background_t const *self)
+{
+	printf ("    background-color: ");
+	switch (self->color_type) {
+	case CCD_PROPERTY_SPEC_NONE:
+		printf ("none");
+		break;
+	case CCD_PROPERTY_SPEC_INHERIT:
+		printf ("inherit");
+		break;
+	case CCD_PROPERTY_SPEC_SPECIFIC:
+		ccd_color_dump (&self->color);
+		break;
+	case CCD_PROPERTY_SPEC_UNKNOWN:
+		/* fall thru */
+		;
+	}
+
+	printf (";\n");
+}
+

Added: branches/bzr/libccd/ccd/ccd-background.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-background.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,55 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_BACKGROUND_H
+#define CCD_BACKGROUND_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <cairo.h>
+#include <glib.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-color.h>
+#include <ccd/ccd-image.h>
+#include <ccd/ccd-property.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	ccd_color_t		color;
+	ccd_property_spec_t	color_type;
+	ccd_image_t		image;
+	ccd_property_spec_t	image_type;
+} ccd_background_t;
+
+ccd_background_t *	ccd_background_new	(void);
+void			ccd_background_free	(ccd_background_t *self);
+
+bool ccd_background_parse (ccd_background_t *self, char const *property, 
+			   CRTerm const *values);
+
+void ccd_background_draw (ccd_background_t const *self, cairo_t *cr, 
+			  int32_t x, int32_t y, int32_t width, int32_t height);
+
+void ccd_background_dump (ccd_background_t const *self);
+
+G_END_DECLS
+
+#endif /* CCD_BACKGROUND_H */
+

Added: branches/bzr/libccd/ccd/ccd-block.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-block.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,46 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "ccd-block.h"
+
+ccd_block_t *
+ccd_block_new (void)
+{
+	ccd_block_t *self;
+
+	self = g_new0 (ccd_block_t, 1);
+
+	return self;
+}
+
+void
+ccd_block_free (ccd_block_t *self)
+{
+	g_assert (self);
+
+	g_free (self);
+}
+
+void
+ccd_block_dump (ccd_block_t const *self)
+{
+	ccd_background_dump (&self->background);
+	ccd_border_dump (&self->border);
+}
+

Added: branches/bzr/libccd/ccd/ccd-block.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-block.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,45 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_BLOCK_H
+#define CCD_BLOCK_H
+
+#include <glib.h>
+#include <cairo.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-background.h>
+#include <ccd/ccd-border.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	/*< private >*/
+	ccd_background_t	background;
+	ccd_border_t		border;
+} ccd_block_t;
+
+ccd_block_t *	ccd_block_new	(void);
+void		ccd_block_free	(ccd_block_t *self);
+
+void ccd_block_dump (ccd_block_t const *self);
+
+G_END_DECLS
+
+#endif /* CCD_BLOCK_H */
+

Added: branches/bzr/libccd/ccd/ccd-border.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-border.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,431 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "ccd-border.h"
+#include "ccd-utils.h"
+
+#define SET_COMMON_WIDTH(cond_, border_, val_)					\
+if (cond_ && !(CCD_BORDER_FLAGS_SPECIFIC_WIDTH & border_.flags)) {		\
+	border_.width = val_;							\
+	border_.flags |= CCD_BORDER_FLAGS_COMMON_WIDTH;				\
+}
+
+#define SET_SPECIFIC_WIDTH(cond_, border_, val_)				\
+if (cond_) {									\
+	border_.width = val_;							\
+	border_.flags |= CCD_BORDER_FLAGS_SPECIFIC_WIDTH;			\
+}
+
+#define SET_COMMON_STYLE(cond_, border_, val_)					\
+if (cond_ && !(CCD_BORDER_FLAGS_SPECIFIC_STYLE & border_.flags)) {		\
+	border_.style = val_;							\
+	border_.flags |= CCD_BORDER_FLAGS_COMMON_STYLE;				\
+}
+
+#define SET_SPECIFIC_STYLE(cond_, border_, val_)				\
+if (cond_) {									\
+	border_.style = val_;							\
+	border_.flags |= CCD_BORDER_FLAGS_SPECIFIC_STYLE;			\
+}
+
+#define SET_COMMON_COLOR(cond_, border_, val_)					\
+if (cond_ && !(CCD_BORDER_FLAGS_SPECIFIC_COLOR & border_.flags)) { 		\
+	border_.color.red = val_.red;						\
+	border_.color.green = val_.green;					\
+	border_.color.blue = val_.blue;						\
+	border_.flags |= CCD_BORDER_FLAGS_COMMON_COLOR;				\
+}
+
+#define SET_SPECIFIC_COLOR(cond_, border_, val_)				\
+if (cond_) { 									\
+	border_.color.red = val_.red;						\
+	border_.color.green = val_.green;					\
+	border_.color.blue = val_.blue;						\
+	border_.flags |= CCD_BORDER_FLAGS_SPECIFIC_COLOR;			\
+}
+
+/*!
+ * Map between border style css string and internal value.
+ */
+static const struct {
+	ccd_border_style_t border_style;
+	char const *css;
+} _border_style_map[] = {
+	{ CCD_BORDER_STYLE_HIDDEN,	"hidden" },
+	{ CCD_BORDER_STYLE_DOTTED,	"dotted" },
+	{ CCD_BORDER_STYLE_DASHED,	"dashed" },
+	{ CCD_BORDER_STYLE_SOLID,	"solid"  },
+	{ CCD_BORDER_STYLE_DOUBLE,	"double" },
+	{ CCD_BORDER_STYLE_GROOVE,	"groove" },
+	{ CCD_BORDER_STYLE_RIDGE,	"ridge"  },
+	{ CCD_BORDER_STYLE_INSET,	"inset"  },
+	{ CCD_BORDER_STYLE_OUTSET,	"outset" }
+};
+
+static bool
+match_style (char const		*css_border_style,
+	     ccd_border_style_t	*style)
+{
+	g_return_val_if_fail (css_border_style && *css_border_style, false);
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_border_style_map); i++) {
+		if (0 == strcmp (_border_style_map[i].css, css_border_style)) {
+			*style = _border_style_map[i].border_style;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static char const *
+lookup_name (ccd_border_style_t border_style)
+{
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_border_style_map); i++) {
+		if (_border_style_map[i].border_style == border_style) {
+			return _border_style_map[i].css;
+		}
+	}	
+
+	return NULL;
+}
+
+ccd_border_t * 
+ccd_border_new (void)
+{
+	return g_new0 (ccd_border_t, 1);
+}
+
+void
+ccd_border_free (ccd_border_t *self)
+{
+	g_free (self);
+}
+
+/*
+ * Parse properties of the form
+ * - border: ;		# only to prevent errors
+ * - border: 1px;
+ * - border: solid;
+ * - border: 1px solid;
+ * - border: red;
+ * - border: 1px red;
+ * - border: 1px solid red;
+ */
+bool
+ccd_border_parse (ccd_border_t	*self,
+		  char const	*property,
+		  CRTerm const	*values)
+{
+	CRTerm const		*iter;
+	double			 width;
+	ccd_border_style_t	 style;
+	ccd_color_t		 color;
+	ccd_property_spec_t	 type;
+	bool			 have_width;
+	bool			 have_color;
+	bool			 have_style;
+
+/* TODO set per stroke or for whole border
+	type = ccd_property_parse_type (values);
+	if (CCD_PROPERTY_SPEC_NONE == type ||
+	    CCD_PROPERTY_SPEC_INHERIT == type) {
+		self->type = type;
+		return true;
+	}
+*/
+
+	iter = values;
+
+	have_width = false;
+	width = 0;	/* prevent warning */
+	if (iter && 
+	    TERM_NUMBER == iter->type) {
+		/* width */
+		width = iter->content.num->val;
+		iter = iter->next;
+		have_width = true;
+	}
+
+	have_style = false;
+	style = CCD_BORDER_STYLE_SOLID;	/* prevent warning */
+	if (iter && 
+	    TERM_IDENT == iter->type &&
+	    match_style (cr_string_peek_raw_str (iter->content.str), &style)) {
+		/* style */
+		iter = iter->next;
+		have_style = true;
+	}
+
+	have_color = false;
+	color.red = color.green = color.blue = 0; /* prevent warning */
+	if (iter &&
+	    ccd_color_parse (&color, iter)) {
+		/* color */
+		iter = iter->next;
+		have_color = true;
+	}
+
+	if (0 == strcmp ("border", property)) {
+
+		SET_COMMON_WIDTH (have_width, self->left, width);
+		SET_COMMON_WIDTH (have_width, self->top, width);
+		SET_COMMON_WIDTH (have_width, self->right, width);
+		SET_COMMON_WIDTH (have_width, self->bottom, width);
+
+		SET_COMMON_STYLE (have_style, self->left, style);
+		SET_COMMON_STYLE (have_style, self->top, style);
+		SET_COMMON_STYLE (have_style, self->right, style);
+		SET_COMMON_STYLE (have_style, self->bottom, style);
+		
+		SET_COMMON_COLOR (have_color, self->left, color);
+		SET_COMMON_COLOR (have_color, self->top, color);
+		SET_COMMON_COLOR (have_color, self->right, color);
+		SET_COMMON_COLOR (have_color, self->bottom, color);
+
+	} else if (0 == strcmp ("border-left", property)) {
+
+		SET_SPECIFIC_WIDTH (have_width, self->left, width);
+		SET_SPECIFIC_STYLE (have_style, self->left, style);
+		SET_SPECIFIC_COLOR (have_color, self->left, color);
+
+	} else if (0 == strcmp ("border-top", property)) {
+
+		SET_SPECIFIC_WIDTH (have_width, self->top, width);
+		SET_SPECIFIC_STYLE (have_style, self->top, style);
+		SET_SPECIFIC_COLOR (have_color, self->top, color);
+
+	} else if (0 == strcmp ("border-right", property)) {
+
+		SET_SPECIFIC_WIDTH (have_width, self->right, width);
+		SET_SPECIFIC_STYLE (have_style, self->right, style);
+		SET_SPECIFIC_COLOR (have_color, self->right, color);
+
+	} else if (0 == strcmp ("border-bottom", property)) {
+
+		SET_SPECIFIC_WIDTH (have_width, self->bottom, width);
+		SET_SPECIFIC_STYLE (have_style, self->bottom, style);
+		SET_SPECIFIC_COLOR (have_color, self->bottom, color);
+
+	} else {
+		return false;
+	}
+
+	return true;
+}
+
+static void
+draw_none (ccd_border_stroke_t const	*stroke,
+	   cairo_t			*cr,
+	   double			 x1,
+	   double			 y1,
+	   double			 x2,
+	   double			 y2)
+{}
+
+static void
+draw_dotted (ccd_border_stroke_t const	*stroke,
+	     cairo_t			*cr,
+	     double			 x1,
+	     double			 y1,
+	     double			 x2,
+	     double			 y2)
+{
+	double dash_len;
+
+	dash_len = stroke->width;
+
+	cairo_save (cr);
+
+	cairo_move_to (cr, x1, y1);
+	cairo_line_to (cr, x2, y2);
+	cairo_set_dash (cr, &dash_len, 1, 0);
+	cairo_set_line_width (cr, stroke->width);
+	cairo_set_source_rgb (cr, stroke->color.red, stroke->color.green, 
+				stroke->color.blue);
+	cairo_stroke (cr);
+
+	cairo_restore (cr);
+}
+
+static void
+draw_dashed (ccd_border_stroke_t const	*stroke,
+	     cairo_t			*cr,
+	     double			 x1,
+	     double			 y1,
+	     double			 x2,
+	     double			 y2)
+{
+	double dashes[2];
+
+	dashes[0] = stroke->width * 3;
+	dashes[1] = stroke->width * 3;
+
+	cairo_save (cr);
+
+	cairo_move_to (cr, x1, y1);
+	cairo_line_to (cr, x2, y2);
+	cairo_set_dash (cr, dashes, G_N_ELEMENTS (dashes), 0);
+	cairo_set_line_width (cr, stroke->width);
+	cairo_set_source_rgb (cr, stroke->color.red, stroke->color.green, 
+				stroke->color.blue);
+	cairo_stroke (cr);
+
+	cairo_restore (cr);
+}
+
+static void
+draw_solid (ccd_border_stroke_t const	*stroke,
+	    cairo_t			*cr,
+	    double			 x1,
+	    double			 y1,
+	    double			 x2,
+	    double			 y2)
+{
+	cairo_save (cr);
+
+	cairo_move_to (cr, x1, y1);
+	cairo_line_to (cr, x2, y2);
+	cairo_set_line_width (cr, stroke->width);
+	cairo_set_source_rgb (cr, stroke->color.red, stroke->color.green, 
+				stroke->color.blue);
+	cairo_stroke (cr);
+
+	cairo_restore (cr);
+}
+
+typedef void (*draw_f) (ccd_border_stroke_t const *, cairo_t *, 
+			double, double, double, double);
+
+static draw_f
+get_draw_func (ccd_border_stroke_t const *stroke)
+{
+	if (CCD_PROPERTY_SPEC_NONE == stroke->type) {
+		return draw_none;
+	}
+
+	switch (stroke->style) {
+	case CCD_BORDER_STYLE_HIDDEN: 
+		g_warning ("CCD_BORDER_STYLE_HIDDEN not implemented");
+		return draw_none;
+	case CCD_BORDER_STYLE_DOTTED:
+		return draw_dotted;
+	case CCD_BORDER_STYLE_DASHED:
+		return draw_dashed;
+	case CCD_BORDER_STYLE_SOLID:
+		return draw_solid;
+	case CCD_BORDER_STYLE_DOUBLE:
+		g_warning ("CCD_BORDER_STYLE_DOUBLE not implemented");
+	case CCD_BORDER_STYLE_GROOVE:
+		g_warning ("CCD_BORDER_STYLE_GROOVE not implemented");
+	case CCD_BORDER_STYLE_RIDGE:
+		g_warning ("CCD_BORDER_STYLE_RIDGE not implemented");
+	case CCD_BORDER_STYLE_INSET:
+		g_warning ("CCD_BORDER_STYLE_INSET not implemented");
+	case CCD_BORDER_STYLE_OUTSET:
+		g_warning ("CCD_BORDER_STYLE_OUTSET not implemented");
+	default:
+		g_assert_not_reached ();
+		return draw_solid;
+	}
+}
+
+void
+ccd_border_draw (ccd_border_stroke_t const	*left,
+		 ccd_border_stroke_t const	*top,
+		 ccd_border_stroke_t const	*right,
+		 ccd_border_stroke_t const	*bottom,
+		 cairo_t			*cr,
+		 double				 x,
+		 double				 y,
+		 double				 width,
+		 double				 height)
+{
+	draw_f	draw_func;
+	double	off;
+
+	if (left) {
+		draw_func = get_draw_func (left);
+		off = left->width / 2.;
+		draw_func (left, cr, x + off, y, x + off, y + height);
+	}
+
+	if (top) {
+		draw_func = get_draw_func (top);
+		off = top->width / 2.;
+		draw_func (top, cr, x, y + off, x + width, y + off);
+	}
+
+	if (right) {
+		draw_func = get_draw_func (right);
+		off = right->width / 2.;
+		draw_func (right, cr, x + width - off, y, x + width - off, y + height);
+	}
+
+	if (bottom) {
+		draw_func = get_draw_func (bottom);
+		off = bottom->width / 2.;
+		draw_func (bottom, cr, x + width, y + height - off, x, y + height - off);
+	}
+}
+
+void
+ccd_border_dump_stroke (ccd_border_stroke_t const *stroke)
+{
+	if (stroke->flags & CCD_BORDER_FLAGS_WIDTH_MASK) {
+		printf ("%.1f ", stroke->width);
+	}
+
+	if (stroke->flags & CCD_BORDER_FLAGS_STYLE_MASK) {
+		printf ("%s ", lookup_name (stroke->style));
+	}
+
+	if (stroke->flags & CCD_BORDER_FLAGS_COLOR_MASK) {
+		ccd_color_dump (&stroke->color);
+	}
+
+	printf (";\n");
+}
+
+void
+ccd_border_dump (ccd_border_t const *self)
+{
+	if (self->left.flags) {
+		printf (CCD_PROPERTY_DUMP_PREFIX "border-left: ");
+		ccd_border_dump_stroke (&self->left);
+	}
+
+	if (self->top.flags) {
+		printf (CCD_PROPERTY_DUMP_PREFIX "border-top: ");
+		ccd_border_dump_stroke (&self->top);
+	}
+
+	if (self->right.flags) {
+		printf (CCD_PROPERTY_DUMP_PREFIX "border-right: ");
+		ccd_border_dump_stroke (&self->right);
+	}
+
+	if (self->bottom.flags) {
+		printf (CCD_PROPERTY_DUMP_PREFIX "border-bottom: ");
+		ccd_border_dump_stroke (&self->bottom);
+	}
+}
+

Added: branches/bzr/libccd/ccd/ccd-border.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-border.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,96 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_BORDER_H
+#define CCD_BORDER_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <cairo.h>
+#include <glib.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-color.h>
+#include <ccd/ccd-property.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+	CCD_BORDER_STYLE_HIDDEN,
+	CCD_BORDER_STYLE_DOTTED,
+	CCD_BORDER_STYLE_DASHED,
+	CCD_BORDER_STYLE_SOLID,
+	CCD_BORDER_STYLE_DOUBLE,
+	CCD_BORDER_STYLE_GROOVE,
+	CCD_BORDER_STYLE_RIDGE,
+	CCD_BORDER_STYLE_INSET,
+	CCD_BORDER_STYLE_OUTSET
+} ccd_border_style_t;
+
+/*
+ * Remember which properties were set explicitely, e.g. using "border-top", 
+ * so it's not overwritten by a subsequent "border" property.
+ */
+typedef enum {
+	CCD_BORDER_FLAGS_COMMON_WIDTH	= 1 << 0,
+	CCD_BORDER_FLAGS_SPECIFIC_WIDTH = 1 << 1,
+	CCD_BORDER_FLAGS_WIDTH_MASK	= CCD_BORDER_FLAGS_COMMON_WIDTH | CCD_BORDER_FLAGS_SPECIFIC_WIDTH,
+
+	CCD_BORDER_FLAGS_COMMON_STYLE	= 1 << 2,
+	CCD_BORDER_FLAGS_SPECIFIC_STYLE = 1 << 3,
+	CCD_BORDER_FLAGS_STYLE_MASK	= CCD_BORDER_FLAGS_COMMON_STYLE | CCD_BORDER_FLAGS_SPECIFIC_STYLE,
+
+	CCD_BORDER_FLAGS_COMMON_COLOR	= 1 << 4,
+	CCD_BORDER_FLAGS_SPECIFIC_COLOR = 1 << 5,
+	CCD_BORDER_FLAGS_COLOR_MASK	= CCD_BORDER_FLAGS_COMMON_COLOR | CCD_BORDER_FLAGS_SPECIFIC_COLOR
+} ccd_border_flags_t;
+
+typedef struct {
+	double			width;
+	ccd_border_style_t	style;
+	ccd_color_t		color;
+	ccd_property_spec_t	type;
+	int			flags;
+} ccd_border_stroke_t;
+
+typedef struct {
+	ccd_border_stroke_t	left;
+	ccd_border_stroke_t	top;
+	ccd_border_stroke_t	right;
+	ccd_border_stroke_t	bottom;
+} ccd_border_t;
+
+ccd_border_t *	ccd_border_new	(void);
+void		ccd_border_free	(ccd_border_t *self);
+
+bool ccd_border_parse (ccd_border_t *self, char const *property, 
+				CRTerm const *values);
+
+void ccd_border_draw (ccd_border_stroke_t const *left, 
+		      ccd_border_stroke_t const *top, 
+		      ccd_border_stroke_t const *right,
+		      ccd_border_stroke_t const *bottom, 
+		      cairo_t *cr, double x, double y, double width, double height);
+
+void ccd_border_dump		(ccd_border_t const *self);
+void ccd_border_dump_stroke	(ccd_border_stroke_t const *stroke);
+
+G_END_DECLS
+
+#endif /* CCD_BORDER_H */
+

Added: branches/bzr/libccd/ccd/ccd-color.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-color.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,305 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * Functions ccd_color_parse_hex() and hex() are derived from pango,
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include "ccd-color.h"
+
+static const struct {
+	char const		*name;
+	const ccd_color_t	color;
+} _color_map[] = {
+  { "aliceblue",		{ 0xf0/255., 0xf8/255., 0xff/255. } },
+  { "antiquewhite",		{ 0xfa/255., 0xeb/255., 0xd7/255. } },
+  { "aqua",			{ 0x00/255., 0xff/255., 0xff/255. } },
+  { "aquamarine",		{ 0x7f/255., 0xff/255., 0xd4/255. } },
+  { "azure",			{ 0xf0/255., 0xff/255., 0xff/255. } },
+  { "beige",			{ 0xf5/255., 0xf5/255., 0xdc/255. } },
+  { "bisque",			{ 0xff/255., 0xe4/255., 0xc4/255. } },
+  { "black",			{ 0x00/255., 0x00/255., 0x00/255. } },
+  { "blanchedalmond",		{ 0xff/255., 0xeb/255., 0xcd/255. } },
+  { "blue",			{ 0x00/255., 0x00/255., 0xff/255. } },
+  { "blueviolet",		{ 0x8a/255., 0x2b/255., 0xe2/255. } },
+  { "brown",			{ 0xa5/255., 0x2a/255., 0x2a/255. } },
+  { "burlywood",		{ 0xde/255., 0xb8/255., 0x87/255. } },
+  { "cadetblue",		{ 0x5f/255., 0x9e/255., 0xa0/255. } },
+  { "chartreuse",		{ 0x7f/255., 0xff/255., 0x00/255. } },
+  { "chocolate",		{ 0xd2/255., 0x69/255., 0x1e/255. } },
+  { "coral",			{ 0xff/255., 0x7f/255., 0x50/255. } },
+  { "cornflowerblue",		{ 0x64/255., 0x95/255., 0xed/255. } },
+  { "cornsilk",			{ 0xff/255., 0xf8/255., 0xdc/255. } },
+  { "crimson",			{ 0xdc/255., 0x14/255., 0x3c/255. } },
+  { "cyan",			{ 0x00/255., 0xff/255., 0xff/255. } },
+  { "darkblue",			{ 0x00/255., 0x00/255., 0x8b/255. } },
+  { "darkcyan",			{ 0x00/255., 0x8b/255., 0x8b/255. } },
+  { "darkgoldenrod",		{ 0xb8/255., 0x86/255., 0x0b/255. } },
+  { "darkgray",			{ 0xa9/255., 0xa9/255., 0xa9/255. } },
+  { "darkgrey",			{ 0xa9/255., 0xa9/255., 0xa9/255. } },
+  { "darkgreen",		{ 0x00/255., 0x64/255., 0x00/255. } },
+  { "darkkhaki",		{ 0xbd/255., 0xb7/255., 0x6b/255. } },
+  { "darkmagenta",		{ 0x8b/255., 0x00/255., 0x8b/255. } },
+  { "darkolivegreen",		{ 0x55/255., 0x6b/255., 0x2f/255. } },
+  { "darkorange",		{ 0xff/255., 0x8c/255., 0x00/255. } },
+  { "darkorchid",		{ 0x99/255., 0x32/255., 0xcc/255. } },
+  { "darkred",			{ 0x8b/255., 0x00/255., 0x00/255. } },
+  { "darksalmon",		{ 0xe9/255., 0x96/255., 0x7a/255. } },
+  { "darkseagreen",		{ 0x8f/255., 0xbc/255., 0x8f/255. } },
+  { "darkslateblue",		{ 0x48/255., 0x3d/255., 0x8b/255. } },
+  { "darkslategray",		{ 0x2f/255., 0x4f/255., 0x4f/255. } },
+  { "darkslategrey",		{ 0x2f/255., 0x4f/255., 0x4f/255. } },
+  { "darkturquoise",		{ 0x00/255., 0xce/255., 0xd1/255. } },
+  { "darkviolet",		{ 0x94/255., 0x00/255., 0xd3/255. } },
+  { "deeppink",			{ 0xff/255., 0x14/255., 0x93/255. } },
+  { "deepskyblue",		{ 0x00/255., 0xbf/255., 0xff/255. } },
+  { "dimgray",			{ 0x69/255., 0x69/255., 0x69/255. } },
+  { "dimgrey",			{ 0x69/255., 0x69/255., 0x69/255. } },
+  { "dodgerblue",		{ 0x1e/255., 0x90/255., 0xff/255. } },
+  { "firebrick",		{ 0xb2/255., 0x22/255., 0x22/255. } },
+  { "floralwhite",		{ 0xff/255., 0xfa/255., 0xf0/255. } },
+  { "forestgreen",		{ 0x22/255., 0x8b/255., 0x22/255. } },
+  { "fuchsia",			{ 0xff/255., 0x00/255., 0xff/255. } },
+  { "gainsboro",		{ 0xdc/255., 0xdc/255., 0xdc/255. } },
+  { "ghostwhite",		{ 0xf8/255., 0xf8/255., 0xff/255. } },
+  { "gold",			{ 0xff/255., 0xd7/255., 0x00/255. } },
+  { "goldenrod",		{ 0xda/255., 0xa5/255., 0x20/255. } },
+  { "gray",			{ 0x80/255., 0x80/255., 0x80/255. } },
+  { "grey",			{ 0x80/255., 0x80/255., 0x80/255. } },
+  { "green",			{ 0x00/255., 0x80/255., 0x00/255. } },
+  { "greenyellow",		{ 0xad/255., 0xff/255., 0x2f/255. } },
+  { "honeydew",			{ 0xf0/255., 0xff/255., 0xf0/255. } },
+  { "hotpink",			{ 0xff/255., 0x69/255., 0xb4/255. } },
+  { "indianred",		{ 0xcd/255., 0x5c/255., 0x5c/255. } },
+  { "indigo",			{ 0x4b/255., 0x00/255., 0x82/255. } },
+  { "ivory",			{ 0xff/255., 0xff/255., 0xf0/255. } },
+  { "khaki",			{ 0xf0/255., 0xe6/255., 0x8c/255. } },
+  { "lavender",			{ 0xe6/255., 0xe6/255., 0xfa/255. } },
+  { "lavenderblush",		{ 0xff/255., 0xf0/255., 0xf5/255. } },
+  { "lawngreen",		{ 0x7c/255., 0xfc/255., 0x00/255. } },
+  { "lemonchiffon",		{ 0xff/255., 0xfa/255., 0xcd/255. } },
+  { "lightblue",		{ 0xad/255., 0xd8/255., 0xe6/255. } },
+  { "lightcoral",		{ 0xf0/255., 0x80/255., 0x80/255. } },
+  { "lightcyan",		{ 0xe0/255., 0xff/255., 0xff/255. } },
+  { "lightgoldenrodyellow",	{ 0xfa/255., 0xfa/255., 0xd2/255. } },
+  { "lightgray",		{ 0xd3/255., 0xd3/255., 0xd3/255. } },
+  { "lightgrey",		{ 0xd3/255., 0xd3/255., 0xd3/255. } },
+  { "lightgreen",		{ 0x90/255., 0xee/255., 0x90/255. } },
+  { "lightpink",		{ 0xff/255., 0xb6/255., 0xc1/255. } },
+  { "lightsalmon",		{ 0xff/255., 0xa0/255., 0x7a/255. } },
+  { "lightseagreen",		{ 0x20/255., 0xb2/255., 0xaa/255. } },
+  { "lightskyblue",		{ 0x87/255., 0xce/255., 0xfa/255. } },
+  { "lightslategray",		{ 0x77/255., 0x88/255., 0x99/255. } },
+  { "lightslategrey",		{ 0x77/255., 0x88/255., 0x99/255. } },
+  { "lightsteelblue",		{ 0xb0/255., 0xc4/255., 0xde/255. } },
+  { "lightyellow",		{ 0xff/255., 0xff/255., 0xe0/255. } },
+  { "lime",			{ 0x00/255., 0xff/255., 0x00/255. } },
+  { "limegreen",		{ 0x32/255., 0xcd/255., 0x32/255. } },
+  { "linen",			{ 0xfa/255., 0xf0/255., 0xe6/255. } },
+  { "magenta",			{ 0xff/255., 0x00/255., 0xff/255. } },
+  { "maroon",			{ 0x80/255., 0x00/255., 0x00/255. } },
+  { "mediumaquamarine",		{ 0x66/255., 0xcd/255., 0xaa/255. } },
+  { "mediumblue",		{ 0x00/255., 0x00/255., 0xcd/255. } },
+  { "mediumorchid",		{ 0xba/255., 0x55/255., 0xd3/255. } },
+  { "mediumpurple",		{ 0x93/255., 0x70/255., 0xd8/255. } },
+  { "mediumseagreen",		{ 0x3c/255., 0xb3/255., 0x71/255. } },
+  { "mediumslateblue",		{ 0x7b/255., 0x68/255., 0xee/255. } },
+  { "mediumspringgreen",	{ 0x00/255., 0xfa/255., 0x9a/255. } },
+  { "mediumturquoise",		{ 0x48/255., 0xd1/255., 0xcc/255. } },
+  { "mediumvioletred",		{ 0xc7/255., 0x15/255., 0x85/255. } },
+  { "midnightblue",		{ 0x19/255., 0x19/255., 0x70/255. } },
+  { "mintcream",		{ 0xf5/255., 0xff/255., 0xfa/255. } },
+  { "mistyrose",		{ 0xff/255., 0xe4/255., 0xe1/255. } },
+  { "moccasin",			{ 0xff/255., 0xe4/255., 0xb5/255. } },
+  { "navajowhite",		{ 0xff/255., 0xde/255., 0xad/255. } },
+  { "navy",			{ 0x00/255., 0x00/255., 0x80/255. } },
+  { "oldlace",			{ 0xfd/255., 0xf5/255., 0xe6/255. } },
+  { "olive",			{ 0x80/255., 0x80/255., 0x00/255. } },
+  { "olivedrab",		{ 0x6b/255., 0x8e/255., 0x23/255. } },
+  { "orange",			{ 0xff/255., 0xa5/255., 0x00/255. } },
+  { "orangered",		{ 0xff/255., 0x45/255., 0x00/255. } },
+  { "orchid",			{ 0xda/255., 0x70/255., 0xd6/255. } },
+  { "palegoldenrod",		{ 0xee/255., 0xe8/255., 0xaa/255. } },
+  { "palegreen",		{ 0x98/255., 0xfb/255., 0x98/255. } },
+  { "paleturquoise",		{ 0xaf/255., 0xee/255., 0xee/255. } },
+  { "palevioletred",		{ 0xd8/255., 0x70/255., 0x93/255. } },
+  { "papayawhip",		{ 0xff/255., 0xef/255., 0xd5/255. } },
+  { "peachpuff",		{ 0xff/255., 0xda/255., 0xb9/255. } },
+  { "peru",			{ 0xcd/255., 0x85/255., 0x3f/255. } },
+  { "pink",			{ 0xff/255., 0xc0/255., 0xcb/255. } },
+  { "plum",			{ 0xdd/255., 0xa0/255., 0xdd/255. } },
+  { "powderblue",		{ 0xb0/255., 0xe0/255., 0xe6/255. } },
+  { "purple",			{ 0x80/255., 0x00/255., 0x80/255. } },
+  { "red",			{ 0xff/255., 0x00/255., 0x00/255. } },
+  { "rosybrown",		{ 0xbc/255., 0x8f/255., 0x8f/255. } },
+  { "royalblue",		{ 0x41/255., 0x69/255., 0xe1/255. } },
+  { "saddlebrown",		{ 0x8b/255., 0x45/255., 0x13/255. } },
+  { "salmon",			{ 0xfa/255., 0x80/255., 0x72/255. } },
+  { "sandybrown",		{ 0xf4/255., 0xa4/255., 0x60/255. } },
+  { "seagreen",			{ 0x2e/255., 0x8b/255., 0x57/255. } },
+  { "seashell",			{ 0xff/255., 0xf5/255., 0xee/255. } },
+  { "sienna",			{ 0xa0/255., 0x52/255., 0x2d/255. } },
+  { "silver",			{ 0xc0/255., 0xc0/255., 0xc0/255. } },
+  { "skyblue",			{ 0x87/255., 0xce/255., 0xeb/255. } },
+  { "slateblue",		{ 0x6a/255., 0x5a/255., 0xcd/255. } },
+  { "slategray",		{ 0x70/255., 0x80/255., 0x90/255. } },
+  { "slategrey",		{ 0x70/255., 0x80/255., 0x90/255. } },
+  { "snow",			{ 0xff/255., 0xfa/255., 0xfa/255. } },
+  { "springgreen",		{ 0x00/255., 0xff/255., 0x7f/255. } },
+  { "steelblue",		{ 0x46/255., 0x82/255., 0xb4/255. } },
+  { "tan",			{ 0xd2/255., 0xb4/255., 0x8c/255. } },
+  { "teal",			{ 0x00/255., 0x80/255., 0x80/255. } },
+  { "thistle",			{ 0xd8/255., 0xbf/255., 0xd8/255. } },
+  { "tomato",			{ 0xff/255., 0x63/255., 0x47/255. } },
+  { "turquoise",		{ 0x40/255., 0xe0/255., 0xd0/255. } },
+  { "violet",			{ 0xee/255., 0x82/255., 0xee/255. } },
+  { "wheat",			{ 0xf5/255., 0xde/255., 0xb3/255. } },
+  { "white",			{ 0xff/255., 0xff/255., 0xff/255. } },
+  { "whitesmoke",		{ 0xf5/255., 0xf5/255., 0xf5/255. } },
+  { "yellow",			{ 0xff/255., 0xff/255., 0x00/255. } },
+  { "yellowgreen",		{ 0x9a/255., 0xcd/255., 0x32/255. } },
+};
+
+bool
+ccd_color_parse_name (char const	*css_color_name, 
+		      ccd_color_t	*color)
+{
+	g_return_val_if_fail (css_color_name && color, false);
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_color_map); i++) {
+		if (0 == g_ascii_strcasecmp (_color_map[i].name, css_color_name)) {
+			color->red = _color_map[i].color.red;
+			color->green = _color_map[i].color.green;
+			color->blue = _color_map[i].color.blue;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static gboolean
+hex (char const		*spec,
+     int		 len,
+     unsigned int	*c)
+{
+	const char *end;
+
+	*c = 0;
+	for (end = spec + len; spec != end; spec++)
+		if (g_ascii_isxdigit (*spec))
+			*c = (*c << 4) | g_ascii_xdigit_value (*spec);
+	else
+		return false;
+
+	return true;
+}
+
+bool
+ccd_color_parse_hex (char const		*spec,
+		     ccd_color_t	*color)
+{
+	size_t		len;
+	unsigned int	r, g, b;
+
+	g_return_val_if_fail (spec, false);
+
+	len = strlen (spec);
+	if (len % 3 || len < 3 || len > 12)
+		return false;
+
+	len /= 3;
+
+	if (!hex (spec, len, &r) ||
+	    !hex (spec + len, len, &g) ||
+	    !hex (spec + len * 2, len, &b))
+		return false;
+
+	if (color) {
+		int bits = len * 4;
+		r <<= 16 - bits;
+		g <<= 16 - bits;
+		b <<= 16 - bits;
+		while (bits < 16) {
+			r |= (r >> bits);
+			g |= (g >> bits);
+			b |= (b >> bits);
+			bits *= 2;
+		}
+		color->red   = r / 255.;
+		color->green = g / 255.;
+		color->blue  = b / 255.;
+	}
+
+	return true;
+}
+
+ccd_property_spec_t
+ccd_color_parse (ccd_color_t	*self,
+		 CRTerm	const	*value)
+{
+	ccd_property_spec_t	type;
+	bool			ret;
+
+	g_return_val_if_fail (self && value, false);
+
+	switch (value->type) {
+	case TERM_IDENT:
+		type = ccd_property_parse_type (value);
+		if (type != CCD_PROPERTY_SPEC_UNKNOWN) {
+			return type;
+		}
+		ret = ccd_color_parse_name (
+			cr_string_peek_raw_str (value->content.str), self);
+		if (ret)
+			return CCD_PROPERTY_SPEC_SPECIFIC;
+		else
+		      return CCD_PROPERTY_SPEC_UNKNOWN;
+	case TERM_HASH:
+		ret = ccd_color_parse_hex (
+			cr_string_peek_raw_str (value->content.str), self);
+		if (ret)
+			return CCD_PROPERTY_SPEC_SPECIFIC;
+		else
+		      return CCD_PROPERTY_SPEC_UNKNOWN;
+	case TERM_RGB:
+		self->red = value->content.rgb->red;
+		self->green = value->content.rgb->green;
+		self->blue = value->content.rgb->blue;
+		return CCD_PROPERTY_SPEC_SPECIFIC;
+	/* fall thru for all other enum values to prevent compiler warnings */
+	case TERM_NO_TYPE:
+	case TERM_NUMBER:
+	case TERM_FUNCTION:
+	case TERM_STRING:
+	case TERM_URI:
+	case TERM_UNICODERANGE:
+	default:
+		return CCD_PROPERTY_SPEC_UNKNOWN;
+	}
+}
+
+void
+ccd_color_dump (ccd_color_t const *self)
+{
+	printf ("rgb(%.3f,%.3f,%.3f)", self->red, self->green, self->blue);
+}
+

Added: branches/bzr/libccd/ccd/ccd-color.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-color.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,48 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_COLOR_H
+#define CCD_COLOR_H
+
+#include <stdbool.h>
+#include <glib.h>
+#include <libcroco/libcroco.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-property.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	double red;
+	double green;
+	double blue;
+} ccd_color_t;
+
+bool ccd_color_parse_name (char const *css_color_name, ccd_color_t *color);
+
+bool ccd_color_parse_hex (char const *OxRRGGBB, ccd_color_t *color);
+
+ccd_property_spec_t ccd_color_parse (ccd_color_t *self, CRTerm const *value);
+
+void ccd_color_dump (ccd_color_t const *self);
+
+G_END_DECLS
+
+#endif /* CCD_COLOR_H */
+

Added: branches/bzr/libccd/ccd/ccd-features.h.in
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-features.h.in	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,30 @@
+/* The CSS Box Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_FEATURES_H
+#define CCD_FEATURES_H
+
+/* Enable debug code */
+#undef CCD_DEBUG
+
+/* Support for drawing Gtk+ primitives like `box-gap' */
+#undef CCD_WITH_GTK
+
+#endif /* CCD_FEATURES_H */
+

Added: branches/bzr/libccd/ccd/ccd-gtk-style.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-gtk-style.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,125 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "ccd-gtk-style.h"
+
+/**
+ * ccd_style_draw_gap:
+ * @self:	a ccd_style_t.
+ * @cr:		the target to draw onto.
+ * @x:		the starting x coordinate.
+ * @y:		the starting y coordinate.
+ * @width:	width of the outline to draw.
+ * @height:	height of the outline to draw.
+ * @gap_side:	side in which to leave the gap.
+ * @gap_start:	starting position of the gap.
+ * @gap_width:	width of the gap.
+ *
+ * Draw a rectangle with gap using this style instance.
+ **/
+void
+ccd_style_draw_gap (ccd_style_t	const	*self, 
+		    cairo_t		*cr, 
+		    int32_t		 x,
+		    int32_t		 y,
+		    int32_t		 width,
+		    int32_t		 height, 
+		    GtkPositionType	 gap_side,
+		    int32_t		 gap_start,
+		    int32_t		 gap_width)
+{
+	if (self->background) {
+		ccd_background_draw (self->background, cr, x, y, width, height);
+	}
+
+	switch (gap_side) {
+	case GTK_POS_LEFT:
+		if (gap_start > y || gap_width < height) {
+			/* Draw gap only if it's not over the whole border. */
+			ccd_border_draw (self->left, NULL, NULL, NULL, cr, 
+					 x, y, 0, gap_start);
+			ccd_border_draw (self->left, NULL, NULL, NULL, cr, 
+					 x, y + gap_start + gap_width, 
+					 0, height - gap_start - gap_width);
+		}
+		ccd_border_draw (NULL, self->top, self->right, self->bottom, cr,
+				 x, y, width, height);
+		break;
+	case GTK_POS_TOP:
+		if (gap_start > x || gap_width < width) {
+			/* Draw gap only if it's not over the whole border. */
+			ccd_border_draw (NULL, self->top, NULL, NULL, cr, 
+					 x, y, gap_start, 0);
+			ccd_border_draw (NULL, self->top, NULL, NULL, cr, 
+					 x + gap_start + gap_width, y, 
+					 width - gap_start - gap_width, 0);
+		}
+		ccd_border_draw (self->left, NULL, self->right, self->bottom, cr,
+				 x, y, width, height);
+		break;
+	case GTK_POS_RIGHT:
+		if (gap_start > y || gap_width < height) {
+			/* Draw gap only if it's not over the whole border. */
+			ccd_border_draw (self->left, NULL, NULL, NULL, cr, 
+					 x + width, y, 0, gap_start);
+			ccd_border_draw (self->left, NULL, NULL, NULL, cr, 
+					 x + width, y + gap_start + gap_width, 
+					 0, height - gap_start - gap_width);
+		}
+		ccd_border_draw (self->left, self->top, NULL, self->bottom, cr,
+				 x, y, width, height);
+		break;
+	case GTK_POS_BOTTOM:
+		if (gap_start > x || gap_width < width) {
+			/* Draw gap only if it's not over the whole border. */
+			ccd_border_draw (NULL, NULL, NULL, self->bottom, cr,
+					 x, y + height, gap_start, 0);
+			ccd_border_draw (NULL, NULL, NULL, self->bottom, cr,
+					 x + gap_start + gap_width, y + height,
+					 width - gap_start - gap_width, 0);
+		}
+		ccd_border_draw (self->left, self->top, self->right, NULL, cr,
+				 x, y, width, height);
+		break;
+	default:
+		g_assert_not_reached ();
+		return;	/* prevent error building without assertions */
+	}
+}
+
+/**
+ * ccd_style_draw_polygon:
+ * @self:	a ccd_style_t.
+ * @cr:		the target to draw onto.
+ * @points:	an array of #GdkPoint<!-- -->s.
+ * @n_points:	length of @points.
+ * @fill:	%true if the polygon should be filled.
+ *
+ * Draw a rectangle with gap using this style instance.
+ **/
+void
+ccd_style_draw_polygon (ccd_style_t const	*self, 
+			cairo_t			*cr, 
+			GdkPoint		*points,
+			int32_t			 n_points,
+			bool		 fill)
+{
+
+}
+

Added: branches/bzr/libccd/ccd/ccd-gtk-style.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-gtk-style.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,43 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_GTK_STYLE_H
+#define CCD_GTK_STYLE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <cairo.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-style.h>
+
+G_BEGIN_DECLS
+
+void ccd_style_draw_gap (ccd_style_t const *self, cairo_t *cr, 
+			 int32_t x, int32_t y, int32_t width, int32_t height, 
+			 GtkPositionType gap_side, int32_t gap_x, int32_t gap_width);
+
+void ccd_style_draw_polygon (ccd_style_t const *self, cairo_t *cr, 
+			     GdkPoint *points, int32_t n_points, bool fill);
+
+G_END_DECLS
+
+#endif /* CCD_GTK_STYLE_H */
+

Added: branches/bzr/libccd/ccd/ccd-image.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-image.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,89 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * Functions ccd_color_parse_hex() and hex() are derived from pango,
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdbool.h>
+#include <string.h>
+#include "ccd-image.h"
+
+void
+ccd_image_discard (ccd_image_t *self)
+{
+	if (self->uri) {
+		g_free (self->uri);
+		self->uri = NULL;
+	}
+
+	if (self->surface) {
+		cairo_surface_destroy (self->surface);
+		self->surface = NULL;
+	}
+}
+
+static bool
+load_image (ccd_image_t	*self, 
+	    char const	*uri)
+{
+	// TODO continue here.
+// cairo_surface_t*    cairo_image_surface_create_from_png (const char *filename);
+
+	return true;
+}
+
+ccd_property_spec_t
+ccd_image_parse (ccd_image_t	*self,
+		 CRTerm const	*value)
+{
+	bool ret;
+
+	switch (value->type) {
+	case TERM_IDENT:
+		if (0 == strcmp ("none", 
+				 cr_string_peek_raw_str (value->content.str))) {
+			self->uri = g_strdup ("none");
+			return CCD_PROPERTY_SPEC_NONE;
+		} else if (0 == strcmp ("inherit", 
+				 cr_string_peek_raw_str (value->content.str))) {
+			self->uri = g_strdup ("inherit");
+			return CCD_PROPERTY_SPEC_INHERIT;
+		} else {
+			return CCD_PROPERTY_SPEC_UNKNOWN;
+		}
+		break;
+	case TERM_URI:
+		self->uri = g_strdup (cr_string_peek_raw_str (value->content.str));
+		ret = load_image (self, self->uri);
+		if (ret)
+			return CCD_PROPERTY_SPEC_SPECIFIC;
+		else
+		      return CCD_PROPERTY_SPEC_UNKNOWN;
+		break;
+	default:
+		return CCD_PROPERTY_SPEC_UNKNOWN;
+	}
+}
+
+void
+ccd_image_dump (ccd_image_t const *self)
+{
+	printf ("%s", self->uri);
+}
+

Added: branches/bzr/libccd/ccd/ccd-image.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-image.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,45 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_IMAGE_H
+#define CCD_IMAGE_H
+
+#include <cairo.h>
+#include <glib.h>
+#include <libcroco/libcroco.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-property.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	char		*uri;
+	cairo_surface_t *surface;
+} ccd_image_t;
+
+ccd_property_spec_t ccd_image_parse (ccd_image_t *self, CRTerm const *value);
+
+void ccd_image_discard (ccd_image_t *self);
+
+void ccd_image_dump (ccd_image_t const *self);
+
+G_END_DECLS
+
+#endif /* CCD_IMAGE_H */
+

Added: branches/bzr/libccd/ccd/ccd-node.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-node.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,134 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "ccd-node.h"
+
+static bool
+is_a (ccd_node_t const	*self,
+      char const	*type_name)
+{
+	return FALSE;
+}
+
+static ccd_node_t * 
+get_container (ccd_node_t const *self)
+{
+	return NULL;
+}
+
+static ccd_node_t * 
+get_base_style (ccd_node_t const *self)
+{
+	return NULL;
+}
+
+static char const * 
+get_type (ccd_node_t const *self)
+{
+	return NULL;
+}
+
+static char const * 
+get_id (ccd_node_t const *self)
+{
+	return NULL;
+}
+
+static char const * 
+get_class (ccd_node_t const *self)
+{
+	return NULL;
+}
+
+static char const * 
+get_pseudo_class (ccd_node_t const *self)
+{
+	return NULL;
+}
+
+static char const * 
+get_attribute (ccd_node_t const	*self,
+	       char const	*name)
+{
+	return NULL;
+}
+
+static void
+release (ccd_node_t *self)
+{
+	return;
+}
+
+static const ccd_node_class_t _default_node_class = {
+	.is_a			= is_a,
+	.get_container		= get_container,
+	.get_base_style		= get_base_style,
+	.get_id			= get_id,
+	.get_type		= get_type,
+	.get_class		= get_class,
+	.get_pseudo_class	= get_pseudo_class,
+	.get_attribute		= get_attribute,
+	.release		= release
+};
+
+static ccd_node_class_t _node_class = {
+	.is_a			= is_a,
+	.get_container		= get_container,
+	.get_base_style		= get_base_style,
+	.get_id			= get_id,
+	.get_type		= get_type,
+	.get_class		= get_class,
+	.get_pseudo_class	= get_pseudo_class,
+	.get_attribute		= get_attribute,
+	.release		= release
+};
+
+ccd_node_class_t const *
+ccd_node_get_class (void)
+{
+	return &_node_class;
+}
+
+typedef void (*node_f) (void);
+#define N_ELEMENTS(vtable_) (sizeof (vtable_) / sizeof (node_f))
+
+void
+ccd_node_set_class (ccd_node_class_t const *node_class)
+{
+	node_f		*node_vtable;
+	node_f const	*new_node_vtable;
+
+	g_return_if_fail (node_class);
+
+	node_vtable = (node_f *) &_node_class;
+	new_node_vtable = (node_f *) node_class;
+	for (unsigned int i = 0; i < N_ELEMENTS (_node_class); i++) {
+		/* Override only implemented methods. */
+		if (new_node_vtable[i]) {
+			node_vtable[i] = new_node_vtable[i];
+		}
+	}
+}
+
+void
+ccd_node_reset_class (void)
+{
+	ccd_node_set_class (&_default_node_class);
+}
+

Added: branches/bzr/libccd/ccd/ccd-node.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-node.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,172 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_NODE_H
+#define CCD_NODE_H
+
+#include <stdbool.h>
+#include <glib.h>
+#include <ccd/ccd-features.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ccd_node_t:
+ * 
+ * Stack-allocatable struct representing a document node. Used for querying the 
+ * #ccd_stylesheet_t.
+ * 
+ * <emphasis>Memory management:</emphasis> Unless specified otherwise, objects 
+ * of this kind are under the responsibility of the libccd consumer.
+ **/
+typedef void * ccd_node_t;
+
+/** 
+ * ccd_node_is_a_f:
+ * @self: a #ccd_node_t.
+ *
+ * Hook function to query whether a #ccd_node_t is of a certain type.
+ *
+ * Returns: %TRUE if matches.
+ **/
+typedef bool (*ccd_node_is_a_f) (ccd_node_t const *self, 
+				 char const *type_name);
+
+/** 
+ * ccd_node_get_container_f:
+ * @self: a #ccd_node_t.
+ *
+ * Hook function to query the container of a #ccd_node_t.
+ *
+ * Returns: newly allocated container node or %NULL.
+ **/
+typedef ccd_node_t * (*ccd_node_get_container_f) (ccd_node_t const *self);
+
+/** 
+ * ccd_node_get_base_style_f:
+ * @self: a #ccd_node_t.
+ *
+ * Hook function to query the name of the style a #ccd_node_t derives from.
+ *
+ * Returns: base style or %NULL. The returned value must be valid until
+ * it is released.
+ **/
+typedef ccd_node_t * (*ccd_node_get_base_style_f) (ccd_node_t const *self);
+
+/** 
+ * ccd_node_get_type_f:
+ * @self: a #ccd_node_t.
+ *
+ * Hook function to query the type name of a #ccd_node_t.
+ *
+ * Returns: node type name or %NULL. The returned value must be valid until
+ * the current stylesheet query returns.
+ **/
+typedef const char * (*ccd_node_get_type_f) (ccd_node_t const *self);
+
+/** 
+ * ccd_node_get_id_f:
+ * @self: a #ccd_node_t.
+ *
+ * Hook function to query the ID of a #ccd_node_t.
+ *
+ * Returns: node ID or %NULL. The returned value must be valid until
+ * the current stylesheet query returns.
+ **/
+typedef const char * (*ccd_node_get_id_f) (ccd_node_t const *self);
+
+/** 
+ * ccd_node_get_class_f:
+ * @self: a #ccd_node_t.
+ *
+ * Hook function to query the class name of a #ccd_node_t.
+ *
+ * Returns: node class name or %NULL. The returned value must be valid until
+ * the current stylesheet query returns.
+ **/
+typedef const char * (*ccd_node_get_class_f) (ccd_node_t const *self);
+
+/** 
+ * ccd_node_get_pseudo_class_f:
+ * @self: a #ccd_node_t.
+ *
+ * Hook function to query the pseudo-class name of a #ccd_node_t.
+ *
+ * Returns: node pseudo-class name or %NULL. The returned value must be valid until
+ * the current stylesheet query returns.
+ **/
+typedef const char * (*ccd_node_get_pseudo_class_f) (ccd_node_t const *self);
+
+/** 
+ * ccd_node_get_attribute_f:
+ * @self: a #ccd_node_t.
+ * @name: attribute name.
+ *
+ * Hook function to query a #ccd_node_t's attributes.
+ *
+ * Returns: attribute value or %NULL. The returned value must be valid until
+ * the current stylesheet query returns.
+ **/
+typedef const char * (*ccd_node_get_attribute_f) (ccd_node_t const	*self,
+						     char const		*name);
+
+/** 
+ * ccd_node_release_f:
+ * @self: a #ccd_node_t.
+ *
+ * Hook function to deallocate a #ccd_node_t instance.
+ **/
+typedef void (*ccd_node_release_f) (ccd_node_t *self);
+
+/**
+ * ccd_node_class_t:
+ * @get_container:	a #ccd_node_get_container_f.
+ * @get_base_style:	a #ccd_node_get_base_style_f.
+ * @get_id:		a #ccd_node_get_id_f.
+ * @get_type:		a #ccd_node_get_type_f.
+ * @get_class:		a #ccd_node_get_class_f.
+ * @get_pseudo_class:	a #ccd_node_get_pseudo_class_f.
+ * @get_attribute:	a #ccd_node_get_attribute_f.
+ * @release:		a #ccd_node_release_f.
+ *
+ * Dispatch table a CCD consumer has to fill so the selection engine can 
+ * retrieve information about the document the document.
+ *
+ * The implemented dispatch table needs to be passed to #ccd_init.
+ **/
+typedef struct {
+	ccd_node_is_a_f			is_a;
+	ccd_node_get_container_f	get_container;
+	ccd_node_get_base_style_f	get_base_style;
+	ccd_node_get_id_f		get_id;
+	ccd_node_get_type_f		get_type;
+	ccd_node_get_class_f		get_class;
+	ccd_node_get_pseudo_class_f	get_pseudo_class;
+	ccd_node_get_attribute_f	get_attribute;
+	ccd_node_release_f		release;
+} ccd_node_class_t;
+
+ccd_node_class_t const *	ccd_node_get_class	(void);
+void				ccd_node_set_class	(ccd_node_class_t const *node_class);
+void				ccd_node_reset_class	(void);
+
+G_END_DECLS
+
+#endif /* CCD_NODE_H */
+

Added: branches/bzr/libccd/ccd/ccd-parser.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-parser.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,291 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <libcroco/libcroco.h>
+#include "ccd-block.h"
+#include "ccd-parser.h"
+#include "ccd-selector.h"
+#include "ccd-selector-group-priv.h"
+
+typedef struct {
+	GSList		*blocks;
+	GHashTable	*type_rules;
+	GHashTable	*class_rules;
+	GHashTable	*id_rules;
+	ccd_block_t	*block;
+} ccd_parser_info_t;
+
+#define HANDLER_GET_INFO(handler_) ((ccd_parser_info_t *) handler->app_data)
+
+static ccd_attribute_selector_match_t
+map_attribute_selector_match (enum AttrMatchWay cr_match)
+{
+	switch (cr_match) {
+	case SET:
+		return CCD_ATTRIBUTE_SELECTOR_MATCH_EXISTS;
+	case EQUALS:
+		return CCD_ATTRIBUTE_SELECTOR_MATCH_EQUALS;
+	case INCLUDES:
+	case DASHMATCH:
+	case NO_MATCH:
+	default:
+		g_assert_not_reached ();
+	}
+
+	/* fall back to (my interpretation of) default behaviour */
+	return CCD_ATTRIBUTE_SELECTOR_MATCH_EXISTS;
+}
+
+static ccd_selector_t *
+walk_additional_selector (CRAdditionalSel *cr_add_sel)
+{
+	ccd_selector_t			*selector;
+	char const			*name;
+	char const			*value;
+	ccd_attribute_selector_match_t	 match;
+
+	g_return_val_if_fail (cr_add_sel, NULL);
+
+	name = NULL;
+	value = NULL;
+	selector = NULL;
+	switch (cr_add_sel->type) {
+	case CLASS_ADD_SELECTOR:
+		name = cr_string_peek_raw_str (cr_add_sel->content.class_name);
+		selector = ccd_class_selector_new (name);
+		break;
+	case PSEUDO_CLASS_ADD_SELECTOR:
+		name = cr_string_peek_raw_str (cr_add_sel->content.pseudo->name);
+		selector = ccd_pseudo_class_selector_new (name);
+		break;
+	case ID_ADD_SELECTOR:
+		name = cr_string_peek_raw_str (cr_add_sel->content.id_name);
+		selector = ccd_pseudo_class_selector_new (name);
+		break;
+	case ATTRIBUTE_ADD_SELECTOR:
+		name = cr_string_peek_raw_str (cr_add_sel->content.attr_sel->name);
+		value = cr_string_peek_raw_str (cr_add_sel->content.attr_sel->value);
+		match = map_attribute_selector_match (cr_add_sel->content.attr_sel->match_way);
+		selector = ccd_attribute_selector_new (name, value, match);
+		break;
+	case NO_ADD_SELECTOR:
+	default:
+		g_assert_not_reached ();
+	}
+
+	g_return_val_if_fail (selector, NULL);
+
+	return selector;
+}
+
+static ccd_selector_t *
+walk_simple_selector_r (CRSimpleSel *cr_simple_sel)
+{
+	ccd_selector_t *selector;
+
+	g_return_val_if_fail (cr_simple_sel, NULL);
+
+	selector = NULL;
+	if (UNIVERSAL_SELECTOR & cr_simple_sel->type_mask) {
+		selector = ccd_universal_selector_new ();
+	} else if (TYPE_SELECTOR & cr_simple_sel->type_mask) {
+		selector = ccd_type_selector_new (cr_string_peek_raw_str (cr_simple_sel->name));
+	} else {
+		char const *sel;
+		sel = cr_simple_sel->name ? cr_string_peek_raw_str (cr_simple_sel->name) : NULL;
+		g_warning ("Unknown selector '%s'\n", sel);
+		return NULL;
+	}
+
+	g_return_val_if_fail (selector, NULL);
+
+	if (cr_simple_sel->add_sel) {
+		ccd_selector_t *refinement;
+		refinement = walk_additional_selector (cr_simple_sel->add_sel);
+		ccd_selector_refine (selector, refinement);
+	}
+
+	if (cr_simple_sel->next) {
+		ccd_selector_t *descendant;
+		descendant = walk_simple_selector_r (cr_simple_sel->next);
+		selector = ccd_selector_append (selector, descendant);
+	}
+
+	return selector;
+}
+
+static void
+start_selector_cb (CRDocHandler	*handler,
+		   CRSelector	*cr_sel)
+{
+	ccd_parser_info_t *info;
+
+	info = HANDLER_GET_INFO (handler);
+
+	g_assert (info && info->block == NULL);
+
+	info->block = ccd_block_new ();
+}
+
+static void
+property_cb (CRDocHandler	*handler,
+	     CRString		*name,
+	     CRTerm		*values,
+	     gboolean	 	 is_important)
+{
+	ccd_parser_info_t	*info;
+	char const 		*property;
+
+	info = HANDLER_GET_INFO (handler);
+
+	g_assert (info && info->block);
+
+	property = cr_string_peek_raw_str (name);
+	if (0 == strcmp ("border", property) ||
+	    0 == strncmp ("border-", property, sizeof ("border-") - 1)) {
+		ccd_border_parse (&info->block->border, property, values);
+	} else if (0 == strcmp ("background", property) || 
+		   0 == strncmp ("background-", property, sizeof ("background-") - 1)) {
+		ccd_background_parse (&info->block->background, property, values);
+	}
+}
+
+static void
+end_selector_cb (CRDocHandler	*handler,
+		 CRSelector	*cr_sel)
+{
+	ccd_parser_info_t	*info;
+	ccd_selector_t		*selector;
+	ccd_selector_group_t	*group;
+	CRSelector		*iter;
+	GHashTable		*rules;
+	char const		*key;
+
+	g_assert (HANDLER_GET_INFO (handler));
+
+	info = HANDLER_GET_INFO (handler);
+
+	iter = cr_sel;
+	do {
+		selector = walk_simple_selector_r (iter->simple_sel);
+		if (selector) {
+			ccd_selector_set_block (selector, info->block);
+
+			rules = NULL;
+			if (ccd_selector_is_type (selector)) {
+				rules = info->type_rules;
+			} else if (ccd_selector_is_class (selector)) {
+				rules = info->class_rules;
+			} else if (ccd_selector_is_id (selector)) {
+				rules = info->id_rules;
+			} else {
+				g_assert_not_reached ();
+			}
+
+			key = ccd_selector_get_key (selector);
+			g_assert (key);
+
+			group = (ccd_selector_group_t *) g_hash_table_lookup (rules, key);
+			if (!group) {
+				group = ccd_selector_group_new ();
+				g_hash_table_insert (rules, (char *) key, group);
+			}
+			ccd_selector_group_add_selector (group, selector);
+		}
+	} while (NULL != (iter = iter->next));
+
+	info->block = NULL;
+}
+
+GSList *
+ccd_parser_parse_file (char const	*css_file,
+		       GHashTable	*type_rules,
+		       GHashTable	*class_rules,
+		       GHashTable	*id_rules)
+{
+	CRParser		*parser;
+	CRDocHandler		*handler;
+	ccd_parser_info_t	 info;
+	enum CRStatus		 ret;
+
+	g_assert (css_file && type_rules && class_rules && id_rules);
+
+	parser = cr_parser_new_from_file ((guchar *) css_file, CR_UTF_8);
+
+	handler = cr_doc_handler_new ();
+	handler->app_data = (gpointer) &info;
+	info.blocks = NULL;
+	info.type_rules = type_rules;
+	info.class_rules = class_rules;
+	info.id_rules = id_rules;
+	info.block = NULL;
+
+	handler->start_selector = start_selector_cb;
+        handler->property = property_cb;
+	handler->end_selector = end_selector_cb;
+
+	cr_parser_set_sac_handler (parser, handler);
+	ret = cr_parser_parse (parser);
+
+	cr_doc_handler_destroy (handler);	
+	cr_parser_destroy (parser);
+
+	return info.blocks;
+}
+
+GSList *
+ccd_parser_parse_buffer (char const	*buffer,
+			 size_t		 size,
+			 GHashTable	*type_rules,
+			 GHashTable	*class_rules,
+			 GHashTable	*id_rules)
+{
+	CRParser		*parser;
+	CRDocHandler		*handler;
+	ccd_parser_info_t	 info;
+	enum CRStatus		 ret;
+
+	g_assert (buffer && size && type_rules && class_rules && id_rules);
+
+	parser = cr_parser_new_from_buf ((guchar *) buffer, (gulong) size, 
+					 CR_UTF_8, false);
+
+	handler = cr_doc_handler_new ();
+	handler->app_data = (gpointer) &info;
+	info.blocks = NULL;
+	info.type_rules = type_rules;
+	info.class_rules = class_rules;
+	info.id_rules = id_rules;
+	info.block = NULL;
+
+	handler->start_selector = start_selector_cb;
+        handler->property = property_cb;
+	handler->end_selector = end_selector_cb;
+
+	cr_parser_set_sac_handler (parser, handler);
+	ret = cr_parser_parse (parser);
+
+	cr_doc_handler_destroy (handler);	
+	cr_parser_destroy (parser);
+
+	return info.blocks;
+}
+

Added: branches/bzr/libccd/ccd/ccd-parser.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-parser.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,39 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_PARSER_H
+#define CCD_PARSER_H
+
+#include <stdbool.h>
+#include <glib.h>
+#include <ccd/ccd-features.h>
+
+G_BEGIN_DECLS
+
+GSList * ccd_parser_parse_buffer (char const *buffer, size_t size, 
+				  GHashTable *type_rules, 
+				  GHashTable *class_rules, GHashTable *id_rules);
+
+GSList * ccd_parser_parse_file (char const *css_file, GHashTable *type_rules, 
+				GHashTable *class_rules, GHashTable *id_rules);
+
+G_END_DECLS
+
+#endif /* CCD_PARSER_H */
+

Added: branches/bzr/libccd/ccd/ccd-property.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-property.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,39 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "ccd-property.h"
+
+ccd_property_spec_t
+ccd_property_parse_type (CRTerm const *value)
+{
+	char const *str;
+
+	if (TERM_IDENT == value->type) {
+		str = cr_string_peek_raw_str (value->content.str);
+		if (0 == strcmp ("none", str)) {
+			return CCD_PROPERTY_SPEC_NONE;
+		} else if (0 == strcmp ("inherit", str)) {
+			return CCD_PROPERTY_SPEC_INHERIT;
+		}
+	}
+
+	return CCD_PROPERTY_SPEC_UNKNOWN;
+}
+

Added: branches/bzr/libccd/ccd/ccd-property.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-property.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,41 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_PROPERTY_H
+#define CCD_PROPERTY_H
+
+#include <glib.h>
+#include <libcroco/libcroco.h>
+#include <ccd/ccd-features.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+	CCD_PROPERTY_SPEC_UNKNOWN = 0,
+	CCD_PROPERTY_SPEC_NONE,
+	CCD_PROPERTY_SPEC_INHERIT,	/* not implemented yet */
+	CCD_PROPERTY_SPEC_SPECIFIC
+} ccd_property_spec_t;
+
+ccd_property_spec_t ccd_property_parse_type (CRTerm const *value);
+
+G_END_DECLS
+
+#endif /* CCD_PROPERTY_H */
+

Added: branches/bzr/libccd/ccd/ccd-selector-group-priv.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-selector-group-priv.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,53 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_SELECTOR_GROUP_PRIV_H
+#define CCD_SELECTOR_GROUP_PRIV_H
+
+#include <stdbool.h>
+#include <glib.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-node.h>
+#include <ccd/ccd-selector-group.h>
+#include <ccd/ccd-selector.h>
+#include <ccd/ccd-style.h>
+
+G_BEGIN_DECLS
+
+void ccd_selector_group_add_selector	(ccd_selector_group_t *self, 
+					 ccd_selector_t *selector);
+void ccd_selector_group_merge		(ccd_selector_group_t *self,
+					 ccd_selector_group_t const *group);
+void ccd_selector_group_merge_base	(ccd_selector_group_t *self,
+					 ccd_selector_group_t const *group);
+
+GSList const *	ccd_selector_group_get_dangling_selectors	(ccd_selector_group_t const *self);
+void		ccd_selector_group_clear_dangling_selectors	(ccd_selector_group_t *self);
+
+bool ccd_selector_group_query_collect (ccd_selector_group_t const *self, 
+				       ccd_node_t const *node, 
+				       ccd_selector_group_t *result_group,
+				       bool as_base);
+bool ccd_selector_group_query_apply (ccd_selector_group_t const *self, 
+			             ccd_node_t const *node, ccd_style_t *style);
+
+G_END_DECLS
+
+#endif /* CCD_SELECTOR_GROUP_PRIV_H */
+

Added: branches/bzr/libccd/ccd/ccd-selector-group.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-selector-group.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,436 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "ccd-selector-group-priv.h"
+
+typedef struct {
+	GSList *selectors;
+} ccd_selector_set_t;
+
+/**
+ * ccd_selector_group_t:
+ * @sets:		
+ * @min_specificity_e:	
+ * @dangling_selectors:
+ * 
+ * Represents a set of associated styling information. 
+ **/
+struct ccd_selector_group_ {
+	GTree		*sets;
+	unsigned int	 min_specificity_e;
+	GSList		*dangling_selectors;
+};
+
+static int
+compare (size_t	 key1,
+	 size_t	 key2, 
+	 void	*data)
+{
+	return key1 - key2;
+}
+
+static void
+free_set (ccd_selector_set_t *set)
+{
+	GSList		*iter;
+	ccd_selector_t	*selector;
+
+	g_assert (set);
+
+	iter = set->selectors;
+	while (iter) {
+		selector = (ccd_selector_t *) iter->data;
+		iter = g_slist_remove (iter, selector);
+		ccd_selector_free (selector);
+	}
+
+	g_free (set);
+}
+
+/**
+ * ccd_selector_group_new:
+ *
+ * Create an empty selector group.
+ *
+ * A newly allocated #ccd_selector_group_t.
+ **/
+ccd_selector_group_t *
+ccd_selector_group_new (void)
+{
+	ccd_selector_group_t *self;
+
+	self = g_new0 (ccd_selector_group_t, 1);
+	self->sets = g_tree_new_full ((GCompareDataFunc) compare, NULL, NULL, 
+					(GDestroyNotify) free_set);
+
+	self->min_specificity_e = CCD_SELECTOR_MAX_SPECIFICITY;
+
+	return self;
+}
+
+/**
+ * ccd_selector_group_free:
+ * @self: a #ccd_selector_group_t.
+ * 
+ * Free the selector group and all associated resources.
+ **/
+void
+ccd_selector_group_free (ccd_selector_group_t *self)
+{
+	g_assert (self);
+
+	g_tree_destroy (self->sets);
+	g_free (self);
+}
+
+/*
+ * The attribute `min_specificity_e' is decremented before each recursive 
+ * invocation, so base styles are cascaded root-first.
+ */
+static void
+query_base_r (ccd_selector_group_t	*self,
+	      ccd_node_t const		*node)
+{
+	ccd_node_class_t const	*node_class;
+	ccd_selector_t		*selector;
+	ccd_node_t		*base;
+	char const		*type_name;
+	unsigned int		 specificity_e;
+
+	g_assert (self->min_specificity_e >= 0);
+
+	node_class = ccd_node_get_class ();
+
+	specificity_e = self->min_specificity_e;
+	base = node_class->get_base_style (node);
+	if (base) {
+		/* recurse */
+		g_assert (self->min_specificity_e > 0);
+		self->min_specificity_e--;
+		query_base_r (self, base);
+		node_class->release (base);
+	}
+
+	/* create dangling base type selector and remember for later fixup */
+	type_name = node_class->get_type (node);
+	selector = ccd_base_type_selector_new (type_name, specificity_e);
+	self->dangling_selectors = g_slist_prepend (self->dangling_selectors, selector);
+}
+
+/*
+ * Takes ownership of the selector.
+ */
+void
+ccd_selector_group_add_selector (ccd_selector_group_t	*self, 
+				 ccd_selector_t		*selector)
+{
+	ccd_selector_set_t	*set;
+	size_t			 specificity;
+
+	g_return_if_fail (self && selector);
+
+	/* insert or update the selector group */
+	specificity = ccd_selector_get_specificity (selector);
+	set = g_tree_lookup (self->sets, GSIZE_TO_POINTER (specificity));
+	if (!set) {
+		set = g_new0 (ccd_selector_set_t, 1);
+		g_tree_insert (self->sets, GSIZE_TO_POINTER (specificity), set);
+	}
+	set->selectors = g_slist_prepend (set->selectors, selector);
+}
+
+static unsigned int
+calculate_min_specificity_e (ccd_selector_group_t	*group,
+			     unsigned int		 n_specificities)
+{
+	unsigned int specificity_e;
+
+	/* The tree is walked in order, so we remember how many 
+	 * specificities `e' will be required to insert the merged selectors at 
+	 * the right place. `- 1' because "group->min_specificity_e" already has
+	 * the next free value. */
+	g_assert (((signed) group->min_specificity_e - (signed) n_specificities - 1) >= 0);
+	specificity_e = group->min_specificity_e - n_specificities - 1;
+
+	group->min_specificity_e -= n_specificities;
+	g_assert (group->min_specificity_e >= 0);
+
+	return specificity_e;
+}
+
+typedef struct {
+	ccd_selector_group_t	*self;
+	bool			 as_base;
+	unsigned int		 specificity_e;
+} traverse_merge_info_t;
+
+static bool
+traverse_merge (size_t			 	 specificity,
+		ccd_selector_set_t const	*set,
+		traverse_merge_info_t		*info)
+{
+	GSList const		*iter;
+	ccd_selector_t const	*selector;
+	ccd_selector_t		*new_selector;
+
+	g_assert (info->self && set);
+
+	iter = set->selectors;
+	while (iter) {
+		selector = (ccd_selector_t const *) iter->data;
+		if (info->as_base) {
+			new_selector = ccd_selector_copy_as_base (selector, info->specificity_e);
+		} else {
+			new_selector = ccd_selector_copy (selector);
+		}
+		ccd_selector_group_add_selector (info->self, new_selector);
+		iter = iter->next;
+	}
+
+	info->specificity_e++;
+
+	return false;
+}
+
+void
+ccd_selector_group_merge (ccd_selector_group_t		*self,
+			  ccd_selector_group_t const	*group)
+{
+	traverse_merge_info_t info;
+
+	g_assert (self && group);
+
+	info.self = self;
+	info.as_base = false;
+	info.specificity_e = 0;
+	g_tree_foreach (group->sets, (GTraverseFunc) traverse_merge, &info);
+}
+
+void
+ccd_selector_group_merge_base (ccd_selector_group_t		*self,
+			       ccd_selector_group_t const	*group)
+{
+	traverse_merge_info_t info;
+
+	g_assert (self && group);
+
+	info.self = self;
+	info.as_base = true;
+	info.specificity_e = calculate_min_specificity_e (self, g_tree_nnodes (group->sets));
+
+	g_tree_foreach (group->sets, (GTraverseFunc) traverse_merge, &info);
+}
+
+GSList const *
+ccd_selector_group_get_dangling_selectors (ccd_selector_group_t const *self)
+{
+	g_assert (self);
+
+	return self->dangling_selectors;
+}
+
+void
+ccd_selector_group_clear_dangling_selectors (ccd_selector_group_t *self)
+{
+	ccd_selector_t	*selector;
+	GSList		*iter;
+
+	g_return_if_fail (self && self->dangling_selectors);
+
+	iter = self->dangling_selectors;
+	while (iter) {
+		selector = (ccd_selector_t *) iter->data;
+		iter = g_slist_remove (iter, selector);
+		ccd_selector_free (selector);
+	}
+
+	self->dangling_selectors = NULL;
+}
+
+typedef struct {
+	ccd_node_t const	*node;
+	ccd_selector_group_t	*result_group;
+	bool			 as_base;
+	unsigned int		 specificity_e;
+	bool			 ret;
+} traverse_query_info_t;
+
+static bool
+traverse_query (size_t			 specificity,
+		ccd_selector_set_t	*set,
+		traverse_query_info_t	*info)
+{
+	ccd_selector_t const	*selector;
+	ccd_selector_t		*new_selector;
+	GSList const		*iter;
+	bool			 ret;
+
+	iter = set->selectors;
+	while (iter) {
+		selector = (ccd_selector_t const *) iter->data;
+		ret = ccd_selector_query_apply (selector, info->node, NULL);
+		if (ret) {
+			if (info->as_base) {
+				new_selector = ccd_selector_copy_as_base (selector, info->specificity_e);
+			} else {
+				new_selector = ccd_selector_copy (selector);
+			}
+			ccd_selector_group_add_selector (info->result_group, new_selector);
+			info->specificity_e++;
+			info->ret = true;
+		}
+		iter = iter->next;
+	}
+
+	return false;
+}
+
+bool
+ccd_selector_group_query_collect (ccd_selector_group_t const	*self, 
+				  ccd_node_t const		*node, 
+				  ccd_selector_group_t		*result_group,
+				  bool				 as_base)
+{
+	traverse_query_info_t info;
+
+	g_assert (self && self->sets && node && result_group);
+
+	info.node = node;
+	info.result_group = result_group;
+	info.as_base = as_base;
+	info.specificity_e = calculate_min_specificity_e (result_group, g_tree_nnodes (self->sets));
+	info.ret = false;
+
+	g_tree_foreach (self->sets, (GTraverseFunc) traverse_query, &info);
+
+	return info.ret;
+}
+
+typedef struct {
+	ccd_node_t const	*node;
+	ccd_style_t		*style;
+	bool			 ret;
+} traverse_match_info_t;
+
+static bool
+traverse_match (size_t			 specificity,
+		ccd_selector_set_t	*set,
+		traverse_match_info_t	*info)
+{
+	GSList const *iter;
+
+	iter = set->selectors;
+	while (iter) {
+		info->ret |= ccd_selector_query_apply ((ccd_selector_t const *) iter->data, 
+						 info->node, info->style);
+		iter = iter->next;
+	}
+
+	return false;
+}
+
+bool
+ccd_selector_group_query_apply (ccd_selector_group_t const	*self,
+				ccd_node_t const		*node,
+				ccd_style_t			*style)
+{
+	traverse_match_info_t info;
+
+	g_assert (self && self->sets && node && style);
+
+	info.node = node;
+	info.style = style;
+	info.ret = false;
+
+	g_tree_foreach (self->sets, (GTraverseFunc) traverse_match, &info);
+
+	return info.ret;
+}
+
+static bool
+traverse_apply (size_t			 specificity,
+		ccd_selector_set_t	*set,
+		ccd_style_t		*style)
+{
+	GSList const *iter;
+
+	iter = set->selectors;
+	while (iter) {
+		ccd_selector_apply ((ccd_selector_t const *) iter->data, style);
+		iter = iter->next;
+	}
+
+	return false;
+}
+
+/**
+ * ccd_selector_group_apply:
+ * @self:	a #ccd_selector_group_t.
+ * @style:	a #ccd_style_t.
+ *
+ * Apply the styling information held by #self to #style.
+ **/
+void
+ccd_selector_group_apply (ccd_selector_group_t const	*self, 
+			  ccd_style_t			*style)
+{
+	g_assert (self && self->sets && style);
+
+	g_tree_foreach (self->sets, (GTraverseFunc) traverse_apply, style);
+}
+
+static bool
+traverse_dump (size_t			 specificity,
+	       ccd_selector_set_t	*set,
+	       void			*data)
+{
+	GSList const *iter;
+
+	iter = set->selectors;
+	while (iter) {
+		ccd_selector_dump ((ccd_selector_t const *) iter->data);
+		iter = iter->next;
+	}
+
+	return false;
+}
+
+/**
+ * ccd_selector_group_dump:
+ * @self:	a ccd_selector_group_t.
+ *
+ * Print informations about the internal state of this object.
+ **/
+void
+ccd_selector_group_dump (ccd_selector_group_t const *self)
+{
+	GSList const *iter;
+
+	g_return_if_fail (self);
+
+	g_tree_foreach (self->sets, (GTraverseFunc) traverse_dump, NULL);
+
+	iter = self->dangling_selectors;
+	while (iter) {
+		printf ("(dangling) ");
+		ccd_selector_dump ((ccd_selector_t const *) iter->data);
+		iter = iter->next;
+	}
+}
+

Added: branches/bzr/libccd/ccd/ccd-selector-group.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-selector-group.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,45 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_SELECTOR_GROUP_H
+#define CCD_SELECTOR_GROUP_H
+
+#include <stdbool.h>
+#include <glib.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-node.h>
+#include <ccd/ccd-selector.h>
+#include <ccd/ccd-style.h>
+
+G_BEGIN_DECLS
+
+typedef struct ccd_selector_group_ ccd_selector_group_t;
+
+ccd_selector_group_t *	ccd_selector_group_new	(void);
+void			ccd_selector_group_free	(ccd_selector_group_t *self);
+
+void ccd_selector_group_apply (ccd_selector_group_t const *self, 
+			       ccd_style_t *style);
+
+void ccd_selector_group_dump (ccd_selector_group_t const *self);
+
+G_END_DECLS
+
+#endif /* CCD_SELECTOR_GROUP_H */
+

Added: branches/bzr/libccd/ccd/ccd-selector.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-selector.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,913 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "ccd-node.h"
+#include "ccd-selector.h"
+#include "ccd-style.h"
+#include "ccd-stylesheet.h"
+
+typedef enum {
+	CCD_SELECTOR_MODALITY_UNIVERSAL,	/* Universal selector. */
+	CCD_SELECTOR_MODALITY_TYPE,		/* By element type. */
+	CCD_SELECTOR_MODALITY_BASE_TYPE,	/* By element type. */
+	CCD_SELECTOR_MODALITY_CLASS,		/* By element class. */
+	CCD_SELECTOR_MODALITY_ID,		/* By element ID. */
+	CCD_SELECTOR_MODALITY_ATTRIBUTE,	/* By element attribute. */
+	CCD_SELECTOR_MODALITY_PSEUDO_CLASS	/* By pseudo class. */
+} ccd_selector_modality_t;
+
+/*
+ * Abstract base selector.
+ * See http://www.w3.org/TR/CSS21/cascade.html#specificity for an explantion 
+ * of the meaning of the fields `a', `b', `c' and `d'. Field `e' (lowest priority)
+ * is used for merging base styles. Field `a' is not used currently.
+ */
+struct ccd_selector_ {
+	ccd_selector_modality_t	 modality;
+	uint8_t			 a;
+	uint8_t			 b;
+	uint8_t			 c;
+	uint8_t			 d;
+	uint8_t			 e;
+	struct ccd_selector_	*refinement;
+	struct ccd_selector_	*container;
+	ccd_block_t const	*block;
+};
+
+static void
+selector_sync (ccd_selector_t const	*self,
+	       ccd_selector_t		*to)
+{
+	g_assert (self && to);
+
+	to->modality = self->modality;
+	to->a = self->a;
+	to->b = self->b;
+	to->c = self->c;
+	to->d = self->d;
+	to->e = self->e;
+	to->refinement = NULL;
+	to->container = NULL;
+	to->block = self->block;
+}
+
+/*
+ * Universal selector.
+ */
+typedef ccd_selector_t ccd_universal_selector_t;
+
+ccd_selector_t * 
+ccd_universal_selector_new (void)
+{
+	ccd_universal_selector_t *self;
+
+	self = g_new0 (ccd_universal_selector_t, 1);
+	self->modality = CCD_SELECTOR_MODALITY_UNIVERSAL;
+
+	return (ccd_selector_t *) self;
+}
+
+static ccd_selector_t *
+universal_selector_dup (ccd_universal_selector_t const *original)
+{
+	ccd_universal_selector_t *self;
+
+	self = g_new0 (ccd_universal_selector_t, 1);
+	selector_sync ((ccd_selector_t const *) original, self);
+
+	return (ccd_selector_t *) self;
+}
+
+static void
+universal_selector_free (ccd_universal_selector_t *self)
+{
+	g_assert (self);
+
+	g_free (self);
+}
+
+static void
+universal_selector_dump (ccd_universal_selector_t const *self)
+{
+	printf (" *");
+}
+
+/*
+ * Select by element type.
+ */
+typedef struct {
+	ccd_selector_t	 parent;
+	char		*type_name;
+} ccd_type_selector_t;
+
+ccd_selector_t *
+ccd_type_selector_new (char const *type_name)
+{
+	ccd_type_selector_t *self;
+
+	g_assert (type_name);
+
+	self = g_new0 (ccd_type_selector_t, 1);
+	self->parent.modality = CCD_SELECTOR_MODALITY_TYPE;
+	self->parent.d = 1;
+	self->type_name = g_strdup (type_name);
+
+	return (ccd_selector_t *) self;
+}
+
+static ccd_selector_t *
+type_selector_dup (ccd_type_selector_t const *original)
+{
+	ccd_type_selector_t *self;
+
+	self = g_new0 (ccd_type_selector_t, 1);
+	selector_sync ((ccd_selector_t const *) original, &self->parent);
+	self->type_name = g_strdup (original->type_name);
+
+	return (ccd_selector_t *) self;
+}
+
+static void
+type_selector_free (ccd_type_selector_t *self)
+{
+	g_assert (self);
+
+	g_free (self->type_name);
+	g_free (self);
+}
+
+static void
+type_selector_dump (ccd_type_selector_t const *self)
+{
+	printf (" %s", self->type_name);
+}
+
+/*
+ * Select by element's base type.
+ * Derived from the type selector
+ */
+ccd_selector_t * 
+ccd_base_type_selector_new (char const		*type_name,
+			    unsigned int	 specificity_e)
+{
+	ccd_selector_t *self;
+
+	self = ccd_type_selector_new (type_name);
+	self->modality = CCD_SELECTOR_MODALITY_BASE_TYPE;
+	self->a = 0;
+	self->b = 0;
+	self->c = 0;
+	self->d = 0;
+	self->e = specificity_e;
+
+	return self;
+}
+
+/*
+ * Select by element class.
+ */
+typedef struct {
+	ccd_selector_t	 parent;
+	char		*class_name;
+} ccd_class_selector_t;
+
+ccd_selector_t *
+ccd_class_selector_new (char const *class_name)
+{
+	ccd_class_selector_t *self;
+
+	g_assert (class_name);
+
+	self = g_new0 (ccd_class_selector_t, 1);
+	self->parent.modality = CCD_SELECTOR_MODALITY_CLASS;
+	self->parent.c = 1;
+	self->class_name = g_strdup (class_name);
+
+	return (ccd_selector_t *) self;
+}
+
+static ccd_selector_t *
+class_selector_dup (ccd_class_selector_t const *original)
+{
+	ccd_class_selector_t *self;
+
+	self = g_new0 (ccd_class_selector_t, 1);
+	selector_sync ((ccd_selector_t const *) original, &self->parent);
+	self->class_name = g_strdup (original->class_name);
+
+	return (ccd_selector_t *) self;
+}
+
+static void
+class_selector_free (ccd_class_selector_t *self)
+{
+	g_assert (self);
+
+	g_free (self->class_name);
+	g_free (self);
+}
+
+static void
+class_selector_dump (ccd_class_selector_t const *self)
+{
+	printf (".%s", self->class_name);
+}
+
+/*
+ * Select by element ID.
+ */
+typedef struct {
+	ccd_selector_t	 parent;
+	char		*id;
+} ccd_id_selector_t;
+
+ccd_selector_t *
+ccd_id_selector_new (char const *id)
+{
+	ccd_id_selector_t *self;
+
+	g_assert (id);
+
+	self = g_new0 (ccd_id_selector_t, 1);
+	self->parent.modality = CCD_SELECTOR_MODALITY_ID;
+	self->parent.b = 1;
+	self->id = g_strdup (id);
+
+	return (ccd_selector_t *) self;
+}
+
+static ccd_selector_t *
+id_selector_dup (ccd_id_selector_t const *original)
+{
+	ccd_id_selector_t *self;
+
+	self = g_new0 (ccd_id_selector_t, 1);
+	selector_sync ((ccd_selector_t const *) original, &self->parent);
+	self->id = g_strdup (original->id);
+
+	return (ccd_selector_t *) self;
+}
+
+static void
+id_selector_free (ccd_id_selector_t *self)
+{
+	g_assert (self);
+
+	g_free (self->id);
+	g_free (self);
+}
+
+static void
+id_selector_dump (ccd_id_selector_t const *self)
+{
+	printf ("#%s", self->id);
+}
+
+/*
+ * Select by attribute.
+ */
+typedef struct {
+	ccd_selector_t			 parent;
+	char				*name;
+	char				*value;
+	ccd_attribute_selector_match_t	 match;
+} ccd_attribute_selector_t;
+
+ccd_selector_t *
+ccd_attribute_selector_new (char const				*name,
+			    char const				*value,
+			    ccd_attribute_selector_match_t	 match)
+{
+	ccd_attribute_selector_t *self;
+
+	g_assert (name && value);
+
+	self = g_new0 (ccd_attribute_selector_t, 1);
+	self->parent.modality = CCD_SELECTOR_MODALITY_ATTRIBUTE;
+	self->name = g_strdup (name);
+	self->value = g_strdup (value);
+	self->match = match;
+
+	return (ccd_selector_t *) self;
+}
+
+static ccd_selector_t *
+attribute_selector_dup (ccd_attribute_selector_t const *original)
+{
+	ccd_attribute_selector_t *self;
+
+	self = g_new0 (ccd_attribute_selector_t, 1);
+	selector_sync ((ccd_selector_t const *) original, &self->parent);
+	self->name = g_strdup (original->name);
+	self->value = g_strdup (original->value);
+	self->match = original->match;
+
+	return (ccd_selector_t *) self;
+}
+
+static void
+attribute_selector_free (ccd_attribute_selector_t *self)
+{
+	g_assert (self);
+
+	g_free (self->name);
+	g_free (self->value);
+	g_free (self);
+}
+
+static void
+attribute_selector_dump (ccd_attribute_selector_t const *self)
+{
+	switch (self->match) {
+	case CCD_ATTRIBUTE_SELECTOR_MATCH_EXISTS:
+		printf ("[%s]", self->name);
+		break;
+	case CCD_ATTRIBUTE_SELECTOR_MATCH_EQUALS:
+		printf ("[%s=%s]", self->name, self->value);
+		break;
+	default:
+		g_assert_not_reached ();
+	}
+}
+
+/*
+ * Select by pseudo class.
+ */
+typedef struct {
+	ccd_selector_t	 parent;
+	char		*pseudo_class;
+} ccd_pseudo_class_selector_t;
+
+ccd_selector_t *
+ccd_pseudo_class_selector_new (char const *pseudo_class)
+{
+	ccd_pseudo_class_selector_t *self;
+
+	g_assert (pseudo_class);
+
+	self = g_new0 (ccd_pseudo_class_selector_t, 1);
+	self->parent.modality = CCD_SELECTOR_MODALITY_PSEUDO_CLASS;
+	self->pseudo_class = g_strdup (pseudo_class);
+
+	return (ccd_selector_t *) self;
+}
+
+static ccd_selector_t *
+pseudo_class_selector_dup (ccd_pseudo_class_selector_t const *original)
+{
+	ccd_pseudo_class_selector_t *self;
+
+	self = g_new0 (ccd_pseudo_class_selector_t, 1);
+	selector_sync ((ccd_selector_t const *) original, &self->parent);
+	self->pseudo_class = g_strdup (original->pseudo_class);
+
+	return (ccd_selector_t *) self;
+}
+
+static void
+pseudo_class_selector_free (ccd_pseudo_class_selector_t *self)
+{
+	g_assert (self);
+
+	g_free (self->pseudo_class);
+	g_free (self);
+}
+
+static void
+pseudo_class_selector_dump (ccd_pseudo_class_selector_t const *self)
+{
+	printf (":%s", self->pseudo_class);
+}
+
+ccd_selector_t *
+ccd_selector_copy (ccd_selector_t const *original)
+{
+	ccd_selector_t *self;
+
+	g_assert (original);
+
+	switch (original->modality) {
+	case CCD_SELECTOR_MODALITY_UNIVERSAL:
+		self = universal_selector_dup ((ccd_universal_selector_t const *) original);
+		break;
+	case CCD_SELECTOR_MODALITY_TYPE:
+	case CCD_SELECTOR_MODALITY_BASE_TYPE:
+		self = type_selector_dup ((ccd_type_selector_t const *) original);
+		break;
+	case CCD_SELECTOR_MODALITY_CLASS:
+		self = class_selector_dup ((ccd_class_selector_t const *) original);
+		break;
+	case CCD_SELECTOR_MODALITY_ID:
+		self = id_selector_dup ((ccd_id_selector_t const *) original);
+		break;
+	case CCD_SELECTOR_MODALITY_ATTRIBUTE:
+		self = attribute_selector_dup ((ccd_attribute_selector_t const *) original);
+		break;
+	case CCD_SELECTOR_MODALITY_PSEUDO_CLASS:
+		self = pseudo_class_selector_dup ((ccd_pseudo_class_selector_t const *) original);
+		break;
+	default:
+		g_warning ("Unknown selector modality %d", original->modality);
+		self = NULL;
+		return self;
+	}
+
+	if (original->refinement) {
+		self->refinement = ccd_selector_copy (original->refinement);
+	}
+
+	if (original->container) {
+		self->container = ccd_selector_copy (original->container);
+	}
+
+	return self;
+}
+
+/*
+ * Create a selector based on an existing one.
+ */
+ccd_selector_t *
+ccd_selector_copy_as_base (ccd_selector_t const	*original,
+			   int			 specificity_e)
+{
+	ccd_selector_t *self;
+
+	g_assert (original && original->modality == CCD_SELECTOR_MODALITY_TYPE);
+
+	self = ccd_selector_copy (original);
+	self->modality = CCD_SELECTOR_MODALITY_BASE_TYPE;
+
+	if (specificity_e > -1) {
+		if (original->d > 0) {
+			self->d--;
+		} else {
+			g_warning ("Specificity d == 0");
+		}
+
+		if (original->e == 0) {
+			g_assert (specificity_e <= CCD_SELECTOR_MAX_SPECIFICITY);
+			self->e = (unsigned) specificity_e;
+		} else {
+			g_warning ("Specificity e != 0");
+		}
+	}
+
+	return self;
+}
+
+/*
+ * Free the whole selector chain.
+ */
+void
+ccd_selector_free (ccd_selector_t *self)
+{
+	g_assert (self);
+
+	if (self->container) {
+		ccd_selector_free (self->container), self->container = NULL;
+	}
+
+	if (self->refinement) {
+		ccd_selector_free (self->refinement), self->refinement = NULL;
+	}
+
+	switch (self->modality) {
+	case CCD_SELECTOR_MODALITY_UNIVERSAL:
+		universal_selector_free ((ccd_universal_selector_t *) self);
+		break;
+	case CCD_SELECTOR_MODALITY_TYPE:
+	case CCD_SELECTOR_MODALITY_BASE_TYPE:
+		type_selector_free ((ccd_type_selector_t *) self);
+		break;
+	case CCD_SELECTOR_MODALITY_CLASS:
+		class_selector_free ((ccd_class_selector_t *) self);
+		break;
+	case CCD_SELECTOR_MODALITY_ID:
+		id_selector_free ((ccd_id_selector_t *) self);
+		break;
+	case CCD_SELECTOR_MODALITY_ATTRIBUTE:
+		attribute_selector_free ((ccd_attribute_selector_t *) self);
+		break;
+	case CCD_SELECTOR_MODALITY_PSEUDO_CLASS:
+		pseudo_class_selector_free ((ccd_pseudo_class_selector_t *) self);
+		break;
+	default:
+		g_warning ("Unknown selector modality %d", self->modality);
+	}
+}
+
+/*
+ * Does it matter that the refinements order is reversed?
+ */
+void
+ccd_selector_refine (ccd_selector_t *self,
+		     ccd_selector_t *selector)
+{
+	g_assert (self && selector);
+
+	selector->refinement = self->refinement;
+	self->refinement = selector;
+
+	switch (selector->modality) {
+	case CCD_SELECTOR_MODALITY_CLASS:
+		g_assert (selector->c < CCD_SELECTOR_MAX_SPECIFICITY);
+		self->c++;
+		break;
+	case CCD_SELECTOR_MODALITY_ID:
+		g_assert (selector->b < CCD_SELECTOR_MAX_SPECIFICITY);
+		self->b++;
+		break;
+	case CCD_SELECTOR_MODALITY_ATTRIBUTE:
+		g_assert (selector->c < CCD_SELECTOR_MAX_SPECIFICITY);
+		self->c++;
+		break;
+	case CCD_SELECTOR_MODALITY_PSEUDO_CLASS:
+		g_assert (selector->d < CCD_SELECTOR_MAX_SPECIFICITY);
+		self->d++;
+		break;
+	case CCD_SELECTOR_MODALITY_UNIVERSAL:
+	case CCD_SELECTOR_MODALITY_TYPE:
+	case CCD_SELECTOR_MODALITY_BASE_TYPE:
+	default:
+		g_warning ("Invalid selector modality %d", self->modality);
+	}
+}
+
+/*
+ * Add a selector to the chain.
+ * This can change the selector instance, make sure to regard the return value.
+ */
+ccd_selector_t *
+ccd_selector_append (ccd_selector_t *self,
+		     ccd_selector_t *selector)
+{
+	g_assert (self && selector);
+
+	selector->container = self;
+
+	/* propagate specificity */
+	selector->a = self->a;
+	selector->b = self->b;
+	selector->c = self->c;
+	selector->d = self->d;
+	selector->e = self->e;
+
+	/* update specificity */
+	switch (self->modality) {
+	case CCD_SELECTOR_MODALITY_UNIVERSAL:
+		/* no weight */
+		break;
+	case CCD_SELECTOR_MODALITY_TYPE:
+		g_assert (selector->d < CCD_SELECTOR_MAX_SPECIFICITY);
+		selector->d++;
+		break;
+	case CCD_SELECTOR_MODALITY_BASE_TYPE:
+	case CCD_SELECTOR_MODALITY_CLASS:
+	case CCD_SELECTOR_MODALITY_ID:
+	case CCD_SELECTOR_MODALITY_ATTRIBUTE:
+	case CCD_SELECTOR_MODALITY_PSEUDO_CLASS:
+	default:
+		g_warning ("Invalid selector modality %d", self->modality);
+	}
+
+	return selector;	
+}
+
+bool
+ccd_selector_is_type (ccd_selector_t const *self)
+{
+	switch (self->modality) {
+	case CCD_SELECTOR_MODALITY_UNIVERSAL:
+	case CCD_SELECTOR_MODALITY_TYPE:
+		return true;
+	case CCD_SELECTOR_MODALITY_BASE_TYPE:
+	case CCD_SELECTOR_MODALITY_CLASS:
+	case CCD_SELECTOR_MODALITY_ID:
+	case CCD_SELECTOR_MODALITY_ATTRIBUTE:
+	case CCD_SELECTOR_MODALITY_PSEUDO_CLASS:
+	default:
+		return false;
+	}
+}
+
+bool
+ccd_selector_is_class (ccd_selector_t const *self)
+{
+	switch (self->modality) {
+	case CCD_SELECTOR_MODALITY_CLASS:
+		return true;		
+	case CCD_SELECTOR_MODALITY_UNIVERSAL:
+	case CCD_SELECTOR_MODALITY_TYPE:
+	case CCD_SELECTOR_MODALITY_BASE_TYPE:
+	case CCD_SELECTOR_MODALITY_ID:
+	case CCD_SELECTOR_MODALITY_ATTRIBUTE:
+	case CCD_SELECTOR_MODALITY_PSEUDO_CLASS:
+	default:
+		return false;
+	}
+}
+
+bool
+ccd_selector_is_id (ccd_selector_t const *self)
+{
+	switch (self->modality) {
+	case CCD_SELECTOR_MODALITY_ID:
+		return true;		
+	case CCD_SELECTOR_MODALITY_UNIVERSAL:
+	case CCD_SELECTOR_MODALITY_TYPE:
+	case CCD_SELECTOR_MODALITY_BASE_TYPE:
+	case CCD_SELECTOR_MODALITY_CLASS:
+	case CCD_SELECTOR_MODALITY_ATTRIBUTE:
+	case CCD_SELECTOR_MODALITY_PSEUDO_CLASS:
+	default:
+		return false;
+	}
+}
+
+ccd_block_t const *
+ccd_selector_get_block (ccd_selector_t const *self)
+{
+	g_assert (self);
+
+	return self->block;
+}
+
+void
+ccd_selector_set_block (ccd_selector_t		*self,
+			ccd_block_t const	*block)
+{
+	g_assert (self);
+
+	self->block = block;
+}
+
+/*
+ * Depending on the modality of the selector this may return NULL.
+ */
+char const *
+ccd_selector_get_key (ccd_selector_t const *self)
+{
+	g_return_val_if_fail (self, NULL);
+
+	switch (self->modality) {
+	case CCD_SELECTOR_MODALITY_UNIVERSAL:
+		return "*";
+	case CCD_SELECTOR_MODALITY_TYPE:
+	case CCD_SELECTOR_MODALITY_BASE_TYPE:
+		return ((ccd_type_selector_t *) self)->type_name;
+	case CCD_SELECTOR_MODALITY_CLASS:
+		return ((ccd_class_selector_t *) self)->class_name;
+	case CCD_SELECTOR_MODALITY_ID:
+		return ((ccd_id_selector_t *) self)->id;
+	case CCD_SELECTOR_MODALITY_ATTRIBUTE:
+	case CCD_SELECTOR_MODALITY_PSEUDO_CLASS:
+	default:
+		return NULL;
+	}
+}
+
+uint32_t
+ccd_selector_get_specificity (ccd_selector_t const *self)
+{
+	g_assert (self->a <= CCD_SELECTOR_MAX_SPECIFICITY &&
+		  self->b <= CCD_SELECTOR_MAX_SPECIFICITY &&
+		  self->c <= CCD_SELECTOR_MAX_SPECIFICITY &&
+		  self->d <= CCD_SELECTOR_MAX_SPECIFICITY &&
+		  self->e <= CCD_SELECTOR_MAX_SPECIFICITY);
+
+	return self->e | (self->d << 6) | (self->c << 12) | (self->b << 18) | (self->a << 24);
+}
+
+void
+ccd_selector_get_specificity_values (ccd_selector_t const	*self, 
+				     unsigned int		*a,
+				     unsigned int		*b,
+				     unsigned int		*c,
+				     unsigned int		*d,
+				     unsigned int		*e)
+{
+	g_assert (self);
+
+	if (a)
+		*a = self->a;
+
+	if (b)
+		*b = self->b;
+
+	if (c)
+		*c = self->c;
+
+	if (d)
+		*d = self->d;
+
+	if (e)
+		*e = self->e;
+}
+
+extern void dump_node (ccd_node_t const *node);
+
+/*
+ * `style' may be NULL, in which case this just tests for a match.
+ */
+bool
+ccd_selector_query_apply (ccd_selector_t const	*self, 
+			  ccd_node_t const	*node,
+			  ccd_style_t		*style)
+{
+	ccd_node_class_t const	*node_class;
+	char const		*name;
+	char const		*value;
+	bool			 is_matching;
+
+	g_return_val_if_fail (self && node, false);
+
+	node_class = ccd_node_get_class ();
+
+	is_matching = false;
+	switch (self->modality) {
+	case CCD_SELECTOR_MODALITY_UNIVERSAL:
+		is_matching = true;
+		break;
+	case CCD_SELECTOR_MODALITY_TYPE:
+		is_matching = node_class->is_a (node, ((ccd_type_selector_t *) self)->type_name);
+		break;
+	case CCD_SELECTOR_MODALITY_BASE_TYPE:
+		/* HACK warning: let's just say it matches, because the base type selectors have
+		 * been set up internally -- that is in the fixup run after loading the stylesheet. */
+		is_matching = true;
+		break;
+	case CCD_SELECTOR_MODALITY_CLASS:
+		name = node_class->get_class (node);
+		is_matching = name ? 0 == strcmp (name, ((ccd_class_selector_t *) self)->class_name) : false;
+		break;
+	case CCD_SELECTOR_MODALITY_ID:
+		name = node_class->get_id (node);
+		is_matching = name ? 0 == strcmp (name, ((ccd_id_selector_t *) self)->id) : false;
+		break;
+	case CCD_SELECTOR_MODALITY_ATTRIBUTE:
+		name = ((ccd_attribute_selector_t *) self)->name;
+		value = node_class->get_attribute (node, name);
+		switch (((ccd_attribute_selector_t *) self)->match) {
+		case CCD_ATTRIBUTE_SELECTOR_MATCH_EXISTS:
+			is_matching = value ? true : false;
+			break;
+		case CCD_ATTRIBUTE_SELECTOR_MATCH_EQUALS:
+			is_matching = value ? 0 == strcmp (value, ((ccd_attribute_selector_t *) self)->value) : false;			
+			break;
+		default:
+			g_assert_not_reached ();
+			is_matching = false;
+		}
+		break;
+	case CCD_SELECTOR_MODALITY_PSEUDO_CLASS:
+		name = node_class->get_pseudo_class (node);
+		is_matching = name ? 0 == strcmp (name, ((ccd_pseudo_class_selector_t *) self)->pseudo_class) : false;
+		break;
+	default:
+		g_assert_not_reached ();
+	}
+
+	if (!is_matching) {
+		return false;
+	}
+
+	/* recursively match refinements */
+	if (self->refinement) {
+		is_matching = ccd_selector_query_apply (self->refinement, node, style);
+		if (!is_matching) {
+			return false;
+		}
+	}
+
+	/* recursively match container */
+	if (self->container) {
+		ccd_node_t *container;
+		container = node_class->get_container (node);
+		is_matching = false;
+		if (container) {
+			is_matching = ccd_selector_query_apply (self->container, container, style);
+			node_class->release (container);
+		}
+		if (!is_matching) {
+			return false;
+		}
+	}
+
+	/* merge */
+	if (self->block && style) {
+		ccd_selector_apply (self, style);
+	}
+
+	return true;
+}
+
+bool
+ccd_selector_apply (ccd_selector_t const	*self,
+		    ccd_style_t			*style)
+{
+	g_return_val_if_fail (self && self->block && style, false);
+
+	switch (self->block->background.color_type) {
+	case CCD_PROPERTY_SPEC_UNKNOWN:
+		/* do nothing */
+		break;
+	case CCD_PROPERTY_SPEC_NONE:
+		/* reset */
+		style->background = NULL;
+		break;
+	case CCD_PROPERTY_SPEC_INHERIT:
+		/* not implemented */
+		g_assert_not_reached ();
+		break;
+	case CCD_PROPERTY_SPEC_SPECIFIC:
+		/* use */
+		style->background = &self->block->background;
+		break;
+	}
+
+	if (self->block->border.left.flags)
+		style->left = &self->block->border.left;
+	if (self->block->border.top.flags)
+		style->top = &self->block->border.top;
+	if (self->block->border.right.flags)
+		style->right = &self->block->border.right;
+	if (self->block->border.bottom.flags)
+		style->bottom = &self->block->border.bottom;
+
+	return true;
+}
+
+void 
+ccd_selector_dump (ccd_selector_t const *self)
+{
+	g_assert (self);
+
+	printf ("%p: ", (void *) self);
+
+	if (self->container) {
+		ccd_selector_t const *container;
+		printf ("( ");
+		container = self->container;
+		while (container) {
+			printf("%s ", ccd_selector_get_key (container));
+			container = container->container;
+		}
+		printf (")");
+	}
+
+	switch (self->modality) {
+	case CCD_SELECTOR_MODALITY_UNIVERSAL:
+		universal_selector_dump ((ccd_universal_selector_t *) self);
+		break;
+	case CCD_SELECTOR_MODALITY_TYPE:
+	case CCD_SELECTOR_MODALITY_BASE_TYPE:
+		type_selector_dump ((ccd_type_selector_t *) self);
+		break;
+	case CCD_SELECTOR_MODALITY_CLASS:
+		class_selector_dump ((ccd_class_selector_t *) self);
+		break;
+	case CCD_SELECTOR_MODALITY_ID:
+		id_selector_dump ((ccd_id_selector_t *) self);
+		break;
+	case CCD_SELECTOR_MODALITY_ATTRIBUTE:
+		attribute_selector_dump ((ccd_attribute_selector_t *) self);
+		break;
+	case CCD_SELECTOR_MODALITY_PSEUDO_CLASS:
+		pseudo_class_selector_dump ((ccd_pseudo_class_selector_t *) self);
+		break;
+	default:
+		g_warning ("Unknown selector modality %d", self->modality);
+	}
+
+	if (self->refinement) {
+		ccd_selector_dump (self->refinement);
+	}
+
+	if (self->block) {
+		printf (" {\n");
+		ccd_block_dump (self->block);
+		printf ("}");
+	}
+
+	printf (" # modality: %d, specificity: %d,%d,%d,%d,%d\n", 
+		self->modality, self->a, self->b, self->c, self->d, self->e);
+}
+

Added: branches/bzr/libccd/ccd/ccd-selector.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-selector.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,82 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_SELECTOR_H
+#define CCD_SELECTOR_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <glib.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-block.h>
+#include <ccd/ccd-node.h>
+#include <ccd/ccd-style.h>
+
+G_BEGIN_DECLS
+
+#define CCD_SELECTOR_MAX_SPECIFICITY ((1 << 5) - 1)
+
+typedef struct ccd_rule_set_ ccd_rule_set_t;
+typedef struct ccd_selector_ ccd_selector_t;
+
+typedef enum {
+	CCD_ATTRIBUTE_SELECTOR_MATCH_EXISTS, 
+	CCD_ATTRIBUTE_SELECTOR_MATCH_EQUALS
+	/* more match types go here */
+} ccd_attribute_selector_match_t;
+
+ccd_selector_t * ccd_universal_selector_new	(void);
+ccd_selector_t * ccd_type_selector_new		(char const *type_name);
+ccd_selector_t * ccd_base_type_selector_new	(char const *type_name, unsigned int specificity_e);
+ccd_selector_t * ccd_class_selector_new		(char const *class_name);
+ccd_selector_t * ccd_id_selector_new		(char const *id);
+ccd_selector_t * ccd_attribute_selector_new	(char const *name, char const *value, ccd_attribute_selector_match_t match);
+ccd_selector_t * ccd_pseudo_class_selector_new	(char const *pseudo_class);
+
+ccd_selector_t * ccd_selector_copy		(ccd_selector_t const *original);
+ccd_selector_t * ccd_selector_copy_as_base	(ccd_selector_t const *original,
+						 int specificity_e);
+
+void ccd_selector_free	(ccd_selector_t *self);
+
+void		 ccd_selector_refine (ccd_selector_t *self, ccd_selector_t *selector);
+ccd_selector_t * ccd_selector_append (ccd_selector_t *self, ccd_selector_t *selector);
+
+bool ccd_selector_is_type	(ccd_selector_t const *self);
+bool ccd_selector_is_class	(ccd_selector_t const *self);
+bool ccd_selector_is_id		(ccd_selector_t const *self);
+
+ccd_block_t const *	ccd_selector_get_block	(ccd_selector_t const *self);
+void			ccd_selector_set_block	(ccd_selector_t *self, ccd_block_t const *block);
+
+char const *		ccd_selector_get_key		(ccd_selector_t const *self);
+uint32_t		ccd_selector_get_specificity	(ccd_selector_t const *self);
+void			ccd_selector_get_specificity_values	(ccd_selector_t const *self, 
+			unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d, unsigned int *e);
+
+bool ccd_selector_query_apply (ccd_selector_t const *self, ccd_node_t const *node, 
+			       ccd_style_t *style);
+bool ccd_selector_apply (ccd_selector_t const *self, ccd_style_t *style);
+
+void ccd_selector_dump (ccd_selector_t const *self);
+
+G_END_DECLS
+
+#endif /* CCD_SELECTOR_H */
+

Added: branches/bzr/libccd/ccd/ccd-style.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-style.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,148 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "ccd-style.h"
+
+/**
+ * ccd_style_init:
+ * @self:	a ccd_style_t.
+ *
+ * Reset the object's internal state.
+ **/
+void
+ccd_style_init (ccd_style_t *self)
+{
+	memset (self, 0, sizeof (*self));
+}
+
+/**
+ * ccd_style_draw_horizontal_line:
+ * @self:	a ccd_style_t.
+ * @cr:		the target to draw onto.
+ * @x1:		the starting x coordinate.
+ * @x2:		the ending x coordinate.
+ * @y:		the y coordinate.
+ *
+ * Draw a horizontal line using this style instance. This takes the `top'
+ * border from the CSS, if specified.
+ **/
+void
+ccd_style_draw_line (ccd_style_t const	*self,
+		     cairo_t		*cr, 
+		     int32_t 		 x1,
+		     int32_t 		 x2,
+		     int32_t 		 y1,
+		     int32_t		 y2)
+{
+	double off;
+
+	if (y1 == y2) {
+		/* horizontal */
+
+		/* Unlike borders, lines are not drawn inside the box, 
+		 * account for that. */
+		off = self->top->width / 2.;
+
+		ccd_border_draw (NULL, self->top, NULL, NULL, 
+					cr, x1, y1 - off, x2 - x1, 0);
+	} else {
+		/* vertical */
+
+		/* Unlike borders, lines are not drawn inside the box, 
+		 * account for that. */
+		off = self->left->width / 2.;
+
+		ccd_border_draw (self->left, NULL, NULL, NULL, 
+					cr, x1 - off, y1, 0, y2 - y1);
+	}
+
+}
+
+/**
+ * ccd_style_draw_outline:
+ * @self:	a ccd_style_t.
+ * @cr:		the target to draw onto.
+ * @x:		the starting x coordinate.
+ * @y:		the starting y coordinate.
+ * @width:	width of the outline to draw.
+ * @height:	height of the outline to draw.
+ *
+ * Draw an outline using this style instance. Information about how to draw
+ * this style's background is diregarded.
+ **/
+void
+ccd_style_draw_outline (ccd_style_t const	*self, 
+			cairo_t			*cr, 
+			int32_t			 x,
+			int32_t			 y,
+			int32_t			 width,
+			int32_t			 height)
+{
+	ccd_border_draw (self->left, self->top, self->right, self->bottom, 
+				cr, x, y, width, height);
+}
+
+/**
+ * ccd_style_draw_rectangle:
+ * @self:	a ccd_style_t.
+ * @cr:		the target to draw onto.
+ * @x:		the starting x coordinate.
+ * @y:		the starting y coordinate.
+ * @width:	width of the outline to draw.
+ * @height:	height of the outline to draw.
+ *
+ * Draw a rectangle using this style instance.
+ **/
+void
+ccd_style_draw_rectangle (ccd_style_t const	*self,
+			  cairo_t		*cr, 
+			  int32_t		 x,
+			  int32_t		 y,
+			  int32_t		 width,
+			  int32_t		 height)
+{
+	if (self->background) {
+		ccd_background_draw (self->background, cr, x, y, width, height);
+	}
+	ccd_border_draw (self->left, self->top, self->right, self->bottom, 
+				cr, x, y, width, height);
+}
+
+/**
+ * ccd_style_dump:
+ * @self:	a ccd_style_t.
+ *
+ * Print informations about the internal state of this object.
+ **/
+void
+ccd_style_dump (ccd_style_t const *self)
+{
+	if (self->background)
+		ccd_background_dump (self->background);
+	if (self->left)
+		ccd_border_dump_stroke (self->left);
+	if (self->top)
+		ccd_border_dump_stroke (self->top);
+	if (self->right)
+		ccd_border_dump_stroke (self->right);
+	if (self->bottom)
+		ccd_border_dump_stroke (self->bottom);
+}
+

Added: branches/bzr/libccd/ccd/ccd-style.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-style.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,65 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_STYLE_H
+#define CCD_STYLE_H
+
+#include <stdint.h>
+#include <glib.h>
+#include <cairo.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-background.h>
+#include <ccd/ccd-border.h>
+
+G_BEGIN_DECLS
+
+/**
+ * ccd_style_t:
+ *
+ * Representation of a block of CSS statements.
+ *
+ * <emphasis>Memory management:</emphasis> Style objects are owned by the 
+ * stylesheet, and therefore not created or modified by the CCD consumer.
+ **/
+typedef struct {
+	/*< private >*/
+	ccd_background_t const		*background;
+	ccd_border_stroke_t const	*left;
+	ccd_border_stroke_t const	*top;
+	ccd_border_stroke_t const	*right;
+	ccd_border_stroke_t const	*bottom;
+} ccd_style_t;
+
+void ccd_style_init (ccd_style_t *self);
+
+void ccd_style_draw_line (ccd_style_t const *self, cairo_t *cr, 
+			  int32_t x1, int32_t x2, int32_t y1, int32_t y2);
+
+void ccd_style_draw_outline (ccd_style_t const *self, cairo_t *cr, 
+			     int32_t x, int32_t y, int32_t width, int32_t height);
+
+void ccd_style_draw_rectangle (ccd_style_t const *self, cairo_t *cr, 
+			       int32_t x, int32_t y, int32_t width, int32_t height);
+
+void ccd_style_dump (ccd_style_t const *self);
+
+G_END_DECLS
+
+#endif /* CCD_STYLE_H */
+

Added: branches/bzr/libccd/ccd/ccd-stylesheet.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-stylesheet.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,444 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "ccd-block.h"
+#include "ccd-node.h"
+#include "ccd-parser.h"
+#include "ccd-selector-group-priv.h"
+#include "ccd-selector.h"
+#include "ccd-stylesheet.h"
+
+/**
+ * ccd_stylesheet_t:
+ * @blocks:		List owning all blocks parsed from the stylesheet.
+ * @type_rules:		Associates type names with all applying selectors.
+ * @class_rules:	Associates class names with all applying selectors.
+ * @id_rules:		Associates IDs with all applying selectors.
+ *
+ * Represents a parsed instance of a stylesheet.
+ **/
+struct ccd_stylesheet_ {
+	GSList		*blocks;
+	GHashTable	*type_rules;
+	GHashTable	*class_rules;
+	GHashTable	*id_rules;
+};
+
+static ccd_stylesheet_t *
+ccd_stylesheet_new (void)
+{
+	ccd_stylesheet_t *self;
+
+	self = g_new0 (ccd_stylesheet_t, 1);
+	self->type_rules = g_hash_table_new (g_str_hash, g_str_equal);
+	self->class_rules = g_hash_table_new (g_str_hash, g_str_equal);
+	self->id_rules = g_hash_table_new (g_str_hash, g_str_equal);
+
+	return self;
+}
+
+static void
+fix_dangling_selectors (ccd_stylesheet_t *self)
+{
+	GHashTableIter		 iter;
+	char const		*key;
+	char const		*dangling_key;
+	ccd_selector_group_t 	*group;
+	ccd_selector_group_t	*fixup_group;
+	GSList const		*item;
+	bool			 have_dangling;
+	void			*k;
+	void			*v;
+
+	/* fix up dangling associations to base styles, walk the tree of type rules */
+	g_hash_table_iter_init (&iter, self->type_rules);
+	while (g_hash_table_iter_next (&iter, &k, &v)) {
+		
+		/* walk extra mile to prevent warnings */
+		key = (char const *) k;
+		group = (ccd_selector_group_t *) v;
+
+		item = ccd_selector_group_get_dangling_selectors (group);
+		have_dangling = (bool) item;
+		/* walk the list of dangling selectors in the current group */
+		while (item) {
+			ccd_selector_t const *selector;
+			/* Merge fixup-group to satisfy dangling selectors.
+			 * If no fixup_group is found that's ok too, the remaining dangling
+			 * selectors will be removed in clear_dangling_selectors(). */
+			selector = (ccd_selector_t const *) item->data;
+			dangling_key = ccd_selector_get_key (selector);
+			fixup_group = g_hash_table_lookup (self->type_rules, dangling_key);
+			if (fixup_group) {
+				ccd_selector_group_merge_base (group, fixup_group);
+			}
+			item = item->next;
+		}
+		if (have_dangling) {
+			ccd_selector_group_clear_dangling_selectors (group);
+		}
+	}
+}
+
+/**
+ * ccd_stylesheet_new_from_buffer:
+ * @buffer:	buffer to parse.
+ * @size:	size of the buffer.
+ *
+ * Create a new stylesheet instance based on a CSS string.
+ *
+ * Returns: a #ccd_stylesheet_t representation of the CSS string.
+ **/
+ccd_stylesheet_t *
+ccd_stylesheet_new_from_buffer (char const	*buffer, 
+				size_t		 size)
+{
+	ccd_stylesheet_t	*self;
+
+	g_critical ("%s() not tested", __FUNCTION__);
+
+	self = ccd_stylesheet_new ();
+
+	self->blocks = ccd_parser_parse_buffer (buffer, size, self->type_rules, 
+						self->class_rules, self->id_rules);
+
+	fix_dangling_selectors (self);
+
+	return self;
+}
+
+/**
+ * ccd_stylesheet_new_from_file:
+ * @css_file: file to parse.
+ *
+ * Create a new stylesheet instance based on a CSS file.
+ *
+ * Returns: a #ccd_stylesheet_t representation of the CSS file.
+ **/
+ccd_stylesheet_t *
+ccd_stylesheet_new_from_file (char const *css_file)
+{
+	ccd_stylesheet_t	*self;
+
+	self = ccd_stylesheet_new ();
+
+	self->blocks = ccd_parser_parse_file (css_file, self->type_rules, 
+					      self->class_rules, self->id_rules);
+
+	fix_dangling_selectors (self);
+
+	return self;
+}
+
+/**
+ * ccd_stylesheet_free:
+ * @self: a #ccd_stylesheet_t.
+ * 
+ * Free the stylesheet and all associated resources.
+ **/
+void
+ccd_stylesheet_free (ccd_stylesheet_t *self)
+{
+	GSList		*iter;
+	ccd_block_t	*block;
+
+	g_assert (self);
+
+	iter = self->blocks;
+	while (iter) {
+		block = (ccd_block_t *) iter->data;
+		iter = g_slist_remove (iter, block);
+		ccd_block_free (block);
+	}
+
+	g_hash_table_destroy (self->type_rules);
+	g_hash_table_destroy (self->class_rules);
+	g_hash_table_destroy (self->id_rules);
+	g_free (self);
+}
+
+/**
+ * ccd_stylesheet_query_type:
+ * @self:	a #ccd_stylesheet_t.
+ * @type_name:	the type to query for, e.g. `h1'.
+ *
+ * Query the stylesheet for styling information regarding a type.
+ *
+ * Returns: a #ccd_selector_group_t containing the requested information of %NULL.
+ **/
+ccd_selector_group_t const *
+ccd_stylesheet_query_type (ccd_stylesheet_t const	*self,
+			   char const			*type_name)
+{
+	ccd_selector_group_t const *group;
+
+	g_assert (self && type_name && self->type_rules);
+
+	group = (ccd_selector_group_t const *) g_hash_table_lookup (self->type_rules, type_name);
+
+	return group;
+}
+
+/*
+ * `base' is used for the recursion.
+ */
+static bool
+collect_type_r (ccd_stylesheet_t const	*self,
+	      ccd_node_t const		*node, 
+	      ccd_node_t const		*base,
+	      ccd_selector_group_t	*result_group,
+	      bool			 as_base)
+{
+	ccd_node_class_t const	*node_class;
+	ccd_selector_group_t	*group;
+	char const		*type_name;
+	bool			 ret;
+
+	node_class = ccd_node_get_class ();
+
+	type_name = node_class->get_type (base);
+
+	ret = false;
+	if (type_name) {
+
+		group = g_hash_table_lookup (self->type_rules, type_name);
+		if (group) {
+			ret = ccd_selector_group_query_collect (group, node, result_group, as_base);
+		}
+
+		/* Try to match base types. */
+		base = node_class->get_base_style (base);
+		if (base) {
+			ret |= collect_type_r (self, node, base, result_group, true);
+			node_class->release (base);
+		}
+
+	} else {
+		g_warning ("No type name");
+	}
+
+	return ret;
+}
+
+/**
+ * ccd_stylesheet_query_collect:
+ * @self:		a #ccd_stylesheet_t.
+ * @node:		a #ccd_node_t implementation that is used by libccd to retrieve information about the underlying document.
+ * @result_group:	a #ccd_selector_group_t that accumulates the results of the query.
+ * @as_base:		whether the results should be accumulates with lowered priority, e.g. when querying for base style information.
+ *
+ * Query the stylesheet for styling information regarding a document node and collect the results.
+ *
+ * Returns: %TRUE if styling information has been found.
+ **/
+bool
+ccd_stylesheet_query_collect (ccd_stylesheet_t const	*self,
+			      ccd_node_t const		*node, 
+			      ccd_selector_group_t	*result_group,
+			      bool			 as_base)
+{
+	ccd_node_class_t const	*node_class;
+	bool			 have_type;
+	bool			 have_class;
+	bool			 have_id;
+
+	node_class = ccd_node_get_class ();
+
+	g_return_val_if_fail (self && node && result_group, false);
+
+	/* match style by type information */
+	have_type = collect_type_r (self, node, node, result_group, as_base);
+
+	/* match by class name 
+	have_class = match_class (self, node, style);
+	*/
+	have_class = false;
+
+	/* match by id
+	have_id = query_id (self, node, style);
+	*/
+	have_id = false;
+
+	return have_type || have_class || have_id;
+}
+
+/*
+ * `base' is used for the recursion.
+ */
+static bool
+apply_type_r (ccd_stylesheet_t const	*self,
+	      ccd_node_t const		*node, 
+	      ccd_node_t const		*base, 
+	      ccd_style_t		*style)
+{
+	ccd_node_class_t const	*node_class;
+	ccd_selector_group_t	*group;
+	char const		*type_name;
+	bool			 ret;
+
+	node_class = ccd_node_get_class ();
+
+	type_name = node_class->get_type (base);
+
+	ret = false;
+	if (type_name) {
+
+		group = g_hash_table_lookup (self->type_rules, type_name);
+		if (group) {
+			ret = ccd_selector_group_query_apply (group, node, style);
+		}
+
+		/* Try to match base types. */
+		base = node_class->get_base_style (base);
+		if (base) {
+			ret |= apply_type_r (self, node, base, style);
+			node_class->release (base);
+		}
+
+	} else {
+		g_warning ("No type name");
+	}
+
+	return ret;
+}
+
+/*
+ * Merge properties from global style classes.
+ * Note: not yet supported by libcroco.
+ */
+static bool
+match_class (ccd_stylesheet_t const	*self,
+	     ccd_node_t const		*node, 
+	     ccd_style_t		*style)
+{
+	ccd_node_class_t const	*node_class;
+	ccd_selector_group_t	*group;
+	char const		*class_name;
+	bool			 ret;
+
+	node_class = ccd_node_get_class ();
+
+	ret = false;
+	class_name = node_class->get_class (node);
+	if (class_name) {
+		group = g_hash_table_lookup (self->class_rules, class_name);
+		if (group) {
+			ret |= ccd_selector_group_query_apply (group, node, style);
+		}		
+	}
+
+	return ret;
+}
+
+/*
+ * Merge properties from global style classes.
+ * Note: not yet supported by libcroco.
+ */
+static bool
+match_id (ccd_stylesheet_t const	*self,
+	  ccd_node_t const		*node, 
+	  ccd_style_t			*style)
+{
+	ccd_node_class_t const	*node_class;
+	ccd_selector_group_t	*group;
+	char const		*id;
+	bool			 ret;
+
+	node_class = ccd_node_get_class ();
+
+	ret = false;
+	id = node_class->get_id (node);
+	if (id) {
+		group = g_hash_table_lookup (self->id_rules, id);
+		if (group) {
+			ret |= ccd_selector_group_query_apply (group, node, style);
+		}		
+	}
+
+	return ret;
+}
+
+/**
+ * ccd_stylesheet_query_apply:
+ * @self:	a #ccd_stylesheet_t.
+ * @node:	a #ccd_node_t implementation that is used by libccd to retrieve information about the underlying document.
+ * @style:	a #ccd_style_t that the results of the query are applied to.
+ *
+ * Query the stylesheet for styling information regarding a document node and apply the results to a #ccd_style_t object.
+ *
+ * Returns: %TRUE if styling information has been found.
+ **/
+bool
+ccd_stylesheet_query_apply (ccd_stylesheet_t const	*self,
+			    ccd_node_t const		*node, 
+			    ccd_style_t			*style)
+{
+	ccd_node_class_t const	*node_class;
+	bool			 have_type;
+	bool			 have_class;
+	bool			 have_id;
+
+	node_class = ccd_node_get_class ();
+
+	g_return_val_if_fail (self && node && style, false);
+
+	/* match style by type information */
+	have_type = apply_type_r (self, node, node, style);
+
+	/* match by class name */
+	have_class = match_class (self, node, style);
+
+	/* match by id */
+	have_id = match_id (self, node, style);
+
+	return have_type || have_class || have_id;
+}
+
+/**
+ * ccd_stylesheet_dump:
+ * @self:	a #ccd_stylesheet_t.
+ *
+ * Print informations about the internal state of this object.
+ **/
+void
+ccd_stylesheet_dump (ccd_stylesheet_t const *self)
+{
+	GHashTableIter		 iter;
+	char const		*key;
+	ccd_selector_group_t	*value;
+
+	g_return_if_fail (self && self->class_rules);
+
+	g_hash_table_iter_init (&iter, self->type_rules);
+	while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
+		ccd_selector_group_dump (value);
+	}
+
+	g_hash_table_iter_init (&iter, self->class_rules);
+	while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
+		ccd_selector_group_dump (value);
+	}
+
+	g_hash_table_iter_init (&iter, self->id_rules);
+	while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
+		ccd_selector_group_dump (value);
+	}
+}
+

Added: branches/bzr/libccd/ccd/ccd-stylesheet.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-stylesheet.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,52 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_STYLESHEET_H
+#define CCD_STYLESHEET_H
+
+#include <stdbool.h>
+#include <glib.h>
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-selector-group.h>
+#include <ccd/ccd-style.h>
+
+G_BEGIN_DECLS
+
+typedef struct ccd_stylesheet_ ccd_stylesheet_t;
+
+ccd_stylesheet_t *	ccd_stylesheet_new_from_buffer	(char const *buffer,
+							 size_t size);
+ccd_stylesheet_t *	ccd_stylesheet_new_from_file	(char const *css_file);
+void			ccd_stylesheet_free		(ccd_stylesheet_t *self);
+
+ccd_selector_group_t const * ccd_stylesheet_query_type (ccd_stylesheet_t const *self,
+							char const *type_name);
+
+bool ccd_stylesheet_query_collect (ccd_stylesheet_t const *self, ccd_node_t const *node, 
+				   ccd_selector_group_t *result_group, bool as_base);
+
+bool ccd_stylesheet_query_apply (ccd_stylesheet_t const *self, ccd_node_t const *node, 
+				 ccd_style_t *style);
+
+void ccd_stylesheet_dump (ccd_stylesheet_t const *self);
+
+G_END_DECLS
+
+#endif /* CCD_STYLESHEET_H */
+

Added: branches/bzr/libccd/ccd/ccd-utils.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd-utils.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,33 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_UTILS_H
+#define CCD_UTILS_H
+
+#include <glib.h>
+#include <ccd/ccd-features.h>
+
+G_BEGIN_DECLS
+
+#define CCD_PROPERTY_DUMP_PREFIX "    "
+
+G_END_DECLS
+
+#endif /* CCD_UTILS_H */
+

Added: branches/bzr/libccd/ccd/ccd.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,46 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "ccd.h"
+
+/**
+ * ccd_init:
+ * @node_class: dispatch table as described at #ccd_node_class_t.
+ * 
+ * Initialize the CCD library before making any calls to it.
+ **/
+void
+ccd_init (ccd_node_class_t const *node_class)
+{
+	g_assert (node_class);
+
+	ccd_node_set_class (node_class);
+}
+
+/**
+ * ccd_shutdown:
+ *
+ * Shut down the CCD library.
+ **/
+void
+ccd_shutdown (void)
+{
+	ccd_node_reset_class ();
+}
+

Added: branches/bzr/libccd/ccd/ccd.h
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/ccd/ccd.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,47 @@
+/* The Cairo CSS Drawing Library.
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CCD_H
+#define CCD_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#include <ccd/ccd-features.h>
+#include <ccd/ccd-node.h>
+#include <ccd/ccd-style.h>
+#include <ccd/ccd-stylesheet.h>
+
+#ifdef CCD_WITH_GTK
+#include <ccd/ccd-gtk-style.h>
+#endif /* CCD_WITH_GTK */
+
+#define XH(n_) (n_)
+#define YH(n_) (n_ + 0.5)
+#define XV(n_) (n_ + 0.5)
+#define YV(n_) (n_)
+
+void 		ccd_init	(ccd_node_class_t const *node_class);
+void 		ccd_shutdown	(void);
+
+G_END_DECLS
+
+#endif /* CCD_H */
+

Added: branches/bzr/libccd/doc/Makefile.am
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/doc/Makefile.am	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,52 @@
+## Process this file with automake to produce Makefile.in
+
+# The name of the module.
+DOC_MODULE=ccd
+
+# The top-level SGML file.
+DOC_MAIN_SGML_FILE=ccd-docs.sgml
+
+# The directory containing the source code. Relative to $(srcdir)
+DOC_SOURCE_DIR=../ccd
+
+# Extra options to pass to gtkdoc-scangobj
+SCANGOBJ_OPTIONS= --nogtkinit --type-init-func="ccd_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)/libccd/ccd/*.h
+CFILE_GLOB=$(top_srcdir)/libccd/ccd/*.c
+
+# Header files to ignore when scanning
+IGNORE_HFILES =
+
+EXTRA_HFILES =
+
+# Images to copy into HTML directory
+HTML_IMAGES =
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE)
+content_files =
+
+# Other files to distribute
+extra_files =
+
+# CFLAGS and LDFLAGS for compiling scan program. Only needed
+# if $(DOC_MODULE).types is non-empty.
+GTKDOC_CFLAGS = # -I$(top_srcdir) $(CCD_CFLAGS)
+GTKDOC_LIBS = # $(top_builddir)/libccd/ccd/libccd.la $(CCD_LIBS)
+
+if GTK_DOC_INSTALLED
+include $(top_srcdir)/gtk-doc.make
+CLEANFILES += ccd-scan.*
+.PHONY : dist-hook-local
+endif
+

Added: branches/bzr/libccd/doc/ccd-docs.sgml
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/doc/ccd-docs.sgml	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
+               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; [
+
+<!ENTITY ccd				SYSTEM "xml/ccd.xml">
+<!ENTITY ccd_node_t			SYSTEM "xml/node.xml">
+<!ENTITY ccd_style_t			SYSTEM "xml/style.xml">
+<!ENTITY ccd_stylesheet_t		SYSTEM "xml/stylesheet.xml">
+<!ENTITY ccd_selector_group_t		SYSTEM "xml/selector_group.xml">
+
+<!ENTITY ccd_gtk_style_functions	SYSTEM "xml/ccd_gtk_style_functions.xml">
+
+<!ENTITY TreeIndex			SYSTEM "xml/tree_index.sgml">
+
+]>
+<book id="index">
+  <bookinfo>
+    <title>CCD Reference Manual</title>
+  </bookinfo>
+
+  <part id="intro">
+    <title>CCD: Introduction</title>
+    <partintro id="ccd-into">
+    <para>
+TODO
+    </para>
+    </partintro>
+  </part>
+
+  <part id="dependencies">
+    <title>CCD: Dependencies</title>
+    <para>
+CCD depends on the following libraries:
+<variablelist>
+
+<varlistentry>
+<term><link linkend="glib" title="GLib">GLib</link></term>
+<listitem><para>
+A general-purpose utility library, not specific to graphical user interfaces.
+GLib provides many useful data types, macros, type conversions,
+string utilities, file utilities, a main loop abstraction, and so on.
+</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><link linkend="cairo" title="Cairo">Cairo</link></term>
+<listitem><para>
+Cairo is a 2D graphics library with support for multiple output devices. 
+Currently supported output targets include the X Window System, Quartz, Win32, 
+image buffers, PostScript, PDF, and SVG file output. Experimental backends 
+include OpenGL (through glitz), XCB, BeOS, OS/2, and DirectFB.
+</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><link linkend="gtk+" title="Gtk+">Gtk+ (optional)</link></term>
+<listitem><para>
+GTK+ is a highly usable, feature rich toolkit for creating graphical user interfaces which boasts cross platform compatibility and an easy to use API. GTK+ it is written in C, but has bindings to many other popular programming languages such as C++, Python and C# among others. GTK+ is licensed under the GNU LGPL 2.1 allowing development of both free and proprietary software with GTK+ without any license fees or royalties.
+</para></listitem>
+</varlistentry>
+
+</variablelist>
+
+    </para>
+</part>
+
+<part id="ccd-users">
+  <title>Projects using CCD</title>
+  <partintro id="ccd-projects">
+  <para>
+CCD is used by
+<variablelist>
+<varlistentry>
+<term><ulink url="http://www.gnome.org/~robsta/gtk-css-engine/";>Gtk CSS Engine</ulink></term>
+<listitem><para>
+The Gtk CSS Engine
+</para></listitem>
+</varlistentry>
+
+</variablelist>
+
+  </para>
+  </partintro>
+</part>
+
+<part id="api">
+  <title>API Reference</title>
+    <partintro id="ccd-api-ref">
+      <para>
+TODO.
+      </para>
+    </partintro>
+  <chapter id="basic">
+    <title>Basic Usage</title>
+    &ccd;
+    &ccd_stylesheet_t;
+    &ccd_selector_group_t;
+    &ccd_style_t;
+    &ccd_node_t;
+  </chapter>
+  <chapter id="gtk-support">
+    <title>Gtk+ Support</title>
+    &ccd_gtk_style_functions;
+  </chapter>
+ </part>
+<index id="ccd-index">
+&TreeIndex;
+</index>
+</book>
+

Added: branches/bzr/libccd/doc/ccd-sections.txt
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/doc/ccd-sections.txt	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,63 @@
+<SECTION>
+<SECTION>
+<TITLE>Initialization</TITLE>
+<FILE>ccd</FILE>
+ccd_init
+ccd_shutdown
+</SECTION>
+
+<TITLE>ccd_node_t</TITLE>
+<FILE>node</FILE>
+ccd_node_t
+ccd_node_class_t
+ccd_node_get_container_f
+ccd_node_get_base_style_f
+ccd_node_get_id_f
+ccd_node_get_type_f
+ccd_node_get_class_f
+ccd_node_get_pseudo_class_f
+ccd_node_get_attribute_f
+ccd_node_release_f
+</SECTION>
+
+<SECTION>
+<TITLE>ccd_style_t</TITLE>
+<FILE>style</FILE>
+ccd_style_t
+ccd_style_init
+ccd_style_draw_line
+ccd_style_draw_outline
+ccd_style_draw_rectangle
+ccd_style_dump
+</SECTION>
+
+<SECTION>
+<TITLE>ccd_stylesheet_t</TITLE>
+<FILE>stylesheet</FILE>
+ccd_stylesheet_t
+ccd_stylesheet_new_from_buffer
+ccd_stylesheet_new_from_file
+ccd_stylesheet_free
+ccd_stylesheet_query_type
+ccd_stylesheet_query_collect
+ccd_stylesheet_query_apply
+ccd_stylesheet_dump
+</SECTION>
+
+<SECTION>
+<TITLE>ccd_selector_group_t</TITLE>
+<FILE>selector_group</FILE>
+ccd_selector_group_t
+ccd_selector_group_new
+ccd_selector_group_free
+ccd_selector_group_apply
+ccd_selector_group_dump
+</SECTION>
+
+<SECTION>
+<TITLE>ccd_style_t Gtk+ Support</TITLE>
+<FILE>ccd_gtk_style_functions</FILE>
+ccd_style_draw_gap
+ccd_style_draw_polygon
+</SECTION>
+

Added: branches/bzr/libccd/doc/version.xml.in
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/doc/version.xml.in	Fri Sep  5 11:32:51 2008
@@ -0,0 +1 @@
+ VERSION@

Added: branches/bzr/libccd/examples/Makefile.am
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/examples/Makefile.am	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,19 @@
+
+AM_CPPFLAGS = \
+	$(CCD_CFLAGS) \
+	-I$(top_srcdir)/libccd \
+	-I$(top_builddir)/libccd
+
+AM_LDFLAGS = \
+	$(CCD_LIBS) \
+	../ccd/libccd.la
+
+noinst_PROGRAMS = example1 internal
+
+example1_SOURCES = example1.c
+
+internal_SOURCES = internal.c
+
+EXTRA_DIST = \
+	example1.css
+

Added: branches/bzr/libccd/examples/example1.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/examples/example1.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,70 @@
+
+#include <stdlib.h>
+#include <cairo.h>
+#include <ccd/ccd.h>
+#include <gtk/gtk.h>
+
+static gboolean
+expose_cb (GtkWidget		*widget,
+	   GdkEventExpose	*event,
+	   ccd_style_t const	*style)
+{
+	cairo_t *cr;
+
+	cr = gdk_cairo_create (widget->window);
+
+	ccd_style_draw_rectangle (style, cr, 
+				  widget->allocation.x + 10,
+				  widget->allocation.y + 10,
+				  widget->allocation.width - 20, 
+				  widget->allocation.height - 20);
+
+	cairo_destroy (cr);
+
+	return FALSE;
+}
+
+/*
+static char const *_css = "			\
+	box { 					\
+		border: 3px solid black		\
+	}					\
+";
+*/
+
+int
+main (int	  argc,
+      char	**argv)
+{
+	ccd_stylesheet_t		*stylesheet;
+	ccd_selector_group_t const	*group;
+	ccd_style_t			 style;
+	GtkWidget			*window;
+
+	gtk_init (&argc, &argv);
+
+	/* stylesheet = ccd_stylesheet_new_from_buffer (_css, sizeof (_css)); */
+	stylesheet = ccd_stylesheet_new_from_file ("example1.css");
+
+	group = ccd_stylesheet_query_type (stylesheet, "box");
+	g_assert (group);
+
+	ccd_style_init (&style);
+	ccd_selector_group_apply (group, &style);
+
+	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_default_size (GTK_WINDOW (window), 160, 90);
+	gtk_widget_set_app_paintable (window, TRUE);
+	g_signal_connect (G_OBJECT (window), "delete-event", 
+			  G_CALLBACK (gtk_main_quit), NULL);
+	g_signal_connect (G_OBJECT (window), "expose-event", 
+			  G_CALLBACK (expose_cb), &style);
+
+	gtk_widget_show_all (window);
+	gtk_main ();
+
+	ccd_stylesheet_free (stylesheet);
+
+	return EXIT_SUCCESS;
+}
+

Added: branches/bzr/libccd/examples/example1.css
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/examples/example1.css	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,3 @@
+box { 
+	border: 3px solid black 
+}

Added: branches/bzr/libccd/examples/internal.c
==============================================================================
--- (empty file)
+++ branches/bzr/libccd/examples/internal.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,103 @@
+
+/*
+ * This example uses internal API.
+ */
+
+#include <gtk/gtk.h>
+#include <ccd/ccd.h>
+
+static void
+draw_decorations (GtkAllocation	*allocation, 
+		  cairo_t	*cr)
+{
+	cairo_move_to (cr, XV (30), YV (10));
+	cairo_line_to (cr, XV (30), YV (20));
+	cairo_stroke (cr);
+
+	cairo_move_to (cr, XH (10), YH (30));
+	cairo_line_to (cr, XH (20), YH (30));
+	cairo_stroke (cr);
+
+	cairo_move_to (cr, XV (allocation->width - 30), YV (10));
+	cairo_line_to (cr, XV (allocation->width - 30), YV (20));
+	cairo_stroke (cr);
+
+	cairo_move_to (cr, XH (allocation->width - 20), YH (30));
+	cairo_line_to (cr, XH (allocation->width - 10), YH (30));
+	cairo_stroke (cr);
+
+	cairo_move_to (cr, XH (allocation->width - 20), YH (allocation->height - 30));
+	cairo_line_to (cr, XH (allocation->width - 10), YH (allocation->height - 30));
+	cairo_stroke (cr);
+
+	cairo_move_to (cr, XV (allocation->width - 30), YV (allocation->height - 20));
+	cairo_line_to (cr, XV (allocation->width - 30), YV (allocation->height - 10));
+	cairo_stroke (cr);
+
+	cairo_move_to (cr, XV (30), YV (allocation->height - 20));
+	cairo_line_to (cr, XV (30), YV (allocation->height - 10));
+	cairo_stroke (cr);
+
+	cairo_move_to (cr, XH (10), YH (allocation->height - 30));
+	cairo_line_to (cr, XH (20), YH (allocation->height - 30));
+	cairo_stroke (cr);
+}
+
+static void
+draw_box (cairo_t	 *cr, 
+	  double	  x,
+	  double	  y,
+	  double	  width,
+	  double	  height)
+{
+	ccd_border_t border = {
+		.left.width = 3, .left.style = CCD_BORDER_STYLE_SOLID, .left.color.red = 0, .left.color.green = 0, .left.color.blue = 0,
+		.top.width = 10, .top.style = CCD_BORDER_STYLE_DOTTED, .top.color.red = 1, .top.color.green = 0, .top.color.blue = 0,
+		.right.width = 1, .right.style = CCD_BORDER_STYLE_DASHED, .right.color.red = 0, .right.color.green = 0, .right.color.blue = 0,
+		.bottom.width = 3, .bottom.style = CCD_BORDER_STYLE_SOLID, .bottom.color.red = 0, .bottom.color.green = 0, .bottom.color.blue = 0
+	};
+
+	ccd_border_draw (&border.left, &border.top, &border.right, &border.bottom, cr, x, y, width, height);
+}
+
+static gboolean
+expose_cb (GtkWidget      *widget,
+           GdkEventExpose *event,
+           gpointer        user_data)
+{
+	cairo_t *cr;
+
+	cr = gdk_cairo_create (widget->window);
+	cairo_set_line_width (cr, 1.0);
+
+	draw_decorations (&widget->allocation, cr);
+
+	draw_box (cr, 30, 30, widget->allocation.width - 60, widget->allocation.height - 60);
+
+	cairo_destroy (cr);
+
+	return FALSE;
+}
+
+int
+main (int	  argc,
+      char	**argv)
+{
+	GtkWidget *window;
+
+	gtk_init (&argc, &argv);
+
+	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_widget_set_app_paintable (window, TRUE);
+	gtk_widget_set_size_request (window, 70, 70);
+	g_signal_connect (G_OBJECT (window), "expose-event", 
+		G_CALLBACK (expose_cb), NULL);
+	g_signal_connect (G_OBJECT (window), "delete-event", 
+		G_CALLBACK (gtk_main_quit), NULL);
+
+	gtk_widget_show_all (window);
+	gtk_main ();
+
+	return 0;
+}
+

Added: branches/bzr/src/Makefile.am
==============================================================================
--- (empty file)
+++ branches/bzr/src/Makefile.am	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,25 @@
+
+AM_CPPFLAGS = \
+	$(GCE_CFLAGS) \
+	-I$(top_srcdir)/libccd \
+	-I$(top_builddir)/libccd
+
+enginedir = $(libdir)/gtk-2.0/$(GTK_VERSION)/engines
+
+engine_LTLIBRARIES = libcss.la
+
+libcss_la_LDFLAGS = -module -avoid-version -no-undefined
+
+libcss_la_LIBADD = \
+	$(GCE_LIBS) \
+	./../libccd/ccd/libccd.la
+
+libcss_la_SOURCES = \
+	gce-maps.c \
+	gce-maps.h \
+	gce-rc-style.c \
+	gce-rc-style.h \
+	gce-style.c \
+	gce-style.h \
+	gce-theme.c
+

Added: branches/bzr/src/gce-maps.c
==============================================================================
--- (empty file)
+++ branches/bzr/src/gce-maps.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,483 @@
+/* Gtk CSS Engine
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "gce-maps.h"
+
+/**
+ * Map between detail strings in gtk and css format.
+ */
+static const struct {
+	char const *gtk_detail;
+	char const *css_detail;
+} _detail_map[] = {
+  { "add-mode",				"add-mode" },
+  { "arrow",				"arrow" },
+  { "bar",				"bar" },
+  { "base",				"base" },
+  { "button",				"button" },
+  { "buttondefault",			"buttondefault" },
+  { "calendar",				"calendar" },
+  { "calendar-day",			"calendar-day" },
+  { "cellcheck",			"cellcheck" },
+  { "cell_even",			"cell-even" },
+  { "cell_even_end",			"cell-even-end" },
+  { "cell_even_middle",			"cell-even-middle" },
+  { "cell_even_ruled",			"cell-even-ruled" },
+  { "cell_even_ruled_end",		"cell-even-ruled-end" },
+  { "cell_even_ruled_middle",		"cell-even-ruled-middle" },
+  { "cell_even_ruled_sorted",		"cell-even-ruled-sorted" },
+  { "cell_even_ruled_sorted_end",	"cell-even-ruled-sorted-end" },
+  { "cell_even_ruled_sorted_middle",	"cell-even-ruled-sorted-middle" },
+  { "cell_even_ruled_sorted_start",	"cell-even-ruled-sorted-start" },
+  { "cell_even_ruled_start",		"cell-even-ruled-start" },
+  { "cell_even_sorted",			"cell-even-sorted" },
+  { "cell_even_sorted_end",		"cell-even-sorted-end" },
+  { "cell_even_sorted_middle",		"cell-even-sorted-middle" },
+  { "cell_even_sorted_start",		"cell-even-sorted-start" },
+  { "cell_even_start",			"cell-even-start" },
+  { "cell_odd",				"cell-odd" },
+  { "cell_odd_end",			"cell-odd-end" },
+  { "cell_odd_middle",			"cell-odd-middle" },
+  { "cell_odd_ruled",			"cell-odd-ruled" },
+  { "cell_odd_ruled_end",		"cell-odd-ruled-end" },
+  { "cell_odd_ruled_middle",		"cell-odd-ruled-middle" },
+  { "cell_odd_ruled_sorted",		"cell-odd-ruled-sorted" },
+  { "cell_odd_ruled_sorted_end",	"cell-odd-ruled-sorted-end" },
+  { "cell_odd_ruled_sorted_middle",	"cell-odd-ruled-sorted-middle" },
+  { "cell_odd_ruled_sorted_start",	"cell-odd-ruled-sorted-start" },
+  { "cell_odd_ruled_start",		"cell-odd-ruled-start" },
+  { "cell_odd_sorted",			"cell-odd-sorted" },
+  { "cell_odd_sorted_end",		"cell-odd-sorted-end" },
+  { "cell_odd_sorted_middle",		"cell-odd-sorted-middle" },
+  { "cell_odd_sorted_start",		"cell-odd-sorted-start" },
+  { "cell_odd_start",			"cell-odd-start" },
+  { "cellradio",			"cellradio" },
+  { "check",				"check" },
+  { "checkbutton",			"checkbutton" },
+  { "colorwheel_dark",			"colorwheel-dark" },
+  { "colorwheel_light",			"colorwheel-light" },
+  { "combobox",				"combobox" },
+  { "curve_bg",				"curve-bg" },
+  { "dnd",				"dnd" },
+  { "entry",				"entry" },
+  { "entry_bg",				"entry-bg" },
+  { "eventbox",				"eventbox" },
+  { "expander",				"expander" },
+  { "frame",				"frame" },
+  { "handle",				"handle" },
+  { "handlebox",			"handlebox" },
+  { "handlebox_bin",			"handlebox-bin" },
+  { "hruler",				"hruler" },
+  { "hscale",				"hscale" },
+  { "hscrollbar",			"hscrollbar" },
+  { "hseparator",			"hseparator" },
+  { "icon_view",			"icon-view" },
+  { "iconview-drop-indicator",		"iconview-drop-indicator" },
+  { "listitem",				"listitem" },
+  { "menu",				"menu" },
+  { "menubar",				"menubar" },
+  { "menuitem",				"menuitem" },
+  { "menu_scroll_arrow_down",		"menu-scroll-arrow-down" },
+  { "menu_scroll_arrow_up",		"menu-scroll-arrow-up" },
+  { "notebook",				"notebook" },
+  { "option",				"option" },
+  { "optionmenu",			"optionmenu" },
+  { "optionmenutab",			"optionmenutab" },
+  { "paned",				"paned" },
+  { "radiobutton",			"radiobutton" },
+  { "scrolled_window",			"scrolled-window" },
+  { "spinbutton",			"spinbutton" },
+  { "spinbutton_down",			"spinbutton-down" },
+  { "spinbutton_up",			"spinbutton-up" },
+  { "statusbar",			"statusbar" },
+  { "tab",				"tab" },
+  { "tearoffmenuitem",			"tearoffmenuitem" },
+  { "text",				"text" },
+  { "textview",				"textview" },
+  { "through",				"through" },
+  { "toolbar",				"toolbar" },
+  { "tooltip",				"tooltip" },
+  { "tray-icon",			"tray-icon" },
+  { "treeitem",				"treeitem" },
+  { "treeview",				"treeview" },
+  { "treeview-drop-indicator",		"treeview-drop-indicator" },
+  { "treeview-drop-indicator-left",	"treeview-drop-indicator-left" },
+  { "treeview-drop-indicator-middle",	"treeview-drop-indicator-middle" },
+  { "treeview-drop-indicator-right",	"treeview-drop-indicator-right" },
+  { "treeview-left",			"treeview-left" },
+  { "treeview-middle",			"treeview-middle" },
+  { "treeview-right",			"treeview-right" },
+  { "trough",				"trough" },
+  { "trough-fill-level",		"trough-fill-level" },
+  { "trough-fill-level-full",		"trough-fill-level-full" },
+  { "trough-lower",			"trough-lower" },
+  { "trough-upper",			"trough-upper" },
+  { "viewport",				"viewport" },
+  { "viewportbin",			"viewportbin" },
+  { "vruler",				"vruler" },
+  { "vscale",				"vscale" },
+  { "vscrollbar",			"vscrollbar" },
+  { "vseparator",			"vseparator" }
+};
+
+/**
+ * Find gtk detail string for a given css detail.
+ *
+ * \note This could be sped up by manually comparing char by char. First 
+ * traversing 'til the first one matches, then goin on with the second one ...
+ * If it would buy us anyting is another question.
+ */
+char const *
+gce_maps_match_detail (char const *css_detail)
+{
+	if (!css_detail) {
+		return NULL;
+	}
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_detail_map); i++) {
+		if (0 == strcmp (_detail_map[i].css_detail, css_detail)) {
+			return _detail_map[i].gtk_detail;
+		}
+	}
+
+	return NULL;
+}
+
+char const *
+gce_maps_get_detail (char const *gtk_detail)
+{
+	if (!gtk_detail) {
+		return NULL;
+	}
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_detail_map); i++) {
+		if (0 == strcmp (_detail_map[i].gtk_detail, gtk_detail)) {
+			return _detail_map[i].css_detail;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * Map between states in gtk and css format.
+ */
+static const struct {
+	GtkStateType	 gtk_state;
+	char const	*css_state;
+} _state_map[] = {
+  { GTK_STATE_NORMAL,		"normal" },
+  { GTK_STATE_ACTIVE,		"active" },
+  { GTK_STATE_PRELIGHT,		"prelight" },
+  { GTK_STATE_SELECTED,		"selected" },
+  { GTK_STATE_INSENSITIVE,	"insensitive" }
+};
+
+/**
+ * Default is GTK_STATE_NORMAL.
+ */
+GtkStateType
+gce_maps_match_state (char const *css_state)
+{
+	g_return_val_if_fail (css_state, GTK_STATE_NORMAL);
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_state_map); i++) {
+		if (0 == strcmp (_state_map[i].css_state, css_state)) {
+			return _state_map[i].gtk_state;
+		}
+	}
+
+	return GTK_STATE_NORMAL;
+}
+
+char const *
+gce_maps_get_state (GtkStateType gtk_state)
+{
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_state_map); i++) {
+		if (_state_map[i].gtk_state == gtk_state) {
+			return _state_map[i].css_state;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * Map between shadow types in gtk and css format.
+ */
+static const struct {
+	GtkShadowType	 gtk_shadow;
+	char const	*css_shadow;
+} _shadow_map[] = {
+  { GTK_SHADOW_NONE,		"none" },
+  { GTK_SHADOW_IN,		"in" },
+  { GTK_SHADOW_OUT,		"out" },
+  { GTK_SHADOW_ETCHED_IN,	"etched-in" },
+  { GTK_SHADOW_ETCHED_OUT,	"etched-out" }
+};
+
+/**
+ * Default is GTK_SHADOW_NONE.
+ */
+GtkShadowType
+gce_maps_match_shadow (char const *css_shadow)
+{
+	g_return_val_if_fail (css_shadow, GTK_SHADOW_NONE);
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_shadow_map); i++) {
+		if (0 == strcmp (_shadow_map[i].css_shadow, css_shadow)) {
+			return _shadow_map[i].gtk_shadow;
+		}
+	}
+
+	return GTK_SHADOW_NONE;
+}
+
+char const *
+gce_maps_get_shadow (GtkShadowType gtk_shadow)
+{
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_shadow_map); i++) {
+		if (_shadow_map[i].gtk_shadow == gtk_shadow) {
+			return _shadow_map[i].css_shadow;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * Map between arrow types in gtk and css format.
+ */
+static const struct {
+	GtkArrowType	 gtk_arrow;
+	char const	*css_arrow;
+} _arrow_map[] = {
+  { GTK_ARROW_UP,	"up" },
+  { GTK_ARROW_DOWN,	"down" },
+  { GTK_ARROW_LEFT,	"left" },
+  { GTK_ARROW_RIGHT,	"right" },
+  { GTK_ARROW_NONE,	"none" }
+};
+
+/**
+ * Default is GTK_ARROW_NONE.
+ */
+GtkArrowType
+gce_maps_match_arrow (char const *css_arrow)
+{
+	g_return_val_if_fail (css_arrow, GTK_ARROW_NONE);
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_arrow_map); i++) {
+		if (0 == strcmp (_arrow_map[i].css_arrow, css_arrow)) {
+			return _arrow_map[i].gtk_arrow;
+		}
+	}
+
+	return GTK_ARROW_NONE;
+}
+
+char const *
+gce_maps_get_arrow (GtkArrowType gtk_arrow)
+{
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_arrow_map); i++) {
+		if (_arrow_map[i].gtk_arrow == gtk_arrow) {
+			return _arrow_map[i].css_arrow;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * Map between position types in gtk and css format.
+ */
+static const struct {
+	GtkPositionType	 gtk_position;
+	char const	*css_position;
+} _position_map[] = {
+  { GTK_POS_LEFT,	"left" },
+  { GTK_POS_RIGHT,	"right" },
+  { GTK_POS_TOP,	"top" },
+  { GTK_POS_BOTTOM,	"bottom" },
+};
+
+/**
+ * Default is GTK_POS_LEFT.
+ */
+GtkPositionType
+gce_maps_match_position (char const *css_position)
+{
+	g_return_val_if_fail (css_position, GTK_POS_LEFT);
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_position_map); i++) {
+		if (0 == strcmp (_position_map[i].css_position, css_position)) {
+			return _position_map[i].gtk_position;
+		}
+	}
+
+	return GTK_POS_LEFT;
+}
+
+char const *
+gce_maps_get_position (GtkPositionType gtk_position)
+{
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_position_map); i++) {
+		if (_position_map[i].gtk_position == gtk_position) {
+			return _position_map[i].css_position;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * Map between edge types in gdk and css format.
+ */
+static const struct {
+	GdkWindowEdge	 gdk_window_edge;
+	char const	*css_window_edge;
+} _window_edge_map[] = {
+  { GDK_WINDOW_EDGE_NORTH_WEST,	"north-west" },
+  { GDK_WINDOW_EDGE_NORTH,	"north" },
+  { GDK_WINDOW_EDGE_NORTH_EAST,	"north-east" },
+  { GDK_WINDOW_EDGE_WEST,	"west" },
+  { GDK_WINDOW_EDGE_EAST,	"east" },
+  { GDK_WINDOW_EDGE_SOUTH_WEST,	"south-west" },
+  { GDK_WINDOW_EDGE_SOUTH,	"south" },
+  { GDK_WINDOW_EDGE_SOUTH_EAST,	"south-east" },
+};
+
+/**
+ * Default is GDK_WINDOW_EDGE_SOUTH_EAST.
+ */
+GdkWindowEdge
+gce_maps_match_window_edge (char const *css_window_edge)
+{
+	g_return_val_if_fail (css_window_edge, GDK_WINDOW_EDGE_SOUTH_EAST);
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_window_edge_map); i++) {
+		if (0 == strcmp (_window_edge_map[i].css_window_edge, css_window_edge)) {
+			return _window_edge_map[i].gdk_window_edge;
+		}
+	}
+
+	return GDK_WINDOW_EDGE_SOUTH_EAST;
+}
+
+char const *
+gce_maps_get_window_edge (GdkWindowEdge gdk_window_edge)
+{
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_window_edge_map); i++) {
+		if (_window_edge_map[i].gdk_window_edge == gdk_window_edge) {
+			return _window_edge_map[i].css_window_edge;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * Map between orientation types in gtk and css format.
+ */
+static const struct {
+	GtkOrientation	 gtk_orientation;
+	char const	*css_orientation;
+} _orientation_map[] = {
+  { GTK_ORIENTATION_HORIZONTAL,	"horizontal" },
+  { GTK_ORIENTATION_VERTICAL,	"vertical" }
+};
+
+/**
+ * Default is GTK_ORIENTATION_HORIZONTAL.
+ */
+GtkOrientation
+gce_maps_match_orientation (char const *css_orientation)
+{
+	g_return_val_if_fail (css_orientation, GTK_ORIENTATION_HORIZONTAL);
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_orientation_map); i++) {
+		if (0 == strcmp (_orientation_map[i].css_orientation, css_orientation)) {
+			return _orientation_map[i].gtk_orientation;
+		}
+	}
+
+	return GTK_ORIENTATION_HORIZONTAL;
+}
+
+char const *
+gce_maps_get_orientation (GtkOrientation gtk_orientation)
+{
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_orientation_map); i++) {
+		if (_orientation_map[i].gtk_orientation == gtk_orientation) {
+			return _orientation_map[i].css_orientation;
+		}
+	}
+
+	return NULL;
+}
+
+
+
+
+
+
+
+/**
+ * Map between expander style types in gtk and css format.
+ */
+static const struct {
+	GtkExpanderStyle	 gtk_expander_style;
+	char const		*css_expander_style;
+} _expander_style_map[] = {
+  { GTK_EXPANDER_COLLAPSED,		"collapsed" },
+  { GTK_EXPANDER_SEMI_COLLAPSED,	"semi-collapsed" },
+  { GTK_EXPANDER_SEMI_EXPANDED,		"semi-expanded" },
+  { GTK_EXPANDER_EXPANDED,		"expanded" }
+};
+
+/**
+ * Default is GTK_EXPANDER_COLLAPSED.
+ */
+GtkExpanderStyle
+gce_maps_match_expander_style (char const *css_expander_style)
+{
+	g_return_val_if_fail (css_expander_style, GTK_EXPANDER_COLLAPSED);
+
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_expander_style_map); i++) {
+		if (0 == strcmp (_expander_style_map[i].css_expander_style, css_expander_style)) {
+			return _expander_style_map[i].gtk_expander_style;
+		}
+	}
+
+	return GTK_EXPANDER_COLLAPSED;
+}
+
+char const *
+gce_maps_get_expander_style (GtkExpanderStyle gtk_expander_style)
+{
+	for (unsigned int i = 0; i < G_N_ELEMENTS (_expander_style_map); i++) {
+		if (_expander_style_map[i].gtk_expander_style == gtk_expander_style) {
+			return _expander_style_map[i].css_expander_style;
+		}
+	}
+
+	return NULL;
+}
+

Added: branches/bzr/src/gce-maps.h
==============================================================================
--- (empty file)
+++ branches/bzr/src/gce-maps.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,55 @@
+/* Gtk CSS Engine
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GCE_MAPS_H
+#define GCE_MAPS_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+char const *		gce_maps_match_detail		(char const *gce_detail);
+char const *		gce_maps_get_detail		(char const *gtk_detail);
+
+GtkStateType		gce_maps_match_state		(char const *gce_state);
+char const *		gce_maps_get_state		(GtkStateType state);
+
+GtkShadowType		gce_maps_match_shadow		(char const *gce_shadow);
+char const *		gce_maps_get_shadow		(GtkShadowType shadow);
+
+GtkArrowType		gce_maps_match_arrow		(char const *gce_arrow);
+char const *		gce_maps_get_arrow		(GtkArrowType gtk_arrow);
+
+GtkPositionType		gce_maps_match_position		(char const *gce_position);
+char const *		gce_maps_get_position		(GtkPositionType gtk_position);
+
+GdkWindowEdge		gce_maps_match_window_edge	(char const *gce_window_edge);
+char const *		gce_maps_get_window_edge	(GdkWindowEdge gdk_window_edge);
+
+GtkOrientation		gce_maps_match_orientation	(char const *css_orientation);
+char const *		gce_maps_get_orientation	(GtkOrientation gtk_orientation);
+
+GtkExpanderStyle	gce_maps_match_expander_style	(char const *css_expander_style);
+char const *		gce_maps_get_expander_style	(GtkExpanderStyle gtk_expander_style);
+
+G_END_DECLS
+
+#endif /* GCE_MAPS_H */
+

Added: branches/bzr/src/gce-rc-style.c
==============================================================================
--- (empty file)
+++ branches/bzr/src/gce-rc-style.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,169 @@
+/* Gtk CSS Engine
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <string.h>
+#include "gce-rc-style.h"
+#include "gce-style.h"
+
+static ccd_stylesheet_t	*_stylesheet = NULL;
+gpointer		*_stylesheet_owner = NULL;
+
+ccd_stylesheet_t const *
+gce_rc_style_get_stylesheet (void)
+{
+	return _stylesheet;
+}
+
+struct _GceRcStyle
+{
+	GtkRcStyle parent;
+};
+
+struct _GceRcStyleClass
+{
+	GtkRcStyleClass parent;
+};
+
+static GType            gce_rc_style_type = 0;
+static GtkRcStyleClass *gce_rc_style_parent_class = NULL;
+
+static GtkStyle*
+create_style (GtkRcStyle *rc_style)
+{
+    return GTK_STYLE (g_object_new (GCE_TYPE_STYLE, NULL));
+}
+
+static guint 
+parse (GtkRcStyle  *rc_style, 
+       GtkSettings *settings, 
+       GScanner    *scanner)
+{
+	static GQuark scope_id = 0;
+
+	char	*gce_file;
+	guint	 old_scope;
+	guint	 token;
+		
+	if (!scope_id)
+		scope_id = g_quark_from_string ("gce_engine");
+	
+	old_scope = g_scanner_set_scope (scanner, scope_id);
+	
+	token = g_scanner_peek_next_token (scanner);
+	if (token != G_TOKEN_RIGHT_CURLY) {
+
+		token = g_scanner_get_next_token (scanner);
+		g_assert (token == G_TOKEN_IDENTIFIER && 
+			  0 == strcmp ("href", scanner->value.v_identifier));
+
+		token = g_scanner_get_next_token (scanner);
+		g_assert (token == '=');
+
+		token = g_scanner_get_next_token (scanner);
+		g_assert (token == G_TOKEN_STRING);
+		g_assert (_stylesheet == NULL);
+		gce_file = gtk_rc_find_pixmap_in_path (gtk_settings_get_default (), 
+				scanner, scanner->value.v_string);
+		_stylesheet = ccd_stylesheet_new_from_file (gce_file);
+#ifdef DEBUG
+		ccd_stylesheet_dump (_stylesheet);
+#endif
+		_stylesheet_owner = (gpointer) rc_style;
+		g_free (gce_file), gce_file = NULL;
+	}
+
+	g_scanner_get_next_token (scanner);	
+	g_scanner_set_scope (scanner, old_scope);
+
+	return G_TOKEN_NONE;
+}
+
+static void 
+merge (GtkRcStyle *dst, 
+       GtkRcStyle *src)
+{
+	gce_rc_style_parent_class->merge (dst, src);
+}
+
+static void
+finalize (GObject *instance)
+{
+	/*
+	GceRcStyle *self;
+	self = GCE_RC_STYLE (instance);
+	*/
+
+	if (_stylesheet_owner == (gpointer) instance) {
+		ccd_stylesheet_free (_stylesheet);
+	}
+
+	G_OBJECT_CLASS (gce_rc_style_parent_class)->finalize (instance);
+}
+
+static void 
+instance_init (GceRcStyle *self)
+{
+}
+
+static void 
+class_init (GceRcStyleClass *klass)
+{
+	GObjectClass	*go_class;
+	GtkRcStyleClass *rc_style_class;
+
+	gce_rc_style_parent_class = g_type_class_peek_parent (klass);
+
+	go_class = G_OBJECT_CLASS (klass);
+	go_class->finalize = finalize;
+
+	rc_style_class = GTK_RC_STYLE_CLASS (klass);
+	rc_style_class->create_style = create_style;
+	rc_style_class->parse = parse;
+	rc_style_class->merge = merge;
+}
+
+void 
+gce_rc_style_register_type (GTypeModule *module)
+{
+	if (!gce_rc_style_type) {
+		static const GTypeInfo info = {
+			sizeof(GceRcStyleClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) class_init,
+			NULL,                   /* class_finalize */
+			NULL,                   /* class_data */
+			sizeof (GceRcStyle),
+			0,                      /* n_preallocs */
+			(GInstanceInitFunc) instance_init,
+		};
+
+		gce_rc_style_type = g_type_module_register_type (module, 
+								  GTK_TYPE_RC_STYLE, 
+								  "GceRcStyle", 
+								  &info, 0);
+	}
+}
+
+GType
+gce_rc_style_get_type (void) 
+{
+	return gce_rc_style_type;
+}

Added: branches/bzr/src/gce-rc-style.h
==============================================================================
--- (empty file)
+++ branches/bzr/src/gce-rc-style.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,46 @@
+/* Gtk CSS Engine
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GCE_RC_STYLE_H
+#define GCE_RC_STYLE_H
+
+#include <ccd/ccd.h>
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GCE_TYPE_RC_STYLE              (gce_rc_style_get_type ())
+#define GCE_RC_STYLE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GCE_TYPE_RC_STYLE, GceRcStyle))
+#define GCE_RC_STYLE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GCE_TYPE_RC_STYLE, GceRcStyleClass))
+#define GCE_IS_RC_STYLE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GCE_TYPE_RC_STYLE))
+#define GCE_IS_RC_STYLE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GCE_TYPE_RC_STYLE))
+#define GCE_RC_STYLE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GCE_TYPE_RC_STYLE, GceRcStyleClass))
+
+typedef struct _GceRcStyle GceRcStyle;
+typedef struct _GceRcStyleClass GceRcStyleClass;
+
+void  gce_rc_style_register_type (GTypeModule *module);
+GType gce_rc_style_get_type (void) G_GNUC_CONST;
+
+ccd_stylesheet_t const * gce_rc_style_get_stylesheet (void);
+
+G_END_DECLS
+
+#endif /* GCE_RC_STYLE_H */

Added: branches/bzr/src/gce-style.c
==============================================================================
--- (empty file)
+++ branches/bzr/src/gce-style.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,1269 @@
+/* Gtk CSS Engine
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include "gce-rc-style.h"
+#include "gce-style.h"
+#include "gce-maps.h"
+
+/* Implementation of hooks for the ccd library */
+
+enum GceNodeAttributeFlags {
+	CLASS		= 1 << 0,
+	PSEUDO_CLASS	= 1 << 1,
+	SHADOW		= 1 << 2
+};
+
+/*
+ * TODO: split into load- and run-time variants?
+ */
+typedef struct GceNode_ {
+	ccd_node_t		 parent;
+	GtkWidget		*widget;
+	/* custom attributes { */
+	char const		*class_name;
+	char const		*pseudo_class;
+	char const		*shadow;
+	char const		*orientation;
+	char const		*edge;
+	char const		*expander_style;
+	/* } */
+	enum {
+		UNSET,
+		CONTAINER,
+		PRIMITIVE,
+		TYPE
+	} flavor;
+	union {
+		char const	*primitive;
+		GType		 gtype;
+	} impl;
+} GceNode;
+
+#define NODE_CACHE_SIZE 24
+
+static struct GceNodeCache {
+	GceNode nodes[NODE_CACHE_SIZE];
+	int	cursor;
+} _node_cache = {
+	.cursor = -1
+};
+
+static GceNode *
+node_cache_top (struct GceNodeCache *cache)
+{
+	g_assert (cache);
+
+	return &cache->nodes[cache->cursor];
+}
+
+static GceNode *
+node_cache_push (struct GceNodeCache *cache)
+{
+	GceNode *node;
+
+	g_assert (cache && cache->cursor < (NODE_CACHE_SIZE - 1));
+
+	cache->cursor++;
+	node = &cache->nodes[cache->cursor];
+	memset (node, 0, sizeof (*node));
+
+	return node;
+}
+
+static void
+node_cache_pop (struct GceNodeCache *cache)
+{
+	g_assert (cache && cache->cursor >= 0);
+
+	cache->cursor--;
+}
+
+static gboolean
+is_a (GceNode const	*node,
+      char const	*type_name)
+{
+	GType gtype;
+
+	switch (node->flavor) {
+	case PRIMITIVE:
+		if (0 == strcmp (type_name, node->impl.primitive)) {
+			return TRUE;
+		}
+		/* fall thru */
+	case UNSET:
+	case CONTAINER:
+	case TYPE:
+		gtype = g_type_from_name (type_name);
+		return g_type_is_a (G_OBJECT_TYPE (node->widget), gtype);
+	default:
+		g_assert_not_reached ();
+		return FALSE;
+	}
+}
+
+static GceNode *
+get_container (GceNode const *node)
+{
+	GceNode		*container_node;
+	GtkWidget	*container;
+
+	g_assert (node);
+
+	switch (node->flavor) {
+	case UNSET:
+	case CONTAINER:
+		container = gtk_widget_get_parent (node->widget);
+		if (container) {
+			container_node = node_cache_push (&_node_cache);
+			container_node->flavor = CONTAINER;
+			container_node->widget = (GtkWidget *) g_object_ref (G_OBJECT (container));
+			container_node->impl.gtype = G_OBJECT_TYPE (G_OBJECT (container));
+		}
+		break;
+	case PRIMITIVE:
+		container_node = node_cache_push (&_node_cache);
+		container_node->flavor = UNSET;
+		container_node->widget = (GtkWidget *) g_object_ref (G_OBJECT (node->widget));
+		container_node->impl.primitive = NULL;
+		break;
+	case TYPE:
+		g_assert_not_reached ();
+		/* fall thru */
+	default:
+		container_node = NULL;
+	}
+
+	return container_node;
+}
+
+static GceNode *
+get_base_style (GceNode const *node)
+{
+	GceNode		*base_node;
+
+	g_assert (node);
+
+	switch (node->flavor) {
+	case UNSET:
+		if (GTK_TYPE_WIDGET == G_OBJECT_TYPE (G_OBJECT (node->widget))) {
+			/* already at top of inheritance hierarchy */
+			base_node = NULL;
+		} else {
+			/* inherit from superclass widget */
+			base_node = node_cache_push (&_node_cache);
+			base_node->widget = (GtkWidget *) g_object_ref (node->widget);
+			base_node->flavor = TYPE;
+			base_node->impl.gtype = g_type_parent (G_OBJECT_TYPE (G_OBJECT (node->widget)));
+		}
+		break;
+	case CONTAINER:
+		if (GTK_TYPE_WIDGET == node->impl.gtype) {
+			/* already at top of inheritance hierarchy */
+			base_node = NULL;
+		} else {
+			/* inherit from superclass widget */
+			base_node = node_cache_push (&_node_cache);
+			base_node->widget = (GtkWidget *) g_object_ref (node->widget);
+			base_node->flavor = CONTAINER;
+			base_node->impl.gtype = g_type_parent (node->impl.gtype);
+		} 
+		break;
+	case PRIMITIVE:
+		base_node = NULL;
+		break;
+	case TYPE:
+		if (GTK_TYPE_WIDGET == node->impl.gtype) {
+			/* already at top of inheritance hierarchy */
+			base_node = NULL;
+		} else {
+			/* inherit from superclass widget */
+			base_node = node_cache_push (&_node_cache);
+			base_node->widget = (GtkWidget *) g_object_ref (node->widget);
+			base_node->flavor = TYPE;
+			base_node->impl.gtype = g_type_parent (node->impl.gtype);
+		} 
+		break;
+	default:
+		g_assert_not_reached ();
+		base_node = NULL;
+	}
+
+	return base_node;
+}
+
+static char const *
+get_id (GceNode const *node)
+{
+	g_return_val_if_fail (node, NULL);
+
+	switch (node->flavor) {
+	case UNSET:
+	case CONTAINER:
+	case PRIMITIVE:
+		return gtk_widget_get_name (node->widget);
+	case TYPE:
+	default:
+		g_assert_not_reached ();
+		return NULL;
+	}
+}
+
+static char const *
+get_type (GceNode const *node)
+{
+	g_return_val_if_fail (node, NULL);
+
+	switch (node->flavor) {
+	case UNSET:
+		return G_OBJECT_TYPE_NAME (G_OBJECT (node->widget));
+	case CONTAINER:
+	case TYPE:
+		return g_type_name (node->impl.gtype);
+	case PRIMITIVE:
+		g_assert (node->impl.primitive);
+		return node->impl.primitive;
+	default:
+		g_assert_not_reached ();
+		return NULL;
+	}
+}
+
+static char const *
+get_class (GceNode const *node)
+{
+	g_return_val_if_fail (node, NULL);
+
+	return node->class_name;
+}
+
+static char const *
+get_pseudo_class (GceNode const *node)
+{
+	g_return_val_if_fail (node, NULL);
+
+	return node->pseudo_class;
+}
+
+static char const *
+get_attribute (GceNode const	*node, 
+	       char const	*name)
+{
+	GValue			 property;
+	char const		*value;
+
+	g_assert (node && node->widget);
+
+	if (node->flavor == TYPE) {
+		g_warning ("Querying attribute `%s' on something not a widget", name);
+		return NULL;
+	}
+
+	/* attributes provided in the drawing function take precedence */
+	if (0 == strcmp ("shadow", name)) {
+		return node->shadow;
+	} else if (0 == strcmp ("orientation", name)) {
+		return node->orientation;
+	} else if (0 == strcmp ("edge", name)) {
+		return node->edge;
+	} else if (0 == strcmp ("expander-style", name)) {
+		return node->expander_style;
+	}
+
+	/* now try to find an apropriate style property */
+	g_value_unset (&property);
+	gtk_widget_style_get_property (node->widget, name, &property);
+	value = NULL;
+	if (G_VALUE_HOLDS (&property, G_TYPE_BOOLEAN)) {
+		value = g_value_get_boolean (&property) ? "true" : "false";
+	} else if (G_VALUE_HOLDS (&property, G_TYPE_STRING)) {
+		value = g_value_get_string (&property);
+	} else {
+		g_warning ("Querying for properties of type `%s' is not supported yet.", 
+			   G_VALUE_TYPE_NAME (&property));
+	}
+
+	return value;
+}
+
+static void
+release (GceNode *node)
+{
+	g_assert (node == node_cache_top (&_node_cache));
+
+	if (node->widget) {
+		g_object_unref (G_OBJECT (node->widget));
+	}
+
+	node_cache_pop (&_node_cache);
+}
+
+static const ccd_node_class_t _node_class = {
+	.is_a			= (ccd_node_is_a_f) is_a,
+	.get_container		= (ccd_node_get_container_f) get_container,
+	.get_base_style		= (ccd_node_get_base_style_f) get_base_style,
+	.get_id			= (ccd_node_get_id_f) get_id,
+	.get_type		= (ccd_node_get_type_f) get_type,
+	.get_class		= (ccd_node_get_class_f) get_class,
+	.get_pseudo_class	= (ccd_node_get_pseudo_class_f) get_pseudo_class,
+	.get_attribute		= (ccd_node_get_attribute_f) get_attribute,
+	.release		= (ccd_node_release_f) release
+};
+
+ccd_node_class_t const *
+gce_style_get_ccd_node_class (void)
+{
+	return &_node_class;
+}
+
+/* Implementation of the engine's GtkStyle subclass */
+
+struct _GceStyle
+{
+	GtkStyle parent;
+};
+
+struct _GceStyleClass
+{
+	GtkStyleClass parent;
+};
+
+
+static GType          gce_style_type = 0;
+static GtkStyleClass *gce_style_parent_class = NULL;
+
+static ccd_selector_group_t *
+setup (GceNode const *node, 
+       GceNode const *base)
+{
+	ccd_stylesheet_t const	*stylesheet;
+	ccd_selector_group_t	*group;
+	gboolean		 status;
+
+	stylesheet = gce_rc_style_get_stylesheet ();
+	group = ccd_selector_group_new ();
+	status = FALSE;
+
+	/* query for widget theming */
+	status |= ccd_stylesheet_query_collect (stylesheet, (ccd_node_t const *) node, group, FALSE);
+
+	/* query for primitive theming */
+	status |= ccd_stylesheet_query_collect (stylesheet, (ccd_node_t const *) base, group, TRUE);
+
+	if (!status) {
+		g_warning ("Un-themed widget `%s', primitive `%s'.", 
+			   G_OBJECT_TYPE_NAME (G_OBJECT (node->widget)), base->impl.primitive);
+		ccd_selector_group_free (group);
+		group = NULL;
+	}
+
+	return group;
+}
+
+static void
+rectangle (GtkStyle		*self, 
+	   GceNode const	*node,
+	   GceNode const	*base,
+	   GdkWindow		*window, 
+	   GdkRectangle		*area, 
+	   GtkWidget		*widget, 
+	   gint			 x, 
+	   gint			 y, 
+	   gint			 width, 
+	   gint			 height,
+	   gboolean		 fill)
+{
+	ccd_selector_group_t	*group;
+	ccd_style_t		 style;
+	cairo_t			*cr;
+
+	group = setup (node, base);
+	if (group) {
+		cr = gdk_cairo_create (window);
+		ccd_style_init (&style);
+
+		if (area) {
+			gdk_cairo_rectangle (cr, area);
+			cairo_clip (cr);
+		}
+
+		ccd_selector_group_apply (group, &style);
+		if (fill) {
+			ccd_style_draw_rectangle (&style, cr, x, y, width, height);
+		} else {
+			ccd_style_draw_outline (&style, cr, x, y, width, height);
+		}
+
+		cairo_destroy (cr);
+		ccd_selector_group_free (group);
+	}
+}
+
+static void
+gap (GtkStyle		*self, 
+     GceNode const	*node,
+     GceNode const	*base,
+     GdkWindow		*window, 
+     GdkRectangle	*area, 
+     GtkWidget		*widget, 
+     gint		 x, 
+     gint		 y, 
+     gint		 width, 
+     gint		 height,
+     GtkPositionType	 gap_side,
+     gint		 gap_start,
+     gint		 gap_width)
+{
+	ccd_selector_group_t	*group;
+	ccd_style_t		 style;
+	cairo_t			*cr;
+
+	group = setup (node, base);
+	if (group) {
+		cr = gdk_cairo_create (window);
+		ccd_style_init (&style);
+
+		if (area) {
+			gdk_cairo_rectangle (cr, area);
+			cairo_clip (cr);
+		}
+
+		ccd_selector_group_apply (group, &style);
+		ccd_style_draw_gap (&style, cr, x, y, width, height, gap_side, gap_start, gap_width);
+
+		cairo_destroy (cr);
+		ccd_selector_group_free (group);
+	}
+}
+
+static void
+line (GtkStyle		*self, 
+      GceNode		*node,
+      GceNode		*base,
+      GdkWindow		*window, 
+      GdkRectangle	*area, 
+      GtkWidget		*widget, 
+      gint		 x1, 
+      gint		 x2, 
+      gint		 y1, 
+      gint		 y2)
+{
+	ccd_selector_group_t	*group;
+	ccd_style_t		 style;
+	cairo_t			*cr;
+
+	group = setup (node, base);
+	if (group) {
+		cr = gdk_cairo_create (window);
+		ccd_style_init (&style);
+
+		if (area) {
+			gdk_cairo_rectangle (cr, area);
+			cairo_clip (cr);
+		}
+
+		ccd_selector_group_apply (group, &style);
+		ccd_style_draw_line (&style, cr, x1, x2, y1, y2);
+
+		cairo_destroy (cr);
+		ccd_selector_group_free (group);
+	}
+}
+
+static void 
+draw_hline (GtkStyle		*self, 
+	    GdkWindow		*window, 
+	    GtkStateType	 state, 
+	    GdkRectangle	*area, 
+	    GtkWidget		*widget, 
+	    char const		*detail, 
+	    gint		 x1, 
+	    gint		 x2, 
+	    gint		 y)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "hline";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->flavor = UNSET;
+
+	line (self, node, base, window, area, widget, x1, x2, y, y);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_vline (GtkStyle		*self, 
+	    GdkWindow		*window, 
+	    GtkStateType	 state, 
+	    GdkRectangle	*area, 
+	    GtkWidget		*widget, 
+	    char const		*detail, 
+	    gint		 y1, 
+	    gint		 y2, 
+	    gint		 x)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "vline";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->flavor = UNSET;
+
+	line (self, node, base, window, area, widget, x, x, y1, y2);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+
+}
+
+static void 
+draw_shadow (GtkStyle		*self, 
+	     GdkWindow		*window, 
+	     GtkStateType	 state, 
+	     GtkShadowType	 shadow, 
+	     GdkRectangle	*area, 
+	     GtkWidget		*widget, 
+	     char const		*detail, 
+	     gint		 x, 
+	     gint		 y, 
+	     gint		 width, 
+	     gint		 height)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "shadow";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_box (GtkStyle		*self, 
+	  GdkWindow		*window, 
+	  GtkStateType		 state, 
+	  GtkShadowType		 shadow,
+	  GdkRectangle		*area,
+	  GtkWidget		*widget,
+	  char const		*detail,
+	  gint			 x,
+	  gint			 y,
+	  gint			 width,
+	  gint			 height)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "box";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget,
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_flat_box (GtkStyle		*self, 
+	       GdkWindow	*window, 
+	       GtkStateType	 state, 
+	       GtkShadowType	 shadow,
+	       GdkRectangle	*area,
+	       GtkWidget	*widget,
+	       char const	*detail,
+	       gint		 x,
+	       gint		 y,
+	       gint		 width,
+	       gint		 height)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "flatbox";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_check (GtkStyle		*self,
+	    GdkWindow		*window,
+	    GtkStateType	 state,
+	    GtkShadowType	 shadow,
+	    GdkRectangle	*area,
+	    GtkWidget		*widget,
+	    char const		*detail,
+	    gint		 x,
+	    gint		 y,
+	    gint		 width,
+	    gint		 height)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "check";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_option (GtkStyle		 *self,
+	     GdkWindow		 *window,
+	     GtkStateType	 state,
+	     GtkShadowType	 shadow,
+	     GdkRectangle	 *area,
+	     GtkWidget		 *widget,
+	     char const		 *detail,
+	     gint		 x,
+	     gint		 y,
+	     gint		 width,
+	     gint		 height)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "option";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_shadow_gap (GtkStyle		*self,
+		 GdkWindow		*window,
+		 GtkStateType		 state,
+		 GtkShadowType		 shadow,
+		 GdkRectangle		*area,
+		 GtkWidget		*widget,
+		 char const		*detail,
+		 gint			 x,
+		 gint			 y,
+		 gint			 width,
+		 gint			 height,
+		 GtkPositionType	 gap_side,
+		 gint			 gap_start,
+		 gint			 gap_width)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "shadow";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->flavor = UNSET;
+
+	gap (self, node, base, window, area, widget, 
+	     x, y, width, height, gap_side, gap_start, gap_width);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_box_gap (GtkStyle			*self,
+	      GdkWindow			*window,
+	      GtkStateType		 state,
+	      GtkShadowType		 shadow,
+	      GdkRectangle		*area,
+	      GtkWidget			*widget,
+	      char const		*detail,
+	      gint			 x,
+	      gint			 y,
+	      gint			 width,
+	      gint			 height,
+	      GtkPositionType		 gap_side,
+	      gint			 gap_start,
+	      gint			 gap_width)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "box";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->flavor = UNSET;
+
+	gap (self, node, base, window, area, widget, 
+	     x, y, width, height, gap_side, gap_start, gap_width);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_extension (GtkStyle	*self,
+		GdkWindow	*window,
+		GtkStateType	 state,
+		GtkShadowType	 shadow,
+		GdkRectangle	*area,
+		GtkWidget	*widget,
+		char const	*detail,
+		gint		 x,
+		gint		 y,
+		gint		 width,
+		gint		 height,
+		GtkPositionType	 gap_side)
+{
+	GceNode *node;
+	GceNode *base;
+	gint	 gap_width;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "extension";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->flavor = UNSET;
+
+	switch (gap_side) {
+	case GTK_POS_LEFT:
+	case GTK_POS_RIGHT:
+		gap_width = height;
+		break;
+	case GTK_POS_TOP:
+	case GTK_POS_BOTTOM:
+		gap_width = width;
+		break;
+	}
+
+	gap (self, node, base, window, area, widget, 
+	     x, y, width, height, gap_side, 0, gap_width);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_slider (GtkStyle		*self,
+	     GdkWindow		*window,
+	     GtkStateType	 state,
+	     GtkShadowType	 shadow,
+	     GdkRectangle	*area,
+	     GtkWidget		*widget,
+	     char const		*detail,
+	     gint		 x,
+	     gint		 y,
+	     gint		 width,
+	     gint		 height,
+	     GtkOrientation	 orientation)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->orientation = gce_maps_get_orientation (orientation);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "slider";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->orientation = base->orientation;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_handle (GtkStyle		*self,
+	     GdkWindow		*window,
+	     GtkStateType	 state,
+	     GtkShadowType	 shadow,
+	     GdkRectangle	*area,
+	     GtkWidget		*widget,
+	     char const		*detail,
+	     gint		 x,
+	     gint		 y,
+	     gint		 width,
+	     gint		 height,
+	     GtkOrientation	 orientation)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->orientation = gce_maps_get_orientation (orientation);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "handle";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->orientation = base->orientation;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_resize_grip (GtkStyle		*self,
+		  GdkWindow		*window,
+		  GtkStateType		 state,
+		  GdkRectangle		*area,
+		  GtkWidget		*widget,
+		  char const		*detail,
+		  GdkWindowEdge		 edge,
+		  gint			 x,
+		  gint			 y,
+		  gint			 width,
+		  gint			 height)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->edge = gce_maps_get_window_edge (edge);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "resizegrip";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->edge = base->edge;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+draw_focus (GtkStyle		*self,
+	    GdkWindow		*window,
+	    GtkStateType	 state,
+	    GdkRectangle	*area,
+	    GtkWidget		*widget,
+	    char const		*detail,
+	    gint		 x,
+	    gint		 y,
+	    gint		 width,
+	    gint		 height)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "focus";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, FALSE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void
+draw_expander (GtkStyle		*self,
+	       GdkWindow	*window,
+	       GtkStateType	 state,
+	       GdkRectangle	*area,
+	       GtkWidget	*widget,
+	       char const	*detail,
+	       gint		 x,
+	       gint		 y,
+	       GtkExpanderStyle	 style)
+{
+#define DEFAULT_EXPANDER_SIZE 12
+	GceNode *node;
+	GceNode *base;
+	gint	 expander_size;
+
+	if (widget &&
+	    gtk_widget_class_find_style_property (GTK_WIDGET_GET_CLASS (widget),
+						  "expander-size")) {
+		gtk_widget_style_get (widget,
+				      "expander-size", &expander_size,
+				      NULL);
+	} else {
+		expander_size = DEFAULT_EXPANDER_SIZE;
+	}
+
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->expander_style = gce_maps_get_expander_style (style);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "expander";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->expander_style = base->expander_style;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, expander_size, expander_size, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+#undef DEFAULT_EXPANDER_SIZE
+}
+
+static void
+draw_diamond (GtkStyle		*self,
+	      GdkWindow		*window,
+	      GtkStateType	 state,
+	      GtkShadowType	 shadow,
+	      GdkRectangle	*area,
+	      GtkWidget		*widget,
+	      char const	*detail,
+	      gint		 x,
+	      gint		 y,
+	      gint		 width,
+	      gint		 height)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "diamond";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void
+draw_arrow (GtkStyle		*self,
+	    GdkWindow		*window,
+	    GtkStateType	 state,
+	    GtkShadowType	 shadow,
+	    GdkRectangle	*area,
+	    GtkWidget		*widget,
+	    char const		*detail,
+	    GtkArrowType	 arrow,
+	    gboolean		 fill,
+	    gint		 x,
+	    gint		 y,
+	    gint		 width,
+	    gint		 height)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->orientation = gce_maps_get_arrow (arrow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "arrow";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->orientation = base->orientation;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void
+draw_tab (GtkStyle		*self,
+	  GdkWindow		*window,
+	  GtkStateType		 state,
+	  GtkShadowType		 shadow,
+	  GdkRectangle		*area,
+	  GtkWidget		*widget,
+	  char const		*detail,
+	  gint			 x,
+	  gint			y,
+	  gint			width,
+	  gint			height)
+{
+	GceNode *node;
+	GceNode *base;
+
+	base = node_cache_push (&_node_cache);
+	base->widget = widget;
+	base->class_name = gce_maps_get_detail (detail);
+	base->pseudo_class = gce_maps_get_state (state);
+	base->shadow = gce_maps_get_shadow (shadow);
+	base->flavor = PRIMITIVE;
+	base->impl.primitive = "tab";
+
+	node = node_cache_push (&_node_cache);
+	node->widget = widget;
+	node->class_name = base->class_name;
+	node->pseudo_class = base->pseudo_class;
+	node->shadow = base->shadow;
+	node->flavor = UNSET;
+
+	rectangle (self, node, base, window, area, widget, 
+		   x, y, width, height, TRUE);
+
+	node_cache_pop (&_node_cache);
+	node_cache_pop (&_node_cache);
+}
+
+static void 
+instance_init (GceStyle *self)
+{
+
+}
+
+static void 
+class_init (GceStyleClass *klass)
+{
+	GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
+
+	gce_style_parent_class = g_type_class_peek_parent (klass);
+
+	style_class->draw_hline = draw_hline;
+	style_class->draw_vline = draw_vline;
+	style_class->draw_shadow = draw_shadow;
+	/*
+	draw_polygon
+	*/
+	style_class->draw_arrow = draw_arrow;
+	style_class->draw_diamond = draw_diamond;
+	style_class->draw_box = draw_box;
+	style_class->draw_flat_box = draw_flat_box;
+	style_class->draw_check = draw_check;
+	style_class->draw_option = draw_option;
+	style_class->draw_tab = draw_tab;
+	style_class->draw_shadow_gap = draw_shadow_gap;
+	style_class->draw_box_gap = draw_box_gap;
+	style_class->draw_extension = draw_extension;
+	style_class->draw_focus = draw_focus;
+	style_class->draw_slider = draw_slider;
+	style_class->draw_handle = draw_handle;
+	style_class->draw_expander = draw_expander;
+/*
+draw_layout
+*/
+	style_class->draw_resize_grip = draw_resize_grip;
+}
+
+void
+gce_style_register_type (GTypeModule *module)
+{
+	if (!gce_style_type) {
+		static const GTypeInfo info = {
+			sizeof (GceStyleClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) class_init,
+			NULL,                   /* class_finalize */
+			NULL,                   /* class_data */
+			sizeof (GceStyle),
+			0,                      /* n_preallocs */
+			(GInstanceInitFunc) instance_init,
+		};
+
+		gce_style_type = g_type_module_register_type (module, 
+							       GTK_TYPE_STYLE, 
+							       "GceStyle", 
+							       &info, 0);
+	}
+}
+
+GType
+gce_style_get_type (void) 
+{
+	return gce_style_type;
+}

Added: branches/bzr/src/gce-style.h
==============================================================================
--- (empty file)
+++ branches/bzr/src/gce-style.h	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,46 @@
+/* Gtk CSS Engine
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GCE_STYLE_H
+#define GCE_STYLE_H
+
+#include <ccd/ccd.h>
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GCE_TYPE_STYLE              (gce_style_get_type ())
+#define GCE_STYLE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GCE_TYPE_STYLE, GceStyle))
+#define GCE_STYLE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GCE_TYPE_STYLE, GceStyleClass))
+#define GCE_IS_STYLE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GCE_TYPE_STYLE))
+#define GCE_IS_STYLE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GCE_TYPE_STYLE))
+#define GCE_STYLE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GCE_TYPE_STYLE, GceStyleClass))
+
+typedef struct _GceStyle GceStyle;
+typedef struct _GceStyleClass GceStyleClass;
+
+ccd_node_class_t const * gce_style_get_ccd_node_class (void);
+
+void  gce_style_register_type (GTypeModule *module);
+GType gce_style_get_type      (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* GCE_STYLE_H */

Added: branches/bzr/src/gce-theme.c
==============================================================================
--- (empty file)
+++ branches/bzr/src/gce-theme.c	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,61 @@
+/* Gtk CSS Engine
+ * Copyright (C) 2008 Robert Staudinger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <ccd/ccd.h>
+#include <gmodule.h>
+#include <gtk/gtk.h>
+
+#include "gce-style.h"
+#include "gce-rc-style.h"
+
+/* This prototypes silence some warnings. */
+G_MODULE_EXPORT void		theme_init		(GTypeModule *module);
+G_MODULE_EXPORT void		theme_exit		(void);
+G_MODULE_EXPORT GtkRcStyle *	theme_create_rc_style	(void);
+G_MODULE_EXPORT const gchar *	g_module_check_init	(GModule *module);
+
+G_MODULE_EXPORT void 
+theme_init (GTypeModule *module)
+{
+	gce_rc_style_register_type (module);
+	gce_style_register_type (module);
+
+	ccd_init (gce_style_get_ccd_node_class ());
+}
+
+G_MODULE_EXPORT void 
+theme_exit (void)
+{
+	ccd_shutdown ();
+}
+
+G_MODULE_EXPORT GtkRcStyle*
+theme_create_rc_style (void)
+{
+	return GTK_RC_STYLE (g_object_new (GCE_TYPE_RC_STYLE, NULL));
+}
+
+G_MODULE_EXPORT const gchar*
+g_module_check_init (GModule *module)
+{
+	return gtk_check_version (GTK_MAJOR_VERSION, 
+				  GTK_MINOR_VERSION, 
+				  GTK_MICRO_VERSION - GTK_INTERFACE_AGE);
+}
+

Added: branches/bzr/themes/Makefile.am
==============================================================================
--- (empty file)
+++ branches/bzr/themes/Makefile.am	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,3 @@
+
+SUBDIRS = gtk-css-test
+

Added: branches/bzr/themes/gtk-css-test/Makefile.am
==============================================================================
--- (empty file)
+++ branches/bzr/themes/gtk-css-test/Makefile.am	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,2 @@
+
+SUBDIRS = gtk-2.0

Added: branches/bzr/themes/gtk-css-test/gtk-2.0/Makefile.am
==============================================================================
--- (empty file)
+++ branches/bzr/themes/gtk-css-test/gtk-2.0/Makefile.am	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,7 @@
+
+themedir = $(datadir)/themes/gtk-css-test/gtk-2.0
+theme_DATA = \
+	gtkrc \
+	styles.css
+
+EXTRA_DIST = $(theme_DATA)

Added: branches/bzr/themes/gtk-css-test/gtk-2.0/gtkrc
==============================================================================
--- (empty file)
+++ branches/bzr/themes/gtk-css-test/gtk-2.0/gtkrc	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,12 @@
+style "default"
+{
+	xthickness = 1
+	ythickness = 1
+
+	engine "css" 
+	{
+		href = "styles.css"
+	}
+}
+widget_class "*" style "default"
+

Added: branches/bzr/themes/gtk-css-test/gtk-2.0/styles.css
==============================================================================
--- (empty file)
+++ branches/bzr/themes/gtk-css-test/gtk-2.0/styles.css	Fri Sep  5 11:32:51 2008
@@ -0,0 +1,130 @@
+/*
+box {
+	background-color: yellow;
+	border: 1px dashed green;
+	border-bottom: 2px solid red;
+}
+
+box:prelight {
+	background-color: red;	
+}
+
+box.bar {
+	background-color: orange;
+}
+
+hline {
+	border: 2px solid black;
+}
+
+vline {
+	border: 2px solid brown;
+}
+
+GtkButton {
+	background-color: blue;	
+}
+
+GtkButton:prelight {
+	background-color: green;	
+}
+
+GtkToggleButton {
+	background-color: lightblue;	
+}
+
+GtkComboBox GtkButton {
+	background-color: lightgreen;
+}
+
+GtkVBox GtkButton {
+	background-color: indigo;	
+}
+
+GtkScrollbar box {
+	background-color: lightgreen;
+}
+
+GtkScrollbar box.trough {
+	background-color: darkgreen;
+}
+
+GtkCheckButton check.checkbutton {
+	background-color: white;
+}
+*/
+
+arrow {
+	background-color: black;
+}
+
+tab {
+	background-color: blue;
+}
+
+option {
+	background-color: red;
+}
+
+check {
+	background-color: green;
+}
+
+box {
+	background-color: darkkhaki;
+	border: 1px solid black;
+}
+
+flatbox {
+	background-color: darkkhaki;
+	border: 1px solid black;
+}
+
+GtkEntry flatbox {
+	background-color: darkkhaki;
+	border: none;
+}
+
+shadow {
+	background-color: khaki;
+	border: 1px solid black;
+}
+
+GtkEntry shadow {
+	background-color: darkkhaki;
+}
+
+slider {
+	background-color: orange;
+	border: 1px solid black;
+}
+
+extension {
+	border: 1px solid black;
+}
+
+focus {
+	border: 2px dotted yellow;
+}
+
+handle {
+	border: 1px dashed blue;
+}
+
+handle[orientation=vertical] {
+	background-color: gray;
+	border-left: 3px solid blue;
+}
+
+resizegrip[edge=south-east] {
+	border-right: 2px solid blue;
+	border-bottom: 2px solid blue;
+}
+
+GtkMenuBar {
+	border-bottom: none;
+}
+
+GtkProgressBar:prelight {
+	background-color: yellow;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]