changeset 4263:74f65a3d2a1f

[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 <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Thu, 09 Jan 2003 09:41:49 +0000
parents 7103653dd34e
children f1876640e568
files src/Makefile.am src/aim.c src/conversation.c src/gtkimhtml.c src/gtkimhtml.h src/themes.c src/ui.h
diffstat 7 files changed, 248 insertions(+), 137 deletions(-) [+]
line wrap: on
line diff
--- 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
 
--- 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();
--- 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)
--- 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;
--- 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);
 
--- /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 <bj91704@binghamton.edu>
+ * 
+ * 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 <stdio.h>
+
+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]);
+	}
+	
+ 
+       
+}
--- 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 *);