changeset 19098:ac904659104f

propagate from branch 'im.pidgin.pidgin.2.1.0' (head 121873f517c4c5e2d65c3a1cdd152694834d7db0) to branch 'im.pidgin.soc.2007.finchfeat' (head c079bc8ba4b62373e63c0923c45007d2eac37aa2)
author Eric Polino <aluink@pidgin.im>
date Tue, 12 Jun 2007 21:21:37 +0000
parents 9018b785ef73 (current diff) d7cd0afd3c36 (diff)
children a1ac8b05ecdb
files COPYRIGHT finch/libgnt/gnt.h finch/libgnt/gntbindable.h finch/libgnt/gntbox.c finch/libgnt/gntkeys.c finch/libgnt/gntkeys.h finch/libgnt/gntmain.c finch/libgnt/gntmenu.c finch/libgnt/gntstyle.c finch/libgnt/gntstyle.h finch/libgnt/gnttree.c finch/libgnt/gntutils.c finch/libgnt/gntutils.h finch/libgnt/gntwidget.c finch/libgnt/gntwm.c libpurple/protocols/bonjour/dns_sd.c libpurple/protocols/bonjour/dns_sd.h
diffstat 13 files changed, 376 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Mon Jun 11 17:36:40 2007 +0000
+++ b/COPYRIGHT	Tue Jun 12 21:21:37 2007 +0000
@@ -274,6 +274,7 @@
 Joao Luís Marques Pinto
 Aleksander Piotrowski
 Julien Pivotto
+Eric Polino <aluink@gmail.com>
 Ari Pollak
 Robey Pointer
 Stephen Pope
--- a/finch/gntdebug.c	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/gntdebug.c	Tue Jun 12 21:21:37 2007 +0000
@@ -298,7 +298,7 @@
 	REGISTER_G_LOG_HANDLER("GThread");
 
 	g_set_print_handler(print_stderr);   /* Redirect the debug messages to stderr */
-	g_set_printerr_handler(suppress_error_messages);
+//	g_set_printerr_handler(suppress_error_messages);
 
 	purple_prefs_add_none(PREF_ROOT);
 	purple_prefs_add_string(PREF_ROOT "/filter", "");
--- a/finch/libgnt/gnt.h	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gnt.h	Tue Jun 12 21:21:37 2007 +0000
@@ -138,4 +138,3 @@
  * @param string
  */
 void gnt_set_clipboard_string(gchar *string);
-
--- a/finch/libgnt/gntbindable.c	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gntbindable.c	Tue Jun 12 21:21:37 2007 +0000
@@ -20,13 +20,201 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <string.h>
+
 #include "gntbindable.h"
 #include "gntstyle.h"
 #include "gnt.h"
 #include "gntutils.h"
+#include "gnttextview.h"
+#include "gnttree.h"
+#include "gntbox.h"
+#include "gntbutton.h"
+#include "gntwindow.h"
+#include "gntlabel.h"
 
 static GObjectClass *parent_class = NULL;
 
