Compilation: fix warning.
[gnumeric.git] / src / expr-name.c
blobb5a31cca82c764befb6e1e980bd5d9a687cd5667
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * expr-name.c: Supported named expressions
5 * Author:
6 * Jody Goldberg <jody@gnome.org>
8 * Based on work by:
9 * Michael Meeks <michael@ximian.com>
12 #include <gnumeric-config.h>
13 #include <glib/gi18n-lib.h>
14 #include <string.h>
15 #include "gnumeric.h"
16 #include "expr-name.h"
18 #include "dependent.h"
19 #include "value.h"
20 #include "workbook-priv.h"
21 #include "expr.h"
22 #include "expr-impl.h"
23 #include "sheet.h"
24 #include "ranges.h"
25 #include "gutils.h"
26 #include "sheet-style.h"
28 #include <goffice/goffice.h>
31 static gboolean
32 expr_name_validate_r1c1 (const char *name)
34 const char *p = name;
35 gint i;
37 if (p[0] != 'R' && p[0] != 'r')
38 return TRUE;
39 p++;
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))
42 i++;
43 if (i==0)
44 return TRUE;
45 if (p[0] != 'C' && p[0] != 'c')
46 return TRUE;
47 p++;
48 for (i = 0; p[0] && g_ascii_isdigit (p[0]); p = g_utf8_next_char (p))
49 i++;
50 if (i==0)
51 return TRUE;
52 return (p[0] != '\0');
55 static gboolean
56 expr_name_validate_a1 (const char *name)
58 const char *p = name;
59 gint i;
61 for (i = 0; *p && g_ascii_isalpha(p[0]);
62 p = g_utf8_next_char (p))
63 i++;
64 if (i==0 || i>4) /* We want to allow "total2010" and it */
65 /* is unlikely to have more than 456976 */
66 /* columns atm */
67 return TRUE;
68 for (i = 0; *p && g_ascii_isdigit (p[0]);
69 p = g_utf8_next_char (p))
70 i++;
71 if (i==0)
72 return TRUE;
73 return (*p != '\0');
76 /**
77 * expr_name_validate:
78 * @name: tentative name
80 * returns TRUE if the given name is valid, FALSE otherwise.
82 gboolean
83 expr_name_validate (const char *name)
85 const char *p;
86 GnmValue *v;
88 g_return_val_if_fail (name != NULL, FALSE);
90 if (name[0] == 0)
91 return FALSE;
93 v = value_new_from_string (VALUE_BOOLEAN, name, NULL, TRUE);
94 if (!v)
95 v = value_new_from_string (VALUE_BOOLEAN, name, NULL, FALSE);
96 if (v) {
97 value_release (v);
98 return FALSE;
101 /* Hmm... Now what? */
102 if (!g_unichar_isalpha (g_utf8_get_char (name)) &&
103 name[0] != '_')
104 return FALSE;
106 for (p = name; *p; p = g_utf8_next_char (p)) {
107 if (!g_unichar_isalnum (g_utf8_get_char (p)) &&
108 p[0] != '_')
109 return FALSE;
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))
117 return FALSE;
119 /* What about R1C1? */
120 if (!expr_name_validate_r1c1 (name))
121 return FALSE;
123 return TRUE;
127 static void
128 cb_nexpr_remove (GnmNamedExpr *nexpr)
130 g_return_if_fail (nexpr->scope != NULL);
132 nexpr->scope = NULL;
133 expr_name_set_expr (nexpr, NULL);
134 expr_name_unref (nexpr);
137 static void
138 cb_collect_name_deps (gpointer key, G_GNUC_UNUSED gpointer value,
139 gpointer user_data)
141 GSList **list = user_data;
142 *list = g_slist_prepend (*list, key);
145 static GSList *
146 expr_name_unlink_deps (GnmNamedExpr *nexpr)
148 GSList *ptr, *deps = NULL;
150 if (nexpr->dependents == NULL)
151 return NULL;
153 g_hash_table_foreach (nexpr->dependents, cb_collect_name_deps, &deps);
155 /* pull them out */
156 for (ptr = deps ; ptr != NULL ; ptr = ptr->next) {
157 GnmDependent *dep = ptr->data;
158 if (dependent_is_linked (dep))
159 dependent_unlink (dep);
161 return deps;
164 static void
165 expr_name_relink_deps (GnmNamedExpr *nexpr)
167 GSList *deps = NULL;
169 if (nexpr->dependents == NULL)
170 return;
172 g_hash_table_foreach (nexpr->dependents, cb_collect_name_deps, &deps);
173 dependents_link (deps);
174 g_slist_free (deps);
177 static guint
178 fake_go_string_hash (gconstpointer s_)
180 const GOString *s = s_;
181 return g_str_hash (s->str);
184 static gboolean
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 */
195 GHashTable *names;
197 /* placeholders for references to undefined names */
198 GHashTable *placeholders;
200 /* <private> */
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);
220 res->ref_count = 1;
222 return res;
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
231 * TO THIS SCOPE.
232 * eg
233 * in scope sheet2 we have a name that refers
234 * to sheet1. That will remain!
236 void
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);
242 g_free (names);
246 static GnmNamedExprCollection *
247 gnm_named_expr_collection_ref (GnmNamedExprCollection *names)
249 names->ref_count++;
250 return names;
253 void
254 gnm_named_expr_collection_dump (GnmNamedExprCollection *names, const char *id)
256 g_printerr ("Named collection %s\n", id);
257 if (!names) {
258 g_printerr (" Empty\n");
259 return;
262 if (names->names && g_hash_table_size (names->names)) {
263 GHashTableIter hiter;
264 gpointer key, value;
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",
274 name, nexpr->name);
278 if (names->placeholders && g_hash_table_size (names->placeholders)) {
279 GHashTableIter hiter;
280 gpointer key, value;
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",
290 name, nexpr->name);
295 gboolean
296 gnm_named_expr_collection_sanity_check (GnmNamedExprCollection *names,
297 const char *id)
299 gboolean err = FALSE;
300 g_printerr ("Checking sanity for container %s\n", id);
301 if (names->names) {
302 GHashTableIter hiter;
303 gpointer key, value;
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) {
310 err = TRUE;
311 g_printerr ("Container %s has strange defined name\n",
312 id);
313 g_printerr (" key is %p [%s]\n",
314 name, name->str);
315 g_printerr (" target's name is %p [%s]\n",
316 nexpr->name, nexpr->name->str);
320 return err;
323 GType
324 gnm_named_expr_collection_get_type (void)
326 static GType t = 0;
328 if (t == 0) {
329 t = g_boxed_type_register_static ("GnmNamedExprCollection",
330 (GBoxedCopyFunc)gnm_named_expr_collection_ref,
331 (GBoxedFreeFunc)gnm_named_expr_collection_free);
333 return t;
336 static void
337 cb_unlink_all_names (G_GNUC_UNUSED gpointer key,
338 gpointer value,
339 G_GNUC_UNUSED gpointer user_data)
341 GnmNamedExpr *nexpr = value;
342 GSList *deps = expr_name_unlink_deps (nexpr);
343 g_slist_free (deps);
346 void
347 gnm_named_expr_collection_unlink (GnmNamedExprCollection *names)
349 if (!names)
350 return;
352 g_hash_table_foreach (names->names,
353 cb_unlink_all_names,
354 NULL);
357 static void
358 cb_relink_all_names (G_GNUC_UNUSED gpointer key,
359 gpointer value,
360 G_GNUC_UNUSED gpointer user_data)
362 GnmNamedExpr *nexpr = value;
363 expr_name_relink_deps (nexpr);
366 void
367 gnm_named_expr_collection_relink (GnmNamedExprCollection *names)
369 if (!names)
370 return;
372 g_hash_table_foreach (names->names,
373 cb_relink_all_names,
374 NULL);
377 GnmNamedExpr *
378 gnm_named_expr_collection_lookup (GnmNamedExprCollection const *scope,
379 char const *name)
381 if (scope != NULL) {
382 GOString fake_name;
383 GnmNamedExpr *nexpr;
385 fake_name.str = name;
386 nexpr = g_hash_table_lookup (scope->names, &fake_name);
387 if (nexpr == NULL)
388 nexpr = g_hash_table_lookup (scope->placeholders,
389 &fake_name);
390 return nexpr;
391 } else
392 return NULL;
395 static void
396 cb_list_names (G_GNUC_UNUSED gpointer key,
397 gpointer value,
398 gpointer user_data)
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):
410 GSList *
411 gnm_named_expr_collection_list (GnmNamedExprCollection const *scope)
413 GSList *res = NULL;
414 if (scope) {
415 g_hash_table_foreach (scope->names,
416 cb_list_names,
417 &res);
419 return res;
422 static void
423 gnm_named_expr_collection_insert (GnmNamedExprCollection *scope,
424 GnmNamedExpr *nexpr)
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",
431 nexpr->name->str,
432 scope_name,
433 nexpr->is_placeholder ? " as a placeholder" : "");
434 g_free (scope_name);
437 /* name can be active at this point, eg we are converting a
438 * placeholder, or changing a scope */
439 nexpr->scope = scope;
440 g_hash_table_replace
441 (nexpr->is_placeholder ? scope->placeholders : scope->names,
442 (gpointer)nexpr->name, nexpr);
445 typedef struct {
446 Sheet const *sheet;
447 GnmRange const *r;
448 GnmNamedExpr *res;
449 } CheckName;
451 static void
452 cb_check_name (G_GNUC_UNUSED gpointer key, GnmNamedExpr *nexpr,
453 CheckName *user)
455 GnmValue *v;
457 if (nexpr->scope == NULL || nexpr->is_hidden || !nexpr->texpr)
458 return;
460 v = gnm_expr_top_get_range (nexpr->texpr);
461 if (v != NULL) {
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)
474 user->res = nexpr;
476 value_release (v);
480 static GnmNamedExpr *
481 gnm_named_expr_collection_check (GnmNamedExprCollection *scope,
482 Sheet const *sheet, GnmRange const *r)
484 CheckName user;
486 if (scope == NULL)
487 return NULL;
489 user.sheet = sheet;
490 user.r = r;
491 user.res = NULL;
493 g_hash_table_foreach (scope->names, (GHFunc)cb_check_name, &user);
494 return user.res;
498 * gnm_named_expr_collection_foreach:
499 * @names: #GnmNamedExprCollection
500 * @func: (scope call):
501 * @data: user data.
503 * Iterate over all names, including placeholders.
505 void
506 gnm_named_expr_collection_foreach (GnmNamedExprCollection *names,
507 GHFunc func,
508 gpointer data)
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.
524 static void
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;
533 GnmNamedExpr *found;
535 /* Implicit reference. */
536 if (!sheet)
537 continue;
539 /* No need to do anything during destruction */
540 if (sheet->deps == NULL)
541 continue;
543 found = g_hash_table_lookup (sheet->deps->referencing_names, nexpr);
544 if (add) {
545 if (found == NULL) {
546 g_hash_table_insert (sheet->deps->referencing_names, nexpr, nexpr);
547 } else {
548 g_warning ("Name being registered multiple times ?");
550 } else {
551 if (found == NULL) {
552 g_warning ("Unregistered name being removed?");
553 } else {
554 g_hash_table_remove (sheet->deps->referencing_names, nexpr);
558 g_slist_free (sheets);
563 * expr_name_lookup:
564 * @pos:
565 * @name:
567 * lookup but do not reference a named expression.
569 GnmNamedExpr *
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);
578 if (pp != NULL) {
579 sheet = pp->sheet;
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);
587 return res;
591 * expr_name_new:
592 * @name:
594 * Creates a new name without linking it into any container.
596 GnmNamedExpr *
597 expr_name_new (char const *name)
599 GnmNamedExpr *nexpr;
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);
607 nexpr->texpr = NULL;
608 nexpr->dependents = NULL;
609 nexpr->is_placeholder = TRUE;
610 nexpr->is_hidden = FALSE;
611 nexpr->is_permanent = FALSE;
612 nexpr->is_editable = TRUE;
613 nexpr->scope = NULL;
615 if (gnm_debug_flag ("names"))
616 g_printerr ("Created new name %s\n", name);
618 return nexpr;
621 struct cb_name_loop_check {
622 /* One of these */
623 char const *name;
624 GnmNamedExpr *nexpr;
626 gboolean stop_at_name;
627 gboolean res;
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))) {
642 args->res = TRUE;
643 data->stop = TRUE;
647 return NULL;
651 * NB. if we already have a circular reference in addition
652 * to this one we are checking we will come to serious grief.
654 gboolean
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);
661 args.name = name;
662 args.nexpr = NULL;
663 args.stop_at_name = FALSE;
664 args.res = FALSE;
665 gnm_expr_walk (texpr->expr, cb_name_loop_check, &args);
666 return args.res;
669 static void
670 expr_name_queue_deps (GnmNamedExpr *nexpr)
672 if (nexpr->dependents)
673 g_hash_table_foreach (nexpr->dependents,
674 (GHFunc)dependent_queue_recalc,
675 NULL);
679 * expr_name_add:
680 * @pp:
681 * @name:
682 * @texpr: if texpr == NULL then create a placeholder with value #NAME?
683 * @error_msg:
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
693 * own.
694 * 2) if @link_to_container is FALSE the caller DOES OWN a reference, and
695 * can free the result by unrefing the name.
697 GnmNamedExpr *
698 expr_name_add (GnmParsePos const *pp, char const *name,
699 GnmExprTop const *texpr, char **error_msg,
700 gboolean link_to_container,
701 GnmNamedExpr *stub)
703 GnmNamedExpr *nexpr = NULL;
704 GnmNamedExprCollection *scope = NULL;
705 GOString fake_name;
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) : "-");
718 g_free (str);
721 if (texpr != NULL &&
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);
725 if (error_msg)
726 *error_msg = g_strdup_printf (_("'%s' has a circular reference"), name);
727 return NULL;
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);
733 if (nexpr != NULL) {
734 if (texpr == NULL) {
735 /* there was already a placeholder for this */
736 if (!link_to_container)
737 expr_name_ref (nexpr);
738 return nexpr;
741 /* convert the placeholder into a real name */
742 g_hash_table_steal (scope->placeholders, &fake_name);
743 nexpr->is_placeholder = FALSE;
744 } else {
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. */
749 if (nexpr != NULL) {
750 if (nexpr->is_permanent)
751 link_to_container = FALSE;
752 else {
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);
759 return NULL;
764 if (error_msg)
765 *error_msg = NULL;
767 if (nexpr == NULL) {
768 if (stub != NULL) {
769 nexpr = stub;
770 stub->is_placeholder = FALSE;
771 go_string_unref (stub->name);
772 stub->name = go_string_new (name);
773 } else {
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);
780 if (texpr == NULL)
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);
787 return nexpr;
790 void
791 expr_name_ref (GnmNamedExpr *nexpr)
793 g_return_if_fail (nexpr != NULL);
795 nexpr->ref_count++;
798 void
799 expr_name_unref (GnmNamedExpr *nexpr)
801 g_return_if_fail (nexpr != NULL);
803 if (nexpr->ref_count-- > 1)
804 return;
806 if (gnm_debug_flag ("names"))
807 g_printerr ("Finalizing name %s\n", nexpr->name->str);
809 g_return_if_fail (nexpr->scope == NULL);
811 if (nexpr->name) {
812 go_string_unref (nexpr->name);
813 nexpr->name = NULL;
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;
827 g_free (nexpr);
830 GType
831 gnm_named_expr_get_type (void)
833 static GType t = 0;
835 if (t == 0) {
836 t = g_boxed_type_register_static ("GnmNamedExpr",
837 (GBoxedCopyFunc)expr_name_ref,
838 (GBoxedFreeFunc)expr_name_unref);
840 return t;
844 * expr_name_remove :
845 * @nexpr:
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!
851 void
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",
859 nexpr->name->str,
860 nexpr->is_placeholder ? " as a placeholder" : "");
863 g_hash_table_remove (
864 nexpr->is_placeholder ? nexpr->scope->placeholders : nexpr->scope->names,
865 nexpr->name);
868 const char *
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.
882 gboolean
883 expr_name_set_name (GnmNamedExpr *nexpr,
884 const char *new_name)
886 const char *old_name;
887 GHashTable *h;
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)
895 return FALSE;
897 fake_new_name.str = new_name;
898 #if 0
899 g_printerr ("Renaming %s to %s\n", old_name, new_name);
900 #endif
901 h = nexpr->scope
902 ? (nexpr->is_placeholder
903 ? nexpr->scope->placeholders
904 : nexpr->scope->names)
905 : NULL;
906 if (h) {
907 if (new_name &&
908 (g_hash_table_lookup (nexpr->scope->placeholders,
909 &fake_new_name) ||
910 g_hash_table_lookup (nexpr->scope->names,
911 &fake_new_name))) {
912 /* The only error not to be blamed on the programmer is
913 already-in-use. */
914 return TRUE;
917 g_hash_table_steal (h, nexpr->name);
920 go_string_unref (nexpr->name);
921 nexpr->name = go_string_new (new_name);
923 if (h)
924 g_hash_table_insert (h, (gpointer)nexpr->name, nexpr);
926 return FALSE;
931 * expr_name_as_string :
932 * @nexpr:
933 * @pp: optionally null.
935 * returns a string that the caller needs to free.
937 char *
938 expr_name_as_string (GnmNamedExpr const *nexpr, GnmParsePos const *pp,
939 GnmConventions const *fmt)
941 if (pp == NULL)
942 pp = &nexpr->pos;
943 return gnm_expr_top_as_string (nexpr->texpr, pp, fmt);
946 GnmValue *
947 expr_name_eval (GnmNamedExpr const *nexpr, GnmEvalPos const *pos,
948 GnmExprEvalFlags flags)
950 g_return_val_if_fail (pos, NULL);
952 if (!nexpr)
953 return value_new_error_NAME (pos);
955 return gnm_expr_top_eval (nexpr->texpr, pos, flags);
959 * expr_name_downgrade_to_placeholder:
960 * @nexpr:
962 * Takes a real non-placeholder name and converts it to being a placeholder.
963 * unrefing its expression
965 void
966 expr_name_downgrade_to_placeholder (GnmNamedExpr *nexpr)
968 g_return_if_fail (nexpr != NULL);
970 expr_name_set_is_placeholder (nexpr, TRUE);
971 expr_name_set_expr
972 (nexpr,
973 gnm_expr_top_new_constant (value_new_error_NAME (NULL)));
976 /*******************************************************************
977 * Manage things that depend on named expressions.
980 * expr_name_set_pos:
981 * @nexpr: the named expression
982 * @pp: the new position
984 * Returns a translated error string which the caller must free if something
985 * goes wrong.
987 char *
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);
1007 if (old_scope)
1008 g_hash_table_steal
1009 (nexpr->is_placeholder ? old_scope->placeholders : old_scope->names,
1010 nexpr->name);
1012 nexpr->pos = *pp;
1013 gnm_named_expr_collection_insert (new_scope, nexpr);
1014 return NULL;
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.
1024 void
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)
1032 return;
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
1043 * names defined.
1045 while (deps) {
1046 GSList *next = deps->next;
1047 GnmDependent *dep = deps->data;
1049 if (dep->sheet && dep->sheet->being_invalidated)
1050 deps->next = junk, junk = deps;
1051 else
1052 deps->next = good, good = deps;
1054 deps = next;
1057 g_slist_free (junk);
1059 nexpr->texpr = texpr;
1060 dependents_link (good);
1061 g_slist_free (good);
1063 if (texpr != NULL)
1064 expr_name_handle_references (nexpr, TRUE);
1066 expr_name_queue_deps (nexpr);
1069 void
1070 expr_name_add_dep (GnmNamedExpr *nexpr, GnmDependent *dep)
1072 if (nexpr->dependents == NULL)
1073 nexpr->dependents = g_hash_table_new (g_direct_hash,
1074 g_direct_equal);
1076 g_hash_table_insert (nexpr->dependents, dep, dep);
1079 void
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 :
1089 * @ne:
1091 * Returns TRUE if @ne is a placeholder for an unknown name
1093 gboolean
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));
1102 void
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)
1109 return;
1110 nexpr->is_placeholder = is_placeholder;
1112 if (nexpr->scope) {
1113 g_hash_table_steal (is_placeholder
1114 ? nexpr->scope->names
1115 : nexpr->scope->placeholders,
1116 nexpr->name);
1117 gnm_named_expr_collection_insert (nexpr->scope, nexpr);
1121 gboolean
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;
1130 gboolean in_use;
1133 static void
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;
1141 args.name = NULL;
1142 args.nexpr = pdata->nexpr;
1143 args.stop_at_name = TRUE;
1144 args.res = FALSE;
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
1156 * defined.
1159 gboolean
1160 expr_name_in_use (GnmNamedExpr *nexpr)
1162 Workbook *wb;
1163 struct cb_expr_name_in_use data;
1165 if (nexpr->dependents != NULL &&
1166 g_hash_table_size (nexpr->dependents) != 0)
1167 return TRUE;
1169 data.nexpr = nexpr;
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,
1175 &data);
1177 return data.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;
1186 int res = 0;
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);
1201 return res;
1205 * sheet_names_check :
1206 * @sheet:
1207 * @r:
1209 * Returns a constant string if @sheet!@r is the target of a named range.
1210 * Preference is given to workbook scope over sheet.
1212 char const *
1213 sheet_names_check (Sheet const *sheet, GnmRange const *r)
1215 GnmNamedExpr *nexpr;
1216 GnmRange tmp;
1218 g_return_val_if_fail (IS_SHEET (sheet), NULL);
1219 g_return_val_if_fail (r != NULL, NULL);
1221 tmp = *r;
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)
1229 return NULL;
1232 return (nexpr != NULL) ? nexpr->name->str : NULL;
1237 * expr_name_perm_add:
1238 * @name: name
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.
1246 void
1247 expr_name_perm_add (Sheet *sheet, char const *name,
1248 GnmExprTop const *value,
1249 gboolean is_editable)
1251 GnmNamedExpr *res;
1252 GnmParsePos pp;
1254 parse_pos_init_sheet (&pp, sheet);
1255 res = expr_name_add (&pp, name, value, NULL, TRUE, NULL);
1256 if (res) {
1257 res->is_permanent = TRUE;
1258 res->is_editable = is_editable;
1262 /* ------------------------------------------------------------------------- */
1264 static void
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):
1277 GOUndo *
1278 expr_name_set_expr_undo_new (GnmNamedExpr *ne)
1280 expr_name_ref (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 /* ------------------------------------------------------------------------- */