changeset 60:61869769c050

Sync with the latest DW code.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Thu, 29 Nov 2001 15:10:39 +0000
parents 286ffd8e8ed8
children 4a02842f8074
files dw.h gtk/dw.c os2/dw.c win/dw.c
diffstat 4 files changed, 388 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/dw.h	Wed Nov 21 23:39:41 2001 +0000
+++ b/dw.h	Thu Nov 29 15:10:39 2001 +0000
@@ -112,9 +112,12 @@
 #define DW_POINTER_ARROW         SPTR_ARROW
 #define DW_POINTER_CLOCK         SPTR_WAIT
 
+#define DW_OS2_NEW_WINDOW        1
+
 typedef struct _window_data {
 	PFNWP oldproc;
 	HWND clickdefault;
+	ULONG flags;
 } WindowData;
 
 typedef struct _hpixmap {
@@ -666,6 +669,7 @@
 int dw_checkbox_query(HWND handle);
 void dw_checkbox_set(HWND handle, int value);
 HWND dw_tree_insert(HWND handle, char *title, unsigned long icon, HWND parent, void *itemdata);
+HWND dw_tree_insert_after(HWND handle, HWND item, char *title, unsigned long icon, HWND parent, void *itemdata);
 void dw_tree_clear(HWND handle);
 void dw_tree_delete(HWND handle, HWND item);
 void dw_tree_set(HWND handle, HWND item, char *title, unsigned long icon);
--- a/gtk/dw.c	Wed Nov 21 23:39:41 2001 +0000
+++ b/gtk/dw.c	Thu Nov 29 15:10:39 2001 +0000
@@ -965,10 +965,13 @@
 
 	DW_MUTEX_LOCK;
 	gtk_widget_show(handle);
-	gdk_window_raise(GTK_WIDGET(handle)->window);
-	gdk_flush();
-	gdk_window_show(GTK_WIDGET(handle)->window);
-	gdk_flush();
+	if(GTK_WIDGET(handle)->window)
+	{
+		gdk_window_raise(GTK_WIDGET(handle)->window);
+		gdk_flush();
+		gdk_window_show(GTK_WIDGET(handle)->window);
+		gdk_flush();
+	}
 	defaultitem = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "defaultitem");
 	if(defaultitem)
 		gtk_widget_grab_focus(defaultitem);
@@ -1777,6 +1780,8 @@
 		DW_MUTEX_UNLOCK;
 		return FALSE;
 	}
+	gtk_tree_set_view_mode(GTK_TREE(tree), GTK_TREE_VIEW_ITEM);
+	gtk_tree_set_selection_mode(GTK_TREE(tree), GTK_SELECTION_SINGLE);
 	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tmp), tree);
 	/* Set the selection mode */
 	gtk_tree_set_selection_mode (GTK_TREE(tree), GTK_SELECTION_SINGLE);
@@ -2077,7 +2082,7 @@
  *       id: An ID to be used with WinWindowFromID() or 0L.
  *       multi: Multiple select TRUE or FALSE.
  */
