From 1778a7f3b1917fceb8bc6b5d48a5548d4e1ee7b9 Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Sun, 5 Jan 2014 20:42:19 +0100
Subject: gwinDestroy() and gwinRemoveChild()

---
 include/gwin/gwin.h | 22 +++++++++++++++++++---
 src/gwin/gwin.c     | 50 +++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/include/gwin/gwin.h b/include/gwin/gwin.h
index ded401d0..73f7ff82 100644
--- a/include/gwin/gwin.h
+++ b/include/gwin/gwin.h
@@ -389,14 +389,26 @@ extern "C" {
 		/**
 		 * @brief	Add a child widget to a parent one
 		 *
-		 * @param[in] parent	The parent widget (does not need to be parent yet)
-		 * @param[in] child		The child widget
-		 * @param[in] last		Should the child widget be added to the front or the back of the list? 
+		 * @param[in] parent	The parent window (does not need to be parent yet)
+		 * @param[in] child		The child window
+		 * @param[in] last		Should the child window be added to the front or the back of the list? 
 		 *
 		 * @api
 		 */
 		void gwinAddChild(GHandle parent, GHandle child, bool_t last);
 
+		/**
+		 * @brief	Remove a child from a parent
+		 *
+		 * @note	Other children of the same parent stay
+		 * @note	Children of the child are lost, they have to be reassigned manually if necessary.
+		 * 
+		 * @param[in] child		The child window
+		 *
+		 * @api
+		 */
+		void gwinRemoveChild(GHandle child);
+
 		/**
 		 * @brief	Get first child of a widget
 		 *
@@ -882,6 +894,10 @@ extern "C" {
 		#include "gwin/image.h"
 	#endif
 
+	#if GWIN_NEED_LAYOUT || defined(__DOXYGEN__)
+		#include "gwin/layout.h"
+	#endif
+
 #endif /* GFX_USE_GWIN */
 
 #endif /* _GWIN_H */
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index 88be0c88..923567ef 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -180,18 +180,20 @@ GHandle gwinGWindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pI
 }
 
 void gwinDestroy(GHandle gh) {
+	if (!gh) {
+		// should log a runtime error here
+		return;
+	}
+
 	#if GWIN_NEED_HIERARCHY
-		// fix hierarchy structure
-		if (gh->parent->child == gh) {
-			// we are the first child
-			gh->parent->child = gh->sibling;
-		} else {
-			// find our predecessor
-			GHandle tmp = gh->parent->child;
-			while (tmp->sibling != gh)
-				tmp = tmp->sibling;
-			tmp->sibling = gh->sibling;
-		}
+		GHandle tmp;
+
+		// recursively destroy our children first
+		for(tmp = gh->child; tmp; tmp = tmp->sibling)
+			gwinDestroy(tmp);
+
+		// remove myself from the hierarchy
+		gwinRemoveChild(gh);	
 	#endif
 	
 	// Make the window invisible
@@ -332,6 +334,32 @@ void gwinRedraw(GHandle gh) {
 		gwinRedraw(parent);
 	}
 
+	void gwinRemoveChild(GHandle gh) {
+		if(!gh || !gh->parent) {
+			// without a parent, removing is impossible
+			// should log a runtime error here
+			return;
+		}
+
+		if (gh->parent->child == gh) {
+			// we are the first child, update parent
+			gh->parent->child = gh->sibling;
+		} else {
+			// otherwise find our predecessor
+			GHandle tmp = gh->parent->child;
+			while (tmp && tmp->sibling != gh)
+				tmp = tmp->sibling;
+
+			if(!tmp) {
+				// our parent's children list is corrupted
+				// should log a runtime error here
+				return;
+			}
+
+			tmp->sibling = gh->sibling;
+		}
+	}
+
 	GHandle gwinGetFirstChild(GHandle gh) {
 		return gh->child;
 	}
-- 
cgit v1.2.3