diff win/dw.c @ 54:c4e1139d9872

Added new tree functions, and fixed a memory leak as well as use of invalid memory when a button destroys itself.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Sat, 17 Nov 2001 17:40:16 +0000
parents 0804483f6320
children b6948eac375a
line wrap: on
line diff
--- a/win/dw.c	Tue Nov 13 11:14:00 2001 +0000
+++ b/win/dw.c	Sat Nov 17 17:40:16 2001 +0000
@@ -1154,7 +1154,7 @@
 					break;
 				case WM_NOTIFY:
 					{
-						if(tmp->message == TVN_SELCHANGED)
+						if(tmp->message == TVN_SELCHANGED || tmp->message == NM_RCLICK)
 						{
 							NMTREEVIEW FAR *tem=(NMTREEVIEW FAR *)mp2;
 							char tmpbuf[100];
@@ -1163,20 +1163,58 @@
 
 							if(strnicmp(tmpbuf, WC_TREEVIEW, strlen(WC_TREEVIEW))==0)
 							{
-								if(tem->hdr.code == TVN_SELCHANGED)
+								if(tem->hdr.code == TVN_SELCHANGED && tmp->message == TVN_SELCHANGED)
 								{
 									if(tmp->window == tem->hdr.hwndFrom)
 									{
-										int (*treeselectfunc)(HWND, HWND, char *, void *) = tmp->signalfunction;
-                                        TVITEM tvi;
+										int (*treeselectfunc)(HWND, HWND, char *, void *, void *) = tmp->signalfunction;
+										TVITEM tvi;
+										void **ptrs;
 
 										tvi.mask = TVIF_HANDLE;
 										tvi.hItem = tem->itemNew.hItem;
 
 										TreeView_GetItem(tmp->window, &tvi);
 
-										result = treeselectfunc(tmp->window, (HWND)tem->itemNew.hItem, (char *)tvi.lParam, tmp->data);
-
+										ptrs = (void **)tvi.lParam;
+										if(ptrs)
+											result = treeselectfunc(tmp->window, (HWND)tem->itemNew.hItem, (char *)ptrs[0], (void *)ptrs[1], tmp->data);
+
+										tmp = NULL;
+									}
+								}
+								else if(tem->hdr.code == NM_RCLICK && tmp->message == NM_RCLICK)
+								{
+									if(tmp->window == tem->hdr.hwndFrom)
+									{
+										int (*containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction;
+										HTREEITEM hti;
+										TVITEM tvi;
+										TVHITTESTINFO thi;
+										void **ptrs = NULL;
+										LONG x, y;
+
+										dw_pointer_query_pos(&x, &y);
+
+										thi.pt.x = x;
+										thi.pt.y = y;
+
+										MapWindowPoints(HWND_DESKTOP, tmp->window, &thi.pt, 1);
+
+										hti = TreeView_HitTest(tmp->window, &thi);
+
+										if(hti)
+										{
+											tvi.mask = TVIF_HANDLE;
+											tvi.hItem = hti;
+
+											TreeView_GetItem(tmp->window, &tvi);
+											dw_tree_item_select(tmp->window, (HWND)hti);
+
+											ptrs = (void **)tvi.lParam;
+
+										}
+										containercontextfunc(tmp->window, ptrs ? (char *)ptrs[0] : NULL, x, y, tmp->data, ptrs ? ptrs[1] : NULL);
 										tmp = NULL;
 									}
 								}
@@ -1301,61 +1339,55 @@
 		break;
 	case WM_DESTROY:
 		/* Free memory before destroying */
-#if 0
-		/* Is this the right message? I seem to be
-		 * getting WM_DESTROY on windows that aren't
-		 * being destroyed.
-		 */
 		_free_window_memory(hWnd, 0);
 		EnumChildWindows(hWnd, _free_window_memory, 0);
-#endif
 		break;
-		case WM_CTLCOLORSTATIC:
-		case WM_CTLCOLORLISTBOX:
-		case WM_CTLCOLORBTN:
-		case WM_CTLCOLOREDIT:
-		case WM_CTLCOLORMSGBOX:
-		case WM_CTLCOLORSCROLLBAR:
-		case WM_CTLCOLORDLG:
+	case WM_CTLCOLORSTATIC:
+	case WM_CTLCOLORLISTBOX:
+	case WM_CTLCOLORBTN:
+	case WM_CTLCOLOREDIT:
+	case WM_CTLCOLORMSGBOX:
+	case WM_CTLCOLORSCROLLBAR:
+	case WM_CTLCOLORDLG:
+		{
+			ColorInfo *thiscinfo = (ColorInfo *)GetWindowLong((HWND)mp2, GWL_USERDATA);
+			if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1)
 			{
-				ColorInfo *thiscinfo = (ColorInfo *)GetWindowLong((HWND)mp2, GWL_USERDATA);
-				if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1)
+				if(thiscinfo->fore > -1 && thiscinfo->back > -1 &&
+				   thiscinfo->fore < 18 && thiscinfo->back < 18)
 				{
-					if(thiscinfo->fore > -1 && thiscinfo->back > -1 &&
-					   thiscinfo->fore < 18 && thiscinfo->back < 18)
-					{
-						SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore],
-												   _green[thiscinfo->fore],
+					SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore],
+											   _green[thiscinfo->fore],
 											   _blue[thiscinfo->fore]));
-						SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back],
-												 _green[thiscinfo->back],
-												 _blue[thiscinfo->back]));
-						DeleteObject(thiscinfo->hbrush);
-						thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back],
-																 _green[thiscinfo->back],
-																 _blue[thiscinfo->back]));
-						SelectObject((HDC)mp1, thiscinfo->hbrush);
-						return (LONG)thiscinfo->hbrush;
-					}
-					if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR && (thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR)
-					{
-						SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore),
-												   DW_GREEN_VALUE(thiscinfo->fore),
-												   DW_BLUE_VALUE(thiscinfo->fore)));
-						SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back),
+					SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back],
+											 _green[thiscinfo->back],
+											 _blue[thiscinfo->back]));
+					DeleteObject(thiscinfo->hbrush);
+					thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back],
+															 _green[thiscinfo->back],
+															 _blue[thiscinfo->back]));
+					SelectObject((HDC)mp1, thiscinfo->hbrush);
+					return (LONG)thiscinfo->hbrush;
+				}
+				if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR && (thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR)
+				{
+					SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore),
+											   DW_GREEN_VALUE(thiscinfo->fore),
+											   DW_BLUE_VALUE(thiscinfo->fore)));
+					SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back),
 												 DW_GREEN_VALUE(thiscinfo->back),
 												 DW_BLUE_VALUE(thiscinfo->back)));
