Update Spanish translation
[gnumeric.git] / src / dialogs / dialog-function-select.c
blob17f39906a55f33460a6eea024d1d47209d2360b6
1 /*
2 * dialog-function-select.c: Implements the function selector
4 * Authors:
5 * Michael Meeks <michael@ximian.com>
6 * Andreas J. Guelzow <aguelzow@pyrshep.ca>
8 * Copyright (C) 2003-2010 Andreas J. Guelzow <aguelzow@pyrshep.ca>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <https://www.gnu.org/licenses/>.
24 #include <gnumeric-config.h>
25 #include <glib/gi18n-lib.h>
26 #include <gnumeric.h>
27 #include <dialogs/dialogs.h>
28 #include <dialogs/help.h>
30 #include <gui-util.h>
31 #include <gutils.h>
32 #include <func.h>
33 #include <workbook.h>
34 #include <wbc-gtk.h>
35 #include <application.h>
36 #include <position.h>
37 #include <expr.h>
38 #include <value.h>
39 #include <sheet.h>
40 #include <gnumeric-conf.h>
41 #include <gnm-format.h>
42 #include <auto-format.h>
44 #include <gsf/gsf-impl-utils.h>
45 #include <string.h>
47 #define FUNCTION_SELECT_KEY "function-selector-dialog"
48 #define FUNCTION_SELECT_HELP_KEY "function-selector-dialog-help-mode"
49 #define FUNCTION_SELECT_PASTE_KEY "function-selector-dialog-paste-mode"
50 #define FUNCTION_SELECT_DIALOG_KEY "function-selector-dialog"
52 #define UNICODE_ELLIPSIS "\xe2\x80\xa6"
54 typedef enum {
55 GURU_MODE = 0,
56 HELP_MODE,
57 PASTE_MODE
58 } DialogMode;
60 typedef struct {
61 WBCGtk *wbcg;
62 Workbook *wb;
63 Sheet *sheet;
65 gboolean localized_function_names;
67 GtkBuilder *gui;
68 GtkWidget *dialog;
69 GtkWidget *ok_button;
70 GtkWidget *paste_button;
71 GtkListStore *model;
72 GtkComboBox *cb;
73 GtkListStore *model_functions;
74 GtkTreeModel *model_filter;
75 GtkTreeView *treeview;
76 GtkTextView *description_view;
77 GtkWidget *search_entry;
79 GSList *recent_funcs;
81 struct {
82 gint from;
83 gint to;
84 char *prefix;
85 } paste;
87 DialogMode mode;
88 char const *formula_guru_key;
89 } FunctionSelectState;
91 enum {
92 CAT_NAME,
93 CATEGORY,
94 CAT_SEPARATOR,
95 NUM_CAT_COLUMNS
97 enum {
98 FUN_NAME,
99 FUNCTION,
100 FUNCTION_DESC,
101 FUNCTION_PAL,
102 FUNCTION_CAT,
103 FUNCTION_VISIBLE,
104 FUNCTION_RECENT,
105 FUNCTION_USED,
106 NUM_COLUMNS
109 /*************************************************************************/
110 /* Search Functions */
111 /*************************************************************************/
113 typedef struct {
114 char const *text;
115 gboolean recent_only;
116 gboolean used_only;
117 GnmFuncGroup const * cat;
118 } search_t;
120 static gboolean
121 cb_dialog_function_select_search_all (GtkTreeModel *model,
122 G_GNUC_UNUSED GtkTreePath *path,
123 GtkTreeIter *iter, gpointer data)
125 search_t *specs = data;
126 gchar *name;
127 gchar *desc;
128 gboolean visible, was_visible, recent, used;
129 GnmFuncGroup const * cat;
131 gtk_tree_model_get (model, iter,
132 FUN_NAME, &name,
133 FUNCTION_DESC, &desc,
134 FUNCTION_VISIBLE, &was_visible,
135 FUNCTION_RECENT, &recent,
136 FUNCTION_USED, &used,
137 FUNCTION_CAT, &cat,
138 -1);
140 if (specs->recent_only && !recent)
141 visible = FALSE;
142 else if (specs->used_only && !used)
143 visible = FALSE;
144 else if (specs->cat != NULL && specs->cat != cat)
145 visible = FALSE;
146 else if (specs->text == NULL)
147 visible = TRUE;
148 else {
149 gchar *name_n, *name_cf, *text_n, *text_cf;
151 text_n = g_utf8_normalize (specs->text, -1, G_NORMALIZE_ALL);
152 text_cf = g_utf8_casefold(text_n, -1);
154 name_n = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
155 name_cf = g_utf8_casefold(name_n, -1);
156 visible = (NULL != g_strstr_len (name_cf, -1, text_cf));
157 g_free (name_n);
158 g_free (name_cf);
160 if (!visible) {
161 name_n = g_utf8_normalize (desc, -1, G_NORMALIZE_ALL);
162 name_cf = g_utf8_casefold(name_n, -1);
163 visible = (NULL != g_strstr_len (name_cf, -1, text_cf));
164 g_free (name_n);
165 g_free (name_cf);
168 g_free (text_n);
169 g_free (text_cf);
172 g_free (name);
173 g_free (desc);
175 if (visible != was_visible)
176 gtk_list_store_set (GTK_LIST_STORE (model), iter,
177 FUNCTION_VISIBLE, visible,
178 -1);
179 return FALSE;
182 static void
183 dialog_function_select_search (GtkEntry *entry, gpointer data)
185 search_t specs = {NULL, FALSE, FALSE, NULL};
186 FunctionSelectState *state = data;
187 GtkTreeIter iter;
189 if (0 != gtk_entry_get_text_length (entry))
190 specs.text = gtk_entry_get_text (entry);
192 if (gtk_combo_box_get_active_iter (state->cb, &iter)) {
193 gtk_tree_model_get (GTK_TREE_MODEL (state->model), &iter,
194 CATEGORY, &specs.cat,
195 -1);
196 specs.recent_only
197 = (specs.cat != NULL &&
198 specs.cat == GINT_TO_POINTER(-1));
199 specs.used_only
200 = (specs.cat != NULL &&
201 specs.cat == GINT_TO_POINTER(-2));
202 if (specs.recent_only || specs.used_only)
203 specs.cat = NULL;
206 gtk_tree_model_foreach (GTK_TREE_MODEL (state->model_functions),
207 cb_dialog_function_select_search_all,
208 (gpointer) &specs);
211 static void
212 dialog_function_select_erase_search_entry (GtkEntry *entry,
213 G_GNUC_UNUSED GtkEntryIconPosition icon_pos,
214 G_GNUC_UNUSED GdkEvent *event,
215 gpointer data)
217 gtk_entry_set_text (entry, "");
218 dialog_function_select_search (entry, data);
221 static void
222 dialog_function_select_cat_changed (G_GNUC_UNUSED GtkComboBox *widget,
223 gpointer data)
225 FunctionSelectState *state = data;
227 dialog_function_select_search (GTK_ENTRY (state->search_entry),
228 data);
231 /*************************************************************************/
233 static gboolean
234 cb_dialog_function_load_recent_funcs(GtkTreeModel *model,
235 G_GNUC_UNUSED GtkTreePath *path,
236 GtkTreeIter *iter,
237 gpointer data)
239 gpointer this;
241 gtk_tree_model_get (model, iter,
242 FUNCTION, &this,
243 -1);
244 if (this == data) {
245 gtk_list_store_set (GTK_LIST_STORE (model), iter,
246 FUNCTION_RECENT, TRUE,
247 -1);
248 return TRUE;
250 return FALSE;
253 static void
254 dialog_function_load_recent_funcs (FunctionSelectState *state)
256 GSList const *recent_funcs;
258 for (recent_funcs = gnm_conf_get_functionselector_recentfunctions ();
259 recent_funcs;
260 recent_funcs = recent_funcs->next) {
261 char const *name = recent_funcs->data;
262 GnmFunc *fd;
264 if (name == NULL)
265 continue;
267 fd = gnm_func_lookup (name, NULL);
268 if (fd) {
269 state->recent_funcs = g_slist_prepend (state->recent_funcs, fd);
270 gtk_tree_model_foreach (GTK_TREE_MODEL (state->model_functions),
271 cb_dialog_function_load_recent_funcs,
272 fd);
277 static void
278 dialog_function_write_recent_func (FunctionSelectState *state, GnmFunc const *fd)
280 GSList *rec_funcs;
281 GSList *gconf_value_list = NULL;
282 guint ulimit = gnm_conf_get_functionselector_num_of_recent ();
284 state->recent_funcs = g_slist_remove (state->recent_funcs, (gpointer) fd);
285 state->recent_funcs = g_slist_prepend (state->recent_funcs, (gpointer) fd);
287 while (g_slist_length (state->recent_funcs) > ulimit)
288 state->recent_funcs = g_slist_remove (state->recent_funcs,
289 g_slist_last (state->recent_funcs)->data);
291 for (rec_funcs = state->recent_funcs; rec_funcs; rec_funcs = rec_funcs->next) {
292 gconf_value_list = g_slist_prepend
293 (gconf_value_list,
294 g_strdup (gnm_func_get_name (rec_funcs->data,
295 state->localized_function_names)));
297 gnm_conf_set_functionselector_recentfunctions (gconf_value_list);
298 g_slist_free_full (gconf_value_list, g_free);
301 static gboolean
302 cb_unref (GtkTreeModel *model, G_GNUC_UNUSED GtkTreePath *path,
303 GtkTreeIter *iter, G_GNUC_UNUSED gpointer data)
305 GnmFunc *f;
307 gtk_tree_model_get (model, iter,
308 FUNCTION, &f,
309 -1);
310 gnm_func_dec_usage (f);
311 return FALSE;
314 static void
315 cb_dialog_function_select_destroy (FunctionSelectState *state)
317 if (state->formula_guru_key &&
318 gnm_dialog_raise_if_exists (state->wbcg, state->formula_guru_key)) {
319 /* The formula guru is waiting for us.*/
320 state->formula_guru_key = NULL;
321 dialog_formula_guru (state->wbcg, NULL);
324 if (state->gui != NULL)
325 g_object_unref (state->gui);
326 g_slist_free (state->recent_funcs);
327 gtk_tree_model_foreach (GTK_TREE_MODEL (state->model_functions),
328 cb_unref,
329 NULL);
330 g_free (state->paste.prefix);
331 g_free (state);
335 * cb_dialog_function_select_cancel_clicked:
336 * @button:
337 * @state:
339 * Close (destroy) the dialog
341 static void
342 cb_dialog_function_select_cancel_clicked (G_GNUC_UNUSED GtkWidget *button,
343 FunctionSelectState *state)
345 gtk_widget_destroy (state->dialog);
346 return;
350 * cb_dialog_function_select_ok_clicked:
351 * @button:
352 * @state:
354 * Close (destroy) the dialog
356 static void
357 cb_dialog_function_select_ok_clicked (G_GNUC_UNUSED GtkWidget *button,
358 FunctionSelectState *state)
360 GtkTreeIter iter;
361 GtkTreeModel *model;
362 GnmFunc *func;
363 GtkTreeSelection *the_selection = gtk_tree_view_get_selection (state->treeview);
365 if (state->formula_guru_key != NULL &&
366 gtk_tree_selection_get_selected (the_selection, &model, &iter)) {
367 WBCGtk *wbcg = state->wbcg;
368 gtk_tree_model_get (model, &iter,
369 FUNCTION, &func,
370 -1);
371 dialog_function_write_recent_func (state, func);
372 state->formula_guru_key = NULL;
373 gtk_widget_destroy (state->dialog);
374 dialog_formula_guru (wbcg, func);
375 return;
378 gtk_widget_destroy (state->dialog);
379 return;
383 * cb_dialog_function_select_paste_clicked:
384 * @button:
385 * @state:
387 * Close (destroy) the dialog
389 static void
390 cb_dialog_function_select_paste_clicked (G_GNUC_UNUSED GtkWidget *button,
391 FunctionSelectState *state)
393 GtkTreeIter iter;
394 GtkTreeModel *model;
395 GnmFunc *func;
396 GtkTreeSelection *the_selection = gtk_tree_view_get_selection (state->treeview);
398 if (gtk_tree_selection_get_selected (the_selection, &model, &iter) &&
399 wbcg_edit_start (state->wbcg, FALSE, FALSE)) {
400 GtkEditable *entry
401 = GTK_EDITABLE (wbcg_get_entry (state->wbcg));
402 gint position;
403 gtk_tree_model_get (model, &iter,
404 FUNCTION, &func,
405 -1);
406 if (func != NULL) {
407 dialog_function_write_recent_func (state, func);
408 if (state->paste.from >= 0)
409 gtk_editable_select_region
410 (entry, state->paste.from,
411 state->paste.to);
412 gtk_editable_delete_selection (entry);
413 position = gtk_editable_get_position (entry);
414 gtk_editable_insert_text
415 (entry, func->name, -1, &position);
416 gtk_editable_set_position (entry, position);
420 gtk_widget_destroy (state->dialog);
421 return;
424 static void
425 cb_dialog_function_row_activated (G_GNUC_UNUSED GtkTreeView *tree_view,
426 G_GNUC_UNUSED GtkTreePath *path,
427 G_GNUC_UNUSED GtkTreeViewColumn *column,
428 FunctionSelectState *state)
430 switch (state->mode) {
431 case GURU_MODE:
432 cb_dialog_function_select_ok_clicked (NULL, state);
433 return;
434 case PASTE_MODE:
435 cb_dialog_function_select_paste_clicked (NULL, state);
436 return;
437 default:
438 return;
442 static gint
443 dialog_function_select_by_name (gconstpointer a_, gconstpointer b_,
444 gpointer user)
446 GnmFunc const * const a = (GnmFunc const * const)a_;
447 GnmFunc const * const b = (GnmFunc const * const)b_;
448 FunctionSelectState const *state = user;
449 gboolean localized = state->localized_function_names;
451 return g_utf8_collate (gnm_func_get_name (a, localized),
452 gnm_func_get_name (b, localized));
455 /*************************************************************************/
456 /* Functions related to the category selector */
457 /*************************************************************************/
459 typedef struct {
460 char const *name;
461 GtkTreeIter *iter;
462 } dialog_function_select_load_cb_t;
464 static gboolean
465 cb_dialog_function_select_load_cb (GtkTreeModel *model,
466 G_GNUC_UNUSED GtkTreePath *path,
467 GtkTreeIter *iter,
468 gpointer data)
470 dialog_function_select_load_cb_t *specs = data;
471 gchar *name;
472 gpointer ptr;
473 gboolean res;
475 gtk_tree_model_get (model, iter,
476 CAT_NAME, &name,
477 CATEGORY, &ptr,
478 -1);
480 if (ptr == NULL || ptr == GINT_TO_POINTER(-1)
481 || ptr == GINT_TO_POINTER(-2))
482 res = FALSE;
483 else if (go_utf8_collate_casefold (specs->name, name) < 0) {
484 specs->iter = gtk_tree_iter_copy (iter);
485 res = TRUE;
486 } else
487 res = FALSE;
489 g_free (name);
491 return res;
494 static void
495 dialog_function_select_load_cb (FunctionSelectState *state)
497 int i = 0;
498 GtkTreeIter p_iter;
499 GnmFuncGroup const * cat;
501 gtk_list_store_clear (state->model);
503 gtk_list_store_insert_before (state->model, &p_iter, NULL);
504 gtk_list_store_set (state->model, &p_iter,
505 CAT_NAME, _("All Functions"),
506 CATEGORY, NULL,
507 CAT_SEPARATOR, FALSE,
508 -1);
509 gtk_list_store_insert_before (state->model, &p_iter, NULL);
510 gtk_list_store_set (state->model, &p_iter,
511 CAT_NAME, _("Recently Used"),
512 CATEGORY, GINT_TO_POINTER(-1),
513 CAT_SEPARATOR, FALSE,
514 -1);
515 gtk_list_store_insert_before (state->model, &p_iter, NULL);
516 gtk_list_store_set (state->model, &p_iter,
517 CAT_NAME, _("In Use"),
518 CATEGORY, GINT_TO_POINTER(-2),
519 CAT_SEPARATOR, FALSE,
520 -1);
522 gtk_list_store_insert_before (state->model, &p_iter, NULL);
523 gtk_list_store_set (state->model, &p_iter,
524 CAT_NAME, "-",
525 CATEGORY, NULL,
526 CAT_SEPARATOR, TRUE,
527 -1);
529 while ((cat = gnm_func_group_get_nth (i++)) != NULL) {
530 dialog_function_select_load_cb_t specs;
531 specs.name = _(cat->display_name->str);
532 specs.iter = NULL;
534 gtk_tree_model_foreach (GTK_TREE_MODEL (state->model),
535 cb_dialog_function_select_load_cb,
536 &specs);
538 gtk_list_store_insert_before (state->model, &p_iter, specs.iter);
539 gtk_list_store_set (state->model, &p_iter,
540 CAT_NAME, specs.name,
541 CATEGORY, cat,
542 CAT_SEPARATOR, FALSE,
543 -1);
544 if (specs.iter != NULL)
545 gtk_tree_iter_free (specs.iter);
549 static gboolean
550 dialog_function_select_cat_row_separator (GtkTreeModel *model,
551 GtkTreeIter *iter,
552 G_GNUC_UNUSED gpointer data)
554 gboolean sep;
556 gtk_tree_model_get (model, iter,
557 CAT_SEPARATOR, &sep,
558 -1);
560 return sep;
563 /*************************************************************************/
564 /* Functions related to the description field */
565 /*************************************************************************/
567 static GtkTextTag *
568 make_link (GtkTextBuffer *description, GtkWidget *target, const char *name,
569 GCallback cb, gpointer user)
571 GtkTextTag *link =
572 gtk_text_tag_table_lookup
573 (gtk_text_buffer_get_tag_table (description), name);
575 if (!link) {
576 GdkRGBA link_color;
577 char *link_color_text;
579 gnm_get_link_color (target, &link_color);
580 link_color_text = gdk_rgba_to_string (&link_color);
582 link = gtk_text_buffer_create_tag
583 (description, name,
584 "underline", PANGO_UNDERLINE_SINGLE,
585 "foreground", link_color_text,
586 NULL);
588 g_free (link_color_text);
590 if (cb)
591 g_signal_connect (link, "event", cb, user);
594 return link;
597 static gboolean
598 cb_link_event (GtkTextTag *link, G_GNUC_UNUSED GObject *trigger,
599 GdkEvent *event, G_GNUC_UNUSED GtkTextIter *iter,
600 G_GNUC_UNUSED gpointer user)
602 switch (event->type) {
603 case GDK_BUTTON_PRESS:
604 case GDK_2BUTTON_PRESS:
605 case GDK_3BUTTON_PRESS: {
606 GdkEventButton *eb = (GdkEventButton *)event;
607 const char *uri = g_object_get_data (G_OBJECT (link), "uri");
608 GError *error = NULL;
610 if (eb->button != 1)
611 break;
612 if (event->type != GDK_BUTTON_PRESS)
613 return TRUE;
615 error = go_gtk_url_show (uri, gdk_event_get_screen (event));
616 if (error) {
617 g_printerr ("Failed to show %s\n(%s)\n",
618 uri,
619 error->message);
620 g_error_free (error);
623 return TRUE;
626 #if 0
627 case GDK_ENTER_NOTIFY:
628 case GDK_LEAVE_NOTIFY:
629 /* We aren't getting these. */
630 #endif
631 default:
632 break;
635 return FALSE;
638 static char *
639 make_expr_example (Sheet *sheet, const char *text,
640 gboolean localized, gboolean consider_format)
642 GnmLocale *oldlocale = NULL;
643 GnmExprTop const *texpr;
644 char *res;
645 GnmParsePos pp;
646 GnmEvalPos ep;
647 GnmConventions const *convs = gnm_conventions_default;
648 char *tmp_text = NULL;
649 GOFormat const *fmt = NULL;
651 if (consider_format &&
652 g_ascii_strncasecmp (text, "TEXT(", 5) == 0 &&
653 text[strlen(text) - 1] == ')') {
654 char *p;
655 tmp_text = g_strdup (text + 5);
656 p = tmp_text + strlen (tmp_text) - 1;
657 while (p >= tmp_text && p[0] != '"') p--;
658 p[0] = 0;
659 while (p >= tmp_text && p[0] != '"') p--;
660 fmt = go_format_new_from_XL (p + 1);
661 while (p >= tmp_text && p[0] != ',') p--;
662 *p = 0;
665 eval_pos_init_sheet (&ep, sheet);
666 parse_pos_init_evalpos (&pp, &ep);
668 if (!localized)
669 oldlocale = gnm_push_C_locale ();
670 texpr = gnm_expr_parse_str (text, &pp,
671 GNM_EXPR_PARSE_DEFAULT,
672 convs,
673 NULL);
674 if (!localized)
675 gnm_pop_C_locale (oldlocale);
677 if (texpr) {
678 char *etxt = gnm_expr_top_as_string (texpr, &pp, convs);
679 GnmValue *val = gnm_expr_top_eval
680 (texpr, &ep, GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
681 char *vtxt;
683 if (!fmt)
684 fmt = gnm_auto_style_format_suggest (texpr, &ep);
685 vtxt = format_value (fmt, val, -1, sheet_date_conv (sheet));
687 gnm_expr_top_unref (texpr);
688 value_release (val);
690 res = g_strdup_printf (_("%s evaluates to %s."), etxt, vtxt);
692 g_free (etxt);
693 g_free (vtxt);
694 } else {
695 g_warning ("Failed to parse [%s]", text);
696 res = g_strdup ("");
699 g_free (tmp_text);
700 go_format_unref (fmt);
702 return res;
707 #define ADD_LTEXT(text,len) gtk_text_buffer_insert (description, &ti, (text), (len))
708 #define ADD_TEXT(text) ADD_LTEXT((text),-1)
709 #define ADD_BOLD_TEXT(text,len) gtk_text_buffer_insert_with_tags (description, &ti, (text), (len), bold, NULL)
710 #define ADD_LINK_TEXT(text,len) gtk_text_buffer_insert_with_tags (description, &ti, (text), (len), link, NULL)
711 #define ADD_TEXT_WITH_ARGS(text) { const char *t = text; while (*t) { const char *at = strstr (t, "@{"); \
712 if (at == NULL) { ADD_TEXT(t); break;} ADD_LTEXT(t, at - t); t = at + 2; at = strchr (t,'}'); \
713 if (at != NULL) { ADD_BOLD_TEXT(t, at - t); t = at + 1; } else {ADD_TEXT (t); break;}}}
714 #define FINISH_ARGS if (seen_args && !args_finished) {\
715 gint min, max; \
716 gnm_func_count_args (func, &min, &max);\
717 if (max == G_MAXINT) { \
718 ADD_BOLD_TEXT(UNICODE_ELLIPSIS, strlen(UNICODE_ELLIPSIS)); \
719 ADD_LTEXT("\n",1); \
720 args_finished = TRUE; \
724 static void
725 describe_new_style (GtkTextBuffer *description,
726 GtkWidget *target,
727 GnmFunc *func, Sheet *sheet)
729 GnmFuncHelp const *help;
730 GtkTextIter ti;
731 GtkTextTag *bold =
732 gtk_text_buffer_create_tag
733 (description, NULL,
734 "weight", PANGO_WEIGHT_BOLD,
735 NULL);
736 gboolean seen_args = FALSE;
737 gboolean args_finished = FALSE;
738 gboolean seen_examples = FALSE;
739 gboolean seen_extref = FALSE;
740 gboolean is_TEXT =
741 g_ascii_strcasecmp (gnm_func_get_name (func, FALSE), "TEXT") == 0;
742 int n;
744 gtk_text_buffer_get_end_iter (description, &ti);
746 help = gnm_func_get_help (func, &n);
748 for (; n-- > 0; help++) {
749 switch (help->type) {
750 case GNM_FUNC_HELP_NAME: {
751 const char *text = gnm_func_gettext (func, help->text);
752 const char *colon = strchr (text, ':');
753 if (!colon)
754 break;
755 ADD_BOLD_TEXT (text, colon - text);
756 ADD_TEXT (": ");
757 ADD_TEXT_WITH_ARGS (colon + 1);
758 ADD_TEXT ("\n\n");
759 break;
761 case GNM_FUNC_HELP_ARG: {
762 const char *text = gnm_func_gettext (func, help->text);
763 const char *colon = strchr (text, ':');
764 if (!colon)
765 break;
767 if (!seen_args) {
768 seen_args = TRUE;
769 ADD_TEXT (_("Arguments:"));
770 ADD_TEXT ("\n");
773 ADD_BOLD_TEXT (text, colon - text);
774 ADD_TEXT (": ");
775 ADD_TEXT_WITH_ARGS (colon + 1);
776 ADD_TEXT ("\n");
777 break;
779 case GNM_FUNC_HELP_DESCRIPTION: {
780 const char *text = gnm_func_gettext (func, help->text);
781 FINISH_ARGS;
782 ADD_TEXT ("\n");
783 ADD_TEXT_WITH_ARGS (text);
784 ADD_TEXT ("\n");
785 break;
787 case GNM_FUNC_HELP_NOTE: {
788 const char *text = gnm_func_gettext (func, help->text);
789 FINISH_ARGS;
790 ADD_TEXT ("\n");
791 ADD_TEXT (_("Note: "));
792 ADD_TEXT_WITH_ARGS (text);
793 ADD_TEXT ("\n");
794 break;
796 case GNM_FUNC_HELP_EXAMPLES: {
797 const char *text = gnm_func_gettext (func, help->text);
798 gboolean was_translated = (text != help->text);
800 FINISH_ARGS;
801 if (!seen_examples) {
802 seen_examples = TRUE;
803 ADD_TEXT ("\n");
804 ADD_TEXT (_("Examples:"));
805 ADD_TEXT ("\n");
808 if (text[0] == '=') {
809 char *example =
810 make_expr_example (sheet, text + 1,
811 was_translated,
812 !is_TEXT);
813 ADD_TEXT (example);
814 g_free (example);
815 } else {
816 ADD_TEXT_WITH_ARGS (text);
818 ADD_TEXT ("\n");
819 break;
821 case GNM_FUNC_HELP_SEEALSO: {
822 const char *text = help->text; /* Not translated */
823 const char *pre = _("See also: ");
824 GtkTextTag *link =
825 make_link (description, target, "LINK",
826 NULL, NULL);
828 FINISH_ARGS;
829 ADD_TEXT ("\n");
831 while (*text) {
832 const char *end = strchr (text, ',');
833 if (!end) end = text + strlen (text);
835 ADD_TEXT (pre);
836 ADD_LINK_TEXT (text, end - text);
838 text = *end ? end + 1 : end;
840 pre = _(", ");
842 ADD_TEXT ("\n");
843 break;
845 case GNM_FUNC_HELP_EXTREF: {
846 GtkTextTag *link;
847 char *uri, *tagname;
848 const char *text;
850 FINISH_ARGS;
852 * We put in just one link and let the web page handle
853 * the rest. In particular, we do not even look at
854 * what the help->text is here.
856 if (seen_extref)
857 break;
859 uri = g_strdup_printf ("http://www.gnumeric.org/func-doc.shtml?%s", func->name);
861 tagname = g_strdup_printf ("EXTLINK-%s", func->name);
862 link = make_link
863 (description, target, tagname,
864 G_CALLBACK (cb_link_event), NULL);
866 g_object_set_data_full (G_OBJECT (link),
867 "uri", uri,
868 g_free);
870 ADD_TEXT (_("Further information: "));
872 text = _("online descriptions");
873 ADD_LINK_TEXT (text, strlen (text));
875 ADD_TEXT (".\n");
877 seen_extref = TRUE;
878 break;
880 case GNM_FUNC_HELP_EXCEL: {
881 const char *text = gnm_func_gettext (func, help->text);
882 FINISH_ARGS;
883 ADD_TEXT ("\n");
884 ADD_TEXT (_("Microsoft Excel: "));
885 ADD_TEXT_WITH_ARGS (text);
886 ADD_TEXT ("\n");
887 break;
889 case GNM_FUNC_HELP_ODF: {
890 const char *text = gnm_func_gettext (func, help->text);
891 FINISH_ARGS;
892 ADD_TEXT ("\n");
893 ADD_TEXT (_("ODF (OpenFormula): "));
894 ADD_TEXT_WITH_ARGS (text);
895 ADD_TEXT ("\n");
896 break;
898 default:
899 break;
902 FINISH_ARGS;
905 #undef ADD_TEXT_WITH_ARGS
906 #undef ADD_TEXT
907 #undef ADD_LTEXT
908 #undef ADD_BOLD_TEXT
909 #undef ADD_LINK_TEXT
910 #undef FINISH_ARGS
912 typedef struct {
913 GnmFunc *fd;
914 FunctionSelectState *state;
915 GtkTreePath *path;
916 } dialog_function_select_find_func_t;
919 static gboolean
920 dialog_function_select_search_func (GtkTreeModel *model,
921 GtkTreePath *path,
922 GtkTreeIter *iter,
923 gpointer dt)
925 GnmFunc* fd;
926 dialog_function_select_find_func_t *data = dt;
928 gtk_tree_model_get (model, iter,
929 FUNCTION, &fd,
930 -1);
931 if (fd == data->fd) {
932 data->path = gtk_tree_path_copy (path);
933 return TRUE;
935 return FALSE;
938 static void
939 dialog_function_select_find_func (FunctionSelectState *state, char* name)
941 GnmFunc *fd;
943 if (name == NULL)
944 return;
946 fd = gnm_func_lookup (name, state->wb);
947 if (fd != NULL) {
948 dialog_function_select_find_func_t data = {fd, state, NULL};
949 GtkTreeSelection *selection = gtk_tree_view_get_selection
950 (state->treeview);
951 GtkTreePath *path;
953 gtk_tree_model_foreach (GTK_TREE_MODEL (state->model_functions),
954 dialog_function_select_search_func,
955 &data);
956 if (data.path != NULL) {
957 GtkTreeIter iter;
958 if (gtk_tree_model_get_iter
959 (GTK_TREE_MODEL (state->model_functions), &iter,
960 data.path))
961 gtk_list_store_set (state->model_functions,
962 &iter,
963 FUNCTION_VISIBLE, TRUE,
964 -1);
966 path = gtk_tree_model_filter_convert_child_path_to_path
967 (GTK_TREE_MODEL_FILTER (state->model_filter),
968 data.path);
970 gtk_tree_selection_select_path (selection,
971 path);
972 gtk_tree_view_scroll_to_cell (state->treeview, path,
973 NULL, FALSE, 0., 0.);
974 gtk_tree_path_free (path);
975 gtk_tree_path_free (data.path);
976 } else
977 g_warning ("Function %s was not found in its category", name);
979 } else
980 g_warning ("Function %s was not found", name);
983 typedef struct {
984 FunctionSelectState *state;
985 gchar * name;
986 } cb_dialog_function_select_idle_handler_t;
988 static gboolean
989 cb_dialog_function_select_idle_handler (gpointer dt)
991 cb_dialog_function_select_idle_handler_t *data = dt;
993 dialog_function_select_find_func (data->state, data->name);
995 g_free (data->name);
996 g_free (data);
998 return FALSE;
1001 static void
1002 cb_description_clicked (GtkTextBuffer *textbuffer,
1003 GtkTextIter *location,
1004 GtkTextMark *mark,
1005 FunctionSelectState *state)
1007 const char * mark_name;
1008 GtkTextTag *link;
1009 GtkTextIter *start;
1010 GtkTextIter *end;
1011 cb_dialog_function_select_idle_handler_t *data;
1013 if ((mark == NULL) || ((mark_name = gtk_text_mark_get_name (mark)) == NULL)
1014 || (strcmp(mark_name, "selection_bound") != 0))
1015 return;
1017 link = gtk_text_tag_table_lookup
1018 (gtk_text_buffer_get_tag_table (textbuffer), "LINK");
1020 if ((link == NULL) || !gtk_text_iter_has_tag (location, link))
1021 return;
1023 start = gtk_text_iter_copy (location);
1024 end = gtk_text_iter_copy (location);
1026 if (!gtk_text_iter_begins_tag (start, link))
1027 gtk_text_iter_backward_to_tag_toggle (start, link);
1028 if (!gtk_text_iter_ends_tag (end, link))
1029 gtk_text_iter_forward_to_tag_toggle (end, link);
1031 data = g_new(cb_dialog_function_select_idle_handler_t, 1);
1033 data->name = gtk_text_buffer_get_text (textbuffer, start, end, FALSE);
1034 gtk_text_iter_free (start);
1035 gtk_text_iter_free (end);
1036 data->state = state;
1038 g_idle_add_full (G_PRIORITY_HIGH_IDLE, cb_dialog_function_select_idle_handler,
1039 data, NULL);
1042 static void
1043 cb_dialog_function_select_fun_selection_changed (GtkTreeSelection *selection,
1044 FunctionSelectState *state)
1046 GtkTreeIter iter;
1047 GtkTreeModel *model;
1048 GnmFunc *func;
1049 GtkTextBuffer *description;
1050 GtkTextMark *mark;
1051 gboolean active = FALSE;
1053 description = gtk_text_view_get_buffer (state->description_view);
1055 mark = gtk_text_buffer_get_mark (description, "start-mark");
1056 gtk_text_view_scroll_to_mark (state->description_view, mark,
1057 0.1, TRUE, 0.0, 0.0);
1058 gtk_text_buffer_set_text (description, "", 0);
1060 if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
1061 gtk_tree_model_get (model, &iter,
1062 FUNCTION, &func,
1063 -1);
1065 gnm_func_load_if_stub (func);
1067 if (gnm_func_get_help (func, NULL) == NULL)
1068 gtk_text_buffer_set_text (description, "?", -1);
1069 else
1070 describe_new_style (description,
1071 GTK_WIDGET (state->description_view),
1072 func, state->sheet);
1073 active = TRUE;
1075 gtk_widget_set_sensitive (state->ok_button, active);
1076 gtk_widget_set_sensitive (state->paste_button, active);
1080 /**********************************************************************/
1081 /* Setup Functions */
1082 /**********************************************************************/
1084 static const gchar *
1085 dialog_function_select_peek_description (GnmFunc *func)
1087 GnmFuncHelp const *help;
1088 int n;
1090 gnm_func_load_if_stub (func);
1092 help = gnm_func_get_help (func, &n);
1093 if (help == NULL)
1094 return "";
1096 for (; n-- > 0; help++) {
1097 switch (help->type) {
1098 case GNM_FUNC_HELP_ARG:
1099 case GNM_FUNC_HELP_NOTE:
1100 case GNM_FUNC_HELP_EXAMPLES:
1101 case GNM_FUNC_HELP_SEEALSO:
1102 case GNM_FUNC_HELP_EXTREF:
1103 case GNM_FUNC_HELP_EXCEL:
1104 case GNM_FUNC_HELP_ODF:
1105 case GNM_FUNC_HELP_DESCRIPTION:
1106 default:
1107 break;
1108 case GNM_FUNC_HELP_NAME: {
1109 const char *text = gnm_func_gettext (func, help->text);
1110 const char *colon = strchr (text, ':');
1111 return (colon ? colon + 1 : text);
1115 return "";
1119 static gchar *
1120 dialog_function_select_get_description (GnmFunc *func, PangoAttrList **pal)
1122 PangoAttribute *attr;
1123 char const *desc = dialog_function_select_peek_description (func);
1124 char const *here;
1125 GString* gstr = g_string_new (NULL);
1127 *pal = pango_attr_list_new ();
1129 if (desc != NULL) {
1130 while (*desc != '\0') {
1131 here = strstr (desc, "@{");
1132 if (here == NULL) {
1133 g_string_append (gstr, desc);
1134 break;
1136 g_string_append_len (gstr, desc, here - desc);
1137 attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
1138 attr->start_index = gstr->len;
1139 desc = here + 2;
1140 here = strchr (desc,'}');
1141 if (here == NULL) {
1142 g_string_append (gstr, desc);
1143 pango_attr_list_insert (*pal, attr);
1144 break;
1146 g_string_append_len (gstr, desc, here - desc);
1147 attr->end_index = gstr->len;
1148 pango_attr_list_insert (*pal, attr);
1149 desc = here + 1;
1153 return g_string_free (gstr, FALSE);
1158 static void
1159 dialog_function_select_load_tree (FunctionSelectState *state)
1161 GtkTreeIter iter;
1162 GnmFuncGroup const * cat;
1163 GSList *funcs = NULL, *ptr;
1164 GnmFunc *func;
1165 gint i = 0;
1166 PangoAttrList *pal;
1167 gchar *desc;
1169 gtk_list_store_clear (state->model_functions);
1171 while ((cat = gnm_func_group_get_nth (i++)) != NULL)
1172 funcs = g_slist_concat (funcs,
1173 g_slist_copy (cat->functions));
1175 funcs = g_slist_sort_with_data (funcs,
1176 dialog_function_select_by_name,
1177 state);
1179 for (ptr = funcs; ptr; ptr = ptr->next) {
1180 func = ptr->data;
1181 if (!(gnm_func_get_flags (func) &
1182 (GNM_FUNC_INTERNAL | GNM_FUNC_IS_PLACEHOLDER))) {
1183 gboolean in_use = gnm_func_get_in_use (func);
1184 gtk_list_store_append (state->model_functions, &iter);
1185 gnm_func_inc_usage (func);
1186 desc = dialog_function_select_get_description (func, &pal);
1187 gtk_list_store_set
1188 (state->model_functions, &iter,
1189 FUN_NAME, gnm_func_get_name (func, state->localized_function_names),
1190 FUNCTION, func,
1191 FUNCTION_DESC, desc,
1192 FUNCTION_PAL, pal,
1193 FUNCTION_CAT, gnm_func_get_function_group (func),
1194 FUNCTION_VISIBLE, TRUE,
1195 FUNCTION_RECENT, FALSE,
1196 FUNCTION_USED, in_use,
1197 -1);
1198 g_free (desc);
1199 pango_attr_list_unref (pal);
1204 g_slist_free (funcs);
1207 static void
1208 dialog_function_select_init (FunctionSelectState *state)
1210 GtkTreeViewColumn *column;
1211 GtkTreeSelection *selection;
1212 GtkTextIter where;
1213 GtkTextBuffer *description;
1214 GtkCellRenderer *cell;
1215 GtkWidget *cancel_button;
1216 GtkWidget *close_button;
1218 g_object_set_data (G_OBJECT (state->dialog), FUNCTION_SELECT_DIALOG_KEY,
1219 state);
1221 /* Set-up combo box */
1222 state->cb = GTK_COMBO_BOX
1223 (go_gtk_builder_get_widget (state->gui, "category-box"));
1224 state->model = gtk_list_store_new
1225 (NUM_CAT_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN);
1227 gtk_combo_box_set_model (state->cb, GTK_TREE_MODEL (state->model));
1228 g_object_unref (state->model);
1229 cell = gtk_cell_renderer_text_new ();
1230 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (state->cb), cell, TRUE);
1231 gtk_cell_layout_add_attribute
1232 (GTK_CELL_LAYOUT (state->cb), cell, "text", CAT_NAME);
1233 dialog_function_select_load_cb (state);
1234 gtk_combo_box_set_row_separator_func
1235 (state->cb, dialog_function_select_cat_row_separator,
1236 state, NULL);
1237 g_signal_connect (state->cb, "changed",
1238 G_CALLBACK (dialog_function_select_cat_changed),
1239 state);
1240 /* Finished set-up of combo box */
1242 /* Set-up treeview */
1244 state->model_functions = gtk_list_store_new
1245 (NUM_COLUMNS,
1246 /* FUN_NAME, */
1247 /* FUNCTION, */
1248 /* FUNCTION_DESC, */
1249 /* FUNCTION_PAL, */
1250 /* FUNCTION_CAT, */
1251 /* FUNCTION_VISIBLE, */
1252 /* FUNCTION_RECENT, */
1253 /* FUNCTION_USED, */
1254 G_TYPE_STRING, G_TYPE_POINTER,
1255 G_TYPE_STRING, PANGO_TYPE_ATTR_LIST,
1256 G_TYPE_POINTER, G_TYPE_BOOLEAN,
1257 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
1259 state->model_filter = gtk_tree_model_filter_new
1260 (GTK_TREE_MODEL (state->model_functions), NULL);
1261 g_object_unref (state->model_functions);
1262 gtk_tree_model_filter_set_visible_column
1263 (GTK_TREE_MODEL_FILTER (state->model_filter), FUNCTION_VISIBLE);
1265 state->treeview = GTK_TREE_VIEW
1266 (go_gtk_builder_get_widget (state->gui, "function-list"));
1267 gtk_tree_view_set_model (state->treeview,
1268 state->model_filter);
1269 g_object_unref (state->model_filter);
1271 selection = gtk_tree_view_get_selection (state->treeview);
1272 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1273 g_signal_connect (selection, "changed",
1274 G_CALLBACK
1275 (cb_dialog_function_select_fun_selection_changed),
1276 state);
1278 column = gtk_tree_view_column_new_with_attributes
1279 (_("Name"),
1280 gtk_cell_renderer_text_new (),
1281 "text", FUN_NAME, NULL);
1282 gtk_tree_view_append_column (state->treeview, column);
1283 column = gtk_tree_view_column_new_with_attributes
1284 (_("Description"),
1285 gtk_cell_renderer_text_new (),
1286 "text", FUNCTION_DESC,
1287 "attributes", FUNCTION_PAL, NULL);
1288 gtk_tree_view_append_column (state->treeview, column);
1290 gtk_tree_view_set_headers_visible (state->treeview, FALSE);
1291 /* Finished set-up of treeview */
1293 dialog_function_select_load_tree (state);
1294 dialog_function_load_recent_funcs (state);
1296 state->search_entry = go_gtk_builder_get_widget (state->gui,
1297 "search-entry");
1298 if (state->paste.prefix != NULL)
1299 gtk_entry_set_text (GTK_ENTRY (state->search_entry),
1300 state->paste.prefix);
1302 g_signal_connect (G_OBJECT (state->search_entry),
1303 "icon-press",
1304 G_CALLBACK
1305 (dialog_function_select_erase_search_entry),
1306 state);
1308 g_signal_connect (G_OBJECT (state->search_entry),
1309 "activate",
1310 G_CALLBACK (dialog_function_select_search),
1311 state);
1312 if (state->mode != HELP_MODE)
1313 g_signal_connect (G_OBJECT (state->treeview),
1314 "row-activated",
1315 G_CALLBACK (cb_dialog_function_row_activated),
1316 state);
1318 gtk_paned_set_position (GTK_PANED (go_gtk_builder_get_widget
1319 (state->gui, "vpaned1")), 300);
1321 state->description_view = GTK_TEXT_VIEW (go_gtk_builder_get_widget
1322 (state->gui, "description"));
1323 gtk_style_context_add_class
1324 (gtk_widget_get_style_context (GTK_WIDGET (state->description_view)),
1325 "function-help");
1326 description = gtk_text_view_get_buffer (state->description_view);
1327 gtk_text_buffer_get_start_iter (description, &where);
1328 gtk_text_buffer_create_mark (description, "start-mark", &where, TRUE);
1330 g_signal_connect_after (G_OBJECT (description),
1331 "mark-set",
1332 G_CALLBACK (cb_description_clicked), state);
1334 state->ok_button = go_gtk_builder_get_widget (state->gui, "ok_button");
1335 gtk_widget_set_sensitive (state->ok_button, FALSE);
1336 g_signal_connect (G_OBJECT (state->ok_button),
1337 "clicked",
1338 G_CALLBACK (cb_dialog_function_select_ok_clicked), state);
1339 state->paste_button = go_gtk_builder_get_widget (state->gui, "paste_button");
1340 gtk_widget_set_sensitive (state->paste_button, FALSE);
1341 g_signal_connect (G_OBJECT (state->paste_button),
1342 "clicked",
1343 G_CALLBACK (cb_dialog_function_select_paste_clicked), state);
1344 cancel_button = go_gtk_builder_get_widget (state->gui, "cancel_button");
1345 g_signal_connect (G_OBJECT (cancel_button), "clicked",
1346 G_CALLBACK (cb_dialog_function_select_cancel_clicked), state);
1347 close_button = go_gtk_builder_get_widget (state->gui, "close_button");
1348 g_signal_connect (G_OBJECT (close_button), "clicked",
1349 G_CALLBACK (cb_dialog_function_select_cancel_clicked), state);
1351 gnm_dialog_setup_destroy_handlers
1352 (GTK_DIALOG (state->dialog),
1353 state->wbcg,
1354 GNM_DIALOG_DESTROY_CURRENT_SHEET_REMOVED);
1356 gnm_init_help_button (
1357 go_gtk_builder_get_widget (state->gui, "help_button"),
1358 GNUMERIC_HELP_LINK_FUNCTION_SELECT);
1359 g_object_set_data_full
1360 (G_OBJECT (state->dialog),
1361 "state", state,
1362 (GDestroyNotify) cb_dialog_function_select_destroy);
1364 if (state->paste.prefix != NULL)
1365 dialog_function_select_search
1366 (GTK_ENTRY (state->search_entry), state);
1368 gtk_widget_set_visible (close_button, state->mode != GURU_MODE);
1369 gtk_widget_set_visible (go_gtk_builder_get_widget
1370 (state->gui, "help_button"),
1371 state->mode == GURU_MODE);
1372 gtk_widget_set_visible (cancel_button, state->mode == GURU_MODE);
1373 gtk_widget_set_visible (state->ok_button, state->mode == GURU_MODE);
1374 gtk_widget_set_visible (state->paste_button, state->mode == PASTE_MODE);
1375 gtk_widget_set_visible (go_gtk_builder_get_widget
1376 (state->gui, "title_label"),
1377 state->mode == GURU_MODE);
1378 gtk_combo_box_set_active (state->cb, state->mode == HELP_MODE ? 2 : 0);
1379 switch (state->mode) {
1380 case GURU_MODE:
1381 break;
1382 case HELP_MODE:
1383 gtk_window_set_title (GTK_WINDOW (state->dialog),
1384 _("Gnumeric Function Help Browser"));
1385 break;
1386 case PASTE_MODE:
1387 gtk_window_set_title (GTK_WINDOW (state->dialog),
1388 _("Paste Function Name dialog"));
1389 break;
1393 static void
1394 dialog_function_select_full (WBCGtk *wbcg, char const *guru_key,
1395 char const *key, DialogMode mode, gint from, gint to)
1397 FunctionSelectState* state;
1398 GtkBuilder *gui;
1400 g_return_if_fail (wbcg != NULL);
1402 if (gnm_dialog_raise_if_exists (wbcg, key))
1403 return;
1404 gui = gnm_gtk_builder_load ("res:ui/function-select.ui", NULL, GO_CMD_CONTEXT (wbcg));
1405 if (gui == NULL)
1406 return;
1408 state = g_new (FunctionSelectState, 1);
1409 state->wbcg = wbcg;
1410 state->sheet = wb_control_cur_sheet (GNM_WBC (wbcg));
1411 state->localized_function_names = state->sheet->convs->localized_function_names;
1412 state->wb = state->sheet->workbook;
1413 state->gui = gui;
1414 state->dialog = go_gtk_builder_get_widget (state->gui, "selection_dialog");
1415 state->formula_guru_key = guru_key;
1416 state->recent_funcs = NULL;
1417 state->mode = mode;
1418 state->paste.from = from;
1419 state->paste.to = to;
1421 gnm_dialog_setup_destroy_handlers (GTK_DIALOG (state->dialog),
1422 state->wbcg,
1423 GNM_DIALOG_DESTROY_SHEET_REMOVED);
1425 if (mode == PASTE_MODE && state->paste.from >= 0) {
1426 GtkEditable *entry
1427 = GTK_EDITABLE (wbcg_get_entry (state->wbcg));
1428 state->paste.prefix = gtk_editable_get_chars
1429 (entry, state->paste.from,
1430 state->paste.to);
1431 } else
1432 state->paste.prefix = NULL;
1434 dialog_function_select_init (state);
1435 gnm_keyed_dialog (state->wbcg, GTK_WINDOW (state->dialog),
1436 key);
1438 gtk_widget_show (state->dialog);
1441 void
1442 dialog_function_select (WBCGtk *wbcg, char const *key)
1444 dialog_function_select_full (wbcg, key,
1445 FUNCTION_SELECT_KEY, GURU_MODE, -1, -1);
1448 void
1449 dialog_function_select_help (WBCGtk *wbcg)
1451 dialog_function_select_full (wbcg, NULL,
1452 FUNCTION_SELECT_HELP_KEY, HELP_MODE,
1453 -1, -1);
1456 void
1457 dialog_function_select_paste (WBCGtk *wbcg, gint from, gint to)
1459 dialog_function_select_full (wbcg, NULL,
1460 FUNCTION_SELECT_PASTE_KEY, PASTE_MODE,
1461 from, to);