Mercurial > pidgin
comparison finch/libgnt/gntbindable.c @ 15817:0e3a8505ebbe
renamed gaim-text to finch
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sun, 18 Mar 2007 19:38:15 +0000 |
parents | |
children | 8410511f4dbb |
comparison
equal
deleted
inserted
replaced
15816:317e7613e581 | 15817:0e3a8505ebbe |
---|---|
1 #include "gntbindable.h" | |
2 #include "gntstyle.h" | |
3 #include "gnt.h" | |
4 #include "gntutils.h" | |
5 | |
6 static GObjectClass *parent_class = NULL; | |
7 | |
8 static void | |
9 gnt_bindable_class_init(GntBindableClass *klass) | |
10 { | |
11 parent_class = g_type_class_peek_parent(klass); | |
12 | |
13 klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, | |
14 (GDestroyNotify)gnt_bindable_action_free); | |
15 klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, | |
16 (GDestroyNotify)gnt_bindable_action_param_free); | |
17 | |
18 gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); | |
19 GNTDEBUG; | |
20 } | |
21 | |
22 static gpointer | |
23 bindable_clone(GntBindableAction *action) | |
24 { | |
25 GntBindableAction *ret = g_new0(GntBindableAction, 1); | |
26 ret->name = g_strdup(action->name); | |
27 ret->u = action->u; | |
28 return ret; | |
29 } | |
30 | |
31 static gpointer | |
32 binding_clone(GntBindableActionParam *param) | |
33 { | |
34 GntBindableActionParam *p = g_new0(GntBindableActionParam, 1); | |
35 p->list = g_list_copy(param->list); | |
36 p->action = param->action; | |
37 return p; | |
38 } | |
39 | |
40 static void | |
41 duplicate_hashes(GntBindableClass *klass) | |
42 { | |
43 /* Duplicate the bindings from parent class */ | |
44 if (klass->actions) { | |
45 klass->actions = g_hash_table_duplicate(klass->actions, g_str_hash, | |
46 g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_free, | |
47 (GDupFunc)g_strdup, (GDupFunc)bindable_clone); | |
48 klass->bindings = g_hash_table_duplicate(klass->bindings, g_str_hash, | |
49 g_str_equal, g_free, (GDestroyNotify)gnt_bindable_action_param_free, | |
50 (GDupFunc)g_strdup, (GDupFunc)binding_clone); | |
51 } else { | |
52 klass->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, | |
53 (GDestroyNotify)gnt_bindable_action_free); | |
54 klass->bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, | |
55 (GDestroyNotify)gnt_bindable_action_param_free); | |
56 } | |
57 | |
58 GNTDEBUG; | |
59 } | |
60 | |
61 /****************************************************************************** | |
62 * GntBindable API | |
63 *****************************************************************************/ | |
64 GType | |
65 gnt_bindable_get_gtype(void) | |
66 { | |
67 static GType type = 0; | |
68 | |
69 if(type == 0) { | |
70 static const GTypeInfo info = { | |
71 sizeof(GntBindableClass), | |
72 (GBaseInitFunc)duplicate_hashes, /* base_init */ | |
73 NULL, /* base_finalize */ | |
74 (GClassInitFunc)gnt_bindable_class_init, | |
75 NULL, | |
76 NULL, /* class_data */ | |
77 sizeof(GntBindable), | |
78 0, /* n_preallocs */ | |
79 NULL, /* instance_init */ | |
80 NULL /* value_table */ | |
81 }; | |
82 | |
83 type = g_type_register_static(G_TYPE_OBJECT, | |
84 "GntBindable", | |
85 &info, G_TYPE_FLAG_ABSTRACT); | |
86 } | |
87 | |
88 return type; | |
89 } | |
90 | |
91 /** | |
92 * Key Remaps | |
93 */ | |
94 const char * | |
95 gnt_bindable_remap_keys(GntBindable *bindable, const char *text) | |
96 { | |
97 const char *remap = NULL; | |
98 GType type = G_OBJECT_TYPE(bindable); | |
99 GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable)); | |
100 | |
101 if (klass->remaps == NULL) | |
102 { | |
103 klass->remaps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
104 gnt_styles_get_keyremaps(type, klass->remaps); | |
105 } | |
106 | |
107 remap = g_hash_table_lookup(klass->remaps, text); | |
108 | |
109 return (remap ? remap : text); | |
110 } | |
111 | |
112 /** | |
113 * Actions and Bindings | |
114 */ | |
115 gboolean | |
116 gnt_bindable_perform_action_named(GntBindable *bindable, const char *name, ...) | |
117 { | |
118 GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable)); | |
119 GList *list = NULL; | |
120 va_list args; | |
121 GntBindableAction *action; | |
122 void *p; | |
123 | |
124 va_start(args, name); | |
125 while ((p = va_arg(args, void *)) != NULL) | |
126 list = g_list_append(list, p); | |
127 va_end(args); | |
128 | |
129 action = g_hash_table_lookup(klass->actions, name); | |
130 if (action && action->u.action) { | |
131 return action->u.action(bindable, list); | |
132 } | |
133 return FALSE; | |
134 } | |
135 | |
136 gboolean | |
137 gnt_bindable_perform_action_key(GntBindable *bindable, const char *keys) | |
138 { | |
139 GntBindableClass *klass = GNT_BINDABLE_CLASS(GNT_BINDABLE_GET_CLASS(bindable)); | |
140 GntBindableActionParam *param = g_hash_table_lookup(klass->bindings, keys); | |
141 | |
142 if (param && param->action) { | |
143 if (param->list) | |
144 return param->action->u.action(bindable, param->list); | |
145 else | |
146 return param->action->u.action_noparam(bindable); | |
147 } | |
148 return FALSE; | |
149 } | |
150 | |
151 static void | |
152 register_binding(GntBindableClass *klass, const char *name, const char *trigger, GList *list) | |
153 { | |
154 GntBindableActionParam *param; | |
155 GntBindableAction *action; | |
156 | |
157 if (name == NULL || *name == '\0') { | |
158 g_hash_table_remove(klass->bindings, (char*)trigger); | |
159 gnt_keys_del_combination(trigger); | |
160 return; | |
161 } | |
162 | |
163 action = g_hash_table_lookup(klass->actions, name); | |
164 if (!action) { | |
165 g_printerr("GntWidget: Invalid action name %s for %s\n", | |
166 name, g_type_name(G_OBJECT_CLASS_TYPE(klass))); | |
167 if (list) | |
168 g_list_free(list); | |
169 return; | |
170 } | |
171 | |
172 param = g_new0(GntBindableActionParam, 1); | |
173 param->action = action; | |
174 param->list = list; | |
175 g_hash_table_replace(klass->bindings, g_strdup(trigger), param); | |
176 gnt_keys_add_combination(trigger); | |
177 } | |
178 | |
179 void gnt_bindable_register_binding(GntBindableClass *klass, const char *name, | |
180 const char *trigger, ...) | |
181 { | |
182 GList *list = NULL; | |
183 va_list args; | |
184 void *data; | |
185 | |
186 va_start(args, trigger); | |
187 while ((data = va_arg(args, void *))) { | |
188 list = g_list_append(list, data); | |
189 } | |
190 va_end(args); | |
191 | |
192 register_binding(klass, name, trigger, list); | |
193 } | |
194 | |
195 void gnt_bindable_class_register_action(GntBindableClass *klass, const char *name, | |
196 GntBindableActionCallback callback, const char *trigger, ...) | |
197 { | |
198 void *data; | |
199 va_list args; | |
200 GntBindableAction *action = g_new0(GntBindableAction, 1); | |
201 GList *list; | |
202 | |
203 action->name = g_strdup(name); | |
204 action->u.action = callback; | |
205 | |
206 g_hash_table_replace(klass->actions, g_strdup(name), action); | |
207 | |
208 if (trigger && *trigger) { | |
209 list = NULL; | |
210 va_start(args, trigger); | |
211 while ((data = va_arg(args, void *))) { | |
212 list = g_list_append(list, data); | |
213 } | |
214 va_end(args); | |
215 | |
216 register_binding(klass, name, trigger, list); | |
217 } | |
218 } | |
219 | |
220 void gnt_bindable_action_free(GntBindableAction *action) | |
221 { | |
222 g_free(action->name); | |
223 g_free(action); | |
224 } | |
225 | |
226 void gnt_bindable_action_param_free(GntBindableActionParam *param) | |
227 { | |
228 g_list_free(param->list); /* XXX: There may be a leak here for string parameters */ | |
229 g_free(param); | |
230 } | |
231 | |
232 |