# HG changeset patch # User Sean Egan # Date 1042105309 0 # Node ID 74f65a3d2a1f715d5311ca3004476dad97e5325a # Parent 7103653dd34e535d267ece456398d8150fae9eb6 [gaim-migrate @ 4514] I wanted to get this into cvs before I went to bed. Now proto-specific themes will work. The code's a bit crude at parts and it's not as fast as I'd like, but I can work some more on it tomorrow. Just figured you'd want to get a look at this. 8 penguin points to whoever finds out why gtk_smiley_tree_destroy (commented out right now, causing leakage) segfaults on me now. committer: Tailor Script diff -r 7103653dd34e -r 74f65a3d2a1f src/Makefile.am --- a/src/Makefile.am Thu Jan 09 06:38:09 2003 +0000 +++ b/src/Makefile.am Thu Jan 09 09:41:49 2003 +0000 @@ -42,6 +42,7 @@ session.c \ socket.c \ sound.c \ + themes.c \ util.c \ ui.h diff -r 7103653dd34e -r 74f65a3d2a1f src/aim.c --- a/src/aim.c Thu Jan 09 06:38:09 2003 +0000 +++ b/src/aim.c Thu Jan 09 09:41:49 2003 +0000 @@ -490,6 +490,8 @@ GList *icons = NULL; GdkPixbuf *icon = NULL; + smiley_theme_probe(); + /* use the nice PNG icon for all the windows */ icon = gdk_pixbuf_new_from_file(DATADIR G_DIR_SEPARATOR_S "pixmaps" G_DIR_SEPARATOR_S "gaim.png",NULL); if (icon) { @@ -809,7 +811,7 @@ #if GAIM_PLUGINS || USE_PERL gaim_probe_plugins(); #endif - + #ifdef _WIN32 /* Various win32 initializations */ wgaim_init(); diff -r 7103653dd34e -r 74f65a3d2a1f src/conversation.c --- a/src/conversation.c Thu Jan 09 06:38:09 2003 +0000 +++ b/src/conversation.c Thu Jan 09 09:41:49 2003 +0000 @@ -86,113 +86,6 @@ /*------------------------------------------------------------------------*/ -void gaim_setup_imhtml_smileys(GtkWidget *imhtml) -{ - /* This is ugly right now--it will get better when the themable smileys come */ - - - char *filename; - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "smile.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":)", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-)", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "sad.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":(", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-(", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "wink.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ";)", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ";-)", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "tongue.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-p", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-P", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "scream.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), "=-O", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), "=-o", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "kiss.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-*", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "yell.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ">:o", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ">:O", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "cool.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), "8-)", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "moneymouth.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-$", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "burp.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-!", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "embarrassed.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-[", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "cry.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":'(", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "think.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-/", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-\\", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "crossedlips.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-x", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-X", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "bigsmile.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-d", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-D", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "angel.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), "O:-)", NULL, filename); - g_free(filename); - - /* "Secret" smileys */ - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "luke.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), "C:)", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), "C:-)", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "oneeye.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), "O-)", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "crazy.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ">:)", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ">:-)", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "mrt.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-o)))", NULL, filename); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-O)))", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "download.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), "8-|)", NULL, filename); - g_free(filename); - - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", "default", "farted.png", NULL); - gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), ":-]", NULL, filename); - g_free(filename); -} void gaim_setup_imhtml(GtkWidget *imhtml) { @@ -202,7 +95,7 @@ gtk_imhtml_show_smileys(GTK_IMHTML(imhtml), FALSE); g_signal_connect(GTK_OBJECT(imhtml), "url_clicked", G_CALLBACK(open_url), NULL); - gaim_setup_imhtml_smileys(imhtml); + smiley_themeize(imhtml); } void quiet_set(GtkWidget *tb, int state) @@ -2246,7 +2139,6 @@ update_icon(cnv); update_checkbox(cnv); - gaim_setup_imhtml_smileys(cnv->text); } int set_dispstyle(int chat) @@ -2410,7 +2302,6 @@ update_icon(c); update_checkbox(c); - gaim_setup_imhtml_smileys(c->text); } void update_buttons_by_protocol(struct conversation *c) diff -r 7103653dd34e -r 74f65a3d2a1f src/gtkimhtml.c --- a/src/gtkimhtml.c Thu Jan 09 06:38:09 2003 +0000 +++ b/src/gtkimhtml.c Thu Jan 09 09:41:49 2003 +0000 @@ -54,7 +54,7 @@ struct _GtkSmileyTree { GString *values; GtkSmileyTree **children; - gchar *image; + GtkIMHtmlSmiley *image; }; static GtkSmileyTree* @@ -65,11 +65,10 @@ static void gtk_smiley_tree_insert (GtkSmileyTree *tree, - const gchar *text, - const gchar *path) + GtkIMHtmlSmiley *smiley) { GtkSmileyTree *t = tree; - const gchar *x = text; + const gchar *x = smiley->smile; if (!strlen (x)) return; @@ -95,11 +94,13 @@ x++; } - t->image = g_strdup(path); + t->image = smiley; } + gboolean gtk_smiley_tree_destroy (GtkSmileyTree *tree) { + /* GSList *list = g_slist_append (NULL, tree); while (list) { @@ -112,12 +113,13 @@ g_string_free (t->values, TRUE); g_free (t->children); } - g_free (t->image); g_free (t); } return TRUE; + */ } + static GtkTextViewClass *parent_class = NULL; @@ -233,11 +235,11 @@ } static void -gtk_smiley_tree_remove (GtkSmileyTree *tree, - const gchar *text) +gtk_smiley_tree_remove (GtkSmileyTree *tree, + GtkIMHtmlSmiley *smiley) { GtkSmileyTree *t = tree; - const gchar *x = text; + const gchar *x = smiley->smile; gint len = 0; while (*x) { @@ -256,7 +258,6 @@ } if (t->image) { - g_free(t->image); t->image = NULL; } } @@ -291,16 +292,14 @@ } void -gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, - gchar *text, - gchar *sml, - gchar *path) +gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, + gchar *sml, + GtkIMHtmlSmiley *smiley) { GtkSmileyTree *tree; g_return_if_fail (imhtml != NULL); g_return_if_fail (GTK_IS_IMHTML (imhtml)); - g_return_if_fail (text != NULL); - + if (sml == NULL) tree = imhtml->default_smilies; else if ((tree = g_hash_table_lookup(imhtml->smiley_data, sml))) { @@ -309,10 +308,7 @@ g_hash_table_insert(imhtml->smiley_data, sml, tree); } - if (path == NULL) - gtk_smiley_tree_remove (tree, text); - else - gtk_smiley_tree_insert (tree, text, path); + gtk_smiley_tree_insert (tree, smiley); } static gboolean @@ -342,14 +338,13 @@ return (*len > 0); } -static gchar* +GdkPixbuf* gtk_smiley_tree_image (GtkIMHtml *imhtml, const gchar *sml, const gchar *text) { GtkSmileyTree *t; const gchar *x = text; - if (sml == NULL) t = imhtml->default_smilies; else @@ -375,7 +370,10 @@ x++; } - return t->image; + if (!t->image->icon) + t->image->icon = gdk_pixbuf_new_from_file(t->image->file, NULL); + + return t->image->icon; } #define VALID_TAG(x) if (!g_strncasecmp (string, x ">", strlen (x ">"))) { \ *tag = g_strndup (string, strlen (x)); \ @@ -932,7 +930,7 @@ } NEW_BIT (NEW_TEXT_BIT); wpos = g_snprintf (ws, smilelen + 1, "%s", c); - gtk_text_buffer_insert_pixbuf(imhtml->text_buffer, &iter, gdk_pixbuf_new_from_file(gtk_smiley_tree_image (imhtml, sml, ws), NULL)); + gtk_text_buffer_insert_pixbuf(imhtml->text_buffer, &iter, gtk_smiley_tree_image (imhtml, sml, ws)); c += smilelen; pos += smilelen; wpos = 0; diff -r 7103653dd34e -r 74f65a3d2a1f src/gtkimhtml.h --- a/src/gtkimhtml.h Thu Jan 09 06:38:09 2003 +0000 +++ b/src/gtkimhtml.h Thu Jan 09 09:41:49 2003 +0000 @@ -38,6 +38,7 @@ typedef gchar** (*GtkIMHtmlImage) (gchar *url); typedef struct _GtkSmileyTree GtkSmileyTree; +typedef struct _GtkIMHtmlSmiley GtkIMHtmlSmiley; typedef struct _GtkIMHtml GtkIMHtml; typedef struct _GtkIMHtmlClass GtkIMHtmlClass; @@ -62,6 +63,13 @@ void (*url_clicked) (GtkIMHtml *, const gchar *); }; +struct _GtkIMHtmlSmiley { + gchar *smile; + gchar *file; + GdkPixbuf *icon; + gboolean hidden; +}; + typedef enum { GTK_IMHTML_NO_COLOURS = 1 << 0, @@ -86,8 +94,7 @@ void gtk_imhtml_associate_smiley (GtkIMHtml *imhtml, gchar *sml, - gchar *text, - gchar *path); + GtkIMHtmlSmiley *smiley); void gtk_imhtml_remove_smileys (GtkIMHtml *imhtml); diff -r 7103653dd34e -r 74f65a3d2a1f src/themes.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/themes.c Thu Jan 09 09:41:49 2003 +0000 @@ -0,0 +1,209 @@ +/* + * Themes for Gaim + * + * Copyright (C) 2003, Sean Egan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "gtkimhtml.h" +#include + +struct smiley_list { + char *sml; + GSList *smileys; + struct smiley_list *next; +}; + +struct smiley_theme { + char *path; + char *name; + char *desc; + char *icon; + char *author; + + struct smiley_list *list; +}; + +GSList *smiley_themes; +static struct smiley_theme *current_smiley_theme; + +void smiley_themeize(GtkWidget *imhtml) +{ + struct smiley_list *list; + if (!current_smiley_theme) + return; + + + + gtk_imhtml_remove_smileys(GTK_IMHTML(imhtml)); + list = current_smiley_theme->list; + while (list) { + char *sml = !strcmp(list->sml, "default") ? NULL : list->sml; + GSList *icons = list->smileys; + while (icons) { + gtk_imhtml_associate_smiley(GTK_IMHTML(imhtml), sml, icons->data); + icons = icons->next; + } + list = list->next; + } +} + +struct smiley_theme *load_smiley_theme(char *file, gboolean load) +{ + FILE *f = fopen(file, "r"); + char buf[256]; + char sml[16]; + char *i; + struct smiley_theme *theme=NULL; + struct smiley_list *list = NULL; + GSList *lst = smiley_themes; + char *dirname; + + while (lst) { + struct smiley_theme *thm = lst->data; + if (!g_strcasecmp(thm->path, file)) { + theme = thm; + break; + } + lst = lst->next; + } + if (!theme) { + theme = g_new0(struct smiley_theme, 1); + theme->path = file; + } + if (!f) + return NULL; + + dirname = g_path_get_dirname(file); + if (load) { + if (current_smiley_theme) { + struct smiley_list *wer = current_smiley_theme->list; + while (wer) { + char *nds = !strcmp(wer->sml, "default") ? NULL : wer->sml; + GSList *dfg = wer->smileys; + while (dfg) { + GtkIMHtmlSmiley *uio = dfg->data; + if (uio->icon) + g_object_unref(uio->icon); + g_free(uio->file); + g_free(uio->smile); + dfg = dfg->next; + } + wer = wer->next; + } + } + current_smiley_theme = theme; + } + + + while (!feof(f)) { + if (!fgets(buf, sizeof(buf), f)) { + g_free(dirname); + return NULL; + } + + if (buf[0] == '#' || buf[0] == '\0') + continue; + + i = buf; + while (isspace(*i)) + i++; + + if (*i == '[' && strchr(i, ']') && load) { + struct smiley_list *child = g_new0(struct smiley_list, 1); + child->sml = g_strndup(i+1, (int)strchr(i, ']') - (int)i - 1); + if (theme->list) + list->next = child; + else + theme->list = child; + list = child; + } else if (!g_strncasecmp(i, "Name=", strlen("Name="))) { + theme->name = g_strdup(i+ strlen("Name=")); + } else if (!g_strncasecmp(i, "Description=", strlen("Description="))) { + theme->desc = g_strdup(i + strlen("Description=")); + } else if (!g_strncasecmp(i, "Icon=", strlen("Icon="))) { + theme->icon = g_build_filename(dirname, i + strlen("Icon="), NULL); + } else if (!g_strncasecmp(i, "Author=", strlen("Author"))) { + theme->desc = g_strdup(i + strlen("Author")); + } else if (load && list) { + gboolean hidden; + char *file = NULL; + GtkIMHtmlSmiley *smiley = g_new0(GtkIMHtmlSmiley, 1); + + if (*i == '!' && *i + 1 == ' ') { + hidden = TRUE; + i = i + 2; + } + while (*i) { + char l[64]; + int li = 0; + while (!isspace(*i)) + l[li++] = *(i++); + if (!file) { + l[li] = 0; + file = g_build_filename(dirname, l, NULL); + } else { + l[li] = 0; + smiley = g_new0(GtkIMHtmlSmiley, 1); + smiley->file = file; + smiley->smile = g_strdup(l); + list->smileys = g_slist_append(list->smileys, smiley); + } + while (isspace(*i)) + i++; + } + } + } + g_free(dirname); + return theme; +} + +void smiley_theme_probe() +{ + GDir *dir; + const gchar *file; + gchar *path; + struct smiley_theme *smile; + int l; + + char* probedirs[3]; + probedirs[0] = g_build_filename(DATADIR, "pixmaps", "gaim", "smileys", NULL); + probedirs[1] = g_build_filename(gaim_user_dir(), "smileys", NULL); + probedirs[2] = 0; + for (l=0; probedirs[l]; l++) { + dir = g_dir_open(probedirs[l], 0, NULL); + if (dir) { + while ((file = g_dir_read_name(dir))) { + path = g_build_filename(probedirs[0], file, "theme", NULL); + + /* Here we check to see that the theme has proper syntax. + * We set the second argument to FALSE so that it doesn't load + * the theme yet. + */ + if (smile = load_smiley_theme(path, TRUE)) { + smiley_themes = g_slist_append(smiley_themes, smile); + } + g_free(path); + } + g_dir_close(dir); + } + g_free(probedirs[l]); + } + + + +} diff -r 7103653dd34e -r 74f65a3d2a1f src/ui.h --- a/src/ui.h Thu Jan 09 06:38:09 2003 +0000 +++ b/src/ui.h Thu Jan 09 09:41:49 2003 +0000 @@ -520,6 +520,9 @@ extern void play_sound(int); extern void play_file(char *); +/* Functions in themes.c */ +extern void smiley_themeize(GtkWidget *); + /* Fucnctions in util.c */ extern GtkWidget *gaim_pixmap(char *, char *); extern GdkPixbuf *gaim_pixbuf(char *, char *);