comparison pidgin/gtkthemes.c @ 15374:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children d75099d2567e
comparison
equal deleted inserted replaced
15373:f79e0f4df793 15374:5fe8042783c1
1 /*
2 * Themes for Gaim
3 *
4 * Gaim is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23 #include "internal.h"
24 #include "gtkgaim.h"
25
26 #include "conversation.h"
27 #include "debug.h"
28 #include "prpl.h"
29 #include "util.h"
30
31 #include "gtkconv.h"
32 #include "gtkdialogs.h"
33 #include "gtkimhtml.h"
34 #include "gtkthemes.h"
35
36 GSList *smiley_themes = NULL;
37 struct smiley_theme *current_smiley_theme;
38
39 gboolean gaim_gtkthemes_smileys_disabled()
40 {
41 if (!current_smiley_theme)
42 return 1;
43
44 return strcmp(current_smiley_theme->name, "none") == 0;
45 }
46
47 void gaim_gtkthemes_smiley_themeize(GtkWidget *imhtml)
48 {
49 struct smiley_list *list;
50 if (!current_smiley_theme)
51 return;
52
53 gtk_imhtml_remove_smileys(GTK_IMHTML(imhtml));
54 list = current_smiley_theme->list;
55 while (list) {
56 char *sml = !strcmp(list->sml, "default") ? NULL : list->sml;
57 GSList *icons = list->smileys;
58 while (icons) {
59 gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), sml, icons->data);
60 icons = icons->next;
61 }
62 list = list->next;
63 }
64 }
65
66 void gaim_gtkthemes_load_smiley_theme(const char *file, gboolean load)
67 {
68 FILE *f = g_fopen(file, "r");
69 char buf[256];
70 char *i;
71 struct smiley_theme *theme=NULL;
72 struct smiley_list *list = NULL;
73 GSList *lst = smiley_themes;
74 char *dirname;
75 gboolean new_theme = FALSE;
76
77 if (!f)
78 return;
79
80 while (lst) {
81 struct smiley_theme *thm = lst->data;
82 if (!strcmp(thm->path, file)) {
83 theme = thm;
84 break;
85 }
86 lst = lst->next;
87 }
88
89 if (!theme) {
90 new_theme = TRUE;
91 theme = g_new0(struct smiley_theme, 1);
92 theme->path = g_strdup(file);
93 } else if (theme == current_smiley_theme) {
94 /* Don't reload the theme if it is already loaded */
95 fclose(f);
96 return;
97 }
98
99 dirname = g_path_get_dirname(file);
100
101 while (!feof(f)) {
102 if (!fgets(buf, sizeof(buf), f)) {
103 break;
104 }
105
106 if (buf[0] == '#' || buf[0] == '\0')
107 continue;
108
109 i = buf;
110 while (isspace(*i))
111 i++;
112
113 if (*i == '[' && strchr(i, ']') && load) {
114 struct smiley_list *child = g_new0(struct smiley_list, 1);
115 child->sml = g_strndup(i+1, strchr(i, ']') - i - 1);
116 if (theme->list)
117 list->next = child;
118 else
119 theme->list = child;
120 list = child;
121 } else if (!g_ascii_strncasecmp(i, "Name=", strlen("Name="))) {
122 int len;
123 g_free(theme->name);
124 theme->name = g_strdup(i+ strlen("Name="));
125 len = strlen(theme->name);
126 theme->name[len-1] = 0;
127 if(len > 2 && theme->name[len-2] == '\r')
128 theme->name[len-2] = 0;
129 } else if (!g_ascii_strncasecmp(i, "Description=", strlen("Description="))) {
130 g_free(theme->desc);
131 theme->desc = g_strdup(i + strlen("Description="));
132 theme->desc[strlen(theme->desc)-1] = 0;
133 } else if (!g_ascii_strncasecmp(i, "Icon=", strlen("Icon="))) {
134 g_free(theme->icon);
135 theme->icon = g_build_filename(dirname, i + strlen("Icon="), NULL);
136 theme->icon[strlen(theme->icon)-1] = 0;
137 } else if (!g_ascii_strncasecmp(i, "Author=", strlen("Author="))) {
138 g_free(theme->author);
139 theme->author = g_strdup(i + strlen("Author="));
140 theme->author[strlen(theme->author)-1] = 0;
141 } else if (load && list) {
142 gboolean hidden = FALSE;
143 char *sfile = NULL;
144
145 if (*i == '!' && *(i + 1) == ' ') {
146 hidden = TRUE;
147 i = i + 2;
148 }
149 while (*i) {
150 char l[64];
151 int li = 0;
152 while (!isspace(*i) && li < sizeof(l) - 1) {
153 if (*i == '\\' && *(i+1) != '\0' && *(i+1) != '\n' && *(i+1) != '\r')
154 i++;
155 l[li++] = *(i++);
156 }
157 if (!sfile) {
158 l[li] = 0;
159 sfile = g_build_filename(dirname, l, NULL);
160 } else {
161 GtkIMHtmlSmiley *smiley = g_new0(GtkIMHtmlSmiley, 1);
162 l[li] = 0;
163 smiley->file = sfile;
164 smiley->smile = g_strdup(l);
165 smiley->hidden = hidden;
166 list->smileys = g_slist_append(list->smileys, smiley);
167 }
168 while (isspace(*i))
169 i++;
170
171 }
172 }
173 }
174
175 g_free(dirname);
176 fclose(f);
177
178 if (!theme->name || !theme->desc || !theme->author) {
179 GSList *already_freed = NULL;
180 struct smiley_list *wer = theme->list, *wer2;
181
182 gaim_debug_error("gtkthemes", "Invalid file format, not loading smiley theme from '%s'\n", file);
183
184 while (wer) {
185 while (wer->smileys) {
186 GtkIMHtmlSmiley *uio = wer->smileys->data;
187 if (uio->icon)
188 g_object_unref(uio->icon);
189 if (!g_slist_find(already_freed, uio->file)) {
190 g_free(uio->file);
191 already_freed = g_slist_append(already_freed, uio->file);
192 }
193 g_free(uio->smile);
194 g_free(uio);
195 wer->smileys = g_slist_remove(wer->smileys, uio);
196 }
197 wer2 = wer->next;
198 g_free(wer->sml);
199 g_free(wer);
200 wer = wer2;
201 }
202 theme->list = NULL;
203 g_slist_free(already_freed);
204
205 g_free(theme->name);
206 g_free(theme->desc);
207 g_free(theme->author);
208 g_free(theme->icon);
209 g_free(theme->path);
210 g_free(theme);
211
212 return;
213 }
214
215 if (new_theme) {
216 smiley_themes = g_slist_append(smiley_themes, theme);
217 }
218
219 if (load) {
220 GList *cnv;
221
222 if (current_smiley_theme) {
223 GSList *already_freed = NULL;
224 struct smiley_list *wer = current_smiley_theme->list, *wer2;
225 while (wer) {
226 while (wer->smileys) {
227 GtkIMHtmlSmiley *uio = wer->smileys->data;
228 if (uio->icon)
229 g_object_unref(uio->icon);
230 if (!g_slist_find(already_freed, uio->file)) {
231 g_free(uio->file);
232 already_freed = g_slist_append(already_freed, uio->file);
233 }
234 g_free(uio->smile);
235 g_free(uio);
236 wer->smileys = g_slist_remove(wer->smileys, uio);
237 }
238 wer2 = wer->next;
239 g_free(wer->sml);
240 g_free(wer);
241 wer = wer2;
242 }
243 current_smiley_theme->list = NULL;
244 g_slist_free(already_freed);
245 }
246 current_smiley_theme = theme;
247
248 for (cnv = gaim_get_conversations(); cnv != NULL; cnv = cnv->next) {
249 GaimConversation *conv = cnv->data;
250
251 if (GAIM_IS_GTK_CONVERSATION(conv)) {
252 gaim_gtkthemes_smiley_themeize(GAIM_GTK_CONVERSATION(conv)->imhtml);
253 gaim_gtkthemes_smiley_themeize(GAIM_GTK_CONVERSATION(conv)->entry);
254 }
255 }
256 }
257 }
258
259 void gaim_gtkthemes_smiley_theme_probe()
260 {
261 GDir *dir;
262 const gchar *file;
263 gchar *path;
264 int l;
265
266 char* probedirs[3];
267 probedirs[0] = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", NULL);
268 probedirs[1] = g_build_filename(gaim_user_dir(), "smileys", NULL);
269 probedirs[2] = 0;
270 for (l=0; probedirs[l]; l++) {
271 dir = g_dir_open(probedirs[l], 0, NULL);
272 if (dir) {
273 while ((file = g_dir_read_name(dir))) {
274 path = g_build_filename(probedirs[l], file, "theme", NULL);
275
276 /* Here we check to see that the theme has proper syntax.
277 * We set the second argument to FALSE so that it doesn't load
278 * the theme yet.
279 */
280 gaim_gtkthemes_load_smiley_theme(path, FALSE);
281 g_free(path);
282 }
283 g_dir_close(dir);
284 } else if (l == 1) {
285 g_mkdir(probedirs[l], S_IRUSR | S_IWUSR | S_IXUSR);
286 }
287 g_free(probedirs[l]);
288 }
289 }
290
291 GSList *gaim_gtkthemes_get_proto_smileys(const char *id) {
292 GaimPlugin *proto;
293 struct smiley_list *list, *def;
294
295 if ((current_smiley_theme == NULL) || (current_smiley_theme->list == NULL))
296 return NULL;
297
298 def = list = current_smiley_theme->list;
299
300 if (id == NULL)
301 return def->smileys;
302
303 proto = gaim_find_prpl(id);
304
305 while (list) {
306 if (!strcmp(list->sml, "default"))
307 def = list;
308 else if (proto && !strcmp(proto->info->name, list->sml))
309 break;
310
311 list = list->next;
312 }
313
314 return list ? list->smileys : def->smileys;
315 }
316
317 void gaim_gtkthemes_init()
318 {
319 GSList *l;
320 const char *current_theme =
321 gaim_prefs_get_string("/gaim/gtk/smileys/theme");
322
323 gaim_gtkthemes_smiley_theme_probe();
324
325 for (l = smiley_themes; l; l = l->next) {
326 struct smiley_theme *smile = l->data;
327 if (smile->name && strcmp(current_theme, smile->name) == 0) {
328 gaim_gtkthemes_load_smiley_theme(smile->path, TRUE);
329 break;
330 }
331 }
332
333 /* If we still don't have a smiley theme, choose the first one */
334 if (!current_smiley_theme && smiley_themes) {
335 struct smiley_theme *smile = smiley_themes->data;
336 gaim_gtkthemes_load_smiley_theme(smile->path, TRUE);
337 }
338
339 }