-						DeleteObject(thiscinfo->hbrush);
-						thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back),
-																 DW_GREEN_VALUE(thiscinfo->back),
-																 DW_BLUE_VALUE(thiscinfo->back)));
-						SelectObject((HDC)mp1, thiscinfo->hbrush);
-						return (LONG)thiscinfo->hbrush;
-					}
+					DeleteObject(thiscinfo->hbrush);
+					thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back),
+															 DW_GREEN_VALUE(thiscinfo->back),
+															 DW_BLUE_VALUE(thiscinfo->back)));
+					SelectObject((HDC)mp1, thiscinfo->hbrush);
+					return (LONG)thiscinfo->hbrush;
 				}
-
 			}
-			break;
+
+		}
+		break;
 	}
 	if(result != -1)
 		return result;
@@ -1572,7 +1604,10 @@
 		switch( msg )
 		{
 		case WM_SETFOCUS:
-			_wndproc(hWnd, msg, mp1, mp2);
+            if(cinfo->combo)
+				_wndproc(cinfo->combo, msg, mp1, mp2);
+			else
+				_wndproc(hWnd, msg, mp1, mp2);
 			break;
 		case WM_CHAR:
 			if(LOWORD(mp1) == '\t')
@@ -1754,43 +1789,47 @@
 		break;
 	case WM_CONTEXTMENU:
 		{
-			LONG x,y;
-			LV_ITEM lvi;
-			int iItem;
-
-			iItem = ListView_GetNextItem(hWnd, -1, LVNI_FOCUSED);
-
-			if(iItem > -1)
-			{
-				lvi.iItem = iItem;
-				lvi.mask = LVIF_PARAM;
-
-				ListView_GetItem(hWnd, &lvi);
-			}
-			else
-				lvi.lParam = (LPARAM)NULL;
-
-			dw_pointer_query_pos(&x, &y);
-
+			SignalHandler *tmp = Root;
+
+			while(tmp)
 			{
-				SignalHandler *tmp = Root;
-
-				while(tmp)
+				if(tmp->message == NM_RCLICK && tmp->window == hWnd)
 				{
-					if(tmp->message == NM_RCLICK && tmp->window == hWnd)
+					int (*containercontextfunc)(HWND, char *, int, int, void *) = tmp->signalfunction;
+					LONG x,y;
+					LV_ITEM lvi;
+					int iItem;
+					LVHITTESTINFO lhi;
+
+					dw_pointer_query_pos(&x, &y);
+
+					lhi.pt.x = x;
+					lhi.pt.y = y;
+
+					MapWindowPoints(HWND_DESKTOP, tmp->window, &lhi.pt, 1);
+
+					iItem = ListView_HitTest(tmp->window, &lhi);
+
+					if(iItem > -1)
 					{
-						int (*containercontextfunc)(HWND, char *, int, int, void *) = tmp->signalfunction;
-
-						/* Seems to be having lParam as 1 which really sucks */
-						if(lvi.lParam < 100)
-							lvi.lParam = 0;
-
-						containercontextfunc(tmp->window, (char *)lvi.lParam, x, y, tmp->data);
-						tmp = NULL;
+						lvi.iItem = iItem;
+						lvi.mask = LVIF_PARAM;
+
+						ListView_GetItem(tmp->window, &lvi);
+						ListView_SetSelectionMark(tmp->window, iItem);
 					}
-					if(tmp)
-						tmp = tmp->next;
+					else
+						lvi.lParam = (LPARAM)NULL;
+
+					/* Seems to be having lParam as 1 which really sucks */
+					if(lvi.lParam < 100)
+						lvi.lParam = 0;
+
+					containercontextfunc(tmp->window, (char *)lvi.lParam, x, y, tmp->data);
+					tmp = NULL;
 				}
+				if(tmp)
+					tmp = tmp->next;
 			}
 		}
 		break;
@@ -2100,12 +2139,20 @@
 	static int bMouseOver = 0;
 	POINT point;
 	RECT rect;
+	WNDPROC pOldProc;
 
 	bubble = (BubbleButton *)GetWindowLong(hwnd, GWL_USERDATA);
 
 	if(!bubble)
 		return DefWindowProc(hwnd, msg, mp1, mp2);
 
+	/* We must save a pointer to the old
+	 * window procedure because if a signal
+	 * handler attached here destroys this
+	 * window it will then be invalid.
+	 */
+	pOldProc = bubble->pOldProc;
+
 	switch(msg)
 	{
 #ifndef NO_SIGNALS
@@ -2286,9 +2333,9 @@
 		break;
 	}
 
-	if(!bubble->pOldProc)
+	if(!pOldProc)
 		return DefWindowProc(hwnd, msg, mp1, mp2);
-	return CallWindowProc(bubble->pOldProc, hwnd, msg, mp1, mp2);
+	return CallWindowProc(pOldProc, hwnd, msg, mp1, mp2);
 }
 
 /* This function recalculates a notebook page for example
@@ -2650,9 +2697,62 @@
  */
 int dw_window_destroy(HWND handle)
 {
+	HWND parent = GetParent(handle);
+	Box *thisbox = (Box *)GetWindowLong(parent, GWL_USERDATA);
+
+	if(parent != HWND_DESKTOP && thisbox && thisbox->count)
+	{
+		int z, index = -1;
+		Item *tmpitem, *thisitem = thisbox->items;
+
+		for(z=0;z<thisbox->count;z++)
+		{
+			if(thisitem[z].hwnd == handle)
+				index = z;
+		}
+
+		if(index == -1)
+			return 0;
+
+		tmpitem = malloc(sizeof(Item)*(thisbox->count-1));
+
+		/* Copy all but the current entry to the new list */
+		for(z=0;z<index;z++)
+		{
+			tmpitem[z] = thisitem[z];
+		}
+		for(z=index+1;z<thisbox->count;z++)
+		{
+			tmpitem[z-1] = thisitem[z];
+		}
+
+		thisbox->items = tmpitem;
+		free(thisitem);
+		thisbox->count--;
+	}
 	return DestroyWindow(handle);
 }
 
