2 * func.c: Function management and utility routines.
5 * Miguel de Icaza (miguel@gnu.org)
6 * Michael Meeks (mmeeks@gnu.org)
7 * Morten Welinder (terra@gnome.org)
8 * Jody Goldberg (jody@gnome.org)
10 #include <gnumeric-config.h>
11 #include <glib/gi18n-lib.h>
12 #include <glib/gstdio.h>
17 #include <parse-util.h>
18 #include <dependent.h>
20 #include <expr-impl.h>
21 #include <expr-name.h>
23 #include <workbook-priv.h>
26 #include <number-match.h>
27 #include <func-builtin.h>
28 #include <command-context-stderr.h>
29 #include <gnm-plugin.h>
32 #include <gnm-marshalers.h>
34 #include <goffice/goffice.h>
42 PROP_TRANSLATION_DOMAIN
,
51 static guint signals
[LAST_SIGNAL
] = { 0 };
54 #define F2(func,s) dgettext ((func)->tdomain->str, (s))
56 static GList
*categories
;
57 static GnmFuncGroup
*unknown_cat
;
59 static GHashTable
*functions_by_name
;
60 static GHashTable
*functions_by_localized_name
;
63 * functions_init: (skip)
69 g_hash_table_new (go_ascii_strcase_hash
, go_ascii_strcase_equal
);
72 functions_by_localized_name
=
73 g_hash_table_new (go_ascii_strcase_hash
, go_ascii_strcase_equal
);
79 * functions_shutdown: (skip)
82 functions_shutdown (void)
84 while (unknown_cat
!= NULL
&& unknown_cat
->functions
!= NULL
) {
85 GnmFunc
*func
= unknown_cat
->functions
->data
;
86 if (func
->usage_count
> 0) {
87 g_warning ("Function %s still has %d users.\n",
88 gnm_func_get_name (func
, FALSE
),
90 func
->usage_count
= 0;
92 g_object_unref (func
);
94 func_builtin_shutdown ();
96 g_hash_table_destroy (functions_by_name
);
97 functions_by_name
= NULL
;
99 g_hash_table_destroy (functions_by_localized_name
);
100 functions_by_localized_name
= NULL
;
104 * gnm_func_enumerate:
106 * Return value: (element-type GnmFunc) (transfer container):
109 gnm_func_enumerate (void)
111 GPtrArray
*res
= g_ptr_array_new ();
112 GHashTableIter hiter
;
115 g_hash_table_iter_init (&hiter
, functions_by_name
);
116 while (g_hash_table_iter_next (&hiter
, NULL
, &value
))
117 g_ptr_array_add (res
, value
);
123 gnm_func_load_if_stub (GnmFunc
*func
)
125 if (func
->fn_type
== GNM_FUNC_TYPE_STUB
)
126 gnm_func_load_stub (func
);
130 split_at_colon (char const *s
, char **rest
)
132 char *dup
= g_strdup (s
);
133 char *colon
= strchr (dup
, ':');
136 if (rest
) *rest
= colon
+ 1;
138 if (rest
) *rest
= NULL
;
143 /* ------------------------------------------------------------------------- */
146 gnm_func_group_free (GnmFuncGroup
*fn_group
)
148 g_return_if_fail (fn_group
!= NULL
);
149 g_return_if_fail (fn_group
->functions
== NULL
);
151 if (fn_group
->ref_count
-- > 1)
154 go_string_unref (fn_group
->internal_name
);
155 go_string_unref (fn_group
->display_name
);
159 static GnmFuncGroup
*
160 gnm_func_group_ref (GnmFuncGroup
*fn_group
)
162 fn_group
->ref_count
++;
167 gnm_func_group_get_type (void)
172 t
= g_boxed_type_register_static ("GnmFuncGroup",
173 (GBoxedCopyFunc
)gnm_func_group_ref
,
174 (GBoxedFreeFunc
)gnm_func_group_free
);
180 function_category_compare (gconstpointer a
, gconstpointer b
)
182 GnmFuncGroup
const *cat_a
= a
;
183 GnmFuncGroup
const *cat_b
= b
;
185 return go_string_cmp (cat_a
->display_name
, cat_b
->display_name
);
189 gnm_func_group_fetch (char const *name
, char const *translation
)
191 GnmFuncGroup
*cat
= NULL
;
194 g_return_val_if_fail (name
!= NULL
, NULL
);
196 for (l
= categories
; l
!= NULL
; l
= l
->next
) {
198 if (strcmp (cat
->internal_name
->str
, name
) == 0) {
204 cat
= g_new (GnmFuncGroup
, 1);
205 cat
->internal_name
= go_string_new (name
);
207 if (translation
!= NULL
) {
208 cat
->display_name
= go_string_new (translation
);
209 cat
->has_translation
= TRUE
;
211 cat
->display_name
= go_string_new (name
);
212 cat
->has_translation
= FALSE
;
214 cat
->functions
= NULL
;
215 categories
= g_list_insert_sorted (
216 categories
, cat
, &function_category_compare
);
217 } else if (translation
!= NULL
&& translation
!= name
&&
218 !cat
->has_translation
) {
219 go_string_unref (cat
->display_name
);
220 cat
->display_name
= go_string_new (translation
);
221 cat
->has_translation
= TRUE
;
222 categories
= g_list_remove_link (categories
, l
);
224 categories
= g_list_insert_sorted (
225 categories
, cat
, &function_category_compare
);
232 gnm_func_group_get_nth (int n
)
234 return g_list_nth_data (categories
, n
);
238 gnm_func_group_add_func (GnmFuncGroup
*fn_group
, GnmFunc
*fn_def
)
240 g_return_if_fail (fn_group
!= NULL
);
241 g_return_if_fail (fn_def
!= NULL
);
243 fn_group
->functions
= g_slist_prepend (fn_group
->functions
, fn_def
);
247 gnm_func_group_remove_func (GnmFuncGroup
*fn_group
, GnmFunc
*fn_def
)
249 g_return_if_fail (fn_group
!= NULL
);
250 g_return_if_fail (fn_def
!= NULL
);
252 fn_group
->functions
= g_slist_remove (fn_group
->functions
, fn_def
);
253 if (fn_group
->functions
== NULL
) {
254 categories
= g_list_remove (categories
, fn_group
);
255 if (unknown_cat
== fn_group
)
257 gnm_func_group_free (fn_group
);
261 /******************************************************************************/
264 extract_arg_types (GnmFunc
*def
)
268 gnm_func_count_args (def
,
269 &def
->fn
.args
.min_args
,
270 &def
->fn
.args
.max_args
);
271 def
->fn
.args
.arg_types
= g_malloc (def
->fn
.args
.max_args
+ 1);
272 for (i
= 0; i
< def
->fn
.args
.max_args
; i
++)
273 def
->fn
.args
.arg_types
[i
] = gnm_func_get_arg_type (def
, i
);
274 def
->fn
.args
.arg_types
[i
] = 0;
278 error_function_no_full_info (GnmFuncEvalInfo
*ei
,
280 GnmExprConstPtr
const *argv
)
282 return value_new_error (ei
->pos
, _("Function implementation not available."));
286 gnm_func_clear_arg_names (GnmFunc
*fd
)
288 if (fd
->arg_names_p
) {
289 g_ptr_array_foreach (fd
->arg_names_p
, (GFunc
) g_free
, NULL
);
290 g_ptr_array_free (fd
->arg_names_p
, TRUE
);
291 fd
->arg_names_p
= NULL
;
296 gnm_func_create_arg_names (GnmFunc
*fn_def
)
301 g_return_if_fail (fn_def
!= NULL
);
303 ptr
= g_ptr_array_new ();
305 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
307 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
312 (F2(fn_def
, fn_def
->help
[i
].text
), NULL
));
315 gnm_func_clear_arg_names (fn_def
);
316 fn_def
->arg_names_p
= ptr
;
321 gnm_func_load_stub (GnmFunc
*func
)
323 g_return_if_fail (func
->fn_type
== GNM_FUNC_TYPE_STUB
);
325 g_signal_emit (G_OBJECT (func
), signals
[SIG_LOAD_STUB
], 0);
327 if (func
->fn_type
== GNM_FUNC_TYPE_STUB
) {
328 static GnmFuncHelp
const no_help
[] = { { GNM_FUNC_HELP_END
} };
330 func
->help
= no_help
;
331 func
->fn
.nodes
= &error_function_no_full_info
;
332 gnm_func_set_function_type (func
, GNM_FUNC_TYPE_NODES
);
337 gnm_func_set_function_type (GnmFunc
*func
, GnmFuncType typ
)
339 g_return_if_fail (GNM_IS_FUNC (func
));
343 case GNM_FUNC_TYPE_ARGS
:
344 extract_arg_types (func
);
345 gnm_func_create_arg_names (func
);
347 case GNM_FUNC_TYPE_NODES
:
348 gnm_func_create_arg_names (func
);
350 case GNM_FUNC_TYPE_STUB
:
357 gnm_func_set_localized_name (GnmFunc
*fd
, const char *lname
)
359 gboolean in_hashes
= !(fd
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
);
361 if (g_strcmp0 (fd
->localized_name
, lname
) == 0)
364 if (in_hashes
&& fd
->localized_name
)
365 g_hash_table_remove (functions_by_localized_name
, fd
->localized_name
);
366 g_free (fd
->localized_name
);
368 fd
->localized_name
= g_strdup (lname
);
369 if (in_hashes
&& lname
)
370 g_hash_table_insert (functions_by_localized_name
,
371 fd
->localized_name
, fd
);
375 * gnm_func_inc_usage:
376 * @func: (transfer none): #GnmFunc
378 * This function increments the usage count of @func. A non-zero usage count
379 * prevents the unloading of the function.
381 * Returns: (transfer full): a new reference to @func.
384 gnm_func_inc_usage (GnmFunc
*func
)
386 g_return_val_if_fail (func
!= NULL
, NULL
);
389 if (func
->usage_count
== 1)
390 g_object_notify (G_OBJECT (func
), "in-use");
395 * gnm_func_dec_usage:
396 * @func: (transfer full): #GnmFunc
398 * This function decrements the usage count of @func. When the usage count
399 * reaches zero, the function may be unloaded, for example by unloading the
400 * plugin that defines it.
403 gnm_func_dec_usage (GnmFunc
*func
)
405 g_return_if_fail (func
!= NULL
);
406 g_return_if_fail (func
->usage_count
> 0);
409 if (func
->usage_count
== 0)
410 g_object_notify (G_OBJECT (func
), "in-use");
414 gnm_func_get_in_use (GnmFunc
*func
)
416 g_return_val_if_fail (func
!= NULL
, FALSE
);
418 return func
->usage_count
> 0;
424 * @name: name of function
425 * @scope: (nullable): scope of function, %NULL for global
427 * Returns: (nullable) (transfer none): the function of that name.
430 gnm_func_lookup (char const *name
, Workbook
*scope
)
432 GnmFunc
*fd
= g_hash_table_lookup (functions_by_name
, name
);
435 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
437 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
441 * gnm_func_lookup_localized:
442 * @name: localized name of function
443 * @scope: (nullable): scope of function, %NULL for global
445 * Returns: (nullable) (transfer none): the function of that name.
448 gnm_func_lookup_localized (char const *name
, Workbook
*scope
)
451 GHashTableIter hiter
;
454 /* Must localize all function names. */
455 g_hash_table_iter_init (&hiter
, functions_by_name
);
456 while (g_hash_table_iter_next (&hiter
, NULL
, &value
)) {
458 (void)gnm_func_get_name (fd
, TRUE
);
461 fd
= g_hash_table_lookup (functions_by_localized_name
, name
);
464 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
466 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
470 * gnm_func_lookup_prefix:
471 * @prefix: prefix to search for
473 * @trans: whether to search translated function names
475 * Returns: (element-type GnmFunc*) (transfer full):
478 gnm_func_lookup_prefix (char const *prefix
, Workbook
*scope
, gboolean trans
)
481 GHashTableIter hiter
;
485 * Always iterate over functions_by_name as the localized name
486 * might not be set yet.
488 g_hash_table_iter_init (&hiter
, functions_by_name
);
489 while (g_hash_table_iter_next (&hiter
, NULL
, &value
)) {
491 if (!(fd
->flags
& GNM_FUNC_IS_PLACEHOLDER
)) {
492 const char *name
= gnm_func_get_name (fd
, trans
);
493 if (g_str_has_prefix (name
, prefix
)) {
494 gnm_func_inc_usage (fd
);
495 res
= g_slist_prepend (res
, fd
);
504 * gnm_func_get_translation_domain:
507 * Returns: (transfer none): the translation domain for @func's help text.
510 gnm_func_get_translation_domain (GnmFunc
*func
)
512 g_return_val_if_fail (GNM_IS_FUNC (func
), NULL
);
513 return func
->tdomain
->str
;
517 * gnm_func_set_translation_domain:
519 * @tdomain: (nullable): Translation domain, %NULL for Gnumeric's.
522 gnm_func_set_translation_domain (GnmFunc
*func
, const char *tdomain
)
524 g_return_if_fail (GNM_IS_FUNC (func
));
527 tdomain
= GETTEXT_PACKAGE
;
529 if (g_strcmp0 (func
->tdomain
->str
, tdomain
) == 0)
532 go_string_unref (func
->tdomain
);
533 func
->tdomain
= go_string_new (tdomain
);
535 g_object_notify (G_OBJECT (func
), "translation-domain");
539 gnm_func_set_function_group (GnmFunc
*func
, GnmFuncGroup
*group
)
541 g_return_if_fail (GNM_IS_FUNC (func
));
542 g_return_if_fail (group
!= NULL
);
544 if (func
->fn_group
== group
)
548 gnm_func_group_remove_func (func
->fn_group
, func
);
549 func
->fn_group
= group
;
550 gnm_func_group_add_func (group
, func
);
552 if (group
== unknown_cat
)
553 func
->flags
|= GNM_FUNC_IS_PLACEHOLDER
;
555 func
->flags
&= ~GNM_FUNC_IS_PLACEHOLDER
;
564 * @tdomain: (nullable):
566 * Returns: (transfer full): a new #GnmFunc.
569 gnm_func_add (GnmFuncGroup
*fn_group
,
570 GnmFuncDescriptor
const *desc
,
573 static char const valid_tokens
[] = "fsbraAES?|";
577 g_return_val_if_fail (fn_group
!= NULL
, NULL
);
578 g_return_val_if_fail (desc
!= NULL
, NULL
);
580 func
= g_object_new (GNM_FUNC_TYPE
,
583 gnm_func_set_translation_domain (func
, tdomain
);
585 func
->help
= desc
->help
? desc
->help
: NULL
;
586 func
->flags
= desc
->flags
;
587 func
->impl_status
= desc
->impl_status
;
588 func
->test_status
= desc
->test_status
;
589 func
->localized_name
= NULL
;
590 func
->arg_names_p
= NULL
;
592 func
->usage_count
= 0;
594 if (desc
->fn_args
!= NULL
) {
595 /* Check those arguments */
596 for (ptr
= desc
->arg_spec
; *ptr
; ptr
++) {
597 g_return_val_if_fail (strchr (valid_tokens
, *ptr
), NULL
);
600 func
->fn
.args
.func
= desc
->fn_args
;
601 func
->fn
.args
.arg_spec
= desc
->arg_spec
;
602 gnm_func_set_function_type (func
, GNM_FUNC_TYPE_ARGS
);
603 } else if (desc
->fn_nodes
!= NULL
) {
605 if (desc
->arg_spec
&& *desc
->arg_spec
) {
606 g_warning ("Arg spec for node function -- why?");
609 func
->fn
.nodes
= desc
->fn_nodes
;
610 gnm_func_set_function_type (func
, GNM_FUNC_TYPE_NODES
);
612 g_warning ("Invalid function has neither args nor nodes handler");
613 g_object_unref (func
);
617 func
->fn_group
= fn_group
;
618 gnm_func_group_add_func (fn_group
, func
);
619 if (!(func
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
))
620 g_hash_table_insert (functions_by_name
,
621 (gpointer
)(func
->name
), func
);
626 /* Handle unknown functions on import without losing their names */
628 unknownFunctionHandler (GnmFuncEvalInfo
*ei
,
629 G_GNUC_UNUSED
int argc
,
630 G_GNUC_UNUSED GnmExprConstPtr
const *argv
)
632 return value_new_error_NAME (ei
->pos
);
636 invent_name (const char *pref
, GHashTable
*h
, const char *template)
638 static int count
= 0;
639 char *name
= g_utf8_strdown (pref
, -1);
641 while (g_hash_table_lookup (h
, name
)) {
644 name
= g_strdup_printf (template, count
);
651 gnm_func_add_placeholder_full (Workbook
*scope
,
652 char const *gname
, char const *lname
,
655 GnmFuncDescriptor desc
;
657 char const *unknown_cat_name
= N_("Unknown Function");
658 gboolean copy_gname
= TRUE
;
659 gboolean copy_lname
= TRUE
;
661 g_return_val_if_fail (gname
|| lname
, NULL
);
662 g_return_val_if_fail (gname
== NULL
|| gnm_func_lookup (gname
, scope
) == NULL
, NULL
);
663 g_return_val_if_fail (lname
== NULL
|| gnm_func_lookup_localized (lname
, scope
) == NULL
, NULL
);
666 unknown_cat
= gnm_func_group_fetch
667 (unknown_cat_name
, _(unknown_cat_name
));
671 * This is actually a bit of a problem if we don't end up
672 * with a copy of lname (because there already is a function
673 * with that name). We're likely to save a template name,
674 * but I don't see what else to do.
676 gname
= invent_name (lname
, functions_by_name
, "unknown%d");
680 /* xgettext: This represents a made-up translated function name. */
681 lname
= invent_name (gname
, functions_by_localized_name
, _("unknown%d"));
685 if (gnm_debug_flag ("func"))
686 g_printerr ("Adding placeholder for %s (aka %s)\n", gname
, lname
);
688 memset (&desc
, 0, sizeof (GnmFuncDescriptor
));
690 desc
.arg_spec
= NULL
;
693 desc
.fn_nodes
= &unknownFunctionHandler
;
694 desc
.flags
= GNM_FUNC_IS_PLACEHOLDER
;
695 desc
.impl_status
= GNM_FUNC_IMPL_STATUS_EXISTS
;
696 desc
.test_status
= GNM_FUNC_TEST_STATUS_UNKNOWN
;
699 desc
.flags
|= GNM_FUNC_IS_WORKBOOK_LOCAL
;
702 /* WISHLIST : it would be nice to have a log if these. */
703 g_warning ("Unknown %s function : %s", type
, desc
.name
);
707 func
= gnm_func_add (unknown_cat
, &desc
, NULL
);
710 gnm_func_set_localized_name (func
, lname
);
712 g_free ((char *)lname
);
716 g_free ((char *)gname
);
719 if (scope
->sheet_local_functions
== NULL
)
720 scope
->sheet_local_functions
= g_hash_table_new_full (
721 g_str_hash
, g_str_equal
,
722 NULL
, g_object_unref
);
723 g_hash_table_insert (scope
->sheet_local_functions
,
724 (gpointer
)func
->name
, func
);
731 * gnm_func_add_placeholder:
732 * @scope: (nullable): scope to defined placeholder, %NULL for global
733 * @name: (nullable): function name
736 * Returns: (transfer none): a placeholder with the given name.
739 gnm_func_add_placeholder (Workbook
*scope
,
740 char const *name
, char const *type
)
742 return gnm_func_add_placeholder_full (scope
, name
, NULL
, type
);
746 * gnm_func_add_placeholder_localized:
747 * @gname: (nullable): function name
748 * @lname: localized function name
750 * Returns: (transfer none): a placeholder with the given localized name.
753 gnm_func_add_placeholder_localized (char const *gname
, char const *lname
)
755 return gnm_func_add_placeholder_full (NULL
, gname
, lname
, "?");
759 * gnm_func_lookup_or_add_placeholder:
760 * @name: function name
762 * Returns: (transfer none): a #GnmFunc named @name, either an existing
763 * one or a placeholder.
766 gnm_func_lookup_or_add_placeholder (char const *name
)
768 GnmFunc
* f
= gnm_func_lookup (name
, NULL
);
770 f
= gnm_func_add_placeholder (NULL
, name
, "");
776 * @func: #GnmFunc to query
777 * @localized: if %TRUE, use localized name
779 * Returns: (transfer none): @func's name
782 gnm_func_get_name (GnmFunc
const *func
, gboolean localized
)
785 GnmFunc
*fd
= (GnmFunc
*)func
;
787 g_return_val_if_fail (func
!= NULL
, NULL
);
792 if (func
->localized_name
)
793 return func
->localized_name
;
796 * Deduce the translated names from the help texts. This
797 * code doesn't currently check for clashes in translated
801 gnm_func_load_if_stub (fd
);
804 (func
->localized_name
== NULL
&&
806 func
->help
[i
].type
!= GNM_FUNC_HELP_END
);
810 if (func
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
813 s
= func
->help
[i
].text
;
815 if (s
== sl
) /* String not actually translated. */
818 U
= split_at_colon (F2 (func
, s
), NULL
);
820 char *lname
= g_utf8_strdown (U
, -1);
821 gnm_func_set_localized_name (fd
, lname
);
827 if (!func
->localized_name
)
828 gnm_func_set_localized_name (fd
, fd
->name
);
830 return func
->localized_name
;
834 * gnm_func_get_description:
835 * @fn_def: the fn defintion
837 * Returns: (transfer none): the description of the function
840 gnm_func_get_description (GnmFunc
const *fn_def
)
843 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
845 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
848 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
852 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
855 desc
= strchr (F2 (fn_def
, fn_def
->help
[i
].text
), ':');
856 return desc
? (desc
+ 1) : "";
862 * gnm_func_count_args:
863 * @fn_def: pointer to function definition
864 * @min: (out): location for mininum args
865 * @max: (out): location for mininum args
867 * This calculates the maximum and minimum number of args that can be passed.
868 * For a vararg function, the maximum will be set to G_MAXINT.
871 gnm_func_count_args (GnmFunc
const *fn_def
, int *min
, int *max
)
873 g_return_if_fail (min
!= NULL
);
874 g_return_if_fail (max
!= NULL
);
875 g_return_if_fail (fn_def
!= NULL
);
877 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
879 switch (fn_def
->fn_type
) {
880 case GNM_FUNC_TYPE_NODES
:
883 if (g_ascii_strcasecmp ("INDEX",fn_def
->name
) == 0)
889 case GNM_FUNC_TYPE_ARGS
: {
890 const char *ptr
= fn_def
->fn
.args
.arg_spec
;
893 for (i
= vararg
= 0; ptr
&& *ptr
; ptr
++) {
914 * gnm_func_get_arg_type:
915 * @fn_def: the fn defintion
916 * @arg_idx: zero based argument offset
918 * Returns: the type of the argument
921 gnm_func_get_arg_type (GnmFunc
const *fn_def
, int arg_idx
)
925 g_return_val_if_fail (arg_idx
>= 0, '?');
926 g_return_val_if_fail (fn_def
!= NULL
, '?');
928 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
930 switch (fn_def
->fn_type
) {
931 case GNM_FUNC_TYPE_ARGS
:
932 for (ptr
= fn_def
->fn
.args
.arg_spec
; ptr
&& *ptr
; ptr
++) {
940 case GNM_FUNC_TYPE_NODES
:
941 return '?'; /* Close enough for now. */
943 case GNM_FUNC_TYPE_STUB
:
944 #ifndef DEBUG_SWITCH_ENUM
947 g_assert_not_reached ();
953 * gnm_func_get_arg_type_string:
954 * @fn_def: the fn defintion
955 * @arg_idx: zero based argument offset
957 * Return value: (transfer none): the type of the argument as a string
960 gnm_func_get_arg_type_string (GnmFunc
const *fn_def
,
963 switch (gnm_func_get_arg_type (fn_def
, arg_idx
)) {
971 return _("Cell Range");
975 return _("Scalar, Blank, or Error");
979 /* Missing values will be NULL. */
983 g_warning ("Unknown arg type");
989 * gnm_func_get_arg_name:
990 * @fn_def: the fn defintion
991 * @arg_idx: zero based argument offset
993 * Returns: (transfer full): the name of the argument
996 gnm_func_get_arg_name (GnmFunc
const *fn_def
, guint arg_idx
)
998 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
1000 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1002 if ((fn_def
->arg_names_p
!= NULL
)
1003 && (arg_idx
< fn_def
->arg_names_p
->len
))
1004 return g_strdup (g_ptr_array_index (fn_def
->arg_names_p
,
1010 * gnm_func_get_arg_description:
1011 * @fn_def: the fn defintion
1012 * @arg_idx: zero based argument offset
1014 * Returns: (transfer none): the description of the argument
1017 gnm_func_get_arg_description (GnmFunc
const *fn_def
, guint arg_idx
)
1020 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
1022 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1025 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
1029 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
1034 desc
= strchr (F2 (fn_def
, fn_def
->help
[i
].text
), ':');
1039 while (g_unichar_isspace (g_utf8_get_char (desc
)))
1040 desc
= g_utf8_next_char (desc
);
1048 * gnm_func_convert_markup_to_pango:
1049 * @desc: the fn or arg description string
1050 * @target: target widget for the markup.
1052 * Return value: the escaped string with @{} markup converted to
1056 gnm_func_convert_markup_to_pango (char const *desc
, GtkWidget
*target
)
1062 char *link_color_text
, *span_text
;
1063 size_t span_text_len
;
1065 gnm_get_link_color (target
, &link_color
);
1066 pg
.red
= 65535 * link_color
.red
;
1067 pg
.green
= 65535 * link_color
.green
;
1068 pg
.blue
= 65535 * link_color
.blue
;
1069 link_color_text
= pango_color_to_string (&pg
);
1070 span_text
= g_strdup_printf ("<span foreground=\"%s\">",
1072 span_text_len
= strlen (span_text
);
1073 g_free (link_color_text
);
1075 markup
= g_markup_escape_text (desc
, -1);
1076 str
= g_string_new (markup
);
1079 while ((at
= strstr (str
->str
, "@{"))) {
1080 gint len
= at
- str
->str
;
1081 go_string_replace (str
, len
, 2, span_text
, -1);
1083 (str
->str
+ len
+ span_text_len
, "}"))) {
1084 len
= at
- str
->str
;
1085 go_string_replace (str
, len
, 1, "</span>", -1);
1087 g_string_append (str
, "</span>");
1091 return g_string_free (str
, FALSE
);
1095 /* ------------------------------------------------------------------------- */
1098 free_values (GnmValue
**values
, int top
)
1102 for (i
= 0; i
< top
; i
++)
1104 value_release (values
[i
]);
1107 /* ------------------------------------------------------------------------- */
1110 * function_call_with_exprs:
1111 * @ei: EvalInfo containing valid fn_def!
1113 * Do the guts of calling a function.
1115 * Returns the result.
1118 function_call_with_exprs (GnmFuncEvalInfo
*ei
)
1120 GnmFunc
const *fn_def
;
1121 int i
, iter_count
, iter_width
= 0, iter_height
= 0;
1123 GnmValue
**args
, *tmp
= NULL
;
1124 int *iter_item
= NULL
;
1126 GnmExprConstPtr
*argv
;
1127 GnmExprEvalFlags flags
, pass_flags
;
1129 g_return_val_if_fail (ei
!= NULL
, NULL
);
1130 g_return_val_if_fail (ei
->func_call
!= NULL
, NULL
);
1134 argc
= ei
->func_call
->argc
;
1135 argv
= ei
->func_call
->argv
;
1136 fn_def
= ei
->func_call
->func
;
1138 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1140 /* Functions that deal with ExprNodes */
1141 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
)
1142 return fn_def
->fn
.nodes (ei
, argc
, argv
);
1144 /* Functions that take pre-computed Values */
1145 if (argc
> fn_def
->fn
.args
.max_args
||
1146 argc
< fn_def
->fn
.args
.min_args
)
1147 return value_new_error_NA (ei
->pos
);
1149 args
= g_alloca (sizeof (GnmValue
*) * fn_def
->fn
.args
.max_args
);
1150 iter_count
= (eval_pos_is_array_context (ei
->pos
) &&
1151 (flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
))
1154 /* Optimization for IF when implicit iteration is not used. */
1155 if (ei
->func_call
->func
->fn
.args
.func
== gnumeric_if
&&
1157 return gnumeric_if2 (ei
, argc
, argv
, flags
);
1159 pass_flags
= (flags
&
1160 (GNM_EXPR_EVAL_ARRAY_CONTEXT
));
1162 for (i
= 0; i
< argc
; i
++) {
1163 char arg_type
= fn_def
->fn
.args
.arg_types
[i
];
1164 /* expr is always non-null, missing args are encoded as
1166 GnmExpr
const *expr
= argv
[i
];
1168 if (arg_type
== 'A' || arg_type
== 'r') {
1169 tmp
= args
[i
] = gnm_expr_eval
1172 GNM_EXPR_EVAL_PERMIT_NON_SCALAR
|
1173 GNM_EXPR_EVAL_WANT_REF
);
1174 if (VALUE_IS_ERROR (tmp
)) {
1175 free_values (args
, i
);
1179 if (VALUE_IS_CELLRANGE (tmp
)) {
1180 gnm_cellref_make_abs (&tmp
->v_range
.cell
.a
,
1181 &tmp
->v_range
.cell
.a
,
1183 gnm_cellref_make_abs (&tmp
->v_range
.cell
.b
,
1184 &tmp
->v_range
.cell
.b
,
1186 /* Array args accept scalars */
1187 } else if (arg_type
!= 'A' && !VALUE_IS_ARRAY (tmp
)) {
1188 free_values (args
, i
+ 1);
1189 return value_new_error_VALUE (ei
->pos
);
1194 /* force scalars whenever we are certain */
1195 tmp
= args
[i
] = gnm_expr_eval
1198 GNM_EXPR_EVAL_PERMIT_EMPTY
|
1199 (iter_count
>= 0 || arg_type
== '?'
1200 ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1203 if (arg_type
== '?') /* '?' arguments are unrestriced */
1206 /* optional arguments can be blank */
1207 if (i
>= fn_def
->fn
.args
.min_args
&& VALUE_IS_EMPTY (tmp
)) {
1208 if (arg_type
== 'E' && !gnm_expr_is_empty (expr
)) {
1209 /* An actual argument produced empty. Make
1210 sure function sees that. */
1211 args
[i
] = value_new_empty ();
1218 tmp
= args
[i
] = value_new_empty ();
1220 /* Handle implicit intersection or iteration depending on flags */
1221 if (VALUE_IS_CELLRANGE (tmp
) || VALUE_IS_ARRAY (tmp
)) {
1222 if (iter_count
> 0) {
1223 if (iter_width
!= value_area_get_width (tmp
, ei
->pos
) ||
1224 iter_height
!= value_area_get_height (tmp
, ei
->pos
)) {
1225 free_values (args
, i
+ 1);
1226 return value_new_error_VALUE (ei
->pos
);
1229 if (iter_count
< 0) {
1230 g_warning ("Damn I thought this was impossible");
1233 iter_item
= g_alloca (sizeof (int) * argc
);
1234 iter_width
= value_area_get_width (tmp
, ei
->pos
);
1235 iter_height
= value_area_get_height (tmp
, ei
->pos
);
1237 iter_item
[iter_count
++] = i
;
1239 /* no need to check type, we would fail comparing a range against a "b, f, or s" */
1243 /* All of these argument types must be scalars */
1246 if (VALUE_IS_STRING (tmp
)) {
1248 gboolean b
= value_get_as_bool (tmp
, &err
);
1250 free_values (args
, i
+ 1);
1251 return value_new_error_VALUE (ei
->pos
);
1253 value_release (args
[i
]);
1254 tmp
= args
[i
] = value_new_bool (b
);
1259 if (VALUE_IS_STRING (tmp
)) {
1260 tmp
= format_match_number (value_peek_string (tmp
), NULL
,
1261 sheet_date_conv (ei
->pos
->sheet
));
1263 free_values (args
, i
+ 1);
1264 return value_new_error_VALUE (ei
->pos
);
1266 value_release (args
[i
]);
1268 } else if (VALUE_IS_ERROR (tmp
)) {
1269 free_values (args
, i
);
1271 } else if (VALUE_IS_EMPTY (tmp
)) {
1272 value_release (args
[i
]);
1273 tmp
= args
[i
] = value_new_int (0);
1276 if (!VALUE_IS_NUMBER (tmp
))
1277 return value_new_error_VALUE (ei
->pos
);
1282 if (VALUE_IS_ERROR (tmp
)) {
1283 free_values (args
, i
);
1288 case 'E': /* nothing necessary */
1291 /* case '?': handled above */
1293 g_warning ("Unknown argument type '%c'", arg_type
);
1298 while (i
< fn_def
->fn
.args
.max_args
)
1301 if (iter_item
!= NULL
) {
1303 GnmValue
*res
= value_new_array_empty (iter_width
, iter_height
);
1304 GnmValue
const *elem
, *err
;
1305 GnmValue
**iter_vals
= g_alloca (sizeof (GnmValue
*) * iter_count
);
1306 GnmValue
**iter_args
= g_alloca (sizeof (GnmValue
*) * iter_count
);
1308 /* collect the args we will iterate on */
1309 for (i
= 0 ; i
< iter_count
; i
++)
1310 iter_vals
[i
] = args
[iter_item
[i
]];
1312 for (x
= iter_width
; x
-- > 0 ; )
1313 for (y
= iter_height
; y
-- > 0 ; ) {
1314 /* marshal the args */
1316 for (i
= 0 ; i
< iter_count
; i
++) {
1317 elem
= value_area_get_x_y (iter_vals
[i
], x
, y
, ei
->pos
);
1318 arg_type
= fn_def
->fn
.args
.arg_types
[iter_item
[i
]];
1319 if (arg_type
== 'b' || arg_type
== 'f') {
1320 if (VALUE_IS_EMPTY (elem
))
1322 else if (VALUE_IS_STRING (elem
)) {
1323 tmp
= format_match_number (value_peek_string (elem
), NULL
,
1324 sheet_date_conv (ei
->pos
->sheet
));
1326 args
[iter_item
[i
]] = iter_args
[i
] = tmp
;
1330 } else if (VALUE_IS_ERROR (elem
)) {
1333 } else if (!VALUE_IS_NUMBER (elem
))
1335 } else if (arg_type
== 's') {
1336 if (VALUE_IS_EMPTY (elem
)) {
1337 args
[iter_item
[i
]] = iter_args
[i
] = value_new_string ("");
1339 } else if (VALUE_IS_ERROR (elem
)) {
1342 } else if (!VALUE_IS_STRING (elem
))
1344 } else if (elem
== NULL
) {
1345 args
[iter_item
[i
]] = iter_args
[i
] = value_new_empty ();
1348 args
[iter_item
[i
]] = iter_args
[i
] = value_dup (elem
);
1351 res
->v_array
.vals
[x
][y
] = (i
== iter_count
)
1352 ? fn_def
->fn
.args
.func (ei
, (GnmValue
const * const *)args
)
1353 : ((err
!= NULL
) ? value_dup (err
)
1354 : value_new_error_VALUE (ei
->pos
));
1355 free_values (iter_args
, i
);
1358 /* free the primaries, not the already freed iteration */
1359 for (i
= 0 ; i
< iter_count
; i
++)
1360 args
[iter_item
[i
]] = iter_vals
[i
];
1362 i
= fn_def
->fn
.args
.max_args
;
1364 tmp
= fn_def
->fn
.args
.func (ei
, (GnmValue
const * const *)args
);
1366 free_values (args
, i
);
1371 * Use this to invoke a register function: the only drawback is that
1372 * you have to compute/expand all of the values to use this
1375 function_call_with_values (GnmEvalPos
const *ep
, char const *fn_name
,
1376 int argc
, GnmValue
const * const *values
)
1380 g_return_val_if_fail (ep
!= NULL
, NULL
);
1381 g_return_val_if_fail (fn_name
!= NULL
, NULL
);
1382 g_return_val_if_fail (ep
->sheet
!= NULL
, NULL
);
1384 /* FIXME : support workbook local functions */
1385 fn_def
= gnm_func_lookup (fn_name
, NULL
);
1387 return value_new_error_NAME (ep
);
1388 return function_def_call_with_values (ep
, fn_def
, argc
, values
);
1392 function_def_call_with_values (GnmEvalPos
const *ep
, GnmFunc
const *fn_def
,
1393 int argc
, GnmValue
const * const *values
)
1401 ef
.func
= (GnmFunc
*)fn_def
;
1403 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1405 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
) {
1407 * If function deals with ExprNodes, create some
1408 * temporary ExprNodes with constants.
1410 GnmExprConstant
*expr
= g_new (GnmExprConstant
, argc
);
1411 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, argc
);
1414 for (i
= 0; i
< argc
; i
++) {
1415 gnm_expr_constant_init (expr
+ i
, values
[i
]);
1416 argv
[i
] = (GnmExprConstPtr
)(expr
+ i
);
1418 retval
= fn_def
->fn
.nodes (&fs
, argc
, argv
);
1422 retval
= fn_def
->fn
.args
.func (&fs
, values
);
1427 /* ------------------------------------------------------------------------- */
1430 FunctionIterateCB callback
;
1433 gboolean ignore_subtotal
;
1434 } IterateCallbackClosure
;
1437 * cb_iterate_cellrange:
1439 * Helper routine used by the function_iterate_do_value routine.
1440 * Invoked by the sheet cell range iterator.
1443 cb_iterate_cellrange (GnmCellIter
const *iter
, gpointer user
)
1446 IterateCallbackClosure
*data
= user
;
1451 if (NULL
== (cell
= iter
->cell
)) {
1452 ep
.sheet
= iter
->pp
.sheet
;
1454 ep
.eval
.col
= iter
->pp
.eval
.col
;
1455 ep
.eval
.row
= iter
->pp
.eval
.row
;
1456 return (*data
->callback
)(&ep
, NULL
, data
->closure
);
1459 if (data
->ignore_subtotal
&& gnm_cell_has_expr (cell
) &&
1460 gnm_expr_top_contains_subtotal (cell
->base
.texpr
))
1463 gnm_cell_eval (cell
);
1464 eval_pos_init_cell (&ep
, cell
);
1466 /* If we encounter an error for the strict case, short-circuit here. */
1467 if (data
->strict
&& (NULL
!= (res
= gnm_cell_is_error (cell
))))
1468 return value_new_error_str (&ep
, res
->v_err
.mesg
);
1470 /* All other cases -- including error -- just call the handler. */
1471 return (*data
->callback
)(&ep
, cell
->value
, data
->closure
);
1475 * function_iterate_do_value:
1477 * Helper routine for function_iterate_argument_values.
1480 function_iterate_do_value (GnmEvalPos
const *ep
,
1481 FunctionIterateCB callback
,
1483 GnmValue
const *value
,
1485 CellIterFlags iter_flags
)
1487 GnmValue
*res
= NULL
;
1489 switch (value
->v_any
.type
){
1492 res
= value_dup (value
);
1501 res
= (*callback
)(ep
, value
, closure
);
1507 /* Note the order here. */
1508 for (y
= 0; y
< value
->v_array
.y
; y
++) {
1509 for (x
= 0; x
< value
->v_array
.x
; x
++) {
1510 res
= function_iterate_do_value (
1511 ep
, callback
, closure
,
1512 value
->v_array
.vals
[x
][y
],
1513 strict
, CELL_ITER_IGNORE_BLANK
);
1520 case VALUE_CELLRANGE
: {
1521 IterateCallbackClosure data
;
1523 data
.callback
= callback
;
1524 data
.closure
= closure
;
1525 data
.strict
= strict
;
1526 data
.ignore_subtotal
= (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
) != 0;
1528 res
= workbook_foreach_cell_in_range (ep
, value
, iter_flags
,
1529 cb_iterate_cellrange
,
1537 * function_iterate_argument_values:
1538 * @ep: The position in a workbook at which to evaluate
1539 * @callback: (scope call): The routine to be invoked for every value computed
1540 * @callback_closure: Closure for the callback.
1543 * @strict: If TRUE, the function is considered "strict". This means
1544 * that if an error value occurs as an argument, the iteration
1545 * will stop and that error will be returned. If FALSE, an
1546 * error will be passed on to the callback (as a GnmValue *
1547 * of type VALUE_ERROR).
1551 * NULL : if no errors were reported.
1552 * GnmValue * : if an error was found during strict evaluation
1553 * VALUE_TERMINATE : if the callback requested termination of the iteration.
1555 * This routine provides a simple way for internal functions with variable
1556 * number of arguments to be written: this would iterate over a list of
1557 * expressions (expr_node_list) and will invoke the callback for every
1558 * GnmValue found on the list (this means that ranges get properly expaned).
1561 function_iterate_argument_values (GnmEvalPos
const *ep
,
1562 FunctionIterateCB callback
,
1563 void *callback_closure
,
1565 GnmExprConstPtr
const *argv
,
1567 CellIterFlags iter_flags
)
1569 GnmValue
*result
= NULL
;
1572 for (a
= 0; result
== NULL
&& a
< argc
; a
++) {
1573 GnmExpr
const *expr
= argv
[a
];
1576 if (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
&&
1577 gnm_expr_contains_subtotal (expr
))
1580 /* need to drill down into names to handle things like
1581 * sum(name) with name := (A:A,B:B) */
1582 while (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_NAME
) {
1583 GnmExprTop
const *texpr
= expr
->name
.name
->texpr
;
1584 expr
= texpr
? texpr
->expr
: NULL
;
1587 return value_new_error_REF (ep
);
1594 /* Handle sets as a special case */
1595 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_SET
) {
1596 result
= function_iterate_argument_values
1597 (ep
, callback
, callback_closure
,
1598 expr
->set
.argc
, expr
->set
.argv
,
1599 strict
, iter_flags
);
1603 /* We need a cleaner model of what to do here.
1606 * will obviously return Range
1608 * SUM(INDIRECT(Range))
1609 * SUM(INDIRECT(Range):....)
1610 * will do implicit intersection on Range (in non-array mode),
1611 * but allow non-scalar results from indirect (no intersection)
1614 * will do implicit intersection in non-array mode */
1615 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_CONSTANT
)
1616 val
= value_dup (expr
->constant
.value
);
1617 else if (eval_pos_is_array_context (ep
) ||
1618 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
||
1619 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_RANGE_CTOR
||
1620 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_INTERSECT
)
1621 val
= gnm_expr_eval (expr
, ep
,
1622 GNM_EXPR_EVAL_PERMIT_EMPTY
| GNM_EXPR_EVAL_PERMIT_NON_SCALAR
);
1624 val
= gnm_expr_eval (expr
, ep
, GNM_EXPR_EVAL_PERMIT_EMPTY
);
1629 if (strict
&& VALUE_IS_ERROR (val
)) {
1630 /* Be careful not to make VALUE_TERMINATE into a real value */
1634 result
= function_iterate_do_value (ep
, callback
, callback_closure
,
1635 val
, strict
, iter_flags
);
1636 value_release (val
);
1643 * gnm_eval_info_get_func:
1644 * @ei: #GnmFuncEvalInfo
1646 * Returns: (transfer none): the called function.
1649 gnm_eval_info_get_func (GnmFuncEvalInfo
const *ei
)
1651 return ei
->func_call
->func
;
1655 gnm_eval_info_get_arg_count (GnmFuncEvalInfo
const *ei
)
1657 return ei
->func_call
->argc
;
1661 gnm_func_link_dep (GnmFunc
*func
, GnmFuncEvalInfo
*ei
, gboolean qlink
)
1663 int res
= DEPENDENT_NO_FLAG
;
1664 g_signal_emit (func
, signals
[SIG_LINK_DEP
], 0, ei
, qlink
, &res
);
1665 return (GnmDependentFlags
)res
;
1668 /* ------------------------------------------------------------------------- */
1670 static GObjectClass
*parent_class
;
1673 GObjectClass parent
;
1675 void (*load_stub
) (GnmFunc
*func
);
1676 int (*link_dep
) (GnmFunc
*func
, GnmFuncEvalInfo
*ei
, gboolean qlink
);
1680 gnm_func_finalize (GObject
*obj
)
1682 GnmFunc
*func
= GNM_FUNC (obj
);
1684 if (func
->usage_count
!= 0) {
1685 g_printerr ("Function %s still has a usage count of %d\n",
1686 func
->name
, func
->usage_count
);
1689 if (func
->fn_group
) {
1690 gnm_func_group_remove_func (func
->fn_group
, func
);
1691 func
->fn_group
= NULL
;
1694 gnm_func_set_localized_name (func
, NULL
);
1696 if (!(func
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
)) {
1697 g_hash_table_remove (functions_by_name
, func
->name
);
1700 if (func
->fn_type
== GNM_FUNC_TYPE_ARGS
)
1701 g_free (func
->fn
.args
.arg_types
);
1703 g_free ((char *)func
->name
);
1705 go_string_unref (func
->tdomain
);
1707 gnm_func_clear_arg_names (func
);
1709 parent_class
->finalize (obj
);
1713 gnm_func_get_property (GObject
*object
, guint property_id
,
1714 GValue
*value
, GParamSpec
*pspec
)
1716 GnmFunc
*func
= (GnmFunc
*)object
;
1718 switch (property_id
) {
1720 g_value_set_string (value
, func
->name
);
1722 case PROP_TRANSLATION_DOMAIN
:
1723 g_value_set_string (value
, func
->tdomain
->str
);
1726 g_value_set_boolean (value
, func
->usage_count
> 0);
1729 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1735 gnm_func_set_property (GObject
*object
, guint property_id
,
1736 GValue
const *value
, GParamSpec
*pspec
)
1738 GnmFunc
*func
= (GnmFunc
*)object
;
1740 switch (property_id
) {
1742 func
->name
= g_value_dup_string (value
);
1744 case PROP_TRANSLATION_DOMAIN
:
1745 gnm_func_set_translation_domain (func
,
1746 g_value_get_string (value
));
1749 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1755 gnm_func_init (GnmFunc
*func
)
1757 func
->tdomain
= go_string_new (GETTEXT_PACKAGE
);
1761 gnm_func_class_init (GObjectClass
*gobject_class
)
1763 parent_class
= g_type_class_peek_parent (gobject_class
);
1765 gobject_class
->finalize
= gnm_func_finalize
;
1766 gobject_class
->get_property
= gnm_func_get_property
;
1767 gobject_class
->set_property
= gnm_func_set_property
;
1769 g_object_class_install_property (gobject_class
, PROP_NAME
,
1770 g_param_spec_string ("name",
1772 P_("The name of the function."),
1776 G_PARAM_CONSTRUCT_ONLY
));
1778 g_object_class_install_property (gobject_class
, PROP_TRANSLATION_DOMAIN
,
1779 g_param_spec_string ("translation-domain",
1780 P_("Translation Domain"),
1781 P_("The translation domain for help texts"),
1784 G_PARAM_READWRITE
));
1786 g_object_class_install_property (gobject_class
, PROP_IN_USE
,
1787 g_param_spec_boolean ("in-use",
1789 P_("Is function being used?"),
1794 signals
[SIG_LOAD_STUB
] = g_signal_new
1798 G_STRUCT_OFFSET (GnmFuncClass
, load_stub
),
1800 g_cclosure_marshal_VOID__VOID
,
1804 signals
[SIG_LINK_DEP
] = g_signal_new
1808 G_STRUCT_OFFSET (GnmFuncClass
, link_dep
),
1810 gnm__INT__POINTER_BOOLEAN
,
1811 // GnmDependentFlags ... GnmFuncEvalInfo
1812 G_TYPE_INT
, 2, G_TYPE_POINTER
, G_TYPE_BOOLEAN
);
1815 GSF_CLASS (GnmFunc
, gnm_func
,
1816 gnm_func_class_init
, gnm_func_init
, G_TYPE_OBJECT
)