From 1775dd11d5f97c89390cdca592798bcac951540f Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sat, 13 Jul 2013 14:51:50 +0300 Subject: [PATCH] Imported Upstream version 2.1.0 --- COPYING | 280 +++++++++++ ChangeLog | 127 +++++ Makefile | 53 +++ gtk-theme-switch2.1 | 40 ++ main.c | 1072 +++++++++++++++++++++++++++++++++++++++++++ readme | 13 + todo | 4 + 7 files changed, 1589 insertions(+) create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Makefile create mode 100644 gtk-theme-switch2.1 create mode 100644 main.c create mode 100644 readme create mode 100644 todo diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..279ea0e --- /dev/null +++ b/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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 diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..0cb48fc --- /dev/null +++ b/ChangeLog @@ -0,0 +1,127 @@ +2.1.0 +----- +- New home page + + +2.1.0rc1 +-------- + +- New developer : Denis Briand +with muhri and Aaron Lehmann agreement, thanks for their confidence. +- New hosting project : gna.org (pending) +- remove deprecated gtk1 support +- add license headers in each sources files. +- rename gtk-theme-switch2.c into main.c +- remove switch.h + + + + +2.0.6 +----- + +- New Maintainer (Closes: #462908) +- solve an unchecked fopen() (Closes: #498447) +Thanks to François Wendling for his audit +and for his patch. +- fix hash table pointer issue (Closes: #229384) +Thanks to Ron Murray for his work and for his patch. +- rename switch2.* by gtk-theme-switch2.* +and add gtk-theme-switch2 name in gtkrc-2.0 conf file (Closes: #319286). +- Bump compat to 7. +- Bump standards version to 3.8.1. +- Remove unused switch.c and switch.1 files. +- Fit Makefile and debian/rules to the renamed files. +- Remove obsolete debian/README.debian file. +- Remove obsolete debian/links file. +- Fit debian/menu to the renamed bin file. +- Fix versionless symlink license in debian/copyright.- Fit man file to the renamed bin file. +- Rename unused ChangeLog to ChangeLog.old +- Change deprecated "dh_clean -k" in "dh_prep" in debian/rules. + + -- Denis Briand Sat, 11 Apr 2009 18:36:20 +0200 + + +2.0.5 +----- + +- QA upload. +Set maintainer to Debian QA Group . +- Build gtk2 binary only. (Closes: #462906, #462904, #291008). +Rename debian/switch.1 to switch2.1 to match binary. +- Drop recommends for gtk-engines-pixmap. (Closes: #473847). +Thanks to amaya for the bug report and fix. +- Update FSF address in copyright. +- Bump debhelper build-dep and compat to 5. +- Bump Standards Version to 3.7.3. +Menu policy transition. + + -- Barry deFreese Tue, 15 Apr 2008 23:28:49 -0400 + + +2.0.4 +----- + +- switch.c (get_dirs): the gtk-2.0/gtkrc dir is used for gtk-2.0 +themes, we should use gtk/gtkrc for gtk themes. +thanks to Tobias Jordan +for the patch. (Closes: #255722, #306245). + + -- Pedro Villavicencio Garrido Sat, 30 Apr 2005 20:26:10 -0400 + + +2.0.3 +----- + +- Fixed bug #278179. + + -- Pedro Villavicencio Garrido Mon, 25 Oct 2004 15:56:29 -0300 + + +2.0.2 +----- + +- New Maintainer with previous Maintainer consent's. +- gtk-theme-switch2 overwritte ~/.gtkrc-2.0, so we made a backup +of this file before overwritte them. (Closes : #271450) + + -- Pedro Villavicencio Garrido Tue, 14 Sep 2004 11:16:43 -0400 + + +2.0.1 +----- + +- New upstream (me) release. Becomes Debian native. +- These patches are new, but were merged into the new native source: + - 05_use_2.0_in_mine.dpatch: use file name '.gtkrc-2.0.mine' when writing + canned .gtkrc-2.0 for personal changes to avoid conflict with .gtkrc.mine. + - 06_check_gtkrc_NULL.dpatch: check to see whether gtkrc is NULL, or else + feof() and fclose() will choke on it. Thanks Zack Cerza. +- Quote stuff in debian/menu. + + -- Joshua Kwan Wed, 16 Jun 2004 00:31:55 -0700 + + +2.0.0rc2 +-------- + +- Changed binary name to switch2 +- Fixed switching in some cases. +- Fixed user font selection. + +2.0.0rc1 +----- + +- Port to Gtk2.0. + +1.0.1 +----- + +- Fix for window resizing at startup. +- Fix for 100% cpu usage when previewing themes. + + +1.0 +--- + +Rewrote from Perl to C. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3aa7186 --- /dev/null +++ b/Makefile @@ -0,0 +1,53 @@ +#======================================================================== +#Gtk Theme Switch, a fast and small Gtk theme switching utility that has a +#GUI and console interface. +# +#Copyright (C) 2009 Maher Awamy +# Aaron Lehmann +# Joshua Kwan +# Pedro Villavicencio Garrido +# Denis Briand +# +#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., +#51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +#========================================================================= + +GCC = gcc +PREFIX=/usr/local +CFLAGS = -g -O2 -Wall +CFLAGS_GTK2 = $(shell pkg-config gtk+-2.0 --cflags) + +LIBS_GTK2 = $(shell pkg-config gtk+-2.0 --libs) + +VERSION = 2.1.0 + +all: gtk-theme-switch2 + +gtk-theme-switch2: main.c + ${GCC} -DSWITCH_GTK2 -o gtk-theme-switch2 main.c ${CFLAGS} ${CFLAGS_GTK2} ${LIBS_GTK2} + +clean: + -rm -f gtk-theme-switch2 *~ + +install: all + mkdir -p ${PREFIX}/bin + mkdir -p ${PREFIX}/man + install -c gtk-theme-switch2 ${PREFIX}/bin + install -c gtk-theme-switch2.1 ${PREFIX}/man + +dist: clean + rm -rf /tmp/gtk-theme-switch-$(VERSION) + cp -r . /tmp/gtk-theme-switch-$(VERSION) + tar czf ../gtk-theme-switch-$(VERSION).tar.gz -C /tmp/ gtk-theme-switch-$(VERSION) + rm -rf /tmp/gtk-theme-switch-$(VERSION) diff --git a/gtk-theme-switch2.1 b/gtk-theme-switch2.1 new file mode 100644 index 0000000..dc9db53 --- /dev/null +++ b/gtk-theme-switch2.1 @@ -0,0 +1,40 @@ +.\" This -*- nroff -*- file has been generated from +.\" DocBook SGML with docbook-to-man on Debian GNU/Linux. +.TH "gtk-theme-switch" "1" +.SH "NAME" +gtk-theme-switch2 \(em program to preview and adjust your GTK+ 2.x theme +.SH "SYNOPSIS" +.PP +\fBgtk-theme-switch2\fP [\fB-h\fP] [\fB-p \fItheme\fP\fP] [\fB-i \fItarball\fP\fP] [\fB-f \fIfont\fP\fP] [\fB-d\fP] +.SH "DESCRIPTION" +.PP +This manual page documents briefly the +\fBgtk-theme-switch2\fP command, utility for managing GTK+ 2.x theme. +.PP +The interface is simple; a "theme dock" is used to select the theme you wish +to change to or preview, and then it is a matter of selecting what you want to +do - apply it or preview it. +.SH "OPTIONS" +.IP "\fB-h\fP" 10 +Show summary of options. +.IP "\fB-d\fP " 10 +Show the 'theme dock' (default.) +.IP "\fB-p [theme]\fP " 10 +Previews the specified theme, or installs it if in a tarball and then previews. +.IP "\fB-i [theme]\fP " 10 +Installs the specified theme, or installs it if in a tarball. +.IP "\fB-f [font]\fP " 10 +Change the GTK+ display font to font. +.SH "SEE ALSO" +.PP +None. +.SH "AUTHOR" +.PP +This manual page was written by Joshua Kwan for +the \fBDebian\fP system (but may be used by others). Permission is +granted to copy, distribute and/or modify this document under +the terms of the GNU Free Documentation +License, Version 1.1 or any later version published by the Free +Software Foundation; with no Invariant Sections, no Front-Cover +Texts and no Back-Cover Texts. +created by instant / docbook-to-man, Sun 17 Aug 2003, 01:18 diff --git a/main.c b/main.c new file mode 100644 index 0000000..56cfe3e --- /dev/null +++ b/main.c @@ -0,0 +1,1072 @@ +/*======================================================================== +Gtk Theme Switch, a fast and small Gtk theme switching utility that has a +GUI and console interface. + +Copyright (C) 2009 Maher Awamy + Aaron Lehmann + Joshua Kwan + Pedro Villavicencio Garrido + Denis Briand + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +=========================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static GList *get_dirs(void); +static void preview_clicked(GtkWidget *button, gpointer data); +static void update_newfont (void); +static void apply_clicked(GtkWidget *button, gpointer data); +static void usage(void); +static void backup_gtkrc(gchar *path_to_gtkrc); +static void ok_clicked(gchar *rc); +static void preview_ok_clicked(gchar *rc); +#ifdef SWITCH_GTK2 +static GtkTreeModel *create_model (void); +void clist_insert (GtkTreeView *clist); +#endif +static void dock(void); +#ifndef SWITCH_GTK2 +static int rightclick (GtkWidget *w, GdkEventButton *event, gpointer data); +static void clist_insert(GtkWidget *clist); +#endif +static void preview(gchar *rc_file); +static void preview_window(gchar *rc_file); +static void send_refresh_signal(void); +static short is_themedir (gchar *path, gchar **rc_file); +static short is_installed_theme (gchar *path, gchar **rc_file); +static short install_tarball (gchar *path, gchar **rc_file); +static int switcheroo (gchar *actual); +static void install_clicked (GtkWidget *w, gpointer data); +static void install_ok_clicked (GtkWidget *w, gpointer data); +static void search_for_theme_or_die_trying (gchar *actual, gchar **rc_file); +static void set_font (GtkWidget *w, GtkWidget *dialog); +static void font_browse_clicked (GtkWidget *w, gpointer data); +static short fgrep_gtkrc_for (gchar *needle); +static GList *compare_glists (GList *t1, GList *t2, GCompareFunc cmpfunc); +void quit_preview(); +void quit(); +void hide_stuff(); +void show_stuff(); +void on_eventbox_click(); + +#define INIT_GTK if (!using_gtk) { gtk_init (&argc, &argv); using_gtk = 1; } + + +/* globals */ +GHashTable *hash; +GList *glist=NULL; +GSList *kids=NULL; +gint preview_counter = 0; + +gchar *homedir, /* we use it a lot, so keep it handy */ + *execname, /* == argv[0] */ + *newfont; /* The name of a new font to use as the default if the user has + selected one. Otherwise NULL. */ + +GtkWidget *dockwin, *combo=NULL, *font_entry, *use_font_button, *box, *install_button, *browse; +gint hidden = 1; +/*end globals */ + +static short fgrep_gtkrc_for (gchar *needle) +{ + gchar *path_to_gtkrc = g_strdup_printf("%s/.gtkrc-2.0", homedir); + FILE *gtkrc = fopen(path_to_gtkrc, "r"); + char tempbuf[16384], *commentsearch; + g_free (path_to_gtkrc); + + if (!gtkrc) + return 0; + + while (!feof (gtkrc)) + { + fgets (tempbuf, 16383, gtkrc); + /* Strip comments */ + for (commentsearch = tempbuf; *commentsearch != '\0'; ++commentsearch) + if (*commentsearch == '#') { *commentsearch = '\0'; break; } + if (strstr(tempbuf, needle)) + { + fclose (gtkrc); + return 1; + } + } + fclose (gtkrc); + return 0; +} + +static GList* +get_dirs (void) +{ + gchar *dirname, *localthemedir, *globalthemedir, *dname; + DIR *dir; + struct dirent *dent; + struct stat stats; + gchar *origdir=g_get_current_dir(); /* back up cwd */ + GList *list=0; + + dirname = g_strconcat(homedir,"/.themes",NULL); + chdir (dirname); + dir = opendir (dirname); + if (dir) + { + /* ONE copy of the local theme directory for putting in the hash */ + /* NB: Don't g_free() it!! */ + localthemedir = g_strdup(dirname); + + while ((dent = readdir (dir))) + { + gchar* gtkrc_path = g_strconcat(dent->d_name, "/gtk-2.0/gtkrc", NULL); + stat(dent->d_name,&stats); + if (!S_ISDIR(stats.st_mode)) continue; + if (strcmp(dent->d_name,"." ) == 0) continue; + if (strcmp(dent->d_name,"..") == 0) continue; + if (access(gtkrc_path, R_OK) == -1) continue; + + dname = g_strdup(dent->d_name); + g_hash_table_insert (hash, dname, localthemedir); + list = g_list_insert_sorted(list, dname, (GCompareFunc)strcmp); + g_free(gtkrc_path); + } + + closedir(dir); + } + + g_free(dirname); + + dirname = gtk_rc_get_theme_dir(); + chdir (dirname); + dir = opendir (dirname); + if (dir) + { + /* ONE copy of the global theme directory for putting in the hash */ + /* NB: Don't g_free() it!! */ + globalthemedir = g_strdup(dirname); + + while ((dent = readdir (dir))) + { + gchar* gtkrc_path = g_strconcat(dent->d_name,"/gtk-2.0/gtkrc",NULL); + stat(dent->d_name,&stats); + if (!S_ISDIR(stats.st_mode)) continue; + if (strcmp(dent->d_name, "." ) == 0) continue; + if (strcmp(dent->d_name, "..") == 0) continue; + if (access(gtkrc_path, R_OK) == -1) continue; + + dname = g_strdup(dent->d_name); + g_hash_table_insert (hash, dname, globalthemedir); + list = g_list_insert_sorted(list, dname, (GCompareFunc)strcmp); + g_free(gtkrc_path); + } + + closedir(dir); + } + + g_free(dirname); + + chdir(origdir); /* Go back to where we were */ + g_free(origdir); /* Now go play like a good little program */ + + return list; +} + +/* Find the first element in t2 that does not exist in t1. + * Uses the supplied cmpfunc() for determining equality of list->data + * strcmp() is the recommended compare function */ +static GList* +compare_glists (GList *t1, GList *t2, GCompareFunc cmpfunc) +{ + GList *tmp1; + for (; t2; t2=t2->next) + { + short matched = 0; + for (tmp1=t1; tmp1; tmp1=tmp1->next) + if ((*cmpfunc)(tmp1->data, t2->data) == 0) { matched = 1; break; } + if (!matched) return t2; + } + return 0; +} + +static void +preview_clicked(GtkWidget *button, gpointer data) +{ + G_CONST_RETURN gchar *entry; + gchar *dir; + gchar *rc; + gchar *actual; + + entry = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); + dir = g_hash_table_lookup(hash,entry); + dir = g_strconcat(dir,"/",NULL); + rc = g_strconcat(dir,entry,NULL); + actual = g_strconcat(dir,entry,NULL); + rc = g_strconcat(rc,"/gtk-2.0/gtkrc",NULL); + update_newfont (); + preview(rc); + g_free(rc); + g_free(actual); +} + +/* Update 'newfont' */ +static void update_newfont (void) +{ + if (newfont) g_free (newfont); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_font_button))) + { + G_CONST_RETURN gchar *newerfont = gtk_entry_get_text (GTK_ENTRY(font_entry)); + if (newerfont && newerfont[0]) + { + newfont = g_strdup(newerfont); + } + } + else newfont = NULL; +} + +static void +apply_clicked(GtkWidget *button, gpointer data) +{ + G_CONST_RETURN gchar *entry = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); + gchar *dir = g_hash_table_lookup(hash,entry); + gchar *name = g_strdup_printf ("%s/%s/gtk-2.0/gtkrc", dir, entry); +/* GtkStyle *style;*/ + + update_newfont (); + + ok_clicked(name); + g_free(name); + + /* make sure we get the ClientEvent ourselves */ + while (gtk_events_pending()) + gtk_main_iteration(); + + /* sync the font field with the GTK font */ +/* style = gtk_rc_get_style (font_entry); + if (style && style->rc_style) + gtk_entry_set_text (GTK_ENTRY(font_entry), pango_font_description_to_string(style->rc_style->font_desc));*/ +} + +static void +usage (void) +{ + printf("\ +%s command line options:\n\ +-h[elp]\t\t\t(display this help message)\n\ +-d[ock]\t\t\t(open dock)\n\ +file\t\t\t(switch to theme (install if theme is a tarball))\n\ +-p[review] file\t\t(preview a theme (installs if file is a tarball))\n\ +-i[nstall] theme.tar.gz\t(install a .tar.gz)\n\ +-f[ont] fontstring\t(set GTK's main font to fontstring)\n\n\ +\ +Passing no command line arguments will cause %s to start in dock-mode)\n\n\ +\ +\"file\" represents any one of (looked for in the listed order):\n\ +1) An absoulte or relative path to a GTK theme directory.\n\ + A directory is considered a theme directory if it contains a\n\ + gtk/gtkrc file.\n\ +2) A gzipped tar file which expands to a GTK theme directory as explained in 1).\n\ +3) A GTK theme directory with the name passed located in ~/.themes.\n\ +4) A GTK theme directory with the name passed located in the global\n\ + \"gtk_themedir\"\n\ +If none of these files are located and found to be correct, the program will\n\ +exit with an error.\n", +execname, execname); +} + +static void +write_rc_file (gchar *include_file, gchar *path) +{ + FILE *gtkrc = fopen(path, "w"); + /*XXX XXX*/ + if (gtkrc == NULL) { + GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(dockwin), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Unable to save your preferences to %s: %s.", + path,strerror(errno) ); + gtk_window_set_title(GTK_WINDOW(dialog), "Error"); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + quit(); + } + /* the caps stuff is bullshit for gnome */ + fprintf(gtkrc, "# -- THEME AUTO-WRITTEN BY gtk-theme-switch2 DO NOT EDIT\ninclude \"%s\"\n\n", include_file); + if (newfont) + /* User set a custom font to overrride defaults. */ + fprintf (gtkrc, "style \"user-font\"\n{\n font_name=\"%s\"\n}\nwidget_class \"*\" style \"user-font\"\n\n", newfont); + fprintf(gtkrc, "include \"%s/.gtkrc-2.0.mine\"\n\n# -- THEME AUTO-WRITTEN BY gtk-theme-switch2 DO NOT EDIT\n", homedir); + fclose (gtkrc); +} + +static void +backup_gtkrc(gchar *path_to_gtkrc) +{ + FILE *gtkrc; + if (!(gtkrc = fopen(path_to_gtkrc, "r"))) + return; + int c; + FILE *gtkrc_backup = fopen(g_strdup_printf("%s/.gtkrc-2.0.bak", homedir),"w"); + + while((c = fgetc(gtkrc)) != EOF){ + fputc(c, gtkrc_backup); + } + + fclose(gtkrc); + fclose(gtkrc_backup); +} + +static void +ok_clicked (gchar *rc_file) +{ + /* Write the config file to disk */ + gchar *path_to_gtkrc = g_strdup_printf("%s/.gtkrc-2.0", homedir); + backup_gtkrc(path_to_gtkrc); + write_rc_file (rc_file, path_to_gtkrc); + send_refresh_signal(); + g_free(path_to_gtkrc); +} + +static void +preview_ok_clicked (gchar *rc_file) +{ + /* Write the config file to disk */ + gchar *path_to_gtkrc = g_strdup_printf("%s/.gtkrc-2.0", homedir); + rename (rc_file, path_to_gtkrc); + send_refresh_signal(); + g_free(path_to_gtkrc); +} + +static void +install_clicked (GtkWidget *w, gpointer data) +{ + GtkWidget *checkbutton = gtk_check_button_new_with_label ("Switch to theme after installation"); + GtkWidget *fs = gtk_file_selection_new ("Select a GTK theme tarball"); + g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), "clicked", G_CALLBACK(install_ok_clicked), fs); + g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(fs)->cancel_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)fs); + gtk_box_pack_start (GTK_BOX(GTK_FILE_SELECTION(fs)->main_vbox), checkbutton, FALSE, FALSE, 0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(checkbutton), FALSE); + g_object_set_data (G_OBJECT(fs), "checkbutton", checkbutton); + gtk_widget_show(checkbutton); + gtk_widget_show(fs); +} + +static void +install_ok_clicked (GtkWidget *w, gpointer data) +{ + gchar *rc_file, *beginning_of_theme_name, *thn; + G_CONST_RETURN gchar *filename; + gint i, pos; + short slashes=0; + gboolean cbstate=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(data), "checkbutton"))); + filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(data)); + thn = g_strdup(filename); + search_for_theme_or_die_trying(thn, &rc_file); + g_free(thn); + gtk_widget_destroy(GTK_WIDGET(data)); + /* ok, we're like evil or something, but that won't stop us */ + for (i=strlen(rc_file); i != 0; --i) + { + if (rc_file[i] == '/') ++slashes; + if (slashes == 2) { rc_file[i] = '\0'; break; } + } + beginning_of_theme_name = rc_file; + for (i=strlen(rc_file) /*different*/; i != 0; --i) + { + if (rc_file[i] == '/') { beginning_of_theme_name = &rc_file[i+1]; break; } + } + /* we've been very naugthy, but we should have the theme's NAME now.. + * it's about time. */ + /* get the list item that contains this */ + pos = g_list_position (glist, g_list_find_custom (glist, beginning_of_theme_name, (GCompareFunc) strcmp)); + if (pos != -1) + /* set combo's item to the newly-installed theme */ +/*FIXME gtk_list_select_item(GTK_LIST(GTK_COMBO(combo)->list), pos);*/ + + if (cbstate) /* checkbutton pressed */ + apply_clicked(NULL, NULL); + + /* I guess we should free this... */ + g_free (rc_file); +} + +static void +set_font (GtkWidget *w, GtkWidget *dialog) +{ + if (newfont) g_free (newfont); + newfont = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG(dialog)); + gtk_entry_set_text (GTK_ENTRY(font_entry), newfont); + gtk_widget_destroy (dialog); +} + +static void +font_browse_clicked (GtkWidget *w, gpointer data) +{ + GtkWidget *font_dialog; + font_dialog = gtk_font_selection_dialog_new ("Select Font"); + gtk_font_selection_dialog_set_preview_text (GTK_FONT_SELECTION_DIALOG(font_dialog), "Gtk Theme Switch"); +/* gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG(font_dialog), gtk_entry_get_text(GTK_ENTRY(font_entry)));*/ + g_signal_connect (G_OBJECT(GTK_FONT_SELECTION_DIALOG(font_dialog)->ok_button), "clicked", G_CALLBACK(set_font), (gpointer)font_dialog); + g_signal_connect_swapped (G_OBJECT(GTK_FONT_SELECTION_DIALOG(font_dialog)->cancel_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)font_dialog); + + gtk_widget_show (font_dialog); +} + +void quit() +{ + GSList *l; + for (l = kids; l ; l=l->next) { + kill(GPOINTER_TO_INT(l->data), 9); + } + exit(0); +} + +static void +dock (void) +{ + GtkWidget *label, *button, *pixmap, *evbox; + GtkTooltips *tips; + + dockwin = gtk_dialog_new(); + gtk_widget_realize(dockwin); + gtk_window_set_title(GTK_WINDOW(dockwin),"Theme Dock"); +/* gtk_window_set_policy(GTK_WINDOW(dockwin), TRUE, TRUE, FALSE);*/ + gtk_window_set_resizable(GTK_WINDOW(dockwin), TRUE); + g_signal_connect(G_OBJECT(dockwin),"destroy",G_CALLBACK(quit),NULL); + box = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dockwin)->vbox), box, FALSE, FALSE, 0); + tips = gtk_tooltips_new(); + label = gtk_label_new("Theme: "); + gtk_box_pack_start(GTK_BOX(box),label,FALSE,FALSE,FALSE); + + combo = gtk_combo_new(); + glist = get_dirs(); + gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); + gtk_box_pack_start(GTK_BOX(box),combo,TRUE,TRUE,FALSE); + + pixmap = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON); + + evbox = gtk_event_box_new(); + + gtk_tooltips_set_tip(tips,evbox,"click here for more options","private"); + gtk_widget_set_events(evbox, GDK_BUTTON_PRESS); + g_signal_connect(G_OBJECT(evbox), "button_press_event", G_CALLBACK(on_eventbox_click), NULL); + + gtk_container_add(GTK_CONTAINER(evbox), pixmap); + gtk_box_pack_start(GTK_BOX(box),evbox,FALSE,FALSE,FALSE); + gtk_widget_show_all(box); + + box = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dockwin)->vbox), box, FALSE, FALSE, 0); + + use_font_button = gtk_check_button_new_with_label("Use font: "); + gtk_box_pack_start(GTK_BOX(box), use_font_button, FALSE, FALSE, 0); + gtk_widget_show(use_font_button); + + font_entry = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(box), font_entry, TRUE, TRUE, 0); + gtk_widget_show(font_entry); + if (newfont) + { + gtk_entry_set_text (GTK_ENTRY(font_entry), newfont); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(use_font_button), TRUE); + g_free (newfont); + } + else + { +/* GtkStyle *style = gtk_rc_get_style (font_entry); + if (style && style->rc_style) + gtk_entry_set_text (GTK_ENTRY(font_entry), pango_font_description_to_string(style->rc_style->font_desc));*/ + } + + newfont = g_strdup(gtk_entry_get_text(GTK_ENTRY(font_entry))); + + if (newfont != 0 && newfont[0]) + { + /* Very dirty hack... + We want to only set the checkbutton to TRUE if the user specified + the font. If the name occurs in their ~/.gtkrc file, they probably did. + If it isn't, they probably didn't. So, "grep" the file for the font string. */ + if (fgrep_gtkrc_for(newfont)) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_font_button), TRUE); + } + + browse = gtk_button_new_with_label("Browse..."); + g_signal_connect(G_OBJECT(browse), "clicked", G_CALLBACK(font_browse_clicked), NULL); + gtk_box_pack_start(GTK_BOX(box), browse, FALSE, FALSE, 0); + + button = gtk_button_new_with_label("Apply"); + g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(apply_clicked),NULL); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG (dockwin)->action_area),button,TRUE,TRUE,FALSE); + gtk_widget_show(button); + + button = gtk_button_new_with_label("Preview"); + g_signal_connect(GTK_OBJECT(button),"clicked",G_CALLBACK(preview_clicked),NULL); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG (dockwin)->action_area),button,TRUE,TRUE,FALSE); + gtk_widget_show(button); + + install_button = gtk_button_new_with_label("Install New Theme"); + g_signal_connect(G_OBJECT(install_button), "clicked", G_CALLBACK(install_clicked), NULL); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG (dockwin)->action_area),install_button,TRUE,TRUE,FALSE); + + gtk_widget_show(dockwin); + +} + +void on_eventbox_click() +{ + if (hidden) { + show_stuff(); + } else { + hide_stuff(); + } +} + +void hide_stuff() +{ + gtk_widget_hide(box); + gtk_widget_hide(install_button); + gtk_widget_hide(browse); + hidden = 1; +} + +void show_stuff() +{ + gtk_widget_show(box); + gtk_widget_show(install_button); + gtk_widget_show(browse); + hidden = 0; +} + + +static GtkTreeModel * +create_model (void) +{ + + GtkListStore *store; + GtkTreeIter iter; + gint i; + gchar *stuff[4][2] = { { "blah1", "blah2" }, + { "blah3", "blah4" }, + { "blah5", "blah6" }, + { "blah7", "blah8" } }; + + /* create list store */ + store = gtk_list_store_new (2, + G_TYPE_STRING, + G_TYPE_STRING); + + /* add data to the list store */ + for (i = 0; i < 4; i++) + { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, stuff[i][0], + 1, stuff[i][1], + -1); + } + + return GTK_TREE_MODEL (store); +} + + +static void +preview (gchar *rc_file) +{ + FILE *pipe; + gint got_it = 0, it_died = 0; + gchar *line; + gchar *path = g_strdup_printf ("%s/.gtkrc.tmp-%i", homedir, preview_counter); + gchar *command = g_strdup_printf ("%s -_dont-use-this %s &", execname, path); + write_rc_file (rc_file, path); + + pipe = popen(command,"r"); + + if (pipe == NULL) { + g_print("gts: error previewing\n"); + return; + } + + fcntl(fileno(pipe), F_SETFL, O_NONBLOCK); + + line = (gchar *)g_malloc(1024); + while(!feof(pipe)) { + fgets(line,1024,pipe); + line[strlen(line)-1] = '\0'; + if (!got_it && !g_strncasecmp(line,"pid=",4)) { + kids = g_slist_append(kids,GINT_TO_POINTER(atoi(line+4))); + got_it = 1; + } else if (!it_died && !g_strncasecmp(line,"die=",4)) { + kids = g_slist_remove(kids,GINT_TO_POINTER(atoi(line+4))); + it_died = 1; + break; + } + + while (gtk_events_pending()) + gtk_main_iteration(); + usleep(50000); + } + + pclose(pipe); + g_free (line); + g_free (path); + g_free (command); + ++preview_counter; +} + +static void +preview_window (gchar *rc_file) +{ + + GtkWidget *label; + GtkWidget *win; + GtkWidget *button; + GtkWidget *toggle_button; + GtkWidget *check_button; + GtkWidget *sw; + GtkWidget *clist; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *radio; + GtkWidget *radio2; + GtkWidget *radio3; + GtkWidget *ok; + GtkWidget *cancel; + GtkWidget *hbox2; + GtkWidget *notebook; + GtkWidget *text; + GtkTreeModel *model; +/* GtkWidget *popup; + GtkWidget *item;*/ + GtkTextBuffer *buff; + gint argc=1; + gchar **argv = &execname; + gchar *default_files[] = { rc_file, NULL}; + gchar *bb = "Type some text here\nto check if your\ntheme has a problem\nwith the text widget.\nAlso right-click here\nfor a popup-menu sample.\n"; + GSList *group; + + gtk_rc_set_default_files (default_files); + gtk_init (&argc, &argv); + + win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(win), "Gtk Theme Switch theme preview"); +/* gtk_window_set_policy(GTK_WINDOW(win), TRUE, TRUE, FALSE);*/ + g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(quit_preview), NULL); + + vbox = gtk_vbox_new(FALSE,0); + notebook = gtk_notebook_new(); + gtk_container_add (GTK_CONTAINER(win), notebook); + label = gtk_label_new("Page 1"); + gtk_notebook_append_page (GTK_NOTEBOOK(notebook), vbox, label); + label = gtk_label_new("Label"); + button = gtk_button_new_with_label("Button"); + toggle_button = gtk_toggle_button_new_with_label("Toggle Button"); + check_button = gtk_check_button_new_with_label("Check Button"); + hbox = gtk_hbox_new(FALSE,0); + radio = gtk_radio_button_new_with_label(NULL,"Radio 1"); + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)); + radio2 = gtk_radio_button_new_with_label(group,"Radio 2"); + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio2)); + radio3 = gtk_radio_button_new_with_label(group,"Radio 3"); + gtk_box_pack_start((GtkBox*)hbox,radio,FALSE,FALSE,FALSE); + gtk_box_pack_start((GtkBox*)hbox,radio2,FALSE,FALSE,FALSE); + gtk_box_pack_start((GtkBox*)hbox,radio3,FALSE,FALSE,FALSE); + sw = gtk_scrolled_window_new(NULL,NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); + model = create_model(); + clist = gtk_tree_view_new_with_model(model); + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (clist), TRUE); + gtk_tree_view_set_search_column (GTK_TREE_VIEW (clist),0); + g_object_unref (G_OBJECT (model)); + + ok = gtk_button_new_with_label("Ok"); + g_signal_connect_swapped(G_OBJECT(ok),"clicked",G_CALLBACK(preview_ok_clicked), (gpointer) rc_file); + cancel = gtk_button_new_with_label("Cancel"); + g_signal_connect_swapped(G_OBJECT(cancel),"clicked",G_CALLBACK(quit_preview),NULL); + hbox2 = gtk_hbox_new(FALSE,0); + gtk_box_pack_start((GtkBox*)hbox2,ok,TRUE,TRUE,FALSE); + gtk_box_pack_start((GtkBox*)hbox2,cancel,TRUE,TRUE,FALSE); + gtk_container_add(GTK_CONTAINER(sw),clist); + gtk_box_pack_start((GtkBox*)vbox,label,FALSE,FALSE,FALSE); + gtk_box_pack_start((GtkBox*)vbox,button,FALSE,FALSE,FALSE); + gtk_box_pack_start((GtkBox*)vbox,toggle_button,FALSE,FALSE,FALSE); + gtk_box_pack_start((GtkBox*)vbox,check_button,FALSE,FALSE,FALSE); + gtk_box_pack_start((GtkBox*)vbox,hbox,FALSE,FALSE,FALSE); + gtk_box_pack_start((GtkBox*)vbox,sw,TRUE,TRUE,FALSE); + gtk_box_pack_start((GtkBox*)vbox,hbox2,FALSE,FALSE,FALSE); + + vbox = gtk_vbox_new (FALSE, 0); + label = gtk_label_new ("Page 2"); + gtk_notebook_append_page (GTK_NOTEBOOK(notebook), vbox, label); + label = gtk_label_new ("Insensitive Label"); + gtk_widget_set_sensitive (label, 0); + gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0); + button = gtk_button_new_with_label ("Insensitive Button"); + gtk_widget_set_sensitive (button, 0); + gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0); + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + buff = gtk_text_buffer_new(NULL); + gtk_text_buffer_set_text(buff,bb, strlen(bb)); + text = gtk_text_view_new(); + gtk_text_view_set_buffer(GTK_TEXT_VIEW(text), buff); + + gtk_container_add (GTK_CONTAINER(sw), text); +/* + popup = gtk_menu_new (); + gtk_widget_show (popup); + item = gtk_menu_item_new_with_label ("Menu Entry 1"); + gtk_widget_show (item); + gtk_menu_append(GTK_MENU(popup), item); + item = gtk_menu_item_new_with_label ("Menu Entry 2"); + gtk_widget_show (item); + gtk_menu_append(GTK_MENU(popup), item); + item = gtk_menu_item_new_with_label ("Menu Entry 3"); + gtk_widget_show (item); + gtk_menu_append(GTK_MENU(popup), item); + gtk_signal_connect(GTK_OBJECT(text), "button_press_event", GTK_SIGNAL_FUNC(rightclick), popup); + */ + gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); + + label = gtk_label_new ("About"); + vbox = gtk_vbox_new (FALSE, 0); + gtk_notebook_append_page (GTK_NOTEBOOK(notebook), vbox, label); + label = gtk_label_new ("Gtk Theme Switch\nby Maher Awamy \nand Aaron Lehmann \nhttp://www.muhri.net/nav.php3?node=gts"); + gtk_box_pack_start (GTK_BOX(vbox), label, TRUE, TRUE, 0); + + clist_insert(GTK_TREE_VIEW(clist)); + + gtk_widget_show_all(win); + + + g_print("pid=%d\n",getpid()); + + gtk_main (); + + unlink (rc_file); + + _exit (1); /* no change */ +} + +void quit_preview() +{ + g_print("die=%d\n",getpid()); + gtk_main_quit(); +} + +static void +send_refresh_signal(void) +{ + GdkEventClient event; + event.type = GDK_CLIENT_EVENT; + event.send_event = TRUE; + event.window = NULL; + event.message_type = gdk_atom_intern("_GTK_READ_RCFILES", FALSE); + event.data_format = 8; + gdk_event_send_clientmessage_toall((GdkEvent *)&event); +} + +/* Sets rc_file to the rc_file of the theme if the result is true. + * It is the caller's repsonsibility to free rc_file */ +static short is_themedir (gchar *path, gchar **rc_file) +{ + gchar *test_rc_file; + struct stat info; + test_rc_file = g_strdup_printf ("%s/gtk-2.0/gtkrc",path); + if (stat(test_rc_file, &info) == 0 && (S_ISREG(info.st_mode) || S_ISLNK(info.st_mode))) + { + /* $path/gtk/gtkrc exists, and is a regular file */ + *rc_file = test_rc_file; + return 1; + } + else + { + g_free (test_rc_file); + return 0; + } +} + +static short install_tarball (gchar *path, gchar **rc_file) +{ + gchar *command, *themedir; + gint result; + GList *new_list, *new_theme; + + themedir = g_strdup_printf ("%s/.themes", homedir); + + if (path[0] != '/') + { + gchar *cwd = g_get_current_dir(); + command = g_strdup_printf ("tar --directory %s -xzf %s/%s 2>/dev/null", themedir, cwd, path); + g_free (cwd); + } + else + command = g_strdup_printf ("tar --directory %s -xzf %s 2>/dev/null", themedir, path); + + /* Ensure that ~/.themes exists */ + mkdir (themedir, S_IRUSR | S_IWUSR | S_IXUSR); + + result = system(command); + g_free (command); + g_free (themedir); + if (result != EXIT_SUCCESS) + return 0; + /* We don't do that anymore. Now we find the first new directory + * in either themedir, and presume that to be the name of the new theme. + * NOT FOOLPROOF, but good as long as you don't mess with stuff while the + * program is running. At least better than deriving the theme name from + * the tarball name. Ugh. */ + + new_list = get_dirs(); + new_theme = compare_glists(glist, new_list, (GCompareFunc)strcmp); + if (new_theme) + { + result = is_installed_theme(new_theme->data, rc_file); + g_list_foreach (glist, (GFunc)g_free, NULL); + g_list_free (glist); + glist = new_list; + /* Update combo, but only in dock mode */ + if (combo) gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); + } + else + { + gchar *interestingpath, basename[1024]; + g_list_foreach (new_list, (GFunc)g_free, NULL); + g_list_free (new_list); + /* fall back to our old hack if no new dir was created, say if the theme + * was already installed... */ + + /* Set rc_file to our best darn guess of the resultant gtk theme + * dir/gtk/gtkrc. This is very tricky. The hack that is used to is + * to return the segment in path between the last slash and the + * first dot or dash after that. */ + interestingpath = &path[strlen(path)-1]; + while (interestingpath != path && *(interestingpath-1) != '/') interestingpath--; + strcpy (basename, interestingpath); + for (interestingpath = &basename[0]; *interestingpath != '\0'; ++interestingpath) + { + if (*interestingpath == '-' || *interestingpath == '.') + { + *interestingpath = '\0'; + break; + } + } + result = is_installed_theme(basename, rc_file); + } + + return result; +} + +static short +is_installed_theme (gchar *path, gchar **rc_file) +{ + gchar *gtk_rc_theme_dir = gtk_rc_get_theme_dir(); + /* don't strlen things twice when computing the size to use for fullpath */ + gint path_len = strlen(path), homedir_len = strlen(homedir); + /* ditto with get_theme_dir */ + gint gtk_rc_theme_dir_len = strlen(gtk_rc_theme_dir); + gchar *fullpath = (gchar *) g_malloc (MAX(homedir_len+path_len+10, + gtk_rc_theme_dir_len+path_len+1)); + short result; + + /* use memcpy since we already have the lengths */ + memcpy (fullpath, homedir, homedir_len); + memcpy (fullpath+homedir_len, "/.themes/", 9); + /* add 1 to length so we get the null char too */ + memcpy (fullpath+homedir_len+9, path, path_len+1); + + if (is_themedir(fullpath, rc_file)) + { + g_free(fullpath); + return 1; + } + memcpy (fullpath, gtk_rc_theme_dir, gtk_rc_theme_dir_len); + /* add 1 to length so we get the null char too */ + memcpy (fullpath+gtk_rc_theme_dir_len, path, path_len+1); + + result = is_themedir(fullpath, rc_file); + + g_free(fullpath); + + return result; +} + +static void +search_for_theme_or_die_trying (gchar *actual, gchar **rc_file) +{ + if (!is_themedir(actual, rc_file) && + !install_tarball(actual, rc_file) && + !is_installed_theme(actual, rc_file)) + { + fprintf (stderr, "\ +%s: Sorry, \"%s\" does not appear to be a valid theme directory or tarball!\n", execname, actual); + exit (EXIT_FAILURE); + } +} + +static gint +switcheroo (gchar *actual) +{ + gchar *rc_file; + search_for_theme_or_die_trying (actual, &rc_file); + /* If we get here, we actually found the theme */ + ok_clicked(rc_file); + g_free (rc_file); + return EXIT_SUCCESS; +} + + + +int main (int argc, char *argv[]) +{ + gchar *rc_file; + gchar *actual; + gint i; + gint result = EXIT_SUCCESS; + GSList *l=NULL; + short using_gtk = 0; + + newfont = 0; + execname = argv[0]; + homedir = getenv("HOME"); + hash = g_hash_table_new (g_str_hash, g_str_equal); + + if (argc == 1) /* start in dock mode auto if no args */ + { + INIT_GTK + dock(); + } + + else if (strcmp(argv[1], "-_dont-use-this") == 0) + { + preview_window (argv[2]); /* GARGARGAR */ + } /* hehe, aaronl is crazy */ + + for (i=1; i != argc; ++i) + { + if (argv[i][0] == '-') + { + /* Single-arg commands/options */ + if (argv[i][1] == 'd') + { + INIT_GTK + dock(); + continue; + } + + /* Double-arg commands/options */ + if (i+1 != argc) + { + if (argv[i][1] == 'p') + { + glist = get_dirs (); + actual = argv[++i]; + if (!is_themedir(actual, &rc_file) && !install_tarball(actual, &rc_file) && !is_installed_theme(actual, &rc_file)) + { + fprintf (stderr, "\ +%s: Sorry, \"%s\" does not appear to be a valid theme directory or tarball!\n", execname, actual); + result = EXIT_FAILURE; + } + else + { + preview (rc_file); + g_free (rc_file); + } + continue; + } + + if (argv[i][1] == 'i') + { + actual = argv[++i]; + if (!install_tarball(actual, &rc_file)) + { + fprintf (stderr, "\ +%s: Sorry, \"%s\" does not appear to be a valid theme tarball!\n", execname, actual); + } + result = EXIT_FAILURE; + continue; + } + + if (argv[i][1] == 'f') + { + newfont = g_strdup (argv[++i]); + continue; + } + } + + /* if this starts with a minus, it's either an unrecognized command + * or -help. Perfect */ + usage(); + result = EXIT_FAILURE; + continue; + } + /* got here... fallback and assume it's a theme */ + glist = get_dirs (); + gtk_init (&argc, &argv); + result |= switcheroo(argv[i]); + } + + if (using_gtk) { + gtk_main(); + for (l=kids;l;l=l->next) { + kill(GPOINTER_TO_INT(l->data), 9); + + } + } + + return result; +} + +void clist_insert(GtkTreeView *clist) +{ + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes("Column 1", + renderer, + "text", + 0, + NULL); + + + gtk_tree_view_column_set_sort_column_id(column, 0); + gtk_tree_view_append_column(clist, column); + + + renderer = gtk_cell_renderer_text_new(); + + column = gtk_tree_view_column_new_with_attributes("Column2", + renderer, + "text", + 1, + NULL); + + gtk_tree_view_column_set_sort_column_id(column, 1); + gtk_tree_view_append_column(clist, column); + + return; +} diff --git a/readme b/readme new file mode 100644 index 0000000..b5ce66f --- /dev/null +++ b/readme @@ -0,0 +1,13 @@ +___gtk-theme-switch___ +http://gna.org/projects/gtk-theme-switch/ + +This program allows you to preview and switch GTK themes. gtk-theme-switch is +designed to be usable and flexible from both the shell prompt and X-Windows +display. Please see the manual page or run the switch executable with the +-help option for information on the allowed command line options. + +Comments and suggestions are welcome: + +muhri@muhri.net +aaronl@vitelus.com +denis@narcan.fr diff --git a/todo b/todo new file mode 100644 index 0000000..bb05bc1 --- /dev/null +++ b/todo @@ -0,0 +1,4 @@ +- add -n/-nosignal option which prevents us from telling other apps to reread the .gtkrc +- integrate grdb (optional). add a checkbox "Emulate theme on non-GTK applications" and write a comment to the gtkrc file when it is used. if the user tries to check this box and grdb is not in $PATH, complain with an error dialog and desleect it. this checkbox will be deselected by default, unless the comment acknowledging previous grdb use is found in an fgrep of ~/gtkrc +-clean up code. +-fix issue with unused lib dependencies -- 2.39.2