changeset 15989:87be53a26478

merge of '437e6f11b1b4135556057db73061de861c27c862' and 'b043ef74cd2699857810ee4e31137890a68d4462'
author Nathan Walp <nwalp@pidgin.im>
date Wed, 04 Apr 2007 10:18:36 +0000
parents e05e5b148723 (diff) 50d949d6bda2 (current diff)
children 37d928a6579e
files
diffstat 10 files changed, 298 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/finch/gntdebug.c	Wed Apr 04 10:18:17 2007 +0000
+++ b/finch/gntdebug.c	Wed Apr 04 10:18:36 2007 +0000
@@ -106,9 +106,16 @@
 	}
 }
 
+static gboolean
+finch_debug_is_enabled(PurpleDebugLevel level, const char *category)
+{
+	return debug.window && !debug.paused;
+}
+
 static PurpleDebugUiOps uiops =
 {
 	finch_debug_print,
+	finch_debug_is_enabled
 };
 
 PurpleDebugUiOps *finch_debug_get_ui_ops()
--- a/finch/libgnt/gntfilesel.c	Wed Apr 04 10:18:17 2007 +0000
+++ b/finch/libgnt/gntfilesel.c	Wed Apr 04 10:18:36 2007 +0000
@@ -11,7 +11,9 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#if 0
 #include <glob.h>
+#endif
 
 enum
 {
@@ -87,11 +89,75 @@
 	return find;
 }
 
+GntFile* gnt_file_new_dir(const char *name)
+{
+	GntFile *file = g_new0(GntFile, 1);
+	file->basename = g_strdup(name);
+	file->type = GNT_FILE_DIR;
+	return file;
+}
+
+GntFile* gnt_file_new(const char *name, unsigned long size)
+{
+	GntFile *file = g_new0(GntFile, 1);
+	file->basename = g_strdup(name);
+	file->type = GNT_FILE_REGULAR;
+	file->size = size;
+	return file;
+}
+
+static gboolean
+local_read_fn(const char *path, GList **files, GError **error)
+{
+	GDir *dir;
+	GntFile *file;
+	const char *str;
+	
+	dir = g_dir_open(path, 0, error);
+	if (dir == NULL || (error && *error)) {
+		return FALSE;
+	}
+
+	*files = NULL;
+	if (*path != '\0' && strcmp(path, G_DIR_SEPARATOR_S)) {
+		file = gnt_file_new_dir("..");
+		*files = g_list_prepend(*files, file);
+	}
+
+	while ((str = g_dir_read_name(dir)) != NULL) {
+		char *fp = g_build_filename(path, str, NULL);
+		struct stat st;
+
+		if (stat(fp, &st)) {
+			g_printerr("Error stating location %s\n", fp);
+		} else {
+			if (S_ISDIR(st.st_mode)) {
+				file = gnt_file_new_dir(str);
+			} else {
+				file = gnt_file_new(str, (long)st.st_size);
+			}
+			*files = g_list_prepend(*files, file);
+		}
+		g_free(fp);
+	}
+
+	*files = g_list_reverse(*files);
+	return TRUE;
+}
+
+static void
+gnt_file_free(GntFile *file)
+{
+	g_free(file->fullpath);
+	g_free(file->basename);
+	g_free(file);
+}
+
 static gboolean
 location_changed(GntFileSel *sel, GError **err)
 {
-	GDir *dir;
-	const char *str;
+	GList *files, *iter;
+	gboolean success;
 
 	if (!sel->dirs)
 		return TRUE;
@@ -105,42 +171,43 @@
 			gnt_widget_draw(GNT_WIDGET(sel));
 		return TRUE;
 	}
+
+	/* XXX:\
+	 * XXX: This is blocking.
+	 * XXX:/
+	 */
+	files = NULL;
+	if (sel->read_fn)
+		success = sel->read_fn(sel->current, &files, err);
+	else
+		success = local_read_fn(sel->current, &files, err);
 	
