From 0658d108b9f1c4d4215f240895ec3742f512b757 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Wed, 07 Jun 2006 16:54:14 +0000 Subject: Add an .hgignore --- 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. + + + Copyright (C) + + 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. + + , 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + * Makefile.am (EXTRA_DIST): fix distcheck + +Thu Jan 16 14:56:26 2003 Owen Taylor + + * 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 + + * main.c (cursor_get_image): + Define variables at top of function. + +2003-02-22 Matt Wilson + + * 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 + + * 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 + + * Makefile.am (cursorthemegen_SOURCES): fix distcheck + +Thu Jan 16 15:25:47 2003 Owen Taylor + + * 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 + + * main.c themefile.c: Use a hash table instead of a + list of cursors. + + * themefile.c generic.cursortheme: Remove element, + put elements directly under node. + + * themefile.c generic.cursortheme: Rename element to + . + +Wed Jan 15 18:25:24 2003 Owen Taylor + + * 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: + +: The toplevel element. There must be + exactly one of these. + + Attributes: + name: The name of the theme. Required. + + Child elements: + , , + +: 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 + +: 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: + + +: 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 + +: Defines the layout of cursors within the grid. + + Attributes: + None + + Child elements: + + +: Defines one row of cursors within the grid + + Attributes: + None + + Child elements: + + +: Defines a single cursor. If there are no + child 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 elements. + + Attributes: + name: The name of the cursor. Required. + + Child elements: + + +: 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 + +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 +#include +#include +#include +#include +#include + +#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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 +#include +#include + +#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 */ +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 "); + 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 "); + 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 */ +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 element in theme file\n"); + have_error = TRUE; + } + else if (!parse_data.seen_layout) + { + g_printerr ("Did not find element in theme file\n"); + have_error = TRUE; + } + else if (!parse_data.theme->sources) + { + g_printerr ("No 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" -- cgit v0.9.1