Mercurial > dwindows
diff gtk/dw.c @ 3:67a643a734d9
Import
author | ktk@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Tue, 03 Jul 2001 07:50:39 +0000 |
parents | |
children | 005fa766e8c2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gtk/dw.c Tue Jul 03 07:50:39 2001 +0000 @@ -0,0 +1,4251 @@ +/* + * Dynamic Windows: + * A GTK like implementation of the PM GUI + * GTK forwarder module for portabilty. + * + * (C) 2000,2001 Brian Smith <dbsoft@technologist.com> + * + */ +#include "dw.h" +#include <string.h> +#include <stdlib.h> +#include <sys/utsname.h> +#include <stdarg.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <sys/time.h> +#include "config.h" +#ifdef USE_IMLIB +#include <gdk_imlib.h> +#endif + +/* These are used for resource management */ +#if defined(DW_RESOURCES) && !defined(BUILD_DLL) +extern DWResources _resources; +#endif + +char monthlist[][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec" }; +GdkColor _colors[] = +{ + { 0, 0x0000, 0x0000, 0x0000 }, /* 0 black */ + { 0, 0xbbbb, 0x0000, 0x0000 }, /* 1 red */ + { 0, 0x0000, 0xbbbb, 0x0000 }, /* 2 green */ + { 0, 0xaaaa, 0xaaaa, 0x0000 }, /* 3 yellow */ + { 0, 0x0000, 0x0000, 0xcccc }, /* 4 blue */ + { 0, 0xbbbb, 0x0000, 0xbbbb }, /* 5 magenta */ + { 0, 0x0000, 0xbbbb, 0xbbbb }, /* 6 cyan */ + { 0, 0xaaaa, 0xaaaa, 0xaaaa }, /* 7 white */ + { 0, 0x7777, 0x7777, 0x7777 }, /* 8 grey */ + { 0, 0xffff, 0x0000, 0x0000 }, /* 9 bright red */ + { 0, 0x0000, 0xffff, 0x0000 }, /* 10 bright green */ + { 0, 0xeeee, 0xeeee, 0x0000 }, /* 11 bright yellow */ + { 0, 0x0000, 0x0000, 0xffff }, /* 12 bright blue */ + { 0, 0xffff, 0x0000, 0xffff }, /* 13 bright magenta */ + { 0, 0x0000, 0xeeee, 0xeeee }, /* 14 bright cyan */ + { 0, 0xffff, 0xffff, 0xffff }, /* 15 bright white */ +}; + +GdkColor _foreground = { 0, 0x0000, 0x0000, 0x0000 }; +GdkColor _background = { 0, 0xaaaa, 0xaaaa, 0xaaaa }; + +char *_dw_browse_file = NULL; +int _dw_file_active = 0, _dw_file_ready = 0; +pthread_t _dw_thread = (pthread_t)-1; +int _dw_mutex_locked = FALSE; + +#define DW_MUTEX_LOCK { if(pthread_self() != _dw_thread && _dw_mutex_locked == FALSE) { gdk_threads_enter(); _dw_mutex_locked = TRUE; _locked_by_me = TRUE; } } +#define DW_MUTEX_UNLOCK { if(pthread_self() != _dw_thread && _locked_by_me == TRUE) { gdk_threads_leave(); _dw_mutex_locked = FALSE; _locked_by_me = FALSE; } } + +/* Currently the non Imlib method does not work */ +#ifndef USE_IMLIB +#define USE_IMLIB +#endif + +GdkColormap *_dw_cmap = NULL; + +/* Signal forwarder prototypes */ +gint _button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data); +gint _button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data); +gint _motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data); +gint _delete_event(GtkWidget *widget, GdkEvent *event, gpointer data); +gint _key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data); +gint _generic_event(GtkWidget *widget, gpointer data); +gint _configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data); +void _activate_event(GtkWidget *widget, gpointer data); +void _container_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data); +void _container_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data); +void _item_select_event(GtkWidget *widget, GtkWidget *child, gpointer data); +void _expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data); + +typedef struct +{ + void *func; + char name[30]; + +} SignalList; + +typedef struct +{ + HWND window; + void *func; + gpointer data; + +} SignalHandler; + +#define SIGNALMAX 12 + +/* A list of signal forwarders, to account for paramater differences. */ +SignalList SignalTranslate[SIGNALMAX] = { + { _configure_event, "configure_event" }, + { _key_press_event, "key_press_event" }, + { _button_press_event, "button_press_event" }, + { _button_release_event, "button_release_event" }, + { _motion_notify_event, "motion_notify_event" }, + { _delete_event, "delete_event" }, + { _expose_event, "expose_event" }, + { _activate_event, "activate" }, + { _generic_event, "clicked" }, + { _container_select_event, "container-select" }, + { _container_context_event, "container-context" }, + { _item_select_event, "item-select" } +}; + +/* Finds the translation function for a given signal name */ +void *_findsigfunc(char *signame) +{ + int z; + + for(z=0;z<SIGNALMAX;z++) + { + if(strcasecmp(signame, SignalTranslate[z].name) == 0) + return SignalTranslate[z].func; + } + return NULL; +} + +gint _button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + int (*buttonfunc)(HWND, int, int, int, void *) = work->func; + int mybutton = event->button; + + if(event->button == 3) + mybutton = 2; + else if(event->button == 2) + mybutton = 3; + + buttonfunc(widget, event->x, event->y, mybutton, work->data); + } + return TRUE; +} + +gint _button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + int (*buttonfunc)(HWND, int, int, int, void *) = work->func; + int mybutton = event->button; + + if(event->button == 3) + mybutton = 2; + else if(event->button == 2) + mybutton = 3; + + buttonfunc(widget, event->x, event->y, mybutton, work->data); + } + return TRUE; +} + +gint _motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + int (*motionfunc)(HWND, int, int, int, void *) = work->func; + int keys = 0, x, y; + GdkModifierType state; + + if (event->is_hint) + gdk_window_get_pointer (event->window, &x, &y, &state); + else + { + x = event->x; + y = event->y; + state = event->state; + } + + if (state & GDK_BUTTON1_MASK) + keys = DW_BUTTON1_MASK; + if (state & GDK_BUTTON3_MASK) + keys |= DW_BUTTON2_MASK; + if (state & GDK_BUTTON2_MASK) + keys |= DW_BUTTON3_MASK; + + motionfunc(widget, x, y, keys, work->data); + } + return TRUE; +} + +gint _delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + int (*closefunc)(HWND, void *) = work->func; + + closefunc(widget, data); + } + return TRUE; +} + +gint _key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + int (*keypressfunc)(HWND, int, void *) = work->func; + + keypressfunc(widget, *event->string, work->data); + } + return TRUE; +} + +gint _generic_event(GtkWidget *widget, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + int (*genericfunc)(HWND, void *) = work->func; + + genericfunc(widget, work->data); + } + return TRUE; +} + +void _activate_event(GtkWidget *widget, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + void (*activatefunc)(HWND, void *) = work->func; + + activatefunc(work->window, work->data); + } + return; +} + +gint _configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + int (*sizefunc)(HWND, int, int, void *) = work->func; + + sizefunc(widget, event->width, event->height, work->data); + } + return TRUE; +} + +void _expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + DWExpose exp; + int (*exposefunc)(HWND, DWExpose *, void *) = work->func; + + exp.x = event->area.x; + exp.y = event->area.y; + exp.width = event->area.width; + exp.height = event->area.height; + exposefunc(widget, &exp, work->data); + } +} + +void _item_select_event(GtkWidget *widget, GtkWidget *child, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + int (*selectfunc)(HWND, int, void *) = work->func; + GList *list; + int item = 0; + + if(GTK_IS_COMBO(work->window)) + list = GTK_LIST(GTK_COMBO(work->window)->list)->children; + else if(GTK_IS_LIST(widget)) + list = GTK_LIST(widget)->children; + else + return; + + while(list) + { + if(list->data == (gpointer)child) + { + gtk_object_set_data(GTK_OBJECT(work->window), "item", (gpointer)item); + selectfunc(work->window, item, work->data); + break; + } + item++; + list = list->next; + } + } +} + +void _container_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 *) = work->func; + char *text; + int row, col; + + gtk_clist_get_selection_info(GTK_CLIST(widget), event->x, event->y, &row, &col); + + text = (char *)gtk_clist_get_row_data(GTK_CLIST(widget), row); + contextfunc(work->window, text, event->x, event->y, work->data); + } + } +} + +void _container_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data) +{ + SignalHandler *work = (SignalHandler *)data; + + if(work) + { + if(event->button == 1 && event->type == GDK_2BUTTON_PRESS) + { + void (*contextfunc)(HWND, char *, void *) = work->func; + char *text; + int row, col; + + gtk_clist_get_selection_info(GTK_CLIST(widget), event->x, event->y, &row, &col); + + text = (char *)gtk_clist_get_row_data(GTK_CLIST(widget), row); + contextfunc(work->window, text, work->data); + } + } +} + +void _select_row(GtkWidget *widget, gint row, gint column, GdkEventButton *event, gpointer data) +{ + GList *tmp = (GList *)gtk_object_get_data(GTK_OBJECT(widget), "selectlist"); + char *rowdata = gtk_clist_get_row_data(GTK_CLIST(widget), row); + + if(rowdata) + { + tmp = g_list_append(tmp, rowdata); + gtk_object_set_data(GTK_OBJECT(widget), "selectlist", tmp); + } + +} + +void _unselect_row(GtkWidget *widget, gint row, gint column, GdkEventButton *event, gpointer data) +{ + GList *tmp = (GList *)gtk_object_get_data(GTK_OBJECT(widget), "selectlist"); + char *rowdata = gtk_clist_get_row_data(GTK_CLIST(widget), row); + + if(rowdata) + { + g_list_remove(tmp, rowdata); + gtk_object_set_data(GTK_OBJECT(widget), "selectlist", tmp); + } +} + +GdkPixmap *_find_pixmap(GdkBitmap **bitmap, long id, HWND handle) +{ + char *data = NULL; + int z; + + for(z=0;z<_resources.resource_max;z++) + { + if(_resources.resource_id[z] == id) + { + data = _resources.resource_data[z]; + break; + } + } + + if(data) + { + GdkPixmap *icon_pixmap = NULL; +#ifndef USE_IMLIB + GtkStyle *iconstyle; + + /* hmmm why do we need the handle here? */ + iconstyle = gtk_widget_get_style(handle); + if (!icon_pixmap) + icon_pixmap = gdk_pixmap_create_from_xpm_d(handle->window, bitmap, &iconstyle->bg[GTK_STATE_NORMAL], &data); +#else + gdk_imlib_data_to_pixmap((char **)data, &icon_pixmap, bitmap); +#endif + return icon_pixmap; + } + return NULL; +} + +void _size_allocate(GtkWindow *window) +{ + XSizeHints sizehints; + + sizehints.base_width = 1; + sizehints.base_height = 1; + sizehints.width_inc = 1; + sizehints.height_inc = 1; + sizehints.min_width = 8; + sizehints.min_height = 8; + + sizehints.flags = (PBaseSize|PMinSize|PResizeInc); + + XSetWMNormalHints (GDK_DISPLAY(), + GDK_WINDOW_XWINDOW (GTK_WIDGET (window)->window), + &sizehints); + gdk_flush (); +} + +/* + * Initializes the Dynamic Windows engine. + * Parameters: + * newthread: True if this is the only thread. + * False if there is already a message loop running. + */ +int dw_int_init(DWResources *res, int newthread) +{ + int z; + + if(res) + { + _resources.resource_max = res->resource_max; + _resources.resource_id = res->resource_id; + _resources.resource_data = res->resource_data; + } + gtk_set_locale(); + g_thread_init(NULL); + gtk_init(0, NULL); +#ifdef USE_IMLIB + gdk_imlib_init(); +#endif + /* Add colors to the system colormap */ + _dw_cmap = gdk_colormap_get_system(); + for(z=0;z<16;z++) + gdk_color_alloc(_dw_cmap, &_colors[z]); + return TRUE; +} + +/* + * Runs a message loop for Dynamic Windows. + * Parameters: + * currenthab: The handle to the current anchor block + * or NULL if this DW is handling the message loop. + * func: Function pointer to the message filter function. + */ +void dw_main(HAB currenthab, void *func) +{ + _dw_thread = pthread_self(); + gdk_threads_enter(); + gtk_main(); + gdk_threads_leave(); +} + +/* + * Free's memory allocated by dynamic windows. + * Parameters: + * ptr: Pointer to dynamic windows allocated + * memory to be free()'d. + */ +void dw_free(void *ptr) +{ + free(ptr); +} + +/* + * Allocates and initializes a dialog struct. + * Parameters: + * data: User defined data to be passed to functions. + */ +DWDialog *dw_dialog_new(void *data) +{ + DWDialog *tmp = malloc(sizeof(DWDialog)); + + tmp->eve = dw_event_new(); + dw_event_reset(tmp->eve); + tmp->data = data; + tmp->done = FALSE; + tmp->result = NULL; + + return tmp; +} + +/* + * Accepts a dialog struct and returns the given data to the + * initial called of dw_dialog_wait(). + * Parameters: + * dialog: Pointer to a dialog struct aquired by dw_dialog_new). + * result: Data to be returned by dw_dialog_wait(). + */ +int dw_dialog_dismiss(DWDialog *dialog, void *result) +{ + dialog->result = result; + if(pthread_self() == _dw_thread) + gtk_main_quit(); + else + dw_event_post(dialog->eve); + dialog->done = TRUE; + return 0; +} + +/* + * Accepts a dialog struct waits for dw_dialog_dismiss() to be + * called by a signal handler with the given dialog struct. + * Parameters: + * dialog: Pointer to a dialog struct aquired by dw_dialog_new). + */ +void *dw_dialog_wait(DWDialog *dialog) +{ + void *tmp; + + if(pthread_self() == _dw_thread) + gtk_main(); + else + dw_event_wait(dialog->eve, -1); + + dw_event_close(&dialog->eve); + tmp = dialog->result; + free(dialog); + return tmp; +} + +void _delete(GtkWidget *widget, GtkWidget *event, gpointer param) +{ + gtk_widget_destroy(GTK_WIDGET(param)); +} + +void _delete2(GtkWidget *widget, gpointer param) +{ + gtk_widget_destroy(GTK_WIDGET(param)); +} + + +/* + * Displays a Message Box with given text and title.. + * Parameters: + * title: The title of the message box. + * format: printf style format string. + * ...: Additional variables for use in the format. + */ +int dw_messagebox(char *title, char *format, ...) +{ + va_list args; + char outbuf[256]; + GtkWidget *dialog, + *button, + *label; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + va_start(args, format); + vsprintf(outbuf, format, args); + va_end(args); + + dialog = gtk_dialog_new(); + + gtk_window_set_title(GTK_WINDOW(dialog), title); + + button = gtk_button_new_with_label("Ok"); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(_delete2), (gpointer)dialog); + gtk_signal_connect(GTK_OBJECT(dialog), "delete_event", GTK_SIGNAL_FUNC(_delete), (gpointer)dialog); + + label = gtk_label_new(outbuf); + gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), 20); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0); + gtk_widget_show(label); + + gtk_widget_show(dialog); + + DW_MUTEX_UNLOCK; + + return strlen(outbuf); +} + +/* + * Displays a Message Box with given text and title.. + * Parameters: + * title: The title of the message box. + * text: The text to display in the box. + * Returns: + * True if YES False of NO. + */ +int dw_yesno(char *title, char *text) +{ + return FALSE; +} + +/* + * Makes the window visible. + * Parameters: + * handle: The window handle to make visible. + */ +int dw_window_show(HWND handle) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_widget_show(handle); + DW_MUTEX_UNLOCK; + return 0; +} + +/* + * Makes the window invisible. + * Parameters: + * handle: The window handle to make visible. + */ +int dw_window_hide(HWND handle) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_widget_hide(handle); + DW_MUTEX_UNLOCK; + return 0; +} + +/* + * Destroys a window and all of it's children. + * Parameters: + * handle: The window handle to destroy. + */ +int dw_window_destroy(HWND handle) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_widget_destroy(handle); + DW_MUTEX_UNLOCK; + return 0; +} + +/* + * Changes a window's parent to newparent. + * Parameters: + * handle: The window handle to destroy. + * newparent: The window's new parent window. + */ +void dw_window_reparent(HWND handle, HWND newparent) +{ + gtk_widget_reparent(handle, newparent); +} + +int _set_font(HWND handle, char *fontname) +{ + GtkStyle *style; + GdkFont *font = NULL; + int retval = FALSE; + + font = gdk_font_load(fontname); + + if(font) + { + style = gtk_widget_get_style(handle); + style->font = font; + gtk_widget_set_style(handle, style); + retval = TRUE; + } + return retval; +} + +/* + * Sets the font used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * fontname: Name and size of the font in the form "size.fontname" + */ +int dw_window_set_font(HWND handle, char *fontname) +{ + GtkWidget *handle2 = handle; + char *font; + int _locked_by_me = FALSE; + gpointer data; + + DW_MUTEX_LOCK; + if(GTK_IS_SCROLLED_WINDOW(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)); + if(tmp) + handle2 = tmp; + } + font = strdup(fontname); + + data = gtk_object_get_data(GTK_OBJECT(handle2), "fontname"); + if(data) + free(data); + + if(font) + gtk_object_set_data(GTK_OBJECT(handle2), "fontname", (gpointer)font); + + DW_MUTEX_UNLOCK; + return TRUE; +} + +int _set_color(HWND handle, unsigned long fore, unsigned long back) +{ + GtkStyle *style; + + if(fore & DW_RGB_COLOR || back & DW_RGB_COLOR) + { + GdkColor forecolor = { 0, DW_RED_VALUE(fore) << 8, DW_GREEN_VALUE(fore) << 8, DW_BLUE_VALUE(fore) << 8 }; + GdkColor backcolor = { 0, DW_RED_VALUE(back) << 8, DW_GREEN_VALUE(back) << 8, DW_BLUE_VALUE(back) << 8 }; + + gdk_color_alloc(_dw_cmap, &forecolor); + gdk_color_alloc(_dw_cmap, &backcolor); + + style = gtk_widget_get_style(handle); + style->fg[0] = forecolor; + style->bg[0] = backcolor; + gtk_widget_set_style(handle, style); + } + else + { + style = gtk_widget_get_style(handle); + style->fg[0] = _colors[fore]; + style->bg[0] = _colors[back]; + gtk_widget_set_style(handle, style); + } + + return TRUE; +} +/* + * Sets the colors used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * fore: Foreground color in RGB format. + * back: Background color in RGB format. + */ +int dw_window_set_color(HWND handle, unsigned long fore, unsigned long back) +{ + GtkWidget *handle2 = handle; + 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; + } + + gtk_object_set_data(GTK_OBJECT(handle2), "fore", (gpointer)fore); + gtk_object_set_data(GTK_OBJECT(handle2), "back", (gpointer)back); + + _set_color(handle2, fore, back); + + DW_MUTEX_UNLOCK; + return TRUE; +} + +/* + * Sets the font used by a specified window (widget) handle. + * Parameters: + * handle: The window (widget) handle. + * border: Size of the window border in pixels. + */ +int dw_window_set_border(HWND handle, int border) +{ + /* TODO */ + return 0; +} + +/* + * Captures the mouse input to this window. + * Parameters: + * handle: Handle to receive mouse input. + */ +void dw_window_capture(HWND handle) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gdk_pointer_grab(handle->window, TRUE, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, NULL, NULL, GDK_CURRENT_TIME); + DW_MUTEX_UNLOCK; +} + +/* + * Releases previous mouse capture. + */ +void dw_window_release(void) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gdk_pointer_ungrab(GDK_CURRENT_TIME); + DW_MUTEX_UNLOCK; +} + +/* + * Create a new Window Frame. + * Parameters: + * owner: The Owner's window handle or HWND_DESKTOP. + * title: The Window title. + * flStyle: Style flags, see the PM reference. + */ +HWND dw_window_new(HWND hwndOwner, char *title, unsigned long flStyle) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + int flags = 0; + + DW_MUTEX_LOCK; + tmp = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + gtk_window_set_title(GTK_WINDOW(tmp), title); + if(!(flStyle & DW_FCF_SIZEBORDER)) + gtk_window_set_policy(GTK_WINDOW(tmp), FALSE, FALSE, TRUE); + + gtk_widget_realize(tmp); + + if(flStyle & DW_FCF_TITLEBAR) + flags |= GDK_DECOR_TITLE; + + if(flStyle & DW_FCF_MINMAX) + flags |= GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE; + + if(flStyle & DW_FCF_SIZEBORDER) + flags |= GDK_DECOR_RESIZEH; + + if(flStyle & DW_FCF_BORDER) + flags |= GDK_DECOR_BORDER; + + gdk_window_set_decorations(tmp->window, flags); + + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new Box to be packed. + * Parameters: + * type: Either BOXVERT (vertical) or BOXHORZ (horizontal). + * pad: Number of pixels to pad around the box. + */ +HWND dw_box_new(int type, int pad) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(type == BOXVERT) + tmp = gtk_vbox_new(FALSE, pad); + else + tmp = gtk_hbox_new(FALSE, pad); + gtk_widget_show(tmp); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new Group Box to be packed. + * Parameters: + * type: Either BOXVERT (vertical) or BOXHORZ (horizontal). + * pad: Number of pixels to pad around the box. + * title: Text to be displayined in the group outline. + */ +HWND dw_groupbox_new(int type, int pad, char *title) +{ + return dw_box_new(type, pad); +} + +/* + * Create a bitmap object to be packed. + * Parameters: + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_bitmap_new(unsigned long id) +{ + GdkPixmap *pixmap= NULL; + GdkBitmap *bitmap; + GtkWidget *tmp; + char * test_xpm[] = { + "1 1 1 1", + " c None", + " "}; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; +#ifndef USE_IMLIB + GtkStyle *iconstyle; + + /* hmmm why do we need the handle here? */ + iconstyle = gtk_widget_get_style(handle); + if (!pixmap) + pixmap = gdk_pixmap_create_from_xpm_d(handle->window, &bitmap, &iconstyle->bg[GTK_STATE_NORMAL], &test_xpm); +#else + gdk_imlib_data_to_pixmap(test_xpm, &pixmap, &bitmap); +#endif + tmp = gtk_pixmap_new(pixmap, bitmap); + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a notebook object to be packed. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HWND dw_notebook_new(unsigned long id, int top) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_notebook_new(); + if(top) + gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tmp), GTK_POS_TOP); + else + gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tmp), GTK_POS_BOTTOM); + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a menu object to be popped up. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HMENUI dw_menu_new(unsigned long id) +{ + int _locked_by_me = FALSE; + HMENUI tmp = malloc(sizeof(struct _hmenui));; + + if(!tmp) + return NULL; + + DW_MUTEX_LOCK; + tmp->menu = gtk_menu_new(); + gtk_widget_show(tmp->menu); + gtk_object_set_data(GTK_OBJECT(tmp->menu), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a menubar on a window. + * Parameters: + * location: Handle of a window frame to be attached to. + */ +HMENUI dw_menubar_new(HWND location) +{ + GtkWidget *box; + int _locked_by_me = FALSE; + HMENUI tmp = malloc(sizeof(struct _hmenui));; + + if(!tmp) + return NULL; + + DW_MUTEX_LOCK; + tmp->menu = gtk_menu_bar_new(); + box = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(location)); + gtk_widget_show(tmp->menu); + + if(box) + gtk_box_pack_end(GTK_BOX(box), tmp->menu, FALSE, FALSE, 0); + + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Destroys a menu created with dw_menubar_new or dw_menu_new. + * Parameters: + * menu: Handle of a menu. + */ +void dw_menu_destroy(HMENUI *menu) +{ + if(menu && *menu) + { + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_widget_destroy((*menu)->menu); + free(*menu); + *menu = NULL; + DW_MUTEX_UNLOCK; + } +} + +void _removetilde(char *dest, char *src) +{ + int z, cur=0; + + for(z=0;z<strlen(src);z++) + { + if(src[z] != '~') + { + dest[cur] = src[z]; + cur++; + } + } + dest[cur] = 0; +} + +/* + * Adds a menuitem or submenu to an existing menu. + * Parameters: + * menu: The handle the the existing menu. + * title: The title text on the menu item to be added. + * id: An ID to be used for message passing. + * flags: Extended attributes to set on the menu. + * end: If TRUE memu is positioned at the end of the menu. + * check: If TRUE menu is "check"able. + * submenu: Handle to an existing menu to be a submenu or NULL. + */ +HWND dw_menu_append_item(HMENUI menu, char *title, unsigned long id, unsigned long flags, int end, int check, HMENUI submenu) +{ + GtkWidget *tmphandle; + char *tempbuf = malloc(strlen(title)+1); + int _locked_by_me = FALSE; + + if(!menu || !menu->menu) + { + free(tempbuf); + return NULL; + } + + DW_MUTEX_LOCK; + _removetilde(tempbuf, title); + + if(strlen(tempbuf) == 0) + tmphandle=gtk_menu_item_new(); + else + { + if(check) + { + char numbuf[10]; + tmphandle=gtk_check_menu_item_new_with_label(tempbuf); + gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(tmphandle), TRUE); + sprintf(numbuf, "%lu", id); + gtk_object_set_data(GTK_OBJECT(menu->menu), numbuf, (gpointer)tmphandle); + } + else + tmphandle=gtk_menu_item_new_with_label(tempbuf); + } + + gtk_widget_show(tmphandle); + + if(submenu) + gtk_menu_item_set_submenu(GTK_MENU_ITEM(tmphandle), submenu->menu); + + if(GTK_IS_MENU_BAR(menu->menu)) + gtk_menu_bar_append(GTK_MENU_BAR(menu->menu), tmphandle); + else + gtk_menu_append(GTK_MENU(menu->menu), tmphandle); + + gtk_object_set_data(GTK_OBJECT(tmphandle), "id", (gpointer)id); + free(tempbuf); + DW_MUTEX_UNLOCK; + return tmphandle; +} + +/* + * Sets the state of a menu item check. + * Parameters: + * menu: The handle the the existing menu. + * id: Menuitem id. + * check: TRUE for checked FALSE for not checked. + */ +void dw_menu_item_set_check(HMENUI menu, int id, int check) +{ + char numbuf[10]; + GtkWidget *tmphandle; + int _locked_by_me = FALSE; + + if(!menu || !menu->menu) + return; + + DW_MUTEX_LOCK; + sprintf(numbuf, "%d", id); + tmphandle = gtk_object_get_data(GTK_OBJECT(menu->menu), numbuf); + + if(tmphandle) + { + if(GTK_CHECK_MENU_ITEM(tmphandle)->active != check) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), check); + } + DW_MUTEX_UNLOCK; +} + +/* + * Pops up a context menu at given x and y coordinates. + * Parameters: + * menu: The handle the the existing menu. + * parent: Handle to the window initiating the popup. + * x: X coordinate. + * y: Y coordinate. + */ +void dw_menu_popup(HMENUI *menu, HWND parent, int x, int y) +{ + int _locked_by_me = FALSE; + + if(!menu || !*menu) + return; + + DW_MUTEX_LOCK; + gtk_menu_popup(GTK_MENU((*menu)->menu), NULL, NULL, NULL, NULL, x, y); + free(*menu); + *menu = NULL; + DW_MUTEX_UNLOCK; +} + + +/* + * Returns the current X and Y coordinates of the mouse pointer. + * Parameters: + * x: Pointer to variable to store X coordinate. + * y: Pointer to variable to store Y coordinate. + */ +void dw_pointer_query_pos(long *x, long *y) +{ + GdkModifierType state; + int gx, gy; + + gdk_window_get_pointer (GDK_ROOT_PARENT(), &gx, &gy, &state); + *x = gx; + *y = gy; +} + +/* + * Sets the X and Y coordinates of the mouse pointer. + * Parameters: + * x: X coordinate. + * y: Y coordinate. + */ +void dw_pointer_set_pos(long x, long y) +{ + XWarpPointer(GDK_DISPLAY(), None, GDK_ROOT_WINDOW(), 0,0,0,0, x, y); +} + +/* + * Create a container object to be packed. + * Parameters: + * id: An ID to be used for getting the resource from the + * resource file. + */ +HWND dw_container_new(unsigned long id) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tmp), + GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + gtk_widget_show(tmp); + + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new static text window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_text_new(char *text, unsigned long id) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_label_new(text); + gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT); + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new Multiline Editbox window (widget) to be packed. + * Parameters: + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_mle_new(unsigned long id) +{ + GtkWidget *tmp, *tmpbox, *scroller; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmpbox = gtk_hbox_new(FALSE, 0); + tmp = gtk_text_new(NULL, NULL); + gtk_text_set_word_wrap(GTK_TEXT(tmp), FALSE); + gtk_text_set_line_wrap(GTK_TEXT(tmp), FALSE); + scroller = gtk_vscrollbar_new(GTK_TEXT(tmp)->vadj); + GTK_WIDGET_UNSET_FLAGS(scroller, GTK_CAN_FOCUS); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + gtk_object_set_data(GTK_OBJECT(tmpbox), "mle", (gpointer)tmp); + gtk_box_pack_start(GTK_BOX(tmpbox), tmp, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(tmpbox), scroller, FALSE, TRUE, 0); + gtk_widget_show(tmp); + gtk_widget_show(scroller); + gtk_widget_show(tmpbox); + DW_MUTEX_UNLOCK; + return tmpbox; +} + +/* + * Create a new Entryfield window (widget) to be packed. + * Parameters: + * text: The default text to be in the entryfield widget. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_entryfield_new(char *text, unsigned long id) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_entry_new(); + + gtk_entry_set_text(GTK_ENTRY(tmp), text); + + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new Entryfield (password) window (widget) to be packed. + * Parameters: + * text: The default text to be in the entryfield widget. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_entryfield_password_new(char *text, ULONG id) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_entry_new(); + + gtk_entry_set_visibility(GTK_ENTRY(tmp), FALSE); + gtk_entry_set_text(GTK_ENTRY(tmp), text); + + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new Combobox window (widget) to be packed. + * Parameters: + * text: The default text to be in the combpbox widget. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_combobox_new(char *text, unsigned long id) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_combo_new(); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(tmp)->entry), text); + gtk_combo_set_use_arrows(GTK_COMBO(tmp), TRUE); + gtk_object_set_user_data(GTK_OBJECT(tmp), NULL); + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new button window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_button_new(char *text, unsigned long id) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_button_new_with_label(text); + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new bitmap button window (widget) to be packed. + * Parameters: + * text: Bubble help text to be displayed. + * id: An ID of a bitmap in the resource file. + */ +HWND dw_bitmapbutton_new(char *text, unsigned long id) +{ + GtkWidget *tmp; + GtkWidget *bitmap; + GtkTooltips *tooltips; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_button_new(); + bitmap = dw_bitmap_new(id); + + if(bitmap) + { + dw_window_set_bitmap(bitmap, id); + gtk_container_add (GTK_CONTAINER(tmp), bitmap); + } + gtk_widget_show(tmp); + if(text) + { + tooltips = gtk_tooltips_new(); + gtk_tooltips_set_colors(tooltips, &_colors[DW_CLR_BLACK], &_colors[DW_CLR_YELLOW]); + gtk_tooltips_set_tip(tooltips, tmp, text, NULL); + gtk_object_set_data(GTK_OBJECT(tmp), "tooltip", (gpointer)tooltips); + } + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new spinbutton window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_spinbutton_new(char *text, unsigned long id) +{ + GtkAdjustment *adj; + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + adj = (GtkAdjustment *)gtk_adjustment_new (1.0, 0.0, 100.0, 1.0, 5.0, 0.0); + tmp = gtk_spin_button_new (adj, 0, 0); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(tmp), TRUE); + gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(tmp), TRUE); + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new radiobutton window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_radiobutton_new(char *text, ULONG id) +{ + /* This will have to be fixed in the future. */ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_radio_button_new_with_label(NULL, text); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + gtk_widget_show(tmp); + + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new slider window (widget) to be packed. + * Parameters: + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_slider_new(unsigned long id) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_progress_bar_new(); + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new checkbox window (widget) to be packed. + * Parameters: + * text: The text to be display by the static text widget. + * id: An ID to be used with WinWindowFromID() or 0L. + */ +HWND dw_checkbox_new(char *text, unsigned long id) +{ + GtkWidget *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_check_button_new_with_label(text); + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Create a new listbox window (widget) to be packed. + * Parameters: + * 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) +{ + GtkWidget *tmp, *list; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (tmp), + GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + + list = gtk_list_new(); + gtk_list_set_selection_mode(GTK_LIST(list), multi ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tmp), + list); + gtk_object_set_user_data(GTK_OBJECT(tmp), list); + gtk_widget_show(list); + gtk_widget_show(tmp); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + + DW_MUTEX_UNLOCK; + return tmp; +} + +/* + * Sets the icon used for a given window. + * Parameters: + * handle: Handle to the window. + * id: An ID to be used to specify the icon. + */ +void dw_window_set_icon(HWND handle, unsigned long id) +{ + GdkBitmap *bitmap; + GdkPixmap *icon_pixmap; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + icon_pixmap = _find_pixmap(&bitmap, id, handle); + + if(handle->window && icon_pixmap) + gdk_window_set_icon(handle->window, NULL, icon_pixmap, bitmap); + + DW_MUTEX_UNLOCK; +} + +/* + * Sets the bitmap used for a given static window. + * Parameters: + * handle: Handle to the window. + * id: An ID to be used to specify the icon. + */ +void dw_window_set_bitmap(HWND handle, unsigned long id) +{ + GdkBitmap *bitmap; + GdkPixmap *tmp; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + tmp = _find_pixmap(&bitmap, id, handle); + if(tmp) + gtk_pixmap_set(GTK_PIXMAP(handle), tmp, bitmap); + DW_MUTEX_UNLOCK; +} + +/* + * Sets the text used for a given window. + * Parameters: + * handle: Handle to the window. + * text: The text associsated with a given window. + */ +void dw_window_set_text(HWND handle, char *text) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_ENTRY(handle)) + gtk_entry_set_text(GTK_ENTRY(handle), text); + else if(GTK_IS_COMBO(handle)) + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(handle)->entry), text); + else if(GTK_IS_LABEL(handle)) + gtk_label_set_text(GTK_LABEL(handle), text); + DW_MUTEX_UNLOCK; +} + +/* + * Gets the text used for a given window. + * Parameters: + * handle: Handle to the window. + * Returns: + * text: The text associsated with a given window. + */ +char *dw_window_get_text(HWND handle) +{ + char *possible = ""; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_ENTRY(handle)) + possible = gtk_entry_get_text(GTK_ENTRY(handle)); + else if(GTK_IS_COMBO(handle)) + possible = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(handle)->entry)); + + DW_MUTEX_UNLOCK; + return strdup(possible); +} + +/* + * Disables given window (widget). + * Parameters: + * handle: Handle to the window. + */ +void dw_window_disable(HWND handle) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_widget_set_sensitive(handle, FALSE); + DW_MUTEX_UNLOCK; +} + +/* + * Enables given window (widget). + * Parameters: + * handle: Handle to the window. + */ +void dw_window_enable(HWND handle) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_widget_set_sensitive(handle, TRUE); + DW_MUTEX_UNLOCK; +} + +/* + * Adds text to an MLE box and returns the current point. + * Parameters: + * handle: Handle to the MLE to be queried. + * buffer: Text buffer to be imported. + * startpoint: Point to start entering text. + */ +unsigned int dw_mle_import(HWND handle, char *buffer, int startpoint) +{ + unsigned int tmppoint = startpoint; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_BOX(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "mle"); + + if(tmp && GTK_IS_TEXT(tmp)) + { + gtk_text_set_point(GTK_TEXT(tmp), startpoint < 0 ? 0 : startpoint); + gtk_text_insert(GTK_TEXT(tmp), NULL, NULL, NULL, buffer, -1); + tmppoint = gtk_text_get_point(GTK_TEXT(tmp)); + } + } + DW_MUTEX_UNLOCK; + return tmppoint; +} + +/* + * Grabs text from an MLE box. + * Parameters: + * handle: Handle to the MLE to be queried. + * buffer: Text buffer to be exported. + * startpoint: Point to start grabbing text. + * length: Amount of text to be grabbed. + */ +void dw_mle_export(HWND handle, char *buffer, int startpoint, int length) +{ + int _locked_by_me = FALSE; + gchar *text; + + DW_MUTEX_LOCK; + if(GTK_IS_BOX(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "mle"); + + if(tmp && GTK_IS_TEXT(tmp)) + { + text = gtk_editable_get_chars(GTK_EDITABLE(&(GTK_TEXT(tmp)->editable)), startpoint, startpoint + length); + if(text) + { + strcpy(buffer, text); + g_free(text); + } + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Obtains information about an MLE box. + * Parameters: + * handle: Handle to the MLE to be queried. + * bytes: A pointer to a variable to return the total bytes. + * lines: A pointer to a variable to return the number of lines. + */ +void dw_mle_query(HWND handle, unsigned long *bytes, unsigned long *lines) +{ + int _locked_by_me = FALSE; + + if(bytes) + *bytes = 0; + if(lines) + *lines = 0; + + DW_MUTEX_LOCK; + if(GTK_IS_BOX(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "mle"); + + if(tmp && GTK_IS_TEXT(tmp)) + { + if(bytes) + *bytes = gtk_text_get_length(GTK_TEXT(tmp)); + if(lines) + { + gchar *text; + + *lines = 0; + text = gtk_editable_get_chars(GTK_EDITABLE(&(GTK_TEXT(tmp)->editable)), 0, bytes ? *bytes : gtk_text_get_length(GTK_TEXT(tmp))); + + if(text) + { + int z, len = strlen(text); + + for(z=0;z<len;z++) + { + if(text[z] == '\n') + (*lines)++; + } + g_free(text); + } + } + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Deletes text from an MLE box. + * Parameters: + * handle: Handle to the MLE to be deleted from. + * startpoint: Point to start deleting text. + * length: Amount of text to be deleted. + */ +void dw_mle_delete(HWND handle, int startpoint, int length) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_BOX(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "mle"); + + if(tmp && GTK_IS_TEXT(tmp)) + { + gtk_text_set_point(GTK_TEXT(tmp), startpoint); + gtk_text_forward_delete(GTK_TEXT(tmp), length); + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Clears all text from an MLE box. + * Parameters: + * handle: Handle to the MLE to be cleared. + */ +void dw_mle_clear(HWND handle) +{ + int length, _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_BOX(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "mle"); + + if(tmp && GTK_IS_TEXT(tmp)) + { + length = gtk_text_get_length(GTK_TEXT(tmp)); + gtk_text_set_point(GTK_TEXT(tmp), 0); + gtk_text_forward_delete(GTK_TEXT(tmp), length); + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Sets the visible line of an MLE box. + * Parameters: + * handle: Handle to the MLE. + * line: Line to be visible. + */ +void dw_mle_set_visible(HWND handle, int line) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_BOX(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "mle"); + + if(tmp && GTK_IS_TEXT(tmp)) + { + unsigned long lines; + float pos, ratio; + + dw_mle_query(handle, NULL, &lines); + + if(lines) + { + ratio = (float)line/(float)lines; + + pos = (ratio * (float)(GTK_TEXT(tmp)->vadj->upper - GTK_TEXT(tmp)->vadj->lower)) + GTK_TEXT(tmp)->vadj->lower; + + gtk_adjustment_set_value(GTK_TEXT(tmp)->vadj, pos); + } + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Sets the current cursor position of an MLE box. + * Parameters: + * handle: Handle to the MLE to be positioned. + * point: Point to position cursor. + */ +void dw_mle_set(HWND handle, int point) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_BOX(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "mle"); + + if(tmp && GTK_IS_TEXT(tmp)) + { + gtk_text_set_point(GTK_TEXT(tmp), point); + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Finds text in an MLE box. + * Parameters: + * handle: Handle to the MLE to be cleared. + * text: Text to search for. + * point: Start point of search. + * flags: Search specific flags. + */ +int dw_mle_search(HWND handle, char *text, int point, unsigned long flags) +{ + int _locked_by_me = FALSE, retval = 0; + + DW_MUTEX_LOCK; + if(GTK_IS_BOX(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "mle"); + + if(tmp && GTK_IS_TEXT(tmp)) + { + int len = gtk_text_get_length(GTK_TEXT(tmp)); + gchar *tmpbuf; + + tmpbuf = gtk_editable_get_chars(GTK_EDITABLE(&(GTK_TEXT(tmp)->editable)), 0, len); + if(tmpbuf) + { + int z, textlen; + + textlen = strlen(text); + + if(flags & DW_MLE_CASESENSITIVE) + { + for(z=point;z<(len-textlen) && !retval;z++) + { + if(strncmp(&tmpbuf[z], text, textlen) == 0) + retval = z + textlen; + } + } + else + { + for(z=point;z<(len-textlen) && !retval;z++) + { + if(strncasecmp(&tmpbuf[z], text, textlen) == 0) + retval = z + textlen; + } + } + + if(retval) + { + gtk_text_set_point(GTK_TEXT(tmp), retval - textlen); + gtk_editable_select_region(&(GTK_TEXT(tmp)->editable), retval - textlen, retval); + } + + g_free(tmpbuf); + } + } + } + + DW_MUTEX_UNLOCK; + return retval; +} + +/* + * Stops redrawing of an MLE box. + * Parameters: + * handle: Handle to the MLE to freeze. + */ +void dw_mle_freeze(HWND handle) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_BOX(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "mle"); + + if(tmp && GTK_IS_TEXT(tmp)) + { + gtk_text_freeze(GTK_TEXT(tmp)); + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Resumes redrawing of an MLE box. + * Parameters: + * handle: Handle to the MLE to thaw. + */ +void dw_mle_thaw(HWND handle) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_BOX(handle)) + { + GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "mle"); + + if(tmp && GTK_IS_TEXT(tmp)) + { + gtk_text_thaw(GTK_TEXT(tmp)); + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Returns the range of the slider. + * Parameters: + * handle: Handle to the slider to be queried. + */ +unsigned int dw_slider_query_range(HWND handle) +{ + return 100; +} + +/* + * Sets the slider position. + * Parameters: + * handle: Handle to the slider to be set. + * position: Position of the slider withing the range. + */ +void dw_slider_set_pos(HWND handle, unsigned int position) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_progress_bar_update(GTK_PROGRESS_BAR(handle), (gfloat)position/100); + DW_MUTEX_UNLOCK; +} + +/* + * Sets the spinbutton value. + * Parameters: + * handle: Handle to the spinbutton to be set. + * position: Current value of the spinbutton. + */ +void dw_spinbutton_set_pos(HWND handle, long position) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_spin_button_set_value(GTK_SPIN_BUTTON(handle), (gfloat)position); + DW_MUTEX_UNLOCK; +} + +/* + * Sets the spinbutton limits. + * Parameters: + * handle: Handle to the spinbutton to be set. + * position: Current value of the spinbutton. + * position: Current value of the spinbutton. + */ +void dw_spinbutton_set_limits(HWND handle, long upper, long lower) +{ + long curval; + GtkAdjustment *adj; + int _locked_by_me = FALSE; + + curval = dw_spinbutton_query(handle); + DW_MUTEX_LOCK; + adj = (GtkAdjustment *)gtk_adjustment_new((gfloat)curval, (gfloat)lower, (gfloat)upper, 1.0, 5.0, 0.0); + DW_MUTEX_UNLOCK; +} + +/* + * Sets the entryfield character limit. + * Parameters: + * handle: Handle to the spinbutton to be set. + * limit: Number of characters the entryfield will take. + */ +void dw_entryfield_set_limit(HWND handle, ULONG limit) +{ + /* TODO: can this be done after the fact? */ +} + +/* + * Returns the current value of the spinbutton. + * Parameters: + * handle: Handle to the spinbutton to be queried. + */ +long dw_spinbutton_query(HWND handle) +{ + long retval; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + retval = (long)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(handle)); + DW_MUTEX_UNLOCK; + + return retval; +} + +/* + * Returns the state of the checkbox. + * Parameters: + * handle: Handle to the checkbox to be queried. + */ +int dw_checkbox_query(HWND handle) +{ + int retval; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + retval = GTK_TOGGLE_BUTTON(handle)->active; + DW_MUTEX_UNLOCK; + + return retval; +} + +/* + * Sets the state of the checkbox. + * Parameters: + * handle: Handle to the checkbox to be queried. + * value: TRUE for checked, FALSE for unchecked. + */ +void dw_checkbox_set(HWND handle, int value) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(handle), value); + DW_MUTEX_UNLOCK; +} + +int _dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator, int extra) +{ + GtkWidget *clist; + char numbuf[10]; + int z; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + clist = gtk_clist_new_with_titles(count, (gchar **)titles); + if(!clist) + { + DW_MUTEX_UNLOCK; + return FALSE; + } + + gtk_signal_connect(GTK_OBJECT(clist), "select_row", GTK_SIGNAL_FUNC(_select_row), NULL); + gtk_signal_connect(GTK_OBJECT(clist), "unselect_row", GTK_SIGNAL_FUNC(_unselect_row), NULL); + + gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 0, TRUE); + gtk_container_add(GTK_CONTAINER(handle), clist); + gtk_object_set_user_data(GTK_OBJECT(handle), (gpointer)clist); + gtk_widget_show(clist); + gtk_object_set_data(GTK_OBJECT(clist), "colcount", (gpointer)count); + + if(extra) + gtk_clist_set_column_width(GTK_CLIST(clist), 1, 120); + + for(z=0;z<count;z++) + { + if(!extra || z > 1) + gtk_clist_set_column_width(GTK_CLIST(clist), z, 50); + sprintf(numbuf, "%d", z); + gtk_object_set_data(GTK_OBJECT(clist), numbuf, (gpointer)flags[z]); + } + + DW_MUTEX_UNLOCK; + return TRUE; +} + +/* + * Sets up the container columns. + * Parameters: + * handle: Handle to the container to be configured. + * flags: An array of unsigned longs with column flags. + * titles: An array of strings with column text titles. + * count: The number of columns (this should match the arrays). + * separator: The column number that contains the main separator. + * (this item may only be used in OS/2) + */ +int dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator) +{ + return _dw_container_setup(handle, flags, titles, count, separator, 0); +} + +/* + * Sets up the filesystem columns, note: filesystem always has an icon/filename field. + * Parameters: + * handle: Handle to the container to be configured. + * flags: An array of unsigned longs with column flags. + * titles: An array of strings with column text titles. + * count: The number of columns (this should match the arrays). + */ +int dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count) +{ + char **newtitles = malloc(sizeof(char *) * (count + 2)); + unsigned long *newflags = malloc(sizeof(unsigned long) * (count + 2)); + + newtitles[0] = "Icon"; + newtitles[1] = "Filename"; + + newflags[0] = DW_CFA_BITMAPORICON | DW_CFA_CENTER | DW_CFA_HORZSEPARATOR | DW_CFA_SEPARATOR; + newflags[1] = DW_CFA_STRING | DW_CFA_LEFT | DW_CFA_HORZSEPARATOR; + + memcpy(&newtitles[2], titles, sizeof(char *) * count); + memcpy(&newflags[2], flags, sizeof(unsigned long) * count); + + _dw_container_setup(handle, newflags, newtitles, count + 2, 2, 1); + + free(newtitles); + free(newflags); + return TRUE; +} + +/* + * Obtains an icon from a module (or header in GTK). + * Parameters: + * module: Handle to module (DLL) in OS/2 and Windows. + * id: A unsigned long id int the resources on OS/2 and + * Windows, on GTK this is converted to a pointer + * to an embedded XPM. + */ +unsigned long dw_icon_load(unsigned long module, unsigned long id) +{ + return id; +} + +/* + * Frees a loaded resource in OS/2 and Windows. + * Parameters: + * handle: Handle to icon returned by dw_icon_load(). + */ +void dw_icon_free(unsigned long handle) +{ +} + +/* + * Allocates memory used to populate a container. + * Parameters: + * handle: Handle to the container window (widget). + * rowcount: The number of items to be populated. + */ +void *dw_container_alloc(HWND handle, int rowcount) +{ + int z, count = 0; + GtkWidget *clist; + char **blah; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + clist = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)); + if(!clist) + { + DW_MUTEX_UNLOCK; + return NULL; + } + + count = (int)gtk_object_get_data(GTK_OBJECT(clist), "colcount"); + + if(!count) + { + DW_MUTEX_UNLOCK; + return NULL; + } + + blah = malloc(sizeof(char *) * count); + memset(blah, 0, sizeof(char *) * count); + + gtk_clist_freeze(GTK_CLIST(clist)); + for(z=0;z<rowcount;z++) + { + gtk_clist_append(GTK_CLIST(clist), blah); + } + free(blah); + DW_MUTEX_UNLOCK; + return (void *)handle; +} + +/* + * Sets an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data) +{ + char numbuf[10], textbuffer[100]; + int flag = 0; + GtkWidget *clist; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + clist = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)); + if(!clist) + { + DW_MUTEX_UNLOCK; + return; + } + + sprintf(numbuf, "%d", column); + flag = (int)gtk_object_get_data(GTK_OBJECT(clist), numbuf); + + if(flag & DW_CFA_BITMAPORICON) + { + long hicon = *((long *)data); + GdkBitmap *bitmap; + GdkPixmap *pixmap = _find_pixmap(&bitmap, hicon, clist); + + if(pixmap) + gtk_clist_set_pixmap(GTK_CLIST(clist), row, column, pixmap, bitmap); + } + else if(flag & DW_CFA_STRING) + { + char *tmp = *((char **)data); + gtk_clist_set_text(GTK_CLIST(clist), row, column, tmp); + } + else if(flag & DW_CFA_ULONG) + { + ULONG tmp = *((ULONG *)data); + + sprintf(textbuffer, "%lu", tmp); + + gtk_clist_set_text(GTK_CLIST(clist), row, column, textbuffer); + } + else if(flag & DW_CFA_DATE) + { + CDATE fdate = *((CDATE *)data); + + sprintf(textbuffer, "%s %d, %d", monthlist[fdate.month], fdate.day, fdate.year); + gtk_clist_set_text(GTK_CLIST(clist), row, column, textbuffer); + } + else if(flag & DW_CFA_TIME) + { + CTIME ftime = *((CTIME *)data); + + if(ftime.hours > 12) + sprintf(textbuffer, "%d:%s%dpm", ftime.hours - 12, (ftime.minutes < 10) ? "0" : "", ftime.minutes); + else + sprintf(textbuffer, "%d:%s%dam", ftime.hours ? ftime.hours : 12, (ftime.minutes < 10) ? "0" : "", ftime.minutes); + gtk_clist_set_text(GTK_CLIST(clist), row, column, textbuffer); + } + DW_MUTEX_UNLOCK; +} + +/* + * Sets an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, unsigned long icon) +{ + dw_container_set_item(handle, pointer, 0, row, (void *)&icon); + dw_container_set_item(handle, pointer, 1, row, (void *)&filename); +} + +/* + * Sets an item in specified row and column to the given data. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * column: Zero based column of data being set. + * row: Zero based row of data being set. + * data: Pointer to the data to be added. + */ +void dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data) +{ + dw_container_set_item(handle, pointer, column + 2, row, data); +} + +/* + * Sets the title of a row in the container. + * Parameters: + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * row: Zero based row of data being set. + * title: String title of the item. + */ +void dw_container_set_row_title(void *pointer, int row, char *title) +{ + GtkWidget *clist; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + clist = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(pointer)); + + if(clist) + gtk_clist_set_row_data(GTK_CLIST(clist), row, (gpointer)title); + DW_MUTEX_UNLOCK; +} + +/* + * Sets the title of a row in the container. + * Parameters: + * handle: Handle to the container window (widget). + * pointer: Pointer to the allocated memory in dw_container_alloc(). + * rowcount: The number of rows to be inserted. + */ +void dw_container_insert(HWND handle, void *pointer, int rowcount) +{ + GtkWidget *clist; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + clist = gtk_object_get_user_data(GTK_OBJECT(handle)); + + if(clist && GTK_IS_CLIST(clist)) + gtk_clist_thaw(GTK_CLIST(clist)); + DW_MUTEX_UNLOCK; +} + +/* + * Removes all rows from a container. + * Parameters: + * handle: Handle to the window (widget) to be cleared. + */ +void dw_container_clear(HWND handle) +{ + GtkWidget *clist; + GList *list; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle)); + if(clist && GTK_IS_CLIST(clist)) + { + list = (GList *)gtk_object_get_data(GTK_OBJECT(clist), "selectlist"); + g_list_free(list); + gtk_object_set_data(GTK_OBJECT(clist), "selectlist", NULL); + gtk_clist_clear(GTK_CLIST(clist)); + } + DW_MUTEX_UNLOCK; +} + +/* + * Removes all rows from a container. + * Parameters: + * handle: Handle to the window (widget) to be cleared. + */ +void dw_container_set_view(HWND handle, unsigned long flags, int iconwidth, int iconheight) +{ +} + +/* + * Starts a new query of a container. + * Parameters: + * handle: Handle to the window (widget) to be queried. + * flags: If this parameter is DW_CRA_SELECTED it will only + * return items that are currently selected. Otherwise + * it will return all records in the container. + */ +char *dw_container_query_start(HWND handle, unsigned long flags) +{ + GtkWidget *clist; + GList *list; + char *retval = NULL; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle)); + + if(!clist) + { + DW_MUTEX_UNLOCK; + return NULL; + } + + /* If there is an old query list, free it */ + list = (GList *)gtk_object_get_data(GTK_OBJECT(clist), "querylist"); + if(list) + g_list_free(list); + + /* Move the current selection list to the query list, and remove the + * current selection list. + */ + list = (GList *)gtk_object_get_data(GTK_OBJECT(clist), "selectlist"); + gtk_object_set_data(GTK_OBJECT(clist), "selectlist", NULL); + gtk_object_set_data(GTK_OBJECT(clist), "querylist", (gpointer)list); + gtk_clist_unselect_all(GTK_CLIST(clist)); + + if(list) + { + gtk_object_set_data(GTK_OBJECT(clist), "querypos", (gpointer)1); + if(list->data) + retval = list->data; + else + retval = ""; + } + DW_MUTEX_UNLOCK; + return retval; +} + +/* + * Continues an existing query of a container. + * Parameters: + * handle: Handle to the window (widget) to be queried. + * flags: If this parameter is DW_CRA_SELECTED it will only + * return items that are currently selected. Otherwise + * it will return all records in the container. + */ +char *dw_container_query_next(HWND handle, unsigned long flags) +{ + GtkWidget *clist; + GList *list; + char *retval = NULL; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle)); + + if(!clist) + { + DW_MUTEX_UNLOCK; + return NULL; + } + + list = (GList *)gtk_object_get_data(GTK_OBJECT(clist), "querylist"); + + if(list) + { + int counter = 0, pos = (int)gtk_object_get_data(GTK_OBJECT(clist), "querypos"); + gtk_object_set_data(GTK_OBJECT(clist), "querypos", (gpointer)pos+1); + + while(list && counter < pos) + { + list = list->next; + counter++; + } + + if(list && list->data) + retval = list->data; + else if(list && !list->data) + retval = ""; + } + DW_MUTEX_UNLOCK; + return retval; +} + +/* + * Creates a rendering context widget (window) to be packed. + * Parameters: + * id: An id to be used with dw_window_from_id. + * Returns: + * A handle to the widget or NULL on failure. + */ +HWND dw_render_new(unsigned long id) +{ + int _locked_by_me = FALSE; + GtkWidget *tmp; + + DW_MUTEX_LOCK; + tmp = gtk_drawing_area_new(); + gtk_widget_set_events(tmp, GDK_EXPOSURE_MASK + | GDK_LEAVE_NOTIFY_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK); + gtk_object_set_data(GTK_OBJECT(tmp), "id", (gpointer)id); + gtk_widget_show(tmp); + DW_MUTEX_UNLOCK; + return tmp; +} + +/* Sets the current foreground drawing color. + * Parameters: + * red: red value. + * green: green value. + * blue: blue value. + */ +void dw_color_foreground_set(unsigned long value) +{ + int _locked_by_me = FALSE; + GdkColor color = { 0, DW_RED_VALUE(value) << 8, DW_GREEN_VALUE(value) << 8, DW_BLUE_VALUE(value) << 8 }; + + DW_MUTEX_LOCK; + gdk_color_alloc(_dw_cmap, &color); + _foreground = color; + DW_MUTEX_UNLOCK; +} + +/* Sets the current background drawing color. + * Parameters: + * red: red value. + * green: green value. + * blue: blue value. + */ +void dw_color_background_set(unsigned long value) +{ + int _locked_by_me = FALSE; + GdkColor color = { 0, DW_RED_VALUE(value) << 8, DW_GREEN_VALUE(value) << 8, DW_BLUE_VALUE(value) << 8 }; + + DW_MUTEX_LOCK; + gdk_color_alloc(_dw_cmap, &color); + _background = color; + DW_MUTEX_UNLOCK; +} + +GdkGC *_set_colors(GdkWindow *window) +{ + GdkGC *gc; + if(!window) + return NULL; + gc = gdk_gc_new(window); + if(gc) + { + gdk_gc_set_foreground(gc, &_foreground); + gdk_gc_set_background(gc, &_background); + } + return gc; +} + +/* Draw a point on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * x: X coordinate. + * y: Y coordinate. + */ +void dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y) +{ + int _locked_by_me = FALSE; + GdkGC *gc = NULL; + + DW_MUTEX_LOCK; + if(handle) + gc = _set_colors(handle->window); + else if(pixmap) + gc = _set_colors(pixmap->pixmap); + if(gc) + { + gdk_draw_point(handle ? handle->window : pixmap->pixmap, gc, x, y); + gdk_gc_unref(gc); + } + DW_MUTEX_UNLOCK; +} + +/* Draw a line on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * x1: First X coordinate. + * y1: First Y coordinate. + * x2: Second X coordinate. + * y2: Second Y coordinate. + */ +void dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2) +{ + int _locked_by_me = FALSE; + GdkGC *gc = NULL; + + DW_MUTEX_LOCK; + if(handle) + gc = _set_colors(handle->window); + else if(pixmap) + gc = _set_colors(pixmap->pixmap); + if(gc) + { + gdk_draw_line(handle ? handle->window : pixmap->pixmap, gc, x1, y1, x2, y2); + gdk_gc_unref(gc); + } + DW_MUTEX_UNLOCK; +} + +/* Draw a rectangle on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * x: X coordinate. + * y: Y coordinate. + * width: Width of rectangle. + * height: Height of rectangle. + */ +void dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height) +{ + int _locked_by_me = FALSE; + GdkGC *gc = NULL; + + DW_MUTEX_LOCK; + if(handle) + gc = _set_colors(handle->window); + else if(pixmap) + gc = _set_colors(pixmap->pixmap); + if(gc) + { + gdk_draw_rectangle(handle ? handle->window : pixmap->pixmap, gc, fill, x, y, width, height); + gdk_gc_unref(gc); + } + DW_MUTEX_UNLOCK; +} + +/* Draw text on a window (preferably a render window). + * Parameters: + * handle: Handle to the window. + * pixmap: Handle to the pixmap. (choose only one of these) + * x: X coordinate. + * y: Y coordinate. +* text: Text to be displayed. + */ +void dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text) +{ + int _locked_by_me = FALSE; + GdkGC *gc = NULL; + GdkFont *font; + char *fontname = "fixed"; + + DW_MUTEX_LOCK; + if(handle) + { + fontname = (char *)gtk_object_get_data(GTK_OBJECT(handle), "fontname"); + gc = _set_colors(handle->window); + } + else if(pixmap) + { + fontname = (char *)gtk_object_get_data(GTK_OBJECT(pixmap->handle), "fontname"); + gc = _set_colors(pixmap->pixmap); + } + if(gc) + { + font = gdk_font_load(fontname); + if(font) + { + gint ascent; + + gdk_text_extents(font, text, strlen(text), NULL, NULL, NULL, &ascent, NULL); + gdk_draw_text(handle ? handle->window : pixmap->pixmap, font, gc, x, y + ascent, text, strlen(text)); + gdk_gc_unref(gc); + gdk_font_unref(font); + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Creates a pixmap with given parameters. + * Parameters: + * handle: Window handle the pixmap is associated with. + * width: Width of the pixmap in pixels. + * height: Height of the pixmap in pixels. + * depth: Color depth of the pixmap. + * Returns: + * A handle to a pixmap or NULL on failure. + */ +HPIXMAP dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth) +{ + int _locked_by_me = FALSE; + HPIXMAP pixmap; + + if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) + return NULL; + + if (!depth) + depth = 24; + + pixmap->width = width; pixmap->height = height; + + + DW_MUTEX_LOCK; + pixmap->handle = handle; + pixmap->pixmap = gdk_pixmap_new(handle->window, width, height, depth); + DW_MUTEX_UNLOCK; + return pixmap; +} + +/* + * Creates a pixmap from internal resource graphic specified by id. + * Parameters: + * handle: Window handle the pixmap is associated with. + * id: Resource ID associated with requested pixmap. + * Returns: + * A handle to a pixmap or NULL on failure. + */ +HPIXMAP dw_pixmap_grab(HWND handle, ULONG id) +{ + GdkBitmap *bitmap; + HPIXMAP pixmap; + int _locked_by_me = FALSE; + + if (!(pixmap = calloc(1,sizeof(struct _hpixmap)))) + return NULL; + + + DW_MUTEX_LOCK; + pixmap->pixmap = _find_pixmap(&bitmap, id, handle); + if(pixmap->pixmap) + { + GdkPixmapPrivate *pvt = (GdkPixmapPrivate *)pixmap->pixmap; + pixmap->width = pvt->width; pixmap->height = pvt->height; + } + DW_MUTEX_UNLOCK; + return pixmap; +} + +/* Call this after drawing to the screen to make sure + * anything you have drawn is visible. + */ +void dw_flush(void) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gdk_flush(); + DW_MUTEX_UNLOCK; +} + +/* + * Destroys an allocated pixmap. + * Parameters: + * pixmap: Handle to a pixmap returned by + * dw_pixmap_new.. + */ +void dw_pixmap_destroy(HPIXMAP pixmap) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gdk_pixmap_unref(pixmap->pixmap); + free(pixmap); + DW_MUTEX_UNLOCK; +} + +/* + * Copies from one item to another. + * Parameters: + * dest: Destination window handle. + * destp: Destination pixmap. (choose only one). + * xdest: X coordinate of destination. + * ydest: Y coordinate of destination. + * width: Width of area to copy. + * height: Height of area to copy. + * src: Source window handle. + * srcp: Source pixmap. (choose only one). + * xsrc: X coordinate of source. + * ysrc: Y coordinate of source. + */ +void dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc) +{ + int _locked_by_me = FALSE; + GdkGC *gc = NULL; + + if((!dest && !destp) || (!src && !srcp)) + return; + + DW_MUTEX_LOCK; + if(dest) + gc = _set_colors(dest->window); + else if(src) + gc = _set_colors(src->window); + else if(destp) + gc = gdk_gc_new(destp->pixmap); + else if(srcp) + gc = gdk_gc_new(srcp->pixmap); + + if(gc) + { + gdk_draw_pixmap(dest ? dest->window : destp->pixmap, gc, src ? src->window : srcp->pixmap, xsrc, ysrc, xdest, ydest, width, height); + gdk_gc_unref(gc); + } + DW_MUTEX_UNLOCK; +} + +/* + * Emits a beep. + * Parameters: + * freq: Frequency. + * dur: Duration. + */ +void dw_beep(int freq, int dur) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gdk_beep(); + DW_MUTEX_UNLOCK; +} + +/* + * Returns the handle to an unnamed mutex semaphore. + */ +HMTX dw_mutex_new(void) +{ + HMTX mutex; + + pthread_mutex_init(&mutex, NULL); + return mutex; +} + +/* + * Closes a semaphore created by dw_mutex_new(). + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + */ +void dw_mutex_close(HMTX mutex) +{ + pthread_mutex_destroy(&mutex); +} + +/* + * Tries to gain access to the semaphore, if it can't it blocks. + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + */ +void dw_mutex_lock(HMTX mutex) +{ + pthread_mutex_lock(&mutex); +} + +/* + * Reliquishes the access to the semaphore. + * Parameters: + * mutex: The handle to the mutex returned by dw_mutex_new(). + */ +void dw_mutex_unlock(HMTX mutex) +{ + pthread_mutex_unlock(&mutex); +} + +/* + * Returns the handle to an unnamed event semaphore. + */ +HEV dw_event_new(void) +{ + HEV eve = (HEV)malloc(sizeof(struct _dw_unix_event)); + + if(!eve) + return NULL; + + /* We need to be careful here, mutexes on Linux are + * FAST by default but are error checking on other + * systems such as FreeBSD and OS/2, perhaps others. + */ + pthread_mutex_init (&(eve->mutex), NULL); + pthread_mutex_lock (&(eve->mutex)); + pthread_cond_init (&(eve->event), NULL); + + pthread_mutex_unlock (&(eve->mutex)); + eve->alive = 1; + eve->posted = 0; + + return eve; +} + +/* + * Resets a semaphore created by dw_event_new(). + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int dw_event_reset (HEV eve) +{ + if(!eve) + return FALSE; + + pthread_mutex_lock (&(eve->mutex)); + pthread_cond_broadcast (&(eve->event)); + pthread_cond_init (&(eve->event), NULL); + eve->posted = 0; + pthread_mutex_unlock (&(eve->mutex)); + return 0; +} + +/* + * Posts a semaphore created by dw_event_new(). Causing all threads + * waiting on this event in dw_event_wait to continue. + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int dw_event_post (HEV eve) +{ + if(!eve) + return FALSE; + + pthread_mutex_lock (&(eve->mutex)); + pthread_cond_broadcast (&(eve->event)); + eve->posted = 1; + pthread_mutex_unlock (&(eve->mutex)); + return 0; +} + +/* + * Waits on a semaphore created by dw_event_new(), until the + * event gets posted or until the timeout expires. + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int dw_event_wait(HEV eve, unsigned long timeout) +{ + int rc; + struct timeval now; + struct timespec timeo; + + if(!eve) + return FALSE; + + if(eve->posted) + return 0; + + pthread_mutex_lock (&(eve->mutex)); + gettimeofday(&now, 0); + timeo.tv_sec = now.tv_sec + (timeout / 1000); + timeo.tv_nsec = now.tv_usec * 1000; + rc = pthread_cond_timedwait (&(eve->event), &(eve->mutex), &timeo); + pthread_mutex_unlock (&(eve->mutex)); + if(!rc) + return 1; + if(rc == ETIMEDOUT) + return -1; + return 0; +} + +/* + * Closes a semaphore created by dw_event_new(). + * Parameters: + * eve: The handle to the event returned by dw_event_new(). + */ +int dw_event_close(HEV *eve) +{ + if(!eve || !(*eve)) + return FALSE; + + pthread_mutex_lock (&((*eve)->mutex)); + pthread_cond_destroy (&((*eve)->event)); + pthread_mutex_unlock (&((*eve)->mutex)); + pthread_mutex_destroy (&((*eve)->mutex)); + free(*eve); + *eve = NULL; + + return TRUE; +} + +/* + * Creates a new thread with a starting point of func. + * Parameters: + * func: Function which will be run in the new thread. + * data: Parameter(s) passed to the function. + * stack: Stack size of new thread (OS/2 and Windows only). + */ +DWTID dw_thread_new(void *func, void *data, int stack) +{ + DWTID gtkthread; + + pthread_create(>kthread, NULL, func, data); + return gtkthread; +} + +/* + * Ends execution of current thread immediately. + */ +void dw_thread_end(void) +{ + pthread_exit(NULL); +} + +/* + * Cleanly terminates a DW session, should be signal handler safe. + * Parameters: + * exitcode: Exit code reported to the operating system. + */ +void dw_exit(int exitcode) +{ + exit(exitcode); +} + +/* + * Pack windows (widgets) into a box from the end (or bottom). + * Parameters: + * box: Window handle of the box to be packed into. + * item: Window handle of the item to be back. + * width: Width in pixels of the item or -1 to be self determined. + * height: Height in pixels of the item or -1 to be self determined. + * hsize: TRUE if the window (widget) should expand horizontally to fill space given. + * vsize: TRUE if the window (widget) should expand vertically to fill space given. + * pad: Number of pixels of padding around the item. + */ +void dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) +{ + int expand = (hsize == FALSE && vsize == FALSE) ? FALSE : TRUE; + int _locked_by_me = FALSE; + + if(!box) + return; + + DW_MUTEX_LOCK; + + if(!item) + { + item = gtk_label_new(""); + gtk_widget_show(item); + } + + if(GTK_IS_BOX(box)) + { + gtk_box_pack_end(GTK_BOX(box), item, expand, TRUE, pad); + gtk_widget_set_usize(item, width, height); + if(GTK_IS_RADIO_BUTTON(item)) + { + GSList *group; + GtkWidget *groupstart = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(box), "group"); + + if(groupstart) + { + group = gtk_radio_button_group(GTK_RADIO_BUTTON(groupstart)); + gtk_radio_button_set_group(GTK_RADIO_BUTTON(item), group); + } + else + gtk_object_set_data(GTK_OBJECT(box), "group", (gpointer)item); + } + } + else + { + GtkWidget *vbox = gtk_vbox_new(FALSE, 0); + + gtk_container_add(GTK_CONTAINER(box), vbox); + gtk_box_pack_end(GTK_BOX(vbox), item, expand, TRUE, 0); + gtk_widget_show(vbox); + + gtk_widget_set_usize(item, width, height); + gtk_object_set_user_data(GTK_OBJECT(box), vbox); + } + DW_MUTEX_UNLOCK; +} + +/* + * Sets the size of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * width: New width in pixels. + * height: New height in pixels. + */ +void dw_window_set_usize(HWND handle, unsigned long width, unsigned long height) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_WINDOW(handle)) + _size_allocate(GTK_WINDOW(handle)); +#if 0 + gtk_window_set_default_size(GTK_WINDOW(handle), width, height); + else +#endif + gtk_widget_set_usize(handle, width, height); + DW_MUTEX_UNLOCK; +} + +/* + * Returns the width of the screen. + */ +int dw_screen_width(void) +{ + int retval; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + retval = gdk_screen_width(); + DW_MUTEX_UNLOCK; + return retval; +} + +/* + * Returns the height of the screen. + */ +int dw_screen_height(void) +{ + int retval; + int _locked_by_me = FALSE; + + DW_MUTEX_UNLOCK; + retval = gdk_screen_height(); + DW_MUTEX_UNLOCK; + return retval; +} + +/* This should return the current color depth */ +unsigned long dw_color_depth(void) +{ + int retval; + int _locked_by_me = FALSE; + + DW_MUTEX_UNLOCK; + retval = gdk_colormap_get_system_size(); + DW_MUTEX_UNLOCK; + return retval; +} + +/* + * Sets the position of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * x: X location from the bottom left. + * y: Y location from the bottom left. + */ +void dw_window_set_pos(HWND handle, unsigned long x, unsigned long y) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(handle->window) + gdk_window_move(handle->window, x, y); + DW_MUTEX_UNLOCK; +} + +/* + * Sets the position and size of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * x: X location from the bottom left. + * y: Y location from the bottom left. + * width: Width of the widget. + * height: Height of the widget. + */ +void dw_window_set_pos_size(HWND handle, unsigned long x, unsigned long y, unsigned long width, unsigned long height) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_WINDOW(handle)) + { + _size_allocate(GTK_WINDOW(handle)); + gtk_widget_set_uposition(handle, x, y); + gtk_window_set_default_size(GTK_WINDOW(handle), width, height); + } + else if(handle->window) + { + gdk_window_resize(handle->window, width, height); + gdk_window_move(handle->window, x, y); + } + DW_MUTEX_UNLOCK; +} + +/* + * Gets the position and size of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * x: X location from the bottom left. + * y: Y location from the bottom left. + * width: Width of the widget. + * height: Height of the widget. + */ +void dw_window_get_pos_size(HWND handle, ULONG *x, ULONG *y, ULONG *width, ULONG *height) +{ + int _locked_by_me = FALSE; + gint gx, gy, gwidth, gheight, gdepth; + + if(handle->window) + { + DW_MUTEX_LOCK; + gdk_window_get_geometry(handle->window, &gx, &gy, &gwidth, &gheight, &gdepth); + gdk_window_get_root_origin(handle->window, &gx, &gy); + if(x) + *x = gx; + if(y) + *y = gy; + if(width) + *width = gwidth; + if(height) + *height = gheight; + DW_MUTEX_UNLOCK; + } +} + +/* + * Sets the style of a given window (widget). + * Parameters: + * handle: Window (widget) handle. + * width: New width in pixels. + * height: New height in pixels. + */ +void dw_window_set_style(HWND handle, unsigned long style, unsigned long mask) +{ + GtkWidget *handle2 = handle; + 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_CLIST(handle2)) + { + if(style & DW_CCS_EXTENDSEL) + gtk_clist_set_selection_mode(GTK_CLIST(handle2), GTK_SELECTION_MULTIPLE); + if(style & DW_CCS_SINGLESEL) + gtk_clist_set_selection_mode(GTK_CLIST(handle2), GTK_SELECTION_SINGLE); + } + DW_MUTEX_UNLOCK; +} + +/* + * Adds a new page to specified notebook. + * Parameters: + * handle: Window (widget) handle. + * flags: Any additional page creation flags. + * front: If TRUE page is added at the beginning. + */ +unsigned long dw_notebook_page_new(HWND handle, unsigned long flags, int front) +{ + int z; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + for(z=0;z<256;z++) + if(!gtk_notebook_get_nth_page(GTK_NOTEBOOK(handle), z)) + { + DW_MUTEX_UNLOCK; + return z; + } + + DW_MUTEX_UNLOCK; + + /* Hopefully this won't happen. */ + return 256; +} + +/* + * Remove a page from a notebook. + * Parameters: + * handle: Handle to the notebook widget. + * pageid: ID of the page to be destroyed. + */ +void dw_notebook_page_destroy(HWND handle, unsigned int pageid) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_notebook_remove_page(GTK_NOTEBOOK(handle), pageid); + DW_MUTEX_UNLOCK; +} + +/* + * Queries the currently visible page ID. + * Parameters: + * handle: Handle to the notebook widget. + */ +unsigned int dw_notebook_page_query(HWND handle) +{ + int retval; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + retval = gtk_notebook_get_current_page(GTK_NOTEBOOK(handle)); + DW_MUTEX_UNLOCK; + return retval; +} + +/* + * Sets the currently visibale page ID. + * Parameters: + * handle: Handle to the notebook widget. + * pageid: ID of the page to be made visible. + */ +void dw_notebook_page_set(HWND handle, unsigned int pageid) +{ + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + gtk_notebook_set_page(GTK_NOTEBOOK(handle), pageid); + DW_MUTEX_UNLOCK; +} + + +/* + * Sets the text on the specified notebook tab. + * Parameters: + * handle: Notebook handle. + * pageid: Page ID of the tab to set. + * text: Pointer to the text to set. + */ +void dw_notebook_page_set_text(HWND handle, unsigned long pageid, char *text) +{ + GtkWidget *child; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + child = gtk_notebook_get_nth_page(GTK_NOTEBOOK(handle), pageid); + if(child) + gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(handle), child, text); + DW_MUTEX_UNLOCK; +} + +/* + * Sets the text on the specified notebook tab status area. + * Parameters: + * handle: Notebook handle. + * pageid: Page ID of the tab to set. + * text: Pointer to the text to set. + */ +void dw_notebook_page_set_status_text(HWND handle, unsigned long pageid, char *text) +{ + /* TODO (if possible) */ +} + +/* + * Packs the specified box into the notebook page. + * Parameters: + * handle: Handle to the notebook to be packed. + * pageid: Page ID in the notebook which is being packed. + * page: Box handle to be packed. + */ +void dw_notebook_pack(HWND handle, unsigned long pageid, HWND page) +{ + GtkWidget *label; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + label = gtk_label_new(""); + + gtk_notebook_append_page (GTK_NOTEBOOK(handle), page, label); + DW_MUTEX_UNLOCK; +} + +/* + * Appends the specified text to the listbox's (or combobox) entry list. + * Parameters: + * handle: Handle to the listbox to be appended to. + * text: Text to append into listbox. + */ +void dw_listbox_append(HWND handle, char *text) +{ + GtkWidget *handle2 = handle; + 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)) + { + GtkWidget *list_item; + GList *tmp; + char *font = (char *)gtk_object_get_data(GTK_OBJECT(handle), "font"); + unsigned long fore = (unsigned long)gtk_object_get_data(GTK_OBJECT(handle), "fore"); + unsigned long back = (unsigned long)gtk_object_get_data(GTK_OBJECT(handle), "back"); + + list_item=gtk_list_item_new_with_label(text); + + if(font) + _set_font(GTK_LIST_ITEM(list_item)->item.bin.child, font); + if(fore && back) + _set_color(GTK_LIST_ITEM(list_item)->item.bin.child, fore, back); + + tmp = g_list_append(NULL, list_item); + gtk_widget_show(list_item); + gtk_list_append_items(GTK_LIST(handle2),tmp); + } + else if(GTK_IS_COMBO(handle2)) + { + GList *tmp = (GList *)gtk_object_get_user_data(GTK_OBJECT(handle2)); + char *addtext = strdup(text); + + if(addtext) + { + tmp = g_list_append(tmp, addtext); + gtk_object_set_user_data(GTK_OBJECT(handle2), tmp); + gtk_combo_set_popdown_strings(GTK_COMBO(handle2), tmp); + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Clears the listbox's (or combobox) list of all entries. + * Parameters: + * handle: Handle to the listbox to be cleared. + */ +void dw_listbox_clear(HWND handle) +{ + GtkWidget *handle2 = handle; + 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_COMBO(handle2)) + { + GList *list, *tmp = (GList *)gtk_object_get_user_data(GTK_OBJECT(handle2)); + + if(tmp) + { + list = tmp; + while(list) + { + if(list->data) + free(list->data); + list=list->next; + } + g_list_free(tmp); + } + gtk_object_set_user_data(GTK_OBJECT(handle2), NULL); + } + else if(GTK_IS_LIST(handle2)) + { + int count = dw_listbox_count(handle); + + gtk_list_clear_items(GTK_LIST(handle2), 0, count - 1); + } + DW_MUTEX_UNLOCK; +} + +/* + * Returns the listbox's item count. + * Parameters: + * handle: Handle to the listbox to be counted + */ +int dw_listbox_count(HWND handle) +{ + GtkWidget *handle2 = handle; + int retval = 0; + 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; + } + else if(GTK_IS_COMBO(handle)) + { + handle2 = GTK_COMBO(handle)->list; + } + if(GTK_IS_LIST(handle2)) + { + GList *list = GTK_LIST(handle2)->children; + while(list) + { + list = list->next; + retval++; + } + } + DW_MUTEX_UNLOCK; + return retval; +} + +/* + * Sets the topmost item in the viewport. + * Parameters: + * handle: Handle to the listbox to be cleared. + * top: Index to the top item. + */ +void dw_listbox_set_top(HWND handle, int top) +{ + GtkWidget *handle2 = handle; + 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 count = dw_listbox_count(handle); + GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(handle)); + float pos, ratio; + + if(count) + { + ratio = (float)top/(float)count; + + pos = (ratio * (float)(adj->upper - adj->lower)) + adj->lower; + + gtk_adjustment_set_value(adj, pos); + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Copies the given index item's text into buffer. + * Parameters: + * handle: Handle to the listbox to be queried. + * index: Index into the list to be queried. + * buffer: Buffer where text will be copied. + * length: Length of the buffer (including NULL). + */ +void dw_listbox_query_text(HWND handle, unsigned int index, char *buffer, unsigned int length) +{ + GtkWidget *handle2 = handle; + 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; + } + else if(GTK_IS_COMBO(handle)) + { + handle2 = GTK_COMBO(handle)->list; + } + if(GTK_IS_LIST(handle2)) + { + int counter = 0; + GList *list = GTK_LIST(handle2)->children; + + while(list) + { + if(counter == index) + { + gchar *text = ""; + + if(GTK_IS_LIST_ITEM(list->data)) + { + GtkListItem *li = GTK_LIST_ITEM(list->data); + + if(GTK_IS_ITEM(&(li->item))) + { + GtkItem *i = &(li->item); + + if(GTK_IS_BIN(&(i->bin))) + { + GtkBin *b = &(i->bin); + + if(GTK_IS_LABEL(b->child)) + gtk_label_get(GTK_LABEL(b->child), &text); + } + } + } + else if(GTK_IS_COMBO(handle) && list->data) + text = (gchar *)list->data; + + strncpy(buffer, (char *)text, length); + break; + } + list = list->next; + counter++; + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Sets the text of a given listbox entry. + * Parameters: + * handle: Handle to the listbox to be queried. + * index: Index into the list to be queried. + * buffer: Buffer where text will be copied. + */ +void dw_listbox_set_text(HWND handle, unsigned int index, char *buffer) +{ + GtkWidget *handle2 = handle; + 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; + } + else if(GTK_IS_COMBO(handle)) + { + handle2 = GTK_COMBO(handle)->list; + } + if(GTK_IS_LIST(handle2)) + { + int counter = 0; + GList *list = GTK_LIST(handle2)->children; + + while(list) + { + if(counter == index) + { + + if(GTK_IS_LIST_ITEM(list->data)) + { + GtkListItem *li = GTK_LIST_ITEM(list->data); + + if(GTK_IS_ITEM(&(li->item))) + { + GtkItem *i = &(li->item); + + if(GTK_IS_BIN(&(i->bin))) + { + GtkBin *b = &(i->bin); + + if(GTK_IS_LABEL(b->child)) + gtk_label_set_text(GTK_LABEL(b->child), buffer); + } + } + } + else if(GTK_IS_COMBO(handle)) + { + if(list->data) + g_free(list->data); + list->data = g_strdup(buffer); + } + break; + } + list = list->next; + counter++; + } + } + DW_MUTEX_UNLOCK; +} + +/* + * Returns the index to the item in the list currently selected. + * Parameters: + * handle: Handle to the listbox to be queried. + */ +unsigned int dw_listbox_selected(HWND handle) +{ + 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; + } + else if(GTK_IS_COMBO(handle)) + { + retval = (unsigned int)gtk_object_get_data(GTK_OBJECT(handle), "item"); + DW_MUTEX_UNLOCK; + return retval; + } + if(GTK_IS_LIST(handle2)) + { + int counter = 0; + GList *list = GTK_LIST(handle2)->children; + while(list) + { + if(list == GTK_LIST(handle2)->selection) + { + retval = counter; + break; + } + + list = list->next; + counter++; + } + } + DW_MUTEX_UNLOCK; + return retval; +} + +/* + * Sets the selection state of a given index. + * Parameters: + * handle: Handle to the listbox to be set. + * index: Item index. + * state: TRUE if selected FALSE if unselected. + */ +void dw_listbox_select(HWND handle, int index, int state) +{ + GtkWidget *handle2 = handle; + 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; + } + else if(GTK_IS_COMBO(handle)) + { + handle2 = GTK_COMBO(handle)->list; + } + if(GTK_IS_LIST(handle2)) + { + if(state) + gtk_list_select_item(GTK_LIST(handle2), index); + else + gtk_list_unselect_item(GTK_LIST(handle2), index); + } + DW_MUTEX_UNLOCK; +} + +/* + * Deletes the item with given index from the list. + * Parameters: + * handle: Handle to the listbox to be set. + * index: Item index. + */ +void dw_listbox_delete(HWND handle, int index) +{ + GtkWidget *handle2 = handle; + 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; + } + else if(GTK_IS_COMBO(handle)) + { + handle2 = GTK_COMBO(handle)->list; + } + if(GTK_IS_LIST(handle2)) + gtk_list_clear_items(GTK_LIST(handle2), index, index); + DW_MUTEX_UNLOCK; +} + + +/* + * Pack a splitbar (sizer) into the specified box from the start. + * Parameters: + * box: Window handle of the box to be packed into. + */ +void dw_box_pack_splitbar_start(HWND box) +{ + /* TODO */ +} + +/* + * Pack a splitbar (sizer) into the specified box from the end. + * Parameters: + * box: Window handle of the box to be packed into. + */ +void dw_box_pack_splitbar_end(HWND box) +{ + /* TODO */ +} + +/* + * Pack windows (widgets) into a box from the start (or top). + * Parameters: + * box: Window handle of the box to be packed into. + * item: Window handle of the item to be back. + * width: Width in pixels of the item or -1 to be self determined. + * height: Height in pixels of the item or -1 to be self determined. + * hsize: TRUE if the window (widget) should expand horizontally to fill space given. + * vsize: TRUE if the window (widget) should expand vertically to fill space given. + * pad: Number of pixels of padding around the item. + */ +void dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) +{ + int expand = (hsize == FALSE && vsize == FALSE) ? FALSE : TRUE; + int _locked_by_me = FALSE; + + if(!box) + return; + + DW_MUTEX_LOCK; + + if(!item) + { + item = gtk_label_new(""); + gtk_widget_show(item); + } + + if(GTK_IS_BOX(box)) + { + gtk_box_pack_start(GTK_BOX(box), item, expand, TRUE, pad); + gtk_widget_set_usize(item, width, height); + if(GTK_IS_RADIO_BUTTON(item)) + { + GSList *group; + GtkWidget *groupstart = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(box), "group"); + + if(groupstart) + { + group = gtk_radio_button_group(GTK_RADIO_BUTTON(groupstart)); + gtk_radio_button_set_group(GTK_RADIO_BUTTON(item), group); + } + else + gtk_object_set_data(GTK_OBJECT(box), "group", (gpointer)item); + } + } + else + { + GtkWidget *vbox = gtk_vbox_new(FALSE, 0); + + gtk_container_add(GTK_CONTAINER(box), vbox); + gtk_box_pack_end(GTK_BOX(vbox), item, expand, TRUE, 0); + gtk_widget_show(vbox); + + gtk_widget_set_usize(item, width, height); + gtk_object_set_user_data(GTK_OBJECT(box), vbox); + } + DW_MUTEX_UNLOCK; +} + +/* + * Returns some information about the current operating environment. + * Parameters: + * env: Pointer to a DWEnv struct. + */ +void dw_environment_query(DWEnv *env) +{ + struct utsname name; + char tempbuf[100]; + int len, z; + + uname(&name); + strcpy(env->osName, name.sysname); + strcpy(tempbuf, name.release); + + env->MajorBuild = env->MinorBuild = 0; + + len = strlen(tempbuf); + + for(z=1;z<len;z++) + { + if(tempbuf[z] == '.') + { + tempbuf[z] = '\0'; + env->MajorVersion = atoi(&tempbuf[z-1]); + env->MinorVersion = atoi(&tempbuf[z+1]); + return; + } + } + env->MajorVersion = atoi(tempbuf); + env->MinorVersion = 0; +} + +/* Internal function to handle the file OK press */ +void _gtk_file_ok(GtkWidget *widget, GtkWidget *window) +{ + char *tmp; + + tmp = gtk_file_selection_get_filename(GTK_FILE_SELECTION(window)); + if(tmp) + _dw_browse_file = strdup(tmp); + gtk_widget_destroy(GTK_WIDGET(window)); + if(pthread_self() == _dw_thread) + gtk_main_quit(); + _dw_file_ready = 1; +} + +/* Internal function to handle the file Cancel press */ +void _gtk_file_cancel(GtkWidget *widget, GtkWidget *window) +{ + gtk_widget_destroy(GTK_WIDGET(window)); + if(pthread_self() == _dw_thread) + gtk_main_quit(); + _dw_file_ready = 1; + +} + +/* + * Opens a file dialog and queries user selection. + * Parameters: + * title: Title bar text for dialog. + * defpath: The default path of the open dialog. + * ext: Default file extention. + * flags: DW_FILE_OPEN or DW_FILE_SAVE. + * Returns: + * NULL on error. A malloced buffer containing + * the file path on success. + * + */ +char *dw_file_browse(char *title, char *defpath, char *ext, int flags) +{ + GtkWidget *filew; + char *tmpvar; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + + /* The DW mutex should be sufficient for + * insuring no thread changes this unknowingly. + */ + if(_dw_file_active) + { + DW_MUTEX_UNLOCK; + return NULL; + } + + _dw_file_active = 1; + _dw_file_ready = 0; + + filew = gtk_file_selection_new(title); + + gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->ok_button), "clicked", (GtkSignalFunc) _gtk_file_ok, filew); + gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->cancel_button), "clicked", (GtkSignalFunc) _gtk_file_cancel, filew); + + if(defpath) + gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew), defpath); + + gtk_widget_show(filew); + + DW_MUTEX_UNLOCK; + + if(pthread_self() == _dw_thread) + gtk_main(); + else + { + /* This should be an event semaphore */ + while(!_dw_file_ready) + usleep(100); + } + + tmpvar = _dw_browse_file; + _dw_browse_file = NULL; + _dw_file_ready = _dw_file_active = 0; + + return tmpvar; +} + + +/* + * Execute and external program in a seperate session. + * Parameters: + * program: Program name with optional path. + * type: Either DW_EXEC_CON or DW_EXEC_GUI. + * params: An array of pointers to string arguements. + * Returns: + * -1 on error. + */ +int dw_exec(char *program, int type, char **params) +{ + int ret = -1; + + if((ret = fork()) == 0) + { + int i; + + for (i = 3; i < 256; i++) + close(i); + setsid(); + if(type == DW_EXEC_GUI) + { + execvp(program, params); + } + else if(type == DW_EXEC_CON) + { + char **tmpargs; + + if(!params) + { + tmpargs = malloc(sizeof(char *)); + tmpargs[0] = NULL; + } + else + { + int z = 0; + + while(params[z]) + { + z++; + } + tmpargs = malloc(sizeof(char *)*(z+3)); + z=0; + tmpargs[0] = "xterm"; + tmpargs[1] = "-e"; + while(params[z]) + { + tmpargs[z+2] = params[z]; + z++; + } + tmpargs[z+2] = NULL; + } + execvp("xterm", tmpargs); + free(tmpargs); + } + /* If we got here exec failed */ + _exit(-1); + } + return ret; +} + +/* + * Loads a web browser pointed at the given URL. + * Parameters: + * url: Uniform resource locator. + */ +int dw_browse(char *url) +{ + /* Is there a way to find the webbrowser in Unix? */ + char *execargs[3], *browser = "netscape"; + + execargs[0] = browser; + execargs[1] = url; + execargs[2] = NULL; + + return dw_exec(browser, DW_EXEC_GUI, execargs); +} + +/* + * Returns a pointer to a static buffer which containes the + * current user directory. Or the root directory (C:\ on + * OS/2 and Windows). + */ +char *dw_user_dir(void) +{ + static char _user_dir[1024] = ""; + + if(!_user_dir[0]) + { + char *home = getenv("HOME"); + + if(home) + strcpy(_user_dir, home); + else + strcpy(_user_dir, "/"); + } + return _user_dir; +} + +/* + * Call a function from the window (widget)'s context. + * Parameters: + * handle: Window handle of the widget. + * function: Function pointer to be called. + * data: Pointer to the data to be passed to the function. + */ +void dw_window_function(HWND handle, void *function, void *data) +{ + /* TODO */ +} + +#ifndef NO_SIGNALS +/* + * Add a callback to a window event. + * Parameters: + * window: Window handle of signal to be called back. + * signame: A string pointer identifying which signal to be hooked. + * sigfunc: The pointer to the function to be used as the callback. + * data: User data to be passed to the handler function. + */ +void dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data) +{ + SignalHandler *work = malloc(sizeof(SignalHandler)); + void *thisfunc = _findsigfunc(signame); + char *thisname = signame; + HWND thiswindow = window; + int _locked_by_me = FALSE; + + DW_MUTEX_LOCK; + if(GTK_IS_SCROLLED_WINDOW(thiswindow)) + { + thiswindow = (HWND)gtk_object_get_user_data(GTK_OBJECT(window)); + } + + if(GTK_IS_MENU_ITEM(thiswindow) && strcmp(signame, "clicked") == 0) + { + thisname = "activate"; + thisfunc = _findsigfunc(thisname); + } + else if(GTK_IS_CLIST(thiswindow) && strcmp(signame, "container-context") == 0) + { + thisname = "button_press_event"; + thisfunc = _findsigfunc("container-context"); + } + else if(GTK_IS_CLIST(thiswindow) && strcmp(signame, "container-select") == 0) + { + thisname = "button_press_event"; + thisfunc = _findsigfunc("container-select"); + } + else if(GTK_IS_COMBO(thiswindow) && strcmp(signame, "item-select") == 0) + { + thisname = "select_child"; + thiswindow = GTK_COMBO(thiswindow)->list; + } + else if(GTK_IS_LIST(thiswindow) && strcmp(signame, "item-select") == 0) + { + thisname = "select_child"; + } + + if(!thisfunc || !thiswindow) + { + free(work); + DW_MUTEX_UNLOCK; + return; + } + + work->window = window; + work->data = data; + work->func = sigfunc; + + gtk_signal_connect(GTK_OBJECT(thiswindow), thisname, GTK_SIGNAL_FUNC(thisfunc), work); + DW_MUTEX_UNLOCK; +} + +/* + * Removes callbacks for a given window with given name. + * Parameters: + * window: Window handle of callback to be removed. + */ +void dw_signal_disconnect_by_name(HWND window, char *signame) +{ +#if 0 + gtk_signal_disconnect_by_name(window, signame); +#endif +} + +/* + * Removes all callbacks for a given window. + * Parameters: + * window: Window handle of callback to be removed. + */ +void dw_signal_disconnect_by_window(HWND window) +{ +#if 0 + gtk_signal_disconnect_by_window(window); +#endif +} + +/* + * Removes all callbacks for a given window with specified data. + * Parameters: + * window: Window handle of callback to be removed. + * data: Pointer to the data to be compared against. + */ +void dw_signal_disconnect_by_data(HWND window, void *data) +{ + dw_signal_disconnect_by_data(window, data); +} +#endif + +#ifdef TEST +HWND mainwindow, + listbox, + okbutton, + cancelbutton, + lbbox, + stext, + buttonbox, + testwindow, + testbox, + testok, + testcancel, + testbox2, + testok2, + testcancel2, + notebook; +int count = 2; + +int test_callback(HWND window, void *data) +{ + dw_window_destroy((HWND)data); + /* Return -1 to allow the default handlers to return. */ + count--; + if(!count) + exit(0); + return -1; +} + +/* + * Let's demonstrate the functionality of this library. :) + */ +int main(void) +{ + unsigned long flStyle = DW_FCF_SYSMENU | DW_FCF_TITLEBAR | + DW_FCF_SHELLPOSITION | DW_FCF_TASKLIST | DW_FCF_DLGBORDER; + int pageid; + + dw_init(TRUE); + + /* Try a little server dialog. :) */ + mainwindow = dw_window_new(DW_DESKTOP, "Server", flStyle | DW_FCF_SIZEBORDER | DW_FCF_MINMAX); + + lbbox = dw_box_new(BOXVERT, 10); + + dw_box_pack_start(mainwindow, lbbox, 0, 0, TRUE, TRUE, 0); + + stext = dw_text_new("Choose a server:", 0); + + dw_window_set_style(stext, DW_DT_VCENTER, DW_DT_VCENTER); + + dw_box_pack_start(lbbox, stext, 130, 15, FALSE, FALSE, 10); + + listbox = dw_listbox_new(100L, FALSE); + + dw_box_pack_start(lbbox, listbox, 130, 200, TRUE, TRUE, 10); + + buttonbox = dw_box_new(BOXHORZ, 0); + + dw_box_pack_start(lbbox, buttonbox, 0, 0, TRUE, TRUE, 0); + + okbutton = dw_button_new("Ok", 1001L); + + dw_box_pack_start(buttonbox, okbutton, 50, 30, TRUE, TRUE, 5); + + cancelbutton = dw_button_new("Cancel", 1002L); + + dw_box_pack_start(buttonbox, cancelbutton, 50, 30, TRUE, TRUE, 5); + + /* Set some nice fonts and colors */ + dw_window_set_color(lbbox, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY); + dw_window_set_color(buttonbox, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY); + dw_window_set_font(stext, "9.WarpSans"); + dw_window_set_color(stext, DW_CLR_BLACK, DW_CLR_PALEGRAY); + dw_window_set_font(listbox, "9.WarpSans"); + dw_window_set_font(okbutton, "9.WarpSans"); + dw_window_set_font(cancelbutton, "9.WarpSans"); + + dw_window_show(mainwindow); + + dw_window_set_usize(mainwindow, 170, 340); + + /* Another small example */ + flStyle |= DW_FCF_MINMAX | DW_FCF_SIZEBORDER; + + testwindow = dw_window_new(DW_DESKTOP, "Wow a test dialog! :) yay!", flStyle); + + testbox = dw_box_new(BOXVERT, 0); + + dw_box_pack_start(testwindow, testbox, 0, 0, TRUE, TRUE, 0); + + notebook = dw_notebook_new(1010L, TRUE); + + dw_box_pack_start(testbox, notebook, 100, 100, TRUE, TRUE, 0); + + testbox = dw_box_new(BOXVERT, 10); + + pageid = dw_notebook_page_new(notebook, 0L, FALSE); + + dw_notebook_pack(notebook, pageid, testbox); + + dw_notebook_page_set_text(notebook, pageid, "Test page"); + dw_notebook_page_set_status_text(notebook, pageid, "Test page"); + + testok = dw_button_new("Ok", 1003L); + + dw_box_pack_start(testbox, testok, 60, 40, TRUE, TRUE, 10); + + testcancel = dw_button_new("Cancel", 1004L); + + dw_box_pack_start(testbox, testcancel, 60, 40, TRUE, TRUE, 10); + + testbox2 = dw_box_new(BOXHORZ, 0); + + dw_box_pack_start(testbox, testbox2, 0, 0, TRUE, TRUE, 0); + + testok2 = dw_button_new("Ok", 1003L); + + dw_box_pack_start(testbox2, testok2, 60, 40, TRUE, TRUE, 10); + + dw_box_pack_splitbar_start(testbox2); + + testcancel2 = dw_button_new("Cancel", 1004L); + + dw_box_pack_start(testbox2, testcancel2, 60, 40, TRUE, TRUE, 10); + + /* Set some nice fonts and colors */ + dw_window_set_color(testbox, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY); + dw_window_set_color(testbox2, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY); + dw_window_set_font(testok, "9.WarpSans"); + dw_window_set_font(testcancel, "9.WarpSans"); + dw_window_set_font(testok2, "9.WarpSans"); + dw_window_set_font(testcancel2, "9.WarpSans"); + + dw_window_show(testwindow); + + /* Setup the function callbacks */ + dw_signal_connect(okbutton, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)mainwindow); + dw_signal_connect(cancelbutton, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)mainwindow); + dw_signal_connect(testok, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)testwindow); + dw_signal_connect(testcancel, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)testwindow); + dw_signal_connect(testok2, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)testwindow); + dw_signal_connect(testcancel2, "clicked", DW_SIGNAL_FUNC(test_callback), (void *)testwindow); + dw_signal_connect(mainwindow, "delete_event", DW_SIGNAL_FUNC(test_callback), (void *)mainwindow); + dw_signal_connect(testwindow, "delete_event", DW_SIGNAL_FUNC(test_callback), (void *)testwindow); + + dw_main(0L, NULL); + + return 0; +} +#endif \ No newline at end of file