-	dir = g_dir_open(sel->current, 0, err);
-	if (dir == NULL || *err) {
+	if (!success || *err) {
 		g_printerr("GntFileSel: error opening location %s (%s)\n",
 			sel->current, *err ? (*err)->message : "reason unknown");
 		return FALSE;
 	}
 
-	if (*sel->current != '\0' && strcmp(sel->current, G_DIR_SEPARATOR_S))
-		gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(".."),
-				gnt_tree_create_row(GNT_TREE(sel->dirs), ".."), NULL, NULL);
-
-	while ((str = g_dir_read_name(dir)) != NULL) {
-		char *fp = g_build_filename(sel->current, str, NULL);
-		struct stat st;
+	for (iter = files; iter; iter = iter->next) {
+		GntFile *file = iter->data;
+		char *str = file->basename;
+		if (file->type == GNT_FILE_DIR) {
+			gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(str),
+					gnt_tree_create_row(GNT_TREE(sel->dirs), str), NULL, NULL);
+			if (sel->multiselect && sel->dirsonly && is_tagged(sel, str))
+				gnt_tree_set_row_flags(GNT_TREE(sel->dirs), (gpointer)str, GNT_TEXT_FLAG_BOLD);
+		} else if (!sel->dirsonly) {
+			char size[128];
+			snprintf(size, sizeof(size), "%ld", file->size);
 
-		if (stat(fp, &st)) {
-			g_printerr("Error stating location %s\n", fp);
-		} else {
-			if (S_ISDIR(st.st_mode)) {
-				gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(str),
-						gnt_tree_create_row(GNT_TREE(sel->dirs), str), NULL, NULL);
-				if (sel->multiselect && sel->dirsonly && is_tagged(sel, str))
-					gnt_tree_set_row_flags(GNT_TREE(sel->dirs), (gpointer)str, GNT_TEXT_FLAG_BOLD);
-			} else if (!sel->dirsonly) {
-				char size[128];
-				snprintf(size, sizeof(size), "%ld", (long)st.st_size);
-
-				gnt_tree_add_row_after(GNT_TREE(sel->files), g_strdup(str),
-						gnt_tree_create_row(GNT_TREE(sel->files), str, size, ""), NULL, NULL);
-				if (sel->multiselect && is_tagged(sel, str))
-					gnt_tree_set_row_flags(GNT_TREE(sel->files), (gpointer)str, GNT_TEXT_FLAG_BOLD);
-			}
+			gnt_tree_add_row_after(GNT_TREE(sel->files), g_strdup(str),
+					gnt_tree_create_row(GNT_TREE(sel->files), str, size, ""), NULL, NULL);
+			if (sel->multiselect && is_tagged(sel, str))
+				gnt_tree_set_row_flags(GNT_TREE(sel->files), (gpointer)str, GNT_TEXT_FLAG_BOLD);
 		}
-		g_free(fp);
 	}
+	g_list_foreach(files, (GFunc)gnt_file_free, NULL);
+	g_list_free(files);
 	if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(sel), GNT_WIDGET_MAPPED))
 		gnt_widget_draw(GNT_WIDGET(sel));
 	return TRUE;