+static struct
+{
+	char * okeys; /* Old keystrokes */
+	char * keys; /* New Keystrokes being bound to the action */
+	GntBindableClass * klass; /* Class of the object that's getting keys rebound */
+	char * name; /* The name of the action */
+	GList * params; /* The list of paramaters */
+	
+} rebind_info = {NULL,NULL,NULL,NULL,NULL};
+
+static void 
+gnt_bindable_free_rebind_info()
+{
+	g_free(rebind_info.name);
+	g_free(rebind_info.keys);
+	g_free(rebind_info.okeys);
+}
+
+static gboolean
+gnt_bindable_rebinding_cancel(GntBindable *bindable, gpointer data)
+{
+	gnt_bindable_free_rebind_info();
+	gnt_widget_destroy(GNT_WIDGET(data));
+	return TRUE;
+}
+
+static gboolean
+gnt_bindable_rebinding_rebind(GntBindable *bindable, gpointer data)
+{
+
+	if(rebind_info.keys) {
+		gnt_bindable_register_binding(rebind_info.klass,
+				NULL,
+				rebind_info.okeys,
+				rebind_info.params);
+		gnt_bindable_register_binding(rebind_info.klass,
+				rebind_info.name,
+				rebind_info.keys,
+				rebind_info.params);
+	}
+	gnt_bindable_free_rebind_info();
+
+	gnt_widget_destroy(GNT_WIDGET(data));
+
+	return TRUE;
+}
+
+static gboolean
+gnt_bindable_rebinding_grab_key(GntBindable *bindable, const char *text, gpointer *data)
+{
+
+	GntTextView *textview= GNT_TEXT_VIEW(data);
+	char *new_text;
+	const char *tmp;
+
+	if(text && *text){
+
+		if(!strcmp(text, GNT_KEY_CTRL_I) || !strcmp(text, GNT_KEY_ENTER)){
+			return FALSE;
+		}
+		
+		tmp = gnt_key_lookup(text);
+		new_text = g_strdup_printf("KEY: \"%s\"",tmp);
+		gnt_text_view_clear(textview);
+		gnt_text_view_append_text_with_flags(textview,new_text,GNT_TEXT_FLAG_NORMAL);
+		g_free(new_text);
+
+		g_free(rebind_info.keys);
+		rebind_info.keys = g_strdup(text);
+
+
+		return TRUE;
+	}
+	return FALSE;
+} 
+static void
+gnt_bindable_rebinding_activate(GntBindable *data, gpointer bindable)
+{
+				
+	GntTree * tree = GNT_TREE(data);
+
+	GntWidget *vbox = gnt_box_new(FALSE,TRUE);
+
+	GntWidget *label;
+	const char * widget_name = g_type_name(G_OBJECT_TYPE(bindable));
+	char * keys;
+
+	GntWidget *key_textview;
+	
+	GntWidget *bind_button, *cancel_button;
+	GntWidget *button_box;
+	
+	GntWidget *win = gnt_window_new();
+	GList * current_row_data,*itr;
+	char * tmp;
+
+	rebind_info.klass = GNT_BINDABLE_GET_CLASS(bindable);
+
+	current_row_data = gnt_tree_get_selection_text_list(tree);
+	rebind_info.name = g_strdup(g_list_nth_data(current_row_data,1));
+
+	keys = gnt_tree_get_selection_data(tree);
+	rebind_info.okeys = g_strdup(gnt_key_translate(keys));
+
+	rebind_info.params = NULL;
+
+	itr = current_row_data;
+	while(itr){
+		g_free(itr->data);
+		itr = itr->next;
+	}
+	g_list_free(current_row_data);
+
+	gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_MID);
+
+	gnt_box_set_title(GNT_BOX(win),"Key Capture");
+
+	tmp = g_strdup_printf("Type the new bindings for %s in a %s.",rebind_info.name,widget_name);
+	label = gnt_label_new(tmp);
+	g_free(tmp);
+	gnt_box_add_widget(GNT_BOX(vbox),label);
+
+	tmp = g_strdup_printf("KEY: \"%s\"",keys);
+	key_textview = gnt_text_view_new();
+	gnt_widget_set_size(key_textview,key_textview->priv.x,2);
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(key_textview),tmp,GNT_TEXT_FLAG_NORMAL);
+	g_free(tmp);
+	gnt_widget_set_name(key_textview,"keystroke");
+	gnt_box_add_widget(GNT_BOX(vbox),key_textview);
+
+	g_signal_connect(G_OBJECT(win), "key_pressed", G_CALLBACK(gnt_bindable_rebinding_grab_key),key_textview);
+
+	button_box = gnt_box_new(FALSE,FALSE);
+	
+	bind_button = gnt_button_new("BIND");
+	gnt_widget_set_name(bind_button,"bind");
+	gnt_box_add_widget(GNT_BOX(button_box), bind_button);
+	
+	cancel_button = gnt_button_new("Cancel");
+	gnt_widget_set_name(cancel_button,"cancel");
+	gnt_box_add_widget(GNT_BOX(button_box),cancel_button);
+	
+	g_signal_connect(G_OBJECT(bind_button), "activate", G_CALLBACK(gnt_bindable_rebinding_rebind),win);
+	g_signal_connect(G_OBJECT(cancel_button), "activate", G_CALLBACK(gnt_bindable_rebinding_cancel),win);
+	
+
+	gnt_box_add_widget(GNT_BOX(vbox),button_box);
+
+	gnt_box_add_widget(GNT_BOX(win),vbox);
+	gnt_widget_show(win);
+
+}
+
+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);
+}
+
 static void
 gnt_bindable_class_init(GntBindableClass *klass)
 {
@@ -251,4 +439,56 @@
 	g_free(param);
 }
 
