pidgin/gtkconv-theme.c

changeset 32710
e07993a28f20
parent 32639
ed0e39d65ddc
child 32725
b8c479aec53b
equal deleted inserted replaced
32056:5ecbc7cf4ee1 32710:e07993a28f20
1 /*
2 * Conversation Themes for Pidgin
3 *
4 * Pidgin 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 */
22
23 #include "gtkconv-theme.h"
24
25 #include "conversation.h"
26 #include "debug.h"
27 #include "prefs.h"
28 #include "xmlnode.h"
29
30 #include "pidgin.h"
31 #include "gtkconv.h"
32 #include "gtkwebview.h"
33
34 #include <stdlib.h>
35 #include <string.h>
36
37 #define PIDGIN_CONV_THEME_GET_PRIVATE(Gobject) \
38 (G_TYPE_INSTANCE_GET_PRIVATE((Gobject), PIDGIN_TYPE_CONV_THEME, PidginConvThemePrivate))
39
40 /******************************************************************************
41 * Structs
42 *****************************************************************************/
43
44 typedef struct {
45 /* current config options */
46 char *variant; /* allowed to be NULL if there are no variants */
47 GList *variants;
48
49 /* Info.plist keys/values */
50 GHashTable *info;
51
52 /* caches */
53 char *template_html;
54 char *header_html;
55 char *footer_html;
56 char *topic_html;
57 char *status_html;
58 char *content_html;
59 char *incoming_content_html;
60 char *outgoing_content_html;
61 char *incoming_next_content_html;
62 char *outgoing_next_content_html;
63 char *incoming_context_html;
64 char *outgoing_context_html;
65 char *incoming_next_context_html;
66 char *outgoing_next_context_html;
67 char *basestyle_css;
68 } PidginConvThemePrivate;
69
70 /******************************************************************************
71 * Enums
72 *****************************************************************************/
73
74 enum {
75 PROP_ZERO = 0,
76 PROP_INFO,
77 PROP_VARIANT,
78 PROP_LAST
79 };
80
81 /******************************************************************************
82 * Globals
83 *****************************************************************************/
84
85 static GObjectClass *parent_class = NULL;
86 #if GLIB_CHECK_VERSION(2,26,0)
87 static GParamSpec *properties[PROP_LAST];
88 #endif
89
90 /******************************************************************************
91 * Helper Functions
92 *****************************************************************************/
93
94 static const GValue *
95 get_key(PidginConvThemePrivate *priv, const char *key, gboolean specific)
96 {
97 GValue *val = NULL;
98
99 /* Try variant-specific key */
100 if (specific && priv->variant) {
101 char *name = g_strdup_printf("%s:%s", key, priv->variant);
102 val = g_hash_table_lookup(priv->info, name);
103 g_free(name);
104 }
105
106 /* Try generic key */
107 if (!val) {
108 val = g_hash_table_lookup(priv->info, key);
109 }
110
111 return val;
112 }
113
114 static const char *
115 get_template_html(PidginConvThemePrivate *priv, const char *dir)
116 {
117 char *file;
118
119 if (priv->template_html)
120 return priv->template_html;
121
122 /* The template path can either come from the theme, or can
123 * be stock Template.html that comes with the plugin */
124 file = g_build_filename(dir, "Contents", "Resources", "Template.html", NULL);
125
126 if (!g_file_test(file, G_FILE_TEST_EXISTS)) {
127 g_free(file);
128 file = g_build_filename(DATADIR, "pidgin", "webkit", "Template.html", NULL);
129 }
130
131 if (!g_file_get_contents(file, &priv->template_html, NULL, NULL)) {
132 purple_debug_error("webkit", "Could not locate a Template.html (%s)\n", file);
133 priv->template_html = g_strdup("");
134 }
135 g_free(file);
136
137 return priv->template_html;
138 }
139
140 static const char *
141 get_basestyle_css(PidginConvThemePrivate *priv, const char *dir)
142 {
143 char *file;
144
145 if (priv->basestyle_css)
146 return priv->basestyle_css;
147
148 file = g_build_filename(dir, "Contents", "Resources", "main.css", NULL);
149 if (!g_file_get_contents(file, &priv->basestyle_css, NULL, NULL))
150 priv->basestyle_css = g_strdup("");
151 g_free(file);
152
153 return priv->basestyle_css;
154 }
155
156 static const char *
157 get_header_html(PidginConvThemePrivate *priv, const char *dir)
158 {
159 char *file;
160
161 if (priv->header_html)
162 return priv->header_html;
163
164 file = g_build_filename(dir, "Contents", "Resources", "Header.html", NULL);
165 if (!g_file_get_contents(file, &priv->header_html, NULL, NULL))
166 priv->header_html = g_strdup("");
167 g_free(file);
168
169 return priv->header_html;
170 }
171
172 static const char *
173 get_footer_html(PidginConvThemePrivate *priv, const char *dir)
174 {
175 char *file;
176
177 if (priv->footer_html)
178 return priv->footer_html;
179
180 file = g_build_filename(dir, "Contents", "Resources", "Footer.html", NULL);
181 if (!g_file_get_contents(file, &priv->footer_html, NULL, NULL))
182 priv->footer_html = g_strdup("");
183 g_free(file);
184
185 return priv->footer_html;
186 }
187
188 static const char *
189 get_topic_html(PidginConvThemePrivate *priv, const char *dir)
190 {
191 char *file;
192
193 if (priv->topic_html)
194 return priv->topic_html;
195
196 file = g_build_filename(dir, "Contents", "Resources", "Topic.html", NULL);
197 if (!g_file_get_contents(file, &priv->topic_html, NULL, NULL)) {
198 purple_debug_info("webkit", "%s could not find Resources/Topic.html\n", dir);
199 priv->topic_html = g_strdup("");
200 }
201 g_free(file);
202
203 return priv->topic_html;
204 }
205
206 static const char *
207 get_content_html(PidginConvThemePrivate *priv, const char *dir)
208 {
209 char *file;
210
211 if (priv->content_html)
212 return priv->content_html;
213
214 file = g_build_filename(dir, "Contents", "Resources", "Content.html", NULL);
215 if (!g_file_get_contents(file, &priv->content_html, NULL, NULL)) {
216 purple_debug_info("webkit", "%s did not have a Content.html\n", dir);
217 priv->content_html = g_strdup("");
218 }
219 g_free(file);
220
221 return priv->content_html;
222 }
223
224 static const char *
225 get_status_html(PidginConvThemePrivate *priv, const char *dir)
226 {
227 char *file;
228
229 if (priv->status_html)
230 return priv->status_html;
231
232 file = g_build_filename(dir, "Contents", "Resources", "Status.html", NULL);
233 if (!g_file_get_contents(file, &priv->status_html, NULL, NULL)) {
234 purple_debug_info("webkit", "%s could not find Resources/Status.html\n", dir);
235 priv->status_html = g_strdup(get_content_html(priv, dir));
236 }
237 g_free(file);
238
239 return priv->status_html;
240 }
241
242 static const char *
243 get_incoming_content_html(PidginConvThemePrivate *priv, const char *dir)
244 {
245 char *file;
246
247 if (priv->incoming_content_html)
248 return priv->incoming_content_html;
249
250 file = g_build_filename(dir, "Contents", "Resources", "Incoming", "Content.html", NULL);
251 if (!g_file_get_contents(file, &priv->incoming_content_html, NULL, NULL)) {
252 purple_debug_info("webkit", "%s did not have a Incoming/Content.html\n", dir);
253 priv->incoming_content_html = g_strdup(get_content_html(priv, dir));
254 }
255 g_free(file);
256
257 return priv->incoming_content_html;
258 }
259
260 static const char *
261 get_incoming_next_content_html(PidginConvThemePrivate *priv, const char *dir)
262 {
263 char *file;
264
265 if (priv->incoming_next_content_html)
266 return priv->incoming_next_content_html;
267
268 file = g_build_filename(dir, "Contents", "Resources", "Incoming", "NextContent.html", NULL);
269 if (!g_file_get_contents(file, &priv->incoming_next_content_html, NULL, NULL)) {
270 priv->incoming_next_content_html = g_strdup(get_incoming_content_html(priv, dir));
271 }
272 g_free(file);
273
274 return priv->incoming_next_content_html;
275 }
276
277 static const char *
278 get_incoming_context_html(PidginConvThemePrivate *priv, const char *dir)
279 {
280 char *file;
281
282 if (priv->incoming_context_html)
283 return priv->incoming_context_html;
284
285 file = g_build_filename(dir, "Contents", "Resources", "Incoming", "Context.html", NULL);
286 if (!g_file_get_contents(file, &priv->incoming_context_html, NULL, NULL)) {
287 purple_debug_info("webkit", "%s did not have a Incoming/Context.html\n", dir);
288 priv->incoming_context_html = g_strdup(get_incoming_content_html(priv, dir));
289 }
290 g_free(file);
291
292 return priv->incoming_context_html;
293 }
294
295 static const char *
296 get_incoming_next_context_html(PidginConvThemePrivate *priv, const char *dir)
297 {
298 char *file;
299
300 if (priv->incoming_next_context_html)
301 return priv->incoming_next_context_html;
302
303 file = g_build_filename(dir, "Contents", "Resources", "Incoming", "NextContext.html", NULL);
304 if (!g_file_get_contents(file, &priv->incoming_next_context_html, NULL, NULL)) {
305 priv->incoming_next_context_html = g_strdup(get_incoming_context_html(priv, dir));
306 }
307 g_free(file);
308
309 return priv->incoming_next_context_html;
310 }
311
312 static const char *
313 get_outgoing_content_html(PidginConvThemePrivate *priv, const char *dir)
314 {
315 char *file;
316
317 if (priv->outgoing_content_html)
318 return priv->outgoing_content_html;
319
320 file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "Content.html", NULL);
321 if (!g_file_get_contents(file, &priv->outgoing_content_html, NULL, NULL)) {
322 priv->outgoing_content_html = g_strdup(get_incoming_content_html(priv, dir));
323 }
324 g_free(file);
325
326 return priv->outgoing_content_html;
327 }
328
329 static const char *
330 get_outgoing_next_content_html(PidginConvThemePrivate *priv, const char *dir)
331 {
332 char *file;
333
334 if (priv->outgoing_next_content_html)
335 return priv->outgoing_next_content_html;
336
337 file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "NextContent.html", NULL);
338 if (!g_file_get_contents(file, &priv->outgoing_next_content_html, NULL, NULL)) {
339 priv->outgoing_next_content_html = g_strdup(get_outgoing_content_html(priv, dir));
340 }
341
342 return priv->outgoing_next_content_html;
343 }
344
345 static const char *
346 get_outgoing_context_html(PidginConvThemePrivate *priv, const char *dir)
347 {
348 char *file;
349
350 if (priv->outgoing_context_html)
351 return priv->outgoing_context_html;
352
353 file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "Context.html", NULL);
354 if (!g_file_get_contents(file, &priv->outgoing_context_html, NULL, NULL)) {
355 priv->outgoing_context_html = g_strdup(get_incoming_context_html(priv, dir));
356 }
357 g_free(file);
358
359 return priv->outgoing_context_html;
360 }
361
362 static const char *
363 get_outgoing_next_context_html(PidginConvThemePrivate *priv, const char *dir)
364 {
365 char *file;
366
367 if (priv->outgoing_next_context_html)
368 return priv->outgoing_next_context_html;
369
370 file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "NextContext.html", NULL);
371 if (!g_file_get_contents(file, &priv->outgoing_next_context_html, NULL, NULL)) {
372 priv->outgoing_next_context_html = g_strdup(get_outgoing_context_html(priv, dir));
373 }
374
375 return priv->outgoing_next_context_html;
376 }
377
378 static void
379 _set_variant(PidginConvTheme *theme, const char *variant)
380 {
381 PidginConvThemePrivate *priv;
382 const GValue *val;
383 char *prefname;
384
385 g_return_if_fail(theme != NULL);
386 g_return_if_fail(variant != NULL);
387
388 priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
389
390 g_free(priv->variant);
391 priv->variant = g_strdup(variant);
392
393 val = get_key(priv, "CFBundleIdentifier", FALSE);
394 prefname = g_strdup_printf(PIDGIN_PREFS_ROOT "/conversations/themes/%s/variant",
395 g_value_get_string(val));
396 purple_prefs_set_string(prefname, variant);
397 g_free(prefname);
398 }
399
400 /******************************************************************************
401 * GObject Stuff
402 *****************************************************************************/
403
404 static void
405 pidgin_conv_theme_get_property(GObject *obj, guint param_id, GValue *value,
406 GParamSpec *psec)
407 {
408 PidginConvTheme *theme = PIDGIN_CONV_THEME(obj);
409
410 switch (param_id) {
411 case PROP_INFO:
412 g_value_set_boxed(value, (gpointer)pidgin_conversation_theme_get_info(theme));
413 break;
414
415 case PROP_VARIANT:
416 g_value_set_string(value, pidgin_conversation_theme_get_variant(theme));
417 break;
418
419 default:
420 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec);
421 break;
422 }
423 }
424
425 static void
426 pidgin_conv_theme_set_property(GObject *obj, guint param_id, const GValue *value,
427 GParamSpec *psec)
428 {
429 PidginConvTheme *theme = PIDGIN_CONV_THEME(obj);
430
431 switch (param_id) {
432 case PROP_INFO:
433 pidgin_conversation_theme_set_info(theme, g_value_get_boxed(value));
434 break;
435
436 case PROP_VARIANT:
437 _set_variant(theme, g_value_get_string(value));
438 break;
439
440 default:
441 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec);
442 break;
443 }
444 }
445
446 static void
447 pidgin_conv_theme_init(GTypeInstance *instance,
448 gpointer klass)
449 {
450 PidginConvThemePrivate *priv;
451
452 priv = PIDGIN_CONV_THEME_GET_PRIVATE(instance);
453 }
454
455 static void
456 pidgin_conv_theme_finalize(GObject *obj)
457 {
458 PidginConvThemePrivate *priv;
459 GList *list;
460
461 priv = PIDGIN_CONV_THEME_GET_PRIVATE(obj);
462
463 g_free(priv->template_html);
464 g_free(priv->header_html);
465 g_free(priv->footer_html);
466 g_free(priv->topic_html);
467 g_free(priv->status_html);
468 g_free(priv->content_html);
469 g_free(priv->incoming_content_html);
470 g_free(priv->outgoing_content_html);
471 g_free(priv->incoming_next_content_html);
472 g_free(priv->outgoing_next_content_html);
473 g_free(priv->incoming_context_html);
474 g_free(priv->outgoing_context_html);
475 g_free(priv->incoming_next_context_html);
476 g_free(priv->outgoing_next_context_html);
477 g_free(priv->basestyle_css);
478
479 if (priv->info)
480 g_hash_table_destroy(priv->info);
481
482 list = priv->variants;
483 while (list) {
484 g_free(list->data);
485 list = g_list_delete_link(list, list);
486 }
487 g_free(priv->variant);
488
489 parent_class->finalize(obj);
490 }
491
492 static void
493 pidgin_conv_theme_class_init(PidginConvThemeClass *klass)
494 {
495 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
496 GParamSpec *pspec;
497
498 parent_class = g_type_class_peek_parent(klass);
499
500 g_type_class_add_private(klass, sizeof(PidginConvThemePrivate));
501
502 obj_class->get_property = pidgin_conv_theme_get_property;
503 obj_class->set_property = pidgin_conv_theme_set_property;
504 obj_class->finalize = pidgin_conv_theme_finalize;
505
506 /* INFO */
507 pspec = g_param_spec_boxed("info", "Info",
508 "The information about this theme",
509 G_TYPE_HASH_TABLE,
510 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
511 g_object_class_install_property(obj_class, PROP_INFO, pspec);
512 #if GLIB_CHECK_VERSION(2,26,0)
513 properties[PROP_INFO] = pspec;
514 #endif
515
516 /* VARIANT */
517 pspec = g_param_spec_string("variant", "Variant",
518 "The current variant for this theme",
519 NULL, G_PARAM_READWRITE);
520 g_object_class_install_property(obj_class, PROP_VARIANT, pspec);
521 #if GLIB_CHECK_VERSION(2,26,0)
522 properties[PROP_VARIANT] = pspec;
523 #endif
524 }
525
526 GType
527 pidgin_conversation_theme_get_type(void)
528 {
529 static GType type = 0;
530 if (type == 0) {
531 static const GTypeInfo info = {
532 sizeof(PidginConvThemeClass),
533 NULL, /* base_init */
534 NULL, /* base_finalize */
535 (GClassInitFunc)pidgin_conv_theme_class_init, /* class_init */
536 NULL, /* class_finalize */
537 NULL, /* class_data */
538 sizeof(PidginConvTheme),
539 0, /* n_preallocs */
540 pidgin_conv_theme_init, /* instance_init */
541 NULL, /* value table */
542 };
543 type = g_type_register_static(PURPLE_TYPE_THEME,
544 "PidginConvTheme", &info, 0);
545 }
546 return type;
547 }
548
549 /*****************************************************************************
550 * Public API functions
551 *****************************************************************************/
552
553 const GHashTable *
554 pidgin_conversation_theme_get_info(const PidginConvTheme *theme)
555 {
556 PidginConvThemePrivate *priv;
557
558 g_return_val_if_fail(theme != NULL, NULL);
559
560 priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
561 return priv->info;
562 }
563
564 void
565 pidgin_conversation_theme_set_info(PidginConvTheme *theme, GHashTable *info)
566 {
567 PidginConvThemePrivate *priv;
568
569 g_return_if_fail(theme != NULL);
570
571 priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
572
573 if (priv->info)
574 g_hash_table_destroy(priv->info);
575
576 priv->info = info;
577 }
578
579 const GValue *
580 pidgin_conversation_theme_lookup(PidginConvTheme *theme, const char *key, gboolean specific)
581 {
582 PidginConvThemePrivate *priv;
583
584 g_return_val_if_fail(theme != NULL, NULL);
585
586 priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
587
588 return get_key(priv, key, specific);
589 }
590
591 const char *
592 pidgin_conversation_theme_get_template(PidginConvTheme *theme, PidginConvThemeTemplateType type)
593 {
594 PidginConvThemePrivate *priv;
595 const char *dir;
596 const char *html;
597
598 g_return_val_if_fail(theme != NULL, NULL);
599
600 priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
601 dir = purple_theme_get_dir(PURPLE_THEME(theme));
602
603 switch (type) {
604 case PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN:
605 html = get_template_html(priv, dir);
606 break;
607 case PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER:
608 html = get_header_html(priv, dir);
609 break;
610 case PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER:
611 html = get_footer_html(priv, dir);
612 break;
613 case PIDGIN_CONVERSATION_THEME_TEMPLATE_TOPIC:
614 html = get_topic_html(priv, dir);
615 break;
616 case PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS:
617 html = get_status_html(priv, dir);
618 break;
619 case PIDGIN_CONVERSATION_THEME_TEMPLATE_CONTENT:
620 html = get_content_html(priv, dir);
621 break;
622 case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT:
623 html = get_incoming_content_html(priv, dir);
624 break;
625 case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT:
626 html = get_incoming_next_content_html(priv, dir);
627 break;
628 case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTEXT:
629 html = get_incoming_context_html(priv, dir);
630 break;
631 case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTEXT:
632 html = get_incoming_next_context_html(priv, dir);
633 break;
634 case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT:
635 html = get_outgoing_content_html(priv, dir);
636 break;
637 case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT:
638 html = get_outgoing_next_content_html(priv, dir);
639 break;
640 case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTEXT:
641 html = get_outgoing_context_html(priv, dir);
642 break;
643 case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTEXT:
644 html = get_outgoing_next_context_html(priv, dir);
645 break;
646 case PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS:
647 html = get_basestyle_css(priv, dir);
648 break;
649 default:
650 purple_debug_error("gtkconv-theme",
651 "Requested invalid template type (%d) for theme %s.\n",
652 type, purple_theme_get_name(PURPLE_THEME(theme)));
653 html = NULL;
654 }
655
656 return html;
657 }
658
659 void
660 pidgin_conversation_theme_add_variant(PidginConvTheme *theme, char *variant)
661 {
662 PidginConvThemePrivate *priv;
663
664 g_return_if_fail(theme != NULL);
665 g_return_if_fail(variant != NULL);
666
667 priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
668
669 priv->variants = g_list_prepend(priv->variants, variant);
670 }
671
672 const char *
673 pidgin_conversation_theme_get_variant(PidginConvTheme *theme)
674 {
675 PidginConvThemePrivate *priv;
676
677 g_return_val_if_fail(theme != NULL, NULL);
678
679 priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
680
681 return priv->variant;
682 }
683
684 void
685 pidgin_conversation_theme_set_variant(PidginConvTheme *theme, const char *variant)
686 {
687 _set_variant(theme, variant);
688 #if GLIB_CHECK_VERSION(2,26,0)
689 g_object_notify_by_pspec(G_OBJECT(theme), properties[PROP_VARIANT]);
690 #else
691 g_object_notify(G_OBJECT(theme), "variant");
692 #endif
693 }
694
695 const GList *
696 pidgin_conversation_theme_get_variants(PidginConvTheme *theme)
697 {
698 PidginConvThemePrivate *priv;
699
700 g_return_val_if_fail(theme != NULL, NULL);
701
702 priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
703
704 return priv->variants;
705 }
706
707 char *
708 pidgin_conversation_theme_get_template_path(PidginConvTheme *theme)
709 {
710 const char *dir;
711 char *filename;
712
713 g_return_val_if_fail(theme != NULL, NULL);
714
715 dir = purple_theme_get_dir(PURPLE_THEME(theme));
716 filename = g_build_filename(dir, "Contents", "Resources", "Template.html", NULL);
717
718 if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
719 g_free(filename);
720 filename = g_build_filename(DATADIR, "pidgin", "webkit", "Template.html", NULL);
721 }
722
723 return filename;
724 }
725
726 char *
727 pidgin_conversation_theme_get_css_path(PidginConvTheme *theme)
728 {
729 PidginConvThemePrivate *priv;
730 const char *dir;
731
732 g_return_val_if_fail(theme != NULL, NULL);
733
734 priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme);
735
736 dir = purple_theme_get_dir(PURPLE_THEME(theme));
737 if (!priv->variant) {
738 return g_build_filename(dir, "Contents", "Resources", "main.css", NULL);
739 } else {
740 char *file = g_strdup_printf("%s.css", priv->variant);
741 char *ret = g_build_filename(dir, "Contents", "Resources", "Variants", file, NULL);
742 g_free(file);
743 return ret;
744 }
745 }
746

mercurial