diff src/redraw_man.c @ 140:0de8fd11271e

Use macro to simplify the code. Many code snippets are repeated annoying. Just because we manipulate a common structure of data. They are move to macros to make it simple and meaning.
author Thinker K.F. Li <thinker@branda.to>
date Tue, 23 Sep 2008 08:28:14 +0800
parents 1695a4b02b14
children e89512d6fa0a
line wrap: on
line diff
--- a/src/redraw_man.c	Mon Sep 22 19:22:57 2008 +0800
+++ b/src/redraw_man.c	Tue Sep 23 08:28:14 2008 +0800
@@ -32,7 +32,29 @@
 static void ob_observer_free(ob_factory_t *factory, observer_t *observer);
 static subject_t *ob_get_parent_subject(ob_factory_t *factory,
 					subject_t *cur_subject);
+/* Functions for children. */
+#define FORCHILDREN(coord, child)				\
+    for((child) = STAILQ_HEAD((coord)->children);		\
+	(child) != NULL;					\
+	(child) = STAILQ_NEXT(coord_t, sibling, (child)))
+#define NEXT_CHILD(child) STAILQ_NEXT(coord_t, sibling, child)
+#define ADD_CHILD(parent, child)					\
+    STAILQ_INS_TAIL((parent)->children, coord_t, sibling, (child))
+#define RM_CHILD(parent, child)						\
+    STAILQ_REMOVE((parent)->children, coord_t, sibling, (child))
+#define FIRST_CHILD(parent) STAILQ_HEAD((parent)->children)
 
+/* Functions for members. */
+#define FORMEMBERS(coord, member)				\
+    for((member) = STAILQ_HEAD((coord)->members);		\
+	(member) != NULL;					\
+	(member) = STAILQ_NEXT(geo_t, coord_next, (member)))
+#define NEXT_MEMBER(member) STAILQ_NEXT(geo_t, coord_next, (member))
+#define ADD_MEMBER(coord, member)					\
+    STAILQ_INS_TAIL((coord)->members, geo_t, coord_next, (member))
+#define RM_MEMBER(coord, member)					\
+    STAILQ_REMOVE((coord)->members, geo_t, coord_next, (member))
+#define FIRST_MEMBER(coord) STAILQ_HEAD((coord)->members)
 
 /*! \brief Sort a list of element by a unsigned integer.
  *
@@ -139,6 +161,39 @@
 #endif
 }
 
+static int geo_off_in_coord(geo_t *geo, coord_t *coord) {
+    int off = 0;
+    geo_t *vgeo;
+
+    FORMEMBERS(coord, vgeo) {
+	if(vgeo == geo)
+	    return off;
+	off++;
+    }
+    return -1;
+}
+
+static void geo_attach_coord(geo_t *geo, coord_t *coord) {
+    ADD_MEMBER(coord, geo);
+    coord->num_members++;
+}
+
+static void geo_detach_coord(geo_t *geo, coord_t *coord) {
+    int off;
+    coord_t *child;
+
+    off = geo_off_in_coord(geo, coord);
+    if(off < 0)
+	return;
+    FORCHILDREN(coord, child) {
+	if(child->before_pmem >= off)
+	    child->before_pmem--;
+    }
+
+    RM_MEMBER(coord, geo);
+    coord->num_members--;
+}
+
 int redraw_man_init(redraw_man_t *rdman, cairo_t *cr, cairo_t *backend) {
     extern void redraw_man_destroy(redraw_man_t *rdman);
 
@@ -260,8 +315,7 @@
     geo_init(geo);
     geo->mouse_event = subject_new(&rdman->ob_factory, geo, OBJT_GEO);
 
-    STAILQ_INS_TAIL(coord->members, geo_t, coord_next, geo);
-    coord->num_members++;
+    geo_attach_coord(geo, coord);
 
     /* New one should be dirty to recompute it when drawing. */
     geo->flags |= GEF_DIRTY;
@@ -285,7 +339,7 @@
 
     geo = shape->geo;
     coord = shape->coord;
