evolution-3.6.4/widgets/table/e-tree-memory.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-tree-memory.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-tree-memory.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Chris Lahey <clahey@ximian.com>
 18  *		Chris Toshok <toshok@ximian.com>
 19  *
 20  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 21  *
 22  */
 23 
 24 #ifdef HAVE_CONFIG_H
 25 #include <config.h>
 26 #endif
 27 
 28 #include <stdio.h>
 29 #include <errno.h>
 30 #include <unistd.h>
 31 #include <fcntl.h>
 32 #include <stdlib.h>
 33 
 34 #include <libxml/parser.h>
 35 #include <libxml/xmlmemory.h>
 36 
 37 #include "e-util/e-util.h"
 38 #include "libevolution-utils/e-xml-utils.h"
 39 
 40 #include "e-tree-memory.h"
 41 
 42 #define E_TREE_MEMORY_GET_PRIVATE(obj) \
 43 	(G_TYPE_INSTANCE_GET_PRIVATE \
 44 	((obj), E_TYPE_TREE_MEMORY, ETreeMemoryPrivate))
 45 
 46 G_DEFINE_TYPE (ETreeMemory, e_tree_memory, E_TYPE_TREE_MODEL)
 47 
 48 enum {
 49 	FILL_IN_CHILDREN,
 50 	LAST_SIGNAL
 51 };
 52 
 53 static guint signals[LAST_SIGNAL] = { 0, };
 54 
 55 typedef struct ETreeMemoryPath ETreeMemoryPath;
 56 
 57 struct ETreeMemoryPath {
 58 	gpointer         node_data;
 59 
 60 	guint            children_computed : 1;
 61 
 62 	/* parent/child/sibling pointers */
 63 	ETreeMemoryPath *parent;
 64 	ETreeMemoryPath *next_sibling;
 65 	ETreeMemoryPath *prev_sibling;
 66 	ETreeMemoryPath *first_child;
 67 	ETreeMemoryPath *last_child;
 68 
 69 	gint             num_children;
 70 };
 71 
 72 struct _ETreeMemoryPrivate {
 73 	ETreeMemoryPath *root;
 74 
 75 	/* whether nodes are created expanded
 76 	 * or collapsed by default */
 77 	gboolean         expanded_default;
 78 
 79 	gint             frozen;
 80 	GFunc            destroy_func;
 81 	gpointer         destroy_user_data;
 82 };
 83 
 84 /* ETreeMemoryPath functions */
 85 
 86 static inline void
 87 check_children (ETreeMemory *memory,
 88                 ETreePath node)
 89 {
 90 	ETreeMemoryPath *path = node;
 91 	if (!path->children_computed) {
 92 		g_signal_emit (memory, signals[FILL_IN_CHILDREN], 0, node);
 93 		path->children_computed = TRUE;
 94 	}
 95 }
 96 
 97 static gint
 98 e_tree_memory_path_depth (ETreeMemoryPath *path)
 99 {
100 	gint depth = 0;
101 
102 	g_return_val_if_fail (path != NULL, -1);
103 
104 	for (path = path->parent; path; path = path->parent)
105 		depth++;
106 	return depth;
107 }
108 
109 static void
110 e_tree_memory_path_insert (ETreeMemoryPath *parent,
111                            gint position,
112                            ETreeMemoryPath *child)
113 {
114 	g_return_if_fail (position <= parent->num_children && position >= -1);
115 
116 	child->parent = parent;
117 
118 	if (parent->first_child == NULL)
119 		parent->first_child = child;
120 
121 	if (position == -1 || position == parent->num_children) {
122 		child->prev_sibling = parent->last_child;
123 		if (parent->last_child)
124 			parent->last_child->next_sibling = child;
125 		parent->last_child = child;
126 	} else {
127 		ETreeMemoryPath *c;
128 		for (c = parent->first_child; c; c = c->next_sibling) {
129 			if (position == 0) {
130 				child->next_sibling = c;
131 				child->prev_sibling = c->prev_sibling;
132 
133 				if (child->next_sibling)
134 					child->next_sibling->prev_sibling = child;
135 				if (child->prev_sibling)
136 					child->prev_sibling->next_sibling = child;
137 
138 				if (parent->first_child == c)
139 					parent->first_child = child;
140 				break;
141 			}
142 			position--;
143 		}
144 	}
145 
146 	parent->num_children++;
147 }
148 
149 static void
150 e_tree_path_unlink (ETreeMemoryPath *path)
151 {
152 	ETreeMemoryPath *parent = path->parent;
153 
154 	/* unlink first/last child if applicable */
155 	if (parent) {
156 		if (path == parent->first_child)
157 			parent->first_child = path->next_sibling;
158 		if (path == parent->last_child)
159 			parent->last_child = path->prev_sibling;
160 
161 		parent->num_children--;
162 	}
163 
164 	/* unlink prev/next sibling links */
165 	if (path->next_sibling)
166 		path->next_sibling->prev_sibling = path->prev_sibling;
167 	if (path->prev_sibling)
168 		path->prev_sibling->next_sibling = path->next_sibling;
169 
170 	path->parent = NULL;
171 	path->next_sibling = NULL;
172 	path->prev_sibling = NULL;
173 }
174 
175 /**
176  * e_tree_memory_freeze:
177  * @etmm: the ETreeModel to freeze.
178  *
179  * This function prepares an ETreeModel for a period of much change.
180  * All signals regarding changes to the tree are deferred until we
181  * thaw the tree.
182  *
183  **/
184 void
185 e_tree_memory_freeze (ETreeMemory *etmm)
186 {
187 	ETreeMemoryPrivate *priv = etmm->priv;
188 
189 	if (priv->frozen == 0)
190 		e_tree_model_pre_change (E_TREE_MODEL (etmm));
191 
192 	priv->frozen++;
193 }
194 
195 /**
196  * e_tree_memory_thaw:
197  * @etmm: the ETreeMemory to thaw.
198  *
199  * This function thaws an ETreeMemory.  All the defered signals can add
200  * up to a lot, we don't know - so we just emit a model_changed
201  * signal.
202  *
203  **/
204 void
205 e_tree_memory_thaw (ETreeMemory *etmm)
206 {
207 	ETreeMemoryPrivate *priv = etmm->priv;
208 
209 	if (priv->frozen > 0)
210 		priv->frozen--;
211 	if (priv->frozen == 0) {
212 		e_tree_model_node_changed (E_TREE_MODEL (etmm), priv->root);
213 	}
214 }
215 
216 /* virtual methods */
217 
218 static void
219 etmm_dispose (GObject *object)
220 {
221 	ETreeMemoryPrivate *priv;
222 
223 	priv = E_TREE_MEMORY_GET_PRIVATE (object);
224 
225 	if (priv->root)
226 		e_tree_memory_node_remove (
227 			E_TREE_MEMORY (object), priv->root);
228 
229 	G_OBJECT_CLASS (e_tree_memory_parent_class)->dispose (object);
230 }
231 
232 static ETreePath
233 etmm_get_root (ETreeModel *etm)
234 {
235 	ETreeMemoryPrivate *priv = E_TREE_MEMORY (etm)->priv;
236 	return priv->root;
237 }
238 
239 static ETreePath
240 etmm_get_parent (ETreeModel *etm,
241                  ETreePath node)
242 {
243 	ETreeMemoryPath *path = node;
244 	return path->parent;
245 }
246 
247 static ETreePath
248 etmm_get_first_child (ETreeModel *etm,
249                       ETreePath node)
250 {
251 	ETreeMemoryPath *path = node;
252 
253 	check_children (E_TREE_MEMORY (etm), node);
254 	return path->first_child;
255 }
256 
257 static ETreePath
258 etmm_get_last_child (ETreeModel *etm,
259                      ETreePath node)
260 {
261 	ETreeMemoryPath *path = node;
262 
263 	check_children (E_TREE_MEMORY (etm), node);
264 	return path->last_child;
265 }
266 
267 static ETreePath
268 etmm_get_next (ETreeModel *etm,
269                ETreePath node)
270 {
271 	ETreeMemoryPath *path = node;
272 	return path->next_sibling;
273 }
274 
275 static ETreePath
276 etmm_get_prev (ETreeModel *etm,
277                ETreePath node)
278 {
279 	ETreeMemoryPath *path = node;
280 	return path->prev_sibling;
281 }
282 
283 static gboolean
284 etmm_is_root (ETreeModel *etm,
285               ETreePath node)
286 {
287 	ETreeMemoryPath *path = node;
288 	return e_tree_memory_path_depth (path) == 0;
289 }
290 
291 static gboolean
292 etmm_is_expandable (ETreeModel *etm,
293                     ETreePath node)
294 {
295 	ETreeMemoryPath *path = node;
296 
297 	check_children (E_TREE_MEMORY (etm), node);
298 	return path->first_child != NULL;
299 }
300 
301 static guint
302 etmm_get_children (ETreeModel *etm,
303                    ETreePath node,
304                    ETreePath **nodes)
305 {
306 	ETreeMemoryPath *path = node;
307 	guint n_children;
308 
309 	check_children (E_TREE_MEMORY (etm), node);
310 
311 	n_children = path->num_children;
312 
313 	if (nodes) {
314 		ETreeMemoryPath *p;
315 		gint i = 0;
316 
317 		(*nodes) = g_new (ETreePath, n_children);
318 		for (p = path->first_child; p; p = p->next_sibling) {
319 			(*nodes)[i++] = p;
320 		}
321 	}
322 
323 	return n_children;
324 }
325 
326 static guint
327 etmm_depth (ETreeModel *etm,
328             ETreePath path)
329 {
330 	return e_tree_memory_path_depth (path);
331 }
332 
333 static gboolean
334 etmm_get_expanded_default (ETreeModel *etm)
335 {
336 	ETreeMemory *etmm = E_TREE_MEMORY (etm);
337 	ETreeMemoryPrivate *priv = etmm->priv;
338 
339 	return priv->expanded_default;
340 }
341 
342 static void
343 etmm_clear_children_computed (ETreeMemoryPath *path)
344 {
345 	for (path = path->first_child; path; path = path->next_sibling) {
346 		path->children_computed = FALSE;
347 		etmm_clear_children_computed (path);
348 	}
349 }
350 
351 static void
352 etmm_node_request_collapse (ETreeModel *etm,
353                             ETreePath node)
354 {
355 	ETreeModelClass *parent_class;
356 
357 	if (node)
358 		etmm_clear_children_computed (node);
359 
360 	parent_class = E_TREE_MODEL_CLASS (e_tree_memory_parent_class);
361 
362 	if (parent_class->node_request_collapse != NULL)
363 		parent_class->node_request_collapse (etm, node);
364 }
365 
366 static void
367 e_tree_memory_class_init (ETreeMemoryClass *class)
368 {
369 	GObjectClass *object_class;
370 	ETreeModelClass *tree_model_class;
371 
372 	g_type_class_add_private (class, sizeof (ETreeMemoryPrivate));
373 
374 	object_class = G_OBJECT_CLASS (class);
375 	object_class->dispose = etmm_dispose;
376 
377 	tree_model_class = E_TREE_MODEL_CLASS (class);
378 	tree_model_class->get_root = etmm_get_root;
379 	tree_model_class->get_prev = etmm_get_prev;
380 	tree_model_class->get_next = etmm_get_next;
381 	tree_model_class->get_first_child = etmm_get_first_child;
382 	tree_model_class->get_last_child = etmm_get_last_child;
383 	tree_model_class->get_parent = etmm_get_parent;
384 
385 	tree_model_class->is_root = etmm_is_root;
386 	tree_model_class->is_expandable = etmm_is_expandable;
387 	tree_model_class->get_children = etmm_get_children;
388 	tree_model_class->depth = etmm_depth;
389 	tree_model_class->get_expanded_default = etmm_get_expanded_default;
390 
391 	tree_model_class->node_request_collapse = etmm_node_request_collapse;
392 
393 	class->fill_in_children = NULL;
394 
395 	signals[FILL_IN_CHILDREN] = g_signal_new (
396 		"fill_in_children",
397 		G_TYPE_FROM_CLASS (object_class),
398 		G_SIGNAL_RUN_LAST,
399 		G_STRUCT_OFFSET (ETreeMemoryClass, fill_in_children),
400 		(GSignalAccumulator) NULL, NULL,
401 		g_cclosure_marshal_VOID__POINTER,
402 		G_TYPE_NONE, 1,
403 		G_TYPE_POINTER);
404 }
405 
406 static void
407 e_tree_memory_init (ETreeMemory *etmm)
408 {
409 	etmm->priv = E_TREE_MEMORY_GET_PRIVATE (etmm);
410 }
411 
412 /**
413  * e_tree_memory_construct:
414  * @etree:
415  *
416  *
417  **/
418 void
419 e_tree_memory_construct (ETreeMemory *etmm)
420 {
421 }
422 
423 /**
424  * e_tree_memory_new
425  *
426  * XXX docs here.
427  *
428  * return values: a newly constructed ETreeMemory.
429  */
430 ETreeMemory *
431 e_tree_memory_new (void)
432 {
433 	return g_object_new (E_TYPE_TREE_MEMORY, NULL);
434 }
435 
436 /**
437  * e_tree_memory_set_expanded_default
438  *
439  * Sets the state of nodes to be append to a thread.
440  * They will either be expanded or collapsed, according to
441  * the value of @expanded.
442  */
443 void
444 e_tree_memory_set_expanded_default (ETreeMemory *etree,
445                                     gboolean expanded)
446 {
447 	g_return_if_fail (etree != NULL);
448 
449 	etree->priv->expanded_default = expanded;
450 }
451 
452 /**
453  * e_tree_memory_node_get_data:
454  * @etmm:
455  * @node:
456  *
457  *
458  *
459  * Return value:
460  **/
461 gpointer
462 e_tree_memory_node_get_data (ETreeMemory *etmm,
463                              ETreePath node)
464 {
465 	ETreeMemoryPath *path = node;
466 
467 	g_return_val_if_fail (path, NULL);
468 
469 	return path->node_data;
470 }
471 
472 /**
473  * e_tree_memory_node_set_data:
474  * @etmm:
475  * @node:
476  * @node_data:
477  *
478  *
479  **/
480 void
481 e_tree_memory_node_set_data (ETreeMemory *etmm,
482                              ETreePath node,
483                              gpointer node_data)
484 {
485 	ETreeMemoryPath *path = node;
486 
487 	g_return_if_fail (path);
488 
489 	path->node_data = node_data;
490 }
491 
492 /**
493  * e_tree_memory_node_insert:
494  * @tree_model:
495  * @parent_path:
496  * @position:
497  * @node_data:
498  *
499  *
500  *
501  * Return value:
502  **/
503 ETreePath
504 e_tree_memory_node_insert (ETreeMemory *tree_model,
505                            ETreePath parent_node,
506                            gint position,
507                            gpointer node_data)
508 {
509 	ETreeMemoryPrivate *priv;
510 	ETreeMemoryPath *new_path;
511 	ETreeMemoryPath *parent_path = parent_node;
512 
513 	g_return_val_if_fail (tree_model != NULL, NULL);
514 
515 	priv = tree_model->priv;
516 
517 	g_return_val_if_fail (parent_path != NULL || priv->root == NULL, NULL);
518 
519 	priv = tree_model->priv;
520 
521 	if (!tree_model->priv->frozen)
522 		e_tree_model_pre_change (E_TREE_MODEL (tree_model));
523 
524 	new_path = g_slice_new0 (ETreeMemoryPath);
525 
526 	new_path->node_data = node_data;
527 	new_path->children_computed = FALSE;
528 
529 	if (parent_path != NULL) {
530 		e_tree_memory_path_insert (parent_path, position, new_path);
531 		if (!tree_model->priv->frozen)
532 			e_tree_model_node_inserted (
533 				E_TREE_MODEL (tree_model),
534 				parent_path, new_path);
535 	} else {
536 		priv->root = new_path;
537 		if (!tree_model->priv->frozen)
538 			e_tree_model_node_changed (
539 				E_TREE_MODEL (tree_model), new_path);
540 	}
541 
542 	return new_path;
543 }
544 
545 ETreePath
546 e_tree_memory_node_insert_id (ETreeMemory *etree,
547                               ETreePath parent,
548                               gint position,
549                               gpointer node_data,
550                               gchar *id)
551 {
552 	return e_tree_memory_node_insert (etree, parent, position, node_data);
553 }
554 
555 /**
556  * e_tree_memory_node_insert_before:
557  * @etree:
558  * @parent:
559  * @sibling:
560  * @node_data:
561  *
562  *
563  *
564  * Return value:
565  **/
566 ETreePath
567 e_tree_memory_node_insert_before (ETreeMemory *etree,
568                                   ETreePath parent,
569                                   ETreePath sibling,
570                                   gpointer node_data)
571 {
572 	ETreeMemoryPath *child;
573 	ETreeMemoryPath *parent_path = parent;
574 	ETreeMemoryPath *sibling_path = sibling;
575 	gint position = 0;
576 
577 	g_return_val_if_fail (etree != NULL, NULL);
578 
579 	if (sibling != NULL) {
580 		for (child = parent_path->first_child; child; child = child->next_sibling) {
581 			if (child == sibling_path)
582 				break;
583 			position++;
584 		}
585 	} else
586 		position = parent_path->num_children;
587 	return e_tree_memory_node_insert (etree, parent, position, node_data);
588 }
589 
590 /* just blows away child data, doesn't take into account unlinking/etc */
591 static void
592 child_free (ETreeMemory *etree,
593             ETreeMemoryPath *node)
594 {
595 	ETreeMemoryPath *child, *next;
596 
597 	child = node->first_child;
598 	while (child) {
599 		next = child->next_sibling;
600 		child_free (etree, child);
601 		child = next;
602 	}
603 
604 	if (etree->priv->destroy_func) {
605 		etree->priv->destroy_func (node->node_data, etree->priv->destroy_user_data);
606 	}
607 
608 	g_slice_free (ETreeMemoryPath, node);
609 }
610 
611 /**
612  * e_tree_memory_node_remove:
613  * @etree:
614  * @path:
615  *
616  *
617  *
618  * Return value:
619  **/
620 gpointer
621 e_tree_memory_node_remove (ETreeMemory *etree,
622                            ETreePath node)
623 {
624 	ETreeMemoryPath *path = node;
625 	ETreeMemoryPath *parent = path->parent;
626 	ETreeMemoryPath *sibling;
627 	gpointer ret = path->node_data;
628 	gint old_position = 0;
629 
630 	g_return_val_if_fail (etree != NULL, NULL);
631 
632 	if (!etree->priv->frozen) {
633 		e_tree_model_pre_change (E_TREE_MODEL (etree));
634 		for (old_position = 0, sibling = path;
635 		     sibling;
636 		     old_position++, sibling = sibling->prev_sibling)
637 			/* Empty intentionally*/;
638 		old_position--;
639 	}
640 
641 	/* unlink this node - we only have to unlink the root node being removed,
642 	 * since the others are only references from this node */
643 	e_tree_path_unlink (path);
644 
645 	/*printf("removing %d nodes from position %d\n", visible, base);*/
646 	if (!etree->priv->frozen)
647 		e_tree_model_node_removed (E_TREE_MODEL (etree), parent, path, old_position);
648 
649 	child_free (etree, path);
650 
651 	if (path == etree->priv->root)
652 		etree->priv->root = NULL;
653 
654 	if (!etree->priv->frozen)
655 		e_tree_model_node_deleted (E_TREE_MODEL (etree), path);
656 
657 	return ret;
658 }
659 
660 typedef struct {
661 	ETreeMemory *memory;
662 	gpointer closure;
663 	ETreeMemorySortCallback callback;
664 } MemoryAndClosure;
665 
666 static gint
667 sort_callback (gconstpointer data1,
668                gconstpointer data2,
669                gpointer user_data)
670 {
671 	ETreePath path1 = *(ETreePath *) data1;
672 	ETreePath path2 = *(ETreePath *) data2;
673 	MemoryAndClosure *mac = user_data;
674 	return (*mac->callback) (mac->memory, path1, path2, mac->closure);
675 }
676 
677 void
678 e_tree_memory_sort_node (ETreeMemory *etmm,
679                          ETreePath node,
680                          ETreeMemorySortCallback callback,
681                          gpointer user_data)
682 {
683 	ETreeMemoryPath **children;
684 	ETreeMemoryPath *child;
685 	gint count;
686 	gint i;
687 	ETreeMemoryPath *path = node;
688 	MemoryAndClosure mac;
689 	ETreeMemoryPath *last;
690 
691 	e_tree_model_pre_change (E_TREE_MODEL (etmm));
692 
693 	i = 0;
694 	for (child = path->first_child; child; child = child->next_sibling)
695 		i++;
696 
697 	children = g_new (ETreeMemoryPath *, i);
698 
699 	count = i;
700 
701 	for (child = path->first_child, i = 0;
702 	     child;
703 	     child = child->next_sibling, i++) {
704 		children[i] = child;
705 	}
706 
707 	mac.memory = etmm;
708 	mac.closure = user_data;
709 	mac.callback = callback;
710 
711 	g_qsort_with_data (
712 		children, count, sizeof (ETreeMemoryPath *),
713 		sort_callback, &mac);
714 
715 	path->first_child = NULL;
716 	last = NULL;
717 	for (i = 0;
718 	     i < count;
719 	     i++) {
720 		children[i]->prev_sibling = last;
721 		if (last)
722 			last->next_sibling = children[i];
723 		else
724 			path->first_child = children[i];
725 		last = children[i];
726 	}
727 	if (last)
728 		last->next_sibling = NULL;
729 
730 	path->last_child = last;
731 
732 	g_free (children);
733 
734 	e_tree_model_node_changed (E_TREE_MODEL (etmm), node);
735 }
736 
737 void
738 e_tree_memory_set_node_destroy_func (ETreeMemory *etmm,
739                                      GFunc destroy_func,
740                                      gpointer user_data)
741 {
742 	etmm->priv->destroy_func = destroy_func;
743 	etmm->priv->destroy_user_data = user_data;
744 }