Mercurial > pidgin
annotate src/gtkthemes.c @ 13133:541486fde12b
[gaim-migrate @ 15495]
SF Patch #1419139 from Christophe Chapuis (tofe2tofe)
"Tests have been added to check if the '\' character can
be skipped in the theme.
Another test has been added to check there is no buffer
overrun while reading the smiley definition."
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Mon, 06 Feb 2006 07:46:35 +0000 |
parents | fe2cb084ab16 |
children | 0cc7773b1d87 |
rev | line source |
---|---|
10295 | 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. | |
11525 | 7 * |
10295 | 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" | |
11525 | 34 #include "gtkthemes.h" |
10295 | 35 |
36 GSList *smiley_themes = NULL; | |
37 struct smiley_theme *current_smiley_theme; | |
38 | |
11525 | 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) | |
10295 | 48 { |
49 struct smiley_list *list; | |
50 if (!current_smiley_theme) | |
51 return; | |
11525 | 52 |
10295 | 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 | |
11525 | 66 void gaim_gtkthemes_load_smiley_theme(const char *file, gboolean load) |
10295 | 67 { |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10295
diff
changeset
|
68 FILE *f = g_fopen(file, "r"); |
10295 | 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 | |
76 if (!f) | |
77 return; | |
78 | |
79 while (lst) { | |
80 struct smiley_theme *thm = lst->data; | |
81 if (!strcmp(thm->path, file)) { | |
82 theme = thm; | |
83 break; | |
84 } | |
85 lst = lst->next; | |
86 } | |
87 | |
88 if (!theme) { | |
89 theme = g_new0(struct smiley_theme, 1); | |
90 theme->path = g_strdup(file); | |
91 smiley_themes = g_slist_append(smiley_themes, theme); | |
92 } | |
93 | |
94 dirname = g_path_get_dirname(file); | |
95 if (load) { | |
96 if (current_smiley_theme) { | |
97 GSList *already_freed = NULL; | |
98 struct smiley_list *wer = current_smiley_theme->list, *wer2; | |
99 while (wer) { | |
100 while (wer->smileys) { | |
101 GtkIMHtmlSmiley *uio = wer->smileys->data; | |
102 if (uio->icon) | |
103 g_object_unref(uio->icon); | |
104 if (!g_slist_find(already_freed, uio->file)) { | |
105 g_free(uio->file); | |
106 already_freed = g_slist_append(already_freed, uio->file); | |
107 } | |
108 g_free(uio->smile); | |
109 g_free(uio); | |
110 wer->smileys=g_slist_remove(wer->smileys, uio); | |
111 } | |
112 wer2 = wer->next; | |
113 g_free(wer->sml); | |
114 g_free(wer); | |
115 wer = wer2; | |
116 } | |
117 current_smiley_theme->list = NULL; | |
118 g_slist_free(already_freed); | |
119 } | |
120 current_smiley_theme = theme; | |
121 } | |
122 | |
123 | |
124 while (!feof(f)) { | |
125 if (!fgets(buf, sizeof(buf), f)) { | |
126 break; | |
127 } | |
128 | |
129 if (buf[0] == '#' || buf[0] == '\0') | |
130 continue; | |
131 | |
132 i = buf; | |
133 while (isspace(*i)) | |
134 i++; | |
135 | |
136 if (*i == '[' && strchr(i, ']') && load) { | |
137 struct smiley_list *child = g_new0(struct smiley_list, 1); | |
138 child->sml = g_strndup(i+1, strchr(i, ']') - i - 1); | |
139 if (theme->list) | |
140 list->next = child; | |
141 else | |
142 theme->list = child; | |
143 list = child; | |
144 } else if (!g_ascii_strncasecmp(i, "Name=", strlen("Name="))) { | |
145 if(theme->name) | |
146 g_free(theme->name); | |
147 theme->name = g_strdup(i+ strlen("Name=")); | |
148 theme->name[strlen(theme->name)-1] = 0; | |
149 } else if (!g_ascii_strncasecmp(i, "Description=", strlen("Description="))) { | |
150 if(theme->desc) | |
151 g_free(theme->desc); | |
152 theme->desc = g_strdup(i + strlen("Description=")); | |
153 theme->desc[strlen(theme->desc)-1] = 0; | |
154 } else if (!g_ascii_strncasecmp(i, "Icon=", strlen("Icon="))) { | |
155 if(theme->icon) | |
156 g_free(theme->icon); | |
157 theme->icon = g_build_filename(dirname, i + strlen("Icon="), NULL); | |
158 theme->icon[strlen(theme->icon)-1] = 0; | |
159 } else if (!g_ascii_strncasecmp(i, "Author=", strlen("Author="))) { | |
160 if(theme->author) | |
161 g_free(theme->author); | |
162 theme->author = g_strdup(i + strlen("Author=")); | |
163 theme->author[strlen(theme->author)-1] = 0; | |
164 } else if (load && list) { | |
165 gboolean hidden = FALSE; | |
166 char *sfile = NULL; | |
167 | |
168 if (*i == '!' && *(i + 1) == ' ') { | |
169 hidden = TRUE; | |
170 i = i + 2; | |
171 } | |
172 while (*i) { | |
173 char l[64]; | |
174 int li = 0; | |
13133
541486fde12b
[gaim-migrate @ 15495]
Richard Laager <rlaager@wiktel.com>
parents:
12915
diff
changeset
|
175 while (!isspace(*i) && li < sizeof(l) - 1) { |
541486fde12b
[gaim-migrate @ 15495]
Richard Laager <rlaager@wiktel.com>
parents:
12915
diff
changeset
|
176 if (*i == '\\' && *(i+1) != '\0' && *(i+1) != '\n' && *(i+1) != '\r') |
12915
fe2cb084ab16
[gaim-migrate @ 15268]
Richard Laager <rlaager@wiktel.com>
parents:
11557
diff
changeset
|
177 i++; |
10295 | 178 l[li++] = *(i++); |
12915
fe2cb084ab16
[gaim-migrate @ 15268]
Richard Laager <rlaager@wiktel.com>
parents:
11557
diff
changeset
|
179 } |
10295 | 180 if (!sfile) { |
181 l[li] = 0; | |
182 sfile = g_build_filename(dirname, l, NULL); | |
183 } else { | |
184 GtkIMHtmlSmiley *smiley = g_new0(GtkIMHtmlSmiley, 1); | |
185 l[li] = 0; | |
186 smiley->file = sfile; | |
187 smiley->smile = g_strdup(l); | |
188 smiley->hidden = hidden; | |
189 list->smileys = g_slist_append(list->smileys, smiley); | |
190 } | |
191 while (isspace(*i)) | |
192 i++; | |
193 | |
194 } | |
195 } | |
196 } | |
197 | |
198 if (load) { | |
199 GList *cnv; | |
200 | |
201 for (cnv = gaim_get_conversations(); cnv != NULL; cnv = cnv->next) { | |
202 GaimConversation *conv = cnv->data; | |
203 | |
204 if (GAIM_IS_GTK_CONVERSATION(conv)) { | |
11525 | 205 gaim_gtkthemes_smiley_themeize(GAIM_GTK_CONVERSATION(conv)->imhtml); |
206 gaim_gtkthemes_smiley_themeize(GAIM_GTK_CONVERSATION(conv)->entry); | |
10295 | 207 } |
208 } | |
209 } | |
210 | |
211 g_free(dirname); | |
212 fclose(f); | |
213 } | |
214 | |
11525 | 215 void gaim_gtkthemes_smiley_theme_probe() |
10295 | 216 { |
217 GDir *dir; | |
218 const gchar *file; | |
219 gchar *path; | |
220 int l; | |
221 | |
222 char* probedirs[3]; | |
223 probedirs[0] = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", NULL); | |
224 probedirs[1] = g_build_filename(gaim_user_dir(), "smileys", NULL); | |
225 probedirs[2] = 0; | |
226 for (l=0; probedirs[l]; l++) { | |
227 dir = g_dir_open(probedirs[l], 0, NULL); | |
228 if (dir) { | |
229 while ((file = g_dir_read_name(dir))) { | |
230 path = g_build_filename(probedirs[l], file, "theme", NULL); | |
231 | |
232 /* Here we check to see that the theme has proper syntax. | |
233 * We set the second argument to FALSE so that it doesn't load | |
234 * the theme yet. | |
235 */ | |
11525 | 236 gaim_gtkthemes_load_smiley_theme(path, FALSE); |
10295 | 237 g_free(path); |
238 } | |
239 g_dir_close(dir); | |
240 } else if (l == 1) { | |
10589
0f7452b1f777
[gaim-migrate @ 11994]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10295
diff
changeset
|
241 g_mkdir(probedirs[l], S_IRUSR | S_IWUSR | S_IXUSR); |
10295 | 242 } |
243 g_free(probedirs[l]); | |
244 } | |
245 } | |
246 | |
11525 | 247 GSList *gaim_gtkthemes_get_proto_smileys(const char *id) { |
10295 | 248 GaimPlugin *proto; |
249 struct smiley_list *list, *def; | |
250 | |
251 if ((current_smiley_theme == NULL) || (current_smiley_theme->list == NULL)) | |
252 return NULL; | |
253 | |
254 def = list = current_smiley_theme->list; | |
255 | |
256 if (id == NULL) | |
257 return def->smileys; | |
258 | |
259 proto = gaim_find_prpl(id); | |
260 | |
261 while (list) { | |
262 if (!strcmp(list->sml, "default")) | |
263 def = list; | |
264 else if (proto && !strcmp(proto->info->name, list->sml)) | |
265 break; | |
266 | |
267 list = list->next; | |
268 } | |
269 | |
270 return list ? list->smileys : def->smileys; | |
271 } | |
11525 | 272 |
273 void gaim_gtkthemes_init() | |
274 { | |
11557
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
275 GSList *l; |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
276 const char *current_theme = |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
277 gaim_prefs_get_string("/gaim/gtk/smileys/theme"); |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
278 |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
279 gaim_gtkthemes_smiley_theme_probe(); |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
280 |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
281 for (l = smiley_themes; l; l = l->next) { |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
282 struct smiley_theme *smile = l->data; |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
283 if (smile->name && strcmp(current_theme, smile->name) == 0) { |
11525 | 284 gaim_gtkthemes_load_smiley_theme(smile->path, TRUE); |
11557
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
285 break; |
11525 | 286 } |
287 } | |
11557
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
288 |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
289 /* If we still don't have a smiley theme, choose the first one */ |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
290 if (!current_smiley_theme && smiley_themes) { |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
291 struct smiley_theme *smile = smiley_themes->data; |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
292 gaim_gtkthemes_load_smiley_theme(smile->path, TRUE); |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
293 } |
1e7c0773380f
[gaim-migrate @ 13819]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11525
diff
changeset
|
294 |
11525 | 295 } |