-HWND dw_listbox_new(unsigned long id, int multi)
+HWND dw_listbox_new(unsigned long id, int multi)
 {
 	GtkWidget *tmp, *list;
 	int _locked_by_me = FALSE;
@@ -2109,7 +2114,7 @@
  */
 void dw_window_set_icon(HWND handle, unsigned long id)
 {
-	GdkBitmap *bitmap;
+	GdkBitmap *bitmap = NULL;
 	GdkPixmap *icon_pixmap;
 	int _locked_by_me = FALSE;
 
@@ -2130,7 +2135,7 @@
  */
 void dw_window_set_bitmap(HWND handle, unsigned long id)
 {
-	GdkBitmap *bitmap;
+	GdkBitmap *bitmap = NULL;
 	GdkPixmap *tmp;
 	int _locked_by_me = FALSE;
 
@@ -2740,6 +2745,99 @@
 }
 
 /*
+ * Inserts an item into a tree window (widget) after another item.
+ * Parameters:
+ *          handle: Handle to the tree to be inserted.
+ *          item: Handle to the item to be positioned after.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ *          parent: Parent handle or 0 if root.
+ *          itemdata: Item specific data.
+ */
+HWND dw_tree_insert_after(HWND handle, HWND item, char *title, unsigned long icon, HWND parent, void *itemdata)
+{
+	GtkWidget *newitem, *tree, *subtree, *label, *hbox, *pixmap;
+	GdkPixmap *gdkpix;
+	GdkBitmap *gdkbmp = NULL;
+	int position = 0;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return NULL;
+
+	DW_MUTEX_LOCK;
+	tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+	if(!tree || !GTK_IS_TREE(tree))
+	{
+		DW_MUTEX_UNLOCK;
+		return NULL;
+	}
+
+	if(item && GTK_IS_TREE_ITEM(item))
+		position = gtk_tree_child_position(GTK_TREE(tree), item);
+
+	position++;
+
+	newitem = gtk_tree_item_new();
+	label = gtk_label_new(title);
+	gtk_object_set_data(GTK_OBJECT(newitem), "text", (gpointer)strdup(title));
+	gtk_object_set_data(GTK_OBJECT(newitem), "itemdata", (gpointer)itemdata);
+	gtk_object_set_data(GTK_OBJECT(newitem), "tree", (gpointer)tree);
+	hbox = gtk_hbox_new(FALSE, 2);
+	gtk_object_set_data(GTK_OBJECT(newitem), "hbox", (gpointer)hbox);
+	gdkpix = _find_pixmap(&gdkbmp, icon, hbox);
+	pixmap = gtk_pixmap_new(gdkpix, gdkbmp);
+	gtk_container_add(GTK_CONTAINER(newitem), hbox);
+	gtk_box_pack_start(GTK_BOX(hbox), pixmap, FALSE, TRUE, 0);
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
+	gtk_widget_show(label);
+	gtk_widget_show(pixmap);
+	gtk_widget_show(hbox);
+
+	if(parent)
+	{
+		subtree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(parent));
+		if(!subtree)
+		{
+			void *thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "select-child-func");
+			void *work = (void *)gtk_object_get_data(GTK_OBJECT(tree), "select-child-data");
+
+			subtree = gtk_tree_new();
+
+			if(thisfunc && work)
+				gtk_signal_connect(GTK_OBJECT(subtree), "select-child", GTK_SIGNAL_FUNC(thisfunc), work);
+
+			thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "container-context-func");
+			work = (void *)gtk_object_get_data(GTK_OBJECT(tree), "container-context-data");
+
+			if(thisfunc && work)
+				gtk_signal_connect(GTK_OBJECT(subtree), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), work);
+
+			gtk_object_set_user_data(GTK_OBJECT(parent), subtree);
+			gtk_tree_set_selection_mode(GTK_TREE(subtree), GTK_SELECTION_SINGLE);
+			gtk_tree_set_view_mode(GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
+			gtk_tree_item_set_subtree(GTK_TREE_ITEM(parent), subtree);
+			gtk_tree_item_collapse(GTK_TREE_ITEM(parent));
+			gtk_widget_show(subtree);
+			gtk_tree_item_expand(GTK_TREE_ITEM(parent));
+			gtk_tree_item_collapse(GTK_TREE_ITEM(parent));
+		}
+		gtk_object_set_data(GTK_OBJECT(newitem), "parenttree", (gpointer)subtree);
+		gtk_tree_insert(GTK_TREE(subtree), newitem, position);
+	}
+	else
+	{
+		gtk_object_set_data(GTK_OBJECT(newitem), "parenttree", (gpointer)tree);
+		gtk_tree_insert(GTK_TREE(tree), newitem, position);
+	}
+	gtk_tree_item_expand(GTK_TREE_ITEM(newitem));
+	gtk_tree_item_collapse(GTK_TREE_ITEM(newitem));
+	gtk_widget_show(newitem);
+	DW_MUTEX_UNLOCK;
+	return newitem;
+}
+
+/*
  * Inserts an item into a tree window (widget).
  * Parameters:
  *          handle: Handle to the tree to be inserted.
@@ -2752,9 +2850,12 @@
 {
 	GtkWidget *item, *tree, *subtree, *label, *hbox, *pixmap;
 	GdkPixmap *gdkpix;
-	GdkBitmap *gdkbmp;
+	GdkBitmap *gdkbmp = NULL;
 	int _locked_by_me = FALSE;
 
+	if(!handle)
+		return NULL;
+
 	DW_MUTEX_LOCK;
 	tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
 	if(!tree || !GTK_IS_TREE(tree))
@@ -2806,10 +2907,14 @@
 			gtk_tree_item_expand(GTK_TREE_ITEM(parent));
 			gtk_tree_item_collapse(GTK_TREE_ITEM(parent));
 		}
+		gtk_object_set_data(GTK_OBJECT(item), "parenttree", (gpointer)subtree);
 		gtk_tree_append(GTK_TREE(subtree), item);
 	}
 	else
+	{
+		gtk_object_set_data(GTK_OBJECT(item), "parenttree", (gpointer)tree);
 		gtk_tree_append(GTK_TREE(tree), item);
+	}
 	gtk_tree_item_expand(GTK_TREE_ITEM(item));
 	gtk_tree_item_collapse(GTK_TREE_ITEM(item));
 	gtk_widget_show(item);
@@ -2829,10 +2934,13 @@
 {
 	GtkWidget *label, *hbox, *pixmap;
 	GdkPixmap *gdkpix;
-	GdkBitmap *gdkbmp;
+	GdkBitmap *gdkbmp = NULL;
 	char *oldtext;
 	int _locked_by_me = FALSE;
 
+	if(!handle || !item)
+		return;
+
 	DW_MUTEX_LOCK;
 	oldtext = (char *)gtk_object_get_data(GTK_OBJECT(item), "text");
 	if(oldtext)
@@ -2865,6 +2973,9 @@
 {
 	int _locked_by_me = FALSE;
 
+	if(!handle || !item)
+		return;
+
 	DW_MUTEX_LOCK;
 	gtk_object_set_data(GTK_OBJECT(item), "itemdata", (gpointer)itemdata);
 	DW_MUTEX_UNLOCK;
@@ -2881,6 +2992,9 @@
 	GtkWidget *lastselect;
 	int _locked_by_me = FALSE;
 
+	if(!handle || !item)
+		return;
+
 	DW_MUTEX_LOCK;
 	lastselect = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "lastselect");
 	if(lastselect && GTK_IS_TREE_ITEM(lastselect))
@@ -2900,6 +3014,9 @@
 	GtkWidget *tree;
 	int _locked_by_me = FALSE;
 
+	if(!handle)
+		return;
+
 	DW_MUTEX_LOCK;
 	tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
 	if(!tree || !GTK_IS_TREE(tree))
@@ -2921,6 +3038,9 @@
 {
 	int _locked_by_me = FALSE;
 
+	if(!handle || !item)
+		return;
+
 	DW_MUTEX_LOCK;
 	if(GTK_IS_TREE_ITEM(item))
 		gtk_tree_item_expand(GTK_TREE_ITEM(item));
@@ -2937,6 +3057,9 @@
 {
 	int _locked_by_me = FALSE;
 
+	if(!handle || !item)
+		return;
+
 	DW_MUTEX_LOCK;
 	if(GTK_IS_TREE_ITEM(item))
 		gtk_tree_item_collapse(GTK_TREE_ITEM(item));
@@ -2951,9 +3074,12 @@
  */
 void dw_tree_delete(HWND handle, HWND item)
 {
-	GtkWidget *tree, *lastselect;
+	GtkWidget *tree, *lastselect, *parenttree;
 	int _locked_by_me = FALSE;
 
+	if(!handle || !item || !GTK_IS_WIDGET(handle) || !GTK_IS_WIDGET(item))
+		return;
+
 	DW_MUTEX_LOCK;
 	tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
 	if(!tree || !GTK_IS_TREE(tree))
@@ -2963,10 +3089,22 @@
 	}
 
 	lastselect = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "lastselect");
