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"
25 #include "sheet-style.h"
27 #include <goffice/goffice.h>
31 expr_name_validate_r1c1 (const char *name
)
36 if (p
[0] != 'R' && p
[0] != 'r')
39 /* no need to worry about [] since they are not alphanumeric */
40 for (i
= 0; p
[0] && g_ascii_isdigit (p
[0]); p
= g_utf8_next_char (p
))
44 if (p
[0] != 'C' && p
[0] != 'c')
47 for (i
= 0; p
[0] && g_ascii_isdigit (p
[0]); p
= g_utf8_next_char (p
))
51 return (p
[0] != '\0');
55 expr_name_validate_a1 (const char *name
)
60 for (i
= 0; *p
&& g_ascii_isalpha(p
[0]);
61 p
= g_utf8_next_char (p
))
63 if (i
==0 || i
>4) /* We want to allow "total2010" and it */
64 /* is unlikely to have more than 456976 */
67 for (i
= 0; *p
&& g_ascii_isdigit (p
[0]);
68 p
= g_utf8_next_char (p
))
77 * @name: tentative name
79 * returns TRUE if the given name is valid, FALSE otherwise.
82 expr_name_validate (const char *name
)
87 g_return_val_if_fail (name
!= NULL
, FALSE
);
92 v
= value_new_from_string (VALUE_BOOLEAN
, name
, NULL
, TRUE
);
94 v
= value_new_from_string (VALUE_BOOLEAN
, name
, NULL
, FALSE
);
100 /* Hmm... Now what? */
101 if (!g_unichar_isalpha (g_utf8_get_char (name
)) &&
105 for (p
= name
; *p
; p
= g_utf8_next_char (p
)) {
106 if (!g_unichar_isalnum (g_utf8_get_char (p
)) &&
111 /* Make sure it's not A1 etc.*/
112 /* Note that we can't use our regular parsers */
113 /* since we also have to avoid names that may become */
114 /* sensible when the sheet size changes. */
115 if (!expr_name_validate_a1 (name
))
118 /* What about R1C1? */
119 if (!expr_name_validate_r1c1 (name
))
127 cb_nexpr_remove (GnmNamedExpr
*nexpr
)
129 g_return_if_fail (nexpr
->scope
!= NULL
);
132 expr_name_set_expr (nexpr
, NULL
);
133 expr_name_unref (nexpr
);
137 cb_collect_name_deps (gpointer key
, G_GNUC_UNUSED gpointer value
,
140 GSList
**list
= user_data
;
141 *list
= g_slist_prepend (*list
, key
);
145 expr_name_unlink_deps (GnmNamedExpr
*nexpr
)
147 GSList
*ptr
, *deps
= NULL
;
149 if (nexpr
->dependents
== NULL
)
152 g_hash_table_foreach (nexpr
->dependents
, cb_collect_name_deps
, &deps
);
155 for (ptr
= deps
; ptr
!= NULL
; ptr
= ptr
->next
) {
156 GnmDependent
*dep
= ptr
->data
;
157 if (dependent_is_linked (dep
))
158 dependent_unlink (dep
);
164 expr_name_relink_deps (GnmNamedExpr
*nexpr
)
168 if (nexpr
->dependents
== NULL
)
171 g_hash_table_foreach (nexpr
->dependents
, cb_collect_name_deps
, &deps
);
172 dependents_link (deps
);
177 fake_go_string_hash (gconstpointer s_
)
179 const GOString
*s
= s_
;
180 return g_str_hash (s
->str
);
184 fake_go_string_equal (gconstpointer a_
, gconstpointer b_
)
186 const GOString
*a
= a_
;
187 const GOString
*b
= b_
;
188 return g_str_equal (a
->str
, b
->str
);
192 struct _GnmNamedExprCollection
{
193 /* all the defined names */
196 /* placeholders for references to undefined names */
197 GHashTable
*placeholders
;
200 unsigned ref_count
; /* boxed type */
204 * gnm_named_expr_collection_new:
206 * Returns: (transfer full): the newly allocated #GnmNamedExprCollection/
208 GnmNamedExprCollection
*
209 gnm_named_expr_collection_new (void)
211 GnmNamedExprCollection
*res
= g_new (GnmNamedExprCollection
, 1);
213 res
->names
= g_hash_table_new_full
214 (fake_go_string_hash
, fake_go_string_equal
,
215 NULL
, (GDestroyNotify
) cb_nexpr_remove
);
216 res
->placeholders
= g_hash_table_new_full
217 (fake_go_string_hash
, fake_go_string_equal
,
218 NULL
, (GDestroyNotify
) cb_nexpr_remove
);
225 * gnm_named_expr_collection_free:
226 * @names: The collection of names
228 * Frees names defined in the local scope.
229 * NOTE : THIS DOES NOT INVALIDATE NAMES THAT REFER
232 * in scope sheet2 we have a name that refers
233 * to sheet1. That will remain!
236 gnm_named_expr_collection_free (GnmNamedExprCollection
*names
)
238 if (names
!= NULL
&& names
->ref_count
-- < 2) {
239 g_hash_table_destroy (names
->names
);
240 g_hash_table_destroy (names
->placeholders
);
245 static GnmNamedExprCollection
*
246 gnm_named_expr_collection_ref (GnmNamedExprCollection
*names
)
253 gnm_named_expr_collection_dump (GnmNamedExprCollection
*names
, const char *id
)
255 g_printerr ("Named collection %s\n", id
);
257 g_printerr (" Empty\n");
261 if (names
->names
&& g_hash_table_size (names
->names
)) {
262 GHashTableIter hiter
;
265 g_printerr (" Defined names:\n");
266 g_hash_table_iter_init (&hiter
, names
->names
);
267 while (g_hash_table_iter_next (&hiter
, &key
, &value
)) {
268 const GOString
*name
= key
;
269 GnmNamedExpr
const *nexpr
= value
;
270 g_printerr (" [%s] =>\n", name
->str
);
271 if (name
!= nexpr
->name
)
272 g_printerr (" Weird keys: %p vs %p\n",
277 if (names
->placeholders
&& g_hash_table_size (names
->placeholders
)) {
278 GHashTableIter hiter
;
281 g_printerr (" Defined placeholders:\n");
282 g_hash_table_iter_init (&hiter
, names
->placeholders
);
283 while (g_hash_table_iter_next (&hiter
, &key
, &value
)) {
284 const GOString
*name
= key
;
285 GnmNamedExpr
const *nexpr
= value
;
286 g_printerr (" [%s] =>\n", name
->str
);
287 if (name
!= nexpr
->name
)
288 g_printerr (" Weird keys: %p vs %p\n",
295 gnm_named_expr_collection_sanity_check (GnmNamedExprCollection
*names
,
298 gboolean err
= FALSE
;
299 g_printerr ("Checking sanity for container %s\n", id
);
301 GHashTableIter hiter
;
304 g_hash_table_iter_init (&hiter
, names
->names
);
305 while (g_hash_table_iter_next (&hiter
, &key
, &value
)) {
306 const GOString
*name
= key
;
307 GnmNamedExpr
const *nexpr
= value
;
308 if (name
!= nexpr
->name
) {
310 g_printerr ("Container %s has strange defined name\n",
312 g_printerr (" key is %p [%s]\n",
314 g_printerr (" target's name is %p [%s]\n",
315 nexpr
->name
, nexpr
->name
->str
);
323 gnm_named_expr_collection_get_type (void)
328 t
= g_boxed_type_register_static ("GnmNamedExprCollection",
329 (GBoxedCopyFunc
)gnm_named_expr_collection_ref
,
330 (GBoxedFreeFunc
)gnm_named_expr_collection_free
);
336 cb_unlink_all_names (G_GNUC_UNUSED gpointer key
,
338 G_GNUC_UNUSED gpointer user_data
)
340 GnmNamedExpr
*nexpr
= value
;
341 GSList
*deps
= expr_name_unlink_deps (nexpr
);
346 gnm_named_expr_collection_unlink (GnmNamedExprCollection
*names
)
351 g_hash_table_foreach (names
->names
,
357 cb_relink_all_names (G_GNUC_UNUSED gpointer key
,
359 G_GNUC_UNUSED gpointer user_data
)
361 GnmNamedExpr
*nexpr
= value
;
362 expr_name_relink_deps (nexpr
);
366 gnm_named_expr_collection_relink (GnmNamedExprCollection
*names
)
371 g_hash_table_foreach (names
->names
,
377 gnm_named_expr_collection_lookup (GnmNamedExprCollection
const *scope
,
384 fake_name
.str
= name
;
385 nexpr
= g_hash_table_lookup (scope
->names
, &fake_name
);
387 nexpr
= g_hash_table_lookup (scope
->placeholders
,
395 cb_list_names (G_GNUC_UNUSED gpointer key
,
399 GSList
**pres
= user_data
;
400 GO_SLIST_PREPEND (*pres
, value
);
404 * gnm_named_expr_collection_list:
405 * @scope: #GnmNamedExprCollection
407 * Returns: (element-type GnmNamedExpr) (transfer container):
410 gnm_named_expr_collection_list (GnmNamedExprCollection
const *scope
)
414 g_hash_table_foreach (scope
->names
,
422 gnm_named_expr_collection_insert (GnmNamedExprCollection
*scope
,
425 if (gnm_debug_flag ("names")) {
426 char *scope_name
= nexpr
->pos
.sheet
427 ? g_strdup_printf ("sheet %s", nexpr
->pos
.sheet
->name_quoted
)
428 : g_strdup ("workbook");
429 g_printerr ("Inserting name %s into its %s container%s\n",
432 nexpr
->is_placeholder
? " as a placeholder" : "");
436 /* name can be active at this point, eg we are converting a
437 * placeholder, or changing a scope */
438 nexpr
->scope
= scope
;
440 (nexpr
->is_placeholder
? scope
->placeholders
: scope
->names
,
441 (gpointer
)nexpr
->name
, nexpr
);
451 cb_check_name (G_GNUC_UNUSED gpointer key
, GnmNamedExpr
*nexpr
,
456 if (nexpr
->scope
== NULL
|| nexpr
->is_hidden
|| !nexpr
->texpr
)
459 v
= gnm_expr_top_get_range (nexpr
->texpr
);
461 if (VALUE_IS_CELLRANGE (v
)) {
462 GnmRangeRef
const *ref
= &v
->v_range
.cell
;
463 if (!ref
->a
.col_relative
&&
464 !ref
->b
.col_relative
&&
465 !ref
->a
.row_relative
&&
466 !ref
->b
.row_relative
&&
467 eval_sheet (ref
->a
.sheet
, user
->sheet
) == user
->sheet
&&
468 eval_sheet (ref
->b
.sheet
, user
->sheet
) == user
->sheet
&&
469 MIN (ref
->a
.col
, ref
->b
.col
) == user
->r
->start
.col
&&
470 MAX (ref
->a
.col
, ref
->b
.col
) == user
->r
->end
.col
&&
471 MIN (ref
->a
.row
, ref
->b
.row
) == user
->r
->start
.row
&&
472 MAX (ref
->a
.row
, ref
->b
.row
) == user
->r
->end
.row
)
479 static GnmNamedExpr
*
480 gnm_named_expr_collection_check (GnmNamedExprCollection
*scope
,
481 Sheet
const *sheet
, GnmRange
const *r
)
492 g_hash_table_foreach (scope
->names
, (GHFunc
)cb_check_name
, &user
);
497 * gnm_named_expr_collection_foreach:
498 * @names: #GnmNamedExprCollection
499 * @func: (scope call):
502 * Iterate over all names, including placeholders.
505 gnm_named_expr_collection_foreach (GnmNamedExprCollection
*names
,
509 g_hash_table_foreach (names
->names
, func
, data
);
510 g_hash_table_foreach (names
->placeholders
, func
, data
);
513 /******************************************************************************/
516 * expr_name_handle_references:
518 * Register or unregister a name with
519 * all of the sheets it explicitly references. This is necessary
520 * because names are not dependents, and if they reference a deleted
521 * sheet we will not notice.
524 expr_name_handle_references (GnmNamedExpr
*nexpr
, gboolean add
)
526 GSList
*sheets
, *ptr
;
528 sheets
= gnm_expr_top_referenced_sheets (nexpr
->texpr
);
530 for (ptr
= sheets
; ptr
!= NULL
; ptr
= ptr
->next
) {
531 Sheet
*sheet
= ptr
->data
;
534 /* Implicit reference. */
538 /* No need to do anything during destruction */
539 if (sheet
->deps
== NULL
)
542 found
= g_hash_table_lookup (sheet
->deps
->referencing_names
, nexpr
);
545 g_hash_table_insert (sheet
->deps
->referencing_names
, nexpr
, nexpr
);
547 g_warning ("Name being registered multiple times ?");
551 g_warning ("Unregistered name being removed?");
553 g_hash_table_remove (sheet
->deps
->referencing_names
, nexpr
);
557 g_slist_free (sheets
);
566 * lookup but do not reference a named expression.
569 expr_name_lookup (GnmParsePos
const *pp
, char const *name
)
571 GnmNamedExpr
*res
= NULL
;
572 Sheet
const *sheet
= NULL
;
573 Workbook
const *wb
= NULL
;
575 g_return_val_if_fail (name
!= NULL
, NULL
);
579 wb
= (sheet
!= NULL
) ? sheet
->workbook
: pp
->wb
;
582 if (sheet
!= NULL
&& sheet
->names
!= NULL
)
583 res
= gnm_named_expr_collection_lookup (sheet
->names
, name
);
584 if (res
== NULL
&& wb
!= NULL
&& wb
->names
!= NULL
)
585 res
= gnm_named_expr_collection_lookup (wb
->names
, name
);
593 * Creates a new name without linking it into any container.
596 expr_name_new (char const *name
)
600 g_return_val_if_fail (name
!= NULL
, NULL
);
602 nexpr
= g_new0 (GnmNamedExpr
,1);
604 nexpr
->ref_count
= 1;
605 nexpr
->name
= go_string_new (name
);
607 nexpr
->dependents
= NULL
;
608 nexpr
->is_placeholder
= TRUE
;
609 nexpr
->is_hidden
= FALSE
;
610 nexpr
->is_permanent
= FALSE
;
611 nexpr
->is_editable
= TRUE
;
614 if (gnm_debug_flag ("names"))
615 g_printerr ("Created new name %s\n", name
);
620 struct cb_name_loop_check
{
625 gboolean stop_at_name
;
629 static GnmExpr
const *
630 cb_name_loop_check (GnmExpr
const *expr
, GnmExprWalk
*data
)
632 struct cb_name_loop_check
*args
= data
->user
;
634 GnmNamedExpr
const *nexpr2
= gnm_expr_get_name (expr
);
636 if ((args
->name
&& !strcmp (nexpr2
->name
->str
, args
->name
)) ||
637 args
->nexpr
== nexpr2
||
638 (!args
->stop_at_name
&& nexpr2
->texpr
&&
639 /* Is the following right? It drops args->nexpr */
640 expr_name_check_for_loop (args
->name
, nexpr2
->texpr
))) {
650 * NB. if we already have a circular reference in addition
651 * to this one we are checking we will come to serious grief.
654 expr_name_check_for_loop (char const *name
, GnmExprTop
const *texpr
)
656 struct cb_name_loop_check args
;
658 g_return_val_if_fail (texpr
!= NULL
, TRUE
);
662 args
.stop_at_name
= FALSE
;
664 gnm_expr_walk (texpr
->expr
, cb_name_loop_check
, &args
);
669 expr_name_queue_deps (GnmNamedExpr
*nexpr
)
671 if (nexpr
->dependents
)
672 g_hash_table_foreach (nexpr
->dependents
,
673 (GHFunc
)dependent_queue_recalc
,
681 * @texpr: if texpr == NULL then create a placeholder with value #NAME?
683 * @link_to_container:
685 * Absorbs the reference to @texpr.
686 * If @error_msg is non NULL it may hold a pointer to a translated descriptive
687 * string. NOTE : caller is responsible for freeing the error message.
689 * The reference semantics of the new expression are
690 * 1) new names with @link_to_container TRUE are referenced by the container.
691 * The caller DOES NOT OWN a reference to the result, and needs to add their
693 * 2) if @link_to_container is FALSE the caller DOES OWN a reference, and
694 * can free the result by unrefing the name.
697 expr_name_add (GnmParsePos
const *pp
, char const *name
,
698 GnmExprTop
const *texpr
, char **error_msg
,
699 gboolean link_to_container
,
702 GnmNamedExpr
*nexpr
= NULL
;
703 GnmNamedExprCollection
*scope
= NULL
;
706 g_return_val_if_fail (pp
!= NULL
, NULL
);
707 g_return_val_if_fail (pp
->sheet
!= NULL
|| pp
->wb
!= NULL
, NULL
);
708 g_return_val_if_fail (name
!= NULL
, NULL
);
709 g_return_val_if_fail (stub
== NULL
|| stub
->is_placeholder
, NULL
);
711 fake_name
.str
= name
;
713 if (gnm_debug_flag ("names")) {
714 char *str
= gnm_expr_top_as_string (texpr
, pp
, NULL
);
715 g_printerr ("Adding Name=[%s] texpr=[%s] stub=[%s]\n",
716 name
, str
, stub
? expr_name_name (stub
) : "-");
721 (expr_name_check_for_loop (name
, texpr
) ||
722 (stub
&& expr_name_check_for_loop (expr_name_name (stub
), texpr
)))) {
723 gnm_expr_top_unref (texpr
);
725 *error_msg
= g_strdup_printf (_("'%s' has a circular reference"), name
);
729 scope
= (pp
->sheet
!= NULL
) ? pp
->sheet
->names
: pp
->wb
->names
;
730 /* see if there was a place holder */
731 nexpr
= g_hash_table_lookup (scope
->placeholders
, &fake_name
);
734 /* there was already a placeholder for this */
735 if (!link_to_container
)
736 expr_name_ref (nexpr
);
740 /* convert the placeholder into a real name */
741 g_hash_table_steal (scope
->placeholders
, &fake_name
);
742 nexpr
->is_placeholder
= FALSE
;
744 nexpr
= g_hash_table_lookup (scope
->names
, &fake_name
);
745 /* If this is a permanent name, we may be adding it */
746 /* on opening of a file, although */
747 /* the name is already in place. */
749 if (nexpr
->is_permanent
)
750 link_to_container
= FALSE
;
752 if (error_msg
!= NULL
)
753 *error_msg
= (pp
->sheet
!= NULL
)
754 ? g_strdup_printf (_("'%s' is already defined in sheet"), name
)
755 : g_strdup_printf (_("'%s' is already defined in workbook"), name
);
757 gnm_expr_top_unref (texpr
);
769 stub
->is_placeholder
= FALSE
;
770 go_string_unref (stub
->name
);
771 stub
->name
= go_string_new (name
);
773 nexpr
= expr_name_new (name
);
774 nexpr
->is_placeholder
= (texpr
== NULL
);
777 parse_pos_init (&nexpr
->pos
,
778 pp
->wb
, pp
->sheet
, pp
->eval
.col
, pp
->eval
.row
);
780 texpr
= gnm_expr_top_new_constant
781 (value_new_error_NAME (NULL
));
782 expr_name_set_expr (nexpr
, texpr
);
783 if (link_to_container
)
784 gnm_named_expr_collection_insert (scope
, nexpr
);
790 expr_name_ref (GnmNamedExpr
*nexpr
)
792 g_return_if_fail (nexpr
!= NULL
);
798 expr_name_unref (GnmNamedExpr
*nexpr
)
800 g_return_if_fail (nexpr
!= NULL
);
802 if (nexpr
->ref_count
-- > 1)
805 if (gnm_debug_flag ("names"))
806 g_printerr ("Finalizing name %s\n", nexpr
->name
->str
);
808 g_return_if_fail (nexpr
->scope
== NULL
);
811 go_string_unref (nexpr
->name
);
815 if (nexpr
->texpr
!= NULL
)
816 expr_name_set_expr (nexpr
, NULL
);
818 if (nexpr
->dependents
!= NULL
) {
819 g_hash_table_destroy (nexpr
->dependents
);
820 nexpr
->dependents
= NULL
;
823 nexpr
->pos
.wb
= NULL
;
824 nexpr
->pos
.sheet
= NULL
;
830 gnm_named_expr_get_type (void)
835 t
= g_boxed_type_register_static ("GnmNamedExpr",
836 (GBoxedCopyFunc
)expr_name_ref
,
837 (GBoxedFreeFunc
)expr_name_unref
);
846 * Remove a @nexpr from its container and deactivate it.
847 * NOTE : @nexpr may continue to exist if things still have references to it,
848 * but they will evaluate to #REF!
851 expr_name_remove (GnmNamedExpr
*nexpr
)
853 g_return_if_fail (nexpr
!= NULL
);
854 g_return_if_fail (nexpr
->scope
!= NULL
);
856 if (gnm_debug_flag ("names")) {
857 g_printerr ("Removing name %s from its container%s\n",
859 nexpr
->is_placeholder
? " as a placeholder" : "");
862 g_hash_table_remove (
863 nexpr
->is_placeholder
? nexpr
->scope
->placeholders
: nexpr
->scope
->names
,
868 expr_name_name (GnmNamedExpr
const *nexpr
)
870 g_return_val_if_fail (nexpr
!= NULL
, NULL
);
871 return nexpr
->name
->str
;
875 * expr_name_set_name :
876 * @nexpr: the named expression
877 * @new_name: the new name of the expression
879 * returns: TRUE on error.
882 expr_name_set_name (GnmNamedExpr
*nexpr
,
883 const char *new_name
)
885 const char *old_name
;
887 GOString fake_new_name
;
889 g_return_val_if_fail (nexpr
!= NULL
, TRUE
);
890 g_return_val_if_fail (nexpr
->scope
== NULL
|| new_name
, TRUE
);
892 old_name
= nexpr
->name
->str
;
893 if (go_str_compare (new_name
, old_name
) == 0)
896 fake_new_name
.str
= new_name
;
898 g_printerr ("Renaming %s to %s\n", old_name
, new_name
);
901 ? (nexpr
->is_placeholder
902 ? nexpr
->scope
->placeholders
903 : nexpr
->scope
->names
)
907 (g_hash_table_lookup (nexpr
->scope
->placeholders
,
909 g_hash_table_lookup (nexpr
->scope
->names
,
911 /* The only error not to be blamed on the programmer is
916 g_hash_table_steal (h
, nexpr
->name
);
919 go_string_unref (nexpr
->name
);
920 nexpr
->name
= go_string_new (new_name
);
923 g_hash_table_insert (h
, (gpointer
)nexpr
->name
, nexpr
);
930 * expr_name_as_string :
932 * @pp: optionally null.
934 * returns a string that the caller needs to free.
937 expr_name_as_string (GnmNamedExpr
const *nexpr
, GnmParsePos
const *pp
,
938 GnmConventions
const *fmt
)
942 return gnm_expr_top_as_string (nexpr
->texpr
, pp
, fmt
);
946 expr_name_eval (GnmNamedExpr
const *nexpr
, GnmEvalPos
const *pos
,
947 GnmExprEvalFlags flags
)
949 g_return_val_if_fail (pos
, NULL
);
952 return value_new_error_NAME (pos
);
954 return gnm_expr_top_eval (nexpr
->texpr
, pos
, flags
);
958 * expr_name_downgrade_to_placeholder:
961 * Takes a real non-placeholder name and converts it to being a placeholder.
962 * unrefing its expression
965 expr_name_downgrade_to_placeholder (GnmNamedExpr
*nexpr
)
967 g_return_if_fail (nexpr
!= NULL
);
969 expr_name_set_is_placeholder (nexpr
, TRUE
);
972 gnm_expr_top_new_constant (value_new_error_NAME (NULL
)));
975 /*******************************************************************
976 * Manage things that depend on named expressions.
980 * @nexpr: the named expression
981 * @pp: the new position
983 * Returns a translated error string which the caller must free if something
987 expr_name_set_pos (GnmNamedExpr
*nexpr
, GnmParsePos
const *pp
)
989 GnmNamedExprCollection
*old_scope
, *new_scope
;
991 g_return_val_if_fail (nexpr
!= NULL
, NULL
);
992 g_return_val_if_fail (pp
!= NULL
, NULL
);
994 old_scope
= nexpr
->scope
;
995 new_scope
= pp
->sheet
? pp
->sheet
->names
: pp
->wb
->names
;
997 if (old_scope
!= new_scope
&&
998 (g_hash_table_lookup (new_scope
->placeholders
, nexpr
->name
) ||
999 g_hash_table_lookup (new_scope
->names
, nexpr
->name
))) {
1000 const char *fmt
= pp
->sheet
1001 ? _("'%s' is already defined in sheet")
1002 : _("'%s' is already defined in workbook");
1003 return g_strdup_printf (fmt
, nexpr
->name
);
1008 (nexpr
->is_placeholder
? old_scope
->placeholders
: old_scope
->names
,
1012 gnm_named_expr_collection_insert (new_scope
, nexpr
);
1017 * expr_name_set_expr :
1018 * @nexpr: the named expression
1019 * @texpr: the new content
1021 * Unrefs the current content of @nexpr and absorbs a ref to @new_expr.
1024 expr_name_set_expr (GnmNamedExpr
*nexpr
, GnmExprTop
const *texpr
)
1026 GSList
*good
= NULL
;
1028 g_return_if_fail (nexpr
!= NULL
);
1030 if (texpr
== nexpr
->texpr
)
1032 if (nexpr
->texpr
!= NULL
) {
1033 GSList
*deps
= NULL
, *junk
= NULL
;
1035 deps
= expr_name_unlink_deps (nexpr
);
1036 expr_name_handle_references (nexpr
, FALSE
);
1037 gnm_expr_top_unref (nexpr
->texpr
);
1040 * We do not want to relink deps for sheets that are going
1041 * away. This speeds up exit for workbooks with lots of
1045 GSList
*next
= deps
->next
;
1046 GnmDependent
*dep
= deps
->data
;
1048 if (dep
->sheet
&& dep
->sheet
->being_invalidated
)
1049 deps
->next
= junk
, junk
= deps
;
1051 deps
->next
= good
, good
= deps
;
1056 g_slist_free (junk
);
1058 nexpr
->texpr
= texpr
;
1059 dependents_link (good
);
1060 g_slist_free (good
);
1063 expr_name_handle_references (nexpr
, TRUE
);
1065 expr_name_queue_deps (nexpr
);
1069 expr_name_add_dep (GnmNamedExpr
*nexpr
, GnmDependent
*dep
)
1071 if (nexpr
->dependents
== NULL
)
1072 nexpr
->dependents
= g_hash_table_new (g_direct_hash
,
1075 g_hash_table_insert (nexpr
->dependents
, dep
, dep
);
1079 expr_name_remove_dep (GnmNamedExpr
*nexpr
, GnmDependent
*dep
)
1081 g_return_if_fail (nexpr
->dependents
!= NULL
);
1083 g_hash_table_remove (nexpr
->dependents
, dep
);
1087 * expr_name_is_placeholder :
1090 * Returns TRUE if @ne is a placeholder for an unknown name
1093 expr_name_is_placeholder (GnmNamedExpr
const *nexpr
)
1095 g_return_val_if_fail (nexpr
!= NULL
, FALSE
);
1097 return (nexpr
->texpr
&&
1098 gnm_expr_top_is_err (nexpr
->texpr
, GNM_ERROR_NAME
));
1102 expr_name_set_is_placeholder (GnmNamedExpr
*nexpr
, gboolean is_placeholder
)
1104 g_return_if_fail (nexpr
!= NULL
);
1106 is_placeholder
= !!is_placeholder
;
1107 if (nexpr
->is_placeholder
== is_placeholder
)
1109 nexpr
->is_placeholder
= is_placeholder
;
1112 g_hash_table_steal (is_placeholder
1113 ? nexpr
->scope
->names
1114 : nexpr
->scope
->placeholders
,
1116 gnm_named_expr_collection_insert (nexpr
->scope
, nexpr
);
1121 expr_name_is_active (GnmNamedExpr
const *nexpr
)
1123 g_return_val_if_fail (nexpr
!= NULL
, FALSE
);
1124 return nexpr
->scope
!= NULL
;
1127 struct cb_expr_name_in_use
{
1128 GnmNamedExpr
*nexpr
;
1133 cb_expr_name_in_use (G_GNUC_UNUSED gconstpointer key
,
1134 GnmNamedExpr
*nexpr
,
1135 struct cb_expr_name_in_use
*pdata
)
1137 if (!pdata
->in_use
) {
1138 struct cb_name_loop_check args
;
1141 args
.nexpr
= pdata
->nexpr
;
1142 args
.stop_at_name
= TRUE
;
1144 gnm_expr_walk (nexpr
->texpr
->expr
, cb_name_loop_check
, &args
);
1145 pdata
->in_use
= args
.res
;
1150 * expr_name_in_use :
1151 * @nexpr: A named expression.
1153 * Returns: TRUE, if the named expression appears to be in use. This is an
1154 * approximation only, as we only look at the workbook in which the name is
1159 expr_name_in_use (GnmNamedExpr
*nexpr
)
1162 struct cb_expr_name_in_use data
;
1164 if (nexpr
->dependents
!= NULL
&&
1165 g_hash_table_size (nexpr
->dependents
) != 0)
1169 data
.in_use
= FALSE
;
1171 wb
= nexpr
->pos
.sheet
? nexpr
->pos
.sheet
->workbook
: nexpr
->pos
.wb
;
1172 workbook_foreach_name (wb
, FALSE
,
1173 (GHFunc
)cb_expr_name_in_use
,
1181 expr_name_cmp_by_name (GnmNamedExpr
const *a
, GnmNamedExpr
const *b
)
1183 Sheet
const *sheeta
= a
->pos
.sheet
;
1184 Sheet
const *sheetb
= b
->pos
.sheet
;
1187 if (sheeta
!= sheetb
) {
1188 /* Locals after non-locals. */
1189 if (!sheeta
|| !sheetb
)
1190 return (!sheeta
) - (!sheetb
);
1192 /* By non-local sheet order. */
1193 res
= g_utf8_collate (sheeta
->name_case_insensitive
,
1194 sheetb
->name_case_insensitive
);
1197 if (res
== 0) /* By name. */
1198 res
= go_utf8_collate_casefold (a
->name
->str
, b
->name
->str
);
1204 * sheet_names_check :
1208 * Returns a constant string if @sheet!@r is the target of a named range.
1209 * Preference is given to workbook scope over sheet.
1212 sheet_names_check (Sheet
const *sheet
, GnmRange
const *r
)
1214 GnmNamedExpr
*nexpr
;
1217 g_return_val_if_fail (IS_SHEET (sheet
), NULL
);
1218 g_return_val_if_fail (r
!= NULL
, NULL
);
1221 range_normalize (&tmp
);
1222 nexpr
= gnm_named_expr_collection_check (sheet
->names
, sheet
, &tmp
);
1223 if (nexpr
== NULL
) {
1224 nexpr
= gnm_named_expr_collection_check (sheet
->workbook
->names
, sheet
, &tmp
);
1225 /* The global name is not accessible if there is a local name (#306685) */
1226 if (nexpr
!= NULL
&&
1227 gnm_named_expr_collection_lookup (sheet
->names
, nexpr
->name
->str
) != NULL
)
1231 return (nexpr
!= NULL
) ? nexpr
->name
->str
: NULL
;
1236 * expr_name_perm_add:
1238 * @texpr: string to be the value of the name
1239 * @is_editable: whether this is a predefined action
1241 * This is a wrapper around expr_name_add to set this as permanent name.
1246 expr_name_perm_add (Sheet
*sheet
, char const *name
,
1247 GnmExprTop
const *value
,
1248 gboolean is_editable
)
1253 parse_pos_init_sheet (&pp
, sheet
);
1254 res
= expr_name_add (&pp
, name
, value
, NULL
, TRUE
, NULL
);
1256 res
->is_permanent
= TRUE
;
1257 res
->is_editable
= is_editable
;
1261 /* ------------------------------------------------------------------------- */
1264 expr_name_set_expr_ref (GnmNamedExpr
*nexpr
, GnmExprTop
const *texpr
)
1266 gnm_expr_top_ref (texpr
);
1267 expr_name_set_expr (nexpr
, texpr
);
1271 * expr_name_set_expr_undo_new:
1272 * @nexpr: #GnmNamedExpr
1274 * Returns: (transfer full):
1277 expr_name_set_expr_undo_new (GnmNamedExpr
*ne
)
1280 gnm_expr_top_ref (ne
->texpr
);
1282 return go_undo_binary_new (ne
, (gpointer
)ne
->texpr
,
1283 (GOUndoBinaryFunc
)expr_name_set_expr_ref
,
1284 (GFreeFunc
)expr_name_unref
,
1285 (GFreeFunc
)gnm_expr_top_unref
);
1288 /* ------------------------------------------------------------------------- */