1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * expr-name.c: Supported named expressions
6 * Jody Goldberg <jody@gnome.org>
9 * Michael Meeks <michael@ximian.com>
12 #include <gnumeric-config.h>
13 #include <glib/gi18n-lib.h>
16 #include "expr-name.h"
18 #include "dependent.h"
20 #include "workbook-priv.h"
22 #include "expr-impl.h"
26 #include "sheet-style.h"
28 #include <goffice/goffice.h>
32 expr_name_validate_r1c1 (const char *name
)
37 if (p
[0] != 'R' && p
[0] != 'r')
40 /* no need to worry about [] since they are not alphanumeric */
41 for (i
= 0; p
[0] && g_ascii_isdigit (p
[0]); p
= g_utf8_next_char (p
))
45 if (p
[0] != 'C' && p
[0] != 'c')
48 for (i
= 0; p
[0] && g_ascii_isdigit (p
[0]); p
= g_utf8_next_char (p
))
52 return (p
[0] != '\0');
56 expr_name_validate_a1 (const char *name
)
61 for (i
= 0; *p
&& g_ascii_isalpha(p
[0]);
62 p
= g_utf8_next_char (p
))
64 if (i
==0 || i
>4) /* We want to allow "total2010" and it */
65 /* is unlikely to have more than 456976 */
68 for (i
= 0; *p
&& g_ascii_isdigit (p
[0]);
69 p
= g_utf8_next_char (p
))
78 * @name: tentative name
80 * returns TRUE if the given name is valid, FALSE otherwise.
83 expr_name_validate (const char *name
)
88 g_return_val_if_fail (name
!= NULL
, FALSE
);
93 v
= value_new_from_string (VALUE_BOOLEAN
, name
, NULL
, TRUE
);
95 v
= value_new_from_string (VALUE_BOOLEAN
, name
, NULL
, FALSE
);
101 /* Hmm... Now what? */
102 if (!g_unichar_isalpha (g_utf8_get_char (name
)) &&
106 for (p
= name
; *p
; p
= g_utf8_next_char (p
)) {
107 if (!g_unichar_isalnum (g_utf8_get_char (p
)) &&
112 /* Make sure it's not A1 etc.*/
113 /* Note that we can't use our regular parsers */
114 /* since we also have to avoid names that may become */
115 /* sensible when the sheet size changes. */
116 if (!expr_name_validate_a1 (name
))
119 /* What about R1C1? */
120 if (!expr_name_validate_r1c1 (name
))
128 cb_nexpr_remove (GnmNamedExpr
*nexpr
)
130 g_return_if_fail (nexpr
->scope
!= NULL
);
133 expr_name_set_expr (nexpr
, NULL
);
134 expr_name_unref (nexpr
);
138 cb_collect_name_deps (gpointer key
, G_GNUC_UNUSED gpointer value
,
141 GSList
**list
= user_data
;
142 *list
= g_slist_prepend (*list
, key
);
146 expr_name_unlink_deps (GnmNamedExpr
*nexpr
)
148 GSList
*ptr
, *deps
= NULL
;
150 if (nexpr
->dependents
== NULL
)
153 g_hash_table_foreach (nexpr
->dependents
, cb_collect_name_deps
, &deps
);
156 for (ptr
= deps
; ptr
!= NULL
; ptr
= ptr
->next
) {
157 GnmDependent
*dep
= ptr
->data
;
158 if (dependent_is_linked (dep
))
159 dependent_unlink (dep
);
165 expr_name_relink_deps (GnmNamedExpr
*nexpr
)
169 if (nexpr
->dependents
== NULL
)
172 g_hash_table_foreach (nexpr
->dependents
, cb_collect_name_deps
, &deps
);
173 dependents_link (deps
);
178 fake_go_string_hash (gconstpointer s_
)
180 const GOString
*s
= s_
;
181 return g_str_hash (s
->str
);
185 fake_go_string_equal (gconstpointer a_
, gconstpointer b_
)
187 const GOString
*a
= a_
;
188 const GOString
*b
= b_
;
189 return g_str_equal (a
->str
, b
->str
);
193 struct _GnmNamedExprCollection
{
194 /* all the defined names */
197 /* placeholders for references to undefined names */
198 GHashTable
*placeholders
;
201 unsigned ref_count
; /* boxed type */
205 * gnm_named_expr_collection_new:
207 * Returns: (transfer full): the newly allocated #GnmNamedExprCollection/
209 GnmNamedExprCollection
*
210 gnm_named_expr_collection_new (void)
212 GnmNamedExprCollection
*res
= g_new (GnmNamedExprCollection
, 1);
214 res
->names
= g_hash_table_new_full
215 (fake_go_string_hash
, fake_go_string_equal
,
216 NULL
, (GDestroyNotify
) cb_nexpr_remove
);
217 res
->placeholders
= g_hash_table_new_full
218 (fake_go_string_hash
, fake_go_string_equal
,
219 NULL
, (GDestroyNotify
) cb_nexpr_remove
);
226 * gnm_named_expr_collection_free:
227 * @names: The collection of names
229 * Frees names defined in the local scope.
230 * NOTE : THIS DOES NOT INVALIDATE NAMES THAT REFER
233 * in scope sheet2 we have a name that refers
234 * to sheet1. That will remain!
237 gnm_named_expr_collection_free (GnmNamedExprCollection
*names
)
239 if (names
!= NULL
&& names
->ref_count
-- < 2) {
240 g_hash_table_destroy (names
->names
);
241 g_hash_table_destroy (names
->placeholders
);
246 static GnmNamedExprCollection
*
247 gnm_named_expr_collection_ref (GnmNamedExprCollection
*names
)
254 gnm_named_expr_collection_dump (GnmNamedExprCollection
*names
, const char *id
)
256 g_printerr ("Named collection %s\n", id
);
258 g_printerr (" Empty\n");
262 if (names
->names
&& g_hash_table_size (names
->names
)) {
263 GHashTableIter hiter
;
266 g_printerr (" Defined names:\n");
267 g_hash_table_iter_init (&hiter
, names
->names
);
268 while (g_hash_table_iter_next (&hiter
, &key
, &value
)) {
269 const GOString
*name
= key
;
270 GnmNamedExpr
const *nexpr
= value
;
271 g_printerr (" [%s] =>\n", name
->str
);
272 if (name
!= nexpr
->name
)
273 g_printerr (" Weird keys: %p vs %p\n",
278 if (names
->placeholders
&& g_hash_table_size (names
->placeholders
)) {
279 GHashTableIter hiter
;
282 g_printerr (" Defined placeholders:\n");
283 g_hash_table_iter_init (&hiter
, names
->placeholders
);
284 while (g_hash_table_iter_next (&hiter
, &key
, &value
)) {
285 const GOString
*name
= key
;
286 GnmNamedExpr
const *nexpr
= value
;
287 g_printerr (" [%s] =>\n", name
->str
);
288 if (name
!= nexpr
->name
)
289 g_printerr (" Weird keys: %p vs %p\n",
296 gnm_named_expr_collection_sanity_check (GnmNamedExprCollection
*names
,
299 gboolean err
= FALSE
;
300 g_printerr ("Checking sanity for container %s\n", id
);
302 GHashTableIter hiter
;
305 g_hash_table_iter_init (&hiter
, names
->names
);
306 while (g_hash_table_iter_next (&hiter
, &key
, &value
)) {
307 const GOString
*name
= key
;
308 GnmNamedExpr
const *nexpr
= value
;
309 if (name
!= nexpr
->name
) {
311 g_printerr ("Container %s has strange defined name\n",
313 g_printerr (" key is %p [%s]\n",
315 g_printerr (" target's name is %p [%s]\n",
316 nexpr
->name
, nexpr
->name
->str
);
324 gnm_named_expr_collection_get_type (void)
329 t
= g_boxed_type_register_static ("GnmNamedExprCollection",
330 (GBoxedCopyFunc
)gnm_named_expr_collection_ref
,
331 (GBoxedFreeFunc
)gnm_named_expr_collection_free
);
337 cb_unlink_all_names (G_GNUC_UNUSED gpointer key
,
339 G_GNUC_UNUSED gpointer user_data
)
341 GnmNamedExpr
*nexpr
= value
;
342 GSList
*deps
= expr_name_unlink_deps (nexpr
);
347 gnm_named_expr_collection_unlink (GnmNamedExprCollection
*names
)
352 g_hash_table_foreach (names
->names
,
358 cb_relink_all_names (G_GNUC_UNUSED gpointer key
,
360 G_GNUC_UNUSED gpointer user_data
)
362 GnmNamedExpr
*nexpr
= value
;
363 expr_name_relink_deps (nexpr
);
367 gnm_named_expr_collection_relink (GnmNamedExprCollection
*names
)
372 g_hash_table_foreach (names
->names
,
378 gnm_named_expr_collection_lookup (GnmNamedExprCollection
const *scope
,
385 fake_name
.str
= name
;
386 nexpr
= g_hash_table_lookup (scope
->names
, &fake_name
);
388 nexpr
= g_hash_table_lookup (scope
->placeholders
,
396 cb_list_names (G_GNUC_UNUSED gpointer key
,
400 GSList
**pres
= user_data
;
401 GO_SLIST_PREPEND (*pres
, value
);
405 * gnm_named_expr_collection_list:
406 * @scope: #GnmNamedExprCollection
408 * Returns: (element-type GnmNamedExpr) (transfer container):
411 gnm_named_expr_collection_list (GnmNamedExprCollection
const *scope
)
415 g_hash_table_foreach (scope
->names
,
423 gnm_named_expr_collection_insert (GnmNamedExprCollection
*scope
,
426 if (gnm_debug_flag ("names")) {
427 char *scope_name
= nexpr
->pos
.sheet
428 ? g_strdup_printf ("sheet %s", nexpr
->pos
.sheet
->name_quoted
)
429 : g_strdup ("workbook");
430 g_printerr ("Inserting name %s into its %s container%s\n",
433 nexpr
->is_placeholder
? " as a placeholder" : "");
437 /* name can be active at this point, eg we are converting a
438 * placeholder, or changing a scope */
439 nexpr
->scope
= scope
;
441 (nexpr
->is_placeholder
? scope
->placeholders
: scope
->names
,
442 (gpointer
)nexpr
->name
, nexpr
);
452 cb_check_name (G_GNUC_UNUSED gpointer key
, GnmNamedExpr
*nexpr
,
457 if (nexpr
->scope
== NULL
|| nexpr
->is_hidden
|| !nexpr
->texpr
)
460 v
= gnm_expr_top_get_range (nexpr
->texpr
);
462 if (VALUE_IS_CELLRANGE (v
)) {
463 GnmRangeRef
const *ref
= &v
->v_range
.cell
;
464 if (!ref
->a
.col_relative
&&
465 !ref
->b
.col_relative
&&
466 !ref
->a
.row_relative
&&
467 !ref
->b
.row_relative
&&
468 eval_sheet (ref
->a
.sheet
, user
->sheet
) == user
->sheet
&&
469 eval_sheet (ref
->b
.sheet
, user
->sheet
) == user
->sheet
&&
470 MIN (ref
->a
.col
, ref
->b
.col
) == user
->r
->start
.col
&&
471 MAX (ref
->a
.col
, ref
->b
.col
) == user
->r
->end
.col
&&
472 MIN (ref
->a
.row
, ref
->b
.row
) == user
->r
->start
.row
&&
473 MAX (ref
->a
.row
, ref
->b
.row
) == user
->r
->end
.row
)
480 static GnmNamedExpr
*
481 gnm_named_expr_collection_check (GnmNamedExprCollection
*scope
,
482 Sheet
const *sheet
, GnmRange
const *r
)
493 g_hash_table_foreach (scope
->names
, (GHFunc
)cb_check_name
, &user
);
498 * gnm_named_expr_collection_foreach:
499 * @names: #GnmNamedExprCollection
500 * @func: (scope call):
503 * Iterate over all names, including placeholders.
506 gnm_named_expr_collection_foreach (GnmNamedExprCollection
*names
,
510 g_hash_table_foreach (names
->names
, func
, data
);
511 g_hash_table_foreach (names
->placeholders
, func
, data
);
514 /******************************************************************************/
517 * expr_name_handle_references:
519 * Register or unregister a name with
520 * all of the sheets it explicitly references. This is necessary
521 * because names are not dependents, and if they reference a deleted
522 * sheet we will not notice.
525 expr_name_handle_references (GnmNamedExpr
*nexpr
, gboolean add
)
527 GSList
*sheets
, *ptr
;
529 sheets
= gnm_expr_top_referenced_sheets (nexpr
->texpr
);
531 for (ptr
= sheets
; ptr
!= NULL
; ptr
= ptr
->next
) {
532 Sheet
*sheet
= ptr
->data
;
535 /* Implicit reference. */
539 /* No need to do anything during destruction */
540 if (sheet
->deps
== NULL
)
543 found
= g_hash_table_lookup (sheet
->deps
->referencing_names
, nexpr
);
546 g_hash_table_insert (sheet
->deps
->referencing_names
, nexpr
, nexpr
);
548 g_warning ("Name being registered multiple times ?");
552 g_warning ("Unregistered name being removed?");
554 g_hash_table_remove (sheet
->deps
->referencing_names
, nexpr
);
558 g_slist_free (sheets
);
567 * lookup but do not reference a named expression.
570 expr_name_lookup (GnmParsePos
const *pp
, char const *name
)
572 GnmNamedExpr
*res
= NULL
;
573 Sheet
const *sheet
= NULL
;
574 Workbook
const *wb
= NULL
;
576 g_return_val_if_fail (name
!= NULL
, NULL
);
580 wb
= (sheet
!= NULL
) ? sheet
->workbook
: pp
->wb
;
583 if (sheet
!= NULL
&& sheet
->names
!= NULL
)
584 res
= gnm_named_expr_collection_lookup (sheet
->names
, name
);
585 if (res
== NULL
&& wb
!= NULL
&& wb
->names
!= NULL
)
586 res
= gnm_named_expr_collection_lookup (wb
->names
, name
);
594 * Creates a new name without linking it into any container.
597 expr_name_new (char const *name
)
601 g_return_val_if_fail (name
!= NULL
, NULL
);
603 nexpr
= g_new0 (GnmNamedExpr
,1);
605 nexpr
->ref_count
= 1;
606 nexpr
->name
= go_string_new (name
);
608 nexpr
->dependents
= NULL
;
609 nexpr
->is_placeholder
= TRUE
;
610 nexpr
->is_hidden
= FALSE
;
611 nexpr
->is_permanent
= FALSE
;
612 nexpr
->is_editable
= TRUE
;
615 if (gnm_debug_flag ("names"))
616 g_printerr ("Created new name %s\n", name
);
621 struct cb_name_loop_check
{
626 gboolean stop_at_name
;
630 static GnmExpr
const *
631 cb_name_loop_check (GnmExpr
const *expr
, GnmExprWalk
*data
)
633 struct cb_name_loop_check
*args
= data
->user
;
635 if (GNM_EXPR_GET_OPER (expr
) == GNM_EXPR_OP_NAME
) {
636 GnmNamedExpr
const *nexpr2
= expr
->name
.name
;
637 if ((args
->name
&& !strcmp (nexpr2
->name
->str
, args
->name
)) ||
638 args
->nexpr
== nexpr2
||
639 (!args
->stop_at_name
&& nexpr2
->texpr
&&
640 /* Is the following right? It drops args->nexpr */
641 expr_name_check_for_loop (args
->name
, nexpr2
->texpr
))) {
651 * NB. if we already have a circular reference in addition
652 * to this one we are checking we will come to serious grief.
655 expr_name_check_for_loop (char const *name
, GnmExprTop
const *texpr
)
657 struct cb_name_loop_check args
;
659 g_return_val_if_fail (texpr
!= NULL
, TRUE
);
663 args
.stop_at_name
= FALSE
;
665 gnm_expr_walk (texpr
->expr
, cb_name_loop_check
, &args
);
670 expr_name_queue_deps (GnmNamedExpr
*nexpr
)
672 if (nexpr
->dependents
)
673 g_hash_table_foreach (nexpr
->dependents
,
674 (GHFunc
)dependent_queue_recalc
,
682 * @texpr: if texpr == NULL then create a placeholder with value #NAME?
684 * @link_to_container:
686 * Absorbs the reference to @texpr.
687 * If @error_msg is non NULL it may hold a pointer to a translated descriptive
688 * string. NOTE : caller is responsible for freeing the error message.
690 * The reference semantics of the new expression are
691 * 1) new names with @link_to_container TRUE are referenced by the container.
692 * The caller DOES NOT OWN a reference to the result, and needs to add their
694 * 2) if @link_to_container is FALSE the caller DOES OWN a reference, and
695 * can free the result by unrefing the name.
698 expr_name_add (GnmParsePos
const *pp
, char const *name
,
699 GnmExprTop
const *texpr
, char **error_msg
,
700 gboolean link_to_container
,
703 GnmNamedExpr
*nexpr
= NULL
;
704 GnmNamedExprCollection
*scope
= NULL
;
707 g_return_val_if_fail (pp
!= NULL
, NULL
);
708 g_return_val_if_fail (pp
->sheet
!= NULL
|| pp
->wb
!= NULL
, NULL
);
709 g_return_val_if_fail (name
!= NULL
, NULL
);
710 g_return_val_if_fail (stub
== NULL
|| stub
->is_placeholder
, NULL
);
712 fake_name
.str
= name
;
714 if (gnm_debug_flag ("names")) {
715 char *str
= gnm_expr_top_as_string (texpr
, pp
, NULL
);
716 g_printerr ("Adding Name=[%s] texpr=[%s] stub=[%s]\n",
717 name
, str
, stub
? expr_name_name (stub
) : "-");
722 (expr_name_check_for_loop (name
, texpr
) ||
723 (stub
&& expr_name_check_for_loop (expr_name_name (stub
), texpr
)))) {
724 gnm_expr_top_unref (texpr
);
726 *error_msg
= g_strdup_printf (_("'%s' has a circular reference"), name
);
730 scope
= (pp
->sheet
!= NULL
) ? pp
->sheet
->names
: pp
->wb
->names
;
731 /* see if there was a place holder */
732 nexpr
= g_hash_table_lookup (scope
->placeholders
, &fake_name
);
735 /* there was already a placeholder for this */
736 if (!link_to_container
)
737 expr_name_ref (nexpr
);
741 /* convert the placeholder into a real name */
742 g_hash_table_steal (scope
->placeholders
, &fake_name
);
743 nexpr
->is_placeholder
= FALSE
;
745 nexpr
= g_hash_table_lookup (scope
->names
, &fake_name
);
746 /* If this is a permanent name, we may be adding it */
747 /* on opening of a file, although */
748 /* the name is already in place. */
750 if (nexpr
->is_permanent
)
751 link_to_container
= FALSE
;
753 if (error_msg
!= NULL
)
754 *error_msg
= (pp
->sheet
!= NULL
)
755 ? g_strdup_printf (_("'%s' is already defined in sheet"), name
)
756 : g_strdup_printf (_("'%s' is already defined in workbook"), name
);
758 gnm_expr_top_unref (texpr
);
770 stub
->is_placeholder
= FALSE
;
771 go_string_unref (stub
->name
);
772 stub
->name
= go_string_new (name
);
774 nexpr
= expr_name_new (name
);
775 nexpr
->is_placeholder
= (texpr
== NULL
);
778 parse_pos_init (&nexpr
->pos
,
779 pp
->wb
, pp
->sheet
, pp
->eval
.col
, pp
->eval
.row
);
781 texpr
= gnm_expr_top_new_constant
782 (value_new_error_NAME (NULL
));
783 expr_name_set_expr (nexpr
, texpr
);
784 if (link_to_container
)
785 gnm_named_expr_collection_insert (scope
, nexpr
);
791 expr_name_ref (GnmNamedExpr
*nexpr
)
793 g_return_if_fail (nexpr
!= NULL
);
799 expr_name_unref (GnmNamedExpr
*nexpr
)
801 g_return_if_fail (nexpr
!= NULL
);
803 if (nexpr
->ref_count
-- > 1)
806 if (gnm_debug_flag ("names"))
807 g_printerr ("Finalizing name %s\n", nexpr
->name
->str
);
809 g_return_if_fail (nexpr
->scope
== NULL
);
812 go_string_unref (nexpr
->name
);
816 if (nexpr
->texpr
!= NULL
)
817 expr_name_set_expr (nexpr
, NULL
);
819 if (nexpr
->dependents
!= NULL
) {
820 g_hash_table_destroy (nexpr
->dependents
);
821 nexpr
->dependents
= NULL
;
824 nexpr
->pos
.wb
= NULL
;
825 nexpr
->pos
.sheet
= NULL
;
831 gnm_named_expr_get_type (void)
836 t
= g_boxed_type_register_static ("GnmNamedExpr",
837 (GBoxedCopyFunc
)expr_name_ref
,
838 (GBoxedFreeFunc
)expr_name_unref
);
847 * Remove a @nexpr from its container and deactivate it.
848 * NOTE : @nexpr may continue to exist if things still have references to it,
849 * but they will evaluate to #REF!
852 expr_name_remove (GnmNamedExpr
*nexpr
)
854 g_return_if_fail (nexpr
!= NULL
);
855 g_return_if_fail (nexpr
->scope
!= NULL
);
857 if (gnm_debug_flag ("names")) {
858 g_printerr ("Removing name %s from its container%s\n",
860 nexpr
->is_placeholder
? " as a placeholder" : "");
863 g_hash_table_remove (
864 nexpr
->is_placeholder
? nexpr
->scope
->placeholders
: nexpr
->scope
->names
,
869 expr_name_name (GnmNamedExpr
const *nexpr
)
871 g_return_val_if_fail (nexpr
!= NULL
, NULL
);
872 return nexpr
->name
->str
;
876 * expr_name_set_name :
877 * @nexpr: the named expression
878 * @new_name: the new name of the expression
880 * returns: TRUE on error.
883 expr_name_set_name (GnmNamedExpr
*nexpr
,
884 const char *new_name
)
886 const char *old_name
;
888 GOString fake_new_name
;
890 g_return_val_if_fail (nexpr
!= NULL
, TRUE
);
891 g_return_val_if_fail (nexpr
->scope
== NULL
|| new_name
, TRUE
);
893 old_name
= nexpr
->name
->str
;
894 if (go_str_compare (new_name
, old_name
) == 0)
897 fake_new_name
.str
= new_name
;
899 g_printerr ("Renaming %s to %s\n", old_name
, new_name
);
902 ? (nexpr
->is_placeholder
903 ? nexpr
->scope
->placeholders
904 : nexpr
->scope
->names
)
908 (g_hash_table_lookup (nexpr
->scope
->placeholders
,
910 g_hash_table_lookup (nexpr
->scope
->names
,
912 /* The only error not to be blamed on the programmer is
917 g_hash_table_steal (h
, nexpr
->name
);
920 go_string_unref (nexpr
->name
);
921 nexpr
->name
= go_string_new (new_name
);
924 g_hash_table_insert (h
, (gpointer
)nexpr
->name
, nexpr
);
931 * expr_name_as_string :
933 * @pp: optionally null.
935 * returns a string that the caller needs to free.
938 expr_name_as_string (GnmNamedExpr
const *nexpr
, GnmParsePos
const *pp
,
939 GnmConventions
const *fmt
)
943 return gnm_expr_top_as_string (nexpr
->texpr
, pp
, fmt
);
947 expr_name_eval (GnmNamedExpr
const *nexpr
, GnmEvalPos
const *pos
,
948 GnmExprEvalFlags flags
)
950 g_return_val_if_fail (pos
, NULL
);
953 return value_new_error_NAME (pos
);
955 return gnm_expr_top_eval (nexpr
->texpr
, pos
, flags
);
959 * expr_name_downgrade_to_placeholder:
962 * Takes a real non-placeholder name and converts it to being a placeholder.
963 * unrefing its expression
966 expr_name_downgrade_to_placeholder (GnmNamedExpr
*nexpr
)
968 g_return_if_fail (nexpr
!= NULL
);
970 expr_name_set_is_placeholder (nexpr
, TRUE
);
973 gnm_expr_top_new_constant (value_new_error_NAME (NULL
)));
976 /*******************************************************************
977 * Manage things that depend on named expressions.
981 * @nexpr: the named expression
982 * @pp: the new position
984 * Returns a translated error string which the caller must free if something
988 expr_name_set_pos (GnmNamedExpr
*nexpr
, GnmParsePos
const *pp
)
990 GnmNamedExprCollection
*old_scope
, *new_scope
;
992 g_return_val_if_fail (nexpr
!= NULL
, NULL
);
993 g_return_val_if_fail (pp
!= NULL
, NULL
);
995 old_scope
= nexpr
->scope
;
996 new_scope
= pp
->sheet
? pp
->sheet
->names
: pp
->wb
->names
;
998 if (old_scope
!= new_scope
&&
999 (g_hash_table_lookup (new_scope
->placeholders
, nexpr
->name
) ||
1000 g_hash_table_lookup (new_scope
->names
, nexpr
->name
))) {
1001 const char *fmt
= pp
->sheet
1002 ? _("'%s' is already defined in sheet")
1003 : _("'%s' is already defined in workbook");
1004 return g_strdup_printf (fmt
, nexpr
->name
);
1009 (nexpr
->is_placeholder
? old_scope
->placeholders
: old_scope
->names
,
1013 gnm_named_expr_collection_insert (new_scope
, nexpr
);
1018 * expr_name_set_expr :
1019 * @nexpr: the named expression
1020 * @texpr: the new content
1022 * Unrefs the current content of @nexpr and absorbs a ref to @new_expr.
1025 expr_name_set_expr (GnmNamedExpr
*nexpr
, GnmExprTop
const *texpr
)
1027 GSList
*good
= NULL
;
1029 g_return_if_fail (nexpr
!= NULL
);
1031 if (texpr
== nexpr
->texpr
)
1033 if (nexpr
->texpr
!= NULL
) {
1034 GSList
*deps
= NULL
, *junk
= NULL
;
1036 deps
= expr_name_unlink_deps (nexpr
);
1037 expr_name_handle_references (nexpr
, FALSE
);
1038 gnm_expr_top_unref (nexpr
->texpr
);
1041 * We do not want to relink deps for sheets that are going
1042 * away. This speeds up exit for workbooks with lots of
1046 GSList
*next
= deps
->next
;
1047 GnmDependent
*dep
= deps
->data
;
1049 if (dep
->sheet
&& dep
->sheet
->being_invalidated
)
1050 deps
->next
= junk
, junk
= deps
;
1052 deps
->next
= good
, good
= deps
;
1057 g_slist_free (junk
);
1059 nexpr
->texpr
= texpr
;
1060 dependents_link (good
);
1061 g_slist_free (good
);
1064 expr_name_handle_references (nexpr
, TRUE
);
1066 expr_name_queue_deps (nexpr
);
1070 expr_name_add_dep (GnmNamedExpr
*nexpr
, GnmDependent
*dep
)
1072 if (nexpr
->dependents
== NULL
)
1073 nexpr
->dependents
= g_hash_table_new (g_direct_hash
,
1076 g_hash_table_insert (nexpr
->dependents
, dep
, dep
);
1080 expr_name_remove_dep (GnmNamedExpr
*nexpr
, GnmDependent
*dep
)
1082 g_return_if_fail (nexpr
->dependents
!= NULL
);
1084 g_hash_table_remove (nexpr
->dependents
, dep
);
1088 * expr_name_is_placeholder :
1091 * Returns TRUE if @ne is a placeholder for an unknown name
1094 expr_name_is_placeholder (GnmNamedExpr
const *nexpr
)
1096 g_return_val_if_fail (nexpr
!= NULL
, FALSE
);
1098 return (nexpr
->texpr
&&
1099 gnm_expr_top_is_err (nexpr
->texpr
, GNM_ERROR_NAME
));
1103 expr_name_set_is_placeholder (GnmNamedExpr
*nexpr
, gboolean is_placeholder
)
1105 g_return_if_fail (nexpr
!= NULL
);
1107 is_placeholder
= !!is_placeholder
;
1108 if (nexpr
->is_placeholder
== is_placeholder
)
1110 nexpr
->is_placeholder
= is_placeholder
;
1113 g_hash_table_steal (is_placeholder
1114 ? nexpr
->scope
->names
1115 : nexpr
->scope
->placeholders
,
1117 gnm_named_expr_collection_insert (nexpr
->scope
, nexpr
);
1122 expr_name_is_active (GnmNamedExpr
const *nexpr
)
1124 g_return_val_if_fail (nexpr
!= NULL
, FALSE
);
1125 return nexpr
->scope
!= NULL
;
1128 struct cb_expr_name_in_use
{
1129 GnmNamedExpr
*nexpr
;
1134 cb_expr_name_in_use (G_GNUC_UNUSED gconstpointer key
,
1135 GnmNamedExpr
*nexpr
,
1136 struct cb_expr_name_in_use
*pdata
)
1138 if (!pdata
->in_use
) {
1139 struct cb_name_loop_check args
;
1142 args
.nexpr
= pdata
->nexpr
;
1143 args
.stop_at_name
= TRUE
;
1145 gnm_expr_walk (nexpr
->texpr
->expr
, cb_name_loop_check
, &args
);
1146 pdata
->in_use
= args
.res
;
1151 * expr_name_in_use :
1152 * @nexpr: A named expression.
1154 * Returns: TRUE, if the named expression appears to be in use. This is an
1155 * approximation only, as we only look at the workbook in which the name is
1160 expr_name_in_use (GnmNamedExpr
*nexpr
)
1163 struct cb_expr_name_in_use data
;
1165 if (nexpr
->dependents
!= NULL
&&
1166 g_hash_table_size (nexpr
->dependents
) != 0)
1170 data
.in_use
= FALSE
;
1172 wb
= nexpr
->pos
.sheet
? nexpr
->pos
.sheet
->workbook
: nexpr
->pos
.wb
;
1173 workbook_foreach_name (wb
, FALSE
,
1174 (GHFunc
)cb_expr_name_in_use
,
1182 expr_name_cmp_by_name (GnmNamedExpr
const *a
, GnmNamedExpr
const *b
)
1184 Sheet
const *sheeta
= a
->pos
.sheet
;
1185 Sheet
const *sheetb
= b
->pos
.sheet
;
1188 if (sheeta
!= sheetb
) {
1189 /* Locals after non-locals. */
1190 if (!sheeta
|| !sheetb
)
1191 return (!sheeta
) - (!sheetb
);
1193 /* By non-local sheet order. */
1194 res
= g_utf8_collate (sheeta
->name_case_insensitive
,
1195 sheetb
->name_case_insensitive
);
1198 if (res
== 0) /* By name. */
1199 res
= go_utf8_collate_casefold (a
->name
->str
, b
->name
->str
);
1205 * sheet_names_check :
1209 * Returns a constant string if @sheet!@r is the target of a named range.
1210 * Preference is given to workbook scope over sheet.
1213 sheet_names_check (Sheet
const *sheet
, GnmRange
const *r
)
1215 GnmNamedExpr
*nexpr
;
1218 g_return_val_if_fail (IS_SHEET (sheet
), NULL
);
1219 g_return_val_if_fail (r
!= NULL
, NULL
);
1222 range_normalize (&tmp
);
1223 nexpr
= gnm_named_expr_collection_check (sheet
->names
, sheet
, &tmp
);
1224 if (nexpr
== NULL
) {
1225 nexpr
= gnm_named_expr_collection_check (sheet
->workbook
->names
, sheet
, &tmp
);
1226 /* The global name is not accessible if there is a local name (#306685) */
1227 if (nexpr
!= NULL
&&
1228 gnm_named_expr_collection_lookup (sheet
->names
, nexpr
->name
->str
) != NULL
)
1232 return (nexpr
!= NULL
) ? nexpr
->name
->str
: NULL
;
1237 * expr_name_perm_add:
1239 * @texpr: string to be the value of the name
1240 * @is_editable: whether this is a predefined action
1242 * This is a wrapper around expr_name_add to set this as permanent name.
1247 expr_name_perm_add (Sheet
*sheet
, char const *name
,
1248 GnmExprTop
const *value
,
1249 gboolean is_editable
)
1254 parse_pos_init_sheet (&pp
, sheet
);
1255 res
= expr_name_add (&pp
, name
, value
, NULL
, TRUE
, NULL
);
1257 res
->is_permanent
= TRUE
;
1258 res
->is_editable
= is_editable
;
1262 /* ------------------------------------------------------------------------- */
1265 expr_name_set_expr_ref (GnmNamedExpr
*nexpr
, GnmExprTop
const *texpr
)
1267 gnm_expr_top_ref (texpr
);
1268 expr_name_set_expr (nexpr
, texpr
);
1272 * expr_name_set_expr_undo_new:
1273 * @nexpr: #GnmNamedExpr
1275 * Returns: (transfer full):
1278 expr_name_set_expr_undo_new (GnmNamedExpr
*ne
)
1281 gnm_expr_top_ref (ne
->texpr
);
1283 return go_undo_binary_new (ne
, (gpointer
)ne
->texpr
,
1284 (GOUndoBinaryFunc
)expr_name_set_expr_ref
,
1285 (GFreeFunc
)expr_name_unref
,
1286 (GFreeFunc
)gnm_expr_top_unref
);
1289 /* ------------------------------------------------------------------------- */