1 #ifndef _GNM_DEPENDENT_H_
2 # define _GNM_DEPENDENT_H_
3 
4 #include <gnumeric.h>
5 #include <goffice/goffice.h>
6 
7 G_BEGIN_DECLS
8 
9 struct _GnmDependent {
10 	guint	  flags;
11 	Sheet	 *sheet;
12 	GnmExprTop const *texpr;
13 
14 	/* Double-linked list.  */
15 	GnmDependent *next_dep, *prev_dep;
16 };
17 
18 typedef struct {
19 	void (*eval)	   (GnmDependent *dep);
20 	void (*set_expr)   (GnmDependent *dep, GnmExprTop const *new_texpr);
21 	GSList* (*changed) (GnmDependent *dep);
22 	GnmCellPos* (*pos) (GnmDependent const *dep);
23 	void (*debug_name) (GnmDependent const *dep, GString *target);
24 } GnmDependentClass;
25 
26 typedef enum {
27 	DEPENDENT_NO_FLAG	   = 0,
28 
29 	/* Types */
30 	DEPENDENT_CELL		   = 0x00000001,	/* builtin type */
31 	DEPENDENT_DYNAMIC_DEP	   = 0x00000002,	/* builtin type */
32 	DEPENDENT_NAME		   = 0x00000003,	/* builtin pseudo type */
33 	DEPENDENT_MANAGED	   = 0x00000004,	/* builtin type */
34 	DEPENDENT_TYPE_MASK	   = 0x00000fff,
35 
36 	/* Linked into the workbook wide expression list */
37 	DEPENDENT_IS_LINKED	   = 0x00001000,
38 	DEPENDENT_NEEDS_RECALC	   = 0x00002000,
39 	DEPENDENT_BEING_CALCULATED = 0x00004000,
40 	/* GnmDependent is in the midst of a cyclic calculation */
41 	DEPENDENT_BEING_ITERATED   = 0x00008000,
42 
43 	DEPENDENT_GOES_INTERSHEET  = 0x00010000,
44 	DEPENDENT_GOES_INTERBOOK   = 0x00020000,
45 	DEPENDENT_USES_NAME	   = 0x00040000,
46 	DEPENDENT_HAS_3D	   = 0x00080000,
47 	DEPENDENT_HAS_DYNAMIC_DEPS = 0x00200000,
48 	DEPENDENT_IGNORE_ARGS	   = 0x00400000,
49 	DEPENDENT_LINK_FLAGS	   = 0x007ff000,
50 
51 	/* An internal utility flag */
52 	DEPENDENT_FLAGGED	   = 0x01000000,
53 	DEPENDENT_CAN_RELOCATE	   = 0x02000000
54 } GnmDependentFlags;
55 
56 #define dependent_type(dep)		((dep)->flags & DEPENDENT_TYPE_MASK)
57 #define dependent_is_cell(dep)		(dependent_type (dep) == DEPENDENT_CELL)
58 #define dependent_needs_recalc(dep)	((dep)->flags & DEPENDENT_NEEDS_RECALC)
59 #define dependent_is_linked(dep)	((dep)->flags & DEPENDENT_IS_LINKED)
60 
61 struct _GnmDepContainer {
62 	GnmDependent *head, *tail;
63 
64 	/* Large ranges hashed on 'range' to accelerate duplicate culling. This
65 	 * is traversed by g_hash_table_foreach mostly.
66 	 */
67 	int buckets;
68 	GHashTable **range_hash;
69 	GOMemChunk *range_pool;
70 
71 	/* Single ranges, this maps an GnmEvalPos * to a GSList of its
72 	 * dependencies.
73 	 */
74 	GHashTable *single_hash;
75 	GOMemChunk *single_pool;
76 
77 	/* All of the ExprNames that refer to this container */
78 	GHashTable *referencing_names;
79 
80 	/* Dynamic Deps */
81 	GHashTable *dynamic_deps;
82 };
83 
84 typedef void (*GnmDepFunc) (GnmDependent *dep, gpointer user);
85 
86 guint32	 dependent_type_register   (GnmDependentClass const *klass);
87 void	 dependent_types_init	   (void);
88 void	 dependent_types_shutdown  (void);
89 
90 void	 dependent_set_expr	   (GnmDependent *dep, GnmExprTop const *new_texpr);
91 void	 dependent_set_sheet	   (GnmDependent *dep, Sheet *sheet);
92 void	 dependent_link		   (GnmDependent *dep);
93 void	 dependent_unlink	   (GnmDependent *dep);
94 void	 dependent_queue_recalc	   (GnmDependent *dep);
95 void	 dependent_add_dynamic_dep (GnmDependent *dep, GnmRangeRef const *rr);
96 
97 gboolean dependent_is_volatile     (GnmDependent *dep);
98 
99 gboolean dependent_has_pos (GnmDependent const *dep);
100 GnmCellPos const *dependent_pos (GnmDependent const *dep);
101 void dependent_move (GnmDependent *dep, int dx, int dy);
102 
103 GOUndo  *dependents_relocate	    (GnmExprRelocateInfo const *info);
104 void	 dependents_link	    (GSList *deps);
105 
106 void	 gnm_cell_eval		    (GnmCell *cell);
107 void	 cell_queue_recalc	    (GnmCell *cell);
108 void	 cell_foreach_dep	    (GnmCell const *cell, GnmDepFunc func, gpointer user);
109 
110 void sheet_region_queue_recalc	  (Sheet const *sheet, GnmRange const *range);
111 void dependents_invalidate_sheet  (Sheet *sheet, gboolean destroy);
112 void dependents_workbook_destroy  (Workbook *wb);
113 void dependents_revive_sheet      (Sheet *sheet);
114 void workbook_queue_all_recalc	  (Workbook *wb);
115 void workbook_queue_volatile_recalc (Workbook *wb);
116 
117 GnmDepContainer *gnm_dep_container_new  (Sheet *sheet);
118 void		 gnm_dep_container_dump	(GnmDepContainer const *deps,
119 					 Sheet *sheet);
120 void dependents_dump (Workbook *wb);
121 void             gnm_dep_container_sanity_check (GnmDepContainer const *deps);
122 void             gnm_dep_container_resize (GnmDepContainer *deps, int rows);
123 
124 // ----------------------------------------------------------------------------
125 
126 typedef struct {
127 	GnmDependent base;
128 } GnmDepManaged;
129 
130 void dependent_managed_init (GnmDepManaged *dep, Sheet *sheet);
131 void dependent_managed_set_expr (GnmDepManaged *dep, GnmExprTop const *texpr);
132 GnmExprTop const *dependent_managed_get_expr (GnmDepManaged const *dep);
133 void dependent_managed_set_sheet (GnmDepManaged *dep, Sheet *sheet);
134 
135 // ----------------------------------------------------------------------------
136 
137 #define DEPENDENT_CONTAINER_FOREACH_DEPENDENT(dc, dep, code)	\
138   do {								\
139 	GnmDependent *dep = (dc)->head;				\
140 	while (dep) {						\
141 		GnmDependent *_next = dep->next_dep;		\
142 		code;						\
143 		dep = _next;					\
144 	}							\
145   } while (0)
146 
147 #define DEPENDENT_MAKE_TYPE(t,...)					\
148 guint									\
149 t ## _get_dep_type (void)						\
150 {									\
151 	static guint32 type = 0;					\
152 	if (type == 0) {						\
153 		static GnmDependentClass klass = { __VA_ARGS__ };	\
154 		klass.eval	 = &t ## _eval;				\
155 		klass.debug_name = &t ## _debug_name;			\
156 		type = dependent_type_register (&klass);		\
157 	}								\
158 	return type;							\
159 }
160 
161 void dependent_debug_name (GnmDependent const *dep, GString *target);
162 
163 G_END_DECLS
164 
165 #endif /* _GNM_DEPENDENT_H_ */
166