+
 	if(lastselect == item)
+	{
+		if(lastselect && GTK_IS_WIDGET(lastselect))
+		{
+			parenttree = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(lastselect), "parenttree");
+			if(parenttree && GTK_IS_TREE(parenttree))
+				gtk_tree_unselect_child(GTK_TREE(parenttree), lastselect);
+		}
 		gtk_object_set_data(GTK_OBJECT(handle), "lastselect", NULL);
-
-	gtk_widget_destroy(item);
+	}
+
+	parenttree = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(item), "parenttree");
+
+	if(parenttree && GTK_IS_WIDGET(parenttree))
+		gtk_tree_remove_item(GTK_TREE(parenttree), item);
 	DW_MUTEX_UNLOCK;
 }
 
@@ -3156,7 +3294,7 @@
 	if(flag & DW_CFA_BITMAPORICON)
 	{
 		long hicon = *((long *)data);
-		GdkBitmap *bitmap;
+		GdkBitmap *bitmap = NULL;
 		GdkPixmap *pixmap = _find_pixmap(&bitmap, hicon, clist);
 
 		if(pixmap)
@@ -3550,7 +3688,7 @@
 
 GdkGC *_set_colors(GdkWindow *window)
 {
-	GdkGC *gc;
+	GdkGC *gc = NULL;
 	int index = _find_thread_index(dw_thread_id());
 
 	if(!window)
@@ -3768,7 +3906,7 @@
  */
 HPIXMAP dw_pixmap_grab(HWND handle, ULONG id)
 {
-	GdkBitmap *bitmap;
+	GdkBitmap *bitmap = NULL;
 	HPIXMAP pixmap;
 	int _locked_by_me = FALSE;
 
@@ -4847,6 +4985,45 @@
 }
 
 /*
+ * Returns the index to the current selected item or -1 when done.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ *          where: Either the previous return or -1 to restart.
+ */
+int dw_listbox_selected_multi(HWND handle, int where)
+{
+	GtkWidget *handle2 = handle;
+	int retval = DW_LIT_NONE;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	if(GTK_IS_LIST(handle2))
+	{
+		int counter = 0;
+		GList *list = GTK_LIST(handle2)->selection;
+		while(list)
+		{
+			if(counter > where)
+			{
+				retval = counter;
+				break;
+			}
+
+			list = list->next;
+			counter++;
+		}
+	}
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/*
  * Returns the index to the item in the list currently selected.
  * Parameters:
  *          handle: Handle to the listbox to be queried.
--- a/os2/dw.c	Wed Nov 21 23:39:41 2001 +0000
+++ b/os2/dw.c	Thu Nov 29 15:10:39 2001 +0000
@@ -748,14 +748,34 @@
 		if(pass > 1 && *depth > 0)
 		{
 			if(thisbox->type == BOXVERT)
-				thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))))/((float)(thisbox->minwidth-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))));
+			{
+				if((thisbox->minwidth-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))) == 0)
+					thisbox->items[z].xratio = 1.0;
+				else
+					thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))))/((float)(thisbox->minwidth-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))));
+			}
 			else
-				thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx));
+			{
+				if(thisbox->minwidth-thisbox->upx == 0)
+					thisbox->items[z].xratio = 1.0;
+				else
+					thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx));
+			}
 
 			if(thisbox->type == BOXHORZ)
-				thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))))/((float)(thisbox->minheight-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))));
+			{
+				if((thisbox->minheight-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))) == 0)
+					thisbox->items[z].yratio = 1.0;
+				else
+					thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))))/((float)(thisbox->minheight-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))));
+			}
 			else
-				thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy));
+			{
+				if(thisbox->minheight-thisbox->upy == 0)
+					thisbox->items[z].yratio = 1.0;
+				else
+					thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy));
+			}
 
 			if(thisbox->items[z].type == TYPEBOX)
 			{
@@ -2756,8 +2776,38 @@
 		swcntrl.uchVisibility = SWL_VISIBLE;
 		WinChangeSwitchEntry(hswitch, &swcntrl);
 	}
+	if(WinWindowFromID(handle, FID_CLIENT))
+	{
+		WindowData *blah = WinQueryWindowPtr(handle, QWP_USER);
+
+		if(blah && !(blah->flags & DW_OS2_NEW_WINDOW))
+		{
+			ULONG cx = dw_screen_width(), cy = dw_screen_height();
+			int newx, newy, changed = 0;
+			SWP swp;
+
+			blah->flags |= DW_OS2_NEW_WINDOW;
+
+			WinQueryWindowPos(handle, &swp);
+
+			newx = swp.x;
+			newy = swp.y;
+
+			if((swp.x+swp.cx) > cx)
+			{
+				newx = (cx - swp.cx)/2;
+				changed = 1;
+			}
+			if((swp.y+swp.cy) > cy)
+			{
+				newy = (cy - swp.cy)/2;
+				changed = 1;
+			}
+			if(changed)
+				WinSetWindowPos(handle, NULLHANDLE, newx, newy, 0, 0, SWP_MOVE);
+		}
+	}
 	return rc;
-
 }
 
 /*
@@ -3011,7 +3061,7 @@
 {
 	HWND hwndclient = 0, hwndframe;
 	Box *newbox = calloc(1, sizeof(Box));
-	PFNWP *blah = malloc(sizeof(PFNWP));
+	WindowData *blah = calloc(1, sizeof(WindowData));
 
 	newbox->pad = 0;
 	newbox->type = BOXVERT;
@@ -3024,11 +3074,14 @@
 	else
 		flStyle |= FCF_TITLEBAR;
 
+	if(!(flStyle & FCF_SHELLPOSITION))
+		blah->flags |= DW_OS2_NEW_WINDOW;
+
 	hwndframe = WinCreateStdWindow(hwndOwner, 0L, &flStyle, ClassName, title, 0L, NULLHANDLE, 0L, &hwndclient);
 	newbox->hwndtitle = WinWindowFromID(hwndframe, FID_TITLEBAR);
 	if(!newbox->titlebar && newbox->hwndtitle)
 		WinSetParent(newbox->hwndtitle, HWND_OBJECT, FALSE);
-	*blah = WinSubclassWindow(hwndframe, _sizeproc);
+	blah->oldproc = WinSubclassWindow(hwndframe, _sizeproc);
 	WinSetWindowPtr(hwndframe, QWP_USER, blah);
 	WinSetWindowPtr(hwndclient, QWP_USER, newbox);
 
@@ -3490,6 +3543,7 @@
  */
 HWND dw_mle_new(ULONG id)
 {
+	WindowData *blah = calloc(1, sizeof(WindowData));
 	HWND tmp = WinCreateWindow(HWND_OBJECT,
 							   WC_MLE,
 							   "",
@@ -3504,6 +3558,8 @@
 							   NULL);
 	dw_window_set_font(tmp, DefaultFont);
 	dw_window_set_font(tmp, DefaultFont);
+	blah->oldproc = WinSubclassWindow(tmp, _comboentryproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
 	return tmp;
 }
 
@@ -3782,7 +3838,7 @@
  */
 HWND dw_checkbox_new(char *text, ULONG id)
 {
-	PFNWP *blah = malloc(sizeof(PFNWP));
+	BubbleButton *bubble = malloc(sizeof(BubbleButton));
 	HWND tmp = WinCreateWindow(HWND_OBJECT,
 							   WC_BUTTON,
 							   text,
@@ -3795,8 +3851,10 @@
 							   NULL);
 	dw_window_set_font(tmp, DefaultFont);
 	dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
-	*blah = WinSubclassWindow(tmp, _entryproc);
-	WinSetWindowPtr(tmp, QWP_USER, blah);
+	bubble->id = id;
+	bubble->bubbletext[0] = '\0';
+	bubble->pOldProc = WinSubclassWindow(tmp, _BtProc);
+	WinSetWindowPtr(tmp, QWP_USER, bubble);
 	return tmp;
 }
 
@@ -4721,20 +4779,24 @@
 }
 
 /*
- * Inserts an item into a tree window (widget).
+ * Inserts an item into a tree window (widget) after another item.
  * Parameters:
  *          handle: Handle to the tree to be inserted.
+ *          item: Handle to the item to be positioned after.
  *          title: The text title of the entry.
  *          icon: Handle to coresponding icon.
  *          parent: Parent handle or 0 if root.
  *          itemdata: Item specific data.
  */
-HWND dw_tree_insert(HWND handle, char *title, unsigned long icon, HWND parent, void *itemdata)
+HWND dw_tree_insert_after(HWND handle, HWND item, char *title, unsigned long icon, HWND parent, void *itemdata)
 {
 	ULONG        cbExtra;
 	PCNRITEM     pci;
 	RECORDINSERT ri;
 
+	if(!item)
+		item = CMA_FIRST;
+
 	/* Calculate extra bytes needed for each record besides that needed for the
 	 * MINIRECORDCORE structure
 	 */
@@ -4757,7 +4819,7 @@
 	memset(&ri, 0, sizeof(RECORDINSERT));
 
 	ri.cb                 = sizeof(RECORDINSERT);
-	ri.pRecordOrder       = (PRECORDCORE)CMA_END;
+	ri.pRecordOrder       = (PRECORDCORE)item;
 	ri.pRecordParent      = (PRECORDCORE)NULL;
 	ri.zOrder             = (USHORT)CMA_TOP;
 	ri.cRecordsInsert     = 1;
@@ -4775,6 +4837,20 @@
 }
 
 /*
+ * Inserts an item into a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree to be inserted.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ *          parent: Parent handle or 0 if root.
+ *          itemdata: Item specific data.
+ */
+HWND dw_tree_insert(HWND handle, char *title, unsigned long icon, HWND parent, void *itemdata)
+{
+	return dw_tree_insert_after(handle, (HWND)CMA_END, title, icon, parent, itemdata);
+}
+
+/*
  * Sets the text and icon of an item in a tree window (widget).
  * Parameters:
  *          handle: Handle to the tree containing the item.
@@ -4884,7 +4960,10 @@
 		return;
 
 	if(pci->rc.pszIcon)
+	{
 		free(pci->rc.pszIcon);
+		pci->rc.pszIcon = 0;
+	}
 
 	WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)&pci, MPFROM2SHORT(1, CMA_INVALIDATE | CMA_FREE));
 }
--- a/win/dw.c	Wed Nov 21 23:39:41 2001 +0000
+++ b/win/dw.c	Thu Nov 29 15:10:39 2001 +0000
@@ -98,6 +98,8 @@
 
 } SignalList;
 
+static int in_checkbox_handler = 0;
+
 /* List of signals and their equivilent Win32 message */
 #define SIGNALMAX 14
 
@@ -711,14 +713,34 @@
 		if(pass > 1 && *depth > 0)
 		{
 			if(thisbox->type == BOXVERT)
-				thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))))/((float)(thisbox->minwidth-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))));
+			{
+				if((thisbox->minwidth-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))) == 0)
+					thisbox->items[z].xratio = 1.0;
+				else
+					thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))))/((float)(thisbox->minwidth-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))));
+			}
 			else
