pidgin/gtksmiley-theme.c

changeset 35707
2979d2a75df8
parent 35706
6a0bbe6adc4a
child 35708
8903e6402d5b
equal deleted inserted replaced
35706:6a0bbe6adc4a 35707:2979d2a75df8
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
20 */ 20 */
21 21
22 #include "gtksmiley-theme.h" 22 #include "gtksmiley-theme.h"
23 23
24 #include "internal.h"
25 #include "glibcompat.h"
26
24 #include "debug.h" 27 #include "debug.h"
25 28
26 #include <glib/gstdio.h> 29 #include <glib/gstdio.h>
27 30
28 #define PIDGIN_SMILEY_THEME_GET_PRIVATE(obj) \ 31 #define PIDGIN_SMILEY_THEME_GET_PRIVATE(obj) \
29 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PIDGIN_TYPE_SMILEY_THEME, \ 32 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PIDGIN_TYPE_SMILEY_THEME, \
30 PidginSmileyThemePrivate)) 33 PidginSmileyThemePrivate))
31 34
32 #define PIDGIN_SMILEY_THEME_MAX_INDEX_SIZE 102400 35 #define PIDGIN_SMILEY_THEME_MAX_LINES 1024
36 #define PIDGIN_SMILEY_THEME_MAX_TOKENS 1024
33 37
34 typedef struct 38 typedef struct
35 { 39 {
36 gchar *path; 40 gchar *path;
41
42 gchar *name;
43 gchar *desc;
44 gchar *icon;
45 gchar *author;
37 } PidginSmileyThemePrivate; 46 } PidginSmileyThemePrivate;
38 47
39 static GObjectClass *parent_class; 48 static GObjectClass *parent_class;
40 49
41 static gchar **probe_dirs; 50 static gchar **probe_dirs;
42 static GList *smiley_themes = NULL; 51 static GList *smiley_themes = NULL;
52
53 typedef struct
54 {
55 gchar *name;
56 gchar *desc;
57 gchar *icon;
58 gchar *author;
59
60 GList *protocols;
61 } PidginSmileyThemeIndex;
62
63 typedef struct
64 {
65 gchar *name;
66 GList *smileys;
67 } PidginSmileyThemeIndexProtocol;
68
69 typedef struct
70 {
71 gchar *file;
72 gboolean hidden;
73 GList *shortcuts;
74 } PidginSmileyThemeIndexSmiley;
75
76 /*******************************************************************************
77 * Theme index parsing
78 ******************************************************************************/
79
80 static void
81 pidgin_smiley_theme_index_free(PidginSmileyThemeIndex *index)
82 {
83 GList *it, *it2;
84
85 g_return_if_fail(index != NULL);
86
87 g_free(index->name);
88 g_free(index->desc);
89 g_free(index->icon);
90 g_free(index->author);
91
92 for (it = index->protocols; it; it = g_list_next(it)) {
93 PidginSmileyThemeIndexProtocol *proto = it->data;
94
95 g_free(proto->name);
96 for (it2 = proto->smileys; it2; it2 = g_list_next(it2)) {
97 PidginSmileyThemeIndexSmiley *smiley = it2->data;
98
99 g_free(smiley->file);
100 g_list_free_full(smiley->shortcuts, g_free);
101 g_free(smiley);
102 }
103 g_list_free(proto->smileys);
104 g_free(proto);
105 }
106 g_list_free(index->protocols);
107 }
108
109 static PidginSmileyThemeIndex *
110 pidgin_smiley_theme_index_parse(const gchar *index_path, gboolean load_contents)
111 {
112 PidginSmileyThemeIndex *index;
113 PidginSmileyThemeIndexProtocol *proto = NULL;
114 FILE *file;
115 int line_no = 0;
116 gboolean inv_frm = FALSE;
117
118 file = g_fopen(index_path, "r");
119 if (!file) {
120 purple_debug_error("gtksmiley-theme",
121 "Failed to open index file %s", index_path);
122 return NULL;
123 }
124
125 index = g_new0(PidginSmileyThemeIndex, 1);
126
127 while (!feof(file)) {
128 PidginSmileyThemeIndexSmiley *smiley;
129 gchar buff[1024];
130 gchar *line, *eqchr;
131 gchar **split;
132 int i;
133
134 if (++line_no > PIDGIN_SMILEY_THEME_MAX_LINES) {
135 purple_debug_warning("gtksmiley-theme", "file too big");
136 break;
137 }
138
139 if (!fgets(buff, sizeof(buff), file))
140 break;
141
142 /* strip comments */
143 if (buff[0] == '#')
144 continue;
145
146 g_strstrip(buff);
147 if (buff[0] == '\0')
148 continue;
149
150 if (!g_utf8_validate(buff, -1, NULL)) {
151 purple_debug_error("gtksmiley-theme", "%s:%"
152 G_GSIZE_FORMAT " is invalid UTF-8",
153 index_path, line_no);
154 continue;
155 }
156
157 line = buff;
158
159 if (line[0] == '[') {
160 gchar *end;
161
162 if (!load_contents)
163 break;
164 line++;
165 end = strchr(line, ']');
166 if (!end) {
167 inv_frm = TRUE;
168 break;
169 }
170
171 proto = g_new0(PidginSmileyThemeIndexProtocol, 1);
172 proto->name = g_strndup(line, end - line);
173
174 index->protocols =
175 g_list_prepend(index->protocols, proto);
176
177 continue;
178 }
179
180 if ((eqchr = strchr(line, '='))) {
181 *eqchr = '\0';
182 if (g_ascii_strcasecmp(line, "name") == 0) {
183 g_free(index->name);
184 index->name = g_strdup(eqchr + 1);
185 g_strchug(index->name);
186 continue;
187 } else if (g_ascii_strcasecmp(line, "description") == 0) {
188 g_free(index->desc);
189 index->desc = g_strdup(eqchr + 1);
190 g_strchug(index->desc);
191 continue;
192 } else if (g_ascii_strcasecmp(line, "icon") == 0) {
193 g_free(index->icon);
194 index->icon = g_strdup(eqchr + 1);
195 g_strchug(index->icon);
196 continue;
197 } else if (g_ascii_strcasecmp(line, "author") == 0) {
198 g_free(index->author);
199 index->author = g_strdup(eqchr + 1);
200 g_strchug(index->author);
201 continue;
202 }
203 *eqchr = '=';
204 }
205
206 /* parsing section content */
207
208 if (proto == NULL) {
209 inv_frm = FALSE;
210 break;
211 }
212
213 smiley = g_new0(PidginSmileyThemeIndexSmiley, 1);
214 proto->smileys = g_list_prepend(proto->smileys, smiley);
215
216 smiley->hidden = FALSE;
217 if (line[0] == '!') {
218 smiley->hidden = TRUE;
219 line++;
220 }
221
222 split = g_strsplit_set(line, " \t",
223 PIDGIN_SMILEY_THEME_MAX_TOKENS);
224 for (i = 0; split[i]; i++) {
225 gchar *token = split[i];
226
227 if (token[0] == '\0')
228 continue;
229 if (i == PIDGIN_SMILEY_THEME_MAX_TOKENS - 1)
230 break;
231
232 if (!smiley->file) {
233 smiley->file = g_strdup(token);
234 continue;
235 }
236
237 smiley->shortcuts = g_list_prepend(smiley->shortcuts,
238 g_strdup(token));
239 }
240 g_strfreev(split);
241 }
242
243 fclose(file);
244
245 if (inv_frm) {
246 purple_debug_error("gtksmiley-theme", "%s:%" G_GSIZE_FORMAT
247 " invalid format", index_path, line_no);
248 pidgin_smiley_theme_index_free(index);
249 index = NULL;
250 }
251
252 return index;
253 }
43 254
44 /******************************************************************************* 255 /*******************************************************************************
45 * Theme loading 256 * Theme loading
46 ******************************************************************************/ 257 ******************************************************************************/
47 258
48 static void 259 static void
49 pidgin_smiley_theme_load(const gchar *theme_path) 260 pidgin_smiley_theme_load(const gchar *theme_path)
50 { 261 {
51 PidginSmileyTheme *theme; 262 PidginSmileyTheme *theme;
52 PidginSmileyThemePrivate *priv; 263 PidginSmileyThemePrivate *priv;
264 PidginSmileyThemeIndex *index;
53 GList *it; 265 GList *it;
54 gchar *index_path; 266 gchar *index_path;
55 267
56 /* it's not super-efficient, but we don't expect huge amount of 268 /* it's not super-efficient, but we don't expect huge amount of
57 * installed themes */ 269 * installed themes */
69 theme = g_object_new(PIDGIN_TYPE_SMILEY_THEME, NULL); 281 theme = g_object_new(PIDGIN_TYPE_SMILEY_THEME, NULL);
70 priv = PIDGIN_SMILEY_THEME_GET_PRIVATE(theme); 282 priv = PIDGIN_SMILEY_THEME_GET_PRIVATE(theme);
71 283
72 priv->path = g_strdup(theme_path); 284 priv->path = g_strdup(theme_path);
73 285
286 index = pidgin_smiley_theme_index_parse(index_path, FALSE);
287
74 g_free(index_path); 288 g_free(index_path);
75 289
76 purple_debug_fatal("tomo", "loading not implemented"); 290 if (!index->name || index->name[0] == '\0') {
291 purple_debug_warning("gtksmiley-theme",
292 "incomplete theme %s", theme_path);
293 pidgin_smiley_theme_index_free(index);
294 g_object_unref(theme);
295 return;
296 }
297
298 priv->name = g_strdup(index->name);
299 if (index->desc && index->desc[0])
300 priv->desc = g_strdup(index->desc);
301 if (index->icon && index->icon[0])
302 priv->icon = g_strdup(index->icon);
303 if (index->author && index->author[0])
304 priv->author = g_strdup(index->author);
305
306 pidgin_smiley_theme_index_free(index);
307
308 smiley_themes = g_list_append(smiley_themes, theme);
77 } 309 }
78 310
79 static void 311 static void
80 pidgin_smiley_theme_probe(void) 312 pidgin_smiley_theme_probe(void)
81 { 313 {
147 purple_user_dir(), "smileys", NULL); 379 purple_user_dir(), "smileys", NULL);
148 380
149 if (!g_file_test(user_smileys_dir, G_FILE_TEST_IS_DIR)) 381 if (!g_file_test(user_smileys_dir, G_FILE_TEST_IS_DIR))
150 g_mkdir(user_smileys_dir, S_IRUSR | S_IWUSR | S_IXUSR); 382 g_mkdir(user_smileys_dir, S_IRUSR | S_IWUSR | S_IXUSR);
151 383
152 //TODO: remove it 384 /* TODO: load configured theme */
153 pidgin_smiley_theme_probe();
154 } 385 }
155 386
156 void 387 void
157 pidgin_smiley_theme_uninit(void) 388 pidgin_smiley_theme_uninit(void)
158 { 389 {
162 GList * 393 GList *
163 pidgin_smiley_theme_get_all(void) 394 pidgin_smiley_theme_get_all(void)
164 { 395 {
165 pidgin_smiley_theme_probe(); 396 pidgin_smiley_theme_probe();
166 397
167 return NULL; 398 return smiley_themes;
168 } 399 }
169 400
170 /******************************************************************************* 401 /*******************************************************************************
171 * Object stuff 402 * Object stuff
172 ******************************************************************************/ 403 ******************************************************************************/

mercurial