Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <mpg@redhat.com>2006-06-07 16:54:14 (GMT)
committer Marco Pesenti Gritti <mpg@redhat.com>2006-06-07 16:54:14 (GMT)
commit0658d108b9f1c4d4215f240895ec3742f512b757 (patch)
tree3b7b55a0752fc1226c7d09c9b05494a58cd8b563
Add an .hgignore
-rw-r--r--AUTHORS0
-rw-r--r--COPYING343
-rw-r--r--ChangeLog0
-rw-r--r--Makefile.am3
-rw-r--r--NEWS0
-rw-r--r--README6
-rw-r--r--art/Makefile.am1
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-1.pngbin0 -> 39210 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-10.pngbin0 -> 5003 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-11.pngbin0 -> 4989 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-12.pngbin0 -> 5031 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-2.pngbin0 -> 4949 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-3.pngbin0 -> 5017 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-4.pngbin0 -> 4856 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-5.pngbin0 -> 4964 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-6.pngbin0 -> 5050 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-7.pngbin0 -> 5008 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-8.pngbin0 -> 5061 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-9.pngbin0 -> 5139 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-24-hotspot.pngbin0 -> 54393 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-36-1.pngbin0 -> 119082 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-36-hotspot.pngbin0 -> 3450 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-48-1.pngbin0 -> 150308 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve-48-hotspot.pngbin0 -> 5177 bytes
-rw-r--r--art/cursor/Bluecurve/Bluecurve.cursortheme191
-rw-r--r--art/cursor/Bluecurve/ChangeLog9
-rw-r--r--art/cursor/Bluecurve/Makefile.am44
-rw-r--r--art/cursor/Makefile.am1
-rw-r--r--art/cursor/cursorthemegen/ChangeLog48
-rw-r--r--art/cursor/cursorthemegen/Makefile.am11
-rw-r--r--art/cursor/cursorthemegen/README186
-rw-r--r--art/cursor/cursorthemegen/cursortheme.h92
-rw-r--r--art/cursor/cursorthemegen/main.c615
-rw-r--r--art/cursor/cursorthemegen/sample.cursortheme148
-rw-r--r--art/cursor/cursorthemegen/themefile.c609
-rwxr-xr-xautogen.sh69
-rw-r--r--configure.in31
-rw-r--r--gtkrc2-default3
38 files changed, 2410 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/AUTHORS
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..707b1c4
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,343 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 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.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+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 give any other recipients of the Program a copy of this License
+along with the Program.
+
+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 Program or any portion
+of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) 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; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, 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 executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or 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 counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program 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.
+
+ 5. 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 Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. 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 Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program 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 Program.
+
+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.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program 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.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+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 Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, 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
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), 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 Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..c980be4
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = art
+
+EXTRA_DIST = gtkrc2-default
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..7c6de6c
--- /dev/null
+++ b/README
@@ -0,0 +1,6 @@
+redhat-artwork contains the "required" artwork for the default Red Hat
+look and feel. Extra bonus art can be found in the redhat-wallpapers
+and redhat-extra-themes packages.
+
+NOTE WHEN BUILDING: Due to a bug in intltool, you need to build the tree
+with a non-UTF-8 locale.
diff --git a/art/Makefile.am b/art/Makefile.am
new file mode 100644
index 0000000..cacd1ba
--- /dev/null
+++ b/art/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = cursor
diff --git a/art/cursor/Bluecurve/Bluecurve-24-1.png b/art/cursor/Bluecurve/Bluecurve-24-1.png
new file mode 100644
index 0000000..b5e4303
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-1.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-10.png b/art/cursor/Bluecurve/Bluecurve-24-10.png
new file mode 100644
index 0000000..ce3012e
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-10.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-11.png b/art/cursor/Bluecurve/Bluecurve-24-11.png
new file mode 100644
index 0000000..423dcc3
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-11.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-12.png b/art/cursor/Bluecurve/Bluecurve-24-12.png
new file mode 100644
index 0000000..0bf4d57
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-12.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-2.png b/art/cursor/Bluecurve/Bluecurve-24-2.png
new file mode 100644
index 0000000..5321bb1
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-2.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-3.png b/art/cursor/Bluecurve/Bluecurve-24-3.png
new file mode 100644
index 0000000..1f31fd3
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-3.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-4.png b/art/cursor/Bluecurve/Bluecurve-24-4.png
new file mode 100644
index 0000000..1e1c7d0
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-4.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-5.png b/art/cursor/Bluecurve/Bluecurve-24-5.png
new file mode 100644
index 0000000..6201a75
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-5.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-6.png b/art/cursor/Bluecurve/Bluecurve-24-6.png
new file mode 100644
index 0000000..4e2350b
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-6.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-7.png b/art/cursor/Bluecurve/Bluecurve-24-7.png
new file mode 100644
index 0000000..e6d48c7
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-7.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-8.png b/art/cursor/Bluecurve/Bluecurve-24-8.png
new file mode 100644
index 0000000..30fe07f
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-8.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-9.png b/art/cursor/Bluecurve/Bluecurve-24-9.png
new file mode 100644
index 0000000..5bf0a41
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-9.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-24-hotspot.png b/art/cursor/Bluecurve/Bluecurve-24-hotspot.png
new file mode 100644
index 0000000..f51c5d8
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-24-hotspot.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-36-1.png b/art/cursor/Bluecurve/Bluecurve-36-1.png
new file mode 100644
index 0000000..1649cad
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-36-1.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-36-hotspot.png b/art/cursor/Bluecurve/Bluecurve-36-hotspot.png
new file mode 100644
index 0000000..6ccd76b
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-36-hotspot.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-48-1.png b/art/cursor/Bluecurve/Bluecurve-48-1.png
new file mode 100644
index 0000000..6f5305a
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-48-1.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve-48-hotspot.png b/art/cursor/Bluecurve/Bluecurve-48-hotspot.png
new file mode 100644
index 0000000..4852623
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve-48-hotspot.png
Binary files differ
diff --git a/art/cursor/Bluecurve/Bluecurve.cursortheme b/art/cursor/Bluecurve/Bluecurve.cursortheme
new file mode 100644
index 0000000..1550a5d
--- /dev/null
+++ b/art/cursor/Bluecurve/Bluecurve.cursortheme
@@ -0,0 +1,191 @@
+<theme name="Bluecurve">
+ <source size="24" gridsize="48">
+ <image file="Bluecurve-24-1.png" use="0"/>
+ <image file="Bluecurve-24-2.png" use="1"/>
+ <image file="Bluecurve-24-3.png" use="2"/>
+ <image file="Bluecurve-24-4.png" use="3"/>
+ <image file="Bluecurve-24-5.png" use="4"/>
+ <image file="Bluecurve-24-6.png" use="5"/>
+ <image file="Bluecurve-24-7.png" use="6"/>
+ <image file="Bluecurve-24-8.png" use="7"/>
+ <image file="Bluecurve-24-9.png" use="8"/>
+ <image file="Bluecurve-24-10.png" use="9"/>
+ <image file="Bluecurve-24-11.png" use="10"/>
+ <image file="Bluecurve-24-12.png" use="11"/>
+ <image file="Bluecurve-24-hotspot.png" use="hotspot"/>
+ </source>
+ <source size="36" gridsize="72">
+ <image file="Bluecurve-36-1.png" use="0"/>
+ <image file="Bluecurve-36-hotspot.png" use="hotspot"/>
+ </source>
+ <source size="48" gridsize="96">
+ <image file="Bluecurve-48-1.png" use="0"/>
+ <image file="Bluecurve-48-hotspot.png" use="hotspot"/>
+ </source>
+ <layout>
+ <row>
+ <cursor name="X_cursor"/>
+ <cursor name="arrow"/>
+ <cursor name="based_arrow_down"/>
+ <cursor name="based_arrow_up"/>
+ <cursor name="boat"/>
+ <cursor name="bogosity"/>
+ <cursor name="bottom_left_corner"/>
+ <cursor name="bottom_right_corner"/>
+ </row><row>
+ <cursor name="bottom_side"/>
+ <cursor name="bottom_tee"/>
+ <cursor name="box_spiral"/>
+ <cursor name="center_ptr"/>
+ <cursor name="circle"/>
+ <cursor name="clock"/>
+ <cursor name="coffee_mug"/>
+ <cursor name="cross"/>
+ </row><row>
+ <cursor name="cross_reverse"/>
+ <cursor name="crosshair"/>
+ <cursor name="diamond_cross"/>
+ <cursor name="dot"/>
+ <cursor name="dotbox"/>
+ <cursor name="double_arrow"/>
+ <cursor name="draft_large"/>
+ <cursor name="draft_small"/>
+ </row><row>
+ <cursor name="draped_box"/>
+ <cursor name="exchange"/>
+ <cursor name="fleur"/>
+ <cursor name="gobbler"/>
+ <cursor name="gumby"/>
+ <cursor name="hand1"/>
+ <cursor name="hand2"/>
+ <cursor name="heart"/>
+ </row><row>
+ <cursor name="icon"/>
+ <cursor name="iron_cross"/>
+ <cursor name="left_ptr"/>
+ <cursor name="left_side"/>
+ <cursor name="left_tee"/>
+ <cursor name="leftbutton"/>
+ <cursor name="ll_angle"/>
+ <cursor name="lr_angle"/>
+ </row><row>
+ <cursor name="man"/>
+ <cursor name="middlebutton"/>
+ <cursor name="mouse"/>
+ <cursor name="pencil"/>
+ <cursor name="pirate"/>
+ <cursor name="plus"/>
+ <cursor name="question_arrow"/>
+ <cursor name="right_ptr"/>
+ </row><row>
+ <cursor name="right_side"/>
+ <cursor name="right_tee"/>
+ <cursor name="rightbutton"/>
+ <cursor name="rtl_logo"/>
+ <cursor name="sailboat"/>
+ <cursor name="sb_down_arrow"/>
+ <cursor name="sb_h_double_arrow"/>
+ <cursor name="sb_left_arrow"/>
+ </row><row>
+ <cursor name="sb_right_arrow"/>
+ <cursor name="sb_up_arrow"/>
+ <cursor name="sb_v_double_arrow"/>
+ <cursor name="shuttle"/>
+ <cursor name="sizing"/>
+ <cursor name="spider"/>
+ <cursor name="spraycan"/>
+ <cursor name="star"/>
+ </row><row>
+ <cursor name="target"/>
+ <cursor name="tcross"/>
+ <cursor name="top_left_arrow"/>
+ <cursor name="top_left_corner"/>
+ <cursor name="top_right_corner"/>
+ <cursor name="top_side"/>
+ <cursor name="top_tee"/>
+ <cursor name="trek"/>
+ </row><row>
+ <cursor name="ul_angle"/>
+ <cursor name="umbrella"/>
+ <cursor name="ur_angle"/>
+ <cursor name="_watch-old_">
+ </cursor>
+ <cursor name="xterm"/>
+ <cursor name="left_ptr_watch">
+ <frame delay="60"/>
+ <frame delay="60"/>
+ <frame delay="60"/>
+ <frame delay="60"/>
+ <frame delay="60"/>
+ <frame delay="60"/>
+ <frame delay="60"/>
+ <frame delay="60"/>
+ <frame delay="60"/>
+ <frame delay="60"/>
+ <frame delay="60"/>
+ <frame delay="60"/>
+ </cursor>
+ </row>
+ <row>
+ <cursor name="color-picker"/>
+ <cursor name="dnd-move"/>
+ <cursor name="dnd-copy"/>
+ <cursor name="dnd-ask"/>
+ <cursor name="dnd-link"/>
+ <cursor name="dnd-none"/>
+ </row>
+ </layout>
+<!--
+ The number of cursors in the WhiteGlass theme distributed with XFree86
+ are reduced using the following aliases:
+
+ <alias name="arrow" target="right_ptr"/>
+ <alias name="cross_reverse" target="cross"/>
+ <alias name="crosshair" target="cross"/>
+ <alias name="draft_large" target="right_ptr"/>
+ <alias name="draft_small" target="right_ptr"/>
+ <alias name="plus" target="cross"/>
+ <alias name="tcross" target="cross"/>
+ <alias name="top_left_arrow" target="top_left_arrow"/>
+ -->
+
+<!--
+ Aliases can also be used to provide cursors to be used in place
+ of particular legacy cursor shapes; whenever libXcursor is
+ asked to create a bitmap cursor, it creates a hash value
+ from the cursor shape, and tries using that as a cursor
+ name. Setting the environment variable XCURSOR_DISCOVER will
+ log this process, which is useful for finding out the hash values.
+
+ The following maps the mozilla pointer-while-waiting cursor to
+ left_ptr_watch.
+-->
+
+ <!-- moz_spinning (left_ptr with watch) -->
+ <alias name="08e8e1c95fe2fc01f976f1e063a24ccd" target="left_ptr_watch"/>
+
+ <!-- moz_question_arrow (left_ptr with question) -->
+ <alias name="5c6cd98b3f3ebcb1f9c7f1c204630408" target="question_arrow"/>
+
+<!--
+ More mozilla hash values that could be aliased:
+
+ moz_alias 0876e1c15ff2fc01f906f1c363074c0f (left_ptr with small arrow)
+ moz_copy 08ffe1cb5fe6fc01f906f1c063814ccf (left_ptr with plus)
+ moz_hand_grabbing 208530c400c041818281048008011002 (closed hand)
+ moz_hand_grab 5aca4d189052212118709018842178c0 (open hand)
+ moz_menu 08ffe1e65f80fcfdf9fff11263e74c48 (left_ptr with menu) */
+ moz_question_arrow 5c6cd98b3f3ebcb1f9c7f1c204630408 (left_ptr with ?)
+
+ GTK+ toolkit cursors:
+-->
+
+ <alias name="1081e37283d90000800003c07f3ef6bf" target="dnd_copy"/>
+ <alias name="9081237383d90e509aa00f00170e968f" target="dnd_move"/>
+ <alias name="3085a0e285430894940527032f8b26df" target="dnd_link"/>
+ <alias name="1001208387f90000800003000700f6ff" target="dnd_none"/>
+
+ <alias name="90b3018312820b127e5a0b7c8034a301" target="color-picker"/>
+
+ <alias name="watch" target="left_ptr_watch"/>
+</theme>
diff --git a/art/cursor/Bluecurve/ChangeLog b/art/cursor/Bluecurve/ChangeLog
new file mode 100644
index 0000000..ac10780
--- /dev/null
+++ b/art/cursor/Bluecurve/ChangeLog
@@ -0,0 +1,9 @@
+2003-01-17 Havoc Pennington <hp@redhat.com>
+
+ * Makefile.am (EXTRA_DIST): fix distcheck
+
+Thu Jan 16 14:56:26 2003 Owen Taylor <otaylor@redhat.com>
+
+ * Bluecurve.cursortheme: Conform to new syntax,
+ add aliases.
+
diff --git a/art/cursor/Bluecurve/Makefile.am b/art/cursor/Bluecurve/Makefile.am
new file mode 100644
index 0000000..4fad5e8
--- /dev/null
+++ b/art/cursor/Bluecurve/Makefile.am
@@ -0,0 +1,44 @@
+THEMEGEN = $(top_builddir)/art/cursor/cursorthemegen/cursorthemegen
+
+all-local: Bluecurve.stamp
+
+bluecurve_images = \
+ Bluecurve-24-hotspot.png \
+ Bluecurve-24-1.png \
+ Bluecurve-24-2.png \
+ Bluecurve-24-3.png \
+ Bluecurve-24-4.png \
+ Bluecurve-24-5.png \
+ Bluecurve-24-6.png \
+ Bluecurve-24-7.png \
+ Bluecurve-24-8.png \
+ Bluecurve-24-9.png \
+ Bluecurve-24-10.png \
+ Bluecurve-24-11.png \
+ Bluecurve-24-12.png \
+ Bluecurve-36-hotspot.png \
+ Bluecurve-36-1.png \
+ Bluecurve-48-hotspot.png \
+ Bluecurve-48-1.png
+
+Bluecurve.stamp: $(bluecurve_images) $(THEMEGEN) Bluecurve.cursortheme
+ rm -rf Bluecurve && \
+ BDIR=`pwd` && cd $(srcdir) && \
+ $$BDIR/$(THEMEGEN) Bluecurve.cursortheme $$BDIR/Bluecurve && \
+ cd $$BDIR && touch Bluecurve.stamp
+
+clean:
+ rm -rf Bluecurve
+
+install-data-local:
+ rm -rf $(datadir)/icons/Bluecurve/cursors
+ mkdir -p $(datadir)/icons/Bluecurve/cursors
+ for i in `cd Bluecurve && echo *` ; do \
+ if test -L Bluecurve/$$i ; then \
+ cp -d Bluecurve/$$i $(datadir)/icons/Bluecurve/cursors/$$i ; \
+ else \
+ install -m 0644 Bluecurve/$$i $(datadir)/icons/Bluecurve/cursors/$$i ; \
+ fi ; \
+ done
+
+EXTRA_DIST=$(bluecurve_images) Bluecurve.cursortheme
diff --git a/art/cursor/Makefile.am b/art/cursor/Makefile.am
new file mode 100644
index 0000000..f35a497
--- /dev/null
+++ b/art/cursor/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = cursorthemegen Bluecurve
diff --git a/art/cursor/cursorthemegen/ChangeLog b/art/cursor/cursorthemegen/ChangeLog
new file mode 100644
index 0000000..40bcc7e
--- /dev/null
+++ b/art/cursor/cursorthemegen/ChangeLog
@@ -0,0 +1,48 @@
+2003-08-06 Alexander Larsson <alexl@redhat.com>
+
+ * main.c (cursor_get_image):
+ Define variables at top of function.
+
+2003-02-22 Matt Wilson <msw@redhat.com>
+
+ * main.c (cursor_source_find_image): use tmp_list =
+ tmp_list->next;, not tmp_list = tmp_list++;
+ (cursor_add_source): convert missing frames into warnings
+ (cursor_theme_write_cursor): skip frames of size -1 (they're
+ missing cursor files)
+
+Tue Feb 4 14:52:27 2003 Owen Taylor <otaylor@redhat.com>
+
+ * main.c (cursor_theme_check_alias): Add a warning if
+ the alias is defined but missing in the image. (#83252)
+
+2003-01-17 Havoc Pennington <hp@redhat.com>
+
+ * Makefile.am (cursorthemegen_SOURCES): fix distcheck
+
+Thu Jan 16 15:25:47 2003 Owen Taylor <otaylor@redhat.com>
+
+ * README: Add, add some docs.
+
+ * main.c themefile.c cursortheme.h: Put under MIT-style
+ license.
+
+ * Makefile.am generic.cursortheme sample.cursortheme:
+ Rename generic.cursortheme => sample.cursortheme
+
+Wed Jan 15 23:48:39 2003 Owen Taylor <otaylor@redhat.com>
+
+ * main.c themefile.c: Use a hash table instead of a
+ list of cursors.
+
+ * themefile.c generic.cursortheme: Remove <sources> element,
+ put <source> elements directly under <theme> node.
+
+ * themefile.c generic.cursortheme: Rename <rows> element to
+ <layout>.
+
+Wed Jan 15 18:25:24 2003 Owen Taylor <otaylor@redhat.com>
+
+ * Import sources into CVS, start ChangeLog
+
+
diff --git a/art/cursor/cursorthemegen/Makefile.am b/art/cursor/cursorthemegen/Makefile.am
new file mode 100644
index 0000000..3ef188d
--- /dev/null
+++ b/art/cursor/cursorthemegen/Makefile.am
@@ -0,0 +1,11 @@
+INCLUDES = $(GDK_PIXBUF2_CFLAGS)
+
+noinst_PROGRAMS = cursorthemegen
+
+cursorthemegen_LDADD = $(GDK_PIXBUF2_LIBS)
+cursorthemegen_SOURCES = \
+ cursortheme.h \
+ themefile.c \
+ main.c
+
+EXTRA_DIST = sample.cursortheme
diff --git a/art/cursor/cursorthemegen/README b/art/cursor/cursorthemegen/README
new file mode 100644
index 0000000..e43a7c1
--- /dev/null
+++ b/art/cursor/cursorthemegen/README
@@ -0,0 +1,186 @@
+Introduction
+============
+
+cursorthemegen is a utility for generating libXcursor
+cursor themes.
+
+The inputs to cursorthemegen are conceptually:
+
+ A) A set of multi-layer images, one for each
+ size.
+ B) A XML theme description file
+
+Each image contains all the cursors arranged in
+a grid; the layers are:
+
+ - A layer with a dot for the hotspot of each cursor
+ - The main image or first animation frame for multi-frame
+ animated cursors
+ - The second animation frame for multi-frame animated cursors
+ - ...
+
+In practice, since loading of multilayer images is not
+supported by standard image libraries, each layer is
+input as a separate image file.
+
+The cursor theme file contains information about the
+source images to read, the location of each named
+cursor within the grid, and a set of aliases from
+names to other names.
+
+
+Invocation
+==========
+
+cursorthemegen takes two arguments:
+
+ cursorthemegen THEMEFILE OUTPUTDIR
+
+cursorthemegen reads in THEMEFILE, compiles a cursor
+theme from it, creates the OUTPUTDIR directory and
+writes the result in it. The OUTPUTDIR directory must
+not already exist.
+
+
+Theme file format
+=================
+
+The tags in the Theme file format are:
+
+<theme>: The toplevel element. There must be
+ exactly one of these.
+
+ Attributes:
+ name: The name of the theme. Required.
+
+ Child elements:
+ <alias>, <layout>, <source>
+
+<alias>: The alias element defines an alias of
+ one cursor name to another cursor.
+
+ Attributes:
+ name: The name of the alias. Required.
+ target: The name cursor (or alias) to which the
+ alias points. Required.
+
+ Child elements:
+ None
+
+<source>: Defines a multilayer source
+
+ Attributes:
+ size: The nominal size of the cursors in the
+ this source. This is used when selecting a
+ cursor. Required.
+
+ gridsize: The size of the grid used for this
+ source. Defaults to the same as 'size'.
+ Optional.
+
+ Child elements:
+ <image>
+
+<image>: One layer in a multilayer source
+
+ Attributes:
+ file: The filename to get the image from. Required.
+ use: Either an integer indicating what animation
+ frame this is (0, 1, ...) or "hotspot" to
+ indicate that this frame contains hotspots. Required.
+
+ Child elements:
+ None
+
+<layout>: Defines the layout of cursors within the grid.
+
+ Attributes:
+ None
+
+ Child elements:
+ <row>
+
+<row>: Defines one row of cursors within the grid
+
+ Attributes:
+ None
+
+ Child elements:
+ <cursor>
+
+<cursor>: Defines a single cursor. If there are no
+ child <frame> elements, it is assumed to be a non-animated
+ cursor with a single frame in it. Otherwise, one
+ or more frames is specified with child <frame> elements.
+
+ Attributes:
+ name: The name of the cursor. Required.
+
+ Child elements:
+ <frame>
+
+<frame>: Defines one frame of a multiframe cursor.
+
+ Attributes:
+ delay: The delay before the next frame is shown in
+ milliseconds. Optional. (If you don't specify the delays
+ for a multiframe animation, the result is undefined.)
+
+ Child elements:
+ None
+
+Note that cursorthemegen doesn't actually use a full
+XML parser, but the XML-subset GMarkup parser from
+GLib, so some less common XML constructs may not work.
+
+
+Makefile example
+================
+
+Makefile rules for generating and installing a theme
+look like:
+
+bluecurve_images = \
+ Bluecurve-1-24.png \
+ Bluecurve-2-24.png \
+ Bluecurve-hotspot-24.png
+
+Bluecurve.stamp: $(bluecurve_images) Bluecurve.cursortheme
+ rm -rf Bluecurve && \
+ $(THEMEGEN) Bluecurve.cursortheme Bluecurve && \
+ touch Bluecurve.stamp
+
+install:
+ rm -rf $(datadir)/icons/Bluecurve/cursors
+ mkdir -p $(datadir)/icons/Bluecurve/cursors
+ for i in `cd Bluecurve && echo *` ; do \
+ if test -L Bluecurve/$$i ; then \
+ cp -d Bluecurve/$$i $(datadir)/icons/Bluecurve/cursors/$$i ; \
+ else \
+ install -m 0644 Bluecurve/$$i $(datadir)/icons/Bluecurve/cursors/$$i ; \
+ fi ; \
+ done
+
+
+License
+=======
+
+Copyright © 2003 Red Hat, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Red Hat not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. Red Hat makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+
+RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
diff --git a/art/cursor/cursorthemegen/cursortheme.h b/art/cursor/cursorthemegen/cursortheme.h
new file mode 100644
index 0000000..78f14fc
--- /dev/null
+++ b/art/cursor/cursorthemegen/cursortheme.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2003 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#ifndef __CURSORTHEME_H__
+#define __CURSORTHEME_H__
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+G_BEGIN_DECLS
+
+typedef struct _Cursor Cursor;
+typedef struct _CursorAlias CursorAlias;
+typedef struct _CursorFrame CursorFrame;
+typedef struct _CursorFrameConfig CursorFrameConfig;
+typedef struct _CursorImage CursorImage;
+typedef struct _CursorSource CursorSource;
+typedef struct _CursorTheme CursorTheme;
+
+struct _Cursor
+{
+ char *name;
+ int row;
+ int column;
+ GSList *frame_configs;
+ GSList *frames;
+};
+
+struct _CursorAlias
+{
+ char *name;
+ char *target;
+};
+
+struct _CursorFrameConfig
+{
+ int delay;
+};
+
+struct _CursorFrame
+{
+ int size;
+ int hot_x;
+ int hot_y;
+ int delay;
+ GdkPixbuf *image;
+};
+
+struct _CursorImage
+{
+ int use; /* Frame number or -1 for hotspot */
+ GdkPixbuf *image;
+};
+
+struct _CursorSource
+{
+ int size;
+ int gridsize;
+ GSList *images;
+};
+
+struct _CursorTheme
+{
+ char *name;
+ GSList *sources;
+ GHashTable *cursors;
+ GHashTable *aliases;
+};
+
+CursorTheme *cursor_theme_read (const char *filename);
+
+G_END_DECLS
+
+#endif /* __CURSORTHEME_H__ */
diff --git a/art/cursor/cursorthemegen/main.c b/art/cursor/cursorthemegen/main.c
new file mode 100644
index 0000000..5925230
--- /dev/null
+++ b/art/cursor/cursorthemegen/main.c
@@ -0,0 +1,615 @@
+/*
+ * Copyright © 2003 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "cursortheme.h"
+
+static CursorImage *
+cursor_source_find_image (CursorSource *source,
+ int use)
+{
+ GSList *tmp_list;
+
+ for (tmp_list = source->images; tmp_list; tmp_list = tmp_list->next)
+ {
+ CursorImage *image = tmp_list->data;
+
+ if (image->use == use)
+ return image;
+ }
+
+ return NULL;
+}
+
+static gboolean
+cursor_find_hotspot (Cursor *cursor,
+ CursorSource *source,
+ int *hot_x,
+ int *hot_y)
+{
+ CursorImage *image;
+ int x = cursor->column * source->gridsize;
+ int y = cursor->row * source->gridsize;
+
+ *hot_x = -1;
+ *hot_y = -1;
+
+ image = cursor_source_find_image (source, -1);
+ if (!image)
+ {
+ g_printerr ("Source at size %d doesn't have a hotspot image\n",
+ source->size);
+ return FALSE;
+ }
+
+ if (!gdk_pixbuf_get_has_alpha (image->image) ||
+ gdk_pixbuf_get_colorspace (image->image) != GDK_COLORSPACE_RGB)
+ {
+ g_printerr ("Invalid format for hotspot file\n");
+ return FALSE;
+ }
+
+ if (x + source->gridsize <= gdk_pixbuf_get_width (image->image) &&
+ y + source->gridsize <= gdk_pixbuf_get_height (image->image))
+ {
+ int rowstride;
+ guchar *pixels;
+ int i, j;
+
+ rowstride = gdk_pixbuf_get_rowstride (image->image);
+ pixels = gdk_pixbuf_get_pixels (image->image) + y * rowstride + x * 4;
+ for (j = 0; j < source->gridsize; j++)
+ {
+ for (i = 0; i < source->gridsize; i++)
+ {
+ if (pixels[4*i + 3] > 0x80)
+ {
+ if (*hot_x >=0 || *hot_y >= 0)
+ {
+ g_printerr ("Multiple hotspots for cursor %s at size %d\n",
+ cursor->name, source->size);
+ return FALSE;
+ }
+ *hot_x = i;
+ *hot_y = j;
+ }
+ }
+ pixels += rowstride;
+ }
+ }
+
+ if (*hot_x == -1 || *hot_y == -1)
+ {
+ g_printerr ("Cannot find hotspot for cursor %s at size %d\n",
+ cursor->name, source->size);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+cursor_is_present (Cursor *cursor,
+ CursorSource *source,
+ int frame)
+{
+ CursorImage *image = cursor_source_find_image (source, frame);
+ int x = cursor->column * source->gridsize;
+ int y = cursor->row * source->gridsize;
+ int i, j;
+
+ const guchar *pixels;
+ int rowstride;
+ int n_channels;
+
+ if (!image)
+ return FALSE;
+
+ if (gdk_pixbuf_get_colorspace (image->image) != GDK_COLORSPACE_RGB)
+ {
+ g_printerr ("Invalid format for image file\n");
+ return FALSE;
+ }
+
+ if (x + source->gridsize > gdk_pixbuf_get_width (image->image) ||
+ y + source->gridsize > gdk_pixbuf_get_height (image->image))
+ return FALSE;
+
+ rowstride = gdk_pixbuf_get_rowstride (image->image);
+ n_channels = gdk_pixbuf_get_n_channels (image->image);
+
+ if (n_channels == 3)
+ return TRUE;
+
+ pixels = gdk_pixbuf_get_pixels (image->image) + y * rowstride + x * 4;
+
+ for (j = 0; j < source->gridsize; j++)
+ {
+ for (i = 0; i < source->gridsize; i++)
+ {
+ if (pixels[4*i + 3] != 0)
+ return TRUE;
+ }
+ pixels += rowstride;
+ }
+
+ return FALSE;
+}
+
+static void
+cursor_frame_find_bounds (Cursor *cursor,
+ CursorFrame *frame,
+ CursorSource *source,
+ int frame_index,
+ int *x,
+ int *y,
+ int *width,
+ int *height)
+{
+ CursorImage *image = cursor_source_find_image (source, frame_index);
+ int start_x = cursor->column * source->gridsize;
+ int start_y = cursor->row * source->gridsize;
+ int i, j;
+
+ const guchar *pixels;
+ int rowstride;
+ int n_channels;
+
+ rowstride = gdk_pixbuf_get_rowstride (image->image);
+ n_channels = gdk_pixbuf_get_n_channels (image->image);
+
+ if (n_channels == 3)
+ {
+ *x = start_x;
+ *y = start_x;
+ *width = source->gridsize;
+ *height = source->gridsize;
+
+ return;
+ }
+ else
+ {
+ int min_x = start_x + frame->hot_x;
+ int max_x = start_x + frame->hot_x + 1;
+ int min_y = start_y + frame->hot_y;
+ int max_y = start_y + frame->hot_y + 1;
+
+ pixels = gdk_pixbuf_get_pixels (image->image) + start_y * rowstride + start_x * 4;
+
+ for (j = 0; j < source->gridsize; j++)
+ {
+ for (i = 0; i < source->gridsize; i++)
+ {
+ if (pixels[4*i + 3] != 0)
+ {
+ if (start_x + i < min_x)
+ min_x = start_x + i;
+ if (start_x + i >= max_x)
+ max_x = start_x + i + 1;
+ if (start_y + j < min_y)
+ min_y = start_y + j;
+ if (start_y + j >= max_y)
+ max_y = start_y + j + 1;
+ }
+ }
+
+ pixels += rowstride;
+ }
+
+ *x = min_x;
+ *y = min_y;
+ *width = max_x - min_x;
+ *height = max_y - min_y;
+ }
+}
+
+static void
+cursor_get_image (Cursor *cursor,
+ CursorFrame *frame,
+ CursorSource *source,
+ int frame_index,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ CursorImage *image = cursor_source_find_image (source, frame_index);
+ GdkPixbuf *tmp_pixbuf;
+
+ /*cursor_frame_find_bounds (cursor, frame, source, frame_index,
+ &x, &y, &width, &height);
+*/
+ tmp_pixbuf = gdk_pixbuf_new_subpixbuf (image->image,
+ x, y, width, height);
+
+ frame->hot_x -= x - cursor->column * source->gridsize;
+ frame->hot_y -= y - cursor->row * source->gridsize;
+
+ frame->image = gdk_pixbuf_copy (tmp_pixbuf);
+ g_object_unref (tmp_pixbuf);
+}
+
+static gboolean
+cursor_add_source (Cursor *cursor,
+ CursorSource *source)
+{
+ GSList *tmp_list;
+ int hot_x, hot_y;
+ int i;
+ int x, y, x2, y2, height, width;
+
+ /* If the first frame is missing we silently treat
+ * it as OK
+ */
+ if (!cursor_is_present (cursor, source, 0))
+ return TRUE;
+
+ if (!cursor_find_hotspot (cursor, source, &hot_x, &hot_y))
+ return FALSE;
+
+ /* generate a single hight width for all cursors in a
+ given animation*/
+
+ for (tmp_list = cursor->frame_configs, i = 0;
+ tmp_list;
+ tmp_list = tmp_list->next, i++)
+ {
+ CursorFrameConfig *frame_config = tmp_list->data;
+ CursorFrame *frame;
+ int tx, ty, tx2, ty2, twidth, theight;
+
+ if (i != 0 && !cursor_is_present (cursor, source, i))
+ continue;
+
+ frame = g_new0 (CursorFrame, 1);
+ frame->size = source->size;
+ frame->hot_x = hot_x;
+ frame->hot_y = hot_y;
+ frame->delay = frame_config->delay;
+
+ cursor_frame_find_bounds (cursor, frame, source, i,
+ &tx, &ty, &twidth, &theight);
+
+ tx2 = tx + twidth;
+ ty2 = ty + theight;
+
+ if (i == 0)
+ {
+ x = tx;
+ y = ty;
+ x2 = tx2;
+ y2 = ty2;
+ }
+ else
+ {
+ if (tx < x)
+ x = tx;
+
+ if (ty < y)
+ y = ty;
+
+ if (tx2 > x2)
+ x2 = tx2;
+
+ if (ty2 > y2)
+ y2 = ty2;
+ }
+
+ g_free (frame);
+ }
+
+ width = x2 - x;
+ height = y2 - y;
+
+ for (tmp_list = cursor->frame_configs, i = 0;
+ tmp_list;
+ tmp_list = tmp_list->next, i++)
+ {
+ CursorFrameConfig *frame_config = tmp_list->data;
+ CursorFrame *frame;
+
+ if (i != 0 && !cursor_is_present (cursor, source, i))
+ {
+ g_printerr ("Frame %d missing for cursor '%s' at size %d\n",
+ i, cursor->name, source->size);
+ frame = g_new0 (CursorFrame, 1);
+ frame->size = -1;
+ cursor->frames = g_slist_append (cursor->frames, frame);
+ continue;
+ }
+
+ frame = g_new0 (CursorFrame, 1);
+ frame->size = source->size;
+ frame->hot_x = hot_x;
+ frame->hot_y = hot_y;
+ frame->delay = frame_config->delay;
+
+ cursor_get_image (cursor, frame, source, i, x, y, width, height);
+
+ cursor->frames = g_slist_append (cursor->frames, frame);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+cursor_theme_read_cursor (CursorTheme *theme,
+ Cursor *cursor)
+{
+ GSList *tmp_list;
+
+ for (tmp_list = theme->sources; tmp_list; tmp_list = tmp_list->next)
+ {
+ if (!cursor_add_source (cursor, tmp_list->data))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+cursor_theme_write_cursor (CursorTheme *theme,
+ Cursor *cursor)
+{
+ GSList *tmp_list;
+ char *config_filename;
+ char *command;
+ FILE *config_file;
+ GError *error = NULL;
+ int status;
+ int i;
+
+ if (g_hash_table_lookup (theme->aliases, cursor->name))
+ {
+ g_printerr ("Warning: cursor '%s' overridden by alias\n", cursor->name);
+ return;
+ }
+
+ if (!cursor->frames)
+ return;
+
+ config_filename = g_strconcat (cursor->name, ".cfg", NULL);
+ config_file = fopen (config_filename, "w");
+
+ if (!config_file)
+ {
+ g_printerr ("Cannot open config file '%s'\n", config_filename);
+ return;
+ }
+
+ for (tmp_list = cursor->frames, i = 0; tmp_list; tmp_list = tmp_list->next, i++)
+ {
+ CursorFrame *frame = tmp_list->data;
+ char *filename;
+
+ if (frame->size == -1)
+ continue;
+ filename = g_strdup_printf ("%s-%d.png", cursor->name, i);
+ if (gdk_pixbuf_save (frame->image, filename, "png", &error, NULL))
+ {
+ if (frame->delay > 0)
+ fprintf (config_file, "%d %d %d %s %d\n",
+ frame->size, frame->hot_x, frame->hot_y, filename, frame->delay);
+ else
+ fprintf (config_file, "%d %d %d %s\n",
+ frame->size, frame->hot_x, frame->hot_y, filename);
+ }
+ else
+ {
+ g_printerr ("Error saving image file: %s\n", error->message);
+ g_error_free (error);
+ }
+ g_free (filename);
+ }
+
+ fclose (config_file);
+
+ command = g_strdup_printf ("sh -c 'xcursorgen %s > %s'\n",
+ config_filename, cursor->name);
+ if (!g_spawn_command_line_sync (command, NULL, NULL, &status, &error))
+ {
+ g_printerr ("Error running xcursorgen for %s: %s\n",
+ cursor->name, error->message);
+ g_error_free (error);
+ }
+ else if (status)
+ {
+ g_printerr ("Error running xcursorgen for %s\n",
+ cursor->name);
+ }
+ else
+ {
+ /* Only delete temporary files if no error occurred
+ */
+ unlink (config_filename);
+ g_free (config_filename);
+
+ for (tmp_list = cursor->frames, i = 0; tmp_list; tmp_list = tmp_list->next, i++)
+ {
+ char *filename;
+
+ filename = g_strdup_printf ("%s-%d.png", cursor->name, i);
+ unlink (filename);
+ g_free (filename);
+ }
+ }
+}
+
+static const char *
+cursor_theme_check_alias (CursorTheme *theme,
+ CursorAlias *alias)
+{
+ /* Dereference, using tortoise-and-hare checkign for circular aliases
+ */
+ CursorAlias *tortoise = alias;
+ CursorAlias *hare = alias;
+ Cursor *target;
+
+ while (TRUE)
+ {
+ CursorAlias *next;
+
+ next = g_hash_table_lookup (theme->aliases, hare->target);
+ if (!next)
+ break;
+ hare = next;
+
+ if (hare == tortoise)
+ goto found_loop;
+
+ next = g_hash_table_lookup (theme->aliases, hare->target);
+ if (!next)
+ break;
+ hare = next;
+
+ if (hare == tortoise)
+ goto found_loop;
+
+ tortoise = g_hash_table_lookup (theme->aliases, tortoise->target);
+ }
+
+ target = g_hash_table_lookup (theme->cursors, hare->target);
+
+ if (!target || !target->frames)
+ {
+ g_printerr ("Cursor '%s', which is the target of alias '%s', is not in theme\n",
+ hare->target, alias->name);
+ return NULL;
+ }
+
+ return hare->target;
+
+ found_loop:
+ g_printerr ("Circular looop detected when dereferencing alias '%s'\n",
+ alias->name);
+ return NULL;
+}
+
+static void
+cursor_theme_write_alias (CursorTheme *theme,
+ CursorAlias *alias)
+{
+ const char *target = cursor_theme_check_alias (theme, alias);
+ if (!target)
+ return;
+
+ if (symlink (target, alias->name) < 0)
+ {
+ g_printerr ("Error creating symlink for alias '%s' to '%s': %s\n",
+ alias->name, target, g_strerror (errno));
+ }
+}
+
+static void
+write_cursor_foreach (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ cursor_theme_write_cursor (data, value);
+}
+
+static void
+write_alias_foreach (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ cursor_theme_write_alias (data, value);
+}
+
+static gboolean
+cursor_theme_write (CursorTheme *theme,
+ const char *output_dir)
+{
+ char *curdir;
+
+ if (mkdir (output_dir, 0755) < 0)
+ {
+ g_printerr ("Error creating output directory '%s'\n: %s",
+ output_dir, g_strerror (errno));
+ return FALSE;
+ }
+
+ curdir = g_get_current_dir ();
+ if (chdir (output_dir) < 0)
+ {
+ g_printerr ("Could not change to output directory '%s'\n", output_dir);
+ return FALSE;
+ }
+
+ g_hash_table_foreach (theme->cursors,
+ write_cursor_foreach,
+ theme);
+
+ g_hash_table_foreach (theme->aliases,
+ write_alias_foreach,
+ theme);
+
+ chdir (curdir);
+
+ return TRUE;
+}
+
+void
+usage (void)
+{
+ g_printerr ("Usage: cursorthemegen CONFIG_FILE OUTPUT_DIR\n");
+ exit (1);
+}
+
+static void
+read_cursor_foreach (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ if (!cursor_theme_read_cursor (data, value))
+ exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+ CursorTheme *theme;
+
+ g_type_init ();
+
+ if (argc != 3)
+ usage ();
+
+ theme = cursor_theme_read (argv[1]);
+ if (!theme)
+ exit (1);
+
+ g_hash_table_foreach (theme->cursors,
+ read_cursor_foreach,
+ theme);
+
+ if (!cursor_theme_write (theme, argv[2]))
+ exit (1);
+
+ return 0;
+}
diff --git a/art/cursor/cursorthemegen/sample.cursortheme b/art/cursor/cursorthemegen/sample.cursortheme
new file mode 100644
index 0000000..e288b42
--- /dev/null
+++ b/art/cursor/cursorthemegen/sample.cursortheme
@@ -0,0 +1,148 @@
+<theme name="Bluecurve">
+ <source size="48">
+ <image file="Bluecurve-1-48.png" use="0"/>
+ <image file="Bluecurve-2-48.png" use="1"/ >
+ <image file="Bluecurve-hotspot-48.png" use="hotspot"/>
+ </source>
+ <layout>
+ <row>
+ <cursor name="X_cursor"/>
+ <cursor name="arrow"/>
+ <cursor name="based_arrow_down"/>
+ <cursor name="based_arrow_up"/>
+ <cursor name="boat"/>
+ <cursor name="bogosity"/>
+ <cursor name="bottom_left_corner"/>
+ <cursor name="bottom_right_corner"/>
+ </row><row>
+ <cursor name="bottom_side"/>
+ <cursor name="bottom_tee"/>
+ <cursor name="box_spiral"/>
+ <cursor name="center_ptr"/>
+ <cursor name="circle"/>
+ <cursor name="clock"/>
+ <cursor name="coffee_mug"/>
+ <cursor name="cross"/>
+ </row><row>
+ <cursor name="cross_reverse"/>
+ <cursor name="crosshair"/>
+ <cursor name="diamond_cross"/>
+ <cursor name="dot"/>
+ <cursor name="dotbox"/>
+ <cursor name="double_arrow"/>
+ <cursor name="draft_large"/>
+ <cursor name="draft_small"/>
+ </row><row>
+ <cursor name="draped_box"/>
+ <cursor name="exchange"/>
+ <cursor name="fleur"/>
+ <cursor name="gobbler"/>
+ <cursor name="gumby"/>
+ <cursor name="hand1"/>
+ <cursor name="hand2"/>
+ <cursor name="heart"/>
+ </row><row>
+ <cursor name="icon"/>
+ <cursor name="iron_cross"/>
+ <cursor name="left_ptr"/>
+ <cursor name="left_side"/>
+ <cursor name="left_tee"/>
+ <cursor name="leftbutton"/>
+ <cursor name="ll_angle"/>
+ <cursor name="lr_angle"/>
+ </row><row>
+ <cursor name="man"/>
+ <cursor name="middlebutton"/>
+ <cursor name="mouse"/>
+ <cursor name="pencil"/>
+ <cursor name="pirate"/>
+ <cursor name="plus"/>
+ <cursor name="question_arrow"/>
+ <cursor name="right_ptr"/>
+ </row><row>
+ <cursor name="right_side"/>
+ <cursor name="right_tee"/>
+ <cursor name="rightbutton"/>
+ <cursor name="rtl_logo"/>
+ <cursor name="sailboat"/>
+ <cursor name="sb_down_arrow"/>
+ <cursor name="sb_h_double_arrow"/>
+ <cursor name="sb_left_arrow"/>
+ </row><row>
+ <cursor name="sb_right_arrow"/>
+ <cursor name="sb_up_arrow"/>
+ <cursor name="sb_v_double_arrow"/>
+ <cursor name="shuttle"/>
+ <cursor name="sizing"/>
+ <cursor name="spider"/>
+ <cursor name="spraycan"/>
+ <cursor name="star"/>
+ </row><row>
+ <cursor name="target"/>
+ <cursor name="tcross"/>
+ <cursor name="top_left_arrow"/>
+ <cursor name="top_left_corner"/>
+ <cursor name="top_right_corner"/>
+ <cursor name="top_side"/>
+ <cursor name="top_tee"/>
+ <cursor name="trek"/>
+ </row><row>
+ <cursor name="ul_angle"/>
+ <cursor name="umbella"/>
+ <cursor name="ur_angle"/>
+ <cursor name="watch"/>
+ <cursor name="xterm"/>
+ <cursor name="left_ptr_watch">
+ <frame delay="500"/>
+ <frame delay="500"/>
+ </cursor>
+ </row>
+ </layout>
+<!--
+ The number of cursors in the WhiteGlass theme distributed with XFree86
+ are reduced using the following aliases:
+
+ <alias name="arrow" target="right_ptr"/>
+ <alias name="cross_reverse" target="cross"/>
+ <alias name="crosshair" target="cross"/>
+ <alias name="draft_large" target="right_ptr"/>
+ <alias name="draft_small" target="right_ptr"/>
+ <alias name="plus" target="cross"/>
+ <alias name="tcross" target="cross"/>
+ <alias name="top_left_arrow" target="top_left_arrow"/>
+ -->
+
+<!--
+ Aliases can also be used to provide cursors to be used in place
+ of particular legacy cursor shapes; whenever libXcursor is
+ asked to create a bitmap cursor, it creates a hash value
+ from the cursor shape, and tries using that as a cursor
+ name. Setting the environment variable XCURSOR_DISCOVER will
+ log this process, which is useful for finding out the hash values.
+
+ The following maps the mozilla pointer-while-waiting cursor to
+ left_ptr_watch.
+-->
+ <!-- moz_spinning (left_ptr with watch) -->
+ <alias name="08e8e1c95fe2fc01f976f1e063a24ccd" target="left_ptr_watch"/>
+
+<!--
+ More mozilla hash values that could be aliased:
+
+ moz_alias 0876e1c15ff2fc01f906f1c363074c0f (left_ptr with small arrow)
+ moz_copy 08ffe1cb5fe6fc01f906f1c063814ccf (left_ptr with plus)
+ moz_hand_grabbing 208530c400c041818281048008011002 (closed hand)
+ moz_hand_grab 5aca4d189052212118709018842178c0 (open hand)
+ moz_menu 08ffe1e65f80fcfdf9fff11263e74c48 (left_ptr with menu) */
+ moz_question_arrow 5c6cd98b3f3ebcb1f9c7f1c204630408 (left_ptr with ?)
+
+ GTK+ toolkit cursors:
+
+ DND copy 1081e37283d90000800003c07f3ef6bf
+ DND move 9081237383d90e509aa00f00170e968f
+ DND link 3085a0e285430894940527032f8b26df
+ DND no drop 1001208387f90000800003000700f6ff
+
+ Eye dropper 90b3018312820b127e5a0b7c8034a301
+-->
+</theme>
diff --git a/art/cursor/cursorthemegen/themefile.c b/art/cursor/cursorthemegen/themefile.c
new file mode 100644
index 0000000..a8a703f
--- /dev/null
+++ b/art/cursor/cursorthemegen/themefile.c
@@ -0,0 +1,609 @@
+/*
+ * Copyright © 2003 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cursortheme.h"
+
+typedef struct _ParseData ParseData;
+
+typedef enum {
+ OUTSIDE,
+ IN_THEME,
+ IN_SOURCE,
+ IN_IMAGE,
+ IN_ALIAS,
+ IN_LAYOUT,
+ IN_ROW,
+ IN_CURSOR,
+ IN_FRAME
+} ParseState;
+
+struct _ParseData {
+ CursorTheme *theme;
+ ParseState state;
+ gboolean seen_theme;
+ gboolean seen_layout;
+ int row;
+ int column;
+ Cursor *current_cursor;
+};
+
+static gboolean
+expect_tag (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar *expected_name, /* Null for expected empty */
+ GError **error)
+{
+ if (!expected_name || strcmp (element_name, expected_name) != 0)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Unexpected tag '%s'",
+ element_name);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+extract_attrs (GMarkupParseContext *context,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ GError **error,
+ ...)
+{
+ va_list vap;
+ const char *name;
+ gboolean *attr_map;
+ gboolean nattrs = 0;
+ int i;
+
+ for (i = 0; attribute_names[i]; i++)
+ nattrs++;
+
+ attr_map = g_new0 (gboolean, nattrs);
+
+ va_start (vap, error);
+ name = va_arg (vap, const char *);
+ while (name)
+ {
+ gboolean mandatory = va_arg (vap, gboolean);
+ const char **loc = va_arg (vap, const char **);
+ gboolean found = FALSE;
+
+ for (i = 0; attribute_names[i]; i++)
+ {
+ if (!attr_map[i] && strcmp (attribute_names[i], name) == 0)
+ {
+ if (found)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Duplicate attribute '%s'", name);
+ return FALSE;
+ }
+
+ *loc = attribute_values[i];
+ found = TRUE;
+ attr_map[i] = TRUE;
+ }
+ }
+
+ if (!found && mandatory)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Missing attribute '%s'", name);
+ return FALSE;
+ }
+
+ name = va_arg (vap, const char *);
+ }
+
+ for (i = 0; i < nattrs; i++)
+ if (!attr_map[i])
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+ "Unknown attribute '%s'", attribute_names[i]);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+get_int (const char *str,
+ int *result)
+{
+ long val;
+ char *p;
+
+ val = strtol (str, &p, 0);
+ if (*str == '\0' || *p != '\0' ||
+ val < G_MININT || val > G_MAXINT)
+ return FALSE;
+
+ *result = val;
+
+ return TRUE;
+}
+
+static void
+add_source (ParseData *parse_data,
+ int size,
+ int gridsize)
+{
+ CursorSource *source = g_new0 (CursorSource, 1);
+ source->size = size;
+ source->gridsize = gridsize;
+ parse_data->theme->sources = g_slist_prepend (parse_data->theme->sources, source);
+}
+
+static void
+add_alias (ParseData *parse_data,
+ const char *name,
+ const char *target)
+{
+ CursorAlias *alias = g_new0 (CursorAlias, 1);
+ alias->name = g_strdup (name);
+ alias->target = g_strdup (target);
+
+ g_hash_table_insert (parse_data->theme->aliases, alias->name, alias);
+}
+
+static gboolean
+add_image (ParseData *parse_data,
+ const char *file,
+ int use,
+ GError **error)
+{
+ GdkPixbuf *pixbuf;
+ CursorSource *source;
+ CursorImage *image;
+
+ pixbuf = gdk_pixbuf_new_from_file (file, error);
+ if (!pixbuf)
+ return FALSE;
+
+ source = parse_data->theme->sources->data;
+ image = g_new0 (CursorImage, 1);
+ image->image = pixbuf;
+ image->use = use;
+ source->images = g_slist_prepend (source->images, image);
+
+ return TRUE;
+}
+
+static void
+add_cursor (ParseData *parse_data,
+ const char *name)
+{
+ Cursor *cursor = g_new0 (Cursor, 1);
+ cursor->name = g_strdup (name);
+ cursor->row = parse_data->row;
+ cursor->column = parse_data->column;
+ parse_data->current_cursor = cursor;
+ g_hash_table_insert (parse_data->theme->cursors, cursor->name, cursor);
+}
+
+static void
+add_frame_config (ParseData *parse_data,
+ int delay)
+{
+ Cursor *cursor = parse_data->current_cursor;
+ CursorFrameConfig *frame_config = g_new0 (CursorFrameConfig, 1);
+ frame_config->delay = delay;
+ cursor->frame_configs = g_slist_prepend (cursor->frame_configs, frame_config);
+}
+
+/* Called for open tags <foo bar="baz"> */
+static void
+cursor_theme_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ ParseData *parse_data = user_data;
+
+ switch (parse_data->state)
+ {
+ case OUTSIDE:
+ {
+ const char *name;
+
+ if (!expect_tag (context, element_name, "theme", error))
+ return;
+ if (parse_data->seen_theme)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Multiple occurrences of <theme>");
+ return;
+ }
+ parse_data->seen_theme = TRUE;
+ parse_data->state = IN_THEME;
+
+ if (!extract_attrs (context, attribute_names, attribute_values, error,
+ "name", TRUE, &name,
+ NULL))
+ return;
+
+ parse_data->theme->name = g_strdup (name);
+ }
+ break;
+ case IN_THEME:
+ if (strcmp (element_name, "source") == 0)
+ {
+ const char *size_str;
+ const char *gridsize_str;
+ int size, gridsize;
+
+ parse_data->state = IN_SOURCE;
+
+ if (!extract_attrs (context, attribute_names, attribute_values, error,
+ "size", TRUE, &size_str,
+ "gridsize", FALSE, &gridsize_str,
+ NULL))
+ return;
+
+ if (!get_int (size_str, &size) || size < 0)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Invalid size %s", size_str);
+ return;
+ }
+
+ if (gridsize_str)
+ {
+ if (!get_int (gridsize_str, &gridsize) || size < 0)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Invalid size %s", size_str);
+ return;
+ }
+ }
+ else
+ gridsize = size;
+
+ add_source (parse_data, size, gridsize);
+ }
+ else if (strcmp (element_name, "alias") == 0)
+ {
+ const char *name;
+ const char *target;
+
+ parse_data->state = IN_ALIAS;
+
+ if (!extract_attrs (context, attribute_names, attribute_values, error,
+ "name", TRUE, &name,
+ "target", FALSE, &target,
+ NULL))
+ return;
+
+ add_alias (parse_data, name, target);
+ }
+ else if (strcmp (element_name, "layout") == 0)
+ {
+ if (parse_data->seen_layout)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Multiple occurrences of <layout>");
+ return;
+ }
+ parse_data->seen_layout = TRUE;
+ parse_data->state = IN_LAYOUT;
+
+ if (!extract_attrs (context, attribute_names, attribute_values, error,
+ NULL))
+ return;
+ }
+ else
+ expect_tag (context, element_name, NULL, error);
+ break;
+ case IN_SOURCE:
+ {
+ const char *file;
+ const char *use_str;
+ int use;
+
+ if (!expect_tag (context, element_name, "image", error))
+ return;
+ parse_data->state = IN_IMAGE;
+
+ if (!extract_attrs (context, attribute_names, attribute_values, error,
+ "file", TRUE, &file,
+ "use", TRUE, &use_str,
+ NULL))
+ return;
+
+ if (strcmp (use_str, "hotspot") == 0)
+ use = -1;
+ else
+ {
+ if (!get_int (use_str, &use) || use < 0)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Invalid use value %s", use_str);
+ return;
+ }
+ }
+
+ add_image (parse_data, file, use, error);
+ }
+
+ break;
+ case IN_LAYOUT:
+ if (!expect_tag (context, element_name, "row", error))
+ return;
+ parse_data->state = IN_ROW;
+ parse_data->column = 0;
+ break;
+ case IN_ROW:
+ {
+ const char *name;
+
+ if (!expect_tag (context, element_name, "cursor", error))
+ return;
+ parse_data->state = IN_CURSOR;
+
+ if (!extract_attrs (context, attribute_names, attribute_values, error,
+ "name", TRUE, &name,
+ NULL))
+ return;
+
+ add_cursor (parse_data, name);
+ }
+ break;
+ case IN_CURSOR:
+ {
+ const char *delay_str = NULL;
+ int delay = -1;
+
+ if (!expect_tag (context, element_name, "frame", error))
+ return;
+ parse_data->state = IN_FRAME;
+
+ if (!extract_attrs (context, attribute_names, attribute_values, error,
+ "delay", FALSE, &delay_str,
+ NULL))
+ return;
+
+ if (delay_str)
+ {
+ if (!get_int (delay_str, &delay) || delay < 0)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Invalid delay value '%s'", delay_str);
+ return;
+ }
+ }
+
+ add_frame_config (parse_data, delay);
+ }
+ break;
+ case IN_ALIAS:
+ case IN_IMAGE:
+ case IN_FRAME:
+ expect_tag (context, element_name, NULL, error);
+ break;
+ }
+}
+
+/* Called for close tags </foo> */
+static void
+cursor_theme_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ ParseData *parse_data = user_data;
+
+ switch (parse_data->state)
+ {
+ case OUTSIDE:
+ g_assert_not_reached ();
+ break;
+ case IN_THEME:
+ parse_data->state = OUTSIDE;
+ parse_data->theme->sources = g_slist_reverse (parse_data->theme->sources);
+ break;
+ case IN_SOURCE:
+ {
+ CursorSource *source = parse_data->theme->sources->data;
+ source->images = g_slist_reverse (source->images);
+ parse_data->state = IN_THEME;
+ }
+ break;
+ case IN_ALIAS:
+ parse_data->state = IN_THEME;
+ break;
+ case IN_IMAGE:
+ parse_data->state = IN_SOURCE;
+ break;
+ case IN_LAYOUT:
+ parse_data->state = IN_THEME;
+ break;
+ case IN_ROW:
+ parse_data->state = IN_LAYOUT;
+ parse_data->row++;
+ break;
+ case IN_CURSOR:
+ {
+ Cursor *cursor = parse_data->current_cursor;
+ if (!cursor->frame_configs)
+ add_frame_config (parse_data, -1);
+ cursor->frame_configs = g_slist_reverse (cursor->frame_configs);
+ parse_data->state = IN_ROW;
+ parse_data->column++;
+ parse_data->current_cursor = NULL;
+ }
+ break;
+ case IN_FRAME:
+ parse_data->state = IN_CURSOR;
+ break;
+ }
+}
+
+/* Called for character data */
+/* text is not nul-terminated */
+static void
+cursor_theme_text (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ int i;
+
+ for (i = 0; i < text_len; i++)
+ if (!g_ascii_isspace (text[i]))
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Unexpected text in theme file");
+ return;
+ }
+}
+
+/* Called for strings that should be re-saved verbatim in this same
+ * position, but are not otherwise interpretable. At the moment
+ * this includes comments and processing instructions.
+ */
+/* text is not nul-terminated. */
+static void
+cursor_theme_passthrough (GMarkupParseContext *context,
+ const gchar *passthrough_text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ /* do nothing */
+}
+
+/* Called on error, including one set by other
+ * methods in the vtable. The GError should not be freed.
+ */
+static void
+cursor_theme_error (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+}
+
+static GMarkupParser cursor_theme_parse = {
+ cursor_theme_start_element,
+ cursor_theme_end_element,
+ cursor_theme_text,
+ cursor_theme_passthrough,
+ cursor_theme_error
+};
+
+static void
+cursor_theme_free (CursorTheme *theme)
+{
+}
+
+CursorTheme *
+cursor_theme_read (const char *filename)
+{
+ ParseData parse_data;
+ GMarkupParseContext *context;
+ GError *error = NULL;
+ char *text;
+ gboolean have_error = FALSE;
+ size_t len;
+
+ if (!g_file_get_contents (filename, &text, &len, &error))
+ {
+ g_printerr ("Cannot read theme definition file: %s\n", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ parse_data.theme = g_new0 (CursorTheme, 1);
+ parse_data.theme->cursors = g_hash_table_new (g_str_hash, g_str_equal);
+ parse_data.theme->aliases = g_hash_table_new (g_str_hash, g_str_equal);
+
+ parse_data.state = OUTSIDE;
+ parse_data.seen_theme = FALSE;
+ parse_data.seen_layout = FALSE;
+ parse_data.row = 0;
+ parse_data.column = 0;
+
+ context = g_markup_parse_context_new (&cursor_theme_parse, 0,
+ &parse_data, NULL);
+
+ if (!g_markup_parse_context_parse (context, text, len, &error) ||
+ !g_markup_parse_context_end_parse (context, &error))
+ {
+ g_printerr ("Error parsing theme definition file: %s\n", error->message);
+ have_error = TRUE;
+ g_error_free (error);
+ }
+ else if (!parse_data.seen_theme)
+ {
+ g_printerr ("Did not find <theme> element in theme file\n");
+ have_error = TRUE;
+ }
+ else if (!parse_data.seen_layout)
+ {
+ g_printerr ("Did not find <layout> element in theme file\n");
+ have_error = TRUE;
+ }
+ else if (!parse_data.theme->sources)
+ {
+ g_printerr ("No <source> element in theme file\n");
+ have_error = TRUE;
+ }
+
+ g_markup_parse_context_free (context);
+
+ if (!have_error)
+ return parse_data.theme;
+ else
+ {
+ cursor_theme_free (parse_data.theme);
+ return NULL;
+ }
+}
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..471d05b
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=olpc-artwork
+TEST_TYPE=-d
+FILE=art
+
+DIE=0
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have autoconf installed to compile $PROJECT."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+AUTOMAKE=automake-1.9
+ACLOCAL=aclocal-1.9
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+ AUTOMAKE=automake
+ ACLOCAL=aclocal
+}
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have automake installed to compile $PROJECT."
+ echo "Get ftp://ftp.cygnus.com/pub/home/tromey/automake-1.2d.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+}
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+ echo "You must run this script in the top-level $PROJECT directory"
+ exit 1
+}
+
+if test -z "$*"; then
+ echo "I am going to run ./configure with no arguments - if you wish "
+ echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+echo $ACLOCAL $ACLOCAL_FLAGS
+$ACLOCAL $ACLOCAL_FLAGS
+
+# optionally feature autoheader
+(autoheader --version) < /dev/null > /dev/null 2>&1 && autoheader
+
+$AUTOMAKE -a $am_opt
+
+autoconf || echo "autoconf failed - version 2.5x is probably required"
+
+cd $ORIGDIR
+
+$srcdir/configure --enable-maintainer-mode "$@"
+
+echo
+echo "Now type 'make' to compile $PROJECT."
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..2d801f8
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,31 @@
+AC_INIT(art)
+
+AM_CONFIG_HEADER(config.h)
+
+AM_INIT_AUTOMAKE(olpc-artwork, 0.3)
+
+# Honor aclocal flags
+ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS"
+
+AM_MAINTAINER_MODE
+
+AM_DISABLE_STATIC
+
+AC_PROG_CC
+AC_HEADER_STDC
+
+PKG_CHECK_MODULES(GTK2, gtk+-2.0 >= 2.0.0,,
+ AC_MSG_ERROR([GTK+-2.0 is required to compile redhat-artwork]))
+
+GDK_PIXBUF2_CFLAGS=`$PKG_CONFIG --cflags gdk-pixbuf-2.0`
+GDK_PIXBUF2_LIBS=`$PKG_CONFIG --libs gdk-pixbuf-2.0`
+AC_SUBST(GDK_PIXBUF2_CFLAGS)
+AC_SUBST(GDK_PIXBUF2_LIBS)
+
+AC_OUTPUT([
+Makefile
+art/Makefile
+art/cursor/Makefile
+art/cursor/cursorthemegen/Makefile
+art/cursor/Bluecurve/Makefile
+])
diff --git a/gtkrc2-default b/gtkrc2-default
new file mode 100644
index 0000000..e7e3318
--- /dev/null
+++ b/gtkrc2-default
@@ -0,0 +1,3 @@
+gtk-theme-name = "Clearlooks"
+gtk-icon-theme-name = "gnome"
+gtk-cursor-theme-name = "Bluecurve"