+/* Causes entire window to be invalidated and redrawn.
+ * Parameters:
+ *           handle: Toplevel window handle to be redrawn.
+ */
+void dw_window_redraw(HWND handle)
+{
+	Box *mybox = (Box *)GetWindowLong(handle, GWL_USERDATA);
+
+	if(mybox)
+	{
+		RECT rect;
+
+		GetClientRect(handle, &rect);
+
+		ShowWindow(mybox->items[0].hwnd, SW_HIDE);
+		_do_resize(mybox, rect.right - rect.left, rect.bottom - rect.top);
+		ShowWindow(mybox->items[0].hwnd, SW_SHOW);
+	}
+}
+
 /*
  * Changes a window's parent to newparent.
  * Parameters:
@@ -3402,6 +3502,7 @@
 							NULL,
 							NULL);
 	ColorInfo *cinfo = (ColorInfo *)calloc(1, sizeof(ColorInfo));
+	ColorInfo *cinfo2 = (ColorInfo *)calloc(1, sizeof(ColorInfo));
 
 	if(!cinfo)
 	{
@@ -3409,10 +3510,10 @@
 		return NULL;
 	}
 
-	cinfo->fore = -1;
-	cinfo->back = -1;
-	cinfo->combo = tmp;
-	EnumChildWindows(tmp, _subclass_child, (LPARAM)cinfo);
+	cinfo2->fore = cinfo->fore = -1;
+	cinfo2->back = cinfo->back = -1;
+	cinfo2->combo = cinfo->combo = tmp;
+	EnumChildWindows(tmp, _subclass_child, (LPARAM)cinfo2);
 
 	SetWindowLong(tmp, GWL_USERDATA, (ULONG)cinfo);
 	dw_window_set_font(tmp, DefaultFont);
@@ -4700,16 +4801,21 @@
  *          title: The text title of the entry.
  *          icon: Handle to coresponding icon.
  *          parent: Parent handle or 0 if root.
- */
-HWND dw_tree_insert(HWND handle, char *title, unsigned long icon, HWND parent)
+ *          itemdata: Item specific data.
+ */
+HWND dw_tree_insert(HWND handle, 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)title;
+	tvi.lParam = (LONG)ptrs;
 	tvi.cchTextMax = strlen(title);
 	tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1);
 