@@ -151,8 +218,13 @@
 {
 	if (strcmp(key, "\r") == 0) {
 		char *str = g_strdup(gnt_tree_get_selection_data(tree));
-		char *path = g_build_filename(sel->current, str, NULL);
-		char *dir = g_path_get_basename(sel->current);
+		char *path, *dir;
+
+		if (!str)
+			return TRUE;
+		
+		path = g_build_filename(sel->current, str, NULL);
+		dir = g_path_get_basename(sel->current);
 		if (!gnt_file_sel_set_current_location(sel, path)) {
 			gnt_tree_set_selected(tree, str);
 		} else if (strcmp(str, "..") == 0) {
@@ -169,64 +241,67 @@
 static gboolean
 location_key_pressed(GntTree *tree, const char *key, GntFileSel *sel)
 {
-	if (strcmp(key, "\r") == 0) {
-		int count;
-		glob_t gl;
-		char *path;
-		char *str;
-		struct stat st;
-		int glob_ret;
+	char *path;
+	char *str;
+#if 0
+	int count;
+	glob_t gl;
+	struct stat st;
+	int glob_ret;
+#endif
+	if (strcmp(key, "\r"))
+		return FALSE;
 
-		str = (char*)gnt_entry_get_text(GNT_ENTRY(sel->location));
-		if (*str == G_DIR_SEPARATOR)
-			path = g_strdup(str);
-		else
-			path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", sel->current, str);
-		str = process_path(path);
-		g_free(path);
-		path = str;
-
-		if (!stat(path, &st)) {
-			if (S_ISDIR(st.st_mode)) {
-				gnt_file_sel_set_current_location(sel, path);
-				goto success;
-			}
-		}
+	str = (char*)gnt_entry_get_text(GNT_ENTRY(sel->location));
+	if (*str == G_DIR_SEPARATOR)
+		path = g_strdup(str);
+	else
+		path = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", sel->current, str);
+	str = process_path(path);
+	g_free(path);
+	path = g_path_get_dirname(str);
+	g_free(str);
 
-		glob_ret = glob(path, GLOB_MARK, NULL, &gl);
-		if (!glob_ret) {  /* XXX: do something with the return value */
-			char *loc = g_path_get_dirname(gl.gl_pathv[0]);
+	if (!gnt_file_sel_set_current_location(sel, path)) {
+		g_free(path);
+		return FALSE;
+	}
+#if 0
+	/* XXX: there needs to be a way to allow other methods for globbing,
+	 * like the read_fn stuff. */
+	glob_ret = glob(path, GLOB_MARK, NULL, &gl);
+	if (!glob_ret) {  /* XXX: do something with the return value */
+		char *loc = g_path_get_dirname(gl.gl_pathv[0]);
 
-			stat(gl.gl_pathv[0], &st);
-			gnt_file_sel_set_current_location(sel, loc);  /* XXX: check the return value */
-			g_free(loc);
-			if (!S_ISDIR(st.st_mode) && !sel->dirsonly) {
-				gnt_tree_remove_all(GNT_TREE(sel->files));
-				for (count = 0; count < gl.gl_pathc; count++) {
-					char *tmp = process_path(gl.gl_pathv[count]);
-					loc = g_path_get_dirname(tmp);
-					if (g_utf8_collate(sel->current, loc) == 0) {
-						char *base = g_path_get_basename(tmp);
-						char size[128];
-						snprintf(size, sizeof(size), "%ld", (long)st.st_size);
-						gnt_tree_add_row_after(GNT_TREE(sel->files), base,
-								gnt_tree_create_row(GNT_TREE(sel->files), base, size, ""), NULL, NULL);
-					}
-					g_free(loc);
-					g_free(tmp);
+		stat(gl.gl_pathv[0], &st);
+		gnt_file_sel_set_current_location(sel, loc);  /* XXX: check the return value */
+		g_free(loc);
+		if (!S_ISDIR(st.st_mode) && !sel->dirsonly) {
+			gnt_tree_remove_all(GNT_TREE(sel->files));
+			for (count = 0; count < gl.gl_pathc; count++) {
+				char *tmp = process_path(gl.gl_pathv[count]);
+				loc = g_path_get_dirname(tmp);
+				if (g_utf8_collate(sel->current, loc) == 0) {
+					char *base = g_path_get_basename(tmp);
+					char size[128];
+					snprintf(size, sizeof(size), "%ld", (long)st.st_size);
+					gnt_tree_add_row_after(GNT_TREE(sel->files), base,
+							gnt_tree_create_row(GNT_TREE(sel->files), base, size, ""), NULL, NULL);
 				}
-				gnt_widget_draw(sel->files);
+				g_free(loc);
+				g_free(tmp);
 			}
-		} else if (sel->files) {
-			gnt_tree_remove_all(GNT_TREE(sel->files));
 			gnt_widget_draw(sel->files);
 		}
-		globfree(&gl);
+	} else if (sel->files) {
+		gnt_tree_remove_all(GNT_TREE(sel->files));
+		gnt_widget_draw(sel->files);
+	}
+	globfree(&gl);
 success:
-		g_free(path);
-		return TRUE;
-	}
-	return FALSE;
+#endif
+	g_free(path);
+	return TRUE;
 }
 
 static void
@@ -329,6 +404,24 @@
 	return TRUE;
 }
 
+static gboolean
+up_directory(GntBindable *bind, GList *null)
+{
+	char *path, *dir;
+	GntFileSel *sel = GNT_FILE_SEL(bind);
+	if (!gnt_widget_has_focus(sel->dirs) &&
+			!gnt_widget_has_focus(sel->files))
+		return FALSE;
+
+	path = g_build_filename(sel->current, "..", NULL);
+	dir = g_path_get_basename(sel->current);
+	if (gnt_file_sel_set_current_location(sel, path))
+		gnt_tree_set_selected(GNT_TREE(sel->dirs), dir);
+	g_free(dir);
+	g_free(path);
+	return TRUE;
+}
+
 static void
 gnt_file_sel_class_init(GntFileSelClass *klass)
 {
@@ -350,6 +443,7 @@
 
 	gnt_bindable_class_register_action(bindable, "toggle-tag", toggle_tag_selection, "t", NULL);
 	gnt_bindable_class_register_action(bindable, "clear-tags", clear_tags, "c", NULL);
+	gnt_bindable_class_register_action(bindable, "up-directory", up_directory, GNT_KEY_BACKSPACE, NULL);
 	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
 
 	GNTDEBUG;
@@ -505,3 +599,9 @@
 	return list;
 }
 
+void gnt_file_sel_set_read_fn(GntFileSel *sel, gboolean (*read_fn)(const char *path, GList **files, GError **error))
+{
+	sel->read_fn = read_fn;
+}
+
+
--- a/finch/libgnt/gntfilesel.h	Wed Apr 04 10:18:17 2007 +0000
+++ b/finch/libgnt/gntfilesel.h	Wed Apr 04 10:18:36 2007 +0000
@@ -20,6 +20,7 @@
 typedef struct _GntFileSel			GntFileSel;
 typedef struct _GntFileSelPriv		GntFileSelPriv;
 typedef struct _GntFileSelClass		GntFileSelClass;
+typedef struct _GntFile             GntFile;
 
 struct _GntFileSel
 {
@@ -39,6 +40,8 @@
 	gboolean dirsonly;   /* Show only directories */
     gboolean multiselect;
     GList *tags;         /* List of tagged files when multiselect is set */
+
+	gboolean (*read_fn)(const char *path, GList **files, GError **error);
 };
 
 struct _GntFileSelClass
@@ -52,6 +55,20 @@
 	void (*gnt_reserved4)(void);
 };
 
+typedef enum _GntFileType
+{
+	GNT_FILE_REGULAR,
+	GNT_FILE_DIR
+} GntFileType;
+
+struct _GntFile
+{
+	char *fullpath;
+	char *basename;
+	GntFileType type;
+	unsigned long size;
+};
+
 G_BEGIN_DECLS
 
 GType gnt_file_sel_get_gtype(void);
@@ -76,6 +93,12 @@
 
 void gnt_file_sel_set_suggested_filename(GntFileSel *sel, const char *suggest);
 
+void gnt_file_sel_set_read_fn(GntFileSel *sel, gboolean (*read_fn)(const char *path, GList **files, GError **error));
+
+GntFile* gnt_file_new(const char *name, unsigned long size);
+
+GntFile* gnt_file_new_dir(const char *name);
+
 G_END_DECLS
 
 #endif /* GNT_FILE_SEL_H */
--- a/finch/libgnt/gntkeys.c	Wed Apr 04 10:18:17 2007 +0000
+++ b/finch/libgnt/gntkeys.c	Wed Apr 04 10:18:36 2007 +0000
@@ -134,6 +134,28 @@
 	return g_hash_table_lookup(specials, name);
 }
 
+typedef struct {
+	const char *name;
+	const char *key;
+} gntkey;
+
+static void
+get_key_name(gpointer key, gpointer value, gpointer data)
+{
+	gntkey *k = data;
+	if (k->name)
+		return;
+	if (g_utf8_collate(value, k->key) == 0)
+		k->name = key;
+}
+
+const char *gnt_key_lookup(const char *key)
+{
+	gntkey k = {NULL, key};
+	g_hash_table_foreach(specials, get_key_name, &k);
+	return k.name;
+}
+
 /**
  * The key-bindings will be saved in a tree. When a keystroke happens, GNT will
  * find the sequence that matches a binding and return the length.
--- a/finch/libgnt/gntkeys.h	Wed Apr 04 10:18:17 2007 +0000
+++ b/finch/libgnt/gntkeys.h	Wed Apr 04 10:18:36 2007 +0000
@@ -82,6 +82,7 @@
 void gnt_init_keys(void);
 void gnt_keys_refine(char *text);
 const char *gnt_key_translate(const char *name);
+const char *gnt_key_lookup(const char *key);
 
 void gnt_keys_add_combination(const char *path);
 void gnt_keys_del_combination(const char *path);
--- a/finch/libgnt/gntutils.c	Wed Apr 04 10:18:17 2007 +0000
+++ b/finch/libgnt/gntutils.c	Wed Apr 04 10:18:36 2007 +0000
@@ -1,4 +1,5 @@
 #include "gntutils.h"
+#include "gnttree.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -145,3 +146,47 @@
 	return continue_emission;
 }
 
+typedef struct {
+	GHashTable *hash;
+	GntTree *tree;
+} BindingView;
+
+static void
+add_binding(gpointer key, gpointer value, gpointer data)
+{
+	BindingView *bv = data;
+	GntBindableActionParam *act = value;
+	const char *name = g_hash_table_lookup(bv->hash, act->action);
+	if (name && *name) {
+		const char *k = gnt_key_lookup(key);
+		if (!k)
+			k = key;
+		gnt_tree_add_row_after(bv->tree, (gpointer)k,
+				gnt_tree_create_row(bv->tree, k, name), NULL, NULL);
+	}
+}
+
+static void
+add_action(gpointer key, gpointer value, gpointer data)
+{
+	BindingView *bv = data;
+	g_hash_table_insert(bv->hash, value, key);
+}
+
+GntWidget *gnt_widget_bindings_view(GntWidget *widget)
+{
+	GntBindable *bind = GNT_BINDABLE(widget);
+	GntWidget *tree = gnt_tree_new_with_columns(2);
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bind));
+	GHashTable *hash = g_hash_table_new(g_direct_hash, g_direct_equal);
+	BindingView bv = {hash, GNT_TREE(tree)};
+
+	gnt_tree_set_compare_func(bv.tree, (GCompareFunc)g_utf8_collate);
+	g_hash_table_foreach(klass->actions, add_action, &bv);
+	g_hash_table_foreach(klass->bindings, add_binding, &bv);
+	gnt_tree_adjust_columns(bv.tree);
+	g_hash_table_destroy(hash);
+
+	return tree;
+}
+
--- a/finch/libgnt/gntutils.h	Wed Apr 04 10:18:17 2007 +0000
+++ b/finch/libgnt/gntutils.h	Wed Apr 04 10:18:36 2007 +0000
@@ -34,3 +34,8 @@
 				  const GValue          *handler_return,
 				  gpointer               dummy);
 
+/**
+ * Returns a GntTree populated with "key" -> "binding" for the widget.
+ */
+GntWidget *gnt_widget_bindings_view(GntWidget *widget);
+
--- a/libpurple/debug.c	Wed Apr 04 10:18:17 2007 +0000
+++ b/libpurple/debug.c	Wed Apr 04 10:18:36 2007 +0000
@@ -53,7 +53,8 @@
 
 	ops = purple_debug_get_ui_ops();
 
-	if (!debug_enabled && ((ops == NULL) || (ops->print == NULL)))
+	if (!debug_enabled && ((ops == NULL) || (ops->print == NULL) ||
+			(ops->is_enabled && !ops->is_enabled(level, category))))
 		return;
 
 	arg_s = g_strdup_vprintf(format, args);
--- a/libpurple/debug.h	Wed Apr 04 10:18:17 2007 +0000
+++ b/libpurple/debug.h	Wed Apr 04 10:18:36 2007 +0000
@@ -49,6 +49,8 @@
 {
 	void (*print)(PurpleDebugLevel level, const char *category,
 				  const char *arg_s);
+	gboolean (*is_enabled)(PurpleDebugLevel level,
+			const char *category);
 } PurpleDebugUiOps;
 
 #ifdef __cplusplus
--- a/pidgin/gtkdebug.c	Wed Apr 04 10:18:17 2007 +0000
+++ b/pidgin/gtkdebug.c	Wed Apr 04 10:18:36 2007 +0000
@@ -1046,8 +1046,8 @@
 	gchar *ts_s;
 	gchar *esc_s, *cat_s, *tmp, *s;
 
-	if (!purple_prefs_get_bool("/purple/gtk/debug/enabled") ||
-	    (debug_win == NULL))
+	if (debug_win == NULL ||
+		!purple_prefs_get_bool("/purple/gtk/debug/enabled"))
 	{
 		return;
 	}
@@ -1104,9 +1104,17 @@
 	g_free(s);
 }
 
+static gboolean
+pidgin_debug_is_enabled(PurpleDebugLevel level, const char *category)
+{
+	return (debug_win != NULL &&
+			purple_prefs_get_bool("/purple/gtk/debug/enabled"));
+}
+
 static PurpleDebugUiOps ops =
 {
 	pidgin_debug_print,
+	pidgin_debug_is_enabled
 };
 
 PurpleDebugUiOps *