-				thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx));
+			{
+				if(thisbox->minwidth-thisbox->upx == 0)
+					thisbox->items[z].xratio = 1.0;
+				else
+					thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx));
+			}
 
 			if(thisbox->type == BOXHORZ)
-				thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))))/((float)(thisbox->minheight-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))));
+			{
+				if((thisbox->minheight-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))) == 0)
+					thisbox->items[z].yratio = 1.0;
+				else
+					thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))))/((float)(thisbox->minheight-((thisbox->items[z].pad*2)+(thisbox->parentpad*2))));
+			}
 			else
-				thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy));
+			{
+				if(thisbox->minheight-thisbox->upy == 0)
+					thisbox->items[z].yratio = 1.0;
+				else
+					thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy));
+			}
 
 			if(thisbox->items[z].type == TYPEBOX)
 			{
@@ -2192,7 +2214,13 @@
 					/* Make sure it's the right window, and the right ID */
 					if(tmp->window == hwnd)
 					{
+						if(bubble->checkbox)
+							in_checkbox_handler = 1;
+
 						clickfunc(tmp->window, tmp->data);
+
+						if(bubble->checkbox)
+							in_checkbox_handler = 0;
 						tmp = NULL;
 					}
 				}
@@ -3547,7 +3575,7 @@
  */
 HWND dw_button_new(char *text, ULONG id)
 {
-	BubbleButton *bubble = malloc(sizeof(BubbleButton));
+	BubbleButton *bubble = calloc(1, sizeof(BubbleButton));
 
 	HWND tmp = CreateWindow(BUTTONCLASSNAME,
 							text,
@@ -3576,7 +3604,7 @@
 HWND dw_bitmapbutton_new(char *text, ULONG id)
 {
 	HWND tmp;
-	BubbleButton *bubble = malloc(sizeof(BubbleButton));
+	BubbleButton *bubble = calloc(1, sizeof(BubbleButton));
 	HBITMAP hbitmap = LoadBitmap(DWInstance, MAKEINTRESOURCE(id));
 
 	tmp = CreateWindow(BUTTONCLASSNAME,
@@ -3708,6 +3736,7 @@
  */
 HWND dw_checkbox_new(char *text, ULONG id)
 {
+	BubbleButton *bubble = calloc(1, sizeof(BubbleButton));
 	HWND tmp = CreateWindow(BUTTONCLASSNAME,
 							text,
 							WS_CHILD | BS_AUTOCHECKBOX |
@@ -3717,14 +3746,12 @@
 							NULL,
 							NULL,
 							NULL);
-	ColorInfo *cinfo = calloc(1, sizeof(ColorInfo));
-
-	cinfo->back = cinfo->fore = -1;
-	cinfo->buddy = 0;
-	cinfo->user = 1;
-
-	cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc);
-	SetWindowLong(tmp, GWL_USERDATA, (ULONG)cinfo);
+	bubble->id = id;
+	bubble->checkbox = 1;
+	bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc);
+	bubble->cinfo.fore = -1;
+	bubble->cinfo.back = -1;
+	SetWindowLong(tmp, GWL_USERDATA, (ULONG)bubble);
 	dw_window_set_font(tmp, DefaultFont);
 	return tmp;
 }
@@ -4794,8 +4821,8 @@
 int dw_checkbox_query(HWND handle)
 {
 	if(SendMessage(handle, BM_GETCHECK, 0, 0) == BST_CHECKED)
-		return TRUE;
-	return FALSE;
+		return (in_checkbox_handler ? FALSE : TRUE);
+	return (in_checkbox_handler ? TRUE : FALSE);
 }
 
 /*
@@ -4814,6 +4841,41 @@
 }
 
 /*
+ * Inserts an item into a tree window (widget) after another item.
+ * Parameters:
+ *          handle: Handle to the tree to be inserted.
+ *          item: Handle to the item to be positioned after.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ *          parent: Parent handle or 0 if root.
+ *          itemdata: Item specific data.
+ */
+HWND dw_tree_insert_after(HWND handle, HWND item, char *title, unsigned long icon, HWND parent, void *itemdata)
+{
+	TVITEM tvi;
+	TVINSERTSTRUCT tvins;
+	HTREEITEM hti;
+	void **ptrs= malloc(sizeof(void *) * 2);
+
+	ptrs[0] = title;
+	ptrs[1] = itemdata;
+
+	tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
+	tvi.pszText = title;
+	tvi.lParam = (LONG)ptrs;
+	tvi.cchTextMax = strlen(title);
+	tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1);
+
+	tvins.item = tvi;
+	tvins.hParent = (HTREEITEM)parent;
+	tvins.hInsertAfter = item ? (HTREEITEM)item : TVI_FIRST;
+
+	hti = TreeView_InsertItem(handle, &tvins);
+
+	return (HWND)hti;
+}
+
+/*
  * Inserts an item into a tree window (widget).
  * Parameters:
  *          handle: Handle to the tree to be inserted.
@@ -4863,18 +4925,20 @@
 	tvi.mask = TVIF_HANDLE;
 	tvi.hItem = (HTREEITEM)item;
 
-	TreeView_GetItem(handle, &tvi);
-
-	ptrs = (void **)tvi.lParam;
-	ptrs[0] = title;
-
-	tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
-	tvi.pszText = title;
-	tvi.cchTextMax = strlen(title);
-	tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1);
-	tvi.hItem = (HTREEITEM)item;
-
-	TreeView_SetItem(handle, &tvi);
+	if(TreeView_GetItem(handle, &tvi))
+	{
+
+		ptrs = (void **)tvi.lParam;
+		ptrs[0] = title;
+
+		tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+		tvi.pszText = title;
+		tvi.cchTextMax = strlen(title);
+		tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1);
+		tvi.hItem = (HTREEITEM)item;
+
+		TreeView_SetItem(handle, &tvi);
+	}
 }
 
 /*
@@ -4892,10 +4956,11 @@
 	tvi.mask = TVIF_HANDLE;
 	tvi.hItem = (HTREEITEM)item;
 
-	TreeView_GetItem(handle, &tvi);
-
-	ptrs = (void **)tvi.lParam;
-	ptrs[1] = itemdata;
+	if(TreeView_GetItem(handle, &tvi))
+	{
+		ptrs = (void **)tvi.lParam;
+		ptrs[1] = itemdata;
+	}
 }
 
 /*
@@ -4950,6 +5015,9 @@
  */
 void dw_tree_delete(HWND handle, HWND item)
 {
+	if((HTREEITEM)item == TVI_ROOT)
+		return;
+
 	TreeView_DeleteItem(handle, (HTREEITEM)item);
 }