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 <expr-deriv.h>
34 #include <gnm-marshalers.h>
36 #include <goffice/goffice.h>
44 PROP_TRANSLATION_DOMAIN
,
54 static guint signals
[LAST_SIGNAL
] = { 0 };
57 static GList
*categories
;
58 static GnmFuncGroup
*unknown_cat
;
60 static GHashTable
*functions_by_name
;
61 static GHashTable
*functions_by_localized_name
;
63 static GnmFunc
*fn_if
;
66 * gnm_func_init_: (skip)
72 g_hash_table_new (go_ascii_strcase_hash
, go_ascii_strcase_equal
);
75 functions_by_localized_name
=
76 g_hash_table_new (go_ascii_strcase_hash
, go_ascii_strcase_equal
);
78 gnm_func_builtin_init ();
80 fn_if
= gnm_func_lookup ("if", NULL
);
84 * gnm_func_shutdown_: (skip)
87 gnm_func_shutdown_ (void)
91 while (unknown_cat
!= NULL
&& unknown_cat
->functions
!= NULL
) {
92 GnmFunc
*func
= unknown_cat
->functions
->data
;
93 if (func
->usage_count
> 0) {
94 g_warning ("Function %s still has %d users.\n",
95 gnm_func_get_name (func
, FALSE
),
97 func
->usage_count
= 0;
99 g_object_unref (func
);
101 gnm_func_builtin_shutdown ();
103 g_hash_table_destroy (functions_by_name
);
104 functions_by_name
= NULL
;
106 g_hash_table_destroy (functions_by_localized_name
);
107 functions_by_localized_name
= NULL
;
111 * gnm_func_enumerate:
113 * Return value: (element-type GnmFunc) (transfer container):
116 gnm_func_enumerate (void)
118 GPtrArray
*res
= g_ptr_array_new ();
119 GHashTableIter hiter
;
122 g_hash_table_iter_init (&hiter
, functions_by_name
);
123 while (g_hash_table_iter_next (&hiter
, NULL
, &value
))
124 g_ptr_array_add (res
, value
);
130 error_function_no_full_info (GnmFuncEvalInfo
*ei
,
132 GnmExprConstPtr
const *argv
)
134 return value_new_error (ei
->pos
, _("Function implementation not available."));
138 gnm_func_load_stub (GnmFunc
*func
)
140 g_return_if_fail (func
->fn_type
== GNM_FUNC_TYPE_STUB
);
142 g_signal_emit (G_OBJECT (func
), signals
[SIG_LOAD_STUB
], 0);
144 if (func
->fn_type
== GNM_FUNC_TYPE_STUB
) {
145 g_printerr ("Failed to load %s\n", func
->name
);
146 gnm_func_set_varargs (func
, error_function_no_full_info
, NULL
);
147 gnm_func_set_help (func
, NULL
, 0);
152 gnm_func_load_if_stub (GnmFunc
*func
)
154 if (func
->fn_type
== GNM_FUNC_TYPE_STUB
)
155 gnm_func_load_stub (func
);
159 split_at_colon (char const *s
, char **rest
)
161 char *dup
= g_strdup (s
);
162 char *colon
= strchr (dup
, ':');
165 if (rest
) *rest
= colon
+ 1;
167 if (rest
) *rest
= NULL
;
172 /* ------------------------------------------------------------------------- */
175 gnm_func_group_free (GnmFuncGroup
*fn_group
)
177 g_return_if_fail (fn_group
!= NULL
);
178 g_return_if_fail (fn_group
->functions
== NULL
);
180 if (fn_group
->ref_count
-- > 1)
183 go_string_unref (fn_group
->internal_name
);
184 go_string_unref (fn_group
->display_name
);
188 static GnmFuncGroup
*
189 gnm_func_group_ref (GnmFuncGroup
*fn_group
)
191 fn_group
->ref_count
++;
196 gnm_func_group_get_type (void)
201 t
= g_boxed_type_register_static ("GnmFuncGroup",
202 (GBoxedCopyFunc
)gnm_func_group_ref
,
203 (GBoxedFreeFunc
)gnm_func_group_free
);
209 function_category_compare (gconstpointer a
, gconstpointer b
)
211 GnmFuncGroup
const *cat_a
= a
;
212 GnmFuncGroup
const *cat_b
= b
;
214 return go_string_cmp (cat_a
->display_name
, cat_b
->display_name
);
218 gnm_func_group_fetch (char const *name
, char const *translation
)
220 GnmFuncGroup
*cat
= NULL
;
223 g_return_val_if_fail (name
!= NULL
, NULL
);
225 for (l
= categories
; l
!= NULL
; l
= l
->next
) {
227 if (strcmp (cat
->internal_name
->str
, name
) == 0) {
233 cat
= g_new (GnmFuncGroup
, 1);
234 cat
->internal_name
= go_string_new (name
);
236 if (translation
!= NULL
) {
237 cat
->display_name
= go_string_new (translation
);
238 cat
->has_translation
= TRUE
;
240 cat
->display_name
= go_string_new (name
);
241 cat
->has_translation
= FALSE
;
243 cat
->functions
= NULL
;
244 categories
= g_list_insert_sorted (
245 categories
, cat
, &function_category_compare
);
246 } else if (translation
!= NULL
&& translation
!= name
&&
247 !cat
->has_translation
) {
248 go_string_unref (cat
->display_name
);
249 cat
->display_name
= go_string_new (translation
);
250 cat
->has_translation
= TRUE
;
251 categories
= g_list_remove_link (categories
, l
);
253 categories
= g_list_insert_sorted (
254 categories
, cat
, &function_category_compare
);
261 gnm_func_group_get_nth (int n
)
263 return g_list_nth_data (categories
, n
);
267 gnm_func_group_add_func (GnmFuncGroup
*fn_group
, GnmFunc
*func
)
269 g_return_if_fail (fn_group
!= NULL
);
270 g_return_if_fail (func
!= NULL
);
272 fn_group
->functions
= g_slist_prepend (fn_group
->functions
, func
);
276 gnm_func_group_remove_func (GnmFuncGroup
*fn_group
, GnmFunc
*func
)
278 g_return_if_fail (fn_group
!= NULL
);
279 g_return_if_fail (func
!= NULL
);
281 fn_group
->functions
= g_slist_remove (fn_group
->functions
, func
);
282 if (fn_group
->functions
== NULL
) {
283 categories
= g_list_remove (categories
, fn_group
);
284 if (unknown_cat
== fn_group
)
286 gnm_func_group_free (fn_group
);
290 /******************************************************************************/
293 gnm_func_create_arg_names (GnmFunc
*func
)
298 g_return_if_fail (func
!= NULL
);
300 ptr
= g_ptr_array_new ();
301 for (i
= 0; i
< func
->help_count
; i
++) {
303 if (func
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
306 s
= gnm_func_gettext (func
, func
->help
[i
].text
);
307 g_ptr_array_add (ptr
, split_at_colon (s
, NULL
));
310 func
->arg_names
= ptr
;
314 gnm_func_is_varargs (GnmFunc
*func
)
316 gnm_func_load_if_stub (func
);
317 return func
->fn_type
== GNM_FUNC_TYPE_NODES
;
321 gnm_func_is_fixargs (GnmFunc
*func
)
323 gnm_func_load_if_stub (func
);
324 return func
->fn_type
== GNM_FUNC_TYPE_ARGS
;
328 gnm_func_set_stub (GnmFunc
*func
)
330 func
->fn_type
= GNM_FUNC_TYPE_STUB
;
332 g_free (func
->arg_spec
);
333 func
->arg_spec
= NULL
;
335 g_free (func
->arg_types
);
336 func
->arg_types
= NULL
;
338 func
->min_args
= func
->max_args
= 0;
340 func
->nodes_func
= NULL
;
341 func
->args_func
= NULL
;
343 gnm_func_set_help (func
, NULL
, 0);
347 * gnm_func_set_varargs: (skip)
349 * @fn: evaluation function
350 * @spec: (nullable): argument type specification
353 gnm_func_set_varargs (GnmFunc
*func
, GnmFuncNodes fn
, const char *spec
)
355 g_return_if_fail (GNM_IS_FUNC (func
));
356 g_return_if_fail (fn
!= NULL
);
358 gnm_func_set_stub (func
); // Clear out stuff
360 func
->fn_type
= GNM_FUNC_TYPE_NODES
;
361 func
->nodes_func
= fn
;
362 func
->arg_spec
= g_strdup (spec
);
364 func
->min_args
= G_MAXINT
;
367 const char *p
= strchr (spec
, '|');
368 const char *q
= strchr (spec
, '.'); // "..."
369 if (p
) func
->min_args
= p
- spec
;
370 if (!q
) func
->min_args
= strlen (spec
) - (p
!= NULL
);
375 * gnm_func_set_fixargs: (skip)
377 * @fn: evaluation function
378 * @spec: argument type specification
381 gnm_func_set_fixargs (GnmFunc
*func
, GnmFuncArgs fn
, const char *spec
)
385 g_return_if_fail (GNM_IS_FUNC (func
));
386 g_return_if_fail (fn
!= NULL
);
387 g_return_if_fail (spec
!= NULL
);
389 gnm_func_set_stub (func
); // Clear out stuff
391 func
->fn_type
= GNM_FUNC_TYPE_ARGS
;
392 func
->args_func
= fn
;
393 func
->arg_spec
= g_strdup (spec
);
395 func
->arg_types
= g_strdup (func
->arg_spec
);
396 p
= strchr (func
->arg_types
, '|');
398 func
->min_args
= p
- func
->arg_types
;
399 memmove (p
, p
+ 1, strlen (p
));
401 func
->min_args
= strlen (func
->arg_types
);
402 func
->max_args
= strlen (func
->arg_types
);
408 * @n: (out) (optional): number of help items, not counting the end item
410 * Returns: (transfer none) (array length=n) (nullable): @func's help items.
413 gnm_func_get_help (GnmFunc
*func
, int *n
)
417 g_return_val_if_fail (GNM_IS_FUNC (func
), NULL
);
418 g_return_val_if_fail (func
->help
, NULL
);
420 if (n
) *n
= func
->help_count
;
426 gnm_func_set_help (GnmFunc
*func
, GnmFuncHelp
const *help
, int n
)
428 g_return_if_fail (GNM_IS_FUNC (func
));
429 g_return_if_fail (n
<= 0 || help
!= NULL
);
432 for (n
= 0; help
&& help
[n
].type
!= GNM_FUNC_HELP_END
; )
438 for (i
= 0; i
<= func
->help_count
; i
++)
439 g_free ((char *)(func
->help
[i
].text
));
444 if (func
->arg_names
) {
445 g_ptr_array_foreach (func
->arg_names
, (GFunc
)g_free
, NULL
);
446 g_ptr_array_free (func
->arg_names
, TRUE
);
447 func
->arg_names
= NULL
;
453 func
->help
= g_new (GnmFuncHelp
, n
+ 1);
454 for (i
= 0; i
< n
; i
++) {
455 func
->help
[i
].type
= help
[i
].type
;
456 func
->help
[i
].text
= g_strdup (help
[i
].text
);
458 func
->help
[n
].type
= GNM_FUNC_HELP_END
;
459 func
->help
[n
].text
= NULL
;
461 func
->help_count
= n
;
462 gnm_func_create_arg_names (func
);
464 func
->help_count
= 0;
470 gnm_func_set_localized_name (GnmFunc
*fd
, const char *lname
)
472 gboolean in_hashes
= !(fd
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
);
474 if (g_strcmp0 (fd
->localized_name
, lname
) == 0)
477 if (in_hashes
&& fd
->localized_name
)
478 g_hash_table_remove (functions_by_localized_name
, fd
->localized_name
);
479 g_free (fd
->localized_name
);
481 fd
->localized_name
= g_strdup (lname
);
482 if (in_hashes
&& lname
)
483 g_hash_table_insert (functions_by_localized_name
,
484 fd
->localized_name
, fd
);
488 * gnm_func_inc_usage:
491 * This function increments the usage count of @func. A non-zero usage count
492 * prevents the unloading of the function.
494 * Returns: (transfer full): a new reference to @func.
497 gnm_func_inc_usage (GnmFunc
*func
)
499 g_return_val_if_fail (func
!= NULL
, NULL
);
502 if (func
->usage_count
== 1)
503 g_object_notify (G_OBJECT (func
), "in-use");
508 * gnm_func_dec_usage:
509 * @func: (transfer full): #GnmFunc
511 * This function decrements the usage count of @func. When the usage count
512 * reaches zero, the function may be unloaded, for example by unloading the
513 * plugin that defines it.
516 gnm_func_dec_usage (GnmFunc
*func
)
518 g_return_if_fail (func
!= NULL
);
519 g_return_if_fail (func
->usage_count
> 0);
522 if (func
->usage_count
== 0)
523 g_object_notify (G_OBJECT (func
), "in-use");
527 gnm_func_get_in_use (GnmFunc
*func
)
529 g_return_val_if_fail (func
!= NULL
, FALSE
);
531 return func
->usage_count
> 0;
537 * @name: name of function
538 * @scope: (nullable): scope of function, %NULL for global
540 * Returns: (nullable) (transfer none): the function of that name.
543 gnm_func_lookup (char const *name
, Workbook
*scope
)
545 GnmFunc
*fd
= g_hash_table_lookup (functions_by_name
, name
);
548 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
550 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
554 * gnm_func_lookup_localized:
555 * @name: localized name of function
556 * @scope: (nullable): scope of function, %NULL for global
558 * Returns: (nullable) (transfer none): the function of that name.
561 gnm_func_lookup_localized (char const *name
, Workbook
*scope
)
564 GHashTableIter hiter
;
567 /* Must localize all function names. */
568 g_hash_table_iter_init (&hiter
, functions_by_name
);
569 while (g_hash_table_iter_next (&hiter
, NULL
, &value
)) {
571 (void)gnm_func_get_name (fd
, TRUE
);
574 fd
= g_hash_table_lookup (functions_by_localized_name
, name
);
577 if (scope
== NULL
|| scope
->sheet_local_functions
== NULL
)
579 return g_hash_table_lookup (scope
->sheet_local_functions
, (gpointer
)name
);
583 * gnm_func_lookup_prefix:
584 * @prefix: prefix to search for
586 * @trans: whether to search translated function names
588 * Returns: (element-type GnmFunc*) (transfer full): A list of functions
589 * whose names start with @prefix.
592 gnm_func_lookup_prefix (char const *prefix
, Workbook
*scope
, gboolean trans
)
595 GHashTableIter hiter
;
599 * Always iterate over functions_by_name as the localized name
600 * might not be set yet.
602 g_hash_table_iter_init (&hiter
, functions_by_name
);
603 while (g_hash_table_iter_next (&hiter
, NULL
, &value
)) {
605 if (!(fd
->flags
& (GNM_FUNC_IS_PLACEHOLDER
| GNM_FUNC_INTERNAL
))) {
606 const char *name
= gnm_func_get_name (fd
, trans
);
607 if (g_str_has_prefix (name
, prefix
)) {
608 gnm_func_inc_usage (fd
);
609 res
= g_slist_prepend (res
, fd
);
618 * gnm_func_get_translation_domain:
621 * Returns: (transfer none): the translation domain for @func's help text.
624 gnm_func_get_translation_domain (GnmFunc
*func
)
626 g_return_val_if_fail (GNM_IS_FUNC (func
), NULL
);
627 return func
->tdomain
->str
;
631 * gnm_func_set_translation_domain:
633 * @tdomain: (nullable): Translation domain, %NULL for Gnumeric's.
636 gnm_func_set_translation_domain (GnmFunc
*func
, const char *tdomain
)
638 g_return_if_fail (GNM_IS_FUNC (func
));
641 tdomain
= GETTEXT_PACKAGE
;
643 if (g_strcmp0 (func
->tdomain
->str
, tdomain
) == 0)
646 go_string_unref (func
->tdomain
);
647 func
->tdomain
= go_string_new (tdomain
);
649 g_object_notify (G_OBJECT (func
), "translation-domain");
655 * @str: string to translate
657 * Returns: (transfer none): @str translated in @func's translation
661 gnm_func_gettext (GnmFunc
*func
, const char *str
)
663 g_return_val_if_fail (GNM_IS_FUNC (func
), NULL
);
664 g_return_val_if_fail (str
!= NULL
, NULL
);
666 return dgettext (func
->tdomain
->str
, str
);
671 gnm_func_get_flags (GnmFunc
*func
)
673 g_return_val_if_fail (GNM_IS_FUNC (func
), GNM_FUNC_SIMPLE
);
678 gnm_func_set_flags (GnmFunc
*func
, GnmFuncFlags f
)
680 g_return_if_fail (GNM_IS_FUNC (func
));
685 gnm_func_get_impl_status (GnmFunc
*func
)
687 g_return_val_if_fail (GNM_IS_FUNC (func
), GNM_FUNC_IMPL_STATUS_UNIMPLEMENTED
);
688 return func
->impl_status
;
692 gnm_func_set_impl_status (GnmFunc
*func
, GnmFuncImplStatus st
)
694 g_return_if_fail (GNM_IS_FUNC (func
));
695 func
->impl_status
= st
;
700 gnm_func_get_test_status (GnmFunc
*func
)
702 g_return_val_if_fail (GNM_IS_FUNC (func
), GNM_FUNC_TEST_STATUS_UNKNOWN
);
703 return func
->test_status
;
707 gnm_func_set_test_status (GnmFunc
*func
, GnmFuncTestStatus st
)
709 g_return_if_fail (GNM_IS_FUNC (func
));
710 func
->test_status
= st
;
715 * gnm_func_get_function_group:
718 * Returns: (transfer none): the function group to which @func belongs.
721 gnm_func_get_function_group (GnmFunc
*func
)
723 g_return_val_if_fail (GNM_IS_FUNC (func
), NULL
);
724 return func
->fn_group
;
729 gnm_func_set_function_group (GnmFunc
*func
, GnmFuncGroup
*group
)
731 g_return_if_fail (GNM_IS_FUNC (func
));
732 g_return_if_fail (group
!= NULL
);
734 if (func
->fn_group
== group
)
738 gnm_func_group_remove_func (func
->fn_group
, func
);
739 func
->fn_group
= group
;
740 gnm_func_group_add_func (group
, func
);
742 if (group
== unknown_cat
)
743 func
->flags
|= GNM_FUNC_IS_PLACEHOLDER
;
745 func
->flags
&= ~GNM_FUNC_IS_PLACEHOLDER
;
749 gnm_func_set_from_desc (GnmFunc
*func
, GnmFuncDescriptor
const *desc
)
751 //static char const valid_tokens[] = "fsbraAES?|";
753 g_return_if_fail (GNM_IS_FUNC (func
));
754 g_return_if_fail (desc
!= NULL
);
756 // Not setting name, localized_name. Also not setting things not present
757 // in desc, such as translation domain.
759 if (desc
->fn_args
!= NULL
) {
760 gnm_func_set_fixargs (func
, desc
->fn_args
, desc
->arg_spec
);
761 } else if (desc
->fn_nodes
!= NULL
) {
762 gnm_func_set_varargs (func
, desc
->fn_nodes
, desc
->arg_spec
);
764 gnm_func_set_stub (func
);
768 gnm_func_set_help (func
, desc
->help
, -1);
769 func
->flags
= desc
->flags
;
770 func
->impl_status
= desc
->impl_status
;
771 func
->test_status
= desc
->test_status
;
779 * @tdomain: (nullable):
781 * Returns: (transfer full): a new #GnmFunc.
784 gnm_func_add (GnmFuncGroup
*fn_group
,
785 GnmFuncDescriptor
const *desc
,
790 g_return_val_if_fail (fn_group
!= NULL
, NULL
);
791 g_return_val_if_fail (desc
!= NULL
, NULL
);
793 func
= g_object_new (GNM_FUNC_TYPE
,
796 gnm_func_set_translation_domain (func
, tdomain
);
798 gnm_func_set_from_desc (func
, desc
);
800 if (func
->fn_type
== GNM_FUNC_TYPE_STUB
) {
801 g_warning ("Invalid function has neither args nor nodes handler");
802 g_object_unref (func
);
806 gnm_func_set_function_group (func
, fn_group
);
808 if (!(func
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
))
809 g_hash_table_insert (functions_by_name
,
810 (gpointer
)(func
->name
), func
);
815 /* Handle unknown functions on import without losing their names */
817 unknownFunctionHandler (GnmFuncEvalInfo
*ei
,
818 G_GNUC_UNUSED
int argc
,
819 G_GNUC_UNUSED GnmExprConstPtr
const *argv
)
821 return value_new_error_NAME (ei
->pos
);
825 invent_name (const char *pref
, GHashTable
*h
, const char *template)
827 static int count
= 0;
828 char *name
= g_utf8_strdown (pref
, -1);
830 while (g_hash_table_lookup (h
, name
)) {
833 name
= g_strdup_printf (template, count
);
840 gnm_func_add_placeholder_full (Workbook
*scope
,
841 char const *gname
, char const *lname
,
844 GnmFuncDescriptor desc
;
846 char const *unknown_cat_name
= N_("Unknown Function");
847 gboolean copy_gname
= TRUE
;
848 gboolean copy_lname
= TRUE
;
850 g_return_val_if_fail (gname
|| lname
, NULL
);
851 g_return_val_if_fail (gname
== NULL
|| gnm_func_lookup (gname
, scope
) == NULL
, NULL
);
852 g_return_val_if_fail (lname
== NULL
|| gnm_func_lookup_localized (lname
, scope
) == NULL
, NULL
);
855 unknown_cat
= gnm_func_group_fetch
856 (unknown_cat_name
, _(unknown_cat_name
));
860 * This is actually a bit of a problem if we don't end up
861 * with a copy of lname (because there already is a function
862 * with that name). We're likely to save a template name,
863 * but I don't see what else to do.
865 gname
= invent_name (lname
, functions_by_name
, "unknown%d");
869 /* xgettext: This represents a made-up translated function name. */
870 lname
= invent_name (gname
, functions_by_localized_name
, _("unknown%d"));
874 if (gnm_debug_flag ("func"))
875 g_printerr ("Adding placeholder for %s (aka %s)\n", gname
, lname
);
877 memset (&desc
, 0, sizeof (GnmFuncDescriptor
));
879 desc
.arg_spec
= NULL
;
882 desc
.fn_nodes
= &unknownFunctionHandler
;
883 desc
.flags
= GNM_FUNC_IS_PLACEHOLDER
;
884 desc
.impl_status
= GNM_FUNC_IMPL_STATUS_EXISTS
;
885 desc
.test_status
= GNM_FUNC_TEST_STATUS_UNKNOWN
;
888 desc
.flags
|= GNM_FUNC_IS_WORKBOOK_LOCAL
;
891 /* WISHLIST : it would be nice to have a log if these. */
892 g_warning ("Unknown %s function : %s", type
, desc
.name
);
896 func
= gnm_func_add (unknown_cat
, &desc
, NULL
);
899 gnm_func_set_localized_name (func
, lname
);
901 g_free ((char *)lname
);
905 g_free ((char *)gname
);
908 if (scope
->sheet_local_functions
== NULL
)
909 scope
->sheet_local_functions
= g_hash_table_new_full (
910 g_str_hash
, g_str_equal
,
911 NULL
, g_object_unref
);
912 g_hash_table_insert (scope
->sheet_local_functions
,
913 (gpointer
)func
->name
, func
);
920 * gnm_func_add_placeholder:
921 * @scope: (nullable): scope to defined placeholder, %NULL for global
922 * @name: (nullable): function name
925 * Returns: (transfer none): a placeholder with the given name.
928 gnm_func_add_placeholder (Workbook
*scope
,
929 char const *name
, char const *type
)
931 return gnm_func_add_placeholder_full (scope
, name
, NULL
, type
);
935 * gnm_func_add_placeholder_localized:
936 * @gname: (nullable): function name
937 * @lname: localized function name
939 * Returns: (transfer none): a placeholder with the given localized name.
942 gnm_func_add_placeholder_localized (char const *gname
, char const *lname
)
944 return gnm_func_add_placeholder_full (NULL
, gname
, lname
, "?");
948 * gnm_func_lookup_or_add_placeholder:
949 * @name: function name
951 * Returns: (transfer none): a #GnmFunc named @name, either an existing
952 * one or a placeholder.
955 gnm_func_lookup_or_add_placeholder (char const *name
)
957 GnmFunc
* f
= gnm_func_lookup (name
, NULL
);
959 f
= gnm_func_add_placeholder (NULL
, name
, "");
965 * @func: #GnmFunc to query
966 * @localized: if %TRUE, use localized name
968 * Returns: (transfer none): @func's name
971 gnm_func_get_name (GnmFunc
const *func
, gboolean localized
)
974 GnmFunc
*fd
= (GnmFunc
*)func
;
976 g_return_val_if_fail (func
!= NULL
, NULL
);
981 if (func
->localized_name
)
982 return func
->localized_name
;
985 * Deduce the translated names from the help texts. This
986 * code doesn't currently check for clashes in translated
990 gnm_func_load_if_stub (fd
);
992 for (i
= 0; func
->localized_name
== NULL
&& i
< func
->help_count
; i
++) {
995 if (func
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
998 s
= func
->help
[i
].text
;
999 sl
= gnm_func_gettext (fd
, s
);
1000 if (s
== sl
) /* String not actually translated. */
1003 U
= split_at_colon (sl
, NULL
);
1005 char *lname
= g_utf8_strdown (U
, -1);
1006 gnm_func_set_localized_name (fd
, lname
);
1012 if (!func
->localized_name
)
1013 gnm_func_set_localized_name (fd
, fd
->name
);
1015 return func
->localized_name
;
1019 * gnm_func_get_description:
1022 * Returns: (transfer none): the description of the function
1025 gnm_func_get_description (GnmFunc
*func
)
1028 g_return_val_if_fail (func
!= NULL
, NULL
);
1030 gnm_func_load_if_stub (func
);
1032 for (i
= 0; i
< func
->help_count
; i
++) {
1035 if (func
->help
[i
].type
!= GNM_FUNC_HELP_NAME
)
1038 desc
= strchr (gnm_func_gettext (func
, func
->help
[i
].text
), ':');
1039 return desc
? (desc
+ 1) : "";
1045 * gnm_func_count_args:
1046 * @func: pointer to function definition
1047 * @min: (out): location for mininum args
1048 * @max: (out): location for mininum args
1050 * This calculates the maximum and minimum number of args that can be passed.
1051 * For a vararg function, the maximum will be set to G_MAXINT.
1054 gnm_func_count_args (GnmFunc
*func
, int *min
, int *max
)
1056 g_return_if_fail (min
!= NULL
);
1057 g_return_if_fail (max
!= NULL
);
1058 g_return_if_fail (func
!= NULL
);
1060 gnm_func_load_if_stub (func
);
1062 *min
= func
->min_args
;
1063 *max
= func
->max_args
;
1067 * gnm_func_get_arg_type:
1068 * @func: the fn defintion
1069 * @arg_idx: zero-based argument offset
1071 * Returns: the type of the argument
1074 gnm_func_get_arg_type (GnmFunc
*func
, int arg_idx
)
1076 g_return_val_if_fail (func
!= NULL
, '?');
1078 gnm_func_load_if_stub (func
);
1080 g_return_val_if_fail (arg_idx
>= 0 && arg_idx
< func
->max_args
, '?');
1082 return func
->arg_types
? func
->arg_types
[arg_idx
] : '?';
1086 * gnm_func_get_arg_type_string:
1087 * @func: the fn defintion
1088 * @arg_idx: zero-based argument offset
1090 * Return value: (transfer none): the type of the argument as a string
1093 gnm_func_get_arg_type_string (GnmFunc
*func
, int arg_idx
)
1095 switch (gnm_func_get_arg_type (func
, arg_idx
)) {
1101 return _("Boolean");
1103 return _("Cell Range");
1107 return _("Scalar, Blank, or Error");
1111 /* Missing values will be NULL. */
1115 g_warning ("Unknown arg type");
1121 * gnm_func_get_arg_name:
1123 * @arg_idx: zero-based argument offset
1125 * Returns: (transfer full) (nullable): the name of the argument
1128 gnm_func_get_arg_name (GnmFunc
const *func
, guint arg_idx
)
1130 g_return_val_if_fail (func
!= NULL
, NULL
);
1132 gnm_func_load_if_stub ((GnmFunc
*)func
);
1134 if (func
->arg_names
&& arg_idx
< func
->arg_names
->len
)
1135 return g_strdup (g_ptr_array_index (func
->arg_names
, arg_idx
));
1140 * gnm_func_get_arg_description:
1141 * @func: the fn defintion
1142 * @arg_idx: zero-based argument offset
1144 * Returns: (transfer none): the description of the argument
1147 gnm_func_get_arg_description (GnmFunc
*func
, guint arg_idx
)
1150 g_return_val_if_fail (func
!= NULL
, NULL
);
1152 gnm_func_load_if_stub (func
);
1154 for (i
= 0; i
< func
->help_count
; i
++) {
1157 if (func
->help
[i
].type
!= GNM_FUNC_HELP_ARG
)
1162 desc
= strchr (gnm_func_gettext (func
, func
->help
[i
].text
), ':');
1167 while (g_unichar_isspace (g_utf8_get_char (desc
)))
1168 desc
= g_utf8_next_char (desc
);
1176 * gnm_func_convert_markup_to_pango:
1177 * @desc: the fn or arg description string
1178 * @target: target widget for the markup.
1180 * Return value: the escaped string with @{} markup converted to
1184 gnm_func_convert_markup_to_pango (char const *desc
, GtkWidget
*target
)
1190 char *link_color_text
, *span_text
;
1191 size_t span_text_len
;
1193 gnm_get_link_color (target
, &link_color
);
1194 pg
.red
= 65535 * link_color
.red
;
1195 pg
.green
= 65535 * link_color
.green
;
1196 pg
.blue
= 65535 * link_color
.blue
;
1197 link_color_text
= pango_color_to_string (&pg
);
1198 span_text
= g_strdup_printf ("<span foreground=\"%s\">",
1200 span_text_len
= strlen (span_text
);
1201 g_free (link_color_text
);
1203 markup
= g_markup_escape_text (desc
, -1);
1204 str
= g_string_new (markup
);
1207 while ((at
= strstr (str
->str
, "@{"))) {
1208 gint len
= at
- str
->str
;
1209 go_string_replace (str
, len
, 2, span_text
, -1);
1211 (str
->str
+ len
+ span_text_len
, "}"))) {
1212 len
= at
- str
->str
;
1213 go_string_replace (str
, len
, 1, "</span>", -1);
1215 g_string_append (str
, "</span>");
1219 return g_string_free (str
, FALSE
);
1223 /* ------------------------------------------------------------------------- */
1226 free_values (GnmValue
**values
, int top
)
1230 for (i
= 0; i
< top
; i
++)
1232 value_release (values
[i
]);
1235 /* ------------------------------------------------------------------------- */
1238 * function_call_with_exprs:
1239 * @ei: EvalInfo containing valid fn_def!
1241 * Do the guts of calling a function.
1243 * Returns the result.
1246 function_call_with_exprs (GnmFuncEvalInfo
*ei
)
1248 GnmFunc
const *fn_def
;
1249 int i
, iter_count
, iter_width
= 0, iter_height
= 0;
1251 GnmValue
**args
, *tmp
= NULL
;
1252 int *iter_item
= NULL
;
1254 GnmExprConstPtr
*argv
;
1255 GnmExprEvalFlags flags
, pass_flags
;
1257 g_return_val_if_fail (ei
!= NULL
, NULL
);
1258 g_return_val_if_fail (ei
->func_call
!= NULL
, NULL
);
1262 argc
= ei
->func_call
->argc
;
1263 argv
= ei
->func_call
->argv
;
1264 fn_def
= ei
->func_call
->func
;
1266 gnm_func_load_if_stub ((GnmFunc
*)fn_def
);
1268 /* Functions that deal with ExprNodes */
1269 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
)
1270 return fn_def
->nodes_func (ei
, argc
, argv
);
1272 /* Functions that take pre-computed Values */
1273 if (argc
> fn_def
->max_args
||
1274 argc
< fn_def
->min_args
)
1275 return value_new_error_NA (ei
->pos
);
1277 args
= g_alloca (sizeof (GnmValue
*) * fn_def
->max_args
);
1278 iter_count
= (eval_pos_is_array_context (ei
->pos
) &&
1279 (flags
& GNM_EXPR_EVAL_PERMIT_NON_SCALAR
))
1282 /* Optimization for IF when implicit iteration is not used. */
1283 if (ei
->func_call
->func
== fn_if
&& iter_count
== -1)
1284 return gnumeric_if2 (ei
, argc
, argv
, flags
);
1286 pass_flags
= (flags
&
1287 (GNM_EXPR_EVAL_ARRAY_CONTEXT
));
1289 for (i
= 0; i
< argc
; i
++) {
1290 char arg_type
= fn_def
->arg_types
[i
];
1291 /* expr is always non-null, missing args are encoded as
1293 GnmExpr
const *expr
= argv
[i
];
1295 if (arg_type
== 'A' || arg_type
== 'r') {
1296 tmp
= args
[i
] = gnm_expr_eval
1299 GNM_EXPR_EVAL_PERMIT_NON_SCALAR
|
1300 GNM_EXPR_EVAL_WANT_REF
);
1301 if (VALUE_IS_ERROR (tmp
)) {
1302 free_values (args
, i
);
1306 if (VALUE_IS_CELLRANGE (tmp
)) {
1307 gnm_cellref_make_abs (&tmp
->v_range
.cell
.a
,
1308 &tmp
->v_range
.cell
.a
,
1310 gnm_cellref_make_abs (&tmp
->v_range
.cell
.b
,
1311 &tmp
->v_range
.cell
.b
,
1313 /* Array args accept scalars */
1314 } else if (arg_type
!= 'A' && !VALUE_IS_ARRAY (tmp
)) {
1315 free_values (args
, i
+ 1);
1316 return value_new_error_VALUE (ei
->pos
);
1321 /* force scalars whenever we are certain */
1322 tmp
= args
[i
] = gnm_expr_eval
1325 GNM_EXPR_EVAL_PERMIT_EMPTY
|
1326 (iter_count
>= 0 || arg_type
== '?'
1327 ? GNM_EXPR_EVAL_PERMIT_NON_SCALAR
1330 if (arg_type
== '?') /* '?' arguments are unrestriced */
1333 /* optional arguments can be blank */
1334 if (i
>= fn_def
->min_args
&& VALUE_IS_EMPTY (tmp
)) {
1335 if (arg_type
== 'E' && !gnm_expr_is_empty (expr
)) {
1336 /* An actual argument produced empty. Make
1337 sure function sees that. */
1338 args
[i
] = value_new_empty ();
1345 tmp
= args
[i
] = value_new_empty ();
1347 /* Handle implicit intersection or iteration depending on flags */
1348 if (VALUE_IS_CELLRANGE (tmp
) || VALUE_IS_ARRAY (tmp
)) {
1349 if (iter_count
> 0) {
1350 if (iter_width
!= value_area_get_width (tmp
, ei
->pos
) ||
1351 iter_height
!= value_area_get_height (tmp
, ei
->pos
)) {
1352 free_values (args
, i
+ 1);
1353 return value_new_error_VALUE (ei
->pos
);
1356 if (iter_count
< 0) {
1357 g_warning ("Damn I thought this was impossible");
1360 iter_item
= g_alloca (sizeof (int) * argc
);
1361 iter_width
= value_area_get_width (tmp
, ei
->pos
);
1362 iter_height
= value_area_get_height (tmp
, ei
->pos
);
1364 iter_item
[iter_count
++] = i
;
1366 /* no need to check type, we would fail comparing a range against a "b, f, or s" */
1370 /* All of these argument types must be scalars */
1373 if (VALUE_IS_STRING (tmp
)) {
1375 gboolean b
= value_get_as_bool (tmp
, &err
);
1377 free_values (args
, i
+ 1);
1378 return value_new_error_VALUE (ei
->pos
);
1380 value_release (args
[i
]);
1381 tmp
= args
[i
] = value_new_bool (b
);
1386 if (VALUE_IS_STRING (tmp
)) {
1387 tmp
= format_match_number (value_peek_string (tmp
), NULL
,
1388 sheet_date_conv (ei
->pos
->sheet
));
1390 free_values (args
, i
+ 1);
1391 return value_new_error_VALUE (ei
->pos
);
1393 value_release (args
[i
]);
1395 } else if (VALUE_IS_ERROR (tmp
)) {
1396 free_values (args
, i
);
1398 } else if (VALUE_IS_EMPTY (tmp
)) {
1399 value_release (args
[i
]);
1400 tmp
= args
[i
] = value_new_int (0);
1403 if (!VALUE_IS_NUMBER (tmp
))
1404 return value_new_error_VALUE (ei
->pos
);
1409 if (VALUE_IS_ERROR (tmp
)) {
1410 free_values (args
, i
);
1415 case 'E': /* nothing necessary */
1418 /* case '?': handled above */
1420 g_warning ("Unknown argument type '%c'", arg_type
);
1425 while (i
< fn_def
->max_args
)
1428 if (iter_item
!= NULL
) {
1430 GnmValue
*res
= value_new_array_empty (iter_width
, iter_height
);
1431 GnmValue
const *elem
, *err
;
1432 GnmValue
**iter_vals
= g_alloca (sizeof (GnmValue
*) * iter_count
);
1433 GnmValue
**iter_args
= g_alloca (sizeof (GnmValue
*) * iter_count
);
1435 /* collect the args we will iterate on */
1436 for (i
= 0 ; i
< iter_count
; i
++)
1437 iter_vals
[i
] = args
[iter_item
[i
]];
1439 for (x
= iter_width
; x
-- > 0 ; )
1440 for (y
= iter_height
; y
-- > 0 ; ) {
1441 /* marshal the args */
1443 for (i
= 0 ; i
< iter_count
; i
++) {
1444 elem
= value_area_get_x_y (iter_vals
[i
], x
, y
, ei
->pos
);
1445 arg_type
= fn_def
->arg_types
[iter_item
[i
]];
1446 if (arg_type
== 'b' || arg_type
== 'f') {
1447 if (VALUE_IS_EMPTY (elem
))
1449 else if (VALUE_IS_STRING (elem
)) {
1450 tmp
= format_match_number (value_peek_string (elem
), NULL
,
1451 sheet_date_conv (ei
->pos
->sheet
));
1453 args
[iter_item
[i
]] = iter_args
[i
] = tmp
;
1457 } else if (VALUE_IS_ERROR (elem
)) {
1460 } else if (!VALUE_IS_NUMBER (elem
))
1462 } else if (arg_type
== 's') {
1463 if (VALUE_IS_EMPTY (elem
)) {
1464 args
[iter_item
[i
]] = iter_args
[i
] = value_new_string ("");
1466 } else if (VALUE_IS_ERROR (elem
)) {
1469 } else if (!VALUE_IS_STRING (elem
))
1471 } else if (elem
== NULL
) {
1472 args
[iter_item
[i
]] = iter_args
[i
] = value_new_empty ();
1475 args
[iter_item
[i
]] = iter_args
[i
] = value_dup (elem
);
1478 res
->v_array
.vals
[x
][y
] = (i
== iter_count
)
1479 ? fn_def
->args_func (ei
, (GnmValue
const * const *)args
)
1480 : ((err
!= NULL
) ? value_dup (err
)
1481 : value_new_error_VALUE (ei
->pos
));
1482 free_values (iter_args
, i
);
1485 /* free the primaries, not the already freed iteration */
1486 for (i
= 0 ; i
< iter_count
; i
++)
1487 args
[iter_item
[i
]] = iter_vals
[i
];
1489 i
= fn_def
->max_args
;
1491 tmp
= fn_def
->args_func (ei
, (GnmValue
const * const *)args
);
1493 free_values (args
, i
);
1498 * Use this to invoke a register function: the only drawback is that
1499 * you have to compute/expand all of the values to use this
1502 function_call_with_values (GnmEvalPos
const *ep
, char const *fn_name
,
1503 int argc
, GnmValue
const * const *values
)
1507 g_return_val_if_fail (ep
!= NULL
, NULL
);
1508 g_return_val_if_fail (fn_name
!= NULL
, NULL
);
1509 g_return_val_if_fail (ep
->sheet
!= NULL
, NULL
);
1511 /* FIXME : support workbook local functions */
1512 fn_def
= gnm_func_lookup (fn_name
, NULL
);
1514 return value_new_error_NAME (ep
);
1515 return function_def_call_with_values (ep
, fn_def
, argc
, values
);
1519 function_def_call_with_values (GnmEvalPos
const *ep
, GnmFunc
const *fn_def
,
1520 int argc
, GnmValue
const * const *values
)
1528 ef
.func
= (GnmFunc
*)fn_def
;
1530 gnm_func_load_if_stub (ef
.func
);
1532 if (fn_def
->fn_type
== GNM_FUNC_TYPE_NODES
) {
1534 * If function deals with ExprNodes, create some
1535 * temporary ExprNodes with constants.
1537 GnmExprConstant
*expr
= g_new (GnmExprConstant
, argc
);
1538 GnmExprConstPtr
*argv
= g_new (GnmExprConstPtr
, argc
);
1541 for (i
= 0; i
< argc
; i
++) {
1542 gnm_expr_constant_init (expr
+ i
, values
[i
]);
1543 argv
[i
] = (GnmExprConstPtr
)(expr
+ i
);
1545 retval
= fn_def
->nodes_func (&fs
, argc
, argv
);
1549 retval
= fn_def
->args_func (&fs
, values
);
1554 /* ------------------------------------------------------------------------- */
1557 FunctionIterateCB callback
;
1560 gboolean ignore_subtotal
;
1561 } IterateCallbackClosure
;
1564 * cb_iterate_cellrange:
1566 * Helper routine used by the function_iterate_do_value routine.
1567 * Invoked by the sheet cell range iterator.
1570 cb_iterate_cellrange (GnmCellIter
const *iter
, gpointer user
)
1573 IterateCallbackClosure
*data
= user
;
1578 if (NULL
== (cell
= iter
->cell
)) {
1579 ep
.sheet
= iter
->pp
.sheet
;
1581 ep
.eval
.col
= iter
->pp
.eval
.col
;
1582 ep
.eval
.row
= iter
->pp
.eval
.row
;
1583 return (*data
->callback
)(&ep
, NULL
, data
->closure
);
1586 if (data
->ignore_subtotal
&& gnm_cell_has_expr (cell
) &&
1587 gnm_expr_top_contains_subtotal (cell
->base
.texpr
))
1590 gnm_cell_eval (cell
);
1591 eval_pos_init_cell (&ep
, cell
);
1593 /* If we encounter an error for the strict case, short-circuit here. */
1594 if (data
->strict
&& (NULL
!= (res
= gnm_cell_is_error (cell
))))
1595 return value_new_error_str (&ep
, res
->v_err
.mesg
);
1597 /* All other cases -- including error -- just call the handler. */
1598 return (*data
->callback
)(&ep
, cell
->value
, data
->closure
);
1602 * function_iterate_do_value:
1604 * Helper routine for function_iterate_argument_values.
1607 function_iterate_do_value (GnmEvalPos
const *ep
,
1608 FunctionIterateCB callback
,
1610 GnmValue
const *value
,
1612 CellIterFlags iter_flags
)
1614 GnmValue
*res
= NULL
;
1616 switch (value
->v_any
.type
){
1619 res
= value_dup (value
);
1628 res
= (*callback
)(ep
, value
, closure
);
1634 /* Note the order here. */
1635 for (y
= 0; y
< value
->v_array
.y
; y
++) {
1636 for (x
= 0; x
< value
->v_array
.x
; x
++) {
1637 res
= function_iterate_do_value (
1638 ep
, callback
, closure
,
1639 value
->v_array
.vals
[x
][y
],
1640 strict
, CELL_ITER_IGNORE_BLANK
);
1647 case VALUE_CELLRANGE
: {
1648 IterateCallbackClosure data
;
1650 data
.callback
= callback
;
1651 data
.closure
= closure
;
1652 data
.strict
= strict
;
1653 data
.ignore_subtotal
= (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
) != 0;
1655 res
= workbook_foreach_cell_in_range (ep
, value
, iter_flags
,
1656 cb_iterate_cellrange
,
1664 * function_iterate_argument_values:
1665 * @ep: The position in a workbook at which to evaluate
1666 * @callback: (scope call): The routine to be invoked for every value computed
1667 * @callback_closure: Closure for the callback.
1670 * @strict: If TRUE, the function is considered "strict". This means
1671 * that if an error value occurs as an argument, the iteration
1672 * will stop and that error will be returned. If FALSE, an
1673 * error will be passed on to the callback (as a GnmValue *
1674 * of type VALUE_ERROR).
1678 * NULL : if no errors were reported.
1679 * GnmValue * : if an error was found during strict evaluation
1680 * VALUE_TERMINATE : if the callback requested termination of the iteration.
1682 * This routine provides a simple way for internal functions with variable
1683 * number of arguments to be written: this would iterate over a list of
1684 * expressions (expr_node_list) and will invoke the callback for every
1685 * GnmValue found on the list (this means that ranges get properly expaned).
1688 function_iterate_argument_values (GnmEvalPos
const *ep
,
1689 FunctionIterateCB callback
,
1690 void *callback_closure
,
1692 GnmExprConstPtr
const *argv
,
1694 CellIterFlags iter_flags
)
1696 GnmValue
*result
= NULL
;
1699 for (a
= 0; result
== NULL
&& a
< argc
; a
++) {
1700 GnmExpr
const *expr
= argv
[a
];
1703 if (iter_flags
& CELL_ITER_IGNORE_SUBTOTAL
&&
1704 gnm_expr_contains_subtotal (expr
))
1707 /* need to drill down into names to handle things like
1708 * sum(name) with name := (A:A,B:B) */
1709 while (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_NAME
) {
1710 GnmExprTop
const *texpr
= expr
->name
.name
->texpr
;
1711 expr
= texpr
? texpr
->expr
: NULL
;
1714 return value_new_error_REF (ep
);
1721 /* Handle sets as a special case */
1722 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_SET
) {
1723 result
= function_iterate_argument_values
1724 (ep
, callback
, callback_closure
,
1725 expr
->set
.argc
, expr
->set
.argv
,
1726 strict
, iter_flags
);
1730 /* We need a cleaner model of what to do here.
1733 * will obviously return Range
1735 * SUM(INDIRECT(Range))
1736 * SUM(INDIRECT(Range):....)
1737 * will do implicit intersection on Range (in non-array mode),
1738 * but allow non-scalar results from indirect (no intersection)
1741 * will do implicit intersection in non-array mode */
1742 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_CONSTANT
)
1743 val
= value_dup (expr
->constant
.value
);
1744 else if (eval_pos_is_array_context (ep
) ||
1745 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_FUNCALL
||
1746 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_RANGE_CTOR
||
1747 GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_INTERSECT
)
1748 val
= gnm_expr_eval (expr
, ep
,
1749 GNM_EXPR_EVAL_PERMIT_EMPTY
| GNM_EXPR_EVAL_PERMIT_NON_SCALAR
);
1751 val
= gnm_expr_eval (expr
, ep
, GNM_EXPR_EVAL_PERMIT_EMPTY
);
1756 if (strict
&& VALUE_IS_ERROR (val
)) {
1757 /* Be careful not to make VALUE_TERMINATE into a real value */
1761 result
= function_iterate_do_value (ep
, callback
, callback_closure
,
1762 val
, strict
, iter_flags
);
1763 value_release (val
);
1770 * gnm_eval_info_get_func:
1771 * @ei: #GnmFuncEvalInfo
1773 * Returns: (transfer none): the called function.
1776 gnm_eval_info_get_func (GnmFuncEvalInfo
const *ei
)
1778 return ei
->func_call
->func
;
1782 gnm_eval_info_get_arg_count (GnmFuncEvalInfo
const *ei
)
1784 return ei
->func_call
->argc
;
1788 gnm_func_link_dep (GnmFunc
*func
, GnmFuncEvalInfo
*ei
, gboolean qlink
)
1790 int res
= DEPENDENT_NO_FLAG
;
1791 g_signal_emit (func
, signals
[SIG_LINK_DEP
], 0, ei
, qlink
, &res
);
1792 return (GnmDependentFlags
)res
;
1796 * gnm_func_derivative:
1798 * @expr: expression that calls @func
1799 * @ep: position of @expr
1800 * @info: #GnmExprDeriv
1802 * Returns: (transfer full) (nullable): the derivative of @expr with respect to
1806 gnm_func_derivative (GnmFunc
*func
, GnmExpr
const *expr
, GnmEvalPos
const *ep
,
1809 GnmExpr
*res
= NULL
;
1811 g_return_val_if_fail (GNM_IS_FUNC (func
), NULL
);
1812 g_signal_emit (func
, signals
[SIG_DERIVATIVE
], 0, expr
, ep
, info
, &res
);
1816 /* ------------------------------------------------------------------------- */
1818 static GObjectClass
*parent_class
;
1821 GObjectClass parent
;
1823 void (*load_stub
) (GnmFunc
*func
);
1824 int (*link_dep
) (GnmFunc
*func
, GnmFuncEvalInfo
*ei
, gboolean qlink
);
1825 GnmExpr
* (*derivative
) (GnmFunc
*func
, GnmExpr
const *expr
, GnmEvalPos
*ep
, GnmExprDeriv
*info
);
1829 gnm_func_finalize (GObject
*obj
)
1831 GnmFunc
*func
= GNM_FUNC (obj
);
1833 g_free (func
->arg_types
);
1835 g_free ((char *)func
->name
);
1837 go_string_unref (func
->tdomain
);
1839 parent_class
->finalize (obj
);
1843 gnm_func_real_dispose (GObject
*obj
)
1845 GnmFunc
*func
= GNM_FUNC (obj
);
1847 if (func
->usage_count
!= 0) {
1848 g_printerr ("Function %s still has a usage count of %d\n",
1849 func
->name
, func
->usage_count
);
1852 gnm_func_set_stub (func
);
1854 if (func
->fn_group
) {
1855 gnm_func_group_remove_func (func
->fn_group
, func
);
1856 func
->fn_group
= NULL
;
1859 gnm_func_set_localized_name (func
, NULL
);
1861 if (!(func
->flags
& GNM_FUNC_IS_WORKBOOK_LOCAL
)) {
1862 g_hash_table_remove (functions_by_name
, func
->name
);
1865 parent_class
->dispose (obj
);
1869 gnm_func_dispose (GnmFunc
*func
)
1871 g_object_run_dispose (G_OBJECT (func
));
1875 gnm_func_get_property (GObject
*object
, guint property_id
,
1876 GValue
*value
, GParamSpec
*pspec
)
1878 GnmFunc
*func
= (GnmFunc
*)object
;
1880 switch (property_id
) {
1882 g_value_set_string (value
, func
->name
);
1884 case PROP_TRANSLATION_DOMAIN
:
1885 g_value_set_string (value
, func
->tdomain
->str
);
1888 g_value_set_boolean (value
, func
->usage_count
> 0);
1891 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1897 gnm_func_set_property (GObject
*object
, guint property_id
,
1898 GValue
const *value
, GParamSpec
*pspec
)
1900 GnmFunc
*func
= (GnmFunc
*)object
;
1902 switch (property_id
) {
1904 func
->name
= g_value_dup_string (value
);
1906 case PROP_TRANSLATION_DOMAIN
:
1907 gnm_func_set_translation_domain (func
,
1908 g_value_get_string (value
));
1911 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1917 gnm_func_init (GnmFunc
*func
)
1919 func
->tdomain
= go_string_new (GETTEXT_PACKAGE
);
1920 func
->flags
= GNM_FUNC_SIMPLE
;
1921 func
->impl_status
= GNM_FUNC_IMPL_STATUS_UNIMPLEMENTED
;
1922 func
->test_status
= GNM_FUNC_TEST_STATUS_UNKNOWN
;
1926 gnm_func_class_init (GObjectClass
*gobject_class
)
1928 parent_class
= g_type_class_peek_parent (gobject_class
);
1930 gobject_class
->finalize
= gnm_func_finalize
;
1931 gobject_class
->dispose
= gnm_func_real_dispose
;
1932 gobject_class
->get_property
= gnm_func_get_property
;
1933 gobject_class
->set_property
= gnm_func_set_property
;
1935 g_object_class_install_property (gobject_class
, PROP_NAME
,
1936 g_param_spec_string ("name",
1938 P_("The name of the function."),
1942 G_PARAM_CONSTRUCT_ONLY
));
1944 g_object_class_install_property (gobject_class
, PROP_TRANSLATION_DOMAIN
,
1945 g_param_spec_string ("translation-domain",
1946 P_("Translation Domain"),
1947 P_("The translation domain for help texts"),
1950 G_PARAM_READWRITE
));
1952 g_object_class_install_property (gobject_class
, PROP_IN_USE
,
1953 g_param_spec_boolean ("in-use",
1955 P_("Is function being used?"),
1961 * GnmFunc::load-stub:
1962 * @func: the #GnmFunc that needs to be loaded
1964 * Signals that @func, which is a stub, needs to be loaded now. Anyone
1965 * creating a stub function should arrange for this signal to be caught
1966 * and the function to be properly instantiated.
1968 signals
[SIG_LOAD_STUB
] = g_signal_new
1972 G_STRUCT_OFFSET (GnmFuncClass
, load_stub
),
1974 g_cclosure_marshal_VOID__VOID
,
1978 * GnmFunc::link-dep:
1979 * @func: the #GnmFunc that is being linked or unlinked
1980 * @ei: #GnmFuncEvalInfo for the call initiating the link or unlink.
1981 * @qlink: %TRUE for link, %FALSE for unlink
1983 * Signals that an expressions that is a call to @func is being linked
1984 * or unlinked. Most functions do not need this.
1986 * Returns: A #GnmDependentFlags allowing arguments not be be linked if
1987 * that is appropriate.
1989 signals
[SIG_LINK_DEP
] = g_signal_new
1993 G_STRUCT_OFFSET (GnmFuncClass
, link_dep
),
1995 gnm__INT__POINTER_BOOLEAN
,
1996 // GnmDependentFlags ... GnmFuncEvalInfo
1997 G_TYPE_INT
, 2, G_TYPE_POINTER
, G_TYPE_BOOLEAN
);
2000 * GnmFunc::derivative:
2002 * @expr: #GnmExpr for the call for which the derivative is sought
2003 * @ep: position f @expr
2004 * @info: #GnmExprDeriv telling which derivative is sought
2006 * Signals that a function call's derivative should be calculatted
2008 * Returns: (transfer full) (nullable): #GnmExpr representing the
2009 * derivative, %NULL for error.
2011 signals
[SIG_DERIVATIVE
] = g_signal_new
2015 G_STRUCT_OFFSET (GnmFuncClass
, derivative
),
2017 gnm__BOXED__BOXED_BOXED_BOXED
,
2018 gnm_expr_get_type(),
2019 3, gnm_expr_get_type(), gnm_eval_pos_get_type(), gnm_expr_deriv_info_get_type());
2022 GSF_CLASS (GnmFunc
, gnm_func
,
2023 gnm_func_class_init
, gnm_func_init
, G_TYPE_OBJECT
)