chiark / gitweb /
use GtkStyles everywhere instead of explicit colors. faster.
[disorder] / disobedience / settings.c
1 /*
2  * This file is part of Disobedience
3  * Copyright (C) 2007 Richard Kettlewell
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20 /** @file disobedience/settings.c
21  * @brief Disobedience settings
22  *
23  * Originally I attempted to use a built-in rc file to configure
24  * Disobedience's colors.  This is quite convenient but fails in the
25  * face of themes, as the theme settings override the application
26  * ones.
27  *
28  * This file therefore collects all the colors of the Disobedience UI
29  * and (in time) will have a configuration dialog too.
30  */
31
32 #include "disobedience.h"
33 #include "inputline.h"
34 #include "split.h"
35 #include <sys/stat.h>
36
37 /** @brief HTML displayer */
38 const char *browser = BROWSER;
39
40 void save_settings(void) {
41   char *dir, *path, *tmp;
42   FILE *fp = 0;
43
44   byte_xasprintf(&dir, "%s/.disorder", getenv("HOME"));
45   byte_xasprintf(&path, "%s/disobedience", dir);
46   byte_xasprintf(&tmp, "%s.tmp", path);
47   mkdir(dir, 02700);                    /* make sure directory exists */
48   if(!(fp = fopen(tmp, "w"))) {
49     fpopup_msg(GTK_MESSAGE_ERROR, "error opening %s: %s",
50                tmp, strerror(errno));
51     goto done;
52   }
53   /* TODO */
54   if(fclose(fp) < 0) {
55     fpopup_msg(GTK_MESSAGE_ERROR, "error writing to %s: %s",
56                tmp, strerror(errno));
57     fp = 0;
58     goto done;
59   }
60   fp = 0;
61   if(rename(tmp, path) < 0)
62     fpopup_msg(GTK_MESSAGE_ERROR, "error renaming %s to %s: %s",
63                tmp, path, strerror(errno));
64 done:
65   if(fp)
66     fclose(fp);
67 }
68
69 static inline unsigned clamp(unsigned n) {
70   return n > 0xFFFF ? 0xFFFF : n;
71 }
72
73 void load_settings(void) {
74   char *path, *line;
75   FILE *fp;
76   char **vec;
77   int nvec;
78
79   byte_xasprintf(&path, "%s/.disorder/disobedience", getenv("HOME"));
80   if(!(fp = fopen(path, "r"))) {
81     if(errno != ENOENT)
82       fpopup_msg(GTK_MESSAGE_ERROR, "error opening %s: %s",
83                  path, strerror(errno));
84   } else {
85     while(!inputline(path, fp, &line, '\n')) {
86       if(!(vec = split(line, &nvec, SPLIT_COMMENTS|SPLIT_QUOTES, 0, 0))
87          || !nvec)
88         continue;
89       if(!strcmp(vec[0], "color")) {
90         if(nvec != 5) {
91           error(0, "%s: malformed '%s' command", path, vec[0]);
92           continue;
93         }
94         /* TODO */
95       } else
96         /* mention errors but otherwise ignore them */
97         error(0, "%s: unknown command '%s'", path, vec[0]);
98     }
99     if(ferror(fp)) {
100       fpopup_msg(GTK_MESSAGE_ERROR, "error reading %s: %s",
101                  path, strerror(errno));
102       fclose(fp);
103     }
104   }
105 }
106
107 /** @brief Callback used by set_tool_colors() */
108 static void set_tool_colors_callback(GtkWidget *w,
109                                      gpointer attribute((unused)) data) {
110   set_tool_colors(w);
111 }
112
113 /** @brief Recursively set tool widget colors */
114 void set_tool_colors(GtkWidget *w) {
115   GtkWidget *child;
116
117   gtk_widget_set_style(w, tool_style);
118   if(GTK_IS_CONTAINER(w))
119     gtk_container_foreach(GTK_CONTAINER(w), set_tool_colors_callback, 0);
120   if(GTK_IS_MENU_ITEM(w)
121      && (child = gtk_menu_item_get_submenu(GTK_MENU_ITEM(w))))
122     set_tool_colors(child);
123 }
124
125 /** @brief Default style for layouts */
126 GtkStyle *layout_style;
127
128 /** @brief Title-row style for layouts */
129 GtkStyle *title_style;
130
131 /** @brief Even-row style for layouts */
132 GtkStyle *even_style;
133
134 /** @brief Odd-row style for layouts */
135 GtkStyle *odd_style;
136
137 /** @brief Active-row style for layouts */
138 GtkStyle *active_style;
139
140 /** @brief Style for tools */
141 GtkStyle *tool_style;
142
143 /** @brief Style for search results */
144 GtkStyle *search_style;
145
146 /** @brief Style for drag targets */
147 GtkStyle *drag_style;
148
149 /** @brief Initialize styles */
150 void init_styles(void) {
151   layout_style = gtk_style_new();
152   title_style = gtk_style_new();
153   even_style = gtk_style_new();
154   odd_style = gtk_style_new();
155   active_style = gtk_style_new();
156   search_style = gtk_style_new();
157   tool_style = gtk_style_new();
158   drag_style = gtk_style_new();
159
160   /* Style defaults */
161     
162   /* Layouts are basically black on white */
163   layout_style->bg[GTK_STATE_NORMAL] = layout_style->white;
164   layout_style->fg[GTK_STATE_NORMAL] = layout_style->black;
165     
166   /* Title row is inverted */
167   title_style->bg[GTK_STATE_NORMAL] = layout_style->fg[GTK_STATE_NORMAL];
168   title_style->fg[GTK_STATE_NORMAL] = layout_style->bg[GTK_STATE_NORMAL];
169
170   /* Active row is pastel green */
171   active_style->bg[GTK_STATE_NORMAL].red = 0xE000;
172   active_style->bg[GTK_STATE_NORMAL].green = 0xFFFF;
173   active_style->bg[GTK_STATE_NORMAL].blue = 0xE000;
174   active_style->fg[GTK_STATE_NORMAL] = layout_style->fg[GTK_STATE_NORMAL];
175
176   /* Even rows are pastel red */
177   even_style->bg[GTK_STATE_NORMAL].red = 0xFFFF;
178   even_style->bg[GTK_STATE_NORMAL].green = 0xEC00;
179   even_style->bg[GTK_STATE_NORMAL].blue = 0xEC00;
180   even_style->fg[GTK_STATE_NORMAL] = layout_style->fg[GTK_STATE_NORMAL];
181
182   /* Odd rows match the underlying layout */
183   odd_style->bg[GTK_STATE_NORMAL] = layout_style->bg[GTK_STATE_NORMAL];
184   odd_style->fg[GTK_STATE_NORMAL] = layout_style->fg[GTK_STATE_NORMAL];
185
186   /* Search results have a yellow background */
187   search_style->fg[GTK_STATE_NORMAL] = layout_style->fg[GTK_STATE_NORMAL];
188   search_style->bg[GTK_STATE_NORMAL].red = 0xFFFF;
189   search_style->bg[GTK_STATE_NORMAL].green = 0xFFFF;
190   search_style->bg[GTK_STATE_NORMAL].blue = 0x0000;
191
192   /* Drag targets are grey */
193   drag_style->bg[GTK_STATE_NORMAL].red = 0x6666;
194   drag_style->bg[GTK_STATE_NORMAL].green = 0x6666;
195   drag_style->bg[GTK_STATE_NORMAL].blue = 0x6666;
196   
197   /* Tools we leave at GTK+ defaults */
198 }
199
200 /*
201 Local Variables:
202 c-basic-offset:2
203 comment-column:40
204 fill-column:79
205 indent-tabs-mode:nil
206 End:
207 */