1 /* guile-gnome
2 * Copyright (C) 2003, 2010 Andy Wingo <wingo at pobox dot com>
3 *
4 * gtk-support.c: Customizations for guile-gtk
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, contact:
18 *
19 * Free Software Foundation Voice: +1-617-542-5942
20 * 59 Temple Place - Suite 330 Fax: +1-617-542-2652
21 * Boston, MA 02111-1307, USA gnu@gnu.org
22 *
23 * Based on work Copyright (C) 2003 James Henstridge <james@daa.com.au>
24 */
25
26 #include <string.h>
27 #include "guile-support.h"
28 #include "gtk-support.h"
29
30
31 /* python-gtk defines a nice series of classes to access rows as elements of a
32 sequence and to access their fields via a sequence interface. I wish we could
33 do that in guile. Food for thought. */
34
35 SCM
guile_gtk_tree_path_to_scm(GtkTreePath * path)36 guile_gtk_tree_path_to_scm (GtkTreePath *path)
37 {
38 gint len, i, *indices;
39 SCM ret;
40
41 len = gtk_tree_path_get_depth(path);
42 indices = gtk_tree_path_get_indices(path);
43 ret = SCM_EOL;
44 for (i = len; i > 0; i--)
45 ret = scm_cons (scm_from_int (indices[i-1]), ret);
46 return ret;
47 }
48
49 GtkTreePath*
guile_gtk_scm_to_tree_path(SCM scm)50 guile_gtk_scm_to_tree_path (SCM scm)
51 #define FUNC_NAME "guile-gtk-scm-to-tree-path"
52 {
53 if (scm_is_string (scm)) {
54 GtkTreePath *ret;
55 scm_dynwind_begin (0);
56 ret = gtk_tree_path_new_from_string (scm_to_locale_string_dynwind (scm));
57 scm_dynwind_end ();
58 return ret;
59 } else if (scm_is_unsigned_integer (scm, 0, SCM_T_UINT32_MAX)) {
60 GtkTreePath *ret = gtk_tree_path_new ();
61 gtk_tree_path_append_index (ret, scm_to_uint (scm));
62 return ret;
63 } else if (SCM_EQ_P (scm, SCM_EOL)) {
64 return NULL;
65 } else if (SCM_NFALSEP (scm_list_p (scm))) {
66 GtkTreePath *path = gtk_tree_path_new ();
67
68 for (; !SCM_EQ_P (scm, SCM_EOL); scm = SCM_CDR (scm))
69 gtk_tree_path_append_index (path, scm_to_uint (scm_car (scm)));
70
71 return path;
72 }
73 return NULL;
74 }
75 #undef FUNC_NAME
76
77 #define GET_ACTION_STR(var,n)\
78 do {\
79 if (n < l) {\
80 SCM x = scm_list_ref (entry, scm_from_uint16 (n)); \
81 SCM_ASSERT (scm_is_false (x) || scm_is_string (x), entry,\
82 2, FUNC_NAME);\
83 var = scm_is_false (x) ? NULL : scm_to_locale_string_dynwind (x);\
84 } else {\
85 var = NULL;\
86 }\
87 }while (0)
88 #define GET_ACTION_BOOL(var,n)\
89 do {\
90 if (n < l) {\
91 var = SCM_NFALSEP (scm_list_ref (entry, scm_from_uint16 (n))); \
92 } else {\
93 var = FALSE;\
94 }\
95 }while (0)
96 #define GET_ACTION_INT(var,n)\
97 do {\
98 if (n < l) {\
99 SCM x = scm_list_ref (entry, scm_from_uint16 (n)); \
100 SCM_ASSERT (scm_is_signed_integer (x, SCM_T_INT32_MIN, \
101 SCM_T_INT32_MAX), \
102 entry, 2, FUNC_NAME);\
103 var = scm_to_int (x);\
104 } else {\
105 var = 0;\
106 }\
107 }while (0)
108
109 void
_wrap_gtk_action_group_add_actions(GtkActionGroup * action_group,SCM entries)110 _wrap_gtk_action_group_add_actions (GtkActionGroup *action_group,
111 SCM entries)
112 #define FUNC_NAME "gtk-action-group-add-actions"
113 {
114 static SCM connect = SCM_BOOL_F;
115 SCM entry, x;
116 GtkAction *action;
117 char *name, *stock_id, *label, *accelerator, *tooltip;
118 gint l;
119
120 SCM_VALIDATE_NONEMPTYLIST (1, entries);
121
122 if (SCM_FALSEP (connect))
123 connect = SCM_VARIABLE_REF (scm_c_module_lookup
124 (scm_c_resolve_module ("gnome gobject"),
125 "gtype-instance-signal-connect"));
126
127 scm_dynwind_begin (0);
128
129 for (; SCM_NNULLP (entries); entries = SCM_CDR (entries)) {
130 entry = SCM_CAR (entries);
131 SCM_VALIDATE_NONEMPTYLIST (1, entry);
132 l = scm_ilength (entry);
133 SCM_ASSERT (l > 0 && l <= 6, entry, 2, FUNC_NAME);
134
135 GET_ACTION_STR (name, 0);
136 SCM_ASSERT (name != NULL, entry, 2, FUNC_NAME);
137 GET_ACTION_STR (stock_id, 1);
138 GET_ACTION_STR (label, 2);
139 GET_ACTION_STR (accelerator, 3);
140 GET_ACTION_STR (tooltip, 4);
141
142 action = g_object_new (GTK_TYPE_ACTION,
143 "name", name, "label", label, "tooltip", tooltip,
144 "stock_id", stock_id, NULL);
145
146 if (5 < l && SCM_NFALSEP ((x = scm_list_ref (entry, scm_from_uint16 (5)))))
147 scm_call_3 (connect,
148 scm_c_gtype_instance_to_scm ((GTypeInstance*)action),
149 scm_from_locale_symbol ("activate"), x);
150
151 gtk_action_group_add_action_with_accel (action_group, action, accelerator);
152 g_object_unref (action);
153 }
154
155 scm_dynwind_end ();
156 }
157 #undef FUNC_NAME
158
159 void
_wrap_gtk_action_group_add_toggle_actions(GtkActionGroup * action_group,SCM entries)160 _wrap_gtk_action_group_add_toggle_actions (GtkActionGroup *action_group,
161 SCM entries)
162 #define FUNC_NAME "gtk-action-group-add-toggle-actions"
163 {
164 static SCM connect = SCM_BOOL_F;
165 SCM entry, x;
166 GtkToggleAction *action;
167 char *name, *stock_id, *label, *accelerator, *tooltip;
168 gboolean is_active;
169 gint l;
170
171 SCM_VALIDATE_NONEMPTYLIST (1, entries);
172
173 if (SCM_FALSEP (connect))
174 connect = SCM_VARIABLE_REF (scm_c_module_lookup
175 (scm_c_resolve_module ("gnome gobject"),
176 "gtype-instance-signal-connect"));
177
178 scm_dynwind_begin (0);
179
180 for (; SCM_NNULLP (entries); entries = SCM_CDR (entries)) {
181 entry = SCM_CAR (entries);
182 SCM_VALIDATE_NONEMPTYLIST (1, entry);
183 l = scm_ilength (entry);
184 SCM_ASSERT (l > 0 && l <= 7, entry, 2, FUNC_NAME);
185
186 GET_ACTION_STR (name, 0);
187 SCM_ASSERT (name != NULL, entry, 2, FUNC_NAME);
188 GET_ACTION_STR (stock_id, 1);
189 GET_ACTION_STR (label, 2);
190 GET_ACTION_STR (accelerator, 3);
191 GET_ACTION_STR (tooltip, 4);
192
193 action = g_object_new (GTK_TYPE_TOGGLE_ACTION,
194 "name", name, "label", label, "tooltip", tooltip,
195 "stock_id", stock_id, NULL);
196
197 if (5 < l && SCM_NFALSEP ((x = scm_list_ref (entry, scm_from_uint16 (5)))))
198 scm_call_3 (connect,
199 scm_c_gtype_instance_to_scm ((GTypeInstance*)action),
200 scm_from_locale_symbol ("activate"), x);
201
202 GET_ACTION_BOOL (is_active, 6);
203 gtk_toggle_action_set_active (action, is_active);
204
205 gtk_action_group_add_action_with_accel (action_group, GTK_ACTION (action), accelerator);
206 g_object_unref (action);
207 }
208
209 scm_dynwind_end ();
210 }
211 #undef FUNC_NAME
212
213 static void
action_group_radio_actions_callback(GtkAction * action,GtkRadioAction * current,gpointer user_data)214 action_group_radio_actions_callback(GtkAction *action,
215 GtkRadioAction *current,
216 gpointer user_data)
217 {
218 SCM proc;
219
220 proc = GPOINTER_TO_SCM (user_data);
221
222 scm_call_2 (proc,
223 scm_c_gtype_instance_to_scm ((GTypeInstance*) action),
224 scm_c_gtype_instance_to_scm ((GTypeInstance*) current));
225
226 }
227
228 void
_wrap_gtk_action_group_add_radio_actions(GtkActionGroup * action_group,SCM entries,gint value,SCM on_change)229 _wrap_gtk_action_group_add_radio_actions (GtkActionGroup *action_group,
230 SCM entries,
231 gint value,
232 SCM on_change)
233 #define FUNC_NAME "gtk-action-group-add-radio-actions"
234 {
235 GtkRadioActionEntry *raes;
236 SCM entry;
237 gint len, i, l;
238
239 SCM_VALIDATE_NONEMPTYLIST (1, entries);
240 SCM_VALIDATE_PROC (4, on_change);
241
242 len = scm_ilength (entries);
243 raes = g_new0 (GtkRadioActionEntry, len);
244
245 scm_dynwind_begin (0);
246
247 for (i=0; SCM_NNULLP (entries); entries = SCM_CDR (entries), i++) {
248 entry = SCM_CAR (entries);
249 SCM_VALIDATE_NONEMPTYLIST (1, entry);
250 l = scm_ilength (entry);
251 SCM_ASSERT (l == 6, entry, 2, FUNC_NAME);
252
253 GET_ACTION_STR (raes[i].name, 0);
254 SCM_ASSERT (raes[i].name != NULL, entry, 2, FUNC_NAME);
255 GET_ACTION_STR (raes[i].stock_id, 1);
256 GET_ACTION_STR (raes[i].label, 2);
257 GET_ACTION_STR (raes[i].accelerator, 3);
258 GET_ACTION_STR (raes[i].tooltip, 4);
259 GET_ACTION_INT (raes[i].value, 5);
260 }
261
262 gtk_action_group_add_radio_actions (action_group, raes, len, value,
263 G_CALLBACK (action_group_radio_actions_callback),
264 SCM_TO_GPOINTER (on_change));
265
266 scm_dynwind_end ();
267
268 g_free (raes);
269 }
270 #undef FUNC_NAME
271
272 void
_wrap_gtk_clipboard_set_text(GtkClipboard * clipboard,const gchar * text)273 _wrap_gtk_clipboard_set_text (GtkClipboard *clipboard, const gchar *text)
274 {
275 gtk_clipboard_set_text (clipboard, text, strlen (text));
276 }
277
278 gint
_wrap_gtk_editable_insert_text(GtkEditable * editable,const gchar * text,gint pos)279 _wrap_gtk_editable_insert_text (GtkEditable *editable, const gchar *text, gint pos)
280 {
281 gtk_editable_insert_text (editable, text, strlen (text), &pos);
282 return pos;
283 }
284
285 GtkWidget*
_wrap_gtk_dialog_get_vbox(GtkDialog * dialog)286 _wrap_gtk_dialog_get_vbox (GtkDialog *dialog)
287 {
288 return dialog->vbox;
289 }
290
291 GtkWidget*
_wrap_gtk_dialog_get_action_area(GtkDialog * dialog)292 _wrap_gtk_dialog_get_action_area (GtkDialog *dialog)
293 {
294 return dialog->action_area;
295 }
296
297 GtkWidget*
_wrap_gtk_color_selection_dialog_get_colorsel(GtkColorSelectionDialog * dialog)298 _wrap_gtk_color_selection_dialog_get_colorsel (GtkColorSelectionDialog *dialog)
299 {
300 return dialog->colorsel;
301 }
302
303 GtkWidget*
_wrap_gtk_color_selection_dialog_get_ok_button(GtkColorSelectionDialog * dialog)304 _wrap_gtk_color_selection_dialog_get_ok_button (GtkColorSelectionDialog *dialog)
305 {
306 return dialog->ok_button;
307 }
308
309 GtkWidget*
_wrap_gtk_color_selection_dialog_get_cancel_button(GtkColorSelectionDialog * dialog)310 _wrap_gtk_color_selection_dialog_get_cancel_button (GtkColorSelectionDialog *dialog)
311 {
312 return dialog->cancel_button;
313 }
314
315 GtkWidget*
_wrap_gtk_color_selection_dialog_get_help_button(GtkColorSelectionDialog * dialog)316 _wrap_gtk_color_selection_dialog_get_help_button (GtkColorSelectionDialog *dialog)
317 {
318 return dialog->help_button;
319 }
320
321 GtkWidget*
_wrap_gtk_file_selection_get_ok_button(GtkFileSelection * selection)322 _wrap_gtk_file_selection_get_ok_button (GtkFileSelection* selection)
323 {
324 return selection->ok_button;
325 }
326
327 GtkWidget*
_wrap_gtk_file_selection_get_cancel_button(GtkFileSelection * selection)328 _wrap_gtk_file_selection_get_cancel_button (GtkFileSelection* selection)
329 {
330 return selection->cancel_button;
331 }
332
333 GtkListStore*
_wrap_gtk_list_store_new(SCM col_types)334 _wrap_gtk_list_store_new (SCM col_types)
335 #define FUNC_NAME "gtk-list-store-new"
336 {
337 GType *col_gtypes;
338 gint len, i;
339 GtkListStore *ret;
340
341 SCM_VALIDATE_NONEMPTYLIST (1, col_types);
342 len = scm_ilength (col_types);
343 col_gtypes = g_new (GType, len);
344
345 for (i=0; i<len; i++) {
346 SCM v = SCM_CAR (col_types);
347 SCM_VALIDATE_GTYPE_CLASS_COPY (1, v, col_gtypes[i]);
348 col_types = SCM_CDR (col_types);
349 }
350
351 ret = gtk_list_store_newv (len, col_gtypes);
352 g_free (col_gtypes);
353 return ret;
354 }
355 #undef FUNC_NAME
356
357 void
_wrap_gtk_list_store_set_value(GtkListStore * store,GtkTreeIter * iter,gint column,SCM scm)358 _wrap_gtk_list_store_set_value (GtkListStore *store, GtkTreeIter *iter,
359 gint column, SCM scm)
360 {
361 GValue *value;
362 GType type;
363
364 SCM_ASSERT (column < gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)),
365 scm_from_int (column), 3, "gtk-list-store-set-value");
366 type = gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), column);
367 value = scm_c_scm_to_gvalue (type, scm);
368
369 gtk_list_store_set_value (store, iter, column, value);
370 g_value_unset (value);
371 g_free (value);
372 }
373
374 GtkTreeIter*
_wrap_gtk_list_store_remove(GtkListStore * store,GtkTreeIter * iter)375 _wrap_gtk_list_store_remove (GtkListStore *store, GtkTreeIter *iter)
376 {
377 if (!gtk_list_store_remove (store, iter))
378 return NULL;
379 return gtk_tree_iter_copy (iter);
380 }
381
382 GtkTreeIter*
_wrap_gtk_list_store_insert(GtkListStore * store,gint position)383 _wrap_gtk_list_store_insert (GtkListStore *store, gint position)
384 {
385 GtkTreeIter new;
386 gtk_list_store_insert (store, &new, position);
387 return gtk_tree_iter_copy (&new);
388 }
389
390 GtkTreeIter*
_wrap_gtk_list_store_insert_before(GtkListStore * store,GtkTreeIter * sibling)391 _wrap_gtk_list_store_insert_before (GtkListStore *store, GtkTreeIter *sibling)
392 {
393 GtkTreeIter new;
394 gtk_list_store_insert_before (store, &new, sibling);
395 return gtk_tree_iter_copy (&new);
396 }
397
398 GtkTreeIter*
_wrap_gtk_list_store_insert_after(GtkListStore * store,GtkTreeIter * sibling)399 _wrap_gtk_list_store_insert_after (GtkListStore *store, GtkTreeIter *sibling)
400 {
401 GtkTreeIter new;
402 gtk_list_store_insert_after (store, &new, sibling);
403 return gtk_tree_iter_copy (&new);
404 }
405
406 GtkTreeIter*
_wrap_gtk_list_store_prepend(GtkListStore * store)407 _wrap_gtk_list_store_prepend (GtkListStore *store)
408 {
409 GtkTreeIter new;
410 gtk_list_store_prepend (store, &new);
411 return gtk_tree_iter_copy (&new);
412 }
413
414 GtkTreeIter*
_wrap_gtk_list_store_append(GtkListStore * store)415 _wrap_gtk_list_store_append (GtkListStore *store)
416 {
417 GtkTreeIter new;
418 gtk_list_store_append (store, &new);
419 return gtk_tree_iter_copy (&new);
420 }
421
422 static void
menu_position_fn(GtkMenu * menu,gint * x,gint * y,gboolean * push_in,gpointer data)423 menu_position_fn (GtkMenu *menu, gint *x, gint *y, gboolean *push_in,
424 gpointer data)
425 {
426 SCM ret, proc = GPOINTER_TO_SCM (data);
427
428 ret = scm_call_1 (proc, scm_c_gtype_instance_to_scm (menu));
429
430 *x = scm_to_int32 (scm_car (ret));
431 *y = scm_to_int32 (scm_cadr (ret));
432 *push_in = scm_is_true (scm_caddr (ret));
433 }
434
435 void
_wrap_gtk_menu_popup(GtkMenu * menu,GtkWidget * parent_menu_shell,GtkWidget * parent_menu_item,SCM func,guint button,guint32 activate_time)436 _wrap_gtk_menu_popup (GtkMenu *menu, GtkWidget *parent_menu_shell,
437 GtkWidget *parent_menu_item, SCM func,
438 guint button, guint32 activate_time)
439 {
440 if (scm_is_true (func))
441 gtk_menu_popup (menu, parent_menu_shell, parent_menu_item,
442 menu_position_fn, SCM_TO_GPOINTER (func),
443 button, activate_time);
444 else
445 gtk_menu_popup (menu, parent_menu_shell, parent_menu_item,
446 NULL, NULL, button, activate_time);
447 }
448
449 /* FIXME: is this still necessary? */
450 SCM
_wrap_gtk_message_dialog_new(GtkWindow * parent,GtkDialogFlags flags,GtkMessageType type,GtkButtonsType buttons,const gchar * text)451 _wrap_gtk_message_dialog_new (GtkWindow* parent, GtkDialogFlags flags, GtkMessageType type,
452 GtkButtonsType buttons, const gchar *text)
453 {
454 GtkWidget *w = gtk_message_dialog_new (parent, flags, type, buttons, "%s", text);
455 g_object_ref (w); /* the initial ref belongs to GTK+ */
456 return scm_c_gtype_instance_to_scm (w);
457 }
458
459 gchar*
_gtk_selection_data_get_as_string(GtkSelectionData * data)460 _gtk_selection_data_get_as_string (GtkSelectionData *data)
461 {
462 return g_strndup ((gchar *)data->data, data->length);
463 }
464
465 void
_wrap_gtk_stock_add(SCM items)466 _wrap_gtk_stock_add (SCM items)
467 #define FUNC_NAME "gtk-stock-add"
468 {
469 int len, i;
470 GtkStockItem *stockitems;
471
472 SCM_ASSERT (SCM_NIMP (items) && SCM_CONSP (items) && SCM_NNULLP (items),
473 items, 1, FUNC_NAME);
474
475 len = scm_ilength (items);
476
477 stockitems = g_new0 (GtkStockItem, len);
478
479 scm_dynwind_begin (0);
480
481 for (i = 0; i < len ; i++) {
482 SCM item = SCM_CAR(items);
483
484 SCM_ASSERT (SCM_NIMP (item) && SCM_CONSP (item) &&
485 scm_ilength(item) == 5 &&
486 scm_is_string (SCM_CAR (item)) &&
487 scm_is_string (SCM_CADR (item)) &&
488 scm_is_unsigned_integer (SCM_CADDR (item), 0, SCM_T_UINT32_MAX) &&
489 scm_is_unsigned_integer (SCM_CADDDR (item), 0, SCM_T_UINT32_MAX),
490 item, 1, FUNC_NAME);
491
492 stockitems[i].stock_id = scm_to_locale_string_dynwind (SCM_CAR (item));
493 stockitems[i].label = scm_to_locale_string_dynwind (SCM_CADR (item));
494 stockitems[i].modifier = scm_to_uint (SCM_CADDR (item));
495 stockitems[i].keyval = scm_to_uint (SCM_CADDDR (item));
496 stockitems[i].translation_domain =
497 scm_is_string (SCM_CADDDR (SCM_CDR (item))) ?
498 scm_to_locale_string_dynwind (SCM_CADDDR (SCM_CDR (item))) : NULL;
499
500 items = SCM_CDR(items);
501 }
502
503 gtk_stock_add (stockitems, len);
504 scm_dynwind_end ();
505 g_free(stockitems);
506 }
507 #undef FUNC_NAME
508
509 SCM
_wrap_gtk_stock_lookup(const gchar * stock_id)510 _wrap_gtk_stock_lookup (const gchar *stock_id)
511 #define FUNC_NAME "gtk-stock-add"
512 {
513 GtkStockItem item;
514
515 if (gtk_stock_lookup (stock_id, &item)) {
516 return SCM_LIST5 (scm_from_locale_string (item.stock_id),
517 scm_from_locale_string (item.label),
518 scm_from_uint (item.modifier),
519 scm_from_uint (item.keyval),
520 scm_from_locale_string (item.translation_domain));
521 }
522
523 return SCM_BOOL_F;
524
525 }
526 #undef FUNC_NAME
527
528 void
_wrap_gtk_text_buffer_set_text(GtkTextBuffer * buf,SCM stext)529 _wrap_gtk_text_buffer_set_text (GtkTextBuffer *buf, SCM stext)
530 #define FUNC_NAME "gtk-text-buffer-set-text"
531 {
532 char *utf8_text;
533 size_t utf8_len;
534
535 SCM_VALIDATE_STRING (2, stext);
536 scm_dynwind_begin (0);
537 utf8_text = scm_to_utf8_stringn_dynwind (stext, &utf8_len);
538 gtk_text_buffer_set_text (buf, utf8_text, utf8_len);
539 scm_dynwind_end ();
540 }
541 #undef FUNC_NAME
542
543 void
_wrap_gtk_text_buffer_insert(GtkTextBuffer * buf,GtkTextIter * iter,SCM stext)544 _wrap_gtk_text_buffer_insert (GtkTextBuffer *buf, GtkTextIter* iter, SCM stext)
545 #define FUNC_NAME "gtk-text-buffer-insert"
546 {
547 char *utf8_text;
548 size_t utf8_len;
549
550 SCM_VALIDATE_STRING (3, stext);
551 scm_dynwind_begin (0);
552 utf8_text = scm_to_utf8_stringn_dynwind (stext, &utf8_len);
553 gtk_text_buffer_insert (buf, iter, utf8_text, utf8_len);
554 scm_dynwind_end ();
555 }
556 #undef FUNC_NAME
557
558 void
_wrap_gtk_text_buffer_insert_at_cursor(GtkTextBuffer * buf,SCM stext)559 _wrap_gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buf, SCM stext)
560 #define FUNC_NAME "gtk-text-buffer-insert-at-cursor"
561 {
562 char *utf8_text;
563 size_t utf8_len;
564
565 SCM_VALIDATE_STRING (2, stext);
566 scm_dynwind_begin (0);
567 utf8_text = scm_to_utf8_stringn_dynwind (stext, &utf8_len);
568 gtk_text_buffer_insert_at_cursor (buf, utf8_text, utf8_len);
569 scm_dynwind_end ();
570 }
571 #undef FUNC_NAME
572
573 gboolean
_wrap_gtk_text_buffer_insert_interactive(GtkTextBuffer * buf,GtkTextIter * iter,SCM stext,gboolean default_editable)574 _wrap_gtk_text_buffer_insert_interactive (GtkTextBuffer *buf, GtkTextIter* iter,
575 SCM stext, gboolean default_editable)
576 #define FUNC_NAME "gtk-text-buffer-insert-interactive"
577 {
578 char *utf8_text;
579 size_t utf8_len;
580 gboolean ret;
581
582 SCM_VALIDATE_STRING (3, stext);
583 scm_dynwind_begin (0);
584 utf8_text = scm_to_utf8_stringn_dynwind (stext, &utf8_len);
585 ret = gtk_text_buffer_insert_interactive (buf, iter, utf8_text, utf8_len,
586 default_editable);
587 scm_dynwind_end ();
588 return ret;
589 }
590 #undef FUNC_NAME
591
592 gboolean
_wrap_gtk_text_buffer_insert_interactive_at_cursor(GtkTextBuffer * buf,SCM stext,gboolean default_editable)593 _wrap_gtk_text_buffer_insert_interactive_at_cursor (GtkTextBuffer *buf, SCM stext,
594 gboolean default_editable)
595 #define FUNC_NAME "gtk-text-buffer-insert-interactive-at-cursor"
596 {
597 char *utf8_text;
598 size_t utf8_len;
599 gboolean ret;
600
601 SCM_VALIDATE_STRING (2, stext);
602 scm_dynwind_begin (0);
603 utf8_text = scm_to_utf8_stringn_dynwind (stext, &utf8_len);
604 ret = gtk_text_buffer_insert_interactive_at_cursor (buf, utf8_text, utf8_len,
605 default_editable);
606 scm_dynwind_end ();
607 return ret;
608 }
609 #undef FUNC_NAME
610
611 void
_wrap_gtk_text_buffer_insert_with_tags(GtkTextBuffer * buf,GtkTextIter * iter,SCM stext,GList * tag_list)612 _wrap_gtk_text_buffer_insert_with_tags (GtkTextBuffer *buf, GtkTextIter* iter,
613 SCM stext, GList* tag_list)
614 #define FUNC_NAME "gtk-text-buffer-insert-with-tags"
615 {
616 char *utf8_text;
617 size_t utf8_len;
618 GtkTextIter start;
619 GList *walk;
620 gint start_offset;
621
622 /* based on gtktextbuffer.c (LGPL) */
623
624 SCM_VALIDATE_STRING (3, stext);
625 scm_dynwind_begin (0);
626 start_offset = gtk_text_iter_get_offset (iter);
627 utf8_text = scm_to_utf8_stringn_dynwind (stext, &utf8_len);
628 gtk_text_buffer_insert (buf, iter, utf8_text, utf8_len);
629 gtk_text_buffer_get_iter_at_offset (buf, &start, start_offset);
630
631 for (walk = tag_list; walk; walk = walk->next)
632 gtk_text_buffer_apply_tag (buf, (GtkTextTag*)walk->data, &start, iter);
633 g_list_free (tag_list);
634 scm_dynwind_end ();
635 }
636 #undef FUNC_NAME
637
638 void
_wrap_gtk_text_buffer_insert_with_tags_by_name(GtkTextBuffer * buf,GtkTextIter * iter,SCM stext,GList * tag_list)639 _wrap_gtk_text_buffer_insert_with_tags_by_name (GtkTextBuffer *buf, GtkTextIter* iter,
640 SCM stext, GList* tag_list)
641 #define FUNC_NAME "gtk-text-buffer-insert-with-tags-by-name"
642 {
643 char *utf8_text;
644 size_t utf8_len;
645 GtkTextIter start;
646 GList *walk;
647 gint start_offset;
648
649 /* based on gtktextbuffer.c (LGPL) */
650
651 SCM_VALIDATE_STRING (3, stext);
652 scm_dynwind_begin (0);
653 start_offset = gtk_text_iter_get_offset (iter);
654 utf8_text = scm_to_utf8_stringn_dynwind (stext, &utf8_len);
655 gtk_text_buffer_insert (buf, iter, utf8_text, utf8_len);
656 gtk_text_buffer_get_iter_at_offset (buf, &start, start_offset);
657
658 for (walk = tag_list; walk; walk = walk->next)
659 gtk_text_buffer_apply_tag (buf,
660 gtk_text_tag_table_lookup (buf->tag_table,
661 (gchar*)walk->data),
662 &start, iter);
663 g_list_free (tag_list);
664 scm_dynwind_end ();
665 }
666 #undef FUNC_NAME
667
668 GtkTextIter*
_wrap_gtk_text_buffer_get_iter_at_line_offset(GtkTextBuffer * buf,gint line_number,gint char_offset)669 _wrap_gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buf, gint line_number,
670 gint char_offset)
671 {
672 GtkTextIter iter;
673 gtk_text_buffer_get_iter_at_line_offset (buf, &iter, line_number, char_offset);
674 return gtk_text_iter_copy (&iter);
675 }
676
677 GtkTextIter*
_wrap_gtk_text_buffer_get_iter_at_line_index(GtkTextBuffer * buf,gint line_number,gint byte_index)678 _wrap_gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buf, gint line_number,
679 gint byte_index)
680 {
681 GtkTextIter iter;
682 gtk_text_buffer_get_iter_at_line_index (buf, &iter, line_number, byte_index);
683 return gtk_text_iter_copy (&iter);
684 }
685
686 GtkTextIter*
_wrap_gtk_text_buffer_get_iter_at_offset(GtkTextBuffer * buf,gint char_offset)687 _wrap_gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buf, gint char_offset)
688 {
689 GtkTextIter iter;
690 gtk_text_buffer_get_iter_at_offset (buf, &iter, char_offset);
691 return gtk_text_iter_copy (&iter);
692 }
693
694 GtkTextIter*
_wrap_gtk_text_buffer_get_iter_at_line(GtkTextBuffer * buf,gint line_number)695 _wrap_gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buf, gint line_number)
696 {
697 GtkTextIter iter;
698 gtk_text_buffer_get_iter_at_line (buf, &iter, line_number);
699 return gtk_text_iter_copy (&iter);
700 }
701
702 GtkTextIter*
_wrap_gtk_text_buffer_get_start_iter(GtkTextBuffer * buf)703 _wrap_gtk_text_buffer_get_start_iter (GtkTextBuffer *buf)
704 {
705 GtkTextIter iter;
706 gtk_text_buffer_get_start_iter (buf, &iter);
707 return gtk_text_iter_copy (&iter);
708 }
709
710 GtkTextIter*
_wrap_gtk_text_buffer_get_end_iter(GtkTextBuffer * buf)711 _wrap_gtk_text_buffer_get_end_iter (GtkTextBuffer *buf)
712 {
713 GtkTextIter iter;
714 gtk_text_buffer_get_end_iter (buf, &iter);
715 return gtk_text_iter_copy (&iter);
716 }
717
718 SCM
_wrap_gtk_text_buffer_get_bounds(GtkTextBuffer * buf)719 _wrap_gtk_text_buffer_get_bounds (GtkTextBuffer *buf)
720 {
721 GtkTextIter start, end;
722 SCM sstart, send;
723
724 gtk_text_buffer_get_bounds (buf, &start, &end);
725 sstart = scm_c_gvalue_new_from_boxed (GTK_TYPE_TEXT_ITER, &start);
726 send = scm_c_gvalue_new_from_boxed (GTK_TYPE_TEXT_ITER, &end);
727 return scm_values (SCM_LIST2 (sstart, send));
728 }
729
730 SCM
_wrap_gtk_text_buffer_get_selection_bounds(GtkTextBuffer * buf)731 _wrap_gtk_text_buffer_get_selection_bounds (GtkTextBuffer *buf)
732 {
733 GtkTextIter start, end;
734 SCM sstart, send;
735
736 if (gtk_text_buffer_get_selection_bounds (buf, &start, &end)) {
737 sstart = scm_c_gvalue_new_from_boxed (GTK_TYPE_TEXT_ITER, &start);
738 send = scm_c_gvalue_new_from_boxed (GTK_TYPE_TEXT_ITER, &end);
739 return scm_values (SCM_LIST2 (sstart, send));
740 }
741 return scm_values (SCM_LIST2 (SCM_BOOL_F, SCM_BOOL_F));
742 }
743
744 GtkTextIter*
_wrap_gtk_text_buffer_get_iter_at_mark(GtkTextBuffer * buf,GtkTextMark * mark)745 _wrap_gtk_text_buffer_get_iter_at_mark (GtkTextBuffer *buf, GtkTextMark* mark)
746 {
747 GtkTextIter iter;
748 gtk_text_buffer_get_iter_at_mark (buf, &iter, mark);
749 return gtk_text_iter_copy (&iter);
750 }
751
752 GtkTextIter*
_wrap_gtk_text_buffer_get_iter_at_child_anchor(GtkTextBuffer * buf,GtkTextChildAnchor * anchor)753 _wrap_gtk_text_buffer_get_iter_at_child_anchor (GtkTextBuffer *buf,
754 GtkTextChildAnchor* anchor)
755 {
756 GtkTextIter iter;
757 gtk_text_buffer_get_iter_at_child_anchor (buf, &iter, anchor);
758 return gtk_text_iter_copy (&iter);
759 }
760
761 GtkTreeIter*
_wrap_gtk_tree_model_get_iter(GtkTreeModel * model,GtkTreePath * path)762 _wrap_gtk_tree_model_get_iter (GtkTreeModel *model, GtkTreePath *path)
763 {
764 GtkTreeIter new;
765
766 if (gtk_tree_model_get_iter (model, &new, path))
767 return gtk_tree_iter_copy (&new);
768 return NULL;
769 }
770
771 GtkTreeIter*
_wrap_gtk_tree_model_get_iter_first(GtkTreeModel * model)772 _wrap_gtk_tree_model_get_iter_first (GtkTreeModel *model)
773 {
774 GtkTreeIter new;
775
776 if (gtk_tree_model_get_iter_first (model, &new))
777 return gtk_tree_iter_copy (&new);
778 return NULL;
779 }
780
781 SCM
_wrap_gtk_tree_model_get_value(GtkTreeModel * model,GtkTreeIter * iter,gint column)782 _wrap_gtk_tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter, gint column)
783 {
784 GValue value = { 0, };
785
786 gtk_tree_model_get_value (model, iter, column, &value);
787
788 return scm_c_gvalue_to_scm (&value);
789 }
790
791 GtkTreeIter*
_wrap_gtk_tree_model_iter_next(GtkTreeModel * model,GtkTreeIter * iter)792 _wrap_gtk_tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
793 {
794 GtkTreeIter *new = gtk_tree_iter_copy (iter);
795
796 if (gtk_tree_model_iter_next (model, new))
797 return new;
798 gtk_tree_iter_free (new);
799 return NULL;
800 }
801
802 GList*
_wrap_gtk_tree_model_iter_children(GtkTreeModel * model,GtkTreeIter * iter)803 _wrap_gtk_tree_model_iter_children (GtkTreeModel *model, GtkTreeIter *iter)
804 {
805 GList *list = NULL;
806 GtkTreeIter prev;
807
808 if (gtk_tree_model_iter_children (model, &prev, iter)) {
809 while (1) {
810 list = g_list_prepend (list, gtk_tree_iter_copy (&prev));
811
812 if (!gtk_tree_model_iter_next (model, &prev)) {
813 return g_list_reverse (list);
814 }
815 }
816 }
817 return NULL;
818 }
819
820 GtkTreeIter*
_wrap_gtk_tree_model_iter_parent(GtkTreeModel * model,GtkTreeIter * iter)821 _wrap_gtk_tree_model_iter_parent (GtkTreeModel *model, GtkTreeIter *iter)
822 {
823 GtkTreeIter new;
824
825 if (gtk_tree_model_iter_parent (model, &new, iter))
826 return gtk_tree_iter_copy (&new);
827 return NULL;
828 }
829
830 GtkTreeIter*
_wrap_gtk_tree_model_iter_nth_child(GtkTreeModel * model,GtkTreeIter * iter,gint n)831 _wrap_gtk_tree_model_iter_nth_child (GtkTreeModel *model, GtkTreeIter *iter, gint n)
832 {
833 GtkTreeIter new;
834
835 if (gtk_tree_model_iter_nth_child (model, &new, iter, n))
836 return gtk_tree_iter_copy (&new);
837 return NULL;
838 }
839
840 SCM
_wrap_gtk_tree_selection_get_selected(GtkTreeSelection * selection)841 _wrap_gtk_tree_selection_get_selected (GtkTreeSelection *selection)
842 {
843 GtkTreeIter iter;
844 GtkTreeModel *model = NULL;
845
846 if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
847 SCM smodel, siter;
848 g_object_ref (model);
849 smodel = scm_c_gtype_instance_to_scm ((GTypeInstance*)model);
850 siter = scm_c_gvalue_new_from_boxed (GTK_TYPE_TREE_ITER, &iter);
851 return scm_values (SCM_LIST2 (smodel, siter));
852 }
853 return scm_values (SCM_LIST2 (SCM_BOOL_F, SCM_BOOL_F));
854 }
855
856 GtkTreeStore*
_wrap_gtk_tree_store_new(SCM col_types)857 _wrap_gtk_tree_store_new (SCM col_types)
858 #define FUNC_NAME "gtk-tree-store-new"
859 {
860 GType *col_gtypes;
861 gint len, i;
862 GtkTreeStore *ret;
863
864 SCM_VALIDATE_NONEMPTYLIST (1, col_types);
865 len = scm_ilength (col_types);
866 col_gtypes = g_new (GType, len);
867
868 for (i=0; i<len; i++) {
869 SCM v = SCM_CAR (col_types);
870 SCM_VALIDATE_GTYPE_CLASS_COPY (1, v, col_gtypes[i]);
871 col_types = SCM_CDR (col_types);
872 }
873
874 ret = gtk_tree_store_newv (len, col_gtypes);
875 g_free (col_gtypes);
876 return ret;
877 }
878 #undef FUNC_NAME
879
880 void
_wrap_gtk_tree_store_set_value(GtkTreeStore * store,GtkTreeIter * iter,gint column,SCM scm)881 _wrap_gtk_tree_store_set_value (GtkTreeStore *store, GtkTreeIter *iter,
882 gint column, SCM scm)
883 {
884 GValue *value;
885 GType type;
886
887 SCM_ASSERT (column < gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)),
888 scm_from_int (column), 3, "gtk-tree-store-set-value");
889 type = gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), column);
890 value = scm_c_scm_to_gvalue (type, scm);
891
892 gtk_tree_store_set_value (store, iter, column, value);
893 g_value_unset (value);
894 g_free (value);
895 }
896
897 GtkTreeIter*
_wrap_gtk_tree_store_remove(GtkTreeStore * store,GtkTreeIter * iter)898 _wrap_gtk_tree_store_remove (GtkTreeStore *store, GtkTreeIter *iter)
899 {
900 if (!gtk_tree_store_remove (store, iter))
901 return NULL;
902 return gtk_tree_iter_copy (iter);
903 }
904
905 GtkTreeIter*
_wrap_gtk_tree_store_insert(GtkTreeStore * store,GtkTreeIter * parent,gint position)906 _wrap_gtk_tree_store_insert (GtkTreeStore *store, GtkTreeIter *parent, gint position)
907 {
908 GtkTreeIter new;
909 gtk_tree_store_insert (store, &new, parent, position);
910 return gtk_tree_iter_copy (&new);
911 }
912
913 GtkTreeIter*
_wrap_gtk_tree_store_insert_before(GtkTreeStore * store,GtkTreeIter * parent,GtkTreeIter * sibling)914 _wrap_gtk_tree_store_insert_before (GtkTreeStore *store, GtkTreeIter *parent,
915 GtkTreeIter *sibling)
916 {
917 GtkTreeIter new;
918 gtk_tree_store_insert_before (store, &new, parent, sibling);
919 return gtk_tree_iter_copy (&new);
920 }
921
922 GtkTreeIter*
_wrap_gtk_tree_store_insert_after(GtkTreeStore * store,GtkTreeIter * parent,GtkTreeIter * sibling)923 _wrap_gtk_tree_store_insert_after (GtkTreeStore *store, GtkTreeIter *parent,
924 GtkTreeIter *sibling)
925 {
926 GtkTreeIter new;
927 gtk_tree_store_insert_after (store, &new, parent, sibling);
928 return gtk_tree_iter_copy (&new);
929 }
930
931 GtkTreeIter*
_wrap_gtk_tree_store_prepend(GtkTreeStore * store,GtkTreeIter * parent)932 _wrap_gtk_tree_store_prepend (GtkTreeStore *store, GtkTreeIter *parent)
933 {
934 GtkTreeIter new;
935 gtk_tree_store_prepend (store, &new, parent);
936 return gtk_tree_iter_copy (&new);
937 }
938
939 GtkTreeIter*
_wrap_gtk_tree_store_append(GtkTreeStore * store,GtkTreeIter * parent)940 _wrap_gtk_tree_store_append (GtkTreeStore *store, GtkTreeIter *parent)
941 {
942 GtkTreeIter new;
943 gtk_tree_store_append (store, &new, parent);
944 return gtk_tree_iter_copy (&new);
945 }
946
947 SCM
_wrap_gtk_tree_view_get_path_at_pos(GtkTreeView * treeview,gint x,gint y)948 _wrap_gtk_tree_view_get_path_at_pos (GtkTreeView *treeview,
949 gint x, gint y)
950 {
951 GtkTreePath *path;
952 GtkTreeViewColumn *column;
953 gint cell_x, cell_y;
954
955 if (gtk_tree_view_get_path_at_pos (treeview, x, y, &path, &column,
956 &cell_x, &cell_y)) {
957 SCM spath = guile_gtk_tree_path_to_scm (path);
958 SCM scolumn = scm_c_gtype_instance_to_scm (column);
959
960 gtk_tree_path_free (path);
961
962 return scm_values (SCM_LIST4 (spath, scolumn, scm_from_int (cell_x),
963 scm_from_int (cell_y)));
964 }
965
966 return scm_values (
967 SCM_LIST4 (SCM_BOOL_F, SCM_BOOL_F, SCM_BOOL_F, SCM_BOOL_F));
968 }
969
970 static void
with_cell_data_func(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * tree_model,GtkTreeIter * iter,gpointer data)971 with_cell_data_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
972 GtkTreeModel *tree_model, GtkTreeIter *iter,
973 gpointer data)
974 {
975 SCM proc, scolumn, scell, smodel, siter;
976 proc = GPOINTER_TO_SCM (data);
977 scolumn = scm_c_gtype_instance_to_scm ((GTypeInstance*)tree_column);
978 scell = scm_c_gtype_instance_to_scm ((GTypeInstance*)cell);
979 smodel = scm_c_gtype_instance_to_scm ((GTypeInstance*)tree_model);
980 siter = scm_c_gvalue_new_from_boxed (GTK_TYPE_TREE_ITER, iter);
981
982 scm_call_4 (proc, scolumn, scell, smodel, siter);
983 }
984
985 static void
cell_data_func(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * tree_model,GtkTreeIter * iter,gpointer data)986 cell_data_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
987 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
988 {
989 scm_dynwind_guile_v__p_p_p_p_p (scm_with_guile, with_cell_data_func,
990 tree_column, cell, tree_model, iter,
991 data);
992 }
993
994 void
_wrap_gtk_tree_view_column_set_cell_data_func(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell_renderer,SCM proc)995 _wrap_gtk_tree_view_column_set_cell_data_func (GtkTreeViewColumn *tree_column,
996 GtkCellRenderer *cell_renderer,
997 SCM proc)
998 {
999 gtk_tree_view_column_set_cell_data_func
1000 (tree_column, cell_renderer, cell_data_func,
1001 SCM_TO_GPOINTER (scm_gc_protect_object (proc)),
1002 (GtkDestroyNotify)scm_gc_unprotect_object);
1003 }
1004
1005 guint
_wrap_gtk_ui_manager_add_ui_from_string(GtkUIManager * ui,const gchar * string,GError ** error)1006 _wrap_gtk_ui_manager_add_ui_from_string (GtkUIManager *ui, const gchar *string,
1007 GError **error)
1008 {
1009 return gtk_ui_manager_add_ui_from_string (ui, string, -1, error);
1010 }
1011
1012 void
_wrap_gtk_drag_dest_set(GtkWidget * widget,GtkDestDefaults flags,const GList * types,GdkDragAction actions)1013 _wrap_gtk_drag_dest_set (GtkWidget *widget, GtkDestDefaults flags,
1014 const GList* types, GdkDragAction actions)
1015 {
1016 const GList *l;
1017 gint i, n;
1018 GtkTargetEntry* entries;
1019
1020 n = g_list_length ((GList*)types);
1021 entries = g_new0 (GtkTargetEntry, n);
1022 for (i=0, l=types; i<n; i++, l=l->next)
1023 entries[i].target = (gchar*)l->data;
1024
1025 gtk_drag_dest_set (widget, flags, entries, n, actions);
1026 }
1027
1028 GdkGC*
gtk_style_get_fg_gc(GtkStyle * style,GtkStateType state)1029 gtk_style_get_fg_gc (GtkStyle *style, GtkStateType state)
1030 {
1031 return style->fg_gc[state];
1032 }
1033
1034 GdkGC*
gtk_style_get_bg_gc(GtkStyle * style,GtkStateType state)1035 gtk_style_get_bg_gc (GtkStyle *style, GtkStateType state)
1036 {
1037 return style->bg_gc[state];
1038 }
1039
1040 GdkGC*
gtk_style_get_white_gc(GtkStyle * style)1041 gtk_style_get_white_gc (GtkStyle *style)
1042 {
1043 return style->white_gc;
1044 }
1045
1046 GdkGC*
gtk_style_get_black_gc(GtkStyle * style)1047 gtk_style_get_black_gc (GtkStyle *style)
1048 {
1049 return style->black_gc;
1050 }
1051
1052 GdkWindow*
gtk_widget_get_window(GtkWidget * widget)1053 gtk_widget_get_window (GtkWidget *widget)
1054 {
1055 return GTK_WIDGET_NO_WINDOW (widget) ? NULL : widget->window;
1056 }
1057
1058 GdkRectangle*
_wrap_gtk_widget_get_allocation(GtkWidget * widget)1059 _wrap_gtk_widget_get_allocation (GtkWidget *widget)
1060 {
1061 GdkRectangle *ret = g_new (GdkRectangle, 1);
1062 #if GTK_CHECK_VERSION(2,18,0)
1063 gtk_widget_get_allocation (widget, (GtkAllocation*)ret);
1064 #else
1065 *ret = widget->allocation;
1066 #endif
1067 return ret;
1068 }
1069
1070 GtkStateType
gtk_widget_get_state(GtkWidget * widget)1071 gtk_widget_get_state (GtkWidget *widget)
1072 {
1073 g_return_val_if_fail (widget != NULL, 0);
1074 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
1075
1076 return GTK_WIDGET_STATE (widget);
1077 }
1078