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)
11 #include <gnumeric-config.h>
12 #include <glib/gi18n-lib.h>
13 #include <glib/gstdio.h>
18 #include <parse-util.h>
19 #include <dependent.h>
21 #include <expr-impl.h>
22 #include <expr-name.h>
24 #include <workbook-priv.h>
27 #include <number-match.h>
28 #include <func-builtin.h>
29 #include <command-context-stderr.h>
30 #include <gnm-plugin.h>
33 #include <gnm-marshalers.h>
35 #include <goffice/goffice.h>
43 PROP_TRANSLATION_DOMAIN
,
52 static guint signals
[LAST_SIGNAL
] = { 0 };
55 #define F2(func,s) dgettext ((func)->tdomain->str, (s))
57 static GList
*categories
;
58 static GnmFuncGroup
*unknown_cat
;
60 static GHashTable
*functions_by_name
;
61 static GHashTable
*functions_by_localized_name
;
64 * functions_init: (skip)
70 g_hash_table_new (go_ascii_strcase_hash
, go_ascii_strcase_equal
);
73 functions_by_localized_name
=
74 g_hash_table_new (go_ascii_strcase_hash
, go_ascii_strcase_equal
);
80 * functions_shutdown: (skip)
83 functions_shutdown (void)
85 while (unknown_cat
!= NULL
&& unknown_cat
->functions
!= NULL
) {
86 GnmFunc
*func
= unknown_cat
->functions
->data
;
87 if (func
->usage_count
> 0) {
88 g_warning ("Function %s still has %d users.\n",
89 gnm_func_get_name (func
, FALSE
),
91 func
->usage_count
= 0;
93 g_object_unref (func
);
95 func_builtin_shutdown ();
97 g_hash_table_destroy (functions_by_name
);
98 functions_by_name
= NULL
;
100 g_hash_table_destroy (functions_by_localized_name
);
101 functions_by_localized_name
= NULL
;
105 * gnm_func_enumerate:
107 * Return value: (element-type GnmFunc) (transfer container):
110 gnm_func_enumerate (void)
112 GPtrArray
*res
= g_ptr_array_new ();
113 GHashTableIter hiter
;
116 g_hash_table_iter_init (&hiter
, functions_by_name
);
117 while (g_hash_table_iter_next (&hiter
, NULL
, &value
))
118 g_ptr_array_add (res
, value
);
124 error_function_no_full_info (GnmFuncEvalInfo
*ei
,
126 GnmExprConstPtr
const *argv
)
128 return value_new_error (ei
->pos
, _("Function implementation not available."));
132 gnm_func_load_stub (GnmFunc
*func
)
134 g_return_if_fail (func
->fn_type
== GNM_FUNC_TYPE_STUB
);
136 g_signal_emit (G_OBJECT (func
), signals
[SIG_LOAD_STUB
], 0);
138 if (func
->fn_type
== GNM_FUNC_TYPE_STUB
) {
139 static GnmFuncHelp
const no_help
[] = { { GNM_FUNC_HELP_END
} };
140 gnm_func_set_varargs (func
, error_function_no_full_info
);
141 func
->help
= no_help
;
146 gnm_func_load_if_stub (GnmFunc
*func
)
148 if (func
->fn_type
== GNM_FUNC_TYPE_STUB
)
149 gnm_func_load_stub (func
);
153 split_at_colon (char const *s
, char **rest
)
155 char *dup
= g_strdup (s
);
156 char *colon
= strchr (dup
, ':');
159 if (rest
) *rest
= colon
+ 1;
161 if (rest
) *rest
= NULL
;
166 /* ------------------------------------------------------------------------- */
169 gnm_func_group_free (GnmFuncGroup
*fn_group
)
171 g_return_if_fail (fn_group
!= NULL
);
172 g_return_if_fail (fn_group
->functions
== NULL
);
174 if (fn_group
->ref_count
-- > 1)
177 go_string_unref (fn_group
->internal_name
);
178 go_string_unref (fn_group
->display_name
);
182 static GnmFuncGroup
*
183 gnm_func_group_ref (GnmFuncGroup
*fn_group
)
185 fn_group
->ref_count
++;
190 gnm_func_group_get_type (void)
195 t
= g_boxed_type_register_static ("GnmFuncGroup",
196 (GBoxedCopyFunc
)gnm_func_group_ref
,
197 (GBoxedFreeFunc
)gnm_func_group_free
);
203 function_category_compare (gconstpointer a
, gconstpointer b
)
205 GnmFuncGroup
const *cat_a
= a
;
206 GnmFuncGroup
const *cat_b
= b
;
208 return go_string_cmp (cat_a
->display_name
, cat_b
->display_name
);
212 gnm_func_group_fetch (char const *name
, char const *translation
)
214 GnmFuncGroup
*cat
= NULL
;
217 g_return_val_if_fail (name
!= NULL
, NULL
);
219 for (l
= categories
; l
!= NULL
; l
= l
->next
) {
221 if (strcmp (cat
->internal_name
->str
, name
) == 0) {
227 cat
= g_new (GnmFuncGroup
, 1);
228 cat
->internal_name
= go_string_new (name
);
230 if (translation
!= NULL
) {
231 cat
->display_name
= go_string_new (translation
);
232 cat
->has_translation
= TRUE
;
234 cat
->display_name
= go_string_new (name
);
235 cat
->has_translation
= FALSE
;
237 cat
->functions
= NULL
;
238 categories
= g_list_insert_sorted (
239 categories
, cat
, &function_category_compare
);
240 } else if (translation
!= NULL
&& translation
!= name
&&
241 !cat
->has_translation
) {
242 go_string_unref (cat
->display_name
);
243 cat
->display_name
= go_string_new (translation
);
244 cat
->has_translation
= TRUE
;
245 categories
= g_list_remove_link (categories
, l
);
247 categories
= g_list_insert_sorted (
248 categories
, cat
, &function_category_compare
);
255 gnm_func_group_get_nth (int n
)
257 return g_list_nth_data (categories
, n
);
261 gnm_func_group_add_func (GnmFuncGroup
*fn_group
, GnmFunc
*fn_def
)
263 g_return_if_fail (fn_group
!= NULL
);
264 g_return_if_fail (fn_def
!= NULL
);
266 fn_group
->functions
= g_slist_prepend (fn_group
->functions
, fn_def
);
270 gnm_func_group_remove_func (GnmFuncGroup
*fn_group
, GnmFunc
*fn_def
)
272 g_return_if_fail (fn_group
!= NULL
);
273 g_return_if_fail (fn_def
!= NULL
);
275 fn_group
->functions
= g_slist_remove (fn_group
->functions
, fn_def
);
276 if (fn_group
->functions
== NULL
) {
277 categories
= g_list_remove (categories
, fn_group
);
278 if (unknown_cat
== fn_group
)
280 gnm_func_group_free (fn_group
);
284 /******************************************************************************/
287 gnm_func_create_arg_names (GnmFunc
*fn_def
)
292 g_return_if_fail (fn_def
!= NULL
);
294 ptr
= g_ptr_array_new ();
296 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
298 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
303 (F2(fn_def
, fn_def
->help
[i
].text
), NULL
));
306 fn_def
->arg_names
= ptr
;
310 gnm_func_is_varargs (GnmFunc
*func
)
312 gnm_func_load_stub (func
);
313 return func
->fn_type
== GNM_FUNC_TYPE_NODES
;
317 gnm_func_is_fixargs (GnmFunc
*func
)
319 gnm_func_load_stub (func
);
320 return func
->fn_type
== GNM_FUNC_TYPE_ARGS
;
324 gnm_func_set_stub (GnmFunc
*func
)
326 func
->fn_type
= GNM_FUNC_TYPE_STUB
;
328 g_free (func
->arg_spec
);
329 func
->arg_spec
= NULL
;
331 g_free (func
->arg_types
);
332 func
->arg_types
= NULL
;
334 if (func
->arg_names
) {
335 g_ptr_array_foreach (func
->arg_names
, (GFunc
)g_free
, NULL
);
336 g_ptr_array_free (func
->arg_names
, TRUE
);
337 func
->arg_names
= NULL
;
340 func
->min_args
= func
->max_args
= 0;
342 func
->nodes_func
= NULL
;
343 func
->args_func
= NULL
;
347 * gnm_func_set_varargs: (skip)
349 * @fn: evaluation function
352 gnm_func_set_varargs (GnmFunc
*func
, GnmFuncNodes fn
)
354 g_return_if_fail (GNM_IS_FUNC (func
));
355 g_return_if_fail (fn
!= NULL
);
357 gnm_func_set_stub (func
); // Clear out stuff
359 func
->fn_type
= GNM_FUNC_TYPE_NODES
;
360 func
->nodes_func
= fn
;
362 func
->min_args
= G_MAXINT
;
366 * gnm_func_set_fixargs: (skip)
368 * @fn: evaluation function
369 * @spec: argument type specification
372 gnm_func_set_fixargs (GnmFunc
*func
, GnmFuncArgs fn
, const char *spec
)
376 g_return_if_fail (GNM_IS_FUNC (func
));
377 g_return_if_fail (fn
!= NULL
);
378 g_return_if_fail (spec
!= NULL
);
380 gnm_func_set_stub (func
); // Clear out stuff
382 func
->fn_type
= GNM_FUNC_TYPE_ARGS
;
383 func
->args_func
= fn
;
384 func
->arg_spec
= g_strdup (spec
);
386 func
->arg_types
= g_strdup (func
->arg_spec
);
387 p
= strchr (func
->arg_types
, '|');
389 func
->min_args
= p
- func
->arg_types
;
390 memmove (p
, p
+ 1, strlen (p
));
393 func
->max_args
= strlen (func
->arg_types
);
395 gnm_func_create_arg_names (func
);
399 gnm_func_set_localized_name (GnmFunc
*fd
, const char *lname
)
401 gboolean in_hashes
= !(fd
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
);
403 if (g_strcmp0 (fd
->localized_name
, lname
) == 0)
406 if (in_hashes
&& fd
->localized_name
)
407 g_hash_table_remove (functions_by_localized_name
, fd
->localized_name
);
408 g_free (fd
->localized_name
);
410 fd
->localized_name
= g_strdup (lname
);
411 if (in_hashes
&& lname
)
412 g_hash_table_insert (functions_by_localized_name
,
413 fd
->localized_name
, fd
);
417 * gnm_func_inc_usage:
420 * This function increments the usage count of @func. A non-zero usage count
421 * prevents the unloading of the function.
423 * Returns: (transfer full): a new reference to @func.
426 gnm_func_inc_usage (GnmFunc
*func
)
428 g_return_val_if_fail (func
!= NULL
, NULL
);
431 if (func
->usage_count
== 1)
432 g_object_notify (G_OBJECT (func
), "in-use");
437 * gnm_func_dec_usage:
438 * @func: (transfer full): #GnmFunc
440 * This function decrements the usage count of @func. When the usage count
441 * reaches zero, the function may be unloaded, for example by unloading the
442 * plugin that defines it.
445 gnm_func_dec_usage (GnmFunc
*func
)
447 g_return_if_fail (func
!= NULL
);
448 g_return_if_fail (func
->usage_count
> 0);
451 if (func
->usage_count
== 0)
452 g_object_notify (G_OBJECT (func
), "in-use");
456 gnm_func_get_in_use (GnmFunc
*func
)
458 g_return_val_if_fail (func
!= NULL
, FALSE
);
460 return func
->usage_count
> 0;
466 * @name: name of function
467 * @scope: (nullable): scope of function, %NULL for global
469 * Returns: (nullable) (transfer none): the function of that name.
472 gnm_func_lookup (char const *name
, Workbook
*scope
)
474 GnmFunc
*fd
= g_hash_table_lookup (functions_by_name
, name
);
477 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
479 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
483 * gnm_func_lookup_localized:
484 * @name: localized name of function
485 * @scope: (nullable): scope of function, %NULL for global
487 * Returns: (nullable) (transfer none): the function of that name.
490 gnm_func_lookup_localized (char const *name
, Workbook
*scope
)
493 GHashTableIter hiter
;
496 /* Must localize all function names. */
497 g_hash_table_iter_init (&hiter
, functions_by_name
);
498 while (g_hash_table_iter_next (&hiter
, NULL
, &value
)) {
500 (void)gnm_func_get_name (fd
, TRUE
);
503 fd
= g_hash_table_lookup (functions_by_localized_name
, name
);
506 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
508 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
512 * gnm_func_lookup_prefix:
513 * @prefix: prefix to search for
515 * @trans: whether to search translated function names
517 * Returns: (element-type GnmFunc*) (transfer full):
520 gnm_func_lookup_prefix (char const *prefix
, Workbook
*scope
, gboolean trans
)
523 GHashTableIter hiter
;
527 * Always iterate over functions_by_name as the localized name
528 * might not be set yet.
530 g_hash_table_iter_init (&hiter
, functions_by_name
);
531 while (g_hash_table_iter_next (&hiter
, NULL
, &value
)) {
533 if (!(fd
->flags
& GNM_FUNC_IS_PLACEHOLDER
)) {
534 const char *name
= gnm_func_get_name (fd
, trans
);
535 if (g_str_has_prefix (name
, prefix
)) {
536 gnm_func_inc_usage (fd
);
537 res
= g_slist_prepend (res
, fd
);
546 * gnm_func_get_translation_domain:
549 * Returns: (transfer none): the translation domain for @func's help text.
552 gnm_func_get_translation_domain (GnmFunc
*func
)
554 g_return_val_if_fail (GNM_IS_FUNC (func
), NULL
);
555 return func
->tdomain
->str
;
559 * gnm_func_set_translation_domain:
561 * @tdomain: (nullable): Translation domain, %NULL for Gnumeric's.
564 gnm_func_set_translation_domain (GnmFunc
*func
, const char *tdomain
)
566 g_return_if_fail (GNM_IS_FUNC (func
));
569 tdomain
= GETTEXT_PACKAGE
;
571 if (g_strcmp0 (func
->tdomain
->str
, tdomain
) == 0)
574 go_string_unref (func
->tdomain
);
575 func
->tdomain
= go_string_new (tdomain
);
577 g_object_notify (G_OBJECT (func
), "translation-domain");
581 gnm_func_get_flags (GnmFunc
*func
)
583 g_return_val_if_fail (GNM_IS_FUNC (func
), GNM_FUNC_SIMPLE
);
588 gnm_func_set_flags (GnmFunc
*func
, GnmFuncFlags f
)
590 g_return_if_fail (GNM_IS_FUNC (func
));
595 gnm_func_get_impl_status (GnmFunc
*func
)
597 g_return_val_if_fail (GNM_IS_FUNC (func
), GNM_FUNC_IMPL_STATUS_UNIMPLEMENTED
);
598 return func
->impl_status
;
602 gnm_func_set_impl_status (GnmFunc
*func
, GnmFuncImplStatus st
)
604 g_return_if_fail (GNM_IS_FUNC (func
));
605 func
->impl_status
= st
;
610 gnm_func_get_test_status (GnmFunc
*func
)
612 g_return_val_if_fail (GNM_IS_FUNC (func
), GNM_FUNC_TEST_STATUS_UNKNOWN
);
613 return func
->test_status
;
617 gnm_func_set_test_status (GnmFunc
*func
, GnmFuncTestStatus st
)
619 g_return_if_fail (GNM_IS_FUNC (func
));
620 func
->test_status
= st
;
625 * gnm_func_get_function_group:
628 * Returns: (transfer none): the function group to which @func belongs.
631 gnm_func_get_function_group (GnmFunc
*func
)
633 g_return_val_if_fail (GNM_IS_FUNC (func
), NULL
);
634 return func
->fn_group
;
639 gnm_func_set_function_group (GnmFunc
*func
, GnmFuncGroup
*group
)
641 g_return_if_fail (GNM_IS_FUNC (func
));
642 g_return_if_fail (group
!= NULL
);
644 if (func
->fn_group
== group
)
648 gnm_func_group_remove_func (func
->fn_group
, func
);
649 func
->fn_group
= group
;
650 gnm_func_group_add_func (group
, func
);
652 if (group
== unknown_cat
)
653 func
->flags
|= GNM_FUNC_IS_PLACEHOLDER
;
655 func
->flags
&= ~GNM_FUNC_IS_PLACEHOLDER
;
659 gnm_func_set_from_desc (GnmFunc
*func
, GnmFuncDescriptor
const *desc
)
661 g_return_if_fail (GNM_IS_FUNC (func
));
662 g_return_if_fail (desc
!= NULL
);
664 // Not setting name, localized_name. Also not setting things not present
665 // in desc, such as translation domain.
667 if (desc
->fn_args
!= NULL
) {
668 gnm_func_set_fixargs (func
, desc
->fn_args
, desc
->arg_spec
);
669 } else if (desc
->fn_nodes
!= NULL
) {
670 if (desc
->arg_spec
&& *desc
->arg_spec
)
671 g_warning ("Arg spec for node function -- why?");
672 gnm_func_set_varargs (func
, desc
->fn_nodes
);
674 gnm_func_set_stub (func
);
678 func
->help
= desc
->help
? desc
->help
: NULL
;
679 func
->flags
= desc
->flags
;
680 func
->impl_status
= desc
->impl_status
;
681 func
->test_status
= desc
->test_status
;
689 * @tdomain: (nullable):
691 * Returns: (transfer full): a new #GnmFunc.
694 gnm_func_add (GnmFuncGroup
*fn_group
,
695 GnmFuncDescriptor
const *desc
,
698 //static char const valid_tokens[] = "fsbraAES?|";
701 g_return_val_if_fail (fn_group
!= NULL
, NULL
);
702 g_return_val_if_fail (desc
!= NULL
, NULL
);
704 func
= g_object_new (GNM_FUNC_TYPE
,
707 gnm_func_set_translation_domain (func
, tdomain
);
709 gnm_func_set_from_desc (func
, desc
);
711 if (func
->fn_type
== GNM_FUNC_TYPE_STUB
) {
712 g_warning ("Invalid function has neither args nor nodes handler");
713 g_object_unref (func
);
717 gnm_func_set_function_group (func
, fn_group
);
719 if (!(func
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
))
720 g_hash_table_insert (functions_by_name
,
721 (gpointer
)(func
->name
), func
);
726 /* Handle unknown functions on import without losing their names */
728 unknownFunctionHandler (GnmFuncEvalInfo
*ei
,
729 G_GNUC_UNUSED
int argc
,
730 G_GNUC_UNUSED GnmExprConstPtr
const *argv
)
732 return value_new_error_NAME (ei
->pos
);
736 invent_name (const char *pref
, GHashTable
*h
, const char *template)
738 static int count
= 0;
739 char *name
= g_utf8_strdown (pref
, -1);
741 while (g_hash_table_lookup (h
, name
)) {
744 name
= g_strdup_printf (template, count
);
751 gnm_func_add_placeholder_full (Workbook
*scope
,
752 char const *gname
, char const *lname
,
755 GnmFuncDescriptor desc
;
757 char const *unknown_cat_name
= N_("Unknown Function");
758 gboolean copy_gname
= TRUE
;
759 gboolean copy_lname
= TRUE
;
761 g_return_val_if_fail (gname
|| lname
, NULL
);
762 g_return_val_if_fail (gname
== NULL
|| gnm_func_lookup (gname
, scope
) == NULL
, NULL
);
763 g_return_val_if_fail (lname
== NULL
|| gnm_func_lookup_localized (lname
, scope
) == NULL
, NULL
);
766 unknown_cat
= gnm_func_group_fetch
767 (unknown_cat_name
, _(unknown_cat_name
));
771 * This is actually a bit of a problem if we don't end up
772 * with a copy of lname (because there already is a function
773 * with that name). We're likely to save a template name,
774 * but I don't see what else to do.
776 gname
= invent_name (lname
, functions_by_name
, "unknown%d");
780 /* xgettext: This represents a made-up translated function name. */
781 lname
= invent_name (gname
, functions_by_localized_name
, _("unknown%d"));
785 if (gnm_debug_flag ("func"))
786 g_printerr ("Adding placeholder for %s (aka %s)\n", gname
, lname
);
788 memset (&desc
, 0, sizeof (GnmFuncDescriptor
));
790 desc
.arg_spec
= NULL
;
793 desc
.fn_nodes
= &unknownFunctionHandler
;
794 desc
.flags
= GNM_FUNC_IS_PLACEHOLDER
;
795 desc
.impl_status
= GNM_FUNC_IMPL_STATUS_EXISTS
;
796 desc
.test_status
= GNM_FUNC_TEST_STATUS_UNKNOWN
;
799 desc
.flags
|= GNM_FUNC_IS_WORKBOOK_LOCAL
;
802 /* WISHLIST : it would be nice to have a log if these. */
803 g_warning ("Unknown %s function : %s", type
, desc
.name
);
807 func
= gnm_func_add (unknown_cat
, &desc
, NULL
);
810 gnm_func_set_localized_name (func
, lname
);
812 g_free ((char *)lname
);
816 g_free ((char *)gname
);
819 if (scope
->sheet_local_functions
== NULL
)
820 scope
->sheet_local_functions
= g_hash_table_new_full (
821 g_str_hash
, g_str_equal
,
822 NULL
, g_object_unref
);
823 g_hash_table_insert (scope
->sheet_local_functions
,
824 (gpointer
)func
->name
, func
);
831 * gnm_func_add_placeholder:
832 * @scope: (nullable): scope to defined placeholder, %NULL for global
833 * @name: (nullable): function name
836 * Returns: (transfer none): a placeholder with the given name.
839 gnm_func_add_placeholder (Workbook
*scope
,
840 char const *name
, char const *type
)
842 return gnm_func_add_placeholder_full (scope
, name
, NULL
, type
);
846 * gnm_func_add_placeholder_localized:
847 * @gname: (nullable): function name
848 * @lname: localized function name
850 * Returns: (transfer none): a placeholder with the given localized name.
853 gnm_func_add_placeholder_localized (char const *gname
, char const *lname
)
855 return gnm_func_add_placeholder_full (NULL
, gname
, lname
, "?");
859 * gnm_func_lookup_or_add_placeholder:
860 * @name: function name
862 * Returns: (transfer none): a #GnmFunc named @name, either an existing
863 * one or a placeholder.
866 gnm_func_lookup_or_add_placeholder (char const *name
)
868 GnmFunc
* f
= gnm_func_lookup (name
, NULL
);
870 f
= gnm_func_add_placeholder (NULL
, name
, "");
876 * @func: #GnmFunc to query
877 * @localized: if %TRUE, use localized name
879 * Returns: (transfer none): @func's name
882 gnm_func_get_name (GnmFunc
const *func
, gboolean localized
)
885 GnmFunc
*fd
= (GnmFunc
*)func
;
887 g_return_val_if_fail (func
!= NULL
, NULL
);
892 if (func
->localized_name
)
893 return func
->localized_name
;
896 * Deduce the translated names from the help texts. This
897 * code doesn't currently check for clashes in translated
901 gnm_func_load_if_stub (fd
);
904 (func
->localized_name
== NULL
&&
906 func
->help
[i
].type
!= GNM_FUNC_HELP_END
);
910 if (func
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
913 s
= func
->help
[i
].text
;
915 if (s
== sl
) /* String not actually translated. */
918 U
= split_at_colon (F2 (func
, s
), NULL
);
920 char *lname
= g_utf8_strdown (U
, -1);
921 gnm_func_set_localized_name (fd
, lname
);
927 if (!func
->localized_name
)
928 gnm_func_set_localized_name (fd
, fd
->name
);
930 return func
->localized_name
;
934 * gnm_func_get_description:
935 * @fn_def: the fn defintion
937 * Returns: (transfer none): the description of the function
940 gnm_func_get_description (GnmFunc
const *fn_def
)
943 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
945 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
948 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
952 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
955 desc
= strchr (F2 (fn_def
, fn_def
->help
[i
].text
), ':');
956 return desc
? (desc
+ 1) : "";
962 * gnm_func_count_args:
963 * @fn_def: pointer to function definition
964 * @min: (out): location for mininum args
965 * @max: (out): location for mininum args
967 * This calculates the maximum and minimum number of args that can be passed.
968 * For a vararg function, the maximum will be set to G_MAXINT.
971 gnm_func_count_args (GnmFunc
const *fn_def
, int *min
, int *max
)
973 g_return_if_fail (min
!= NULL
);
974 g_return_if_fail (max
!= NULL
);
975 g_return_if_fail (fn_def
!= NULL
);
977 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
979 *min
= fn_def
->min_args
;
980 *max
= fn_def
->max_args
;
984 * gnm_func_get_arg_type:
985 * @fn_def: the fn defintion
986 * @arg_idx: zero-based argument offset
988 * Returns: the type of the argument
991 gnm_func_get_arg_type (GnmFunc
const *fn_def
, int arg_idx
)
993 g_return_val_if_fail (fn_def
!= NULL
, '?');
995 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
997 g_return_val_if_fail (arg_idx
>= 0 && arg_idx
< fn_def
->max_args
, '?');
999 return fn_def
->arg_types
? fn_def
->arg_types
[arg_idx
] : '?';
1003 * gnm_func_get_arg_type_string:
1004 * @fn_def: the fn defintion
1005 * @arg_idx: zero-based argument offset
1007 * Return value: (transfer none): the type of the argument as a string
1010 gnm_func_get_arg_type_string (GnmFunc
const *fn_def
,
1013 switch (gnm_func_get_arg_type (fn_def
, arg_idx
)) {
1019 return _("Boolean");
1021 return _("Cell Range");
1025 return _("Scalar, Blank, or Error");
1029 /* Missing values will be NULL. */
1033 g_warning ("Unknown arg type");
1039 * gnm_func_get_arg_name:
1041 * @arg_idx: zero-based argument offset
1043 * Returns: (transfer full) (nullable): the name of the argument
1046 gnm_func_get_arg_name (GnmFunc
const *func
, guint arg_idx
)
1048 g_return_val_if_fail (func
!= NULL
, NULL
);
1050 gnm_func_load_if_stub ((GnmFunc
*)func
);
1052 if (func
->arg_names
&& arg_idx
< func
->arg_names
->len
)
1053 return g_strdup (g_ptr_array_index (func
->arg_names
, arg_idx
));
1058 * gnm_func_get_arg_description:
1059 * @fn_def: the fn defintion
1060 * @arg_idx: zero-based argument offset
1062 * Returns: (transfer none): the description of the argument
1065 gnm_func_get_arg_description (GnmFunc
const *fn_def
, guint arg_idx
)
1068 g_return_val_if_fail (fn_def
!= NULL
, NULL
);
1070 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1073 fn_def
->help
&& fn_def
->help
[i
].type
!= GNM_FUNC_HELP_END
;
1077 if (fn_def
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
1082 desc
= strchr (F2 (fn_def
, fn_def
->help
[i
].text
), ':');
1087 while (g_unichar_isspace (g_utf8_get_char (desc
)))
1088 desc
= g_utf8_next_char (desc
);
1096 * gnm_func_convert_markup_to_pango:
1097 * @desc: the fn or arg description string
1098 * @target: target widget for the markup.
1100 * Return value: the escaped string with @{} markup converted to
1104 gnm_func_convert_markup_to_pango (char const *desc
, GtkWidget
*target
)
1110 char *link_color_text
, *span_text
;
1111 size_t span_text_len
;
1113 gnm_get_link_color (target
, &link_color
);
1114 pg
.red
= 65535 * link_color
.red
;
1115 pg
.green
= 65535 * link_color
.green
;
1116 pg
.blue
= 65535 * link_color
.blue
;
1117 link_color_text
= pango_color_to_string (&pg
);
1118 span_text
= g_strdup_printf ("<span foreground=\"%s\">",
1120 span_text_len
= strlen (span_text
);
1121 g_free (link_color_text
);
1123 markup
= g_markup_escape_text (desc
, -1);
1124 str
= g_string_new (markup
);
1127 while ((at
= strstr (str
->str
, "@{"))) {
1128 gint len
= at
- str
->str
;
1129 go_string_replace (str
, len
, 2, span_text
, -1);
1131 (str
->str
+ len
+ span_text_len
, "}"))) {
1132 len
= at
- str
->str
;
1133 go_string_replace (str
, len
, 1, "</span>", -1);
1135 g_string_append (str
, "</span>");
1139 return g_string_free (str
, FALSE
);
1143 /* ------------------------------------------------------------------------- */
1146 free_values (GnmValue
**values
, int top
)
1150 for (i
= 0; i
< top
; i
++)
1152 value_release (values
[i
]);
1155 /* ------------------------------------------------------------------------- */
1158 * function_call_with_exprs:
1159 * @ei: EvalInfo containing valid fn_def!
1161 * Do the guts of calling a function.
1163 * Returns the result.
1166 function_call_with_exprs (GnmFuncEvalInfo
*ei
)
1168 GnmFunc
const *fn_def
;
1169 int i
, iter_count
, iter_width
= 0, iter_height
= 0;
1171 GnmValue
**args
, *tmp
= NULL
;
1172 int *iter_item
= NULL
;
1174 GnmExprConstPtr
*argv
;
1175 GnmExprEvalFlags flags
, pass_flags
;
1177 g_return_val_if_fail (ei
!= NULL
, NULL
);
1178 g_return_val_if_fail (ei
->func_call
!= NULL
, NULL
);
1182 argc
= ei
->func_call
->argc
;
1183 argv
= ei
->func_call
->argv
;
1184 fn_def
= ei
->func_call
->func
;
1186 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1188 /* Functions that deal with ExprNodes */
1189 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
)
1190 return fn_def
->nodes_func (ei
, argc
, argv
);
1192 /* Functions that take pre-computed Values */
1193 if (argc
> fn_def
->max_args
||
1194 argc
< fn_def
->min_args
)
1195 return value_new_error_NA (ei
->pos
);
1197 args
= g_alloca (sizeof (GnmValue
*) * fn_def
->max_args
);
1198 iter_count
= (eval_pos_is_array_context (ei
->pos
) &&
1199 (flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
))
1202 /* Optimization for IF when implicit iteration is not used. */
1203 if (ei
->func_call
->func
->args_func
== gnumeric_if
&&
1205 return gnumeric_if2 (ei
, argc
, argv
, flags
);
1207 pass_flags
= (flags
&
1208 (GNM_EXPR_EVAL_ARRAY_CONTEXT
));
1210 for (i
= 0; i
< argc
; i
++) {
1211 char arg_type
= fn_def
->arg_types
[i
];
1212 /* expr is always non-null, missing args are encoded as
1214 GnmExpr
const *expr
= argv
[i
];
1216 if (arg_type
== 'A' || arg_type
== 'r') {
1217 tmp
= args
[i
] = gnm_expr_eval
1220 GNM_EXPR_EVAL_PERMIT_NON_SCALAR
|
1221 GNM_EXPR_EVAL_WANT_REF
);
1222 if (VALUE_IS_ERROR (tmp
)) {
1223 free_values (args
, i
);
1227 if (VALUE_IS_CELLRANGE (tmp
)) {
1228 gnm_cellref_make_abs (&tmp
->v_range
.cell
.a
,
1229 &tmp
->v_range
.cell
.a
,
1231 gnm_cellref_make_abs (&tmp
->v_range
.cell
.b
,
1232 &tmp
->v_range
.cell
.b
,
1234 /* Array args accept scalars */
1235 } else if (arg_type
!= 'A' && !VALUE_IS_ARRAY (tmp
)) {
1236 free_values (args
, i
+ 1);
1237 return value_new_error_VALUE (ei
->pos
);
1242 /* force scalars whenever we are certain */
1243 tmp
= args
[i
] = gnm_expr_eval
1246 GNM_EXPR_EVAL_PERMIT_EMPTY
|
1247 (iter_count
>= 0 || arg_type
== '?'
1248 ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1251 if (arg_type
== '?') /* '?' arguments are unrestriced */
1254 /* optional arguments can be blank */
1255 if (i
>= fn_def
->min_args
&& VALUE_IS_EMPTY (tmp
)) {
1256 if (arg_type
== 'E' && !gnm_expr_is_empty (expr
)) {
1257 /* An actual argument produced empty. Make
1258 sure function sees that. */
1259 args
[i
] = value_new_empty ();
1266 tmp
= args
[i
] = value_new_empty ();
1268 /* Handle implicit intersection or iteration depending on flags */
1269 if (VALUE_IS_CELLRANGE (tmp
) || VALUE_IS_ARRAY (tmp
)) {
1270 if (iter_count
> 0) {
1271 if (iter_width
!= value_area_get_width (tmp
, ei
->pos
) ||
1272 iter_height
!= value_area_get_height (tmp
, ei
->pos
)) {
1273 free_values (args
, i
+ 1);
1274 return value_new_error_VALUE (ei
->pos
);
1277 if (iter_count
< 0) {
1278 g_warning ("Damn I thought this was impossible");
1281 iter_item
= g_alloca (sizeof (int) * argc
);
1282 iter_width
= value_area_get_width (tmp
, ei
->pos
);
1283 iter_height
= value_area_get_height (tmp
, ei
->pos
);
1285 iter_item
[iter_count
++] = i
;
1287 /* no need to check type, we would fail comparing a range against a "b, f, or s" */
1291 /* All of these argument types must be scalars */
1294 if (VALUE_IS_STRING (tmp
)) {
1296 gboolean b
= value_get_as_bool (tmp
, &err
);
1298 free_values (args
, i
+ 1);
1299 return value_new_error_VALUE (ei
->pos
);
1301 value_release (args
[i
]);
1302 tmp
= args
[i
] = value_new_bool (b
);
1307 if (VALUE_IS_STRING (tmp
)) {
1308 tmp
= format_match_number (value_peek_string (tmp
), NULL
,
1309 sheet_date_conv (ei
->pos
->sheet
));
1311 free_values (args
, i
+ 1);
1312 return value_new_error_VALUE (ei
->pos
);
1314 value_release (args
[i
]);
1316 } else if (VALUE_IS_ERROR (tmp
)) {
1317 free_values (args
, i
);
1319 } else if (VALUE_IS_EMPTY (tmp
)) {
1320 value_release (args
[i
]);
1321 tmp
= args
[i
] = value_new_int (0);
1324 if (!VALUE_IS_NUMBER (tmp
))
1325 return value_new_error_VALUE (ei
->pos
);
1330 if (VALUE_IS_ERROR (tmp
)) {
1331 free_values (args
, i
);
1336 case 'E': /* nothing necessary */
1339 /* case '?': handled above */
1341 g_warning ("Unknown argument type '%c'", arg_type
);
1346 while (i
< fn_def
->max_args
)
1349 if (iter_item
!= NULL
) {
1351 GnmValue
*res
= value_new_array_empty (iter_width
, iter_height
);
1352 GnmValue
const *elem
, *err
;
1353 GnmValue
**iter_vals
= g_alloca (sizeof (GnmValue
*) * iter_count
);
1354 GnmValue
**iter_args
= g_alloca (sizeof (GnmValue
*) * iter_count
);
1356 /* collect the args we will iterate on */
1357 for (i
= 0 ; i
< iter_count
; i
++)
1358 iter_vals
[i
] = args
[iter_item
[i
]];
1360 for (x
= iter_width
; x
-- > 0 ; )
1361 for (y
= iter_height
; y
-- > 0 ; ) {
1362 /* marshal the args */
1364 for (i
= 0 ; i
< iter_count
; i
++) {
1365 elem
= value_area_get_x_y (iter_vals
[i
], x
, y
, ei
->pos
);
1366 arg_type
= fn_def
->arg_types
[iter_item
[i
]];
1367 if (arg_type
== 'b' || arg_type
== 'f') {
1368 if (VALUE_IS_EMPTY (elem
))
1370 else if (VALUE_IS_STRING (elem
)) {
1371 tmp
= format_match_number (value_peek_string (elem
), NULL
,
1372 sheet_date_conv (ei
->pos
->sheet
));
1374 args
[iter_item
[i
]] = iter_args
[i
] = tmp
;
1378 } else if (VALUE_IS_ERROR (elem
)) {
1381 } else if (!VALUE_IS_NUMBER (elem
))
1383 } else if (arg_type
== 's') {
1384 if (VALUE_IS_EMPTY (elem
)) {
1385 args
[iter_item
[i
]] = iter_args
[i
] = value_new_string ("");
1387 } else if (VALUE_IS_ERROR (elem
)) {
1390 } else if (!VALUE_IS_STRING (elem
))
1392 } else if (elem
== NULL
) {
1393 args
[iter_item
[i
]] = iter_args
[i
] = value_new_empty ();
1396 args
[iter_item
[i
]] = iter_args
[i
] = value_dup (elem
);
1399 res
->v_array
.vals
[x
][y
] = (i
== iter_count
)
1400 ? fn_def
->args_func (ei
, (GnmValue
const * const *)args
)
1401 : ((err
!= NULL
) ? value_dup (err
)
1402 : value_new_error_VALUE (ei
->pos
));
1403 free_values (iter_args
, i
);
1406 /* free the primaries, not the already freed iteration */
1407 for (i
= 0 ; i
< iter_count
; i
++)
1408 args
[iter_item
[i
]] = iter_vals
[i
];
1410 i
= fn_def
->max_args
;
1412 tmp
= fn_def
->args_func (ei
, (GnmValue
const * const *)args
);
1414 free_values (args
, i
);
1419 * Use this to invoke a register function: the only drawback is that
1420 * you have to compute/expand all of the values to use this
1423 function_call_with_values (GnmEvalPos
const *ep
, char const *fn_name
,
1424 int argc
, GnmValue
const * const *values
)
1428 g_return_val_if_fail (ep
!= NULL
, NULL
);
1429 g_return_val_if_fail (fn_name
!= NULL
, NULL
);
1430 g_return_val_if_fail (ep
->sheet
!= NULL
, NULL
);
1432 /* FIXME : support workbook local functions */
1433 fn_def
= gnm_func_lookup (fn_name
, NULL
);
1435 return value_new_error_NAME (ep
);
1436 return function_def_call_with_values (ep
, fn_def
, argc
, values
);
1440 function_def_call_with_values (GnmEvalPos
const *ep
, GnmFunc
const *fn_def
,
1441 int argc
, GnmValue
const * const *values
)
1449 ef
.func
= (GnmFunc
*)fn_def
;
1451 gnm_func_load_if_stub (ef
.func
);
1453 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
) {
1455 * If function deals with ExprNodes, create some
1456 * temporary ExprNodes with constants.
1458 GnmExprConstant
*expr
= g_new (GnmExprConstant
, argc
);
1459 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, argc
);
1462 for (i
= 0; i
< argc
; i
++) {
1463 gnm_expr_constant_init (expr
+ i
, values
[i
]);
1464 argv
[i
] = (GnmExprConstPtr
)(expr
+ i
);
1466 retval
= fn_def
->nodes_func (&fs
, argc
, argv
);
1470 retval
= fn_def
->args_func (&fs
, values
);
1475 /* ------------------------------------------------------------------------- */
1478 FunctionIterateCB callback
;
1481 gboolean ignore_subtotal
;
1482 } IterateCallbackClosure
;
1485 * cb_iterate_cellrange:
1487 * Helper routine used by the function_iterate_do_value routine.
1488 * Invoked by the sheet cell range iterator.
1491 cb_iterate_cellrange (GnmCellIter
const *iter
, gpointer user
)
1494 IterateCallbackClosure
*data
= user
;
1499 if (NULL
== (cell
= iter
->cell
)) {
1500 ep
.sheet
= iter
->pp
.sheet
;
1502 ep
.eval
.col
= iter
->pp
.eval
.col
;
1503 ep
.eval
.row
= iter
->pp
.eval
.row
;
1504 return (*data
->callback
)(&ep
, NULL
, data
->closure
);
1507 if (data
->ignore_subtotal
&& gnm_cell_has_expr (cell
) &&
1508 gnm_expr_top_contains_subtotal (cell
->base
.texpr
))
1511 gnm_cell_eval (cell
);
1512 eval_pos_init_cell (&ep
, cell
);
1514 /* If we encounter an error for the strict case, short-circuit here. */
1515 if (data
->strict
&& (NULL
!= (res
= gnm_cell_is_error (cell
))))
1516 return value_new_error_str (&ep
, res
->v_err
.mesg
);
1518 /* All other cases -- including error -- just call the handler. */
1519 return (*data
->callback
)(&ep
, cell
->value
, data
->closure
);
1523 * function_iterate_do_value:
1525 * Helper routine for function_iterate_argument_values.
1528 function_iterate_do_value (GnmEvalPos
const *ep
,
1529 FunctionIterateCB callback
,
1531 GnmValue
const *value
,
1533 CellIterFlags iter_flags
)
1535 GnmValue
*res
= NULL
;
1537 switch (value
->v_any
.type
){
1540 res
= value_dup (value
);
1549 res
= (*callback
)(ep
, value
, closure
);
1555 /* Note the order here. */
1556 for (y
= 0; y
< value
->v_array
.y
; y
++) {
1557 for (x
= 0; x
< value
->v_array
.x
; x
++) {
1558 res
= function_iterate_do_value (
1559 ep
, callback
, closure
,
1560 value
->v_array
.vals
[x
][y
],
1561 strict
, CELL_ITER_IGNORE_BLANK
);
1568 case VALUE_CELLRANGE
: {
1569 IterateCallbackClosure data
;
1571 data
.callback
= callback
;
1572 data
.closure
= closure
;
1573 data
.strict
= strict
;
1574 data
.ignore_subtotal
= (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
) != 0;
1576 res
= workbook_foreach_cell_in_range (ep
, value
, iter_flags
,
1577 cb_iterate_cellrange
,
1585 * function_iterate_argument_values:
1586 * @ep: The position in a workbook at which to evaluate
1587 * @callback: (scope call): The routine to be invoked for every value computed
1588 * @callback_closure: Closure for the callback.
1591 * @strict: If TRUE, the function is considered "strict". This means
1592 * that if an error value occurs as an argument, the iteration
1593 * will stop and that error will be returned. If FALSE, an
1594 * error will be passed on to the callback (as a GnmValue *
1595 * of type VALUE_ERROR).
1599 * NULL : if no errors were reported.
1600 * GnmValue * : if an error was found during strict evaluation
1601 * VALUE_TERMINATE : if the callback requested termination of the iteration.
1603 * This routine provides a simple way for internal functions with variable
1604 * number of arguments to be written: this would iterate over a list of
1605 * expressions (expr_node_list) and will invoke the callback for every
1606 * GnmValue found on the list (this means that ranges get properly expaned).
1609 function_iterate_argument_values (GnmEvalPos
const *ep
,
1610 FunctionIterateCB callback
,
1611 void *callback_closure
,
1613 GnmExprConstPtr
const *argv
,
1615 CellIterFlags iter_flags
)
1617 GnmValue
*result
= NULL
;
1620 for (a
= 0; result
== NULL
&& a
< argc
; a
++) {
1621 GnmExpr
const *expr
= argv
[a
];
1624 if (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
&&
1625 gnm_expr_contains_subtotal (expr
))
1628 /* need to drill down into names to handle things like
1629 * sum(name) with name := (A:A,B:B) */
1630 while (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_NAME
) {
1631 GnmExprTop
const *texpr
= expr
->name
.name
->texpr
;
1632 expr
= texpr
? texpr
->expr
: NULL
;
1635 return value_new_error_REF (ep
);
1642 /* Handle sets as a special case */
1643 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_SET
) {
1644 result
= function_iterate_argument_values
1645 (ep
, callback
, callback_closure
,
1646 expr
->set
.argc
, expr
->set
.argv
,
1647 strict
, iter_flags
);
1651 /* We need a cleaner model of what to do here.
1654 * will obviously return Range
1656 * SUM(INDIRECT(Range))
1657 * SUM(INDIRECT(Range):....)
1658 * will do implicit intersection on Range (in non-array mode),
1659 * but allow non-scalar results from indirect (no intersection)
1662 * will do implicit intersection in non-array mode */
1663 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_CONSTANT
)
1664 val
= value_dup (expr
->constant
.value
);
1665 else if (eval_pos_is_array_context (ep
) ||
1666 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
||
1667 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_RANGE_CTOR
||
1668 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_INTERSECT
)
1669 val
= gnm_expr_eval (expr
, ep
,
1670 GNM_EXPR_EVAL_PERMIT_EMPTY
| GNM_EXPR_EVAL_PERMIT_NON_SCALAR
);
1672 val
= gnm_expr_eval (expr
, ep
, GNM_EXPR_EVAL_PERMIT_EMPTY
);
1677 if (strict
&& VALUE_IS_ERROR (val
)) {
1678 /* Be careful not to make VALUE_TERMINATE into a real value */
1682 result
= function_iterate_do_value (ep
, callback
, callback_closure
,
1683 val
, strict
, iter_flags
);
1684 value_release (val
);
1691 * gnm_eval_info_get_func:
1692 * @ei: #GnmFuncEvalInfo
1694 * Returns: (transfer none): the called function.
1697 gnm_eval_info_get_func (GnmFuncEvalInfo
const *ei
)
1699 return ei
->func_call
->func
;
1703 gnm_eval_info_get_arg_count (GnmFuncEvalInfo
const *ei
)
1705 return ei
->func_call
->argc
;
1709 gnm_func_link_dep (GnmFunc
*func
, GnmFuncEvalInfo
*ei
, gboolean qlink
)
1711 int res
= DEPENDENT_NO_FLAG
;
1712 g_signal_emit (func
, signals
[SIG_LINK_DEP
], 0, ei
, qlink
, &res
);
1713 return (GnmDependentFlags
)res
;
1716 /* ------------------------------------------------------------------------- */
1718 static GObjectClass
*parent_class
;
1721 GObjectClass parent
;
1723 void (*load_stub
) (GnmFunc
*func
);
1724 int (*link_dep
) (GnmFunc
*func
, GnmFuncEvalInfo
*ei
, gboolean qlink
);
1728 gnm_func_finalize (GObject
*obj
)
1730 GnmFunc
*func
= GNM_FUNC (obj
);
1732 g_free (func
->arg_types
);
1734 g_free ((char *)func
->name
);
1736 go_string_unref (func
->tdomain
);
1738 parent_class
->finalize (obj
);
1742 gnm_func_real_dispose (GObject
*obj
)
1744 GnmFunc
*func
= GNM_FUNC (obj
);
1746 if (func
->usage_count
!= 0) {
1747 g_printerr ("Function %s still has a usage count of %d\n",
1748 func
->name
, func
->usage_count
);
1751 gnm_func_set_stub (func
);
1753 if (func
->fn_group
) {
1754 gnm_func_group_remove_func (func
->fn_group
, func
);
1755 func
->fn_group
= NULL
;
1758 gnm_func_set_localized_name (func
, NULL
);
1760 if (!(func
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
)) {
1761 g_hash_table_remove (functions_by_name
, func
->name
);
1764 parent_class
->dispose (obj
);
1768 gnm_func_dispose (GnmFunc
*func
)
1770 g_object_run_dispose (G_OBJECT (func
));
1774 gnm_func_get_property (GObject
*object
, guint property_id
,
1775 GValue
*value
, GParamSpec
*pspec
)
1777 GnmFunc
*func
= (GnmFunc
*)object
;
1779 switch (property_id
) {
1781 g_value_set_string (value
, func
->name
);
1783 case PROP_TRANSLATION_DOMAIN
:
1784 g_value_set_string (value
, func
->tdomain
->str
);
1787 g_value_set_boolean (value
, func
->usage_count
> 0);
1790 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1796 gnm_func_set_property (GObject
*object
, guint property_id
,
1797 GValue
const *value
, GParamSpec
*pspec
)
1799 GnmFunc
*func
= (GnmFunc
*)object
;
1801 switch (property_id
) {
1803 func
->name
= g_value_dup_string (value
);
1805 case PROP_TRANSLATION_DOMAIN
:
1806 gnm_func_set_translation_domain (func
,
1807 g_value_get_string (value
));
1810 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1816 gnm_func_init (GnmFunc
*func
)
1818 func
->tdomain
= go_string_new (GETTEXT_PACKAGE
);
1819 func
->flags
= GNM_FUNC_SIMPLE
;
1820 func
->impl_status
= GNM_FUNC_IMPL_STATUS_UNIMPLEMENTED
;
1821 func
->test_status
= GNM_FUNC_TEST_STATUS_UNKNOWN
;
1825 gnm_func_class_init (GObjectClass
*gobject_class
)
1827 parent_class
= g_type_class_peek_parent (gobject_class
);
1829 gobject_class
->finalize
= gnm_func_finalize
;
1830 gobject_class
->dispose
= gnm_func_real_dispose
;
1831 gobject_class
->get_property
= gnm_func_get_property
;
1832 gobject_class
->set_property
= gnm_func_set_property
;
1834 g_object_class_install_property (gobject_class
, PROP_NAME
,
1835 g_param_spec_string ("name",
1837 P_("The name of the function."),
1841 G_PARAM_CONSTRUCT_ONLY
));
1843 g_object_class_install_property (gobject_class
, PROP_TRANSLATION_DOMAIN
,
1844 g_param_spec_string ("translation-domain",
1845 P_("Translation Domain"),
1846 P_("The translation domain for help texts"),
1849 G_PARAM_READWRITE
));
1851 g_object_class_install_property (gobject_class
, PROP_IN_USE
,
1852 g_param_spec_boolean ("in-use",
1854 P_("Is function being used?"),
1859 signals
[SIG_LOAD_STUB
] = g_signal_new
1863 G_STRUCT_OFFSET (GnmFuncClass
, load_stub
),
1865 g_cclosure_marshal_VOID__VOID
,
1869 signals
[SIG_LINK_DEP
] = g_signal_new
1873 G_STRUCT_OFFSET (GnmFuncClass
, link_dep
),
1875 gnm__INT__POINTER_BOOLEAN
,
1876 // GnmDependentFlags ... GnmFuncEvalInfo
1877 G_TYPE_INT
, 2, G_TYPE_POINTER
, G_TYPE_BOOLEAN
);
1880 GSF_CLASS (GnmFunc
, gnm_func
,
1881 gnm_func_class_init
, gnm_func_init
, G_TYPE_OBJECT
)