@@ -4723,6 +4829,69 @@
 }
 
 /*
+ * Sets the text and icon of an item in a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ */
+void dw_tree_set(HWND handle, HWND item, char *title, unsigned long icon)
+{
+	TVITEM tvi;
+	void **ptrs;
+
+	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);
+}
+
+/*
+ * Sets the item data of a tree item.
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ *          itemdata: User defined data to be associated with item.
+ */
+void dw_tree_set_data(HWND handle, HWND item, void *itemdata)
+{
+	TVITEM tvi;
+	void **ptrs;
+
+	tvi.mask = TVIF_HANDLE;
+	tvi.hItem = (HTREEITEM)item;
+
+	TreeView_GetItem(handle, &tvi);
+
+	ptrs = (void **)tvi.lParam;
+	ptrs[1] = itemdata;
+}
+
+/*
+ * Sets this item as the active selection.
+ * Parameters:
+ *       handle: Handle to the tree window (widget) to be selected.
+ *       item: Handle to the item to be selected.
+ */
+void dw_tree_item_select(HWND handle, HWND item)
+{
+	TreeView_SelectItem(handle, (HTREEITEM)item);
+	SetFocus(handle);
+}
+
+/*
  * Removes all nodes from a tree.
  * Parameters:
  *       handle: Handle to the window (widget) to be cleared.
@@ -4733,6 +4902,28 @@
 }
 
 /*
+ * Expands a node on a tree.
+ * Parameters:
+ *       handle: Handle to the tree window (widget).
+ *       item: Handle to node to be expanded.
+ */
+void dw_tree_expand(HWND handle, HWND item)
+{
+	TreeView_Expand(handle, (HTREEITEM)item, TVE_EXPAND);
+}
+
+/*
+ * Collapses a node on a tree.
+ * Parameters:
+ *       handle: Handle to the tree window (widget).
+ *       item: Handle to node to be collapsed.
+ */
+void dw_tree_collapse(HWND handle, HWND item)
+{
+	TreeView_Expand(handle, (HTREEITEM)item, TVE_COLLAPSE);
+}
+
+/*
  * Removes a node from a tree.
  * Parameters:
  *       handle: Handle to the window (widget) to be cleared.