# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1006018816 0 # Node ID c4e1139d98720d6b7f8a0c2fc8665b0ef10d524f # Parent 8add9a616d0e185a6bf673e7da62b0e131feb124 Added new tree functions, and fixed a memory leak as well as use of invalid memory when a button destroys itself. diff -r 8add9a616d0e -r c4e1139d9872 dw.def --- a/dw.def Tue Nov 13 11:14:00 2001 +0000 +++ b/dw.def Sat Nov 17 17:40:16 2001 +0000 @@ -60,6 +60,7 @@ dw_window_raise @76 dw_window_lower @77 dw_window_click_default @78 + dw_window_redraw @79 dw_bitmap_new @80 @@ -202,6 +203,11 @@ dw_tree_insert @371 dw_tree_clear @372 dw_tree_delete @373 + dw_tree_set @374 + dw_tree_expand @375 + dw_tree_collapse @376 + dw_tree_item_select @377 + dw_tree_set_data @378 dw_font_text_extents @380 diff -r 8add9a616d0e -r c4e1139d9872 dw.h --- a/dw.h Tue Nov 13 11:14:00 2001 +0000 +++ b/dw.h Sat Nov 17 17:40:16 2001 +0000 @@ -594,6 +594,7 @@ int dw_window_raise(HWND handle); int dw_window_lower(HWND handle); int dw_window_destroy(HWND handle); +void dw_window_redraw(HWND handle); int dw_window_set_font(HWND handle, char *fontname); int dw_window_set_color(HWND handle, unsigned long fore, unsigned long back); HWND dw_window_new(HWND hwndOwner, char *title, unsigned long flStyle); @@ -664,9 +665,14 @@ long dw_spinbutton_query(HWND handle); 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); +HWND dw_tree_insert(HWND handle, 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); +void dw_tree_expand(HWND handle, HWND item); +void dw_tree_collapse(HWND handle, HWND item); +void dw_tree_item_select(HWND handle, HWND item); +void dw_tree_set_data(HWND handle, HWND item, void *itemdata); int dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator); unsigned long dw_icon_load(unsigned long module, unsigned long id); void dw_icon_free(unsigned long handle); diff -r 8add9a616d0e -r c4e1139d9872 dww.def --- a/dww.def Tue Nov 13 11:14:00 2001 +0000 +++ b/dww.def Sat Nov 17 17:40:16 2001 +0000 @@ -57,6 +57,7 @@ dw_window_raise @76 dw_window_lower @77 dw_window_click_default @78 + dw_window_redraw @79 dw_bitmap_new @80 @@ -199,6 +200,11 @@ dw_tree_insert @371 dw_tree_clear @372 dw_tree_delete @373 + dw_tree_set @374 + dw_tree_expand @375 + dw_tree_collapse @376 + dw_tree_item_select @377 + dw_tree_set_data @378 dw_font_text_extents @380 diff -r 8add9a616d0e -r c4e1139d9872 gtk/dw.c --- a/gtk/dw.c Tue Nov 13 11:14:00 2001 +0000 +++ b/gtk/dw.c Sat Nov 17 17:40:16 2001 +0000 @@ -90,6 +90,7 @@ void _expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data); void _set_focus_event(GtkWindow *window, GtkWidget *widget, gpointer data); void _tree_select_event(GtkTree *tree, GtkWidget *child, gpointer data); +void _tree_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data); void msleep(long period); @@ -108,7 +109,7 @@ } SignalHandler; -#define SIGNALMAX 14 +#define SIGNALMAX 15 /* A list of signal forwarders, to account for paramater differences. */ SignalList SignalTranslate[SIGNALMAX] = { @@ -123,6 +124,7 @@ { _generic_event, "clicked" }, { _container_select_event, "container-select" }, { _container_context_event, "container-context" }, + { _tree_context_event, "tree-context" }, { _item_select_event, "item-select" }, { _tree_select_event, "tree-select" }, { _set_focus_event, "set-focus" } @@ -235,7 +237,7 @@ { int (*closefunc)(HWND, void *) = work->func; - closefunc(widget, data); + closefunc(widget, work->data); } return TRUE; } @@ -367,16 +369,53 @@ } } +void _tree_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + if(event->button == 3) + { + void (*contextfunc)(HWND, char *, int, int, void *, void *) = work->func; + char *text = (char *)gtk_object_get_data(GTK_OBJECT(widget), "text"); + void *itemdata = (void *)gtk_object_get_data(GTK_OBJECT(widget), "itemdata"); + + if(widget != work->window) + { + GtkWidget *tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(work->window)); + + if(tree && GTK_IS_TREE(tree)) + { + GtkWidget *lastselect = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tree), "lastselect"); + + if(lastselect && GTK_IS_TREE_ITEM(lastselect)) + { + text = (char *)gtk_object_get_data(GTK_OBJECT(lastselect), "text"); + itemdata = (void *)gtk_object_get_data(GTK_OBJECT(lastselect), "itemdata"); + } + } + } + + contextfunc(work->window, text, event->x, event->y, work->data, itemdata); + } + } +} + void _tree_select_event(GtkTree *tree, GtkWidget *child, gpointer data) { SignalHandler *work = (SignalHandler *)data; if(work) { - void (*treeselectfunc)(HWND, HWND, char *, void *) = work->func; + void (*treeselectfunc)(HWND, HWND, char *, void *, void *) = work->func; char *text = (char *)gtk_object_get_data(GTK_OBJECT(child), "text"); - - treeselectfunc(work->window, child, text, work->data); + void *itemdata = (char *)gtk_object_get_data(GTK_OBJECT(child), "itemdata"); + GtkWidget *treeroot = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(child), "tree"); + + if(treeroot && GTK_IS_TREE(treeroot)) + gtk_object_set_data(GTK_OBJECT(treeroot), "lastselect", (gpointer)child); + treeselectfunc(work->window, child, text, itemdata, work->data); } } @@ -974,6 +1013,14 @@ return 0; } +/* Causes entire window to be invalidated and redrawn. + * Parameters: + * handle: Toplevel window handle to be redrawn. + */ +void dw_window_redraw(HWND handle) +{ +} + /* * Changes a window's parent to newparent. * Parameters: @@ -2692,8 +2739,9 @@ * 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) +HWND dw_tree_insert(HWND handle, char *title, unsigned long icon, HWND parent, void *itemdata) { GtkWidget *item, *tree, *subtree, *label, *hbox, *pixmap; GdkPixmap *gdkpix; @@ -2710,7 +2758,10 @@ item = gtk_tree_item_new(); label = gtk_label_new(title); gtk_object_set_data(GTK_OBJECT(item), "text", (gpointer)strdup(title)); + gtk_object_set_data(GTK_OBJECT(item), "itemdata", (gpointer)itemdata); + gtk_object_set_data(GTK_OBJECT(item), "tree", (gpointer)tree); hbox = gtk_hbox_new(FALSE, 2); + gtk_object_set_data(GTK_OBJECT(item), "hbox", (gpointer)hbox); gdkpix = _find_pixmap(&gdkbmp, icon, hbox); pixmap = gtk_pixmap_new(gdkpix, gdkbmp); gtk_container_add(GTK_CONTAINER(item), hbox); @@ -2733,22 +2784,106 @@ 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_tree_append(GTK_TREE(subtree), item); } else 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); DW_MUTEX_UNLOCK; return item; } /* + * 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) +{ + GtkWidget *label, *hbox, *pixmap; + GdkPixmap *gdkpix; + GdkBitmap *gdkbmp; + char *oldtext; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + oldtext = (char *)gtk_object_get_data(GTK_OBJECT(item), "text"); + if(oldtext) + free(oldtext); + label = gtk_label_new(title); + gtk_object_set_data(GTK_OBJECT(item), "text", (gpointer)strdup(title)); + hbox = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(item), "hbox"); + gtk_widget_destroy(hbox); + hbox = gtk_hbox_new(FALSE, 2); + gtk_object_set_data(GTK_OBJECT(item), "hbox", (gpointer)hbox); + gdkpix = _find_pixmap(&gdkbmp, icon, hbox); + pixmap = gtk_pixmap_new(gdkpix, gdkbmp); + gtk_container_add(GTK_CONTAINER(item), 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); + DW_MUTEX_UNLOCK; +} + +/* + * 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) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_object_set_data(GTK_OBJECT(item), "itemdata", (gpointer)itemdata); + DW_MUTEX_UNLOCK; +} + +/* + * 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) +{ + GtkWidget *lastselect; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + lastselect = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "lastselect"); + if(lastselect && GTK_IS_TREE_ITEM(lastselect)) + gtk_tree_item_deselect(GTK_TREE_ITEM(lastselect)); + gtk_tree_item_select(GTK_TREE_ITEM(item)); + gtk_object_set_data(GTK_OBJECT(handle), "lastselect", (gpointer)item); + DW_MUTEX_UNLOCK; +} + +/* * Removes all nodes from a tree. * Parameters: * handle: Handle to the window (widget) to be cleared. @@ -2770,6 +2905,38 @@ } /* + * 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) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_TREE_ITEM(item)) + gtk_tree_item_expand(GTK_TREE_ITEM(item)); + DW_MUTEX_UNLOCK; +} + +/* + * 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) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_TREE_ITEM(item)) + gtk_tree_item_collapse(GTK_TREE_ITEM(item)); + DW_MUTEX_UNLOCK; +} + +/* * Removes a node from a tree. * Parameters: * handle: Handle to the window (widget) to be cleared. @@ -2777,7 +2944,7 @@ */ void dw_tree_delete(HWND handle, HWND item) { - GtkWidget *tree; + GtkWidget *tree, *lastselect; int _locked_by_me = FALSE; DW_MUTEX_LOCK; @@ -2787,7 +2954,13 @@ DW_MUTEX_UNLOCK; return; } + + lastselect = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "lastselect"); + if(lastselect == item) + gtk_object_set_data(GTK_OBJECT(handle), "lastselect", NULL); + gtk_tree_remove_item(GTK_TREE(tree), item); + gtk_widget_destroy(item); DW_MUTEX_UNLOCK; } @@ -5200,6 +5373,21 @@ thisname = "button_press_event"; thisfunc = _findsigfunc("container-context"); } + else if(GTK_IS_TREE(thiswindow) && strcmp(signame, "container-context") == 0) + { + thisfunc = _findsigfunc("tree-context"); + + work->window = window; + work->data = data; + work->func = sigfunc; + + gtk_object_set_data(GTK_OBJECT(thiswindow), "container-context-func", (gpointer)thisfunc); + gtk_object_set_data(GTK_OBJECT(thiswindow), "container-context-data", (gpointer)work); + gtk_signal_connect(GTK_OBJECT(thiswindow), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), work); + gtk_signal_connect(GTK_OBJECT(window), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), work); + DW_MUTEX_UNLOCK; + return; + } else if(GTK_IS_CLIST(thiswindow) && strcmp(signame, "container-select") == 0) { thisname = "button_press_event"; diff -r 8add9a616d0e -r c4e1139d9872 os2/dw.c --- a/os2/dw.c Tue Nov 13 11:14:00 2001 +0000 +++ b/os2/dw.c Sat Nov 17 17:40:16 2001 +0000 @@ -106,7 +106,7 @@ { CN_ENTER, "container-select" }, { CN_CONTEXTMENU, "container-context" }, { LN_SELECT, "item-select" }, - { WM_USER+1, "tree-select" }, + { CN_EMPHASIS, "tree-select" }, { WM_SETFOCUS, "set-focus" } }; @@ -153,6 +153,15 @@ } #endif +typedef struct _CNRITEM +{ + MINIRECORDCORE rc; + HPOINTER hptrIcon; + PVOID user; + +} CNRITEM, *PCNRITEM; + + /* This function changes the owner of buttons in to the * dynamicwindows handle to fix a problem in notebooks. */ @@ -186,24 +195,22 @@ { HENUM henum; HWND child; + void *ptr = (void *)WinQueryWindowPtr(handle, QWP_USER); #ifndef NO_SIGNALS dw_signal_disconnect_by_window(handle); #endif + if(ptr) + { + WinSetWindowPtr(handle, QWP_USER, 0); + free(ptr); + } + henum = WinBeginEnumWindows(handle); while((child = WinGetNextWindow(henum)) != NULLHANDLE) - { - void *ptr = (void *)WinQueryWindowPtr(handle, QWP_USER); - - if(ptr) - { - WinSetWindowPtr(handle, QWP_USER, 0); - free(ptr); - } - _free_window_memory(child); - } + WinEndEnumWindows(henum); return; } @@ -1579,30 +1586,71 @@ break; case CN_CONTEXTMENU: { - int (*containercontextfunc)(HWND, char *, int, int, void *) = (int (*)(HWND, char *, int, int, void *))tmp->signalfunction; + int (*containercontextfunc)(HWND, char *, int, int, void *, void *) = (int (*)(HWND, char *, int, int, void *, void *))tmp->signalfunction; int id = SHORT1FROMMP(mp1); HWND conthwnd = dw_window_from_id(hWnd, id); char *text = NULL; + void *user = NULL; LONG x,y; if(mp2) { - PRECORDCORE pre; - - pre = (PRECORDCORE)mp2; - text = pre->pszIcon; + PCNRITEM pci; + + pci = (PCNRITEM)mp2; + + text = pci->rc.pszIcon; + user = pci->user; } - dw_pointer_query_pos(&x, &y); if(tmp->window == conthwnd) { - result = containercontextfunc(tmp->window, text, x, y, tmp->data); + if(mp2) + { + NOTIFYRECORDEMPHASIS pre; + + dw_tree_item_select(tmp->window, (HWND)mp2); + pre.pRecord = mp2; + pre.fEmphasisMask = CRA_CURSORED; + pre.hwndCnr = tmp->window; + _run_event(hWnd, WM_CONTROL, MPFROM2SHORT(0, CN_EMPHASIS), (MPARAM)&pre); + } + result = containercontextfunc(tmp->window, text, x, y, tmp->data, user); tmp = NULL; } } break; + case CN_EMPHASIS: + { + PNOTIFYRECORDEMPHASIS pre = (PNOTIFYRECORDEMPHASIS)mp2; + static int emph_recurse = 0; + + if(!emph_recurse) + { + emph_recurse = 1; + + if(mp2) + { + if(tmp->window == pre->hwndCnr) + { + PCNRITEM pci = (PCNRITEM)pre->pRecord; + + if(pci && pre->fEmphasisMask & CRA_CURSORED) + { + int (*treeselectfunc)(HWND, HWND, char *, void *, void *) = (int (*)(HWND, HWND, char *, void *, void *))tmp->signalfunction; + + result = treeselectfunc(tmp->window, (HWND)pci, pci->rc.pszIcon, pci->user, tmp->data); + + tmp = NULL; + } + } + } + emph_recurse = 0; + } + } + break; case LN_SELECT: { int (*listboxselectfunc)(HWND, int, void *) = (int (*)(HWND, int, void *))tmp->signalfunction; @@ -1650,37 +1698,6 @@ } } - if(tmp && origmsg == WM_BUTTON1DOWN) - { - if(tmp->message == WM_USER+1) - { - if(tmp->window == hWnd) - { - QUERYRECFROMRECT rc; - POINTS pts = (*((POINTS*)&mp1)); - RECORDCORE *prc; - - rc.cb = sizeof(QUERYRECFROMRECT); - rc.rect.xLeft = pts.x; - rc.rect.xRight = pts.x + 1; - rc.rect.yTop = pts.y; - rc.rect.yBottom = pts.y - 1; - rc.fsSearch = CMA_PARTIAL | CMA_ITEMORDER; - - prc = (RECORDCORE *)WinSendMsg(hWnd, CM_QUERYRECORDFROMRECT, (MPARAM)CMA_FIRST, MPFROMP(&rc)); - - if(prc) - { - int (*treeselectfunc)(HWND, HWND, char *, void *) = (int (*)(HWND, HWND, char *, void *))tmp->signalfunction; - - result = treeselectfunc(tmp->window, (HWND)prc, prc->pszIcon, tmp->data); - - tmp = NULL; - } - } - } - } - if(tmp) tmp = tmp->next; @@ -2222,12 +2239,15 @@ MRESULT EXPENTRY _BtProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { BubbleButton *bubble; + PFNWP oldproc; bubble = (BubbleButton *)WinQueryWindowPtr(hwnd, QWL_USER); if(!bubble) return WinDefWindowProc(hwnd, msg, mp1, mp2); + oldproc = bubble->pOldProc; + switch(msg) { #ifndef NO_SIGNALS @@ -2408,9 +2428,9 @@ break; } - if(!bubble->pOldProc) + if(!oldproc) return WinDefWindowProc(hwnd, msg, mp1, mp2); - return bubble->pOldProc(hwnd, msg, mp1, mp2); + return oldproc(hwnd, msg, mp1, mp2); } MRESULT EXPENTRY _RendProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) @@ -2731,9 +2751,67 @@ */ int dw_window_destroy(HWND handle) { + HWND parent = WinQueryWindow(handle, QW_PARENT); + Box *thisbox = WinQueryWindowPtr(parent, QWP_USER); + + if(!handle) + return -1; + + if(parent != HWND_DESKTOP && thisbox && thisbox->count) + { + int z, index = -1; + Item *tmpitem, *thisitem = thisbox->items; + + for(z=0;zcount;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;zcount;z++) + { + tmpitem[z-1] = thisitem[z]; + } + + thisbox->items = tmpitem; + free(thisitem); + thisbox->count--; + } + _free_window_memory(handle); return WinDestroyWindow(handle); } +/* Causes entire window to be invalidated and redrawn. + * Parameters: + * handle: Toplevel window handle to be redrawn. + */ +void dw_window_redraw(HWND handle) +{ + HWND window = WinWindowFromID(handle, FID_CLIENT); + Box *mybox = (Box *)WinQueryWindowPtr(window, QWP_USER); + + if(window && mybox) + { + unsigned long width, height; + + dw_window_get_pos_size(window, NULL, NULL, &width, &height); + + WinShowWindow(mybox->items[0].hwnd, FALSE); + _do_resize(mybox, width, height); + WinShowWindow(mybox->items[0].hwnd, TRUE); + } +} + /* * Changes a window's parent to newparent. * Parameters: @@ -4572,13 +4650,6 @@ WinSendMsg(handle,BM_SETCHECK,MPFROMSHORT(value),0); } -typedef struct _CNRITEM -{ - MINIRECORDCORE rc; - HPOINTER hptrIcon; - -} CNRITEM, *PCNRITEM; - /* * Inserts an item into a tree window (widget). * Parameters: @@ -4586,8 +4657,9 @@ * 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) { ULONG cbExtra; PCNRITEM pci; @@ -4610,6 +4682,7 @@ pci->rc.hptrIcon = icon; pci->hptrIcon = icon; + pci->user = itemdata; memset(&ri, 0, sizeof(RECORDINSERT)); @@ -4632,6 +4705,65 @@ } /* + * 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) +{ + PCNRITEM pci = (PCNRITEM)item; + + if(!pci) + return; + + pci->rc.pszIcon = title; + pci->rc.hptrIcon = icon; + + pci->hptrIcon = icon; + + WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pci, MPFROM2SHORT(1, CMA_TEXTCHANGED)); +} + +/* + * 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) +{ + PCNRITEM pci = (PCNRITEM)item; + + if(!pci) + return; + + pci->user = 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) +{ + PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); + + while(pCore) + { + if(pCore->flRecordAttr & CRA_SELECTED) + WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)pCore, MPFROM2SHORT(FALSE, CRA_SELECTED | CRA_CURSORED)); + pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)); + } + WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)item, MPFROM2SHORT(TRUE, CRA_SELECTED | CRA_CURSORED)); +} + +/* * Removes all nodes from a tree. * Parameters: * handle: Handle to the window (widget) to be cleared. @@ -4642,6 +4774,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) +{ + WinSendMsg(handle, CM_EXPANDTREE, MPFROMP(item), 0); +} + +/* + * 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) +{ + WinSendMsg(handle, CM_COLLAPSETREE, MPFROMP(item), 0); +} + +/* * Removes a node from a tree. * Parameters: * handle: Handle to the window (widget) to be cleared. diff -r 8add9a616d0e -r c4e1139d9872 win/dw.c --- 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;zcount;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;zcount;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.