+GntBindable * gnt_bindable_bindings_view(GntBindable *bind)
+{
+	GntBindable *tree = GNT_BINDABLE(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);
+	if (GNT_TREE(tree)->list == NULL) {
+		gnt_widget_destroy(GNT_WIDGET(tree));
+		tree = NULL;
+	} else
+		gnt_tree_adjust_columns(bv.tree);
+	g_hash_table_destroy(hash);
+
+	return tree;
+}
+
+static void
+reset_binding_window(GntBindableClass *window, gpointer k)
+{
+	GntBindableClass *klass = GNT_BINDABLE_CLASS(k);
+	klass->help_window = NULL;
+}
+
+gboolean
+gnt_bindable_build_help_window(GntBindable *bindable)
+{
+
+	GntWidget *tree;
+	GntBindableClass *klass = GNT_BINDABLE_GET_CLASS(bindable);
+	char *title;
+
+	tree = GNT_WIDGET(gnt_bindable_bindings_view(bindable));
+
+	klass->help_window = GNT_BINDABLE(gnt_window_new());
+	title = g_strdup_printf("Bindings for %s", g_type_name(G_OBJECT_TYPE(bindable)));
+	gnt_box_set_title(GNT_BOX(klass->help_window), title);
+	if (tree) {
+		g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(gnt_bindable_rebinding_activate), bindable);
+		gnt_box_add_widget(GNT_BOX(klass->help_window), tree);
+	} else
+		gnt_box_add_widget(GNT_BOX(klass->help_window), gnt_label_new("This widget has no customizable bindings."));
+
+	g_signal_connect(G_OBJECT(klass->help_window), "destroy", G_CALLBACK(reset_binding_window), klass);
+	gnt_widget_show(GNT_WIDGET(klass->help_window));
+	g_free(title);
+
+	return TRUE;
+}
+
--- a/finch/libgnt/gntbindable.h	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gntbindable.h	Tue Jun 12 21:21:37 2007 +0000
@@ -53,7 +53,8 @@
 	GHashTable *actions;  /* name -> Action */
 	GHashTable *bindings; /* key -> ActionParam */
 
-	void (*gnt_reserved1)(void);
+	GntBindable * help_window;
+
 	void (*gnt_reserved2)(void);
 	void (*gnt_reserved3)(void);
 	void (*gnt_reserved4)(void);
@@ -146,6 +147,31 @@
  */
 gboolean gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...);
 
+/**
+* Returns a GntTree populated with "key" -> "binding" for the widget.
+*/
+/**
+* 
+* @param widget
+*
+* @return
+*/
+GntBindable * gnt_bindable_bindings_view(GntBindable *bind);
+
+/**
+ *
+ * Builds a window that list the key bindings for a GntBindable object.  From this window a user can select a listing to rebind a new key for the given action.
+ *
+ */
+/**
+ * 
+ * @param bindable
+ *	
+ * @return
+ */
+
+gboolean gnt_bindable_build_help_window(GntBindable *bindable);
+
 G_END_DECLS
 
 #endif /* GNT_BINDABLE_H */
--- a/finch/libgnt/gntbox.c	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gntbox.c	Tue Jun 12 21:21:37 2007 +0000
@@ -315,10 +315,6 @@
 		{
 			find_next_focus(box);
 		}
-		else if (strcmp(text, GNT_KEY_BACK_TAB) == 0)
-		{
-			find_prev_focus(box);
-		}
 	}
 	else if (text[0] == '\t')
 	{
--- a/finch/libgnt/gntkeys.c	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gntkeys.c	Tue Jun 12 21:21:37 2007 +0000
@@ -72,7 +72,6 @@
 	INSERT_KEY("pagedown", GNT_KEY_PGDOWN);
 	INSERT_KEY("insert",   GNT_KEY_INS);
 	INSERT_KEY("delete",   GNT_KEY_DEL);
-	INSERT_KEY("back_tab", GNT_KEY_BACK_TAB);
 
 	INSERT_KEY("left",   GNT_KEY_LEFT);
 	INSERT_KEY("right",  GNT_KEY_RIGHT);
@@ -206,8 +205,8 @@
 		node->flags |= IS_END;
 		return;
 	}