-    STAILQ_REMOVE(coord->members, geo_t, coord_next, geo);
+    geo_detach_coord(geo, coord);
     subject_free(&rdman->ob_factory, geo->mouse_event);
     sh_detach_geo(shape);
     elmpool_elm_free(rdman->geo_pool, shape->geo);
@@ -340,17 +394,17 @@
     if(parent == NULL)
 	return ERR;
 
-    if(STAILQ_HEAD(coord->members) != NULL)
+    if(FIRST_MEMBER(coord) != NULL)
 	return ERR;
 
-    if(STAILQ_HEAD(coord->children) != NULL)
+    if(FIRST_CHILD(coord) != NULL)
 	return ERR;
 
     /* Free canvas (\ref redraw) */
     if(coord->flags & COF_OWN_CANVAS)
 	free_canvas(coord->canvas);
 
-    STAILQ_REMOVE(parent->children, coord_t, sibling, coord);
+    RM_CHILD(parent, coord);
     subject_free(&rdman->ob_factory, coord->mouse_event);
     elmpool_elm_free(rdman->coord_pool, coord);
     rdman->n_coords--;
@@ -510,9 +564,7 @@
 
     /* Clean member shapes. */
     cnt = 0;
-    for(geo = STAILQ_HEAD(coord->members);
-	geo != NULL;
-	geo = STAILQ_NEXT(geo_t, coord_next, geo)) {
+    FORMEMBERS(coord, geo) {
 	SWAP(geo->cur_area, geo->last_area, area_t *);
 	clean_shape(geo->shape);
 	cnt++;
@@ -524,9 +576,7 @@
 	return ERR;
 
     pos_cnt = 0;
-    for(geo = STAILQ_HEAD(coord->members);
-	geo != NULL;
-	geo = STAILQ_NEXT(geo_t, coord_next, geo)) {
+    FORMEMBERS(coord, geo) {
 	area_to_positions(geo->cur_area, poses + pos_cnt);
 	pos_cnt += 2;
     }
@@ -771,21 +821,21 @@
     int mem_idx;
 
     canvas = coord->canvas;
-    member = STAILQ_HEAD(coord->members);
+    member = FIRST_MEMBER(coord);
     mem_idx = 0;
-    child = STAILQ_HEAD(coord->children);
+    child = FIRST_CHILD(coord);
     while(child != NULL || member != NULL) {
 	if(child && child->before_pmem == mem_idx) {
 	    r = draw_coord_shapes_in_areas(rdman, child, n_areas, areas);
 	    dirty |= r;
-	    child = STAILQ_NEXT(coord_t, sibling, child);
+	    child = NEXT_CHILD(child);
 	} else {
 	    ASSERT(member != NULL);
 	    if(is_geo_in_areas(member, n_areas, areas)) {
 		draw_shape(rdman, canvas, member->shape);
 		dirty = 1;
 	    }
-	    member = STAILQ_NEXT(geo_t, coord_next, member);
+	    member = NEXT_MEMBER(member);
 	    mem_idx++;
 	}
     }
@@ -949,20 +999,20 @@
     
     if(last == NULL) {
 	coord = rdman->root_coord;
-	while(coord != NULL && STAILQ_HEAD(coord->members) == NULL)
+	while(coord != NULL && FIRST_MEMBER(coord) == NULL)
 	    coord = preorder_coord_subtree(rdman->root_coord, coord);
 	if(coord == NULL)
 	    return NULL;
-	return STAILQ_HEAD(coord->members);
+	return FIRST_MEMBER(coord);
     }
 
     coord = last->shape->coord;
-    next = STAILQ_NEXT(geo_t, coord_next, last);
+    next = NEXT_MEMBER(last);
     while(next == NULL) {
 	coord = preorder_coord_subtree(rdman->root_coord, coord);
 	if(coord == NULL)
 	    return NULL;
-	next = STAILQ_HEAD(coord->members);
+	next = FIRST_MEMBER(coord);
     }
     return next;
 }