-	while (*path && node->next[(unsigned char)*path]) {
-		node = node->next[(unsigned char)*path];
+	while (*path && node->next[*path]) {
+		node = node->next[*path];
 		node->ref++;
 		path++;
 	}
@@ -215,7 +214,7 @@
 		return;
 	n = g_new0(struct _node, 1);
 	n->ref = 1;
-	node->next[(unsigned char)*path++] = n;
+	node->next[*path++] = n;
 	add_path(n, path);
 }
 
@@ -230,13 +229,13 @@
 
 	if (!*path)
 		return;
-	next = node->next[(unsigned char)*path];
+	next = node->next[*path];
 	if (!next)
 		return;
 	del_path(next, path + 1);
 	next->ref--;
 	if (next->ref == 0) {
-		node->next[(unsigned char)*path] = NULL;
+		node->next[*path] = NULL;
 		g_free(next);
 	}
 }
@@ -252,12 +251,12 @@
 	struct _node *n = &root;
 
 	root.flags &= ~IS_END;
-	while (*path && n->next[(unsigned char)*path] && !(n->flags & IS_END)) {
+	while (*path && n->next[*path] && !(n->flags & IS_END)) {
 		if (!g_ascii_isspace(*path) &&
 				!g_ascii_iscntrl(*path) &&
 				!g_ascii_isgraph(*path))
 			return 0;
-		n = n->next[(unsigned char)*path++];
+		n = n->next[*path++];
 		depth++;
 	}
 
--- a/finch/libgnt/gntmain.c	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gntmain.c	Tue Jun 12 21:21:37 2007 +0000
@@ -246,6 +246,12 @@
 	if (HOLDING_ESCAPE)
 		keys[0] = '\033';
 	k = keys;
+	if(*k < 0){ /* Alt not sending ESC* */
+		*(k + 1) = 128 - *k;
+		*k = 27;
+		*(k + 2) = 0;
+		rd++;
+	}
 	while (rd) {
 		char back;
 		int p;
--- a/finch/libgnt/gntmenu.c	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gntmenu.c	Tue Jun 12 21:21:37 2007 +0000
@@ -242,10 +242,7 @@
 static void
 gnt_menu_hide(GntWidget *widget)
 {
-	GntMenu *sub, *menu = GNT_MENU(widget);
-
-	while ((sub = menu->submenu))
-		gnt_widget_hide(GNT_WIDGET(sub));
+	GntMenu *menu = GNT_MENU(widget);
 	if (menu->parentmenu)
 		menu->parentmenu->submenu = NULL;
 }
--- a/finch/libgnt/gntstyle.c	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gntstyle.c	Tue Jun 12 21:21:37 2007 +0000
@@ -22,6 +22,7 @@
 
 #include "gntstyle.h"
 #include "gntcolors.h"
+
 #include "gntws.h"
 
 #include <glib.h>
@@ -294,7 +295,6 @@
 			str_styles[styles[i].en] =
 					g_key_file_get_string(kfile, "general", styles[i].style, NULL);
 		}
-
 		for (i = 0; i < nkeys; i++)
 			g_hash_table_replace(unknowns, g_strdup(keys[i]),
 					g_strdup(g_key_file_get_string(kfile, "general", keys[i], NULL)));
@@ -338,7 +338,6 @@
 	for (i = 0; i < GNT_STYLES; i++)
 		g_free(str_styles[i]);
 
-	g_hash_table_destroy(unknowns);
 #if GLIB_CHECK_VERSION(2,6,0)
 	g_key_file_free(gkfile);
 #endif
--- a/finch/libgnt/gnttree.c	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gnttree.c	Tue Jun 12 21:21:37 2007 +0000
@@ -303,7 +303,7 @@
 
 		notfirst = TRUE;
 
-		if (len > width - 2) {
+		if (len > width) {
 			len = width - 1;
 			cut = TRUE;
 		}
--- a/finch/libgnt/gntutils.h	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gntutils.h	Tue Jun 12 21:21:37 2007 +0000
@@ -99,6 +99,8 @@
  * @param widget
  *
  * @return
+ *
+ * @deprecated Consider using gnt_bindable_bindings_view instead.
  */
 GntWidget * gnt_widget_bindings_view(GntWidget *widget);
 
--- a/finch/libgnt/gntwm.c	Mon Jun 11 17:36:40 2007 +0000
+++ b/finch/libgnt/gntwm.c	Tue Jun 12 21:21:37 2007 +0000
@@ -34,7 +34,9 @@
 #include <string.h>
 #include <time.h>
 
+#include "gntbutton.h"
 #include "gntwm.h"
+#include "gntentry.h"
 #include "gntstyle.h"
 #include "gntmarshal.h"
 #include "gnt.h"
@@ -83,6 +85,7 @@
 static time_t last_active_time;
 static gboolean idle_update;
 static GList *act = NULL; /* list of WS with unseen activitiy */
+static gboolean ignore_keys = FALSE;
 
 static GList *
 g_list_bring_to_front(GList *list, gpointer data)
@@ -630,6 +633,7 @@
 list_of_windows(GntWM *wm, gboolean workspace)
 {
 	GntWidget *tree, *win;
+
 	setup__list(wm);
 	wm->windows = &wm->_list;
 
@@ -1128,6 +1132,71 @@
 	return TRUE;
 }
 
+static gboolean
+ignore_keys_start(GntBindable *bindable, GList *n)
+{
+	GntWM *wm = GNT_WM(bindable);
+
+	if(!wm->menu && !wm->_list.window && wm->mode == GNT_KP_MODE_NORMAL){
+		ignore_keys = TRUE;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+ignore_keys_end(GntBindable *bindable, GList *n)
+{
+	return ignore_keys ? !(ignore_keys = FALSE) : FALSE;
+}
+
+static gboolean
+help_for_bindable(GntWM *wm, GntBindable *bindable)
+{
+	gboolean ret = TRUE;
+	GntBindableClass *klass = GNT_BINDABLE_GET_CLASS(bindable);
+ 
+	if (klass->help_window) {
+		gnt_wm_raise_window(wm, GNT_WIDGET(klass->help_window));
+	} else {
+		ret =  gnt_bindable_build_help_window(bindable);
+	}
+	return ret;
+
+}
+
+static gboolean
+help_for_wm(GntBindable *bindable, GList *null)
+{
+	return help_for_bindable(GNT_WM(bindable),bindable);
+}
+
+static gboolean
+help_for_window(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	GntWidget *widget = wm->ordered->data;
+
+	return help_for_bindable(wm,GNT_BINDABLE(widget));
+}
+
+static gboolean
+help_for_widget(GntBindable *bindable, GList *null)
+{
+	GntWM *wm = GNT_WM(bindable);
+	GntWidget *widget;
+
+	if (!wm->ordered)
+		return TRUE;
+
+	widget = wm->ordered->data;
+	if (!GNT_IS_BOX(widget))
+		return TRUE;
+
+	return help_for_bindable(wm, GNT_BINDABLE(GNT_BOX(widget)->active));
+
+}
+
 static void
 gnt_wm_class_init(GntWMClass *klass)
 {
@@ -1271,9 +1340,19 @@
 	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "place-tagged", place_tagged,
 				"\033" "T", NULL);
 	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "workspace-list", workspace_list,
-				"\033" "s", NULL);
+				"\033" "s", NULL);	
 	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-clipboard",
 				toggle_clipboard, "\033" "C", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "help-for-wm", help_for_wm,
+				"\033" "\\", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "help-for-window", help_for_window,
+				"\033" "|", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-clipboard", toggle_clipboard, 
+				"\033" "C", NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "ignore-keys-start", ignore_keys_start, 
+				GNT_KEY_CTRL_G, NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "ignore-keys-end", ignore_keys_end, 
+				"\033" GNT_KEY_CTRL_G, NULL);
 
 	gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
 
@@ -1647,6 +1726,15 @@
 
 	idle_update = TRUE;
 
+	if(ignore_keys){
+		if(keys && !strcmp(keys, "\033" GNT_KEY_CTRL_G)){
+			if(gnt_bindable_perform_action_key(GNT_BINDABLE(wm), keys)){
+				return TRUE;
+			}
+		}
+		return wm->cws->ordered ? gnt_widget_key_pressed(GNT_WIDGET(wm->cws->ordered->data), keys) : FALSE;
+	}
+
 	if (gnt_bindable_perform_action_key(GNT_BINDABLE(wm), keys)) {
 		return TRUE;
 	}