comparison gtk3/dw.c @ 775:5ec50e403a8a

Added initial support for GTK 3.0. Split it off into its own directory. Lots of stuff is broken but it builds and sort of works.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Sun, 20 Mar 2011 05:12:40 +0000
parents
children c0e7200dad31
comparison
equal deleted inserted replaced
774:bf3e9892146f 775:5ec50e403a8a
1 /*
2 * Dynamic Windows:
3 * A GTK like implementation of the PM GUI
4 * GTK3 forwarder module for portabilty.
5 *
6 * (C) 2000-2011 Brian Smith <brian@dbsoft.org>
7 * (C) 2003-2004 Mark Hessling <m.hessling@qut.edu.au>
8 * (C) 2002 Nickolay V. Shmyrev <shmyrev@yandex.ru>
9 */
10 #include "config.h"
11 #include "dw.h"
12 #include <string.h>
13 #include <stdlib.h>
14 #if !defined(GDK_WINDOWING_WIN32)
15 # include <sys/utsname.h>
16 # include <sys/socket.h>
17 # include <sys/un.h>
18 # include <sys/mman.h>
19 #endif
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <sys/time.h>
25 #include <dirent.h>
26 #include <sys/stat.h>
27 #include <signal.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <gdk/gdkkeysyms.h>
31 #ifdef USE_IMLIB
32 #include <gdk_imlib.h>
33 #endif
34
35 #ifdef USE_GTKMOZEMBED
36 # include <gtkmozembed.h>
37 # undef GTK_TYPE_MOZ_EMBED
38 # define GTK_TYPE_MOZ_EMBED (_dw_moz_embed_get_type())
39 #endif
40
41 #ifdef USE_LIBGTKHTML2
42 # include <libgtkhtml/gtkhtml.h>
43 #endif
44
45 #ifdef USE_WEBKIT
46 # if defined(USE_WEBKIT10) || defined(USE_WEBKIT11)
47 # include <webkit/webkit.h>
48 # else
49 # include <webkit.h>
50 # endif
51 #endif
52
53 #include <gdk-pixbuf/gdk-pixbuf.h>
54
55 #if __STDC_VERSION__ < 199901L
56 # if __GNUC__ >= 2
57 # define __func__ __FUNCTION__
58 # else
59 # define __func__ "<unknown>"
60 # endif
61 #endif
62
63 #include "gtk/messagebox_error.xpm"
64 #include "gtk/messagebox_warning.xpm"
65 #include "gtk/messagebox_information.xpm"
66 #include "gtk/messagebox_question.xpm"
67
68 #ifdef USE_GTKMOZEMBED
69 extern gint mozilla_get_mouse_event_button(gpointer event);
70 extern gint mozilla_get_mouse_location( gpointer event, glong *x, glong *y);
71 #endif
72
73 /* These are used for resource management */
74 #if defined(DW_RESOURCES) && !defined(BUILD_DLL)
75 extern DWResources _resources;
76 #endif
77
78 GdkColor _colors[] =
79 {
80 { 0, 0x0000, 0x0000, 0x0000 }, /* 0 black */
81 { 0, 0xbbbb, 0x0000, 0x0000 }, /* 1 red */
82 { 0, 0x0000, 0xbbbb, 0x0000 }, /* 2 green */
83 { 0, 0xaaaa, 0xaaaa, 0x0000 }, /* 3 yellow */
84 { 0, 0x0000, 0x0000, 0xcccc }, /* 4 blue */
85 { 0, 0xbbbb, 0x0000, 0xbbbb }, /* 5 magenta */
86 { 0, 0x0000, 0xbbbb, 0xbbbb }, /* 6 cyan */
87 { 0, 0xbbbb, 0xbbbb, 0xbbbb }, /* 7 white */
88 { 0, 0x7777, 0x7777, 0x7777 }, /* 8 grey */
89 { 0, 0xffff, 0x0000, 0x0000 }, /* 9 bright red */
90 { 0, 0x0000, 0xffff, 0x0000 }, /* 10 bright green */
91 { 0, 0xeeee, 0xeeee, 0x0000 }, /* 11 bright yellow */
92 { 0, 0x0000, 0x0000, 0xffff }, /* 12 bright blue */
93 { 0, 0xffff, 0x0000, 0xffff }, /* 13 bright magenta */
94 { 0, 0x0000, 0xeeee, 0xeeee }, /* 14 bright cyan */
95 { 0, 0xffff, 0xffff, 0xffff }, /* 15 bright white */
96 };
97
98 /*
99 * List those icons that have transparency first
100 */
101 #define NUM_EXTS 5
102 char *image_exts[NUM_EXTS] =
103 {
104 ".xpm",
105 ".png",
106 ".ico",
107 ".jpg",
108 ".bmp",
109 };
110
111 #define DW_THREAD_LIMIT 50
112
113 #ifndef max
114 # define max(a,b) (((a) > (b)) ? (a) : (b))
115 #endif
116
117 #ifndef min
118 # define min(a,b) (((a) < (b)) ? (a) : (b))
119 #endif
120
121 FILE *dbgfp = NULL;
122
123 DWTID _dw_thread_list[DW_THREAD_LIMIT];
124 GdkColor _foreground[DW_THREAD_LIMIT];
125 GdkColor _background[DW_THREAD_LIMIT];
126 int _transparent[DW_THREAD_LIMIT];
127 GtkClipboard *_clipboard_object[DW_THREAD_LIMIT];
128 gchar *_clipboard_contents[DW_THREAD_LIMIT];
129
130 GtkWidget *last_window = NULL, *popup = NULL;
131
132 static int _dw_ignore_click = 0, _dw_ignore_expand = 0, _dw_color_active = 0;
133 static pthread_t _dw_thread = (pthread_t)-1;
134 static int _dw_mutex_locked[DW_THREAD_LIMIT];
135 /* Use default border size for the default enlightenment theme */
136 static int _dw_border_width = 12, _dw_border_height = 28;
137
138 #define DW_MUTEX_LOCK { int index = _find_thread_index(dw_thread_id()); if(pthread_self() != _dw_thread && _dw_mutex_locked[index] == FALSE) { gdk_threads_enter(); _dw_mutex_locked[index] = TRUE; _locked_by_me = TRUE; } }
139 #define DW_MUTEX_UNLOCK { if(pthread_self() != _dw_thread && _locked_by_me == TRUE) { gdk_threads_leave(); _dw_mutex_locked[_find_thread_index(dw_thread_id())] = FALSE; _locked_by_me = FALSE; } }
140
141 #define DEFAULT_SIZE_WIDTH 12
142 #define DEFAULT_SIZE_HEIGHT 6
143 #define DEFAULT_TITLEBAR_HEIGHT 22
144
145 static GdkVisual *_dw_cmap = NULL;
146
147 /* Signal forwarder prototypes */
148 static gint _button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
149 static gint _button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
150 static gint _motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data);
151 static gint _delete_event(GtkWidget *widget, GdkEvent *event, gpointer data);
152 static gint _key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data);
153 static gint _generic_event(GtkWidget *widget, gpointer data);
154 static gint _configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data);
155 static gint _activate_event(GtkWidget *widget, gpointer data);
156 static gint _container_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
157 static gint _container_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
158 static gint _item_select_event(GtkWidget *widget, GtkWidget *child, gpointer data);
159 static gint _expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data);
160 static gint _set_focus_event(GtkWindow *window, GtkWidget *widget, gpointer data);
161 static gint _tree_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
162 static gint _value_changed_event(GtkAdjustment *adjustment, gpointer user_data);
163 static gint _tree_select_event(GtkTreeSelection *sel, gpointer data);
164 static gint _tree_expand_event(GtkTreeView *treeview, GtkTreeIter *arg1, GtkTreePath *arg2, gpointer data);
165 static gint _switch_page_event(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer data);
166 static gint _column_click_event(GtkWidget *widget, gint column_num, gpointer data);
167
168 /* Embedable Mozilla functions*/
169 #ifdef USE_GTKMOZEMBED
170 void (*_gtk_moz_embed_go_back)(GtkMozEmbed *) = NULL;
171 void (*_gtk_moz_embed_go_forward)(GtkMozEmbed *) = NULL;
172 void (*_gtk_moz_embed_load_url)(GtkMozEmbed *, const char *) = NULL;
173 void (*_gtk_moz_embed_reload)(GtkMozEmbed *, guint32) = NULL;
174 void (*_gtk_moz_embed_stop_load)(GtkMozEmbed *) = NULL;
175 void (*_gtk_moz_embed_render_data)(GtkMozEmbed *, const char *, guint32, const char *, const char *) = NULL;
176 GtkWidget *(*_gtk_moz_embed_new)(void) = NULL;
177 GtkType (*_dw_moz_embed_get_type)(void) = NULL;
178 gboolean (*_gtk_moz_embed_can_go_back)(GtkMozEmbed *) = NULL;
179 gboolean (*_gtk_moz_embed_can_go_forward)(GtkMozEmbed *) = NULL;
180 void (*_gtk_moz_embed_set_comp_path)(const char *) = NULL;
181 void (*_gtk_moz_embed_set_profile_path)(const char *, const char *) = NULL;
182 void (*_gtk_moz_embed_push_startup)(void) = NULL;
183 #endif
184
185 #ifdef USE_LIBGTKHTML2
186 GtkHtmlContext *(*_gtk_html_context_get)(void) = NULL;
187 HtmlDocument *(*_html_document_new)(void) = NULL;
188 GtkWidget *(*_html_view_new)(void) = NULL;
189 #endif
190
191 #ifdef USE_WEBKIT
192 /*
193 * we need to add these equivalents from webkitwebview.h so we can refer to
194 * our own pointers to functions (we don't link with the webkit libraries
195 */
196 # define DW_WEBKIT_TYPE_WEB_VIEW (_webkit_web_view_get_type())
197 # define DW_WEBKIT_WEB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), DW_WEBKIT_TYPE_WEB_VIEW, WebKitWebView))
198 WEBKIT_API GType (*_webkit_web_view_get_type)(void) = NULL;
199 WEBKIT_API void (*_webkit_web_view_load_html_string)(WebKitWebView *, const gchar *, const gchar *) = NULL;
200 WEBKIT_API void (*_webkit_web_view_open)(WebKitWebView *, const gchar *) = NULL;
201 WEBKIT_API GtkWidget *(*_webkit_web_view_new)(void) = NULL;
202 WEBKIT_API void (*_webkit_web_view_go_back)(WebKitWebView *) = NULL;
203 WEBKIT_API void (*_webkit_web_view_go_forward)(WebKitWebView *) = NULL;
204 WEBKIT_API void (*_webkit_web_view_reload)(WebKitWebView *) = NULL;
205 WEBKIT_API void (*_webkit_web_view_stop_loading)(WebKitWebView *) = NULL;
206 # ifdef WEBKIT_CHECK_VERSION
207 # if WEBKIT_CHECK_VERSION(1,1,5)
208 WEBKIT_API void (*_webkit_web_frame_print)(WebKitWebFrame *) = NULL;
209 WEBKIT_API WebKitWebFrame *(*_webkit_web_view_get_focused_frame)(WebKitWebView *) = NULL;
210 # endif
211 # endif
212 #endif
213
214 typedef struct
215 {
216 GdkPixbuf *pixbuf;
217 int used;
218 unsigned long width, height;
219 } DWPrivatePixmap;
220
221 static DWPrivatePixmap *_PixmapArray = NULL;
222 static int _PixmapCount = 0;
223
224 typedef struct
225 {
226 void *func;
227 char name[30];
228
229 } SignalList;
230
231 typedef struct
232 {
233 HWND window;
234 void *func;
235 gpointer data;
236 gint cid;
237 void *intfunc;
238
239 } SignalHandler;
240
241 #define SIGNALMAX 19
242
243 /* A list of signal forwarders, to account for paramater differences. */
244 static SignalList SignalTranslate[SIGNALMAX] = {
245 { _configure_event, DW_SIGNAL_CONFIGURE },
246 { _key_press_event, DW_SIGNAL_KEY_PRESS },
247 { _button_press_event, DW_SIGNAL_BUTTON_PRESS },
248 { _button_release_event, DW_SIGNAL_BUTTON_RELEASE },
249 { _motion_notify_event, DW_SIGNAL_MOTION_NOTIFY },
250 { _delete_event, DW_SIGNAL_DELETE },
251 { _expose_event, DW_SIGNAL_EXPOSE },
252 { _activate_event, "activate" },
253 { _generic_event, DW_SIGNAL_CLICKED },
254 { _container_select_event, DW_SIGNAL_ITEM_ENTER },
255 { _container_context_event, DW_SIGNAL_ITEM_CONTEXT },
256 { _tree_context_event, "tree-context" },
257 { _item_select_event, DW_SIGNAL_LIST_SELECT },
258 { _tree_select_event, DW_SIGNAL_ITEM_SELECT },
259 { _set_focus_event, DW_SIGNAL_SET_FOCUS },
260 { _value_changed_event, DW_SIGNAL_VALUE_CHANGED },
261 { _switch_page_event, DW_SIGNAL_SWITCH_PAGE },
262 { _column_click_event, DW_SIGNAL_COLUMN_CLICK },
263 { _tree_expand_event, DW_SIGNAL_TREE_EXPAND }
264 };
265
266 /* Alignment flags */
267 #define DW_CENTER 0.5f
268 #define DW_LEFT 0.0f
269 #define DW_RIGHT 1.0f
270 #define DW_TOP 0.0f
271 #define DW_BOTTOM 1.0f
272
273 /* MDI Support Code */
274 #define GTK_MDI(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, gtk_mdi_get_type (), GtkMdi)
275 #define GTK_MDI_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, gtk_mdi_get_type (), GtkMdiClass)
276 #define GTK_IS_MDI(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, gtk_mdi_get_type ())
277
278 typedef struct _GtkMdi GtkMdi;
279 typedef struct _GtkMdiClass GtkMdiClass;
280 typedef struct _GtkMdiDragInfo GtkMdiDragInfo;
281 typedef enum _GtkMdiChildState GtkMdiChildState;
282
283 enum _GtkMdiChildState
284 {
285 CHILD_NORMAL,
286 CHILD_MAXIMIZED,
287 CHILD_ICONIFIED
288 };
289
290 struct _GtkMdi
291 {
292 GtkContainer container;
293 GList *children;
294
295 GdkPoint drag_start;
296 gint drag_button;
297 };
298
299 struct _GtkMdiClass
300 {
301 GtkContainerClass parent_class;
302
303 void (*mdi) (GtkMdi * mdi);
304 };
305
306 #include "gtk/maximize.xpm"
307 #include "gtk/minimize.xpm"
308 #include "gtk/kill.xpm"
309
310 #define GTK_MDI_BACKGROUND "Grey70"
311 #define GTK_MDI_LABEL_BACKGROUND "RoyalBlue4"
312 #define GTK_MDI_LABEL_FOREGROUND "white"
313 #define GTK_MDI_DEFAULT_WIDTH 0
314 #define GTK_MDI_DEFAULT_HEIGHT 0
315 #define GTK_MDI_MIN_HEIGHT 22
316 #define GTK_MDI_MIN_WIDTH 55
317
318 typedef struct _GtkMdiChild GtkMdiChild;
319
320 struct _GtkMdiChild
321 {
322 GtkWidget *widget;
323
324 GtkWidget *child;
325 GtkMdi *mdi;
326
327 gint x;
328 gint y;
329 gint width;
330 gint height;
331
332 GtkMdiChildState state;
333 };
334
335 static void gtk_mdi_class_init(GtkMdiClass *klass);
336 static void gtk_mdi_init(GtkMdi *mdi);
337
338 static void gtk_mdi_realize(GtkWidget *widget);
339 static void gtk_mdi_size_request(GtkWidget *widget, GtkRequisition *requisition);
340 static void gtk_mdi_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
341 static gint gtk_mdi_expose(GtkWidget *widget, GdkEventExpose *event);
342
343 /* Callbacks */
344 static gboolean move_child_callback(GtkWidget *widget, GdkEvent *event, gpointer data);
345 static gboolean resize_child_callback(GtkWidget *widget, GdkEvent *event, gpointer data);
346 static gboolean iconify_child_callback(GtkWidget *widget, GdkEvent *event, gpointer data);
347 static gboolean maximize_child_callback(GtkWidget *widget, GdkEvent *event, gpointer data);
348 static gboolean kill_child_callback(GtkWidget *widget, GdkEvent *event, gpointer data);
349
350 static void gtk_mdi_add(GtkContainer *container, GtkWidget *widget);
351 static void gtk_mdi_remove_true(GtkContainer *container, GtkWidget *widget);
352 static void gtk_mdi_forall(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);
353
354 static GtkMdiChild *get_child(GtkMdi *mdi, GtkWidget * widget);
355
356 static void _dw_log( char *format, ... )
357 {
358 va_list args;
359 va_start(args, format);
360 if ( dbgfp != NULL )
361 {
362 vfprintf( dbgfp, format, args );
363 fflush( dbgfp );
364 }
365 va_end(args);
366 }
367
368 static GType gtk_mdi_get_type(void)
369 {
370 static GType mdi_type = 0;
371
372 if (!mdi_type)
373 {
374
375 static const GTypeInfo mdi_info =
376 {
377 sizeof (GtkMdiClass),
378 NULL,
379 NULL,
380 (GClassInitFunc) gtk_mdi_class_init,
381 NULL,
382 NULL,
383 sizeof (GtkMdi),
384 0,
385 (GInstanceInitFunc) gtk_mdi_init,
386 };
387
388 mdi_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkMdi", &mdi_info, 0);
389 }
390
391 return mdi_type;
392 }
393
394 /* Local data */
395 static GtkWidgetClass *parent_class = NULL;
396
397 static void gtk_mdi_class_init(GtkMdiClass *class)
398 {
399 GObjectClass *object_class;
400 GtkWidgetClass *widget_class;
401 GtkContainerClass *container_class;
402
403 object_class = (GObjectClass *) class;
404 widget_class = (GtkWidgetClass *) class;
405 container_class = (GtkContainerClass *) class;
406
407 parent_class = g_type_class_ref (GTK_TYPE_CONTAINER);
408
409 widget_class->realize = gtk_mdi_realize;
410 #if 0 /* TODO */
411 widget_class->expose_event = gtk_mdi_expose;
412 widget_class->size_request = gtk_mdi_size_request;
413 #endif
414 widget_class->size_allocate = gtk_mdi_size_allocate;
415
416 container_class->add = gtk_mdi_add;
417 container_class->remove = gtk_mdi_remove_true;
418 container_class->forall = gtk_mdi_forall;
419 class->mdi = NULL;
420 }
421
422 static void gtk_mdi_init(GtkMdi *mdi)
423 {
424 mdi->drag_button = -1;
425 mdi->children = NULL;
426 }
427
428 static GtkWidget *gtk_mdi_new(void)
429 {
430 GtkWidget *mdi;
431 GdkColor background;
432
433 mdi = GTK_WIDGET (g_object_new (gtk_mdi_get_type (), NULL));
434 gdk_color_parse (GTK_MDI_BACKGROUND, &background);
435 gtk_widget_modify_bg (mdi, GTK_STATE_NORMAL, &background);
436
437 return mdi;
438 }
439
440 static void gtk_mdi_put(GtkMdi *mdi, GtkWidget *child_widget, gint x, gint y, GtkWidget *label)
441 {
442 GtkMdiChild *child;
443
444 GtkWidget *table;
445 GtkWidget *button[3];
446
447 GtkWidget *child_box;
448 GtkWidget *top_event_box;
449 GtkWidget *bottom_event_box;
450 GtkWidget *child_widget_box;
451 GtkWidget *image;
452
453 GdkColor color;
454 gint i, j;
455 GdkCursor *cursor;
456 GdkPixbuf *pixbuf;
457 GtkStyle *style;
458
459 child_box = gtk_event_box_new ();
460 child_widget_box = gtk_event_box_new ();
461 top_event_box = gtk_event_box_new ();
462 bottom_event_box = gtk_event_box_new ();
463 table = gtk_table_new (4, 7, FALSE);
464 gtk_table_set_row_spacings (GTK_TABLE (table), 1);
465 gtk_table_set_col_spacings (GTK_TABLE (table), 1);
466 gtk_table_set_row_spacing (GTK_TABLE (table), 3, 0);
467 gtk_table_set_col_spacing (GTK_TABLE (table), 6, 0);
468 gtk_table_set_row_spacing (GTK_TABLE (table), 2, 0);
469 gtk_table_set_col_spacing (GTK_TABLE (table), 5, 0);
470
471 for (i = 0; i < 3; i++)
472 {
473 button[i] = gtk_event_box_new ();
474 gtk_widget_set_events (button[0], GDK_BUTTON_PRESS_MASK);
475 }
476
477 gdk_color_parse (GTK_MDI_LABEL_BACKGROUND, &color);
478
479 gtk_widget_modify_bg (top_event_box, GTK_STATE_NORMAL, &color);
480 gtk_widget_modify_bg (bottom_event_box, GTK_STATE_NORMAL, &color);
481 gtk_widget_modify_bg (child_box, GTK_STATE_NORMAL, &color);
482 for (i = GTK_STATE_NORMAL; i < GTK_STATE_ACTIVE; i++)
483 {
484 for (j = 0; j < 3; j++)
485 {
486 gtk_widget_modify_bg (button[j], i, &color);
487 }
488 }
489 gdk_color_parse (GTK_MDI_LABEL_FOREGROUND, &color);
490 gtk_widget_modify_fg (label, GTK_STATE_NORMAL, &color);
491 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
492
493 gtk_container_add (GTK_CONTAINER (top_event_box), label);
494 gtk_container_add (GTK_CONTAINER (child_widget_box), child_widget);
495 gtk_widget_set_size_request (bottom_event_box, 2, 2);
496
497
498 style = gtk_widget_get_default_style ();
499 pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **)minimize_xpm);
500 image = gtk_image_new_from_pixbuf(pixbuf);
501 gtk_widget_show(image);
502 gtk_container_add (GTK_CONTAINER (button[0]), image);
503 pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **) maximize_xpm);
504 image = gtk_image_new_from_pixbuf(pixbuf);
505 gtk_widget_show(image);
506 gtk_container_add (GTK_CONTAINER (button[1]), image);
507 pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **) kill_xpm);
508 image = gtk_image_new_from_pixbuf(pixbuf);
509 gtk_widget_show(image);
510 gtk_container_add (GTK_CONTAINER (button[2]), image);
511
512 gtk_table_attach (GTK_TABLE (table), child_widget_box, 1, 6, 2, 3,
513 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
514 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
515 0, 0);
516 gtk_table_attach (GTK_TABLE (table), top_event_box, 1, 2, 1, 2,
517 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
518 0,
519 0, 0);
520 gtk_table_attach (GTK_TABLE (table), bottom_event_box, 6, 7, 3, 4,
521 0,
522 0,
523 0, 0);
524 gtk_table_attach (GTK_TABLE (table), button[0], 2, 3, 1, 2,
525 0,
526 0,
527 0, 0);
528 gtk_table_attach (GTK_TABLE (table), button[1], 3, 4, 1, 2,
529 0,
530 0,
531 0, 0);
532 gtk_table_attach (GTK_TABLE (table), button[2], 4, 5, 1, 2,
533 0,
534 0,
535 0, 0);
536
537 gtk_container_add (GTK_CONTAINER (child_box), table);
538
539 child = g_new (GtkMdiChild, 1);
540 child->widget = child_box;
541 child->x = x;
542 child->y = y;
543 child->width = -1;
544 child->height = -1;
545 child->child = child_widget;
546 child->mdi = mdi;
547 child->state = CHILD_NORMAL;
548
549 gtk_widget_set_parent (child_box, GTK_WIDGET (mdi));
550 mdi->children = g_list_append (mdi->children, child);
551
552 gtk_widget_show (child_box);
553 gtk_widget_show (table);
554 gtk_widget_show (top_event_box);
555 gtk_widget_show (bottom_event_box);
556 gtk_widget_show (child_widget_box);
557 for (i = 0; i < 3; i++)
558 {
559 gtk_widget_show (button[i]);
560 }
561
562 cursor = gdk_cursor_new (GDK_HAND1);
563 gtk_widget_realize (top_event_box);
564 gdk_window_set_cursor (gtk_widget_get_window(top_event_box), cursor);
565 cursor = gdk_cursor_new (GDK_BOTTOM_RIGHT_CORNER);
566 gtk_widget_realize (bottom_event_box);
567 gdk_window_set_cursor (gtk_widget_get_window(bottom_event_box), cursor);
568
569 g_signal_connect (G_OBJECT (top_event_box), "event",
570 G_CALLBACK (move_child_callback),
571 child);
572 g_signal_connect (G_OBJECT (bottom_event_box), "event",
573 G_CALLBACK (resize_child_callback),
574 child);
575 g_signal_connect (G_OBJECT (button[0]), "button_press_event",
576 G_CALLBACK (iconify_child_callback),
577 child);
578 g_signal_connect (G_OBJECT (button[1]), "button_press_event",
579 G_CALLBACK (maximize_child_callback),
580 child);
581 g_signal_connect (G_OBJECT (button[2]), "button_press_event",
582 G_CALLBACK (kill_child_callback),
583 child);
584 }
585
586 static void gtk_mdi_move(GtkMdi *mdi, GtkWidget *widget, gint x, gint y)
587 {
588 GtkMdiChild *child;
589
590 g_return_if_fail(GTK_IS_MDI(mdi));
591 g_return_if_fail(GTK_IS_WIDGET(widget));
592
593 child = get_child(mdi, widget);
594 g_return_if_fail(child);
595
596 child->x = x;
597 child->y = y;
598 if (gtk_widget_get_visible(widget) && gtk_widget_get_visible(GTK_WIDGET(mdi)))
599 gtk_widget_queue_resize(GTK_WIDGET(widget));
600 }
601
602 static void gtk_mdi_get_pos(GtkMdi *mdi, GtkWidget *widget, gint *x, gint *y)
603 {
604 GtkMdiChild *child;
605
606 g_return_if_fail(GTK_IS_MDI (mdi));
607 g_return_if_fail(GTK_IS_WIDGET (widget));
608
609 child = get_child(mdi, widget);
610 g_return_if_fail(child);
611
612 *x = child->x;
613 *y = child->y;
614 }
615
616 static void gtk_mdi_tile(GtkMdi *mdi)
617 {
618 int i, n;
619 int width, height;
620 GList *children;
621 GtkMdiChild *child;
622
623 g_return_if_fail(GTK_IS_MDI(mdi));
624
625 children = mdi->children;
626 n = g_list_length (children);
627 width = gtk_widget_get_allocated_width(GTK_WIDGET (mdi));
628 height = gtk_widget_get_allocated_height(GTK_WIDGET (mdi)) / n;
629 for(i=0;i<n;i++)
630 {
631 child = (GtkMdiChild *) children->data;
632 children = children->next;
633 child->x = 0;
634 child->y = i * height;
635 gtk_widget_set_size_request (child->widget, width, height);
636 child->state = CHILD_NORMAL;
637 child->width = -1;
638 child->height = -1;
639 }
640 if (gtk_widget_get_visible(GTK_WIDGET (mdi)))
641 gtk_widget_queue_resize (GTK_WIDGET (mdi));
642 return;
643 }
644 static void gtk_mdi_cascade(GtkMdi *mdi)
645 {
646 int i, n;
647 int width, height;
648 GList *children;
649 GtkMdiChild *child;
650
651 g_return_if_fail(GTK_IS_MDI(mdi));
652 if(!gtk_widget_get_visible(GTK_WIDGET(mdi)))
653 return;
654
655 children = mdi->children;
656 n = g_list_length (children);
657 width = gtk_widget_get_allocated_width(GTK_WIDGET (mdi)) / (2 * n - 1);
658 height = gtk_widget_get_allocated_height(GTK_WIDGET (mdi)) / (2 * n - 1);
659 for (i = 0; i < n; i++)
660 {
661 child = (GtkMdiChild *) children->data;
662 children = children->next;
663 child->x = i * width;
664 child->y = i * height;
665 gtk_widget_set_size_request (child->widget, width * n, height * n);
666 child->state = CHILD_NORMAL;
667 child->width = -1;
668 child->height = -1;
669 }
670 if (gtk_widget_get_visible(GTK_WIDGET(mdi)))
671 gtk_widget_queue_resize(GTK_WIDGET(mdi));
672 return;
673 }
674
675 static GtkMdiChildState gtk_mdi_get_state(GtkMdi *mdi, GtkWidget *widget)
676 {
677 GtkMdiChild *child;
678
679 g_return_val_if_fail (GTK_IS_MDI (mdi), CHILD_NORMAL);
680 g_return_val_if_fail (GTK_IS_WIDGET (widget), CHILD_NORMAL);
681
682 child = get_child (mdi, widget);
683 g_return_val_if_fail (child, CHILD_NORMAL);
684
685 return child->state;
686 }
687
688 static void gtk_mdi_set_state(GtkMdi *mdi, GtkWidget *widget, GtkMdiChildState state)
689 {
690 GtkMdiChild *child;
691
692 g_return_if_fail (GTK_IS_MDI (mdi));
693 g_return_if_fail (GTK_IS_WIDGET (widget));
694
695 child = get_child (mdi, widget);
696 g_return_if_fail (child);
697
698 child->state = state;
699 if (gtk_widget_get_visible(child->widget) && gtk_widget_get_visible(GTK_WIDGET(mdi)))
700 gtk_widget_queue_resize(GTK_WIDGET(child->widget));
701 }
702
703 static void gtk_mdi_remove(GtkMdi *mdi, GtkWidget *widget)
704 {
705 GtkMdiChild *child;
706
707 g_return_if_fail (GTK_IS_MDI (mdi));
708 child = get_child (mdi, widget);
709 g_return_if_fail (child);
710 gtk_mdi_remove_true (GTK_CONTAINER (mdi), child->widget);
711 }
712
713 static void gtk_mdi_realize(GtkWidget *widget)
714 {
715 GtkMdi *mdi;
716 GdkWindowAttr attributes;
717 gint attributes_mask;
718
719 mdi = GTK_MDI (widget);
720
721 g_return_if_fail (widget != NULL);
722 g_return_if_fail (GTK_IS_MDI (mdi));
723
724 gtk_widget_set_realized(widget, TRUE);
725
726 GtkAllocation allocation;
727 gtk_widget_get_allocation(widget, &allocation);
728 attributes.x = allocation.x;
729 attributes.y = allocation.y;
730 attributes.width = allocation.width;
731 attributes.height = allocation.height;
732 attributes.wclass = GDK_INPUT_OUTPUT;
733 attributes.window_type = GDK_WINDOW_CHILD;
734 attributes.event_mask = gtk_widget_get_events (widget) |
735 GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
736 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
737 GDK_POINTER_MOTION_HINT_MASK;
738 attributes.visual = gtk_widget_get_visual (widget);
739
740 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
741 gtk_widget_set_parent_window(widget, gdk_window_new (gtk_widget_get_parent_window(widget), &attributes, attributes_mask));
742
743 gtk_widget_set_style(widget, gtk_style_attach (gtk_widget_get_style(widget), gtk_widget_get_window(widget)));
744
745 gdk_window_set_user_data (gtk_widget_get_window(widget), widget);
746
747 gtk_style_set_background (gtk_widget_get_style(widget), gtk_widget_get_window(widget), GTK_STATE_NORMAL);
748 }
749
750 static void gtk_mdi_size_request (GtkWidget *widget, GtkRequisition *requisition)
751 {
752 GtkMdi *mdi;
753 GtkMdiChild *child;
754 GList *children;
755 GtkRequisition child_requisition;
756
757 mdi = GTK_MDI (widget);
758 requisition->width = GTK_MDI_DEFAULT_WIDTH;
759 requisition->height = GTK_MDI_DEFAULT_HEIGHT;
760
761 children = mdi->children;
762 while(children)
763 {
764 child = children->data;
765 children = children->next;
766
767 if(gtk_widget_get_visible(child->widget))
768 {
769 gtk_widget_size_request(child->widget, &child_requisition);
770 }
771 }
772 }
773
774 static void gtk_mdi_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
775 {
776 GtkMdi *mdi;
777 GtkMdiChild *child;
778 GtkAllocation child_allocation;
779 GtkRequisition child_requisition;
780 GList *children;
781
782 mdi = GTK_MDI (widget);
783
784 gtk_widget_set_allocation(widget, allocation);
785
786 if(gtk_widget_get_realized(widget))
787 gdk_window_move_resize (gtk_widget_get_window(widget),
788 allocation->x,
789 allocation->y,
790 allocation->width,
791 allocation->height);
792
793
794 children = mdi->children;
795 while(children)
796 {
797 child = children->data;
798 children = children->next;
799
800 if(gtk_widget_get_visible(child->widget))
801 {
802 gtk_widget_get_child_requisition (child->widget, &child_requisition);
803 child_allocation.x = 0;
804 child_allocation.y = 0;
805 switch (child->state)
806 {
807 case CHILD_NORMAL:
808 {
809 if ((child->width < 0) && (child->height < 0))
810 {
811 child_allocation.width = child_requisition.width;
812 child_allocation.height = child_requisition.height;
813 }
814 else
815 {
816 child_allocation.width = child->width;
817 child_allocation.height = child->height;
818 child->width = -1;
819 child->height = -1;
820 }
821 child_allocation.x += child->x;
822 child_allocation.y += child->y;
823 break;
824 }
825 case CHILD_MAXIMIZED:
826 {
827 if ((child->width < 0) && (child->height < 0))
828 {
829 child->width = child_requisition.width;
830 child->height = child_requisition.height;
831 }
832 child_allocation.width = allocation->width;
833 child_allocation.height = allocation->height;
834 }
835 break;
836 case CHILD_ICONIFIED:
837 {
838 if ((child->width < 0) && (child->height < 0))
839 {
840 child->width = child_requisition.width;
841 child->height = child_requisition.height;
842 }
843 child_allocation.x += child->x;
844 child_allocation.y += child->y;
845 child_allocation.width = child_requisition.width;
846 child_allocation.height = GTK_MDI_MIN_HEIGHT;
847 break;
848 }
849 }
850 gtk_widget_size_allocate (child->widget, &child_allocation);
851 }
852 }
853 }
854
855 static gint gtk_mdi_expose(GtkWidget *widget, GdkEventExpose *event)
856 {
857 #if 0 /* TODO: Is this needed... propogate expose is no longer supported */
858 GtkMdiChild *child;
859 GList *children;
860 GtkMdi *mdi;
861
862 g_return_val_if_fail (widget != NULL, FALSE);
863 g_return_val_if_fail (GTK_IS_MDI (widget), FALSE);
864 g_return_val_if_fail (event != NULL, FALSE);
865
866 mdi = GTK_MDI (widget);
867 for (children = mdi->children; children; children = children->next)
868 {
869 child = (GtkMdiChild *) children->data;
870 gtk_container_propagate_expose (GTK_CONTAINER (mdi),
871 child->widget,
872 event);
873 }
874 #endif
875 return FALSE;
876 }
877
878 static void gtk_mdi_add(GtkContainer *container, GtkWidget *widget)
879 {
880 GtkWidget *label;
881 label = gtk_label_new ("");
882 gtk_mdi_put (GTK_MDI (container), widget, 0, 0, label);
883 }
884
885 static void gtk_mdi_remove_true(GtkContainer *container, GtkWidget *widget)
886 {
887 GtkMdi *mdi;
888 GtkMdiChild *child = NULL;
889 GList *children;
890
891 mdi = GTK_MDI (container);
892
893 children = mdi->children;
894 while (children)
895 {
896 child = children->data;
897 if (child->widget == widget)
898 break;
899
900 children = children->next;
901 }
902
903 if(child)
904 {
905 gtk_widget_unparent (child->widget);
906 g_free (child);
907 }
908 mdi->children = g_list_remove_link (mdi->children, children);
909 g_list_free (children);
910 }
911
912 static void gtk_mdi_forall(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data)
913 {
914 GtkMdi *mdi;
915 GtkMdiChild *child;
916 GList *children;
917
918 g_return_if_fail (callback != NULL);
919
920 mdi = GTK_MDI (container);
921
922 children = mdi->children;
923 while (children)
924 {
925 child = children->data;
926 children = children->next;
927
928 (*callback) (child->widget, callback_data);
929 }
930 }
931
932 static gboolean move_child_callback(GtkWidget *widget, GdkEvent *event, gpointer data)
933 {
934 GtkMdi *mdi;
935 GtkMdiChild *child;
936
937 child = (GtkMdiChild *) data;
938 mdi = child->mdi;
939
940 g_return_val_if_fail (GTK_IS_MDI (mdi), FALSE);
941 g_return_val_if_fail (GTK_IS_EVENT_BOX (widget), FALSE);
942
943
944 switch (event->type)
945 {
946 case GDK_2BUTTON_PRESS:
947 {
948 gdk_window_raise (gtk_widget_get_window(child->widget));
949 }
950 case GDK_BUTTON_PRESS:
951 if (child->state == CHILD_MAXIMIZED)
952 return FALSE;
953 if (mdi->drag_button < 0)
954 {
955 if (gdk_pointer_grab (event->button.window,
956 FALSE,
957 GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
958 GDK_BUTTON_RELEASE_MASK,
959 NULL,
960 NULL,
961 event->button.time) != GDK_GRAB_SUCCESS)
962 return FALSE;
963
964 mdi->drag_button = event->button.button;
965
966 mdi->drag_start.x = event->button.x;
967 mdi->drag_start.y = event->button.y;
968 }
969 break;
970
971 case GDK_BUTTON_RELEASE:
972 if (mdi->drag_button < 0)
973 return FALSE;
974
975 if (mdi->drag_button == event->button.button)
976 {
977 int x, y;
978
979 gdk_pointer_ungrab (event->button.time);
980 mdi->drag_button = -1;
981
982 x = event->button.x + child->x - mdi->drag_start.x;
983 y = event->button.y + child->y - mdi->drag_start.y;
984
985 gtk_mdi_move (mdi, child->child, x, y);
986 }
987 break;
988
989 case GDK_MOTION_NOTIFY:
990 {
991 int x, y;
992
993 if (mdi->drag_button < 0)
994 return FALSE;
995
996 gdk_window_get_pointer (gtk_widget_get_window(widget), &x, &y, NULL);
997
998
999 x = x - mdi->drag_start.x + child->x;
1000 y = y - mdi->drag_start.y + child->y;
1001
1002
1003 gtk_mdi_move (mdi, child->child, x, y);
1004 }
1005 break;
1006
1007 default:
1008 break;
1009 }
1010
1011 return FALSE;
1012 }
1013
1014 static gboolean resize_child_callback(GtkWidget *widget, GdkEvent *event, gpointer data)
1015 {
1016 GtkMdi *mdi;
1017 GtkMdiChild *child;
1018
1019 child = (GtkMdiChild *) data;
1020 mdi = child->mdi;
1021
1022 g_return_val_if_fail (GTK_IS_MDI (mdi), FALSE);
1023 g_return_val_if_fail (GTK_IS_EVENT_BOX (widget), FALSE);
1024
1025 switch (event->type)
1026 {
1027 case GDK_BUTTON_PRESS:
1028 if (mdi->drag_button < 0)
1029 {
1030 if (gdk_pointer_grab (event->button.window,
1031 FALSE,
1032 GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
1033 GDK_BUTTON_RELEASE_MASK,
1034 NULL,
1035 NULL,
1036 event->button.time) != GDK_GRAB_SUCCESS)
1037 return FALSE;
1038
1039 mdi->drag_button = event->button.button;
1040 if ((child->state == CHILD_MAXIMIZED) || (child->state == CHILD_ICONIFIED))
1041 {
1042 GtkAllocation allocation;
1043
1044 child->state = CHILD_NORMAL;
1045 gtk_widget_get_allocation(child->widget, &allocation);
1046 child->x = allocation.x;
1047 child->y = allocation.y;
1048 child->width = allocation.width;
1049 child->height = allocation.height;
1050 }
1051
1052 }
1053 break;
1054
1055 case GDK_BUTTON_RELEASE:
1056 if (mdi->drag_button < 0)
1057 return FALSE;
1058
1059 if (mdi->drag_button == event->button.button)
1060 {
1061 int width, height;
1062 GtkAllocation allocation;
1063
1064 gdk_pointer_ungrab (event->button.time);
1065 mdi->drag_button = -1;
1066
1067 gtk_widget_get_allocation(widget, &allocation);
1068 width = event->button.x + allocation.x;
1069 height = event->button.y + allocation.y;
1070
1071 width = MAX (width, GTK_MDI_MIN_WIDTH);
1072 height = MAX (height, GTK_MDI_MIN_HEIGHT);
1073
1074 gtk_widget_set_size_request (child->widget, width, height);
1075 gtk_widget_queue_resize (child->widget);
1076 }
1077 break;
1078
1079 case GDK_MOTION_NOTIFY:
1080 {
1081 int x, y;
1082 int width, height;
1083 GtkAllocation allocation;
1084
1085 if (mdi->drag_button < 0)
1086 return FALSE;
1087
1088 gdk_window_get_pointer (gtk_widget_get_window(widget), &x, &y, NULL);
1089
1090 gtk_widget_get_allocation(widget, &allocation);
1091 width = x + allocation.x;
1092 height = y + allocation.y;
1093
1094 width = MAX (width, GTK_MDI_MIN_WIDTH);
1095 height = MAX (height, GTK_MDI_MIN_HEIGHT);
1096
1097 gtk_widget_set_size_request (child->widget, width, height);
1098 gtk_widget_queue_resize (child->widget);
1099 }
1100 break;
1101
1102 default:
1103 break;
1104 }
1105
1106 return FALSE;
1107 }
1108
1109 static gboolean iconify_child_callback (GtkWidget *widget, GdkEvent *event, gpointer data)
1110 {
1111 GtkMdiChild *child;
1112 child = (GtkMdiChild *) data;
1113 if(child->state == CHILD_ICONIFIED)
1114 {
1115 child->state = CHILD_NORMAL;
1116 }
1117 else
1118 {
1119 child->state = CHILD_ICONIFIED;
1120 }
1121 if(gtk_widget_get_visible(child->widget))
1122 gtk_widget_queue_resize(GTK_WIDGET (child->widget));
1123 return FALSE;
1124 }
1125
1126 static gboolean maximize_child_callback (GtkWidget *widget, GdkEvent * event, gpointer data)
1127 {
1128 GtkMdiChild *child;
1129 child = (GtkMdiChild *) data;
1130 if (child->state == CHILD_MAXIMIZED)
1131 {
1132 child->state = CHILD_NORMAL;
1133 }
1134 else
1135 {
1136 child->state = CHILD_MAXIMIZED;
1137 }
1138 if(gtk_widget_get_visible(child->widget))
1139 gtk_widget_queue_resize(GTK_WIDGET (child->widget));
1140 return FALSE;
1141 }
1142
1143 static gboolean kill_child_callback (GtkWidget *widget, GdkEvent *event, gpointer data)
1144 {
1145 GtkMdiChild *child;
1146 GtkMdi *mdi;
1147
1148 child = (GtkMdiChild *) data;
1149 mdi = child->mdi;
1150
1151 g_return_val_if_fail (GTK_IS_MDI (mdi), FALSE);
1152
1153 gtk_mdi_remove_true (GTK_CONTAINER (mdi), child->widget);
1154 return FALSE;
1155 }
1156
1157 static GtkMdiChild *get_child (GtkMdi *mdi, GtkWidget *widget)
1158 {
1159 GList *children;
1160
1161 children = mdi->children;
1162 while (children)
1163 {
1164 GtkMdiChild *child;
1165
1166 child = children->data;
1167 children = children->next;
1168
1169 if (child->child == widget)
1170 return child;
1171 }
1172
1173 return NULL;
1174 }
1175
1176 static void _dw_msleep(long period)
1177 {
1178 #ifdef __sun__
1179 /* usleep() isn't threadsafe on Solaris */
1180 struct timespec req;
1181
1182 req.tv_sec = 0;
1183 req.tv_nsec = period * 10000000;
1184
1185 nanosleep(&req, NULL);
1186 #else
1187 usleep(period * 1000);
1188 #endif
1189 }
1190
1191 /* Finds the translation function for a given signal name */
1192 static void *_findsigfunc(char *signame)
1193 {
1194 int z;
1195
1196 for(z=0;z<SIGNALMAX;z++)
1197 {
1198 if(strcasecmp(signame, SignalTranslate[z].name) == 0)
1199 return SignalTranslate[z].func;
1200 }
1201 return NULL;
1202 }
1203
1204 static SignalHandler _get_signal_handler(GtkWidget *widget, gpointer data)
1205 {
1206 int counter = (int)data;
1207 SignalHandler sh;
1208 char text[100];
1209
1210 sprintf(text, "_dw_sigwindow%d", counter);
1211 sh.window = (HWND)g_object_get_data(G_OBJECT(widget), text);
1212 sprintf(text, "_dw_sigfunc%d", counter);
1213 sh.func = (void *)g_object_get_data(G_OBJECT(widget), text);
1214 sprintf(text, "_dw_intfunc%d", counter);
1215 sh.intfunc = (void *)g_object_get_data(G_OBJECT(widget), text);
1216 sprintf(text, "_dw_sigdata%d", counter);
1217 sh.data = g_object_get_data(G_OBJECT(widget), text);
1218 sprintf(text, "_dw_sigcid%d", counter);
1219 sh.cid = (gint)g_object_get_data(G_OBJECT(widget), text);
1220
1221 return sh;
1222 }
1223
1224 static void _remove_signal_handler(GtkWidget *widget, int counter)
1225 {
1226 char text[100];
1227 gint cid;
1228
1229 sprintf(text, "_dw_sigcid%d", counter);
1230 cid = (gint)g_object_get_data(G_OBJECT(widget), text);
1231 g_signal_handler_disconnect(G_OBJECT(widget), cid);
1232 g_object_set_data(G_OBJECT(widget), text, NULL);
1233 sprintf(text, "_dw_sigwindow%d", counter);
1234 g_object_set_data(G_OBJECT(widget), text, NULL);
1235 sprintf(text, "_dw_sigfunc%d", counter);
1236 g_object_set_data(G_OBJECT(widget), text, NULL);
1237 sprintf(text, "_dw_intfunc%d", counter);
1238 g_object_set_data(G_OBJECT(widget), text, NULL);
1239 sprintf(text, "_dw_sigdata%d", counter);
1240 g_object_set_data(G_OBJECT(widget), text, NULL);
1241 }
1242
1243 static int _set_signal_handler(GtkWidget *widget, HWND window, void *func, gpointer data, void *intfunc)
1244 {
1245 int counter = (int)g_object_get_data(G_OBJECT(widget), "_dw_sigcounter");
1246 char text[100];
1247
1248 sprintf(text, "_dw_sigwindow%d", counter);
1249 g_object_set_data(G_OBJECT(widget), text, (gpointer)window);
1250 sprintf(text, "_dw_sigfunc%d", counter);
1251 g_object_set_data(G_OBJECT(widget), text, (gpointer)func);
1252 sprintf(text, "_dw_intfunc%d", counter);
1253 g_object_set_data(G_OBJECT(widget), text, (gpointer)intfunc);
1254 sprintf(text, "_dw_sigdata%d", counter);
1255 g_object_set_data(G_OBJECT(widget), text, (gpointer)data);
1256
1257 counter++;
1258 g_object_set_data(G_OBJECT(widget), "_dw_sigcounter", GINT_TO_POINTER(counter));
1259
1260 return counter - 1;
1261 }
1262
1263 static void _set_signal_handler_id(GtkWidget *widget, int counter, gint cid)
1264 {
1265 char text[100];
1266
1267 sprintf(text, "_dw_sigcid%d", counter);
1268 g_object_set_data(G_OBJECT(widget), text, GINT_TO_POINTER(cid));
1269 }
1270
1271 static gint _set_focus_event(GtkWindow *window, GtkWidget *widget, gpointer data)
1272 {
1273 SignalHandler work = _get_signal_handler((GtkWidget *)window, data);
1274 int retval = FALSE;
1275
1276 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1277 if(work.window)
1278 {
1279 int (*setfocusfunc)(HWND, void *) = work.func;
1280
1281 retval = setfocusfunc(work.window, work.data);
1282 }
1283 return retval;
1284 }
1285
1286 static gint _button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
1287 {
1288 SignalHandler work = _get_signal_handler(widget, data);
1289 int retval = FALSE;
1290
1291 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1292 if(work.window)
1293 {
1294 int (*buttonfunc)(HWND, int, int, int, void *) = work.func;
1295 int mybutton = event->button;
1296
1297 if(event->button == 3)
1298 mybutton = 2;
1299 else if(event->button == 2)
1300 mybutton = 3;
1301
1302 retval = buttonfunc(work.window, event->x, event->y, mybutton, work.data);
1303 }
1304 return retval;
1305 }
1306
1307 static gint _button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
1308 {
1309 SignalHandler work = _get_signal_handler(widget, data);
1310 int retval = FALSE;
1311
1312 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1313 if(work.window)
1314 {
1315 int (*buttonfunc)(HWND, int, int, int, void *) = work.func;
1316 int mybutton = event->button;
1317
1318 if(event->button == 3)
1319 mybutton = 2;
1320 else if(event->button == 2)
1321 mybutton = 3;
1322
1323 retval = buttonfunc(work.window, event->x, event->y, mybutton, work.data);
1324 }
1325 return retval;
1326 }
1327
1328 static gint _motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
1329 {
1330 SignalHandler work = _get_signal_handler(widget, data);
1331 int retval = FALSE;
1332
1333 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1334 if(work.window)
1335 {
1336 int (*motionfunc)(HWND, int, int, int, void *) = work.func;
1337 int keys = 0, x, y;
1338 GdkModifierType state;
1339
1340 if (event->is_hint)
1341 gdk_window_get_pointer (event->window, &x, &y, &state);
1342 else
1343 {
1344 x = event->x;
1345 y = event->y;
1346 state = event->state;
1347 }
1348
1349 if (state & GDK_BUTTON1_MASK)
1350 keys = DW_BUTTON1_MASK;
1351 if (state & GDK_BUTTON3_MASK)
1352 keys |= DW_BUTTON2_MASK;
1353 if (state & GDK_BUTTON2_MASK)
1354 keys |= DW_BUTTON3_MASK;
1355
1356 retval = motionfunc(work.window, x, y, keys, work.data);
1357 }
1358 return retval;
1359 }
1360
1361 static gint _delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
1362 {
1363 SignalHandler work = _get_signal_handler(widget, data);
1364 int retval = FALSE;
1365
1366 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1367 if(work.window)
1368 {
1369 int (*closefunc)(HWND, void *) = work.func;
1370
1371 retval = closefunc(work.window, work.data);
1372 }
1373 return retval;
1374 }
1375
1376 static gint _key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
1377 {
1378 SignalHandler work = _get_signal_handler(widget, data);
1379 int retval = FALSE;
1380
1381 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1382 if(work.window)
1383 {
1384 int (*keypressfunc)(HWND, char, int, int, void *) = work.func;
1385
1386 retval = keypressfunc(work.window, *event->string, event->keyval,
1387 event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK), work.data);
1388 }
1389 return retval;
1390 }
1391
1392 static gint _generic_event(GtkWidget *widget, gpointer data)
1393 {
1394 SignalHandler work = _get_signal_handler(widget, data);
1395 int retval = FALSE;
1396
1397 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1398 if(work.window)
1399 {
1400 int (*genericfunc)(HWND, void *) = work.func;
1401
1402 retval = genericfunc(work.window, work.data);
1403 }
1404 return retval;
1405 }
1406
1407 static gint _activate_event(GtkWidget *widget, gpointer data)
1408 {
1409 SignalHandler work = _get_signal_handler(widget, data);
1410 int retval = FALSE;
1411
1412 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1413 if(work.window && !_dw_ignore_click)
1414 {
1415 int (*activatefunc)(HWND, void *) = work.func;
1416
1417 retval = activatefunc(popup ? popup : work.window, work.data);
1418 popup = NULL;
1419 }
1420 return retval;
1421 }
1422
1423 static gint _configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
1424 {
1425 SignalHandler work = _get_signal_handler(widget, data);
1426 int retval = FALSE;
1427
1428 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1429 if(work.window)
1430 {
1431 int (*sizefunc)(HWND, int, int, void *) = work.func;
1432
1433 retval = sizefunc(work.window, event->width, event->height, work.data);
1434 }
1435 return retval;
1436 }
1437
1438 static gint _expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
1439 {
1440 SignalHandler work = _get_signal_handler(widget, data);
1441 int retval = FALSE;
1442
1443 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1444 if(work.window)
1445 {
1446 DWExpose exp;
1447 int (*exposefunc)(HWND, DWExpose *, void *) = work.func;
1448
1449 exp.x = event->area.x;
1450 exp.y = event->area.y;
1451 exp.width = event->area.width;
1452 exp.height = event->area.height;
1453 retval = exposefunc(work.window, &exp, work.data);
1454 }
1455 return retval;
1456 }
1457
1458 static gint _item_select_event(GtkWidget *widget, GtkWidget *child, gpointer data)
1459 {
1460 SignalHandler work = _get_signal_handler(widget, data);
1461 static int _dw_recursing = 0;
1462 int retval = FALSE;
1463
1464 #if 0
1465 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1466 if(_dw_recursing)
1467 return FALSE;
1468
1469 if(work.window)
1470 {
1471 int (*selectfunc)(HWND, int, void *) = work.func;
1472 GList *list;
1473 int item = 0;
1474
1475 _dw_recursing = 1;
1476
1477 if(GTK_IS_COMBO_BOX(work.window))
1478 list = GTK_LIST(GTK_COMBO_BOX(work.window)->list)->children;
1479 else if(GTK_IS_LIST(widget))
1480 list = GTK_LIST(widget)->children;
1481 else
1482 return FALSE;
1483
1484 while(list)
1485 {
1486 if(list->data == (gpointer)child)
1487 {
1488 if(!g_object_get_data(G_OBJECT(work.window), "_dw_appending"))
1489 {
1490 g_object_set_data(G_OBJECT(work.window), "_dw_item", GINT_TO_POINTER(item));
1491 if(selectfunc)
1492 retval = selectfunc(work.window, item, work.data);
1493 }
1494 break;
1495 }
1496 item++;
1497 list = list->next;
1498 }
1499 _dw_recursing = 0;
1500 }
1501 #endif
1502 return retval;
1503 }
1504
1505 static gint _container_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
1506 {
1507 SignalHandler work = _get_signal_handler(widget, data);
1508 int retval = FALSE;
1509
1510 #if 0
1511 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1512 if(work.window)
1513 {
1514 if(event->button == 3)
1515 {
1516 int (*contextfunc)(HWND, char *, int, int, void *, void *) = work.func;
1517 char *text;
1518 int row, col;
1519
1520 gtk_clist_get_selection_info(GTK_CLIST(widget), event->x, event->y, &row, &col);
1521
1522 text = (char *)gtk_clist_get_row_data(GTK_CLIST(widget), row);
1523 retval = contextfunc(work.window, text, event->x, event->y, work.data, NULL);
1524 }
1525 }
1526 #endif
1527 return retval;
1528 }
1529
1530 static gint _tree_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
1531 {
1532 SignalHandler work = _get_signal_handler(widget, data);
1533 int retval = FALSE;
1534
1535 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1536 if(work.window)
1537 {
1538 if(event->button == 3)
1539 {
1540 int (*contextfunc)(HWND, char *, int, int, void *, void *) = work.func;
1541 char *text = NULL;
1542 void *itemdata = NULL;
1543
1544 if(widget && GTK_IS_TREE_VIEW(widget))
1545 {
1546 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
1547 GtkTreeIter iter;
1548
1549 if(sel && gtk_tree_selection_get_selected(sel, NULL, &iter))
1550 {
1551 GtkTreeModel *store = (GtkTreeModel *)gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
1552 gtk_tree_model_get(store, &iter, 0, &text, 2, &itemdata, -1);
1553 }
1554 }
1555
1556 retval = contextfunc(work.window, text, event->x, event->y, work.data, itemdata);
1557 }
1558 }
1559 return retval;
1560 }
1561
1562 static gint _tree_select_event(GtkTreeSelection *sel, gpointer data)
1563 {
1564 GtkWidget *item, *widget = (GtkWidget *)gtk_tree_selection_get_tree_view(sel);
1565 int retval = FALSE;
1566
1567 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1568 if(widget)
1569 {
1570 SignalHandler work = _get_signal_handler(widget, data);
1571
1572 if(work.window)
1573 {
1574 int (*treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = work.func;
1575 GtkTreeIter iter;
1576 char *text = NULL;
1577 void *itemdata = NULL;
1578
1579 if(gtk_tree_selection_get_selected(sel, NULL, &iter))
1580 {
1581 GtkTreeModel *store = (GtkTreeModel *)gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
1582 gtk_tree_model_get(store, &iter, 0, &text, 2, &itemdata, 3, &item, -1);
1583 retval = treeselectfunc(work.window, (HTREEITEM)item, text, work.data, itemdata);
1584 }
1585 }
1586 }
1587 return retval;
1588 }
1589
1590 static gint _tree_expand_event(GtkTreeView *widget, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
1591 {
1592 SignalHandler work = _get_signal_handler((GtkWidget *)widget, data);
1593 int retval = FALSE;
1594
1595 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1596 if(!_dw_ignore_expand && work.window)
1597 {
1598 int (*treeexpandfunc)(HWND, HTREEITEM, void *) = work.func;
1599 retval = treeexpandfunc(work.window, (HTREEITEM)iter, work.data);
1600 }
1601 return retval;
1602 }
1603
1604 static gint _container_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
1605 {
1606 SignalHandler work = _get_signal_handler(widget, data);
1607 int retval = FALSE;
1608
1609 #if 0
1610 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1611 if(work.window)
1612 {
1613 if(event->button == 1 && event->type == GDK_2BUTTON_PRESS)
1614 {
1615 int (*contextfunc)(HWND, char *, void *) = work.func;
1616 char *text;
1617 int row, col;
1618
1619 gtk_clist_get_selection_info(GTK_CLIST(widget), event->x, event->y, &row, &col);
1620
1621 text = (char *)gtk_clist_get_row_data(GTK_CLIST(widget), row);
1622 retval = contextfunc(work.window, text, work.data);
1623 g_object_set_data(G_OBJECT(widget), "_dw_double_click", GINT_TO_POINTER(1));
1624 }
1625 }
1626 #endif
1627 return retval;
1628 }
1629
1630 static gint _container_enter_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
1631 {
1632 SignalHandler work = _get_signal_handler(widget, data);
1633 int retval = FALSE;
1634
1635 #if 0
1636 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1637 if(work.window && event->keyval == VK_RETURN)
1638 {
1639 int (*contextfunc)(HWND, char *, void *) = work.func;
1640 char *text;
1641
1642 text = (char *)gtk_clist_get_row_data(GTK_CLIST(widget), GTK_CLIST(widget)->focus_row);
1643 retval = contextfunc(work.window, text, work.data);
1644 }
1645 #endif
1646 return retval;
1647 }
1648
1649 /* Return the logical page id from the physical page id */
1650 int _get_logical_page(HWND handle, unsigned long pageid)
1651 {
1652 int z;
1653 GtkWidget **pagearray = g_object_get_data(G_OBJECT(handle), "_dw_pagearray");
1654 GtkWidget *thispage = gtk_notebook_get_nth_page(GTK_NOTEBOOK(handle), pageid);
1655
1656 if(pagearray && thispage)
1657 {
1658 for(z=0;z<256;z++)
1659 {
1660 if(thispage == pagearray[z])
1661 return z;
1662 }
1663 }
1664 return 256;
1665 }
1666
1667
1668 static gint _switch_page_event(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer data)
1669 {
1670 SignalHandler work = _get_signal_handler((GtkWidget *)notebook, data);
1671 int retval = FALSE;
1672
1673 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1674 if(work.window)
1675 {
1676 int (*switchpagefunc)(HWND, unsigned long, void *) = work.func;
1677 retval = switchpagefunc(work.window, _get_logical_page(GTK_WIDGET(notebook), page_num), work.data);
1678 }
1679 return retval;
1680 }
1681
1682 static gint _column_click_event(GtkWidget *widget, gint column_num, gpointer data)
1683 {
1684 SignalHandler work = _get_signal_handler(widget, data);
1685 int retval = FALSE;
1686
1687 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1688 if(work.window)
1689 {
1690 int (*clickcolumnfunc)(HWND, int, void *) = work.func;
1691 retval = clickcolumnfunc(work.window, column_num, work.data);
1692 }
1693 return retval;
1694 }
1695
1696 static gint _container_select_row(GtkWidget *widget, gint row, gint column, GdkEventButton *event, gpointer data)
1697 {
1698 #if 0
1699 SignalHandler work = _get_signal_handler(widget, data);
1700 char *rowdata = gtk_clist_get_row_data(GTK_CLIST(widget), row);
1701 int (*contextfunc)(HWND, HWND, char *, void *, void *) = work.func;
1702
1703 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1704 if(!work.window)
1705 return TRUE;
1706
1707 if(g_object_get_data(G_OBJECT(widget), "_dw_double_click"))
1708 {
1709 g_object_set_data(G_OBJECT(widget), "_dw_double_click", GINT_TO_POINTER(0));
1710 return TRUE;
1711 }
1712 return contextfunc(work.window, 0, rowdata, work.data, 0);;
1713 #endif
1714 return TRUE;
1715 }
1716
1717 static int _round_value(gfloat val)
1718 {
1719 int newval = (int)val;
1720
1721 if(val >= 0.5 + (gfloat)newval)
1722 newval++;
1723
1724 return newval;
1725 }
1726
1727 static gint _value_changed_event(GtkAdjustment *adjustment, gpointer data)
1728 {
1729 int max = _round_value(gtk_adjustment_get_upper(adjustment));
1730 int val = _round_value(gtk_adjustment_get_value(adjustment));
1731 GtkWidget *slider = (GtkWidget *)g_object_get_data(G_OBJECT(adjustment), "_dw_slider");
1732 GtkWidget *spinbutton = (GtkWidget *)g_object_get_data(G_OBJECT(adjustment), "_dw_spinbutton");
1733 GtkWidget *scrollbar = (GtkWidget *)g_object_get_data(G_OBJECT(adjustment), "_dw_scrollbar");
1734
1735 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1736 if (slider)
1737 {
1738 SignalHandler work = _get_signal_handler((GtkWidget *)adjustment, data);
1739
1740 if (work.window)
1741 {
1742 int (*valuechangedfunc)(HWND, int, void *) = work.func;
1743
1744 if(GTK_IS_VSCALE(slider))
1745 valuechangedfunc(work.window, (max - val) - 1, work.data);
1746 else
1747 valuechangedfunc(work.window, val, work.data);
1748 }
1749 }
1750 else if (scrollbar || spinbutton)
1751 {
1752 SignalHandler work = _get_signal_handler((GtkWidget *)adjustment, data);
1753
1754 if (work.window)
1755 {
1756 int (*valuechangedfunc)(HWND, int, void *) = work.func;
1757
1758 valuechangedfunc(work.window, val, work.data);
1759 }
1760 }
1761 return FALSE;
1762 }
1763
1764 static gint _default_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
1765 {
1766 GtkWidget *next = (GtkWidget *)data;
1767
1768 if ( dbgfp != NULL ) _dw_log("%s %d: %s\n",__FILE__,__LINE__,__func__);
1769 if(next)
1770 {
1771 if(event->keyval == GDK_KEY_Return)
1772 {
1773 if(GTK_IS_BUTTON(next))
1774 g_signal_emit_by_name(G_OBJECT(next), "clicked");
1775 else
1776 gtk_widget_grab_focus(next);
1777 }
1778 }
1779 return FALSE;
1780 }
1781
1782 static GdkPixbuf *_find_private_pixbuf(long id, unsigned long *userwidth, unsigned long *userheight)
1783 {
1784 if(id < _PixmapCount && _PixmapArray[id].used)
1785 {
1786 if(userwidth)
1787 *userwidth = _PixmapArray[id].width;
1788 if(userheight)
1789 *userheight = _PixmapArray[id].height;
1790 return _PixmapArray[id].pixbuf;
1791 }
1792 return NULL;
1793 }
1794
1795 static GdkPixbuf *_find_pixbuf(long id, unsigned long *userwidth, unsigned long *userheight)
1796 {
1797 char *data = NULL;
1798 int z;
1799
1800 if(id & (1 << 31))
1801 return _find_private_pixbuf((id & 0xFFFFFF), userwidth, userheight);
1802
1803 for(z=0;z<_resources.resource_max;z++)
1804 {
1805 if(_resources.resource_id[z] == id)
1806 {
1807 data = _resources.resource_data[z];
1808 break;
1809 }
1810 }
1811
1812 if(data)
1813 {
1814 GdkPixbuf *icon_pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)data);
1815
1816 if(userwidth)
1817 *userwidth = gdk_pixbuf_get_width(icon_pixbuf);
1818 if(userheight)
1819 *userheight = gdk_pixbuf_get_height(icon_pixbuf);
1820
1821 return icon_pixbuf;
1822 }
1823 return NULL;
1824 }
1825
1826 /* Find the index of a given thread */
1827 static int _find_thread_index(DWTID tid)
1828 {
1829 int z;
1830
1831 for(z=0;z<DW_THREAD_LIMIT;z++)
1832 {
1833 if(_dw_thread_list[z] == tid)
1834 return z;
1835 }
1836 return 0;
1837 }
1838
1839 /* Add a thread id to the thread list */
1840 static void _dw_thread_add(DWTID tid)
1841 {
1842 int z;
1843
1844 for(z=0;z<DW_THREAD_LIMIT;z++)
1845 {
1846 if(_dw_thread_list[z] == tid)
1847 return;
1848
1849 if(_dw_thread_list[z] == (DWTID)-1)
1850 {
1851 _dw_thread_list[z] = tid;
1852 _foreground[z].pixel = _foreground[z].red =_foreground[z].green = _foreground[z].blue = 0;
1853 _background[z].pixel = 1;
1854 _background[z].red = _background[z].green = _background[z].blue = 0;
1855 _transparent[z] = 1;
1856 _clipboard_contents[z] = NULL;
1857 _clipboard_object[z] = NULL;
1858 return;
1859 }
1860 }
1861 }
1862
1863 /* Remove a thread id to the thread list */
1864 static void _dw_thread_remove(DWTID tid)
1865 {
1866 int z;
1867
1868 for(z=0;z<DW_THREAD_LIMIT;z++)
1869 {
1870 if(_dw_thread_list[z] == (DWTID)tid)
1871 {
1872 _dw_thread_list[z] = (DWTID)-1;
1873 if ( _clipboard_contents[z] != NULL )
1874 {
1875 g_free( _clipboard_contents[z] );
1876 _clipboard_contents[z] = NULL;;
1877 }
1878 _clipboard_object[z] = NULL;;
1879 }
1880 }
1881 }
1882
1883 /* Try to load the mozilla embed shared libary */
1884 #ifdef USE_GTKMOZEMBED
1885 #include <ctype.h>
1886
1887 void init_mozembed(void)
1888 {
1889 void *handle = NULL;
1890 gchar *profile;
1891 handle = dlopen( "libgtkembedmoz.so", RTLD_LAZY );
1892
1893 /* If we loaded it, grab the symbols we want */
1894 if ( handle )
1895 {
1896 _gtk_moz_embed_go_back = dlsym(handle, "gtk_moz_embed_go_back");
1897 _gtk_moz_embed_go_forward = dlsym(handle, "gtk_moz_embed_go_forward");
1898 _gtk_moz_embed_load_url = dlsym(handle, "gtk_moz_embed_load_url");
1899 _gtk_moz_embed_reload = dlsym(handle, "gtk_moz_embed_reload");
1900 _gtk_moz_embed_stop_load = dlsym(handle, "gtk_moz_embed_stop_load");
1901 _gtk_moz_embed_render_data = dlsym(handle, "gtk_moz_embed_render_data");
1902 _dw_moz_embed_get_type = dlsym(handle, "gtk_moz_embed_get_type");
1903 _gtk_moz_embed_new = dlsym(handle, "gtk_moz_embed_new");
1904 _gtk_moz_embed_can_go_back = dlsym(handle, "gtk_moz_embed_can_go_back");
1905 _gtk_moz_embed_can_go_forward = dlsym(handle, "gtk_moz_embed_can_go_forward");
1906 _gtk_moz_embed_set_comp_path = dlsym(handle, "gtk_moz_embed_set_comp_path");
1907 _gtk_moz_embed_set_profile_path = dlsym(handle, "gtk_moz_embed_set_profile_path");
1908 _gtk_moz_embed_push_startup = dlsym(handle, "gtk_moz_embed_push_startup");
1909 _gtk_moz_embed_set_comp_path( "/usr/lib/mozilla");
1910 _gtk_moz_embed_set_comp_path( "/usr/lib/firefox");
1911 profile = g_build_filename(g_get_home_dir(), ".dwindows/mozilla", NULL);
1912
1913 /* initialize profile */
1914 _gtk_moz_embed_set_profile_path(profile, "dwindows");
1915 g_free(profile);
1916
1917 /* startup done */
1918 _gtk_moz_embed_push_startup();
1919 }
1920 }
1921 #endif
1922
1923 /* Try to load the libgtkhtml2 shared libary */
1924 #ifdef USE_LIBGTKHTML2
1925 #include <ctype.h>
1926
1927 void init_libgtkhtml2 (void)
1928 {
1929 void *handle = NULL;
1930 handle = dlopen( "libgtkhtml-2.so", RTLD_LAZY );
1931
1932 /* If we loaded it, grab the symbols we want */
1933 if ( handle )
1934 {
1935 _html_document_new = dlsym(handle, "html_document_new");
1936 _html_view_new = dlsym(handle, "html_view_new");
1937 //...
1938 _gtk_html_context_get = dlsym(handle, "gtk_html_context_get" );
1939 g_object_set( G_OBJECT(_gtk_html_context_get()), "debug_painting", FALSE, NULL );
1940 }
1941 }
1942 #endif
1943
1944 /* Try to load the WebKitGtk shared libary */
1945 #ifdef USE_WEBKIT
1946 void init_webkit(void)
1947 {
1948 char libname[100];
1949 void *handle = NULL;
1950
1951 sprintf( libname, "lib%s.so", WEBKIT_LIB);
1952 handle = dlopen( libname, RTLD_LAZY );
1953
1954 /* If we loaded it, grab the symbols we want */
1955 if ( handle )
1956 {
1957 _webkit_web_view_get_type = dlsym( handle, "webkit_web_view_get_type" );
1958 _webkit_web_view_load_html_string = dlsym( handle, "webkit_web_view_load_html_string" );
1959 _webkit_web_view_open = dlsym( handle, "webkit_web_view_open" );
1960 _webkit_web_view_new = dlsym( handle, "webkit_web_view_new" );
1961 _webkit_web_view_go_back = dlsym( handle, "webkit_web_view_go_back" );
1962 _webkit_web_view_go_forward = dlsym( handle, "webkit_web_view_go_forward" );
1963 _webkit_web_view_reload = dlsym( handle, "webkit_web_view_reload" );
1964 _webkit_web_view_stop_loading = dlsym( handle, "webkit_web_view_stop_loading" );
1965 # ifdef WEBKIT_CHECK_VERSION
1966 # if WEBKIT_CHECK_VERSION(1,1,5)
1967 _webkit_web_frame_print = dlsym( handle, "webkit_web_frame_print" );
1968 _webkit_web_view_get_focused_frame = dlsym( handle, "webkit_web_view_get_focused_frame" );
1969 # endif
1970 # endif
1971 }
1972 }
1973 #endif
1974
1975 /*
1976 * Initializes the Dynamic Windows engine.
1977 * Parameters:
1978 * newthread: True if this is the only thread.
1979 * False if there is already a message loop running.
1980 */
1981 int dw_int_init(DWResources *res, int newthread, int *argc, char **argv[])
1982 {
1983 int z;
1984 char *tmp;
1985 char *fname;
1986
1987 if(res)
1988 {
1989 _resources.resource_max = res->resource_max;
1990 _resources.resource_id = res->resource_id;
1991 _resources.resource_data = res->resource_data;
1992 }
1993 g_thread_init(NULL);
1994 gdk_threads_init();
1995
1996 gtk_init(argc, argv);
1997
1998 tmp = getenv("DW_BORDER_WIDTH");
1999 if(tmp)
2000 _dw_border_width = atoi(tmp);
2001 tmp = getenv("DW_BORDER_HEIGHT");
2002 if(tmp)
2003 _dw_border_height = atoi(tmp);
2004
2005 for(z=0;z<DW_THREAD_LIMIT;z++)
2006 _dw_thread_list[z] = (DWTID)-1;
2007
2008 gtk_rc_parse_string("style \"gtk-tooltips-style\" { bg[NORMAL] = \"#eeee00\" } widget \"gtk-tooltips\" style \"gtk-tooltips-style\"");
2009
2010 #ifdef USE_GTKMOZEMBED
2011 init_mozembed();
2012 #endif
2013
2014 #ifdef USE_LIBGTKHTML2
2015 init_libgtkhtml2();
2016 #endif
2017
2018 #ifdef USE_WEBKIT
2019 init_webkit();
2020 #endif
2021 /*
2022 * Setup logging/debugging
2023 */
2024 if ( (fname = getenv( "DWINDOWS_DEBUGFILE" ) ) != NULL )
2025 {
2026 dbgfp = fopen( fname, "w" );
2027 }
2028
2029 return TRUE;
2030 }
2031
2032 /*
2033 * Runs a message loop for Dynamic Windows.
2034 */
2035 void dw_main(void)
2036 {
2037 gdk_threads_enter();
2038 _dw_thread = pthread_self();
2039 _dw_thread_add(_dw_thread);
2040 gtk_main();
2041 _dw_thread = (pthread_t)-1;
2042 gdk_threads_leave();
2043 }
2044
2045 /*
2046 * Runs a message loop for Dynamic Windows, for a period of milliseconds.
2047 * Parameters:
2048 * milliseconds: Number of milliseconds to run the loop for.
2049 */
2050 void dw_main_sleep(int milliseconds)
2051 {
2052 struct timeval tv, start;
2053 pthread_t curr = pthread_self();
2054
2055 gettimeofday(&start, NULL);
2056
2057 if(_dw_thread == (pthread_t)-1 || _dw_thread == curr)
2058 {
2059 pthread_t orig = _dw_thread;
2060
2061 gettimeofday(&tv, NULL);
2062
2063 while(((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000) <= milliseconds)
2064 {
2065 if(orig == (pthread_t)-1)
2066 {
2067 gdk_threads_enter();
2068 _dw_thread = curr;
2069 }
2070 if(gtk_events_pending())
2071 gtk_main_iteration();
2072 else
2073 _dw_msleep(1);
2074 if(orig == (pthread_t)-1)
2075 {
2076 _dw_thread = orig;
2077 gdk_threads_leave();
2078 }
2079 gettimeofday(&tv, NULL);
2080 }
2081 }
2082 else
2083 _dw_msleep(milliseconds);
2084 }
2085
2086 /*
2087 * Processes a single message iteration and returns.
2088 */
2089 void dw_main_iteration(void)
2090 {
2091 gdk_threads_enter();
2092 _dw_thread = pthread_self();
2093 _dw_thread_add(_dw_thread);
2094 gtk_main_iteration();
2095 _dw_thread = (pthread_t)-1;
2096 gdk_threads_leave();
2097 }
2098
2099 /*
2100 * Free's memory allocated by dynamic windows.
2101 * Parameters:
2102 * ptr: Pointer to dynamic windows allocated
2103 * memory to be free()'d.
2104 */
2105 void dw_free(void *ptr)
2106 {
2107 free(ptr);
2108 }
2109
2110 /*
2111 * Allocates and initializes a dialog struct.
2112 * Parameters:
2113 * data: User defined data to be passed to functions.
2114 */
2115 DWDialog *dw_dialog_new(void *data)
2116 {
2117 DWDialog *tmp = malloc(sizeof(DWDialog));
2118
2119 if ( tmp )
2120 {
2121 tmp->eve = dw_event_new();
2122 dw_event_reset(tmp->eve);
2123 tmp->data = data;
2124 tmp->done = FALSE;
2125 tmp->method = FALSE;
2126 tmp->result = NULL;
2127 }
2128 return tmp;
2129 }
2130
2131 /*
2132 * Accepts a dialog struct and returns the given data to the
2133 * initial called of dw_dialog_wait().
2134 * Parameters:
2135 * dialog: Pointer to a dialog struct aquired by dw_dialog_new).
2136 * result: Data to be returned by dw_dialog_wait().
2137 */
2138 int dw_dialog_dismiss(DWDialog *dialog, void *result)
2139 {
2140 dialog->result = result;
2141 if(dialog->method)
2142 gtk_main_quit();
2143 else
2144 dw_event_post(dialog->eve);
2145 dialog->done = TRUE;
2146 return 0;
2147 }
2148
2149 /*
2150 * Accepts a dialog struct waits for dw_dialog_dismiss() to be
2151 * called by a signal handler with the given dialog struct.
2152 * Parameters:
2153 * dialog: Pointer to a dialog struct aquired by dw_dialog_new).
2154 */
2155 void *dw_dialog_wait(DWDialog *dialog)
2156 {
2157 void *tmp;
2158 int newprocess = 0;
2159
2160 /* _dw_thread will be -1 if dw_main hasn't been run yet. */
2161 if(_dw_thread == (pthread_t)-1)
2162 {
2163 _dw_thread = pthread_self();
2164 newprocess = 1;
2165 gdk_threads_enter();
2166 }
2167
2168 if(pthread_self() == _dw_thread)
2169 {
2170 dialog->method = TRUE;
2171 gtk_main();
2172 }
2173 else
2174 {
2175 dialog->method = FALSE;
2176 dw_event_wait(dialog->eve, -1);
2177 }
2178
2179 if(newprocess)
2180 {
2181 _dw_thread = (pthread_t)-1;
2182 gdk_threads_leave();
2183 }
2184
2185 dw_event_close(&dialog->eve);
2186 tmp = dialog->result;
2187 free(dialog);
2188 return tmp;
2189 }
2190
2191 static int _dw_ok_func(HWND window, void *data)
2192 {
2193 DWDialog *dwwait = (DWDialog *)data;
2194
2195 if(!dwwait)
2196 return FALSE;
2197
2198 dw_window_destroy((HWND)dwwait->data);
2199 dw_dialog_dismiss((DWDialog *)data, (void *)DW_MB_RETURN_OK);
2200 return FALSE;
2201 }
2202
2203 int _dw_yes_func(HWND window, void *data)
2204 {
2205 DWDialog *dwwait = (DWDialog *)data;
2206
2207 if(!dwwait)
2208 return FALSE;
2209
2210 dw_window_destroy((HWND)dwwait->data);
2211 dw_dialog_dismiss((DWDialog *)data, (void *)DW_MB_RETURN_YES);
2212 return FALSE;
2213 }
2214
2215 int _dw_no_func(HWND window, void *data)
2216 {
2217 DWDialog *dwwait = (DWDialog *)data;
2218
2219 if(!dwwait)
2220 return FALSE;
2221
2222 dw_window_destroy((HWND)dwwait->data);
2223 dw_dialog_dismiss((DWDialog *)data, (void *)DW_MB_RETURN_NO);
2224 return FALSE;
2225 }
2226
2227 int _dw_cancel_func(HWND window, void *data)
2228 {
2229 DWDialog *dwwait = (DWDialog *)data;
2230
2231 if(!dwwait)
2232 return FALSE;
2233
2234 dw_window_destroy((HWND)dwwait->data);
2235 dw_dialog_dismiss((DWDialog *)data, (void *)DW_MB_RETURN_CANCEL);
2236 return FALSE;
2237 }
2238
2239 /*
2240 * Displays a Message Box with given text and title..
2241 * Parameters:
2242 * title: The title of the message box.
2243 * flags: Defines buttons and icons to display
2244 * format: printf style format string.
2245 * ...: Additional variables for use in the format.
2246 */
2247 int dw_messagebox(char *title, int flags, char *format, ...)
2248 {
2249 HWND entrywindow, texttargetbox, imagetextbox, mainbox, okbutton, nobutton, yesbutton, cancelbutton, buttonbox, stext;
2250 ULONG flStyle = DW_FCF_TITLEBAR | DW_FCF_SHELLPOSITION | DW_FCF_SIZEBORDER;
2251 DWDialog *dwwait;
2252 va_list args;
2253 char outbuf[1000];
2254 char **xpm_data = NULL;
2255 int x, y, extra_width=0,text_width,text_height;
2256 int width,height;
2257
2258 va_start(args, format);
2259 vsnprintf(outbuf, 999, format, args);
2260 va_end(args);
2261
2262 entrywindow = dw_window_new(HWND_DESKTOP, title, flStyle);
2263 mainbox = dw_box_new(DW_VERT, 10);
2264 dw_box_pack_start(entrywindow, mainbox, 0, 0, TRUE, TRUE, 0);
2265
2266 /* determine if an icon is to be used - if so we need another HORZ box */
2267 if((flags & DW_MB_ERROR) | (flags & DW_MB_WARNING) | (flags & DW_MB_INFORMATION) | (flags & DW_MB_QUESTION))
2268 {
2269 imagetextbox = dw_box_new(DW_HORZ, 0);
2270 dw_box_pack_start(mainbox, imagetextbox, 0, 0, TRUE, TRUE, 2);
2271 texttargetbox = imagetextbox;
2272 }
2273 else
2274 {
2275 imagetextbox = NULL;
2276 texttargetbox = mainbox;
2277 }
2278
2279 if(flags & DW_MB_ERROR)
2280 xpm_data = (char **)_dw_messagebox_error;
2281 else if(flags & DW_MB_WARNING)
2282 xpm_data = (char **)_dw_messagebox_warning;
2283 else if(flags & DW_MB_INFORMATION)
2284 xpm_data = (char **)_dw_messagebox_information;
2285 else if(flags & DW_MB_QUESTION)
2286 xpm_data = (char **)_dw_messagebox_question;
2287
2288 if(xpm_data)
2289 extra_width = 32;
2290
2291 if(texttargetbox == imagetextbox)
2292 {
2293 HWND handle = dw_bitmap_new( 100 );
2294 GdkPixbuf *icon_pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)xpm_data);
2295
2296 gtk_image_set_from_pixbuf(GTK_IMAGE(handle), icon_pixbuf);
2297
2298 dw_box_pack_start( texttargetbox, handle, 32, 32, FALSE, FALSE, 2);
2299 }
2300
2301 /* Create text */
2302 text_width = 240;
2303 text_height = 0;
2304 stext = dw_text_new(outbuf, 0);
2305 dw_window_set_style(stext, DW_DT_WORDBREAK, DW_DT_WORDBREAK);
2306 dw_font_text_extents_get(stext, NULL, outbuf, &width, &height);
2307 #if 0
2308 height = height+3;
2309 if(width < text_width)
2310 text_height = height*2;
2311 else if(width < text_width*2)
2312 text_height = height*3;
2313 else if(width < text_width*3)
2314 text_height = height*4;
2315 else /* width > (3*text_width) */
2316 {
2317 text_width = (width / 3) + 60;
2318 text_height = height*4;
2319 }
2320 #else
2321 text_width = min( width, dw_screen_width() - extra_width - 100 );
2322 text_height = min( height, dw_screen_height() );
2323 #endif
2324 dw_box_pack_start(texttargetbox, stext, text_width, text_height, TRUE, TRUE, 2);
2325
2326 /* Buttons */
2327 buttonbox = dw_box_new(DW_HORZ, 10);
2328
2329 dw_box_pack_start(mainbox, buttonbox, 0, 0, TRUE, FALSE, 0);
2330
2331 dwwait = dw_dialog_new((void *)entrywindow);
2332
2333 /* which buttons ? */
2334 if(flags & DW_MB_OK)
2335 {
2336 okbutton = dw_button_new("Ok", 1001L);
2337 dw_box_pack_start(buttonbox, okbutton, 50, 30, TRUE, FALSE, 2);
2338 dw_signal_connect(okbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_ok_func), (void *)dwwait);
2339 }
2340 else if(flags & DW_MB_OKCANCEL)
2341 {
2342 okbutton = dw_button_new("Ok", 1001L);
2343 dw_box_pack_start(buttonbox, okbutton, 50, 30, TRUE, FALSE, 2);
2344 dw_signal_connect(okbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_ok_func), (void *)dwwait);
2345 cancelbutton = dw_button_new("Cancel", 1002L);
2346 dw_box_pack_start(buttonbox, cancelbutton, 50, 30, TRUE, FALSE, 2);
2347 dw_signal_connect(cancelbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_cancel_func), (void *)dwwait);
2348 }
2349 else if(flags & DW_MB_YESNO)
2350 {
2351 yesbutton = dw_button_new("Yes", 1001L);
2352 dw_box_pack_start(buttonbox, yesbutton, 50, 30, TRUE, FALSE, 2);
2353 dw_signal_connect(yesbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_yes_func), (void *)dwwait);
2354 nobutton = dw_button_new("No", 1002L);
2355 dw_box_pack_start(buttonbox, nobutton, 50, 30, TRUE, FALSE, 2);
2356 dw_signal_connect(nobutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_no_func), (void *)dwwait);
2357 }
2358 else if(flags & DW_MB_YESNOCANCEL)
2359 {
2360 yesbutton = dw_button_new("Yes", 1001L);
2361 dw_box_pack_start(buttonbox, yesbutton, 50, 30, TRUE, FALSE, 2);
2362 dw_signal_connect(yesbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_yes_func), (void *)dwwait);
2363 nobutton = dw_button_new("No", 1002L);
2364 dw_box_pack_start(buttonbox, nobutton, 50, 30, TRUE, FALSE, 2);
2365 dw_signal_connect(nobutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_no_func), (void *)dwwait);
2366 cancelbutton = dw_button_new("Cancel", 1003L);
2367 dw_box_pack_start(buttonbox, cancelbutton, 50, 30, TRUE, FALSE, 2);
2368 dw_signal_connect(cancelbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_cancel_func), (void *)dwwait);
2369 }
2370
2371 height = max(50,text_height)+100;
2372 x = ( - (text_width+60+extra_width))/2;
2373 y = (dw_screen_height() - height)/2;
2374
2375 dw_window_set_pos_size(entrywindow, x, y, (text_width+60+extra_width), height);
2376
2377 dw_window_show(entrywindow);
2378
2379 return (int)dw_dialog_wait(dwwait);
2380 }
2381
2382 /*
2383 * Minimizes or Iconifies a top-level window.
2384 * Parameters:
2385 * handle: The window handle to minimize.
2386 */
2387 int dw_window_minimize(HWND handle)
2388 {
2389 int _locked_by_me = FALSE;
2390 GtkWidget *mdi = NULL;
2391
2392 if(!handle)
2393 return 0;
2394
2395 DW_MUTEX_LOCK;
2396 if((mdi = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_mdi")) && GTK_IS_MDI(mdi))
2397 {
2398 gtk_mdi_set_state(GTK_MDI(mdi), handle, CHILD_ICONIFIED);
2399 }
2400 else
2401 {
2402 #if 0
2403 XIconifyWindow(GDK_WINDOW_XDISPLAY(GTK_WIDGET(handle)->window),
2404 GDK_WINDOW_XWINDOW(GTK_WIDGET(handle)->window),
2405 DefaultScreen (GDK_DISPLAY ()));
2406 #else
2407 gtk_window_iconify( GTK_WINDOW(handle) );
2408 #endif
2409 }
2410 DW_MUTEX_UNLOCK;
2411 return 0;
2412 }
2413
2414 /*
2415 * Makes the window topmost.
2416 * Parameters:
2417 * handle: The window handle to make topmost.
2418 */
2419 int dw_window_raise(HWND handle)
2420 {
2421 int _locked_by_me = FALSE;
2422
2423 if(!handle)
2424 return 0;
2425
2426 DW_MUTEX_LOCK;
2427 gdk_window_raise(gtk_widget_get_window(GTK_WIDGET(handle)));
2428 DW_MUTEX_UNLOCK;
2429 return 0;
2430 }
2431
2432 /*
2433 * Makes the window bottommost.
2434 * Parameters:
2435 * handle: The window handle to make bottommost.
2436 */
2437 int dw_window_lower(HWND handle)
2438 {
2439 int _locked_by_me = FALSE;
2440
2441 if(!handle)
2442 return 0;
2443
2444 DW_MUTEX_LOCK;
2445 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(handle)));
2446 DW_MUTEX_UNLOCK;
2447 return 0;
2448 }
2449
2450 /*
2451 * Makes the window visible.
2452 * Parameters:
2453 * handle: The window handle to make visible.
2454 */
2455 int dw_window_show(HWND handle)
2456 {
2457 int _locked_by_me = FALSE;
2458 GtkWidget *defaultitem;
2459 GtkWidget *mdi;
2460
2461 if (!handle)
2462 return 0;
2463
2464 DW_MUTEX_LOCK;
2465 gtk_widget_show(handle);
2466 if ((mdi = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_mdi")) && GTK_IS_MDI(mdi))
2467 {
2468 gtk_mdi_set_state(GTK_MDI(mdi), handle, CHILD_NORMAL);
2469 }
2470 else
2471 {
2472 if (gtk_widget_get_window(GTK_WIDGET(handle)))
2473 {
2474 int width = (int)g_object_get_data(G_OBJECT(handle), "_dw_width");
2475 int height = (int)g_object_get_data(G_OBJECT(handle), "_dw_height");
2476
2477 if (width && height)
2478 {
2479 gtk_widget_set_size_request(handle, width, height);
2480 g_object_set_data(G_OBJECT(handle), "_dw_width", GINT_TO_POINTER(0));
2481 g_object_set_data(G_OBJECT(handle), "_dw_height", GINT_TO_POINTER(0));
2482 }
2483
2484 gdk_window_raise(gtk_widget_get_window(GTK_WIDGET(handle)));
2485 gdk_flush();
2486 gdk_window_show(gtk_widget_get_window(GTK_WIDGET(handle)));
2487 gdk_flush();
2488 }
2489 defaultitem = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_defaultitem");
2490 if (defaultitem)
2491 gtk_widget_grab_focus(defaultitem);
2492 }
2493 DW_MUTEX_UNLOCK;
2494 return 0;
2495 }
2496
2497 /*
2498 * Makes the window invisible.
2499 * Parameters:
2500 * handle: The window handle to make visible.
2501 */
2502 int dw_window_hide(HWND handle)
2503 {
2504 int _locked_by_me = FALSE;
2505 GtkWidget *mdi = NULL;
2506
2507 if(!handle)
2508 return 0;
2509
2510 DW_MUTEX_LOCK;
2511 if((mdi = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_mdi")) && GTK_IS_MDI(mdi))
2512 {
2513 gtk_mdi_set_state(GTK_MDI(mdi), handle, CHILD_ICONIFIED);
2514 }
2515 else
2516 gtk_widget_hide(handle);
2517 DW_MUTEX_UNLOCK;
2518 return 0;
2519 }
2520
2521 /*
2522 * Destroys a window and all of it's children.
2523 * Parameters:
2524 * handle: The window handle to destroy.
2525 */
2526 int dw_window_destroy(HWND handle)
2527 {
2528 int _locked_by_me = FALSE;
2529 GtkWidget *mdi = NULL;
2530
2531 if(!handle)
2532 return 0;
2533
2534 DW_MUTEX_LOCK;
2535 if((mdi = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_mdi")) && GTK_IS_MDI(mdi))
2536 {
2537 gtk_mdi_remove(GTK_MDI(mdi), handle);
2538 }
2539 if(GTK_IS_WIDGET(handle))
2540 {
2541 GtkWidget *eventbox = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_eventbox");
2542
2543 if(eventbox && GTK_IS_WIDGET(eventbox))
2544 gtk_widget_destroy(eventbox);
2545 else
2546 gtk_widget_destroy(handle);
2547 }
2548 DW_MUTEX_UNLOCK;
2549 return 0;
2550 }
2551
2552 /* Causes entire window to be invalidated and redrawn.
2553 * Parameters:
2554 * handle: Toplevel window handle to be redrawn.
2555 */
2556 void dw_window_redraw(HWND handle)
2557 {
2558 }
2559
2560 /*
2561 * Changes a window's parent to newparent.
2562 * Parameters:
2563 * handle: The window handle to destroy.
2564 * newparent: The window's new parent window.
2565 */
2566 void dw_window_reparent(HWND handle, HWND newparent)
2567 {
2568 int _locked_by_me = FALSE;
2569
2570 DW_MUTEX_LOCK;
2571 gdk_window_reparent(gtk_widget_get_window(GTK_WIDGET(handle)), newparent ? gtk_widget_get_window(GTK_WIDGET(newparent)) : GDK_ROOT_WINDOW(), 0, 0);
2572 DW_MUTEX_UNLOCK;
2573 }
2574
2575 static int _set_font(HWND handle, char *fontname)
2576 {
2577 int retval = FALSE;
2578 PangoFontDescription *font = pango_font_description_from_string(fontname);
2579
2580 if(font)
2581 {
2582 gtk_widget_modify_font(handle, font);
2583 pango_font_description_free(font);
2584 }
2585 return retval;
2586 }
2587
2588 /*
2589 * Sets the font used by a specified window (widget) handle.
2590 * Parameters:
2591 * handle: The window (widget) handle.
2592 * fontname: Name and size of the font in the form "size.fontname"
2593 */
2594 int dw_window_set_font(HWND handle, char *fontname)
2595 {
2596 PangoFontDescription *pfont;
2597 GtkWidget *handle2 = handle;
2598 char *font;
2599 int _locked_by_me = FALSE;
2600 gpointer data;
2601
2602 DW_MUTEX_LOCK;
2603 if(GTK_IS_SCROLLED_WINDOW(handle))
2604 {
2605 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
2606 if(tmp)
2607 handle2 = tmp;
2608 }
2609 font = strdup(fontname);
2610
2611 /* Free old font name if one is allocated */
2612 data = g_object_get_data(G_OBJECT(handle2), "_dw_fontname");
2613 if(data)
2614 free(data);
2615
2616 g_object_set_data(G_OBJECT(handle2), "_dw_fontname", (gpointer)font);
2617 pfont = pango_font_description_from_string(fontname);
2618
2619 if(pfont)
2620 {
2621 gtk_widget_modify_font(handle2, pfont);
2622 pango_font_description_free(pfont);
2623 }
2624 DW_MUTEX_UNLOCK;
2625 return TRUE;
2626 }
2627
2628 /*
2629 * Gets the font used by a specified window (widget) handle.
2630 * Parameters:
2631 * handle: The window (widget) handle.
2632 */
2633 char *dw_window_get_font(HWND handle)
2634 {
2635 PangoFontDescription *pfont;
2636 PangoContext *pcontext;
2637 GtkWidget *handle2 = handle;
2638 char *font;
2639 char *retfont=NULL;
2640 int _locked_by_me = FALSE;
2641 gpointer data;
2642
2643 DW_MUTEX_LOCK;
2644 if(GTK_IS_SCROLLED_WINDOW(handle))
2645 {
2646 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
2647 if(tmp)
2648 handle2 = tmp;
2649 }
2650
2651 #if 0
2652 /* Free old font name if one is allocated */
2653 data = g_object_get_data(G_OBJECT(handle2), "_dw_fontname");
2654 if(data)
2655 free(data);
2656
2657 g_object_set_data(G_OBJECT(handle2), "_dw_fontname", (gpointer)font);
2658 #endif
2659
2660 pcontext = gtk_widget_get_pango_context( handle2 );
2661 if ( pcontext )
2662 {
2663 pfont = pango_context_get_font_description( pcontext );
2664 if ( pfont )
2665 {
2666 font = pango_font_description_to_string( pfont );
2667 retfont = strdup(font);
2668 g_free( font );
2669 }
2670 }
2671 DW_MUTEX_UNLOCK;
2672 return retfont;
2673 }
2674
2675 void _free_gdk_colors(HWND handle)
2676 {
2677 GdkColor *old = (GdkColor *)g_object_get_data(G_OBJECT(handle), "_dw_foregdk");
2678
2679 if(old)
2680 free(old);
2681
2682 old = (GdkColor *)g_object_get_data(G_OBJECT(handle), "_dw_backgdk");
2683
2684 if(old)
2685 free(old);
2686 }
2687
2688 /* Free old color pointers and allocate new ones */
2689 static void _save_gdk_colors(HWND handle, GdkColor fore, GdkColor back)
2690 {
2691 GdkColor *foregdk = malloc(sizeof(GdkColor));
2692 GdkColor *backgdk = malloc(sizeof(GdkColor));
2693
2694 _free_gdk_colors(handle);
2695
2696 *foregdk = fore;
2697 *backgdk = back;
2698
2699 g_object_set_data(G_OBJECT(handle), "_dw_foregdk", (gpointer)foregdk);
2700 g_object_set_data(G_OBJECT(handle), "_dw_backgdk", (gpointer)backgdk);
2701 }
2702
2703 static int _set_color(HWND handle, unsigned long fore, unsigned long back)
2704 {
2705 /* Remember that each color component in X11 use 16 bit no matter
2706 * what the destination display supports. (and thus GDK)
2707 */
2708 GdkColor forecolor, backcolor;
2709
2710 if(fore & DW_RGB_COLOR)
2711 {
2712 forecolor.pixel = 0;
2713 forecolor.red = DW_RED_VALUE(fore) << 8;
2714 forecolor.green = DW_GREEN_VALUE(fore) << 8;
2715 forecolor.blue = DW_BLUE_VALUE(fore) << 8;
2716
2717 gtk_widget_modify_text(handle, 0, &forecolor);
2718 gtk_widget_modify_text(handle, 1, &forecolor);
2719 gtk_widget_modify_fg(handle, 0, &forecolor);
2720 gtk_widget_modify_fg(handle, 1, &forecolor);
2721 }
2722 else if(fore != DW_CLR_DEFAULT)
2723 {
2724 forecolor = _colors[fore];
2725
2726 gtk_widget_modify_text(handle, 0, &_colors[fore]);
2727 gtk_widget_modify_text(handle, 1, &_colors[fore]);
2728 gtk_widget_modify_fg(handle, 0, &_colors[fore]);
2729 gtk_widget_modify_fg(handle, 1, &_colors[fore]);
2730 }
2731 if(back & DW_RGB_COLOR)
2732 {
2733 backcolor.pixel = 0;
2734 backcolor.red = DW_RED_VALUE(back) << 8;
2735 backcolor.green = DW_GREEN_VALUE(back) << 8;
2736 backcolor.blue = DW_BLUE_VALUE(back) << 8;
2737
2738 gtk_widget_modify_base(handle, 0, &backcolor);
2739 gtk_widget_modify_base(handle, 1, &backcolor);
2740 gtk_widget_modify_bg(handle, 0, &backcolor);
2741 gtk_widget_modify_bg(handle, 1, &backcolor);
2742 }
2743 else if(back != DW_CLR_DEFAULT)
2744 {
2745 backcolor = _colors[back];
2746
2747 gtk_widget_modify_base(handle, 0, &_colors[back]);
2748 gtk_widget_modify_base(handle, 1, &_colors[back]);
2749 gtk_widget_modify_bg(handle, 0, &_colors[back]);
2750 gtk_widget_modify_bg(handle, 1, &_colors[back]);
2751 }
2752
2753 _save_gdk_colors(handle, forecolor, backcolor);
2754
2755 return TRUE;
2756 }
2757 /*
2758 * Sets the colors used by a specified window (widget) handle.
2759 * Parameters:
2760 * handle: The window (widget) handle.
2761 * fore: Foreground color in RGB format.
2762 * back: Background color in RGB format.
2763 */
2764 int dw_window_set_color(HWND handle, unsigned long fore, unsigned long back)
2765 {
2766 GtkWidget *handle2 = handle;
2767 int _locked_by_me = FALSE;
2768
2769 DW_MUTEX_LOCK;
2770
2771 if(GTK_IS_SCROLLED_WINDOW(handle) || GTK_IS_BOX(handle))
2772 {
2773 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
2774 if(tmp)
2775 handle2 = tmp;
2776 }
2777 else if(GTK_IS_TABLE(handle))
2778 {
2779 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_eventbox");
2780 if(tmp)
2781 handle2 = tmp;
2782 }
2783
2784 _set_color(handle2, fore, back);
2785
2786 DW_MUTEX_UNLOCK;
2787 return TRUE;
2788 }
2789
2790 /*
2791 * Sets the font used by a specified window (widget) handle.
2792 * Parameters:
2793 * handle: The window (widget) handle.
2794 * border: Size of the window border in pixels.
2795 */
2796 int dw_window_set_border(HWND handle, int border)
2797 {
2798 /* TODO */
2799 return 0;
2800 }
2801
2802 /*
2803 * Captures the mouse input to this window.
2804 * Parameters:
2805 * handle: Handle to receive mouse input.
2806 */
2807 void dw_window_capture(HWND handle)
2808 {
2809 int _locked_by_me = FALSE;
2810
2811 DW_MUTEX_LOCK;
2812 gdk_pointer_grab(gtk_widget_get_window(handle), TRUE, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK, NULL, NULL, GDK_CURRENT_TIME);
2813 DW_MUTEX_UNLOCK;
2814 }
2815
2816 /*
2817 * Changes the appearance of the mouse pointer.
2818 * Parameters:
2819 * handle: Handle to widget for which to change.
2820 * cursortype: ID of the pointer you want.
2821 */
2822 void dw_window_set_pointer(HWND handle, int pointertype)
2823 {
2824 int _locked_by_me = FALSE;
2825 GdkCursor *cursor;
2826
2827 DW_MUTEX_LOCK;
2828 if(pointertype & (1 << 31))
2829 {
2830 GdkPixbuf *pixbuf = _find_private_pixbuf((pointertype & 0xFFFFFF), NULL, NULL);
2831 cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, 8, 8);
2832 }
2833 else if(!pointertype)
2834 cursor = NULL;
2835 else
2836 cursor = gdk_cursor_new(pointertype);
2837 if(handle && gtk_widget_get_window(handle))
2838 gdk_window_set_cursor(gtk_widget_get_window(handle), cursor);
2839 if(cursor)
2840 gdk_cursor_unref(cursor);
2841 DW_MUTEX_UNLOCK;
2842 }
2843
2844 /*
2845 * Releases previous mouse capture.
2846 */
2847 void dw_window_release(void)
2848 {
2849 int _locked_by_me = FALSE;
2850
2851 DW_MUTEX_LOCK;
2852 gdk_pointer_ungrab(GDK_CURRENT_TIME);
2853 DW_MUTEX_UNLOCK;
2854 }
2855
2856 /*
2857 * Create a new Window Frame.
2858 * Parameters:
2859 * owner: The Owner's window handle or HWND_DESKTOP.
2860 * title: The Window title.
2861 * flStyle: Style flags, see the PM reference.
2862 */
2863 HWND dw_window_new(HWND hwndOwner, char *title, unsigned long flStyle)
2864 {
2865 GtkWidget *tmp;
2866 int _locked_by_me = FALSE;
2867 int flags = 0;
2868
2869 DW_MUTEX_LOCK;
2870 if(hwndOwner && GTK_IS_MDI(hwndOwner))
2871 {
2872 GtkWidget *label;
2873
2874 tmp = dw_box_new(DW_VERT, 0);
2875
2876 label = gtk_label_new(title);
2877 gtk_widget_show(label);
2878 g_object_set_data(G_OBJECT(tmp), "_dw_mdi_child", GINT_TO_POINTER(1));
2879 g_object_set_data(G_OBJECT(tmp), "_dw_mdi_title", (gpointer)label);
2880 g_object_set_data(G_OBJECT(tmp), "_dw_mdi", (gpointer)hwndOwner);
2881
2882 gtk_mdi_put(GTK_MDI(hwndOwner), tmp, 100, 75, label);
2883 }
2884 else
2885 {
2886 last_window = tmp = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2887
2888 gtk_window_set_title(GTK_WINDOW(tmp), title);
2889 if(!(flStyle & DW_FCF_SIZEBORDER))
2890 gtk_window_set_resizable(GTK_WINDOW(tmp), FALSE);
2891
2892 gtk_widget_realize(tmp);
2893
2894 if(flStyle & DW_FCF_TITLEBAR)
2895 flags |= GDK_DECOR_TITLE;
2896
2897 if(flStyle & DW_FCF_MINMAX)
2898 flags |= GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE;
2899
2900 if(flStyle & DW_FCF_SIZEBORDER)
2901 flags |= GDK_DECOR_RESIZEH | GDK_DECOR_BORDER;
2902
2903 if(flStyle & DW_FCF_BORDER || flStyle & DW_FCF_DLGBORDER)
2904 flags |= GDK_DECOR_BORDER;
2905
2906 if(flStyle & DW_FCF_MAXIMIZE)
2907 {
2908 flags &= ~DW_FCF_MAXIMIZE;
2909 gtk_window_maximize(GTK_WINDOW(tmp));
2910 }
2911 if(flStyle & DW_FCF_MINIMIZE)
2912 {
2913 flags &= ~DW_FCF_MINIMIZE;
2914 gtk_window_iconify(GTK_WINDOW(tmp));
2915 }
2916
2917 gdk_window_set_decorations(gtk_widget_get_window(tmp), flags);
2918
2919 if(hwndOwner)
2920 gdk_window_reparent(gtk_widget_get_window(GTK_WIDGET(tmp)), gtk_widget_get_window(GTK_WIDGET(hwndOwner)), 0, 0);
2921
2922 if(flStyle & DW_FCF_SIZEBORDER)
2923 g_object_set_data(G_OBJECT(tmp), "_dw_size", GINT_TO_POINTER(1));
2924 }
2925 g_object_set_data(G_OBJECT(tmp), "_dw_style", GINT_TO_POINTER(flStyle));
2926 DW_MUTEX_UNLOCK;
2927 return tmp;
2928 }
2929
2930 /*
2931 * Create a new Box to be packed.
2932 * Parameters:
2933 * type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
2934 * pad: Number of pixels to pad around the box.
2935 */
2936 HWND dw_box_new(int type, int pad)
2937 {
2938 GtkWidget *tmp, *eventbox;
2939 int _locked_by_me = FALSE;
2940
2941 DW_MUTEX_LOCK;
2942 tmp = gtk_table_new(1, 1, FALSE);
2943 eventbox = gtk_event_box_new();
2944
2945 gtk_widget_show(eventbox);
2946 g_object_set_data(G_OBJECT(tmp), "_dw_eventbox", (gpointer)eventbox);
2947 g_object_set_data(G_OBJECT(tmp), "_dw_boxtype", GINT_TO_POINTER(type));
2948 g_object_set_data(G_OBJECT(tmp), "_dw_boxpad", GINT_TO_POINTER(pad));
2949 gtk_widget_show(tmp);
2950 DW_MUTEX_UNLOCK;
2951 return tmp;
2952 }
2953
2954 #ifndef INCOMPLETE
2955 /*
2956 * Create a new scrollable Box to be packed.
2957 * Parameters:
2958 * type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
2959 * pad: Number of pixels to pad around the box.
2960 * This works fine under GTK+, but is incomplete on other platforms
2961 */
2962 HWND dw_scrollbox_new( int type, int pad )
2963 {
2964 GtkWidget *tmp, *box, *eventbox;
2965 int _locked_by_me = FALSE;
2966
2967 DW_MUTEX_LOCK;
2968 tmp = gtk_scrolled_window_new(NULL, NULL);
2969 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (tmp), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2970
2971 box = gtk_table_new(1, 1, FALSE);
2972 eventbox = gtk_event_box_new();
2973
2974 gtk_widget_show(eventbox);
2975 g_object_set_data(G_OBJECT(box), "_dw_eventbox", (gpointer)eventbox);
2976 g_object_set_data(G_OBJECT(box), "_dw_boxtype", GINT_TO_POINTER(type));
2977 g_object_set_data(G_OBJECT(box), "_dw_boxpad", GINT_TO_POINTER(pad));
2978 g_object_set_data(G_OBJECT(tmp), "_dw_boxhandle", (gpointer)box);
2979
2980 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tmp),box);
2981 g_object_set_data(G_OBJECT(tmp), "_dw_user", box);
2982 gtk_widget_show(box);
2983 gtk_widget_show(tmp);
2984
2985 DW_MUTEX_UNLOCK;
2986 return tmp;
2987 }
2988
2989 /*
2990 * Returns the position of the scrollbar in the scrollbox
2991 * Parameters:
2992 * handle: Handle to the scrollbox to be queried.
2993 * orient: The vertical or horizontal scrollbar.
2994 */
2995 int dw_scrollbox_get_pos(HWND handle, int orient)
2996 {
2997 int val = -1, _locked_by_me = FALSE;
2998 GtkAdjustment *adjustment;
2999
3000 if (!handle)
3001 return -1;
3002
3003 DW_MUTEX_LOCK;
3004 if ( orient == DW_HORZ )
3005 adjustment = gtk_scrolled_window_get_hadjustment( GTK_SCROLLED_WINDOW(handle) );
3006 else
3007 adjustment = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(handle) );
3008 if (adjustment)
3009 val = _round_value(gtk_adjustment_get_value(adjustment));
3010 DW_MUTEX_UNLOCK;
3011 return val;
3012 }
3013
3014 /*
3015 * Gets the range for the scrollbar in the scrollbox.
3016 * Parameters:
3017 * handle: Handle to the scrollbox to be queried.
3018 * orient: The vertical or horizontal scrollbar.
3019 */
3020 int API dw_scrollbox_get_range(HWND handle, int orient)
3021 {
3022 int range = -1, _locked_by_me = FALSE;
3023 GtkAdjustment *adjustment;
3024
3025 if (!handle)
3026 return -1;
3027
3028 DW_MUTEX_LOCK;
3029 if ( orient == DW_HORZ )
3030 adjustment = gtk_scrolled_window_get_hadjustment( GTK_SCROLLED_WINDOW(handle) );
3031 else
3032 adjustment = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(handle) );
3033 if (adjustment)
3034 {
3035 range = _round_value(gtk_adjustment_get_upper(adjustment));
3036 }
3037 DW_MUTEX_UNLOCK;
3038 return range;
3039 }
3040 #endif
3041
3042 /*
3043 * Create a new Group Box to be packed.
3044 * Parameters:
3045 * type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
3046 * pad: Number of pixels to pad around the box.
3047 * title: Text to be displayined in the group outline.
3048 */
3049 HWND dw_groupbox_new(int type, int pad, char *title)
3050 {
3051 GtkWidget *tmp, *frame, *label;
3052 PangoFontDescription *pfont;
3053 PangoContext *pcontext;
3054 int _locked_by_me = FALSE;
3055
3056 DW_MUTEX_LOCK;
3057 frame = gtk_frame_new(NULL);
3058 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
3059 gtk_frame_set_label(GTK_FRAME(frame), title && *title ? title : NULL);
3060 /*
3061 * Get the current font for the frame's label and make it bold
3062 */
3063 label = gtk_frame_get_label_widget(GTK_FRAME(frame));
3064 pcontext = gtk_widget_get_pango_context( label );
3065 if ( pcontext )
3066 {
3067 pfont = pango_context_get_font_description( pcontext );
3068 if ( pfont )
3069 {
3070 pango_font_description_set_weight( pfont, PANGO_WEIGHT_BOLD );
3071 gtk_widget_modify_font( label, pfont );
3072 }
3073 }
3074
3075 tmp = gtk_table_new(1, 1, FALSE);
3076 gtk_container_set_border_width(GTK_CONTAINER(tmp), pad);
3077 g_object_set_data(G_OBJECT(tmp), "_dw_boxtype", GINT_TO_POINTER(type));
3078 g_object_set_data(G_OBJECT(tmp), "_dw_boxpad", GINT_TO_POINTER(pad));
3079 g_object_set_data(G_OBJECT(frame), "_dw_boxhandle", (gpointer)tmp);
3080 gtk_container_add(GTK_CONTAINER(frame), tmp);
3081 gtk_widget_show(tmp);
3082 gtk_widget_show(frame);
3083 DW_MUTEX_UNLOCK;
3084 return frame;
3085 }
3086
3087 /*
3088 * Create a new MDI Frame to be packed.
3089 * Parameters:
3090 * id: An ID to be used with dw_window_from_id or 0L.
3091 */
3092 HWND dw_mdi_new(unsigned long id)
3093 {
3094 GtkWidget *tmp;
3095 int _locked_by_me = FALSE;
3096
3097 DW_MUTEX_LOCK;
3098 tmp = gtk_mdi_new();
3099 gtk_widget_show(tmp);
3100 DW_MUTEX_UNLOCK;
3101 return tmp;
3102 }
3103
3104 /*
3105 * Create a bitmap object to be packed.
3106 * Parameters:
3107 * id: An ID to be used with dw_window_from_id() or 0L.
3108 */
3109 HWND dw_bitmap_new(unsigned long id)
3110 {
3111 GtkWidget *tmp;
3112 int _locked_by_me = FALSE;
3113
3114 DW_MUTEX_LOCK;
3115 tmp = gtk_image_new();
3116 gtk_widget_show(tmp);
3117 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3118 DW_MUTEX_UNLOCK;
3119 return tmp;
3120 }
3121
3122 /*
3123 * Create a notebook object to be packed.
3124 * Parameters:
3125 * id: An ID to be used for getting the resource from the
3126 * resource file.
3127 */
3128 HWND dw_notebook_new(unsigned long id, int top)
3129 {
3130 GtkWidget *tmp, **pagearray = calloc(sizeof(GtkWidget *), 256);
3131 int _locked_by_me = FALSE;
3132
3133 DW_MUTEX_LOCK;
3134 tmp = gtk_notebook_new();
3135 if(top)
3136 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tmp), GTK_POS_TOP);
3137 else
3138 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tmp), GTK_POS_BOTTOM);
3139 gtk_notebook_set_scrollable(GTK_NOTEBOOK(tmp), TRUE);
3140 #if 0
3141 gtk_notebook_popup_enable(GTK_NOTEBOOK(tmp));
3142 #endif
3143 gtk_widget_show(tmp);
3144 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3145 g_object_set_data(G_OBJECT(tmp), "_dw_pagearray", (gpointer)pagearray);
3146 DW_MUTEX_UNLOCK;
3147 return tmp;
3148 }
3149
3150 /*
3151 * Create a menu object to be popped up.
3152 * Parameters:
3153 * id: An ID to be used for getting the resource from the
3154 * resource file.
3155 */
3156 HMENUI dw_menu_new(unsigned long id)
3157 {
3158 int _locked_by_me = FALSE;
3159 GtkAccelGroup *accel_group;
3160 HMENUI tmp;
3161
3162 DW_MUTEX_LOCK;
3163 tmp = gtk_menu_new();
3164 gtk_widget_show(tmp);
3165 accel_group = gtk_accel_group_new();
3166 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3167 g_object_set_data(G_OBJECT(tmp), "_dw_accel", (gpointer)accel_group);
3168 DW_MUTEX_UNLOCK;
3169 return tmp;
3170 }
3171
3172 /*
3173 * Create a menubar on a window.
3174 * Parameters:
3175 * location: Handle of a window frame to be attached to.
3176 * If there is no box already packed into the "location", the menu will not appear
3177 * so tell the user.
3178 */
3179 HMENUI dw_menubar_new(HWND location)
3180 {
3181 GtkWidget *box;
3182 int _locked_by_me = FALSE;
3183 GtkAccelGroup *accel_group;
3184 HMENUI tmp;
3185
3186 DW_MUTEX_LOCK;
3187 tmp = gtk_menu_bar_new();
3188 box = (GtkWidget *)g_object_get_data(G_OBJECT(location), "_dw_user");
3189 gtk_widget_show(tmp);
3190 accel_group = gtk_accel_group_new();
3191 g_object_set_data(G_OBJECT(tmp), "_dw_accel", (gpointer)accel_group);
3192
3193 if (box)
3194 gtk_box_pack_end(GTK_BOX(box), tmp, FALSE, FALSE, 0);
3195 else
3196 fprintf(stderr,"dw_menubar_new(): Coding error: You MUST pack a box into the window in which this menubar is to be added BEFORE calling this function.\n");
3197
3198 DW_MUTEX_UNLOCK;
3199 return tmp;
3200 }
3201
3202 /*
3203 * Destroys a menu created with dw_menubar_new or dw_menu_new.
3204 * Parameters:
3205 * menu: Handle of a menu.
3206 */
3207 void dw_menu_destroy(HMENUI *menu)
3208 {
3209 if(menu && *menu)
3210 {
3211 int _locked_by_me = FALSE;
3212
3213 DW_MUTEX_LOCK;
3214 gtk_widget_destroy(*menu);
3215 *menu = NULL;
3216 DW_MUTEX_UNLOCK;
3217 }
3218 }
3219
3220 char _removetilde(char *dest, char *src)
3221 {
3222 int z, cur=0;
3223 char accel = '\0';
3224
3225 for(z=0;z<strlen(src);z++)
3226 {
3227 if(src[z] != '~')
3228 {
3229 dest[cur] = src[z];
3230 cur++;
3231 }
3232 else
3233 {
3234 dest[cur] = '_';
3235 accel = src[z+1];
3236 cur++;
3237 }
3238 }
3239 dest[cur] = 0;
3240 return accel;
3241 }
3242
3243 /*
3244 * Adds a menuitem or submenu to an existing menu.
3245 * Parameters:
3246 * menu: The handle to the existing menu.
3247 * title: The title text on the menu item to be added.
3248 * id: An ID to be used for message passing.
3249 * flags: Extended attributes to set on the menu.
3250 * end: If TRUE memu is positioned at the end of the menu.
3251 * check: If TRUE menu is "check"able.
3252 * submenu: Handle to an existing menu to be a submenu or NULL.
3253 */
3254 HWND dw_menu_append_item(HMENUI menu, char *title, unsigned long id, unsigned long flags, int end, int check, HMENUI submenu)
3255 {
3256 GtkWidget *tmphandle;
3257 char accel, *tempbuf = malloc(strlen(title)+1);
3258 int _locked_by_me = FALSE, submenucount;
3259 guint tmp_key;
3260 GtkAccelGroup *accel_group;
3261
3262 if (!menu)
3263 {
3264 free(tempbuf);
3265 return NULL;
3266 }
3267
3268 DW_MUTEX_LOCK;
3269 accel = _removetilde(tempbuf, title);
3270
3271 accel_group = (GtkAccelGroup *)g_object_get_data(G_OBJECT(menu), "_dw_accel");
3272 submenucount = (int)g_object_get_data(G_OBJECT(menu), "_dw_submenucount");
3273
3274 if (strlen(tempbuf) == 0)
3275 tmphandle=gtk_menu_item_new();
3276 else
3277 {
3278 if (check)
3279 {
3280 char numbuf[10];
3281
3282 tmphandle = gtk_check_menu_item_new_with_label(tempbuf);
3283 if (accel && accel_group)
3284 {
3285 gtk_label_set_use_underline(GTK_LABEL(gtk_bin_get_child(GTK_BIN(tmphandle))), TRUE);
3286 #if 0 /* TODO: This isn't working right */
3287 gtk_widget_add_accelerator(tmphandle, "activate", accel_group, tmp_key, GDK_MOD1_MASK, 0);
3288 #endif
3289 }
3290 sprintf(numbuf, "%lu", id);
3291 g_object_set_data(G_OBJECT(menu), numbuf, (gpointer)tmphandle);
3292 }
3293 else
3294 {
3295 char numbuf[10];
3296
3297 tmphandle=gtk_menu_item_new_with_label(tempbuf);
3298 if (accel && accel_group)
3299 {
3300 gtk_label_set_use_underline(GTK_LABEL(gtk_bin_get_child(GTK_BIN(tmphandle))), TRUE);
3301 #if 0 /* TODO: This isn't working right */
3302 gtk_widget_add_accelerator(tmphandle, "activate", accel_group, tmp_key, GDK_MOD1_MASK, 0);
3303 #endif
3304 }
3305 sprintf(numbuf, "%lu", id);
3306 g_object_set_data(G_OBJECT(menu), numbuf, (gpointer)tmphandle);
3307 }
3308 }
3309
3310 gtk_widget_show(tmphandle);
3311
3312 if (submenu)
3313 {
3314 char tempbuf[100];
3315
3316 sprintf(tempbuf, "_dw_submenu%d", submenucount);
3317 submenucount++;
3318 gtk_menu_item_set_submenu(GTK_MENU_ITEM(tmphandle), submenu);
3319 g_object_set_data(G_OBJECT(menu), tempbuf, (gpointer)submenu);
3320 g_object_set_data(G_OBJECT(menu), "_dw_submenucount", (gpointer)submenucount);
3321 }
3322
3323 if (GTK_IS_MENU_BAR(menu))
3324 gtk_menu_shell_append(GTK_MENU_SHELL(menu), tmphandle);
3325 else
3326 gtk_menu_shell_append(GTK_MENU_SHELL(menu), tmphandle);
3327
3328 g_object_set_data(G_OBJECT(tmphandle), "_dw_id", GINT_TO_POINTER(id));
3329 free(tempbuf);
3330 /*
3331 * Set flags
3332 */
3333 if ( check && (flags & DW_MIS_CHECKED) )
3334 {
3335 _dw_ignore_click = 1;
3336 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), 1);
3337 _dw_ignore_click = 0;
3338 }
3339
3340 if ( flags & DW_MIS_DISABLED )
3341 gtk_widget_set_sensitive( tmphandle, FALSE );
3342
3343 DW_MUTEX_UNLOCK;
3344 return tmphandle;
3345 }
3346
3347 GtkWidget *_find_submenu_id(GtkWidget *start, char *name)
3348 {
3349 GtkWidget *tmp;
3350 int z, submenucount = (int)g_object_get_data(G_OBJECT(start), "_dw_submenucount");
3351
3352 if((tmp = g_object_get_data(G_OBJECT(start), name)))
3353 return tmp;
3354
3355 for(z=0;z<submenucount;z++)
3356 {
3357 char tempbuf[100];
3358 GtkWidget *submenu, *menuitem;
3359
3360 sprintf(tempbuf, "_dw_submenu%d", z);
3361
3362 if((submenu = g_object_get_data(G_OBJECT(start), tempbuf)))
3363 {
3364 if((menuitem = _find_submenu_id(submenu, name)))
3365 return menuitem;
3366 }
3367 }
3368 return NULL;
3369 }
3370
3371 /*
3372 * Sets the state of a menu item check.
3373 * Parameters:
3374 * menu: The handle the the existing menu.
3375 * id: Menuitem id.
3376 * check: TRUE for checked FALSE for not checked.
3377 * deprecated: use dw_menu_item_set_state()
3378 */
3379 void dw_menu_item_set_check(HMENUI menu, unsigned long id, int check)
3380 {
3381 char numbuf[10];
3382 GtkWidget *tmphandle;
3383 int _locked_by_me = FALSE;
3384
3385 if(!menu)
3386 return;
3387
3388 DW_MUTEX_LOCK;
3389 sprintf(numbuf, "%lu", id);
3390 tmphandle = _find_submenu_id(menu, numbuf);
3391
3392 if(tmphandle)
3393 {
3394 _dw_ignore_click = 1;
3395 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(tmphandle)) != check)
3396 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), check);
3397 _dw_ignore_click = 0;
3398 }
3399 DW_MUTEX_UNLOCK;
3400 }
3401
3402 /*
3403 * Sets the state of a menu item.
3404 * Parameters:
3405 * menu: The handle the the existing menu.
3406 * id: Menuitem id.
3407 * state: TRUE for checked FALSE for not checked.
3408 */
3409 void dw_menu_item_set_state(HMENUI menu, unsigned long id, unsigned long state)
3410 {
3411 char numbuf[10];
3412 GtkWidget *tmphandle;
3413 int check;
3414 int _locked_by_me = FALSE;
3415
3416 if(!menu)
3417 return;
3418
3419 DW_MUTEX_LOCK;
3420 sprintf(numbuf, "%lu", id);
3421 tmphandle = _find_submenu_id(menu, numbuf);
3422
3423 if ( (state & DW_MIS_CHECKED) || (state & DW_MIS_UNCHECKED) )
3424 {
3425 if ( state & DW_MIS_CHECKED )
3426 check = 1;
3427 else
3428 check = 0;
3429
3430 if (tmphandle)
3431 {
3432 _dw_ignore_click = 1;
3433 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(tmphandle)) != check)
3434 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), check);
3435 _dw_ignore_click = 0;
3436 }
3437 }
3438 if ( (state & DW_MIS_ENABLED) || (state & DW_MIS_DISABLED) )
3439 {
3440 if (tmphandle )
3441 {
3442 _dw_ignore_click = 1;
3443 if ( state & DW_MIS_ENABLED )
3444 gtk_widget_set_sensitive( tmphandle, TRUE );
3445 else
3446 gtk_widget_set_sensitive( tmphandle, FALSE );
3447 _dw_ignore_click = 0;
3448 }
3449 }
3450 DW_MUTEX_UNLOCK;
3451 }
3452
3453 /*
3454 * Pops up a context menu at given x and y coordinates.
3455 * Parameters:
3456 * menu: The handle the the existing menu.
3457 * parent: Handle to the window initiating the popup.
3458 * x: X coordinate.
3459 * y: Y coordinate.
3460 */
3461 void dw_menu_popup(HMENUI *menu, HWND parent, int x, int y)
3462 {
3463 int _locked_by_me = FALSE;
3464
3465 if(!menu || !*menu)
3466 return;
3467
3468 popup = parent;
3469
3470 DW_MUTEX_LOCK;
3471 gtk_menu_popup(GTK_MENU(*menu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
3472 *menu = NULL;
3473 DW_MUTEX_UNLOCK;
3474 }
3475
3476
3477 /*
3478 * Returns the current X and Y coordinates of the mouse pointer.
3479 * Parameters:
3480 * x: Pointer to variable to store X coordinate.
3481 * y: Pointer to variable to store Y coordinate.
3482 */
3483 void dw_pointer_query_pos(long *x, long *y)
3484 {
3485 GdkModifierType state;
3486 int gx, gy;
3487 int _locked_by_me = FALSE;
3488
3489 DW_MUTEX_LOCK;
3490 #ifdef GDK_WINDOWING_X11
3491 gdk_window_get_pointer (gdk_x11_window_lookup_for_display(gdk_display_get_default(), GDK_ROOT_WINDOW()), &gx, &gy, &state);
3492 #endif
3493 *x = gx;
3494 *y = gy;
3495 DW_MUTEX_UNLOCK;
3496 }
3497
3498 /*
3499 * Sets the X and Y coordinates of the mouse pointer.
3500 * Parameters:
3501 * x: X coordinate.
3502 * y: Y coordinate.
3503 */
3504 void dw_pointer_set_pos(long x, long y)
3505 {
3506 int _locked_by_me = FALSE;
3507
3508 DW_MUTEX_LOCK;
3509 #ifdef GDK_WINDOWING_X11
3510 # if GTK_CHECK_VERSION(2,8,0)
3511 gdk_display_warp_pointer( gdk_display_get_default(), gdk_screen_get_default(), x, y );
3512 // gdk_display_warp_pointer( GDK_DISPLAY(), gdk_screen_get_default(), x, y );
3513 # else
3514 XWarpPointer(GDK_DISPLAY(), None, GDK_ROOT_WINDOW(), 0,0,0,0, x, y);
3515 # endif
3516 #endif
3517 DW_MUTEX_UNLOCK;
3518 }
3519
3520 #define _DW_TREE_CONTAINER 1
3521 #define _DW_TREE_TREE 2
3522 #define _DW_TREE_LISTBOX 3
3523
3524 GtkWidget *_tree_create(unsigned long id)
3525 {
3526 GtkWidget *tmp;
3527
3528 tmp = gtk_scrolled_window_new(NULL, NULL);
3529 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (tmp),
3530 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3531
3532 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3533 gtk_widget_show(tmp);
3534 return tmp;
3535 }
3536
3537 GtkWidget *_tree_setup(GtkWidget *tmp, GtkTreeModel *store)
3538 {
3539 GtkWidget *tree = gtk_tree_view_new_with_model(store);
3540 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tmp), tree);
3541 g_object_set_data(G_OBJECT(tmp), "_dw_user", (gpointer)tree);
3542 return tree;
3543 }
3544
3545 /*
3546 * Create a container object to be packed.
3547 * Parameters:
3548 * id: An ID to be used for getting the resource from the
3549 * resource file.
3550 */
3551 HWND dw_container_new(unsigned long id, int multi)
3552 {
3553 GtkWidget *tmp;
3554 int _locked_by_me = FALSE;
3555
3556 DW_MUTEX_LOCK;
3557 if(!(tmp = _tree_create(id)))
3558 {
3559 DW_MUTEX_UNLOCK;
3560 return 0;
3561 }
3562 g_object_set_data(G_OBJECT(tmp), "_dw_tree_type", (gpointer)1);
3563 g_object_set_data(G_OBJECT(tmp), "_dw_multi_sel", GINT_TO_POINTER(multi));
3564 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3565 gtk_widget_show(tmp);
3566 DW_MUTEX_UNLOCK;
3567 return tmp;
3568 }
3569
3570 /*
3571 * Create a tree object to be packed.
3572 * Parameters:
3573 * id: An ID to be used for getting the resource from the
3574 * resource file.
3575 */
3576 HWND dw_tree_new(ULONG id)
3577 {
3578 GtkWidget *tmp, *tree;
3579 GtkTreeStore *store;
3580 GtkTreeViewColumn *col;
3581 GtkCellRenderer *rend;
3582 GtkTreeSelection *sel;
3583 int _locked_by_me = FALSE;
3584
3585 DW_MUTEX_LOCK;
3586 if(!(tmp = _tree_create(id)))
3587 {
3588 DW_MUTEX_UNLOCK;
3589 return 0;
3590 }
3591 store = gtk_tree_store_new(4, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER, G_TYPE_POINTER);
3592 tree = _tree_setup(tmp, GTK_TREE_MODEL(store));
3593 g_object_set_data(G_OBJECT(tmp), "_dw_tree_type", (gpointer)2);
3594 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3595 col = gtk_tree_view_column_new();
3596
3597 rend = gtk_cell_renderer_pixbuf_new();
3598 gtk_tree_view_column_pack_start(col, rend, FALSE);
3599 gtk_tree_view_column_add_attribute(col, rend, "pixbuf", 1);
3600 rend = gtk_cell_renderer_text_new();
3601 gtk_tree_view_column_pack_start(col, rend, TRUE);
3602 gtk_tree_view_column_add_attribute(col, rend, "text", 0);
3603
3604 gtk_tree_view_append_column(GTK_TREE_VIEW (tree), col);
3605 gtk_tree_view_set_expander_column(GTK_TREE_VIEW(tree), col);
3606 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
3607
3608 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
3609 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
3610 gtk_widget_show(tree);
3611
3612 DW_MUTEX_UNLOCK;
3613 return tmp;
3614 }
3615
3616
3617 /*
3618 * Create a new static text window (widget) to be packed.
3619 * Parameters:
3620 * text: The text to be display by the static text widget.
3621 * id: An ID to be used with dw_window_from_id() or 0L.
3622 */
3623 HWND dw_text_new(char *text, unsigned long id)
3624 {
3625 GtkWidget *tmp;
3626 int _locked_by_me = FALSE;
3627
3628 DW_MUTEX_LOCK;
3629 tmp = gtk_label_new(text);
3630
3631 /* Left and centered */
3632 gtk_misc_set_alignment(GTK_MISC(tmp), 0.0f, 0.5f);
3633 gtk_widget_show(tmp);
3634 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3635 gtk_misc_set_alignment(GTK_MISC(tmp), DW_LEFT, DW_LEFT);
3636 DW_MUTEX_UNLOCK;
3637 return tmp;
3638 }
3639
3640 /*
3641 * Create a new status text window (widget) to be packed.
3642 * Parameters:
3643 * text: The text to be display by the static text widget.
3644 * id: An ID to be used with dw_window_from_id() or 0L.
3645 */
3646 HWND dw_status_text_new(char *text, ULONG id)
3647 {
3648 GtkWidget *tmp, *frame;
3649 int _locked_by_me = FALSE;
3650
3651 DW_MUTEX_LOCK;
3652 frame = gtk_frame_new(NULL);
3653 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
3654 tmp = gtk_label_new(text);
3655 gtk_container_add(GTK_CONTAINER(frame), tmp);
3656 gtk_widget_show(tmp);
3657 gtk_widget_show(frame);
3658
3659 /* Left and centered */
3660 gtk_misc_set_alignment(GTK_MISC(tmp), 0.0f, 0.5f);
3661 g_object_set_data(G_OBJECT(frame), "_dw_id", GINT_TO_POINTER(id));
3662 g_object_set_data(G_OBJECT(frame), "_dw_label", (gpointer)tmp);
3663 DW_MUTEX_UNLOCK;
3664 return frame;
3665 }
3666
3667 /*
3668 * Create a new Multiline Editbox window (widget) to be packed.
3669 * Parameters:
3670 * id: An ID to be used with dw_window_from_id() or 0L.
3671 */
3672 HWND dw_mle_new(unsigned long id)
3673 {
3674 GtkWidget *tmp, *tmpbox, *scroller;
3675 int _locked_by_me = FALSE;
3676
3677 DW_MUTEX_LOCK;
3678 tmpbox = gtk_scrolled_window_new (NULL, NULL);
3679 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(tmpbox),
3680 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3681 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(tmpbox), GTK_SHADOW_ETCHED_IN);
3682 tmp = gtk_text_view_new();
3683 gtk_container_add (GTK_CONTAINER(tmpbox), tmp);
3684 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tmp), GTK_WRAP_NONE);
3685
3686 scroller = NULL;
3687 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3688 g_object_set_data(G_OBJECT(tmpbox), "_dw_user", (gpointer)tmp);
3689 gtk_widget_show(tmp);
3690 gtk_widget_show(tmpbox);
3691 DW_MUTEX_UNLOCK;
3692 return tmpbox;
3693 }
3694
3695 /*
3696 * Create a new Entryfield window (widget) to be packed.
3697 * Parameters:
3698 * text: The default text to be in the entryfield widget.
3699 * id: An ID to be used with dw_window_from_id() or 0L.
3700 */
3701 HWND dw_entryfield_new(char *text, unsigned long id)
3702 {
3703 GtkWidget *tmp;
3704 int _locked_by_me = FALSE;
3705
3706 DW_MUTEX_LOCK;
3707 tmp = gtk_entry_new();
3708
3709 gtk_entry_set_text(GTK_ENTRY(tmp), text);
3710
3711 gtk_widget_show(tmp);
3712 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3713
3714 DW_MUTEX_UNLOCK;
3715 return tmp;
3716 }
3717
3718 /*
3719 * Create a new Entryfield (password) window (widget) to be packed.
3720 * Parameters:
3721 * text: The default text to be in the entryfield widget.
3722 * id: An ID to be used with dw_window_from_id() or 0L.
3723 */
3724 HWND dw_entryfield_password_new(char *text, ULONG id)
3725 {
3726 GtkWidget *tmp;
3727 int _locked_by_me = FALSE;
3728
3729 DW_MUTEX_LOCK;
3730 tmp = gtk_entry_new();
3731
3732 gtk_entry_set_visibility(GTK_ENTRY(tmp), FALSE);
3733 gtk_entry_set_text(GTK_ENTRY(tmp), text);
3734
3735 gtk_widget_show(tmp);
3736 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3737
3738 DW_MUTEX_UNLOCK;
3739 return tmp;
3740 }
3741
3742 /*
3743 * Create a new Combobox window (widget) to be packed.
3744 * Parameters:
3745 * text: The default text to be in the combpbox widget.
3746 * id: An ID to be used with dw_window_from_id() or 0L.
3747 */
3748 HWND dw_combobox_new(char *text, unsigned long id)
3749 {
3750 GtkWidget *tmp;
3751 GtkListStore *store;
3752 int sigid, _locked_by_me = FALSE;
3753 gint cid;
3754
3755 DW_MUTEX_LOCK;
3756 store = gtk_list_store_new(1, G_TYPE_STRING);
3757 tmp = gtk_combo_box_new_with_model_and_entry(GTK_TREE_MODEL(store));
3758 gtk_widget_show(tmp);
3759 g_object_set_data(G_OBJECT(tmp), "_dw_tree_type", (gpointer)3);
3760 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3761 DW_MUTEX_UNLOCK;
3762 return tmp;
3763 }
3764
3765 /*
3766 * Create a new button window (widget) to be packed.
3767 * Parameters:
3768 * text: The text to be display by the static text widget.
3769 * id: An ID to be used with dw_window_from_id() or 0L.
3770 */
3771 HWND dw_button_new(char *text, unsigned long id)
3772 {
3773 GtkWidget *tmp;
3774 int _locked_by_me = FALSE;
3775
3776 DW_MUTEX_LOCK;
3777 tmp = gtk_button_new_with_label(text);
3778 gtk_widget_show(tmp);
3779 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3780 DW_MUTEX_UNLOCK;
3781 return tmp;
3782 }
3783
3784 /*
3785 * Create a new bitmap button window (widget) to be packed.
3786 * Parameters:
3787 * text: Bubble help text to be displayed.
3788 * id: An ID of a bitmap in the resource file.
3789 */
3790 HWND dw_bitmapbutton_new(char *text, unsigned long id)
3791 {
3792 GtkWidget *tmp;
3793 GtkWidget *bitmap;
3794 int _locked_by_me = FALSE;
3795
3796 DW_MUTEX_LOCK;
3797 tmp = gtk_button_new();
3798 bitmap = dw_bitmap_new(id);
3799
3800 if(bitmap)
3801 {
3802 dw_window_set_bitmap(bitmap, id, NULL);
3803 gtk_container_add (GTK_CONTAINER(tmp), bitmap);
3804 }
3805 gtk_widget_show(tmp);
3806 if(text)
3807 {
3808 gtk_widget_set_tooltip_text(tmp, text);
3809 }
3810 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3811 DW_MUTEX_UNLOCK;
3812 return tmp;
3813 }
3814
3815 /*
3816 * Create a new bitmap button window (widget) to be packed from a file.
3817 * Parameters:
3818 * label_text: Text to display on button. TBD when Windows works
3819 * text: Bubble help text to be displayed.
3820 * id: An ID to be used with dw_window_from_id() or 0L.
3821 * filename: Name of the file, omit extention to have
3822 * DW pick the appropriate file extension.
3823 * (BMP on OS/2 or Windows, XPM on Unix)
3824 */
3825 HWND dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename)
3826 {
3827 GtkWidget *bitmap;
3828 GtkWidget *box;
3829 GtkWidget *label;
3830 GtkWidget *button;
3831 char *label_text=NULL;
3832 int _locked_by_me = FALSE;
3833
3834 DW_MUTEX_LOCK;
3835
3836 /* Create box for image and label */
3837 box = gtk_hbox_new (FALSE, 0);
3838 gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3839
3840 /* Now on to the image stuff */
3841 bitmap = dw_bitmap_new(id);
3842 if(bitmap)
3843 {
3844 dw_window_set_bitmap( bitmap, 0, filename );
3845 /* Pack the image into the box */
3846 gtk_box_pack_start( GTK_BOX(box), bitmap, TRUE, FALSE, 3 );
3847 gtk_widget_show( bitmap );
3848 }
3849 if(label_text)
3850 {
3851 /* Create a label for the button */
3852 label = gtk_label_new( label_text );
3853 /* Pack the label into the box */
3854 gtk_box_pack_start( GTK_BOX(box), label, TRUE, FALSE, 3 );
3855 gtk_widget_show( label );
3856 }
3857 /* Create a new button */
3858 button = gtk_button_new();
3859
3860 /* Pack and show all our widgets */
3861 gtk_widget_show( box );
3862 gtk_container_add( GTK_CONTAINER(button), box );
3863 gtk_widget_show( button );
3864 if(text)
3865 {
3866 gtk_widget_set_tooltip_text(button, text);
3867 }
3868 g_object_set_data(G_OBJECT(button), "_dw_id", GINT_TO_POINTER(id));
3869 DW_MUTEX_UNLOCK;
3870 return button;
3871 }
3872
3873 /*
3874 * Create a new bitmap button window (widget) to be packed from data.
3875 * Parameters:
3876 * text: Bubble help text to be displayed.
3877 * id: An ID to be used with dw_window_from_id() or 0L.
3878 * data: Raw data of image.
3879 * (BMP on OS/2 or Windows, XPM on Unix)
3880 * len: Length of raw data
3881 */
3882 HWND dw_bitmapbutton_new_from_data(char *text, unsigned long id, char *data, int len)
3883 {
3884 GtkWidget *tmp;
3885 GtkWidget *bitmap;
3886 int _locked_by_me = FALSE;
3887
3888 DW_MUTEX_LOCK;
3889 tmp = gtk_button_new();
3890 bitmap = dw_bitmap_new(id);
3891
3892 if ( bitmap )
3893 {
3894 dw_window_set_bitmap_from_data(bitmap, 0, data, len);
3895 gtk_container_add (GTK_CONTAINER(tmp), bitmap);
3896 }
3897 gtk_widget_show(tmp);
3898 if(text)
3899 {
3900 gtk_widget_set_tooltip_text(tmp, text);
3901 }
3902 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3903 DW_MUTEX_UNLOCK;
3904 return tmp;
3905 }
3906
3907 /*
3908 * Create a new spinbutton window (widget) to be packed.
3909 * Parameters:
3910 * text: The text to be display by the static text widget.
3911 * id: An ID to be used with dw_window_from_id() or 0L.
3912 */
3913 HWND dw_spinbutton_new(char *text, unsigned long id)
3914 {
3915 GtkAdjustment *adj;
3916 GtkWidget *tmp;
3917 int _locked_by_me = FALSE;
3918
3919 DW_MUTEX_LOCK;
3920 adj = (GtkAdjustment *)gtk_adjustment_new (1.0, 0.0, 100.0, 1.0, 5.0, 0.0);
3921 tmp = gtk_spin_button_new (adj, 0, 0);
3922 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(tmp), TRUE);
3923 gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(tmp), TRUE);
3924 gtk_widget_show(tmp);
3925 g_object_set_data(G_OBJECT(tmp), "_dw_adjustment", (gpointer)adj);
3926 g_object_set_data(G_OBJECT(adj), "_dw_spinbutton", (gpointer)tmp);
3927 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3928 DW_MUTEX_UNLOCK;
3929 return tmp;
3930 }
3931
3932 /*
3933 * Create a new radiobutton window (widget) to be packed.
3934 * Parameters:
3935 * text: The text to be display by the static text widget.
3936 * id: An ID to be used with dw_window_from_id() or 0L.
3937 */
3938 HWND dw_radiobutton_new(char *text, ULONG id)
3939 {
3940 /* This will have to be fixed in the future. */
3941 GtkWidget *tmp;
3942 int _locked_by_me = FALSE;
3943
3944 DW_MUTEX_LOCK;
3945 tmp = gtk_radio_button_new_with_label(NULL, text);
3946 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3947 gtk_widget_show(tmp);
3948
3949 DW_MUTEX_UNLOCK;
3950 return tmp;
3951 }
3952
3953 /*
3954 * Create a new slider window (widget) to be packed.
3955 * Parameters:
3956 * vertical: TRUE or FALSE if slider is vertical.
3957 * increments: Number of increments available.
3958 * id: An ID to be used with dw_window_from_id() or 0L.
3959 */
3960 HWND dw_slider_new(int vertical, int increments, ULONG id)
3961 {
3962 GtkWidget *tmp;
3963 GtkAdjustment *adjustment;
3964 int _locked_by_me = FALSE;
3965
3966 DW_MUTEX_LOCK;
3967 adjustment = (GtkAdjustment *)gtk_adjustment_new(0, 0, (gfloat)increments, 1, 1, 1);
3968 if(vertical)
3969 tmp = gtk_vscale_new(adjustment);
3970 else
3971 tmp = gtk_hscale_new(adjustment);
3972 gtk_widget_show(tmp);
3973 gtk_scale_set_draw_value(GTK_SCALE(tmp), 0);
3974 gtk_scale_set_digits(GTK_SCALE(tmp), 0);
3975 g_object_set_data(G_OBJECT(tmp), "_dw_adjustment", (gpointer)adjustment);
3976 g_object_set_data(G_OBJECT(adjustment), "_dw_slider", (gpointer)tmp);
3977 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
3978 DW_MUTEX_UNLOCK;
3979 return tmp;
3980 }
3981
3982 /*
3983 * Create a new scrollbar window (widget) to be packed.
3984 * Parameters:
3985 * vertical: TRUE or FALSE if scrollbar is vertical.
3986 * increments: Number of increments available.
3987 * id: An ID to be used with dw_window_from_id() or 0L.
3988 */
3989 HWND dw_scrollbar_new(int vertical, ULONG id)
3990 {
3991 GtkWidget *tmp;
3992 GtkAdjustment *adjustment;
3993 int _locked_by_me = FALSE;
3994
3995 DW_MUTEX_LOCK;
3996 adjustment = (GtkAdjustment *)gtk_adjustment_new(0, 0, 0, 1, 1, 1);
3997 if(vertical)
3998 tmp = gtk_vscrollbar_new(adjustment);
3999 else
4000 tmp = gtk_hscrollbar_new(adjustment);
4001 gtk_widget_set_can_focus(tmp, FALSE);
4002 gtk_widget_show(tmp);
4003 g_object_set_data(G_OBJECT(tmp), "_dw_adjustment", (gpointer)adjustment);
4004 g_object_set_data(G_OBJECT(adjustment), "_dw_scrollbar", (gpointer)tmp);
4005 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
4006 DW_MUTEX_UNLOCK;
4007 return tmp;
4008 }
4009
4010 /*
4011 * Create a new percent bar window (widget) to be packed.
4012 * Parameters:
4013 * id: An ID to be used with dw_window_from_id() or 0L.
4014 */
4015 HWND dw_percent_new(unsigned long id)
4016 {
4017 GtkWidget *tmp;
4018 int _locked_by_me = FALSE;
4019
4020 DW_MUTEX_LOCK;
4021 tmp = gtk_progress_bar_new();
4022 gtk_widget_show(tmp);
4023 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
4024 DW_MUTEX_UNLOCK;
4025 return tmp;
4026 }
4027
4028 /*
4029 * Create a new checkbox window (widget) to be packed.
4030 * Parameters:
4031 * text: The text to be display by the static text widget.
4032 * id: An ID to be used with dw_window_from_id() or 0L.
4033 */
4034 HWND dw_checkbox_new(char *text, unsigned long id)
4035 {
4036 GtkWidget *tmp;
4037 int _locked_by_me = FALSE;
4038
4039 DW_MUTEX_LOCK;
4040 tmp = gtk_check_button_new_with_label(text);
4041 gtk_widget_show(tmp);
4042 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
4043 DW_MUTEX_UNLOCK;
4044 return tmp;
4045 }
4046
4047 /*
4048 * Create a new listbox window (widget) to be packed.
4049 * Parameters:
4050 * id: An ID to be used with dw_window_from_id() or 0L.
4051 * multi: Multiple select TRUE or FALSE.
4052 */
4053 HWND dw_listbox_new(unsigned long id, int multi)
4054 {
4055 GtkWidget *tmp, *tree;
4056 GtkListStore *store;
4057 GtkTreeViewColumn *col;
4058 GtkCellRenderer *rend;
4059 GtkTreeSelection *sel;
4060 int _locked_by_me = FALSE;
4061
4062 DW_MUTEX_LOCK;
4063 if(!(tmp = _tree_create(id)))
4064 {
4065 DW_MUTEX_UNLOCK;
4066 return 0;
4067 }
4068 store = gtk_list_store_new(1, G_TYPE_STRING);
4069 tree = _tree_setup(tmp, GTK_TREE_MODEL(store));
4070 g_object_set_data(G_OBJECT(tmp), "_dw_tree_type", (gpointer)3);
4071 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
4072
4073 col = gtk_tree_view_column_new();
4074 rend = gtk_cell_renderer_text_new();
4075 gtk_tree_view_column_pack_start(col, rend, TRUE);
4076 gtk_tree_view_column_add_attribute(col, rend, "text", 0);
4077
4078 gtk_tree_view_append_column(GTK_TREE_VIEW (tree), col);
4079 gtk_tree_view_set_expander_column(GTK_TREE_VIEW(tree), col);
4080 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
4081
4082 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
4083 if(multi)
4084 {
4085 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
4086 }
4087 else
4088 {
4089 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
4090 }
4091 gtk_widget_show(tmp);
4092 DW_MUTEX_UNLOCK;
4093 return tmp;
4094 }
4095
4096 /*
4097 * Sets the icon used for a given window.
4098 * Parameters:
4099 * handle: Handle to the window.
4100 * id: An ID to be used to specify the icon.
4101 */
4102 void dw_window_set_icon(HWND handle, HICN icon)
4103 {
4104 GdkPixbuf *icon_pixbuf;
4105 int _locked_by_me = FALSE;
4106
4107 DW_MUTEX_LOCK;
4108 icon_pixbuf = _find_pixbuf(icon, NULL, NULL);
4109
4110 if(gtk_widget_get_window(handle) && icon_pixbuf)
4111 {
4112 GList *list = g_list_alloc();
4113 list = g_list_append(list, icon_pixbuf);
4114 gdk_window_set_icon_list(gtk_widget_get_window(handle), list);
4115 g_object_unref(G_OBJECT(list));
4116 }
4117 DW_MUTEX_UNLOCK;
4118 }
4119
4120 /*
4121 * Sets the bitmap used for a given static window.
4122 * Parameters:
4123 * handle: Handle to the window.
4124 * id: An ID to be used to specify the icon,
4125 * (pass 0 if you use the filename param)
4126 * filename: a path to a file (Bitmap on OS/2 or
4127 * Windows and a pixmap on Unix, pass
4128 * NULL if you use the id param)
4129 */
4130 void dw_window_set_bitmap(HWND handle, unsigned long id, char *filename)
4131 {
4132 GdkPixbuf *tmp = NULL;
4133 int found_ext = 0;
4134 int i;
4135 int _locked_by_me = FALSE;
4136
4137 if(!id && !filename)
4138 return;
4139
4140 DW_MUTEX_LOCK;
4141 if(id)
4142 tmp = _find_pixbuf(id, NULL, NULL);
4143 else
4144 {
4145 char *file = alloca(strlen(filename) + 5);
4146
4147 if (!file)
4148 {
4149 DW_MUTEX_UNLOCK;
4150 return;
4151 }
4152
4153 strcpy(file, filename);
4154
4155 /* check if we can read from this file (it exists and read permission) */
4156 if ( access(file, 04 ) != 0 )
4157 {
4158 /* Try with various extentions */
4159 for ( i = 0; i < NUM_EXTS; i++ )
4160 {
4161 strcpy( file, filename );
4162 strcat( file, image_exts[i] );
4163 if ( access( file, 04 ) == 0 )
4164 {
4165 found_ext = 1;
4166 break;
4167 }
4168 }
4169 if ( found_ext == 0 )
4170 {
4171 DW_MUTEX_UNLOCK;
4172 return;
4173 }
4174 }
4175 tmp = gdk_pixbuf_new_from_file(file, NULL );
4176 }
4177
4178 if (tmp)
4179 {
4180 if ( GTK_IS_BUTTON(handle) )
4181 {
4182 GtkWidget *image = gtk_button_get_image( GTK_BUTTON(handle) );
4183 gtk_image_set_from_pixbuf(GTK_IMAGE(image), tmp);
4184 }
4185 else
4186 {
4187 gtk_image_set_from_pixbuf(GTK_IMAGE(handle), tmp);
4188 }
4189 }
4190 DW_MUTEX_UNLOCK;
4191 }
4192
4193 /*
4194 * Sets the bitmap used for a given static window.
4195 * Parameters:
4196 * handle: Handle to the window.
4197 * id: An ID to be used to specify the icon,
4198 * (pass 0 if you use the filename param)
4199 * data: the image data
4200 * Bitmap on Windows and a pixmap on Unix, pass
4201 * NULL if you use the id param)
4202 * len: length of data
4203 */
4204 void dw_window_set_bitmap_from_data(HWND handle, unsigned long id, char *data, int len)
4205 {
4206 GdkPixbuf *tmp;
4207 int _locked_by_me = FALSE;
4208 char *file;
4209 FILE *fp;
4210
4211 if (!id && !data)
4212 return;
4213
4214 DW_MUTEX_LOCK;
4215 if (id)
4216 tmp = _find_pixbuf(id, NULL, NULL);
4217 else
4218 {
4219 GdkPixbuf *pixbuf;
4220 if (!data)
4221 {
4222 DW_MUTEX_UNLOCK;
4223 return;
4224 }
4225 /*
4226 * A real hack; create a temporary file and write the contents
4227 * of the data to the file
4228 */
4229 file = tmpnam( NULL );
4230 fp = fopen( file, "wb" );
4231 if ( fp )
4232 {
4233 fwrite( data, len, 1, fp );
4234 fclose( fp );
4235 }
4236 else
4237 {
4238 DW_MUTEX_UNLOCK;
4239 return;
4240 }
4241 pixbuf = gdk_pixbuf_new_from_file(file, NULL );
4242 /* remove our temporary file */
4243 unlink (file );
4244 }
4245
4246 if(tmp)
4247 {
4248 gtk_image_set_from_pixbuf(GTK_IMAGE(handle), tmp);
4249 }
4250 DW_MUTEX_UNLOCK;
4251 }
4252
4253 /*
4254 * Sets the text used for a given window.
4255 * Parameters:
4256 * handle: Handle to the window.
4257 * text: The text associated with a given window.
4258 */
4259 void dw_window_set_text(HWND handle, char *text)
4260 {
4261 int _locked_by_me = FALSE;
4262 GtkWidget *tmp;
4263
4264 DW_MUTEX_LOCK;
4265 if((tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_mdi_title")))
4266 handle = tmp;
4267 if(GTK_IS_ENTRY(handle))
4268 gtk_entry_set_text(GTK_ENTRY(handle), text);
4269 #if 0
4270 else if(GTK_IS_COMBO_BOX(handle))
4271 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO_BOX(handle)->entry), text);
4272 #endif
4273 else if(GTK_IS_LABEL(handle))
4274 gtk_label_set_text(GTK_LABEL(handle), text);
4275 else if(GTK_IS_BUTTON(handle))
4276 {
4277 gtk_button_set_label(GTK_BUTTON(handle), text);
4278 }
4279 else if(gtk_widget_is_toplevel(handle))
4280 gtk_window_set_title(GTK_WINDOW(handle), text);
4281 else if (GTK_IS_FRAME(handle))
4282 {
4283 /*
4284 * This is a groupbox or status_text
4285 */
4286 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_label");
4287 if ( tmp && GTK_IS_LABEL(tmp) )
4288 gtk_label_set_text(GTK_LABEL(tmp), text);
4289 else /* assume groupbox */
4290 gtk_frame_set_label(GTK_FRAME(handle), text && *text ? text : NULL);
4291 }
4292 DW_MUTEX_UNLOCK;
4293 }
4294
4295 /*
4296 * Gets the text used for a given window.
4297 * Parameters:
4298 * handle: Handle to the window.
4299 * Returns:
4300 * text: The text associsated with a given window.
4301 */
4302 char *dw_window_get_text(HWND handle)
4303 {
4304 const char *possible = "";
4305 int _locked_by_me = FALSE;
4306
4307 DW_MUTEX_LOCK;
4308 if(GTK_IS_ENTRY(handle))
4309 possible = gtk_entry_get_text(GTK_ENTRY(handle));
4310 #if 0
4311 else if(GTK_IS_COMBO_BOX(handle))
4312 possible = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO_BOX(handle)->entry));
4313 #endif
4314
4315 DW_MUTEX_UNLOCK;
4316 return strdup(possible);
4317 }
4318
4319 /*
4320 * Disables given window (widget).
4321 * Parameters:
4322 * handle: Handle to the window.
4323 */
4324 void dw_window_disable(HWND handle)
4325 {
4326 int _locked_by_me = FALSE;
4327
4328 DW_MUTEX_LOCK;
4329 gtk_widget_set_sensitive(handle, FALSE);
4330 DW_MUTEX_UNLOCK;
4331 }
4332
4333 /*
4334 * Enables given window (widget).
4335 * Parameters:
4336 * handle: Handle to the window.
4337 */
4338 void dw_window_enable(HWND handle)
4339 {
4340 int _locked_by_me = FALSE;
4341
4342 DW_MUTEX_LOCK;
4343 gtk_widget_set_sensitive(handle, TRUE);
4344 DW_MUTEX_UNLOCK;
4345 }
4346
4347 /*
4348 * Gets the child window handle with specified ID.
4349 * Parameters:
4350 * handle: Handle to the parent window.
4351 * id: Integer ID of the child.
4352 */
4353 HWND API dw_window_from_id(HWND handle, int id)
4354 {
4355 GList *orig = NULL, *list = NULL;
4356 int _locked_by_me = FALSE;
4357
4358 DW_MUTEX_LOCK;
4359 if(handle && GTK_IS_CONTAINER(handle))
4360 {
4361 orig = list = gtk_container_get_children(GTK_CONTAINER(handle));
4362 }
4363 while(list)
4364 {
4365 if(GTK_IS_WIDGET(list->data))
4366 {
4367 if(id == (int)g_object_get_data(G_OBJECT(list->data), "_dw_id"))
4368 {
4369 HWND ret = (HWND)list->data;
4370 g_list_free(orig);
4371 DW_MUTEX_UNLOCK;
4372 return ret;
4373 }
4374 }
4375 list = list->next;
4376 }
4377 if(orig)
4378 g_list_free(orig);
4379 DW_MUTEX_UNLOCK;
4380 return 0L;
4381 }
4382
4383 void _strip_cr(char *dest, char *src)
4384 {
4385 int z, x = 0;
4386
4387 for(z=0;z<strlen(src);z++)
4388 {
4389 if(src[z] != '\r')
4390 {
4391 dest[x] = src[z];
4392 x++;
4393 }
4394 }
4395 dest[x] = 0;
4396 }
4397
4398 /*
4399 * Adds text to an MLE box and returns the current point.
4400 * Parameters:
4401 * handle: Handle to the MLE to be queried.
4402 * buffer: Text buffer to be imported.
4403 * startpoint: Point to start entering text.
4404 */
4405 unsigned int dw_mle_import(HWND handle, char *buffer, int startpoint)
4406 {
4407 unsigned int tmppoint = startpoint;
4408 int _locked_by_me = FALSE;
4409
4410 DW_MUTEX_LOCK;
4411 if(GTK_IS_SCROLLED_WINDOW(handle))
4412 {
4413 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
4414
4415 if(tmp && GTK_IS_TEXT_VIEW(tmp))
4416 {
4417 char *impbuf = malloc(strlen(buffer)+1);
4418 GtkTextBuffer *tbuffer;
4419 GtkTextIter iter;
4420
4421 _strip_cr(impbuf, buffer);
4422
4423 tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
4424 gtk_text_buffer_get_iter_at_offset(tbuffer, &iter, startpoint);
4425 gtk_text_buffer_place_cursor(tbuffer, &iter);
4426 gtk_text_buffer_insert_at_cursor(tbuffer, impbuf, -1);
4427 tmppoint = (startpoint > -1 ? startpoint : 0) + strlen(impbuf);
4428 free(impbuf);
4429 }
4430 }
4431 DW_MUTEX_UNLOCK;
4432 return tmppoint;
4433 }
4434
4435 /*
4436 * Grabs text from an MLE box.
4437 * Parameters:
4438 * handle: Handle to the MLE to be queried.
4439 * buffer: Text buffer to be exported. MUST allow for trailing nul character.
4440 * startpoint: Point to start grabbing text.
4441 * length: Amount of text to be grabbed.
4442 */
4443 void dw_mle_export(HWND handle, char *buffer, int startpoint, int length)
4444 {
4445 int _locked_by_me = FALSE;
4446 gchar *text;
4447
4448 DW_MUTEX_LOCK;
4449 /* force the return value to nul in case the following tests fail */
4450 if(buffer)
4451 buffer[0] = '\0';
4452 if(GTK_IS_SCROLLED_WINDOW(handle))
4453 {
4454 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
4455
4456 if(tmp && GTK_IS_TEXT_VIEW(tmp))
4457 {
4458 GtkTextBuffer *tbuffer;
4459 GtkTextIter start, end;
4460
4461 tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
4462 gtk_text_buffer_get_iter_at_offset(tbuffer, &start, startpoint);
4463 gtk_text_buffer_get_iter_at_offset(tbuffer, &end, startpoint + length);
4464 text = gtk_text_iter_get_text(&start, &end);
4465 if(text) /* Should this get freed? */
4466 {
4467 if(buffer)
4468 strcpy(buffer, text);
4469 }
4470 }
4471 }
4472 DW_MUTEX_UNLOCK;
4473 }
4474
4475 /*
4476 * Obtains information about an MLE box.
4477 * Parameters:
4478 * handle: Handle to the MLE to be queried.
4479 * bytes: A pointer to a variable to return the total bytes.
4480 * lines: A pointer to a variable to return the number of lines.
4481 */
4482 void dw_mle_get_size(HWND handle, unsigned long *bytes, unsigned long *lines)
4483 {
4484 int _locked_by_me = FALSE;
4485
4486 if(bytes)
4487 *bytes = 0;
4488 if(lines)
4489 *lines = 0;
4490
4491 DW_MUTEX_LOCK;
4492 if(GTK_IS_SCROLLED_WINDOW(handle))
4493 {
4494 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
4495
4496 if(tmp && GTK_IS_TEXT_VIEW(tmp))
4497 {
4498 GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tmp));
4499
4500 if(bytes)
4501 *bytes = gtk_text_buffer_get_char_count(buffer) + 1;
4502 if(lines)
4503 *lines = gtk_text_buffer_get_line_count(buffer) + 1;
4504 }
4505 }
4506 DW_MUTEX_UNLOCK;
4507 }
4508
4509 /*
4510 * Deletes text from an MLE box.
4511 * Parameters:
4512 * handle: Handle to the MLE to be deleted from.
4513 * startpoint: Point to start deleting text.
4514 * length: Amount of text to be deleted.
4515 */
4516 void dw_mle_delete(HWND handle, int startpoint, int length)
4517 {
4518 int _locked_by_me = FALSE;
4519
4520 DW_MUTEX_LOCK;
4521 if(GTK_IS_SCROLLED_WINDOW(handle))
4522 {
4523 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
4524
4525 if(tmp && GTK_IS_TEXT_VIEW(tmp))
4526 {
4527 GtkTextBuffer *tbuffer;
4528 GtkTextIter start, end;
4529
4530 tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
4531 gtk_text_buffer_get_iter_at_offset(tbuffer, &start, startpoint);
4532 gtk_text_buffer_get_iter_at_offset(tbuffer, &end, startpoint + length);
4533 gtk_text_buffer_delete(tbuffer, &start, &end);
4534 }
4535 }
4536 DW_MUTEX_UNLOCK;
4537 }
4538
4539 /*
4540 * Clears all text from an MLE box.
4541 * Parameters:
4542 * handle: Handle to the MLE to be cleared.
4543 */
4544 void dw_mle_clear(HWND handle)
4545 {
4546 int length, _locked_by_me = FALSE;
4547
4548 DW_MUTEX_LOCK;
4549 if(GTK_IS_SCROLLED_WINDOW(handle))
4550 {
4551 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
4552
4553 if(tmp && GTK_IS_TEXT_VIEW(tmp))
4554 {
4555 GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tmp));
4556
4557 length = -1;
4558 gtk_text_buffer_set_text(buffer, "", length);
4559 }
4560 }
4561 DW_MUTEX_UNLOCK;
4562 }
4563
4564 /*
4565 * Sets the visible line of an MLE box.
4566 * Parameters:
4567 * handle: Handle to the MLE.
4568 * line: Line to be visible.
4569 */
4570 void dw_mle_set_visible(HWND handle, int line)
4571 {
4572 int _locked_by_me = FALSE;
4573
4574 DW_MUTEX_LOCK;
4575 if(GTK_IS_SCROLLED_WINDOW(handle))
4576 {
4577 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
4578
4579 if(tmp && GTK_IS_TEXT_VIEW(tmp))
4580 {
4581 GtkTextBuffer *tbuffer;
4582 GtkTextIter iter;
4583 GtkTextMark *mark = (GtkTextMark *)g_object_get_data(G_OBJECT(handle), "_dw_mark");
4584
4585 tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
4586 gtk_text_buffer_get_iter_at_offset(tbuffer, &iter, 0);
4587 gtk_text_iter_set_line(&iter, line);
4588 if(!mark)
4589 {
4590 mark = gtk_text_buffer_create_mark(tbuffer, NULL, &iter, FALSE);
4591 g_object_set_data(G_OBJECT(handle), "_dw_mark", (gpointer)mark);
4592 }
4593 else
4594 gtk_text_buffer_move_mark(tbuffer, mark, &iter);
4595 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(tmp), mark,
4596 0, FALSE, 0, 0);
4597 }
4598 }
4599 DW_MUTEX_UNLOCK;
4600 }
4601
4602 /*
4603 * Sets the editablity of an MLE box.
4604 * Parameters:
4605 * handle: Handle to the MLE.
4606 * state: TRUE if it can be edited, FALSE for readonly.
4607 */
4608 void dw_mle_set_editable(HWND handle, int state)
4609 {
4610 int _locked_by_me = FALSE;
4611
4612 DW_MUTEX_LOCK;
4613 if(GTK_IS_SCROLLED_WINDOW(handle))
4614 {
4615 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
4616
4617 if(tmp && GTK_IS_TEXT_VIEW(tmp))
4618 gtk_text_view_set_editable(GTK_TEXT_VIEW(tmp), state);
4619 }
4620 DW_MUTEX_UNLOCK;
4621 }
4622
4623 /*
4624 * Sets the word wrap state of an MLE box.
4625 * Parameters:
4626 * handle: Handle to the MLE.
4627 * state: TRUE if it wraps, FALSE if it doesn't.
4628 */
4629 void dw_mle_set_word_wrap(HWND handle, int state)
4630 {
4631 int _locked_by_me = FALSE;
4632
4633 DW_MUTEX_LOCK;
4634 if(GTK_IS_SCROLLED_WINDOW(handle))
4635 {
4636 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
4637
4638 if(tmp && GTK_IS_TEXT_VIEW(tmp))
4639 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tmp), GTK_WRAP_WORD);
4640 }
4641 DW_MUTEX_UNLOCK;
4642 }
4643
4644 /*
4645 * Sets the current cursor position of an MLE box.
4646 * Parameters:
4647 * handle: Handle to the MLE to be positioned.
4648 * point: Point to position cursor.
4649 */
4650 void dw_mle_set_cursor(HWND handle, int point)
4651 {
4652 int _locked_by_me = FALSE;
4653
4654 DW_MUTEX_LOCK;
4655 if(GTK_IS_SCROLLED_WINDOW(handle))
4656 {
4657 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
4658
4659 if(tmp && GTK_IS_TEXT_VIEW(tmp))
4660 {
4661 GtkTextBuffer *tbuffer;
4662 GtkTextIter iter;
4663 GtkTextMark *mark = (GtkTextMark *)g_object_get_data(G_OBJECT(handle), "_dw_mark");
4664
4665 tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
4666 gtk_text_buffer_get_iter_at_offset(tbuffer, &iter, point);
4667 if(!mark)
4668 {
4669 mark = gtk_text_buffer_create_mark(tbuffer, NULL, &iter, FALSE);
4670 g_object_set_data(G_OBJECT(handle), "_dw_mark", (gpointer)mark);
4671 }
4672 else
4673 gtk_text_buffer_move_mark(tbuffer, mark, &iter);
4674 gtk_text_buffer_place_cursor(tbuffer, &iter);
4675 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(tmp), mark,
4676 0, FALSE, 0, 0);
4677 }
4678 }
4679 DW_MUTEX_UNLOCK;
4680 }
4681
4682 /*
4683 * Finds text in an MLE box.
4684 * Parameters:
4685 * handle: Handle to the MLE to be cleared.
4686 * text: Text to search for.
4687 * point: Start point of search.
4688 * flags: Search specific flags.
4689 */
4690 int dw_mle_search(HWND handle, char *text, int point, unsigned long flags)
4691 {
4692 int _locked_by_me = FALSE, retval = 0;
4693
4694 DW_MUTEX_LOCK;
4695 if(GTK_IS_SCROLLED_WINDOW(handle))
4696 {
4697 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
4698
4699 if(tmp && GTK_IS_TEXT_VIEW(tmp))
4700 {
4701 GtkTextBuffer *tbuffer;
4702 GtkTextIter iter, found;
4703
4704 tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
4705 gtk_text_buffer_get_iter_at_offset(tbuffer, &iter, point);
4706 gtk_text_iter_forward_search(&iter, text, GTK_TEXT_SEARCH_TEXT_ONLY, &found, NULL, NULL);
4707 retval = gtk_text_iter_get_offset(&found);
4708 }
4709 }
4710 DW_MUTEX_UNLOCK;
4711 return retval;
4712 }
4713
4714 /*
4715 * Stops redrawing of an MLE box.
4716 * Parameters:
4717 * handle: Handle to the MLE to freeze.
4718 */
4719 void dw_mle_freeze(HWND handle)
4720 {
4721 }
4722
4723 /*
4724 * Resumes redrawing of an MLE box.
4725 * Parameters:
4726 * handle: Handle to the MLE to thaw.
4727 */
4728 void dw_mle_thaw(HWND handle)
4729 {
4730 }
4731
4732 /*
4733 * Sets the percent bar position.
4734 * Parameters:
4735 * handle: Handle to the percent bar to be set.
4736 * position: Position of the percent bar withing the range.
4737 */
4738 void dw_percent_set_pos(HWND handle, unsigned int position)
4739 {
4740 int _locked_by_me = FALSE;
4741
4742 DW_MUTEX_LOCK;
4743 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(handle), (gfloat)position/100);
4744 DW_MUTEX_UNLOCK;
4745 }
4746
4747 /*
4748 * Returns the position of the slider.
4749 * Parameters:
4750 * handle: Handle to the slider to be queried.
4751 */
4752 unsigned int dw_slider_get_pos(HWND handle)
4753 {
4754 int val = 0, _locked_by_me = FALSE;
4755 GtkAdjustment *adjustment;
4756
4757 if(!handle)
4758 return 0;
4759
4760 DW_MUTEX_LOCK;
4761 adjustment = (GtkAdjustment *)g_object_get_data(G_OBJECT(handle), "_dw_adjustment");
4762 if(adjustment)
4763 {
4764 int max = _round_value(gtk_adjustment_get_upper(adjustment)) - 1;
4765 int thisval = _round_value(gtk_adjustment_get_value(adjustment));
4766
4767 if(GTK_IS_VSCALE(handle))
4768 val = max - thisval;
4769 else
4770 val = thisval;
4771 }
4772 DW_MUTEX_UNLOCK;
4773 return val;
4774 }
4775
4776 /*
4777 * Sets the slider position.
4778 * Parameters:
4779 * handle: Handle to the slider to be set.
4780 * position: Position of the slider withing the range.
4781 */
4782 void dw_slider_set_pos(HWND handle, unsigned int position)
4783 {
4784 int _locked_by_me = FALSE;
4785 GtkAdjustment *adjustment;
4786
4787 if(!handle)
4788 return;
4789
4790 DW_MUTEX_LOCK;
4791 adjustment = (GtkAdjustment *)g_object_get_data(G_OBJECT(handle), "_dw_adjustment");
4792 if(adjustment)
4793 {
4794 int max = _round_value(gtk_adjustment_get_upper(adjustment)) - 1;
4795
4796 if(GTK_IS_VSCALE(handle))
4797 gtk_adjustment_set_value(adjustment, (gfloat)(max - position));
4798 else
4799 gtk_adjustment_set_value(adjustment, (gfloat)position);
4800 }
4801 DW_MUTEX_UNLOCK;
4802 }
4803
4804 /*
4805 * Returns the position of the scrollbar.
4806 * Parameters:
4807 * handle: Handle to the scrollbar to be queried.
4808 */
4809 unsigned int dw_scrollbar_get_pos(HWND handle)
4810 {
4811 int val = 0, _locked_by_me = FALSE;
4812 GtkAdjustment *adjustment;
4813
4814 if(!handle)
4815 return 0;
4816
4817 DW_MUTEX_LOCK;
4818 adjustment = (GtkAdjustment *)g_object_get_data(G_OBJECT(handle), "_dw_adjustment");
4819 if(adjustment)
4820 val = _round_value(gtk_adjustment_get_value(adjustment));
4821 DW_MUTEX_UNLOCK;
4822 return val;
4823 }
4824
4825 /*
4826 * Sets the scrollbar position.
4827 * Parameters:
4828 * handle: Handle to the scrollbar to be set.
4829 * position: Position of the scrollbar withing the range.
4830 */
4831 void dw_scrollbar_set_pos(HWND handle, unsigned int position)
4832 {
4833 int _locked_by_me = FALSE;
4834 GtkAdjustment *adjustment;
4835
4836 if(!handle)
4837 return;
4838
4839 DW_MUTEX_LOCK;
4840 adjustment = (GtkAdjustment *)g_object_get_data(G_OBJECT(handle), "_dw_adjustment");
4841 if(adjustment)
4842 gtk_adjustment_set_value(adjustment, (gfloat)position);
4843 DW_MUTEX_UNLOCK;
4844 }
4845
4846 /*
4847 * Sets the scrollbar range.
4848 * Parameters:
4849 * handle: Handle to the scrollbar to be set.
4850 * range: Maximum range value.
4851 * visible: Visible area relative to the range.
4852 */
4853 void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible)
4854 {
4855 int _locked_by_me = FALSE;
4856 GtkAdjustment *adjustment;
4857
4858 if(!handle)
4859 return;
4860
4861 DW_MUTEX_LOCK;
4862 adjustment = (GtkAdjustment *)g_object_get_data(G_OBJECT(handle), "_dw_adjustment");
4863 if(adjustment)
4864 {
4865 gtk_adjustment_set_upper(adjustment, (gdouble)range);
4866 gtk_adjustment_set_page_increment(adjustment,(gdouble)visible);
4867 gtk_adjustment_set_page_size(adjustment, (gdouble)visible);
4868 }
4869 DW_MUTEX_UNLOCK;
4870 }
4871
4872 /*
4873 * Sets the spinbutton value.
4874 * Parameters:
4875 * handle: Handle to the spinbutton to be set.
4876 * position: Current value of the spinbutton.
4877 */
4878 void dw_spinbutton_set_pos(HWND handle, long position)
4879 {
4880 int _locked_by_me = FALSE;
4881
4882 DW_MUTEX_LOCK;
4883 gtk_spin_button_set_value(GTK_SPIN_BUTTON(handle), (gfloat)position);
4884 DW_MUTEX_UNLOCK;
4885 }
4886
4887 /*
4888 * Sets the spinbutton limits.
4889 * Parameters:
4890 * handle: Handle to the spinbutton to be set.
4891 * position: Current value of the spinbutton.
4892 * position: Current value of the spinbutton.
4893 */
4894 void dw_spinbutton_set_limits(HWND handle, long upper, long lower)
4895 {
4896 long curval;
4897 GtkAdjustment *adj;
4898 int _locked_by_me = FALSE;
4899
4900 curval = dw_spinbutton_get_pos(handle);
4901 DW_MUTEX_LOCK;
4902 adj = (GtkAdjustment *)gtk_adjustment_new((gfloat)curval, (gfloat)lower, (gfloat)upper, 1.0, 5.0, 0.0);
4903 gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(handle), adj);
4904 /*
4905 * Set our internal relationships between the adjustment and the spinbutton
4906 */
4907 g_object_set_data(G_OBJECT(handle), "_dw_adjustment", (gpointer)adj);
4908 g_object_set_data(G_OBJECT(adj), "_dw_spinbutton", (gpointer)handle);
4909 DW_MUTEX_UNLOCK;
4910 }
4911
4912 /*
4913 * Sets the entryfield character limit.
4914 * Parameters:
4915 * handle: Handle to the spinbutton to be set.
4916 * limit: Number of characters the entryfield will take.
4917 */
4918 void dw_entryfield_set_limit(HWND handle, ULONG limit)
4919 {
4920 int _locked_by_me = FALSE;
4921
4922 DW_MUTEX_LOCK;
4923 gtk_entry_set_max_length(GTK_ENTRY(handle), limit);
4924 DW_MUTEX_UNLOCK;
4925 }
4926
4927 /*
4928 * Returns the current value of the spinbutton.
4929 * Parameters:
4930 * handle: Handle to the spinbutton to be queried.
4931 */
4932 long dw_spinbutton_get_pos(HWND handle)
4933 {
4934 long retval;
4935 int _locked_by_me = FALSE;
4936
4937 DW_MUTEX_LOCK;
4938 retval = (long)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(handle));
4939 DW_MUTEX_UNLOCK;
4940
4941 return retval;
4942 }
4943
4944 /*
4945 * Returns the state of the checkbox.
4946 * Parameters:
4947 * handle: Handle to the checkbox to be queried.
4948 */
4949 int dw_checkbox_get(HWND handle)
4950 {
4951 int retval;
4952 int _locked_by_me = FALSE;
4953
4954 DW_MUTEX_LOCK;
4955 retval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(handle));
4956 DW_MUTEX_UNLOCK;
4957
4958 return retval;
4959 }
4960
4961 /*
4962 * Sets the state of the checkbox.
4963 * Parameters:
4964 * handle: Handle to the checkbox to be queried.
4965 * value: TRUE for checked, FALSE for unchecked.
4966 */
4967 void dw_checkbox_set(HWND handle, int value)
4968 {
4969 int _locked_by_me = FALSE;
4970
4971 DW_MUTEX_LOCK;
4972 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(handle), value);
4973 DW_MUTEX_UNLOCK;
4974 }
4975
4976 /*
4977 * Inserts an item into a tree window (widget) after another item.
4978 * Parameters:
4979 * handle: Handle to the tree to be inserted.
4980 * item: Handle to the item to be positioned after.
4981 * title: The text title of the entry.
4982 * icon: Handle to coresponding icon.
4983 * parent: Parent handle or 0 if root.
4984 * itemdata: Item specific data.
4985 */
4986 HTREEITEM dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, HICN icon, HTREEITEM parent, void *itemdata)
4987 {
4988 GtkWidget *tree;
4989 GtkTreeIter *iter;
4990 GtkTreeStore *store;
4991 GdkPixbuf *pixbuf;
4992 HTREEITEM retval = 0;
4993 int _locked_by_me = FALSE;
4994
4995 if(!handle)
4996 return NULL;
4997
4998 DW_MUTEX_LOCK;
4999 if((tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user"))
5000 && GTK_IS_TREE_VIEW(tree) &&
5001 (store = (GtkTreeStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5002 {
5003 iter = (GtkTreeIter *)malloc(sizeof(GtkTreeIter));
5004
5005 pixbuf = _find_pixbuf(icon, NULL, NULL);
5006
5007 gtk_tree_store_insert_after(store, iter, (GtkTreeIter *)parent, (GtkTreeIter *)item);
5008 gtk_tree_store_set (store, iter, 0, title, 1, pixbuf, 2, itemdata, 3, iter, -1);
5009 if(pixbuf && !(icon & (1 << 31)))
5010 g_object_unref(pixbuf);
5011 retval = (HTREEITEM)iter;
5012 }
5013 DW_MUTEX_UNLOCK;
5014
5015 return retval;
5016 }
5017
5018 /*
5019 * Inserts an item into a tree window (widget).
5020 * Parameters:
5021 * handle: Handle to the tree to be inserted.
5022 * title: The text title of the entry.
5023 * icon: Handle to coresponding icon.
5024 * parent: Parent handle or 0 if root.
5025 * itemdata: Item specific data.
5026 */
5027 HTREEITEM dw_tree_insert(HWND handle, char *title, HICN icon, HTREEITEM parent, void *itemdata)
5028 {
5029 GtkWidget *tree;
5030 GtkTreeIter *iter;
5031 GtkTreeStore *store;
5032 GdkPixbuf *pixbuf;
5033 HTREEITEM retval = 0;
5034 int _locked_by_me = FALSE;
5035
5036 if(!handle)
5037 return NULL;
5038
5039 DW_MUTEX_LOCK;
5040 if((tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user"))
5041 && GTK_IS_TREE_VIEW(tree) &&
5042 (store = (GtkTreeStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5043 {
5044 iter = (GtkTreeIter *)malloc(sizeof(GtkTreeIter));
5045
5046 pixbuf = _find_pixbuf(icon, NULL, NULL);
5047
5048 gtk_tree_store_append (store, iter, (GtkTreeIter *)parent);
5049 gtk_tree_store_set (store, iter, 0, title, 1, pixbuf, 2, itemdata, 3, iter, -1);
5050 if(pixbuf && !(icon & (1 << 31)))
5051 g_object_unref(pixbuf);
5052 retval = (HTREEITEM)iter;
5053 }
5054 DW_MUTEX_UNLOCK;
5055
5056 return retval;
5057 }
5058
5059 /*
5060 * Sets the text and icon of an item in a tree window (widget).
5061 * Parameters:
5062 * handle: Handle to the tree containing the item.
5063 * item: Handle of the item to be modified.
5064 * title: The text title of the entry.
5065 * icon: Handle to coresponding icon.
5066 */
5067 void dw_tree_item_change(HWND handle, HTREEITEM item, char *title, HICN icon)
5068 {
5069 GtkWidget *tree;
5070 GtkTreeStore *store;
5071 GdkPixbuf *pixbuf;
5072 int _locked_by_me = FALSE;
5073
5074 if(!handle)
5075 return;
5076
5077 DW_MUTEX_LOCK;
5078 if((tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user"))
5079 && GTK_IS_TREE_VIEW(tree) &&
5080 (store = (GtkTreeStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5081 {
5082 pixbuf = _find_pixbuf(icon, NULL, NULL);
5083
5084 gtk_tree_store_set(store, (GtkTreeIter *)item, 0, title, 1, pixbuf, -1);
5085 if(pixbuf && !(icon & (1 << 31)))
5086 g_object_unref(pixbuf);
5087 }
5088 DW_MUTEX_UNLOCK;
5089 }
5090
5091 /*
5092 * Sets the item data of a tree item.
5093 * Parameters:
5094 * handle: Handle to the tree containing the item.
5095 * item: Handle of the item to be modified.
5096 * itemdata: User defined data to be associated with item.
5097 */
5098 void dw_tree_item_set_data(HWND handle, HTREEITEM item, void *itemdata)
5099 {
5100 GtkWidget *tree;
5101 GtkTreeStore *store;
5102 int _locked_by_me = FALSE;
5103
5104 if(!handle || !item)
5105 return;
5106
5107 DW_MUTEX_LOCK;
5108 if((tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user"))
5109 && GTK_IS_TREE_VIEW(tree) &&
5110 (store = (GtkTreeStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5111 gtk_tree_store_set(store, (GtkTreeIter *)item, 2, itemdata, -1);
5112 DW_MUTEX_UNLOCK;
5113 }
5114
5115 /*
5116 * Gets the text an item in a tree window (widget).
5117 * Parameters:
5118 * handle: Handle to the tree containing the item.
5119 * item: Handle of the item to be modified.
5120 */
5121 char * API dw_tree_get_title(HWND handle, HTREEITEM item)
5122 {
5123 int _locked_by_me = FALSE;
5124 char *text = NULL;
5125 GtkWidget *tree;
5126 GtkTreeModel *store;
5127
5128 if(!handle || !item)
5129 return text;
5130
5131 DW_MUTEX_LOCK;
5132 tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
5133
5134 if(tree && GTK_IS_TREE_VIEW(tree) &&
5135 (store = (GtkTreeModel *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5136 gtk_tree_model_get(store, (GtkTreeIter *)item, 0, &text, -1);
5137 DW_MUTEX_UNLOCK;
5138 return text;
5139 }
5140
5141 /*
5142 * Gets the text an item in a tree window (widget).
5143 * Parameters:
5144 * handle: Handle to the tree containing the item.
5145 * item: Handle of the item to be modified.
5146 */
5147 HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item)
5148 {
5149 int _locked_by_me = FALSE;
5150 HTREEITEM parent = (HTREEITEM)0;
5151 GtkWidget *tree;
5152 GtkTreeModel *store;
5153
5154 if(!handle || !item)
5155 return parent;
5156
5157 DW_MUTEX_LOCK;
5158 tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
5159
5160 if(tree && GTK_IS_TREE_VIEW(tree) &&
5161 (store = (GtkTreeModel *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5162 {
5163 GtkTreeIter *p = malloc(sizeof(GtkTreeIter));
5164
5165 if(gtk_tree_model_iter_parent(store, p, (GtkTreeIter *)item))
5166 parent = p;
5167 else
5168 free(p);
5169 }
5170 DW_MUTEX_UNLOCK;
5171 return parent;
5172 }
5173
5174 /*
5175 * Gets the item data of a tree item.
5176 * Parameters:
5177 * handle: Handle to the tree containing the item.
5178 * item: Handle of the item to be modified.
5179 */
5180 void *dw_tree_item_get_data(HWND handle, HTREEITEM item)
5181 {
5182 void *ret = NULL;
5183 GtkWidget *tree;
5184 GtkTreeModel *store;
5185 int _locked_by_me = FALSE;
5186
5187 if(!handle || !item)
5188 return NULL;
5189
5190 DW_MUTEX_LOCK;
5191 if((tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user"))
5192 && GTK_IS_TREE_VIEW(tree) &&
5193 (store = (GtkTreeModel *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5194 gtk_tree_model_get(store, (GtkTreeIter *)item, 2, &ret, -1);
5195 DW_MUTEX_UNLOCK;
5196 return ret;
5197 }
5198
5199 /*
5200 * Sets this item as the active selection.
5201 * Parameters:
5202 * handle: Handle to the tree window (widget) to be selected.
5203 * item: Handle to the item to be selected.
5204 */
5205 void dw_tree_item_select(HWND handle, HTREEITEM item)
5206 {
5207 GtkWidget *tree;
5208 GtkTreeStore *store;
5209 int _locked_by_me = FALSE;
5210
5211 if(!handle || !item)
5212 return;
5213
5214 DW_MUTEX_LOCK;
5215 if((tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user"))
5216 && GTK_IS_TREE_VIEW(tree) &&
5217 (store = (GtkTreeStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5218 {
5219 GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), (GtkTreeIter *)item);
5220 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
5221
5222 gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree), path, NULL, FALSE);
5223 gtk_tree_selection_select_iter(sel, (GtkTreeIter *)item);
5224 gtk_tree_path_free(path);
5225 }
5226 DW_MUTEX_UNLOCK;
5227 }
5228
5229 static void _dw_recursive_free(GtkTreeModel *store, GtkTreeIter parent)
5230 {
5231 void *data;
5232 GtkTreeIter iter;
5233
5234 gtk_tree_model_get(store, &parent, 3, &data, -1);
5235 if(data)
5236 free(data);
5237 gtk_tree_store_set(GTK_TREE_STORE(store), &parent, 3, NULL, -1);
5238
5239 if(gtk_tree_model_iter_children(store, &iter, &parent))
5240 {
5241 do {
5242 _dw_recursive_free(GTK_TREE_MODEL(store), iter);
5243 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
5244 }
5245 }
5246
5247 /*
5248 * Removes all nodes from a tree.
5249 * Parameters:
5250 * handle: Handle to the window (widget) to be cleared.
5251 */
5252 void dw_tree_clear(HWND handle)
5253 {
5254 GtkWidget *tree;
5255 GtkTreeStore *store;
5256 int _locked_by_me = FALSE;
5257
5258 if(!handle)
5259 return;
5260
5261 DW_MUTEX_LOCK;
5262 if((tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user"))
5263 && GTK_IS_TREE_VIEW(tree) &&
5264 (store = (GtkTreeStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5265 {
5266 GtkTreeIter iter;
5267
5268 if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
5269 {
5270 do {
5271 _dw_recursive_free(GTK_TREE_MODEL(store), iter);
5272 } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
5273 }
5274 gtk_tree_store_clear(store);
5275 }
5276 DW_MUTEX_UNLOCK;
5277 }
5278
5279 /*
5280 * Expands a node on a tree.
5281 * Parameters:
5282 * handle: Handle to the tree window (widget).
5283 * item: Handle to node to be expanded.
5284 */
5285 void dw_tree_item_expand(HWND handle, HTREEITEM item)
5286 {
5287 GtkWidget *tree;
5288 GtkTreeStore *store;
5289 int _locked_by_me = FALSE;
5290
5291 if(!handle)
5292 return;
5293
5294 DW_MUTEX_LOCK;
5295 if((tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user"))
5296 && GTK_IS_TREE_VIEW(tree) &&
5297 (store = (GtkTreeStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5298 {
5299 GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), (GtkTreeIter *)item);
5300 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree), path, FALSE);
5301 gtk_tree_path_free(path);
5302 }
5303 DW_MUTEX_UNLOCK;
5304 }
5305
5306 /*
5307 * Collapses a node on a tree.
5308 * Parameters:
5309 * handle: Handle to the tree window (widget).
5310 * item: Handle to node to be collapsed.
5311 */
5312 void dw_tree_item_collapse(HWND handle, HTREEITEM item)
5313 {
5314 GtkWidget *tree;
5315 GtkTreeStore *store;
5316 int _locked_by_me = FALSE;
5317
5318 if(!handle)
5319 return;
5320
5321 DW_MUTEX_LOCK;
5322 if((tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user"))
5323 && GTK_IS_TREE_VIEW(tree) &&
5324 (store = (GtkTreeStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5325 {
5326 GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), (GtkTreeIter *)item);
5327 gtk_tree_view_collapse_row(GTK_TREE_VIEW(tree), path);
5328 gtk_tree_path_free(path);
5329 }
5330 DW_MUTEX_UNLOCK;
5331 }
5332
5333 /*
5334 * Removes a node from a tree.
5335 * Parameters:
5336 * handle: Handle to the window (widget) to be cleared.
5337 * item: Handle to node to be deleted.
5338 */
5339 void dw_tree_item_delete(HWND handle, HTREEITEM item)
5340 {
5341 GtkWidget *tree;
5342 GtkTreeStore *store;
5343 int _locked_by_me = FALSE;
5344
5345 if(!handle)
5346 return;
5347
5348 DW_MUTEX_LOCK;
5349 if((tree = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user"))
5350 && GTK_IS_TREE_VIEW(tree) &&
5351 (store = (GtkTreeStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(tree))))
5352 {
5353 gtk_tree_store_remove(store, (GtkTreeIter *)item);
5354 free(item);
5355 }
5356 DW_MUTEX_UNLOCK;
5357 }
5358
5359 static int _dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator, int extra)
5360 {
5361 int z;
5362 GtkWidget *tree;
5363 GtkListStore *store;
5364 GtkTreeViewColumn *col;
5365 GtkCellRenderer *rend;
5366 GtkTreeSelection *sel;
5367 int _locked_by_me = FALSE;
5368 GType *array = calloc(count, sizeof(gint));
5369
5370 DW_MUTEX_LOCK;
5371 /* First loop... create array to create the store */
5372 for(z=0;z<count;z++)
5373 {
5374 if(flags[z] & DW_CFA_BITMAPORICON)
5375 {
5376 array[z] = GDK_TYPE_PIXBUF;
5377 }
5378 else if(flags[z] & DW_CFA_STRING)
5379 {
5380 array[z] = G_TYPE_STRING;
5381 }
5382 else if(flags[z] & DW_CFA_ULONG)
5383 {
5384 array[z] = G_TYPE_ULONG;
5385 }
5386 else if(flags[z] & DW_CFA_TIME)
5387 {
5388 array[z] = G_TYPE_STRING;
5389 }
5390 else if(flags[z] & DW_CFA_DATE)
5391 {
5392 array[z] = G_TYPE_STRING;
5393 }
5394 }
5395 /* Create the store and then the tree */
5396 store = gtk_list_store_newv(count, array);
5397 tree = _tree_setup(handle, GTK_TREE_MODEL(store));
5398 /* Second loop... create the columns */
5399 for(z=0;z<count;z++)
5400 {
5401 col = gtk_tree_view_column_new();
5402 if(flags[z] & DW_CFA_BITMAPORICON)
5403 {
5404 rend = gtk_cell_renderer_pixbuf_new();
5405 gtk_tree_view_column_pack_start(col, rend, FALSE);
5406 gtk_tree_view_column_add_attribute(col, rend, "pixbuf", z);
5407 }
5408 else if(flags[z] & DW_CFA_STRING)
5409 {
5410 rend = gtk_cell_renderer_text_new();
5411 gtk_tree_view_column_pack_start(col, rend, TRUE);
5412 gtk_tree_view_column_add_attribute(col, rend, "text", z);
5413 }
5414 else if(flags[z] & DW_CFA_ULONG)
5415 {
5416 rend = gtk_cell_renderer_text_new();
5417 gtk_tree_view_column_pack_start(col, rend, TRUE);
5418 gtk_tree_view_column_add_attribute(col, rend, "text", z);
5419 }
5420 else if(flags[z] & DW_CFA_TIME)
5421 {
5422 rend = gtk_cell_renderer_text_new();
5423 gtk_tree_view_column_pack_start(col, rend, TRUE);
5424 gtk_tree_view_column_add_attribute(col, rend, "text", z);
5425 }
5426 else if(flags[z] & DW_CFA_DATE)
5427 {
5428 rend = gtk_cell_renderer_text_new();
5429 gtk_tree_view_column_pack_start(col, rend, TRUE);
5430 gtk_tree_view_column_add_attribute(col, rend, "text", z);
5431 }
5432 gtk_tree_view_append_column(GTK_TREE_VIEW (tree), col);
5433 gtk_tree_view_set_expander_column(GTK_TREE_VIEW(tree), col);
5434 }
5435 /* Finish up */
5436 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), TRUE);
5437 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
5438 if(g_object_get_data(G_OBJECT(handle), "_dw_multi_sel"))
5439 {
5440 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
5441 }
5442 else
5443 {
5444 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
5445 }
5446 gtk_widget_show(handle);
5447 free(array);
5448 DW_MUTEX_UNLOCK;
5449 return TRUE;
5450 }
5451
5452 /*
5453 * Sets up the container columns.
5454 * Parameters:
5455 * handle: Handle to the container to be configured.
5456 * flags: An array of unsigned longs with column flags.
5457 * titles: An array of strings with column text titles.
5458 * count: The number of columns (this should match the arrays).
5459 * separator: The column number that contains the main separator.
5460 * (this item may only be used in OS/2)
5461 */
5462 int dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator)
5463 {
5464 return _dw_container_setup(handle, flags, titles, count, separator, 0);
5465 }
5466
5467 /*
5468 * Sets up the filesystem columns, note: filesystem always has an icon/filename field.
5469 * Parameters:
5470 * handle: Handle to the container to be configured.
5471 * flags: An array of unsigned longs with column flags.
5472 * titles: An array of strings with column text titles.
5473 * count: The number of columns (this should match the arrays).
5474 */
5475 int dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count)
5476 {
5477 char **newtitles = malloc(sizeof(char *) * (count + 2));
5478 unsigned long *newflags = malloc(sizeof(unsigned long) * (count + 2));
5479
5480 newtitles[0] = "Filename";
5481 newflags[0] = DW_CFA_STRINGANDICON | DW_CFA_LEFT | DW_CFA_HORZSEPARATOR;
5482
5483 memcpy(&newtitles[2], titles, sizeof(char *) * count);
5484 memcpy(&newflags[2], flags, sizeof(unsigned long) * count);
5485
5486 _dw_container_setup(handle, newflags, newtitles, count + 1, 1, 1);
5487
5488 if ( newtitles) free(newtitles);
5489 if ( newflags ) free(newflags);
5490 return TRUE;
5491 }
5492
5493 /*
5494 * Obtains an icon from a module (or header in GTK).
5495 * Parameters:
5496 * module: Handle to module (DLL) in OS/2 and Windows.
5497 * id: A unsigned long id int the resources on OS/2 and
5498 * Windows, on GTK this is converted to a pointer
5499 * to an embedded XPM.
5500 */
5501 HICN dw_icon_load(unsigned long module, unsigned long id)
5502 {
5503 return id;
5504 }
5505
5506 HICN _dw_icon_load_internal(GdkPixbuf *pixbuf)
5507 {
5508 unsigned long z, ret = 0;
5509 int found = -1;
5510
5511 /* Find a free entry in the array */
5512 for (z=0;z<_PixmapCount;z++)
5513 {
5514 if (!_PixmapArray[z].used)
5515 {
5516 ret = found = z;
5517 break;
5518 }
5519 }
5520
5521 /* If there are no free entries, expand the
5522 * array.
5523 */
5524 if (found == -1)
5525 {
5526 DWPrivatePixmap *old = _PixmapArray;
5527
5528 ret = found = _PixmapCount;
5529 _PixmapCount++;
5530
5531 _PixmapArray = malloc(sizeof(DWPrivatePixmap) * _PixmapCount);
5532
5533 if (found)
5534 memcpy(_PixmapArray, old, sizeof(DWPrivatePixmap) * found);
5535 if (old)
5536 free(old);
5537 _PixmapArray[found].used = 1;
5538 _PixmapArray[found].pixbuf = NULL;
5539 }
5540
5541 _PixmapArray[found].pixbuf = pixbuf;
5542 _PixmapArray[found].width = gdk_pixbuf_get_width(pixbuf);
5543 _PixmapArray[found].height = gdk_pixbuf_get_height(pixbuf);
5544
5545 if (!_PixmapArray[found].pixbuf)
5546 {
5547 _PixmapArray[found].used = 0;
5548 _PixmapArray[found].pixbuf = NULL;
5549 return 0;
5550 }
5551 return (HICN)ret | (1 << 31);
5552 }
5553
5554 /*
5555 * Obtains an icon from a file.
5556 * Parameters:
5557 * filename: Name of the file, omit extention to have
5558 * DW pick the appropriate file extension.
5559 * (ICO on OS/2 or Windows, XPM on Unix)
5560 */
5561 HICN API dw_icon_load_from_file(char *filename)
5562 {
5563 int _locked_by_me = FALSE;
5564 GdkPixbuf *pixbuf;
5565 char *file = alloca(strlen(filename) + 5);
5566 int found_ext = 0;
5567 int i, ret = 0;
5568
5569 if (!file)
5570 return 0;
5571
5572 strcpy(file, filename);
5573
5574 /* check if we can read from this file (it exists and read permission) */
5575 if (access(file, 04) != 0)
5576 {
5577 /* Try with various extentions */
5578 for ( i = 0; i < NUM_EXTS; i++ )
5579 {
5580 strcpy( file, filename );
5581 strcat( file, image_exts[i] );
5582 if ( access( file, 04 ) == 0 )
5583 {
5584 found_ext = 1;
5585 break;
5586 }
5587 }
5588 if ( found_ext == 0 )
5589 {
5590 return 0;
5591 }
5592 }
5593
5594 DW_MUTEX_LOCK;
5595 pixbuf = gdk_pixbuf_new_from_file(file, NULL);
5596 if (pixbuf)
5597 {
5598 ret = _dw_icon_load_internal(pixbuf);
5599 }
5600 DW_MUTEX_UNLOCK;
5601 return ret;
5602 }
5603
5604 /*
5605 * Obtains an icon from data.
5606 * Parameters:
5607 * data: Source of data for image.
5608 * len: length of data
5609 */
5610 HICN API dw_icon_load_from_data(char *data, int len)
5611 {
5612 int _locked_by_me = FALSE;
5613 char *file;
5614 FILE *fp;
5615 GdkPixbuf *pixbuf;
5616 unsigned long z, ret = 0;
5617
5618 /*
5619 * A real hack; create a temporary file and write the contents
5620 * of the data to the file
5621 */
5622 file = tmpnam( NULL );
5623 fp = fopen( file, "wb" );
5624 if ( fp )
5625 {
5626 fwrite( data, len, 1, fp );
5627 fclose( fp );
5628 }
5629 else
5630 {
5631 return 0;
5632 }
5633 DW_MUTEX_LOCK;
5634 pixbuf = gdk_pixbuf_new_from_file(file, NULL);
5635 if (pixbuf)
5636 {
5637 ret = _dw_icon_load_internal(pixbuf);
5638 }
5639 DW_MUTEX_UNLOCK;
5640 return ret;
5641 }
5642
5643 /*
5644 * Frees a loaded resource in OS/2 and Windows.
5645 * Parameters:
5646 * handle: Handle to icon returned by dw_icon_load().
5647 */
5648 void dw_icon_free(HICN handle)
5649 {
5650 /* If it is a private icon, find the item
5651 * free the associated structures and set
5652 * the entry to unused.
5653 */
5654 if(handle & (1 << 31))
5655 {
5656 unsigned long id = handle & 0xFFFFFF;
5657
5658 if(id < _PixmapCount && _PixmapArray[id].used)
5659 {
5660 if(_PixmapArray[id].pixbuf)
5661 {
5662 g_object_unref(_PixmapArray[id].pixbuf);
5663 _PixmapArray[id].pixbuf = NULL;
5664 }
5665 _PixmapArray[id].used = 0;
5666 }
5667 }
5668 }
5669
5670 /*
5671 * Allocates memory used to populate a container.
5672 * Parameters:
5673 * handle: Handle to the container window (widget).
5674 * rowcount: The number of items to be populated.
5675 */
5676 void *dw_container_alloc(HWND handle, int rowcount)
5677 {
5678 #if 0
5679 int z, count = 0, prevrowcount = 0;
5680 GtkWidget *clist;
5681 GdkColor *fore, *back;
5682 char **blah;
5683 int _locked_by_me = FALSE;
5684
5685 DW_MUTEX_LOCK;
5686 clist = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
5687 if(!clist)
5688 {
5689 DW_MUTEX_UNLOCK;
5690 return NULL;
5691 }
5692
5693 count = (int)g_object_get_data(G_OBJECT(clist), "_dw_colcount");
5694 prevrowcount = (int)g_object_get_data(G_OBJECT(clist), "_dw_rowcount");
5695
5696 if(!count)
5697 {
5698 DW_MUTEX_UNLOCK;
5699 return NULL;
5700 }
5701
5702 blah = malloc(sizeof(char *) * count);
5703 memset(blah, 0, sizeof(char *) * count);
5704
5705 fore = (GdkColor *)g_object_get_data(G_OBJECT(clist), "_dw_foregdk");
5706 back = (GdkColor *)g_object_get_data(G_OBJECT(clist), "_dw_backgdk");
5707 gtk_clist_freeze(GTK_CLIST(clist));
5708 for(z=0;z<rowcount;z++)
5709 {
5710 gtk_clist_append(GTK_CLIST(clist), blah);
5711 if(fore)
5712 gtk_clist_set_foreground(GTK_CLIST(clist), z + prevrowcount, fore);
5713 if(back)
5714 gtk_clist_set_background(GTK_CLIST(clist), z + prevrowcount, back);
5715 }
5716 g_object_set_data(G_OBJECT(clist), "_dw_insertpos", GINT_TO_POINTER(prevrowcount));
5717 g_object_set_data(G_OBJECT(clist), "_dw_rowcount", GINT_TO_POINTER(rowcount + prevrowcount));
5718 free(blah);
5719 DW_MUTEX_UNLOCK;
5720 return (void *)handle;
5721 #endif
5722 return NULL;
5723 }
5724
5725 /*
5726 * Internal representation of dw_container_set_item() extracted so we can pass
5727 * two data pointers; icon and text for dw_filesystem_set_item().
5728 */
5729 void _dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data, char *text)
5730 {
5731 #if 0
5732 char numbuf[10], textbuffer[100];
5733 int flag = 0;
5734 GtkWidget *clist;
5735 int _locked_by_me = FALSE;
5736
5737 DW_MUTEX_LOCK;
5738 clist = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
5739 if(!clist)
5740 {
5741 DW_MUTEX_UNLOCK;
5742 return;
5743 }
5744
5745 sprintf(numbuf, "%d", column);
5746 flag = (int)g_object_get_data(G_OBJECT(clist), numbuf);
5747 row += (int)g_object_get_data(G_OBJECT(clist), "_dw_insertpos");
5748
5749 if(flag & DW_CFA_BITMAPORICON)
5750 {
5751 long hicon = *((long *)data);
5752 GdkBitmap *bitmap = NULL;
5753 GdkPixmap *pixmap = _find_pixmap(&bitmap, hicon, clist, NULL, NULL);
5754
5755 if(pixmap)
5756 gtk_clist_set_pixmap(GTK_CLIST(clist), row, column, pixmap, bitmap);
5757 }
5758 else if(flag & DW_CFA_STRINGANDICON)
5759 {
5760 long hicon = *((long *)data);
5761 GdkBitmap *bitmap = NULL;
5762 GdkPixmap *pixmap = _find_pixmap(&bitmap, hicon, clist, NULL, NULL);
5763
5764 if(pixmap)
5765 gtk_clist_set_pixtext(GTK_CLIST(clist), row, column, text, 2, pixmap, bitmap);
5766 }
5767 else if(flag & DW_CFA_STRING)
5768 {
5769 char *tmp = *((char **)data);
5770 gtk_clist_set_text(GTK_CLIST(clist), row, column, tmp);
5771 }
5772 else if(flag & DW_CFA_ULONG)
5773 {
5774 ULONG tmp = *((ULONG *)data);
5775
5776 sprintf(textbuffer, "%lu", tmp);
5777
5778 gtk_clist_set_text(GTK_CLIST(clist), row, column, textbuffer);
5779 }
5780 else if(flag & DW_CFA_DATE)
5781 {
5782 struct tm curtm;
5783 CDATE cdate = *((CDATE *)data);
5784
5785 memset( &curtm, 0, sizeof(curtm) );
5786 curtm.tm_mday = cdate.day;
5787 curtm.tm_mon = cdate.month - 1;
5788 curtm.tm_year = cdate.year - 1900;
5789
5790 strftime(textbuffer, 100, "%x", &curtm);
5791
5792 gtk_clist_set_text(GTK_CLIST(clist), row, column, textbuffer);
5793 }
5794 else if(flag & DW_CFA_TIME)
5795 {
5796 struct tm curtm;
5797 CTIME ctime = *((CTIME *)data);
5798
5799 memset( &curtm, 0, sizeof(curtm) );
5800 curtm.tm_hour = ctime.hours;
5801 curtm.tm_min = ctime.minutes;
5802 curtm.tm_sec = ctime.seconds;
5803
5804 strftime(textbuffer, 100, "%X", &curtm);
5805
5806 gtk_clist_set_text(GTK_CLIST(clist), row, column, textbuffer);
5807 }
5808 DW_MUTEX_UNLOCK;
5809 #endif
5810 }
5811
5812 /*
5813 * Sets an item in specified row and column to the given data.
5814 * Parameters:
5815 * handle: Handle to the container window (widget).
5816 * pointer: Pointer to the allocated memory in dw_container_alloc().
5817 * column: Zero based column of data being set.
5818 * row: Zero based row of data being set.
5819 * data: Pointer to the data to be added.
5820 */
5821 void dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data)
5822 {
5823 _dw_container_set_item(handle, NULL, column, row, data, NULL);
5824 }
5825
5826 /*
5827 * Changes an existing item in specified row and column to the given data.
5828 * Parameters:
5829 * handle: Handle to the container window (widget).
5830 * column: Zero based column of data being set.
5831 * row: Zero based row of data being set.
5832 * data: Pointer to the data to be added.
5833 */
5834 void dw_container_change_item(HWND handle, int column, int row, void *data)
5835 {
5836 _dw_container_set_item(handle, NULL, column, row, data, NULL);
5837 }
5838
5839 /*
5840 * Changes an existing item in specified row and column to the given data.
5841 * Parameters:
5842 * handle: Handle to the container window (widget).
5843 * column: Zero based column of data being set.
5844 * row: Zero based row of data being set.
5845 * data: Pointer to the data to be added.
5846 */
5847 void API dw_filesystem_change_item(HWND handle, int column, int row, void *data)
5848 {
5849 dw_filesystem_set_item(handle, NULL, column, row, data);
5850 }
5851
5852 /*
5853 * Changes an item in specified row and column to the given data.
5854 * Parameters:
5855 * handle: Handle to the container window (widget).
5856 * pointer: Pointer to the allocated memory in dw_container_alloc().
5857 * column: Zero based column of data being set.
5858 * row: Zero based row of data being set.
5859 * data: Pointer to the data to be added.
5860 */
5861 void API dw_filesystem_change_file(HWND handle, int row, char *filename, HICN icon)
5862 {
5863 dw_filesystem_set_file(handle, NULL, row, filename, icon);
5864 }
5865
5866 /*
5867 * Sets an item in specified row and column to the given data.
5868 * Parameters:
5869 * handle: Handle to the container window (widget).
5870 * pointer: Pointer to the allocated memory in dw_container_alloc().
5871 * column: Zero based column of data being set.
5872 * row: Zero based row of data being set.
5873 * data: Pointer to the data to be added.
5874 */
5875 void dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, HICN icon)
5876 {
5877 _dw_container_set_item(handle, pointer, 0, row, (void *)&icon, filename);
5878 }
5879
5880 /*
5881 * Sets an item in specified row and column to the given data.
5882 * Parameters:
5883 * handle: Handle to the container window (widget).
5884 * pointer: Pointer to the allocated memory in dw_container_alloc().
5885 * column: Zero based column of data being set.
5886 * row: Zero based row of data being set.
5887 * data: Pointer to the data to be added.
5888 */
5889 void dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data)
5890 {
5891 _dw_container_set_item(handle, pointer, column + 1, row, data, NULL);
5892 }
5893
5894 /*
5895 * Gets column type for a container column
5896 * Parameters:
5897 * handle: Handle to the container window (widget).
5898 * column: Zero based column.
5899 */
5900 int dw_container_get_column_type(HWND handle, int column)
5901 {
5902 char numbuf[10];
5903 int flag, rc;
5904 #if 0
5905 GtkWidget *clist;
5906 int _locked_by_me = FALSE;
5907
5908 DW_MUTEX_LOCK;
5909 clist = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
5910 if(!clist)
5911 {
5912 DW_MUTEX_UNLOCK;
5913 return 0;
5914 }
5915
5916 sprintf(numbuf, "%d", column);
5917 flag = (int)g_object_get_data(G_OBJECT(clist), numbuf);
5918
5919 if(flag & DW_CFA_BITMAPORICON)
5920 rc = DW_CFA_BITMAPORICON;
5921 else if(flag & DW_CFA_STRING)
5922 rc = DW_CFA_STRING;
5923 else if(flag & DW_CFA_ULONG)
5924 rc = DW_CFA_ULONG;
5925 else if(flag & DW_CFA_DATE)
5926 rc = DW_CFA_DATE;
5927 else if(flag & DW_CFA_TIME)
5928 rc = DW_CFA_TIME;
5929 else
5930 rc = 0;
5931 DW_MUTEX_UNLOCK;
5932 #endif
5933 return rc;
5934 }
5935
5936 /*
5937 * Gets column type for a filesystem container column
5938 * Parameters:
5939 * handle: Handle to the container window (widget).
5940 * column: Zero based column.
5941 */
5942 int API dw_filesystem_get_column_type(HWND handle, int column)
5943 {
5944 return dw_container_get_column_type( handle, column + 1 );
5945 }
5946
5947 /*
5948 * Sets the width of a column in the container.
5949 * Parameters:
5950 * handle: Handle to window (widget) of container.
5951 * column: Zero based column of width being set.
5952 * width: Width of column in pixels.
5953 */
5954 void dw_container_set_column_width(HWND handle, int column, int width)
5955 {
5956 }
5957
5958 /*
5959 * Sets the title of a row in the container.
5960 * Parameters:
5961 * pointer: Pointer to the allocated memory in dw_container_alloc().
5962 * row: Zero based row of data being set.
5963 * title: String title of the item.
5964 */
5965 void dw_container_set_row_title(void *pointer, int row, char *title)
5966 {
5967 }
5968
5969 /*
5970 * Sets the title of a row in the container.
5971 * Parameters:
5972 * handle: Handle to the container window (widget).
5973 * pointer: Pointer to the allocated memory in dw_container_alloc().
5974 * rowcount: The number of rows to be inserted.
5975 */
5976 void dw_container_insert(HWND handle, void *pointer, int rowcount)
5977 {
5978 }
5979
5980 /*
5981 * Removes the first x rows from a container.
5982 * Parameters:
5983 * handle: Handle to the window (widget) to be deleted from.
5984 * rowcount: The number of rows to be deleted.
5985 */
5986 void dw_container_delete(HWND handle, int rowcount)
5987 {
5988 }
5989
5990 /*
5991 * Removes all rows from a container.
5992 * Parameters:
5993 * handle: Handle to the window (widget) to be cleared.
5994 * redraw: TRUE to cause the container to redraw immediately.
5995 */
5996 void dw_container_clear(HWND handle, int redraw)
5997 {
5998 }
5999
6000 /*
6001 * Scrolls container up or down.
6002 * Parameters:
6003 * handle: Handle to the window (widget) to be scrolled.
6004 * direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or
6005 * DW_SCROLL_BOTTOM. (rows is ignored for last two)
6006 * rows: The number of rows to be scrolled.
6007 */
6008 void dw_container_scroll(HWND handle, int direction, long rows)
6009 {
6010 }
6011
6012 /*
6013 * Starts a new query of a container.
6014 * Parameters:
6015 * handle: Handle to the window (widget) to be queried.
6016 * flags: If this parameter is DW_CRA_SELECTED it will only
6017 * return items that are currently selected. Otherwise
6018 * it will return all records in the container.
6019 */
6020 char *dw_container_query_start(HWND handle, unsigned long flags)
6021 {
6022 char *retval = NULL;
6023 int _locked_by_me = FALSE;
6024
6025 return retval;
6026 }
6027
6028 /*
6029 * Continues an existing query of a container.
6030 * Parameters:
6031 * handle: Handle to the window (widget) to be queried.
6032 * flags: If this parameter is DW_CRA_SELECTED it will only
6033 * return items that are currently selected. Otherwise
6034 * it will return all records in the container.
6035 */
6036 char *dw_container_query_next(HWND handle, unsigned long flags)
6037 {
6038 char *retval = NULL;
6039 int _locked_by_me = FALSE;
6040
6041 return retval;
6042 }
6043
6044 /*
6045 * Cursors the item with the text speficied, and scrolls to that item.
6046 * Parameters:
6047 * handle: Handle to the window (widget) to be queried.
6048 * text: Text usually returned by dw_container_query().
6049 */
6050 void dw_container_cursor(HWND handle, char *text)
6051 {
6052 }
6053
6054 /*
6055 * Deletes the item with the text speficied.
6056 * Parameters:
6057 * handle: Handle to the window (widget).
6058 * text: Text usually returned by dw_container_query().
6059 */
6060 void dw_container_delete_row(HWND handle, char *text)
6061 {
6062 }
6063
6064 /*
6065 * Optimizes the column widths so that all data is visible.
6066 * Parameters:
6067 * handle: Handle to the window (widget) to be optimized.
6068 */
6069 void dw_container_optimize(HWND handle)
6070 {
6071 }
6072
6073 /*
6074 * Inserts an icon into the taskbar.
6075 * Parameters:
6076 * handle: Window handle that will handle taskbar icon messages.
6077 * icon: Icon handle to display in the taskbar.
6078 * bubbletext: Text to show when the mouse is above the icon.
6079 */
6080 void dw_taskbar_insert(HWND handle, HICN icon, char *bubbletext)
6081 {
6082 /* TODO */
6083 }
6084
6085 /*
6086 * Deletes an icon from the taskbar.
6087 * Parameters:
6088 * handle: Window handle that was used with dw_taskbar_insert().
6089 * icon: Icon handle that was used with dw_taskbar_insert().
6090 */
6091 void dw_taskbar_delete(HWND handle, HICN icon)
6092 {
6093 /* TODO */
6094 }
6095
6096 /*
6097 * Creates a rendering context widget (window) to be packed.
6098 * Parameters:
6099 * id: An id to be used with dw_window_from_id.
6100 * Returns:
6101 * A handle to the widget or NULL on failure.
6102 */
6103 HWND dw_render_new(unsigned long id)
6104 {
6105 int _locked_by_me = FALSE;
6106 GtkWidget *tmp;
6107
6108 DW_MUTEX_LOCK;
6109 tmp = gtk_drawing_area_new();
6110 gtk_widget_set_events(tmp, GDK_EXPOSURE_MASK
6111 | GDK_LEAVE_NOTIFY_MASK
6112 | GDK_BUTTON_PRESS_MASK
6113 | GDK_BUTTON_RELEASE_MASK
6114 | GDK_KEY_PRESS_MASK
6115 | GDK_POINTER_MOTION_MASK
6116 | GDK_POINTER_MOTION_HINT_MASK);
6117 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
6118 gtk_widget_set_can_focus(tmp, TRUE);
6119 gtk_widget_show(tmp);
6120 DW_MUTEX_UNLOCK;
6121 return tmp;
6122 }
6123
6124 /* Returns a GdkColor from a DW color */
6125 static GdkColor _internal_color(unsigned long value)
6126 {
6127 if(DW_RGB_COLOR & value)
6128 {
6129 GdkColor color = { 0, DW_RED_VALUE(value) << 8, DW_GREEN_VALUE(value) << 8, DW_BLUE_VALUE(value) << 8 };
6130 return color;
6131 }
6132 if (value < 16)
6133 return _colors[value];
6134 return _colors[0];
6135 }
6136
6137 /* Sets the current foreground drawing color.
6138 * Parameters:
6139 * red: red value.
6140 * green: green value.
6141 * blue: blue value.
6142 */
6143 void dw_color_foreground_set(unsigned long value)
6144 {
6145 int _locked_by_me = FALSE, index = _find_thread_index(dw_thread_id());
6146 GdkColor color = _internal_color(value);
6147
6148 DW_MUTEX_LOCK;
6149 _foreground[index] = color;
6150 DW_MUTEX_UNLOCK;
6151 }
6152
6153 /* Sets the current background drawing color.
6154 * Parameters:
6155 * red: red value.
6156 * green: green value.
6157 * blue: blue value.
6158 */
6159 void dw_color_background_set(unsigned long value)
6160 {
6161 int _locked_by_me = FALSE, index = _find_thread_index(dw_thread_id());
6162 GdkColor color = _internal_color(value);
6163
6164 DW_MUTEX_LOCK;
6165 if(value == DW_CLR_DEFAULT)
6166 _transparent[index] = 1;
6167 else
6168 _transparent[index] = 0;
6169
6170 _background[index] = color;
6171 DW_MUTEX_UNLOCK;
6172 }
6173
6174 /* Internal function to handle the color OK press */
6175 static gint _gtk_color_ok(GtkWidget *widget, DWDialog *dwwait)
6176 {
6177 GdkColor color;
6178 unsigned long dw_color;
6179 GtkColorSelection *colorsel;
6180
6181 if(!dwwait)
6182 return FALSE;
6183
6184 colorsel = (GtkColorSelection *)gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dwwait->data));
6185 gtk_color_selection_get_current_color(colorsel, &color);
6186 gtk_widget_destroy(GTK_WIDGET(dwwait->data));
6187 _dw_color_active = 0;
6188 dw_color = DW_RGB( (color.red & 0xFF), (color.green & 0xFF), (color.blue & 0xFF));
6189 dw_dialog_dismiss(dwwait, (void *)dw_color);
6190 return FALSE;
6191 }
6192
6193 /* Internal function to handle the color Cancel press */
6194 static gint _gtk_color_cancel(GtkWidget *widget, DWDialog *dwwait)
6195 {
6196 if(!dwwait)
6197 return FALSE;
6198
6199 gtk_widget_destroy(GTK_WIDGET(dwwait->data));
6200 _dw_color_active = 0;
6201 dw_dialog_dismiss(dwwait, (void *)-1);
6202 return FALSE;
6203 }
6204
6205 /* Allows the user to choose a color using the system's color chooser dialog.
6206 * Parameters:
6207 * value: current color
6208 * Returns:
6209 * The selected color or the current color if cancelled.
6210 */
6211 unsigned long API dw_color_choose(unsigned long value)
6212 {
6213 GtkWidget *colorw;
6214 int _locked_by_me = FALSE;
6215 DWDialog *dwwait;
6216 GtkColorSelection *colorsel;
6217 GdkColor color = _internal_color(value);
6218 GObject *part;
6219 unsigned long dw_color;
6220
6221 DW_MUTEX_LOCK;
6222
6223 /* The DW mutex should be sufficient for
6224 * insuring no thread changes this unknowingly.
6225 */
6226 if(_dw_color_active)
6227 {
6228 DW_MUTEX_UNLOCK;
6229 return value;
6230 }
6231
6232 _dw_color_active = 1;
6233
6234 colorw = gtk_color_selection_dialog_new("Select Color");
6235
6236 dwwait = dw_dialog_new((void *)colorw);
6237
6238 colorsel = (GtkColorSelection *)gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(colorw));
6239 #if 0 /* TODO */
6240 part = gtk_buildable_get_internal_child(GTK_BUILDABLE(colorsel,
6241 g_signal_connect(G_OBJECT(colorsel->ok_button), "clicked", G_CALLBACK(_gtk_color_ok), dwwait);
6242 g_signal_connect(G_OBJECT(colorsel->cancel_button), "clicked", G_CALLBACK(_gtk_color_cancel), dwwait);
6243 #endif
6244
6245 gtk_color_selection_set_previous_color(colorsel,&color);
6246 gtk_color_selection_set_current_color(colorsel,&color);
6247 gtk_color_selection_set_has_palette(colorsel,TRUE);
6248
6249 gtk_widget_show(colorw);
6250
6251 dw_color = (unsigned long)dw_dialog_wait(dwwait);
6252 if ((unsigned long)dw_color == -1)
6253 dw_color = value;
6254 DW_MUTEX_UNLOCK;
6255 return (unsigned long)dw_color;
6256 /*
6257 dw_messagebox("Not implemented", DW_MB_OK|DW_MB_INFORMATION, "This feature not yet supported.");
6258 return value;
6259 */
6260 }
6261
6262 /* Draw a point on a window (preferably a render window).
6263 * Parameters:
6264 * handle: Handle to the window.
6265 * pixmap: Handle to the pixmap. (choose only one of these)
6266 * x: X coordinate.
6267 * y: Y coordinate.
6268 */
6269 void dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y)
6270 {
6271 int _locked_by_me = FALSE;
6272 cairo_t *cr = NULL;
6273
6274 DW_MUTEX_LOCK;
6275 if(handle)
6276 cr = gdk_cairo_create(gtk_widget_get_window(handle));
6277 #if 0 /* TODO */
6278 else if(pixmap)
6279 gc = _set_colors(pixmap->pixbuf);
6280 #endif
6281 if(cr)
6282 {
6283 int index = _find_thread_index(dw_thread_id());
6284
6285 cairo_set_source_rgb(cr, _foreground[index].red, _foreground[index].green, _foreground[index].blue);
6286 cairo_set_line_width(cr, 1);
6287 cairo_move_to(cr, x, y);
6288 cairo_stroke(cr);
6289 cairo_destroy(cr);
6290 }
6291 DW_MUTEX_UNLOCK;
6292 }
6293
6294 /* Draw a line on a window (preferably a render window).
6295 * Parameters:
6296 * handle: Handle to the window.
6297 * pixmap: Handle to the pixmap. (choose only one of these)
6298 * x1: First X coordinate.
6299 * y1: First Y coordinate.
6300 * x2: Second X coordinate.
6301 * y2: Second Y coordinate.
6302 */
6303 void dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2)
6304 {
6305 int _locked_by_me = FALSE;
6306 cairo_t *cr = NULL;
6307
6308 DW_MUTEX_LOCK;
6309 if(handle)
6310 cr = gdk_cairo_create(gtk_widget_get_window(handle));
6311 #if 0 /* TODO */
6312 else if(pixmap)
6313 gc = _set_colors(pixmap->pixbuf);
6314 #endif
6315 if(cr)
6316 {
6317 int index = _find_thread_index(dw_thread_id());
6318
6319 cairo_set_source_rgb(cr, _foreground[index].red, _foreground[index].green, _foreground[index].blue);
6320 cairo_set_line_width(cr, 1);
6321 cairo_move_to(cr, x1, y1);
6322 cairo_line_to(cr, x2, y2);
6323 cairo_stroke(cr);
6324 cairo_destroy(cr);
6325 }
6326 DW_MUTEX_UNLOCK;
6327 }
6328
6329 /* Draw a closed polygon on a window (preferably a render window).
6330 * Parameters:
6331 * handle: Handle to the window.
6332 * pixmap: Handle to the pixmap. (choose only one of these)
6333 * fill: if true filled
6334 * number of points
6335 * x[]: X coordinates.
6336 * y[]: Y coordinates.
6337 */
6338 void dw_draw_polygon(HWND handle, HPIXMAP pixmap, int fill, int npoints, int *x, int *y)
6339 {
6340 int _locked_by_me = FALSE;
6341 cairo_t *cr = NULL;
6342 int z;
6343
6344 DW_MUTEX_LOCK;
6345 if(handle)
6346 cr = gdk_cairo_create(gtk_widget_get_window(handle));
6347 #if 0 /* TODO */
6348 else if(pixmap)
6349 gc = _set_colors(pixmap->pixbuf);
6350 #endif
6351 if(cr)
6352 {
6353 int index = _find_thread_index(dw_thread_id());
6354
6355 cairo_set_source_rgb(cr, _foreground[index].red, _foreground[index].green, _foreground[index].blue);
6356 cairo_set_line_width(cr, 1);
6357 cairo_move_to(cr, x[0], y[0]);
6358 for(z=1;z<npoints;z++)
6359 {
6360 cairo_line_to(cr, x[z], y[z]);
6361 }
6362 if(fill)
6363 cairo_fill(cr);
6364 cairo_stroke(cr);
6365 cairo_destroy(cr);
6366 }
6367 DW_MUTEX_UNLOCK;
6368 }
6369
6370 /* Draw a rectangle on a window (preferably a render window).
6371 * Parameters:
6372 * handle: Handle to the window.
6373 * pixmap: Handle to the pixmap. (choose only one of these)
6374 * fill: if true filled
6375 * x: X coordinate.
6376 * y: Y coordinate.
6377 * width: Width of rectangle.
6378 * height: Height of rectangle.
6379 */
6380 void dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height)
6381 {
6382 int _locked_by_me = FALSE;
6383 cairo_t *cr = NULL;
6384
6385 DW_MUTEX_LOCK;
6386 if(handle)
6387 cr = gdk_cairo_create(gtk_widget_get_window(handle));
6388 #if 0 /* TODO */
6389 else if(pixmap)
6390 gc = _set_colors(pixmap->pixbuf);
6391 #endif
6392 if(cr)
6393 {
6394 int index = _find_thread_index(dw_thread_id());
6395
6396 cairo_set_source_rgb(cr, _foreground[index].red, _foreground[index].green, _foreground[index].blue);
6397 cairo_set_line_width(cr, 1);
6398 cairo_move_to(cr, x, y);
6399 cairo_line_to(cr, x, y + height);
6400 cairo_line_to(cr, x + width, y + height);
6401 cairo_line_to(cr, x + width, y);
6402 if(fill)
6403 cairo_fill(cr);
6404 cairo_stroke(cr);
6405 cairo_destroy(cr);
6406 }
6407 DW_MUTEX_UNLOCK;
6408 }
6409
6410 /* Draw text on a window (preferably a render window).
6411 * Parameters:
6412 * handle: Handle to the window.
6413 * pixmap: Handle to the pixmap. (choose only one of these)
6414 * x: X coordinate.
6415 * y: Y coordinate.
6416 * text: Text to be displayed.
6417 */
6418 void dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text)
6419 {
6420 int _locked_by_me = FALSE;
6421 cairo_t *cr = NULL;
6422 PangoFontDescription *font;
6423 char *fontname = "fixed";
6424
6425 if(!text)
6426 return;
6427
6428 DW_MUTEX_LOCK;
6429 if(handle)
6430 {
6431 cr = gdk_cairo_create(gtk_widget_get_window(handle));
6432 fontname = (char *)g_object_get_data(G_OBJECT(handle), "_dw_fontname");
6433 }
6434 #if 0 /* TODO */
6435 else if(pixmap)
6436 {
6437 fontname = (char *)g_object_get_data(G_OBJECT(pixmap->handle), "_dw_fontname");
6438 gc = _set_colors(pixmap->pixbuf);
6439 }
6440 #endif
6441 if(cr)
6442 {
6443 font = pango_font_description_from_string(fontname);
6444 if(font)
6445 {
6446 PangoContext *context = pango_cairo_create_context(cr);
6447
6448 if(context)
6449 {
6450 PangoLayout *layout = pango_layout_new(context);
6451
6452 if(layout)
6453 {
6454 int index = _find_thread_index(dw_thread_id());
6455
6456 pango_layout_set_font_description(layout, font);
6457 pango_layout_set_text(layout, text, strlen(text));
6458
6459 cairo_set_source_rgb(cr, _foreground[index].red, _foreground[index].green, _foreground[index].blue);
6460 cairo_move_to(cr, x, y);
6461 pango_cairo_show_layout (cr, layout);
6462
6463 g_object_unref(layout);
6464 }
6465 g_object_unref(context);
6466 }
6467 pango_font_description_free(font);
6468 }
6469 cairo_destroy(cr);
6470 }
6471 DW_MUTEX_UNLOCK;
6472 }
6473
6474 /* Query the width and height of a text string.
6475 * Parameters:
6476 * handle: Handle to the window.
6477 * pixmap: Handle to the pixmap. (choose only one of these)
6478 * text: Text to be queried.
6479 * width: Pointer to a variable to be filled in with the width.
6480 * height Pointer to a variable to be filled in with the height.
6481 */
6482 void dw_font_text_extents_get(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height)
6483 {
6484 int _locked_by_me = FALSE;
6485 PangoFontDescription *font;
6486 char *fontname = NULL;
6487 int free_fontname = 0;
6488
6489 if(!text)
6490 return;
6491
6492 DW_MUTEX_LOCK;
6493 if(handle)
6494 {
6495 fontname = (char *)g_object_get_data(G_OBJECT(handle), "_dw_fontname");
6496 if ( fontname == NULL )
6497 {
6498 fontname = dw_window_get_font(handle);
6499 free_fontname = 1;
6500 }
6501 }
6502 else if(pixmap)
6503 fontname = (char *)g_object_get_data(G_OBJECT(pixmap->handle), "_dw_fontname");
6504
6505 font = pango_font_description_from_string(fontname ? fontname : "monospace 10");
6506 if(font)
6507 {
6508 PangoContext *context = gdk_pango_context_get();
6509
6510 if(context)
6511 {
6512 PangoLayout *layout = pango_layout_new(context);
6513
6514 if(layout)
6515 {
6516 PangoRectangle rect;
6517
6518 pango_layout_set_font_description(layout, font);
6519 pango_layout_set_text(layout, text, -1);
6520 pango_layout_get_pixel_extents(layout, NULL, &rect);
6521
6522 if(width)
6523 *width = rect.width;
6524 if(height)
6525 *height = rect.height;
6526
6527 g_object_unref(layout);
6528 }
6529 g_object_unref(context);
6530 }
6531 pango_font_description_free(font);
6532 }
6533 if ( free_fontname )
6534 free( fontname );
6535 DW_MUTEX_UNLOCK;
6536 }
6537
6538 /*
6539 * Creates a pixmap with given parameters.
6540 * Parameters:
6541 * handle: Window handle the pixmap is associated with.
6542 * or zero to enable this pixmap to be written
6543 * off the screen to reduce flicker
6544 * width: Width of the pixmap in pixels.
6545 * height: Height of the pixmap in pixels.
6546 * depth: Color depth of the pixmap.
6547 * Returns:
6548 * A handle to a pixmap or NULL on failure.
6549 */
6550 HPIXMAP dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth)
6551 {
6552 int _locked_by_me = FALSE;
6553 HPIXMAP pixmap;
6554
6555 if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
6556 return NULL;
6557
6558 if (!depth)
6559 depth = -1;
6560
6561 pixmap->width = width; pixmap->height = height;
6562
6563
6564 DW_MUTEX_LOCK;
6565 pixmap->handle = handle;
6566 /* Depth needs to be divided by 3... but for the RGB colorspace...
6567 * only 8 bits per sample is allowed, so to avoid issues just pass 8 for now.
6568 */
6569 if ( handle )
6570 pixmap->pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, width, height );
6571 else
6572 pixmap->pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, width, height );
6573 DW_MUTEX_UNLOCK;
6574 return pixmap;
6575 }
6576
6577 /*
6578 * Creates a pixmap from a file.
6579 * Parameters:
6580 * handle: Window handle the pixmap is associated with.
6581 * filename: Name of the file, omit extention to have
6582 * DW pick the appropriate file extension.
6583 * (BMP on OS/2 or Windows, XPM on Unix)
6584 * Returns:
6585 * A handle to a pixmap or NULL on failure.
6586 */
6587 HPIXMAP dw_pixmap_new_from_file(HWND handle, char *filename)
6588 {
6589 int _locked_by_me = FALSE;
6590 HPIXMAP pixmap;
6591 char *file = alloca(strlen(filename) + 5);
6592 int found_ext = 0;
6593 int i;
6594
6595 if (!file || !(pixmap = calloc(1,sizeof(struct _hpixmap))))
6596 return NULL;
6597
6598 strcpy(file, filename);
6599
6600 /* check if we can read from this file (it exists and read permission) */
6601 if(access(file, 04) != 0)
6602 {
6603 /* Try with various extentions */
6604 for ( i = 0; i < NUM_EXTS; i++ )
6605 {
6606 strcpy( file, filename );
6607 strcat( file, image_exts[i] );
6608 if ( access( file, 04 ) == 0 )
6609 {
6610 found_ext = 1;
6611 break;
6612 }
6613 }
6614 if ( found_ext == 0 )
6615 {
6616 free(pixmap);
6617 return NULL;
6618 }
6619 }
6620
6621 DW_MUTEX_LOCK;
6622 pixmap->pixbuf = gdk_pixbuf_new_from_file(file, NULL);
6623 pixmap->width = gdk_pixbuf_get_width(pixmap->pixbuf);
6624 pixmap->height = gdk_pixbuf_get_height(pixmap->pixbuf);
6625 pixmap->handle = handle;
6626 DW_MUTEX_UNLOCK;
6627 return pixmap;
6628 }
6629
6630 /*
6631 * Creates a pixmap from data
6632 * Parameters:
6633 * handle: Window handle the pixmap is associated with.
6634 * data: Source of image data
6635 * DW pick the appropriate file extension.
6636 * (BMP on OS/2 or Windows, XPM on Unix)
6637 * Returns:
6638 * A handle to a pixmap or NULL on failure.
6639 */
6640 HPIXMAP dw_pixmap_new_from_data(HWND handle, char *data, int len)
6641 {
6642 int _locked_by_me = FALSE;
6643 char *file;
6644 FILE *fp;
6645 HPIXMAP pixmap;
6646
6647 if (!data || !(pixmap = calloc(1,sizeof(struct _hpixmap))))
6648 return NULL;
6649
6650 DW_MUTEX_LOCK;
6651 /*
6652 * A real hack; create a temporary file and write the contents
6653 * of the data to the file
6654 */
6655 file = tmpnam( NULL );
6656 fp = fopen( file, "wb" );
6657 if ( fp )
6658 {
6659 fwrite( data, len, 1, fp );
6660 fclose( fp );
6661 }
6662 else
6663 {
6664 DW_MUTEX_UNLOCK;
6665 return 0;
6666 }
6667 pixmap->pixbuf = gdk_pixbuf_new_from_file(file, NULL);
6668 pixmap->width = gdk_pixbuf_get_width(pixmap->pixbuf);
6669 pixmap->height = gdk_pixbuf_get_height(pixmap->pixbuf);
6670 /* remove our temporary file */
6671 unlink (file );
6672 pixmap->handle = handle;
6673 DW_MUTEX_UNLOCK;
6674 return pixmap;
6675 }
6676
6677 /*
6678 * Sets the transparent color for a pixmap
6679 * Parameters:
6680 * pixmap: Handle to a pixmap returned by
6681 * dw_pixmap_new..
6682 * color: transparent color
6683 * Note: This does nothing on GTK+ as transparency
6684 * is handled automatically
6685 */
6686 void dw_pixmap_set_transparent_color(HPIXMAP pixmap, unsigned long color)
6687 {
6688 int _locked_by_me = FALSE;
6689
6690 DW_MUTEX_LOCK;
6691 pixmap = pixmap;
6692 color = color;
6693 DW_MUTEX_UNLOCK;
6694 }
6695
6696 /*
6697 * Creates a pixmap from internal resource graphic specified by id.
6698 * Parameters:
6699 * handle: Window handle the pixmap is associated with.
6700 * id: Resource ID associated with requested pixmap.
6701 * Returns:
6702 * A handle to a pixmap or NULL on failure.
6703 */
6704 HPIXMAP dw_pixmap_grab(HWND handle, ULONG id)
6705 {
6706 HPIXMAP pixmap;
6707 int _locked_by_me = FALSE;
6708
6709 if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
6710 return NULL;
6711
6712
6713 DW_MUTEX_LOCK;
6714 pixmap->pixbuf = gdk_pixbuf_copy(_find_pixbuf(id, &pixmap->width, &pixmap->height));
6715 DW_MUTEX_UNLOCK;
6716 return pixmap;
6717 }
6718
6719 /* Call this after drawing to the screen to make sure
6720 * anything you have drawn is visible.
6721 */
6722 void dw_flush(void)
6723 {
6724 }
6725
6726 /*
6727 * Destroys an allocated pixmap.
6728 * Parameters:
6729 * pixmap: Handle to a pixmap returned by
6730 * dw_pixmap_new..
6731 */
6732 void dw_pixmap_destroy(HPIXMAP pixmap)
6733 {
6734 int _locked_by_me = FALSE;
6735
6736 DW_MUTEX_LOCK;
6737 g_object_unref(G_OBJECT(pixmap->pixbuf));
6738 free(pixmap);
6739 DW_MUTEX_UNLOCK;
6740 }
6741
6742 /*
6743 * Copies from one item to another.
6744 * Parameters:
6745 * dest: Destination window handle.
6746 * destp: Destination pixmap. (choose only one).
6747 * xdest: X coordinate of destination.
6748 * ydest: Y coordinate of destination.
6749 * width: Width of area to copy.
6750 * height: Height of area to copy.
6751 * src: Source window handle.
6752 * srcp: Source pixmap. (choose only one).
6753 * xsrc: X coordinate of source.
6754 * ysrc: Y coordinate of source.
6755 */
6756 void dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc)
6757 {
6758 /* Ok, these #ifdefs are going to get a bit confusing because
6759 * when using gdk-pixbuf, pixmaps are really pixbufs, so we
6760 * have to use the pixbuf functions on them, and thus convoluting
6761 * the code here a bit. -Brian
6762 */
6763 int _locked_by_me = FALSE;
6764 cairo_t *cr = NULL;
6765
6766 if((!dest && (!destp || !destp->pixbuf)) || (!src && (!srcp || !srcp->pixbuf)))
6767 return;
6768
6769 DW_MUTEX_LOCK;
6770 if(dest)
6771 cr = gdk_cairo_create(gtk_widget_get_window(dest));
6772 #if 0 /* TODO */
6773 else if(destp)
6774 gc = gdk_gc_new(destp->pixbuf);
6775 #endif
6776
6777 if(cr)
6778 {
6779 if(src)
6780 gdk_cairo_set_source_window (cr, gtk_widget_get_window(src), xsrc, ysrc);
6781 else if(srcp)
6782 gdk_cairo_set_source_pixbuf (cr, srcp->pixbuf, xsrc, ysrc);
6783
6784 cairo_paint(cr);
6785 cairo_destroy(cr);
6786 }
6787 DW_MUTEX_UNLOCK;
6788 }
6789
6790 /*
6791 * Emits a beep.
6792 * Parameters:
6793 * freq: Frequency.
6794 * dur: Duration.
6795 */
6796 void dw_beep(int freq, int dur)
6797 {
6798 int _locked_by_me = FALSE;
6799
6800 DW_MUTEX_LOCK;
6801 gdk_beep();
6802 DW_MUTEX_UNLOCK;
6803 }
6804
6805 void _my_strlwr(char *buf)
6806 {
6807 int z, len = strlen(buf);
6808
6809 for(z=0;z<len;z++)
6810 {
6811 if(buf[z] >= 'A' && buf[z] <= 'Z')
6812 buf[z] -= 'A' - 'a';
6813 }
6814 }
6815
6816 /* Open a shared library and return a handle.
6817 * Parameters:
6818 * name: Base name of the shared library.
6819 * handle: Pointer to a module handle,
6820 * will be filled in with the handle.
6821 */
6822 int dw_module_load(char *name, HMOD *handle)
6823 {
6824 int len;
6825 char *newname;
6826 char errorbuf[1024];
6827
6828
6829 if(!handle)
6830 return -1;
6831
6832 if((len = strlen(name)) == 0)
6833 return -1;
6834
6835 /* Lenth + "lib" + ".so" + NULL */
6836 newname = malloc(len + 7);
6837
6838 if(!newname)
6839 return -1;
6840
6841 sprintf(newname, "lib%s.so", name);
6842 _my_strlwr(newname);
6843
6844 *handle = dlopen(newname, RTLD_NOW);
6845 if(*handle == NULL)
6846 {
6847 strncpy(errorbuf, dlerror(), 1024);
6848 printf("%s\n", errorbuf);
6849 sprintf(newname, "lib%s.so", name);
6850 *handle = dlopen(newname, RTLD_NOW);
6851 }
6852
6853 free(newname);
6854
6855 return (NULL == *handle) ? -1 : 0;
6856 }
6857
6858 /* Queries the address of a symbol within open handle.
6859 * Parameters:
6860 * handle: Module handle returned by dw_module_load()
6861 * name: Name of the symbol you want the address of.
6862 * func: A pointer to a function pointer, to obtain
6863 * the address.
6864 */
6865 int dw_module_symbol(HMOD handle, char *name, void**func)
6866 {
6867 if(!func || !name)
6868 return -1;
6869
6870 if(strlen(name) == 0)
6871 return -1;
6872
6873 *func = (void*)dlsym(handle, name);
6874 return (NULL == *func);
6875 }
6876
6877 /* Frees the shared library previously opened.
6878 * Parameters:
6879 * handle: Module handle returned by dw_module_load()
6880 */
6881 int dw_module_close(HMOD handle)
6882 {
6883 if(handle)
6884 return dlclose(handle);
6885 return 0;
6886 }
6887
6888 /*
6889 * Returns the handle to an unnamed mutex semaphore.
6890 */
6891 HMTX dw_mutex_new(void)
6892 {
6893 HMTX mutex = malloc(sizeof(pthread_mutex_t));
6894
6895 pthread_mutex_init(mutex, NULL);
6896 return mutex;
6897 }
6898
6899 /*
6900 * Closes a semaphore created by dw_mutex_new().
6901 * Parameters:
6902 * mutex: The handle to the mutex returned by dw_mutex_new().
6903 */
6904 void dw_mutex_close(HMTX mutex)
6905 {
6906 if(mutex)
6907 {
6908 pthread_mutex_destroy(mutex);
6909 free(mutex);
6910 }
6911 }
6912
6913 /*
6914 * Tries to gain access to the semaphore, if it can't it blocks.
6915 * Parameters:
6916 * mutex: The handle to the mutex returned by dw_mutex_new().
6917 */
6918 void dw_mutex_lock(HMTX mutex)
6919 {
6920 /* If we are being called from an event handler we must release
6921 * the GTK mutex so we don't deadlock.
6922 */
6923 if(pthread_self() == _dw_thread)
6924 gdk_threads_leave();
6925
6926 pthread_mutex_lock(mutex);
6927
6928 /* And of course relock it when we have acquired the mutext */
6929 if(pthread_self() == _dw_thread)
6930 gdk_threads_enter();
6931 }
6932
6933 /*
6934 * Reliquishes the access to the semaphore.
6935 * Parameters:
6936 * mutex: The handle to the mutex returned by dw_mutex_new().
6937 */
6938 void dw_mutex_unlock(HMTX mutex)
6939 {
6940 pthread_mutex_unlock(mutex);
6941 }
6942
6943 /*
6944 * Returns the handle to an unnamed event semaphore.
6945 */
6946 HEV dw_event_new(void)
6947 {
6948 HEV eve = (HEV)malloc(sizeof(struct _dw_unix_event));
6949
6950 if(!eve)
6951 return NULL;
6952
6953 /* We need to be careful here, mutexes on Linux are
6954 * FAST by default but are error checking on other
6955 * systems such as FreeBSD and OS/2, perhaps others.
6956 */
6957 pthread_mutex_init (&(eve->mutex), NULL);
6958 pthread_mutex_lock (&(eve->mutex));
6959 pthread_cond_init (&(eve->event), NULL);
6960
6961 pthread_mutex_unlock (&(eve->mutex));
6962 eve->alive = 1;
6963 eve->posted = 0;
6964
6965 return eve;
6966 }
6967
6968 /*
6969 * Resets a semaphore created by dw_event_new().
6970 * Parameters:
6971 * eve: The handle to the event returned by dw_event_new().
6972 */
6973 int dw_event_reset (HEV eve)
6974 {
6975 if(!eve)
6976 return FALSE;
6977
6978 pthread_mutex_lock (&(eve->mutex));
6979 pthread_cond_broadcast (&(eve->event));
6980 pthread_cond_init (&(eve->event), NULL);
6981 eve->posted = 0;
6982 pthread_mutex_unlock (&(eve->mutex));
6983 return 0;
6984 }
6985
6986 /*
6987 * Posts a semaphore created by dw_event_new(). Causing all threads
6988 * waiting on this event in dw_event_wait to continue.
6989 * Parameters:
6990 * eve: The handle to the event returned by dw_event_new().
6991 */
6992 int dw_event_post (HEV eve)
6993 {
6994 if(!eve)
6995 return FALSE;
6996
6997 pthread_mutex_lock (&(eve->mutex));
6998 pthread_cond_broadcast (&(eve->event));
6999 eve->posted = 1;
7000 pthread_mutex_unlock (&(eve->mutex));
7001 return 0;
7002 }
7003
7004 /*
7005 * Waits on a semaphore created by dw_event_new(), until the
7006 * event gets posted or until the timeout expires.
7007 * Parameters:
7008 * eve: The handle to the event returned by dw_event_new().
7009 */
7010 int dw_event_wait(HEV eve, unsigned long timeout)
7011 {
7012 int rc;
7013 struct timeval now;
7014 struct timespec timeo;
7015
7016 if(!eve)
7017 return FALSE;
7018
7019 if(eve->posted)
7020 return 0;
7021
7022 pthread_mutex_lock (&(eve->mutex));
7023 gettimeofday(&now, 0);
7024 timeo.tv_sec = now.tv_sec + (timeout / 1000);
7025 timeo.tv_nsec = now.tv_usec * 1000;
7026 rc = pthread_cond_timedwait (&(eve->event), &(eve->mutex), &timeo);
7027 pthread_mutex_unlock (&(eve->mutex));
7028 if(!rc)
7029 return 1;
7030 if(rc == ETIMEDOUT)
7031 return -1;
7032 return 0;
7033 }
7034
7035 /*
7036 * Closes a semaphore created by dw_event_new().
7037 * Parameters:
7038 * eve: The handle to the event returned by dw_event_new().
7039 */
7040 int dw_event_close(HEV *eve)
7041 {
7042 if(!eve || !(*eve))
7043 return FALSE;
7044
7045 pthread_mutex_lock (&((*eve)->mutex));
7046 pthread_cond_destroy (&((*eve)->event));
7047 pthread_mutex_unlock (&((*eve)->mutex));
7048 pthread_mutex_destroy (&((*eve)->mutex));
7049 free(*eve);
7050 *eve = NULL;
7051
7052 return TRUE;
7053 }
7054
7055 struct _seminfo {
7056 int fd;
7057 int waiting;
7058 };
7059
7060 static void _handle_sem(int *tmpsock)
7061 {
7062 fd_set rd;
7063 struct _seminfo *array = (struct _seminfo *)malloc(sizeof(struct _seminfo));
7064 int listenfd = tmpsock[0];
7065 int bytesread, connectcount = 1, maxfd, z, posted = 0;
7066 char command;
7067 sigset_t mask;
7068
7069 sigfillset(&mask); /* Mask all allowed signals */
7070 pthread_sigmask(SIG_BLOCK, &mask, NULL);
7071
7072 /* problems */
7073 if(tmpsock[1] == -1)
7074 {
7075 free(array);
7076 return;
7077 }
7078
7079 array[0].fd = tmpsock[1];
7080 array[0].waiting = 0;
7081
7082 /* Free the memory allocated in dw_named_event_new. */
7083 free(tmpsock);
7084
7085 while(1)
7086 {
7087 FD_ZERO(&rd);
7088 FD_SET(listenfd, &rd);
7089
7090 maxfd = listenfd;
7091
7092 /* Added any connections to the named event semaphore */
7093 for(z=0;z<connectcount;z++)
7094 {
7095 if(array[z].fd > maxfd)
7096 maxfd = array[z].fd;
7097
7098 FD_SET(array[z].fd, &rd);
7099 }
7100
7101 if(select(maxfd+1, &rd, NULL, NULL, NULL) == -1)
7102 return;
7103
7104 if(FD_ISSET(listenfd, &rd))
7105 {
7106 struct _seminfo *newarray;
7107 int newfd = accept(listenfd, 0, 0);
7108
7109 if(newfd > -1)
7110 {
7111 /* Add new connections to the set */
7112 newarray = (struct _seminfo *)malloc(sizeof(struct _seminfo)*(connectcount+1));
7113 memcpy(newarray, array, sizeof(struct _seminfo)*(connectcount));
7114
7115 newarray[connectcount].fd = newfd;
7116 newarray[connectcount].waiting = 0;
7117
7118 connectcount++;
7119
7120 /* Replace old array with new one */
7121 free(array);
7122 array = newarray;
7123 }
7124 }
7125
7126 /* Handle any events posted to the semaphore */
7127 for(z=0;z<connectcount;z++)
7128 {
7129 if(FD_ISSET(array[z].fd, &rd))
7130 {
7131 if((bytesread = read(array[z].fd, &command, 1)) < 1)
7132 {
7133 struct _seminfo *newarray;
7134
7135 /* Remove this connection from the set */
7136 newarray = (struct _seminfo *)malloc(sizeof(struct _seminfo)*(connectcount-1));
7137 if(!z)
7138 memcpy(newarray, &array[1], sizeof(struct _seminfo)*(connectcount-1));
7139 else
7140 {
7141 memcpy(newarray, array, sizeof(struct _seminfo)*z);
7142 if(z!=(connectcount-1))
7143 memcpy(&newarray[z], &array[z+1], sizeof(struct _seminfo)*(z-connectcount-1));
7144 }
7145 connectcount--;
7146
7147 /* Replace old array with new one */
7148 free(array);
7149 array = newarray;
7150 }
7151 else if(bytesread == 1)
7152 {
7153 switch(command)
7154 {
7155 case 0:
7156 {
7157 /* Reset */
7158 posted = 0;
7159 }
7160 break;
7161 case 1:
7162 /* Post */
7163 {
7164 int s;
7165 char tmp = (char)0;
7166
7167 posted = 1;
7168
7169 for(s=0;s<connectcount;s++)
7170 {
7171 /* The semaphore has been posted so
7172 * we tell all the waiting threads to
7173 * continue.
7174 */
7175 if(array[s].waiting)
7176 write(array[s].fd, &tmp, 1);
7177 }
7178 }
7179 break;
7180 case 2:
7181 /* Wait */
7182 {
7183 char tmp = (char)0;
7184
7185 array[z].waiting = 1;
7186
7187 /* If we are posted exit immeditately */
7188 if(posted)
7189 write(array[z].fd, &tmp, 1);
7190 }
7191 break;
7192 case 3:
7193 {
7194 /* Done Waiting */
7195 array[z].waiting = 0;
7196 }
7197 break;
7198 }
7199 }
7200 }
7201 }
7202
7203 }
7204
7205 }
7206
7207 /* Using domain sockets on unix for IPC */
7208 /* Create a named event semaphore which can be
7209 * opened from other processes.
7210 * Parameters:
7211 * eve: Pointer to an event handle to receive handle.
7212 * name: Name given to semaphore which can be opened
7213 * by other processes.
7214 */
7215 HEV dw_named_event_new(char *name)
7216 {
7217 struct sockaddr_un un;
7218 int ev, *tmpsock = (int *)malloc(sizeof(int)*2);
7219 DWTID dwthread;
7220
7221 if(!tmpsock)
7222 return NULL;
7223
7224 tmpsock[0] = socket(AF_UNIX, SOCK_STREAM, 0);
7225 ev = socket(AF_UNIX, SOCK_STREAM, 0);
7226 memset(&un, 0, sizeof(un));
7227 un.sun_family=AF_UNIX;
7228 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
7229 strcpy(un.sun_path, "/tmp/.dw/");
7230 strcat(un.sun_path, name);
7231
7232 /* just to be safe, this should be changed
7233 * to support multiple instances.
7234 */
7235 remove(un.sun_path);
7236
7237 bind(tmpsock[0], (struct sockaddr *)&un, sizeof(un));
7238 listen(tmpsock[0], 0);
7239 connect(ev, (struct sockaddr *)&un, sizeof(un));
7240 tmpsock[1] = accept(tmpsock[0], 0, 0);
7241
7242 if(tmpsock[0] < 0 || tmpsock[1] < 0 || ev < 0)
7243 {
7244 if(tmpsock[0] > -1)
7245 close(tmpsock[0]);
7246 if(tmpsock[1] > -1)
7247 close(tmpsock[1]);
7248 if(ev > -1)
7249 close(ev);
7250 free(tmpsock);
7251 return NULL;
7252 }
7253
7254 /* Create a thread to handle this event semaphore */
7255 pthread_create(&dwthread, NULL, (void *)_handle_sem, (void *)tmpsock);
7256 return (HEV)ev;
7257 }
7258
7259 /* Open an already existing named event semaphore.
7260 * Parameters:
7261 * eve: Pointer to an event handle to receive handle.
7262 * name: Name given to semaphore which can be opened
7263 * by other processes.
7264 */
7265 HEV dw_named_event_get(char *name)
7266 {
7267 struct sockaddr_un un;
7268 int ev = socket(AF_UNIX, SOCK_STREAM, 0);
7269 if(ev < 0)
7270 return NULL;
7271
7272 un.sun_family=AF_UNIX;
7273 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
7274 strcpy(un.sun_path, "/tmp/.dw/");
7275 strcat(un.sun_path, name);
7276 connect(ev, (struct sockaddr *)&un, sizeof(un));
7277 return (HEV)ev;
7278 }
7279
7280 /* Resets the event semaphore so threads who call wait
7281 * on this semaphore will block.
7282 * Parameters:
7283 * eve: Handle to the semaphore obtained by
7284 * an open or create call.
7285 */
7286 int dw_named_event_reset(HEV eve)
7287 {
7288 /* signal reset */
7289 char tmp = (char)0;
7290
7291 if((int)eve < 0)
7292 return 0;
7293
7294 if(write((int)eve, &tmp, 1) == 1)
7295 return 0;
7296 return 1;
7297 }
7298
7299 /* Sets the posted state of an event semaphore, any threads
7300 * waiting on the semaphore will no longer block.
7301 * Parameters:
7302 * eve: Handle to the semaphore obtained by
7303 * an open or create call.
7304 */
7305 int dw_named_event_post(HEV eve)
7306 {
7307
7308 /* signal post */
7309 char tmp = (char)1;
7310
7311 if((int)eve < 0)
7312 return 0;
7313
7314 if(write((int)eve, &tmp, 1) == 1)
7315 return 0;
7316 return 1;
7317 }
7318
7319 /* Waits on the specified semaphore until it becomes
7320 * posted, or returns immediately if it already is posted.
7321 * Parameters:
7322 * eve: Handle to the semaphore obtained by
7323 * an open or create call.
7324 * timeout: Number of milliseconds before timing out
7325 * or -1 if indefinite.
7326 */
7327 int dw_named_event_wait(HEV eve, unsigned long timeout)
7328 {
7329 fd_set rd;
7330 struct timeval tv, *useme;
7331 int retval = 0;
7332 char tmp;
7333
7334 if((int)eve < 0)
7335 return DW_ERROR_NON_INIT;
7336
7337 /* Set the timout or infinite */
7338 if(timeout == -1)
7339 useme = NULL;
7340 else
7341 {
7342 tv.tv_sec = timeout / 1000;
7343 tv.tv_usec = timeout % 1000;
7344
7345 useme = &tv;
7346 }
7347
7348 FD_ZERO(&rd);
7349 FD_SET((int)eve, &rd);
7350
7351 /* Signal wait */
7352 tmp = (char)2;
7353 write((int)eve, &tmp, 1);
7354
7355 retval = select((int)eve+1, &rd, NULL, NULL, useme);
7356
7357 /* Signal done waiting. */
7358 tmp = (char)3;
7359 write((int)eve, &tmp, 1);
7360
7361 if(retval == 0)
7362 return DW_ERROR_TIMEOUT;
7363 else if(retval == -1)
7364 return DW_ERROR_INTERRUPT;
7365
7366 /* Clear the entry from the pipe so
7367 * we don't loop endlessly. :)
7368 */
7369 read((int)eve, &tmp, 1);
7370 return 0;
7371 }
7372
7373 /* Release this semaphore, if there are no more open
7374 * handles on this semaphore the semaphore will be destroyed.
7375 * Parameters:
7376 * eve: Handle to the semaphore obtained by
7377 * an open or create call.
7378 */
7379 int dw_named_event_close(HEV eve)
7380 {
7381 /* Finally close the domain socket,
7382 * cleanup will continue in _handle_sem.
7383 */
7384 close((int)eve);
7385 return 0;
7386 }
7387
7388 /*
7389 * Setup thread independent color sets.
7390 */
7391 void _dwthreadstart(void *data)
7392 {
7393 void (*threadfunc)(void *) = NULL;
7394 void **tmp = (void **)data;
7395
7396 threadfunc = (void (*)(void *))tmp[0];
7397
7398 _dw_thread_add(dw_thread_id());
7399 threadfunc(tmp[1]);
7400 _dw_thread_remove(dw_thread_id());
7401 free(tmp);
7402 }
7403
7404 /*
7405 * Allocates a shared memory region with a name.
7406 * Parameters:
7407 * handle: A pointer to receive a SHM identifier.
7408 * dest: A pointer to a pointer to receive the memory address.
7409 * size: Size in bytes of the shared memory region to allocate.
7410 * name: A string pointer to a unique memory name.
7411 */
7412 HSHM dw_named_memory_new(void **dest, int size, char *name)
7413 {
7414 char namebuf[1024];
7415 struct _dw_unix_shm *handle = malloc(sizeof(struct _dw_unix_shm));
7416
7417 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
7418 sprintf(namebuf, "/tmp/.dw/%s", name);
7419
7420 if((handle->fd = open(namebuf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0)
7421 {
7422 free(handle);
7423 return NULL;
7424 }
7425
7426 ftruncate(handle->fd, size);
7427
7428 /* attach the shared memory segment to our process's address space. */
7429 *dest = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0);
7430
7431 if(*dest == MAP_FAILED)
7432 {
7433 close(handle->fd);
7434 *dest = NULL;
7435 free(handle);
7436 return NULL;
7437 }
7438
7439 handle->size = size;
7440 handle->sid = getsid(0);
7441 handle->path = strdup(namebuf);
7442
7443 return handle;
7444 }
7445
7446 /*
7447 * Aquires shared memory region with a name.
7448 * Parameters:
7449 * dest: A pointer to a pointer to receive the memory address.
7450 * size: Size in bytes of the shared memory region to requested.
7451 * name: A string pointer to a unique memory name.
7452 */
7453 HSHM dw_named_memory_get(void **dest, int size, char *name)
7454 {
7455 char namebuf[1024];
7456 struct _dw_unix_shm *handle = malloc(sizeof(struct _dw_unix_shm));
7457
7458 mkdir("/tmp/.dw", S_IWGRP|S_IWOTH);
7459 sprintf(namebuf, "/tmp/.dw/%s", name);
7460
7461 if((handle->fd = open(namebuf, O_RDWR)) < 0)
7462 {
7463 free(handle);
7464 return NULL;
7465 }
7466
7467 /* attach the shared memory segment to our process's address space. */
7468 *dest = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0);
7469
7470 if(*dest == MAP_FAILED)
7471 {
7472 close(handle->fd);
7473 *dest = NULL;
7474 free(handle);
7475 return NULL;
7476 }
7477
7478 handle->size = size;
7479 handle->sid = -1;
7480 handle->path = NULL;
7481
7482 return handle;
7483 }
7484
7485 /*
7486 * Frees a shared memory region previously allocated.
7487 * Parameters:
7488 * handle: Handle obtained from DB_named_memory_allocate.
7489 * ptr: The memory address aquired with DB_named_memory_allocate.
7490 */
7491 int dw_named_memory_free(HSHM handle, void *ptr)
7492 {
7493 struct _dw_unix_shm *h = handle;
7494 int rc = munmap(ptr, h->size);
7495
7496 close(h->fd);
7497 if(h->path)
7498 {
7499 /* Only remove the actual file if we are the
7500 * creator of the file.
7501 */
7502 if(h->sid != -1 && h->sid == getsid(0))
7503 remove(h->path);
7504 free(h->path);
7505 }
7506 return rc;
7507 }
7508 /*
7509 * Creates a new thread with a starting point of func.
7510 * Parameters:
7511 * func: Function which will be run in the new thread.
7512 * data: Parameter(s) passed to the function.
7513 * stack: Stack size of new thread (OS/2 and Windows only).
7514 */
7515 DWTID dw_thread_new(void *func, void *data, int stack)
7516 {
7517 DWTID gtkthread;
7518 void **tmp = malloc(sizeof(void *) * 2);
7519 int rc;
7520
7521 tmp[0] = func;
7522 tmp[1] = data;
7523
7524 rc = pthread_create(&gtkthread, NULL, (void *)_dwthreadstart, (void *)tmp);
7525 if ( rc == 0 )
7526 return gtkthread;
7527 else
7528 return rc;
7529 }
7530
7531 /*
7532 * Ends execution of current thread immediately.
7533 */
7534 void dw_thread_end(void)
7535 {
7536 pthread_exit(NULL);
7537 }
7538
7539 /*
7540 * Returns the current thread's ID.
7541 */
7542 DWTID dw_thread_id(void)
7543 {
7544 return (DWTID)pthread_self();
7545 }
7546
7547 /*
7548 * Cleanly terminates a DW session, should be signal handler safe.
7549 * Parameters:
7550 * exitcode: Exit code reported to the operating system.
7551 */
7552 void dw_exit(int exitcode)
7553 {
7554 if ( dbgfp != NULL )
7555 {
7556 fclose( dbgfp );
7557 }
7558 exit(exitcode);
7559 }
7560
7561 #define DW_EXPAND (GTK_EXPAND | GTK_SHRINK | GTK_FILL)
7562
7563 /*
7564 * Pack windows (widgets) into a box from the end (or bottom).
7565 * Parameters:
7566 * box: Window handle of the box to be packed into.
7567 * item: Window handle of the item to be back.
7568 * width: Width in pixels of the item or -1 to be self determined.
7569 * height: Height in pixels of the item or -1 to be self determined.
7570 * hsize: TRUE if the window (widget) should expand horizontally to fill space given.
7571 * vsize: TRUE if the window (widget) should expand vertically to fill space given.
7572 * pad: Number of pixels of padding around the item.
7573 */
7574 void dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
7575 {
7576 int warn = FALSE, _locked_by_me = FALSE;
7577 GtkWidget *tmp, *tmpitem;
7578
7579 if(!box)
7580 return;
7581
7582 /*
7583 * If you try and pack an item into itself VERY bad things can happen; like at least an
7584 * infinite loop on GTK! Lets be safe!
7585 */
7586 if(box == item)
7587 {
7588 dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!");
7589 return;
7590 }
7591
7592 DW_MUTEX_LOCK;
7593
7594 if((tmp = g_object_get_data(G_OBJECT(box), "_dw_boxhandle")))
7595 box = tmp;
7596
7597 if(!item)
7598 {
7599 item = gtk_label_new("");
7600 gtk_widget_show_all(item);
7601 }
7602
7603 tmpitem = (GtkWidget *)g_object_get_data(G_OBJECT(item), "_dw_boxhandle");
7604
7605 if(GTK_IS_TABLE(box))
7606 {
7607 int boxcount = (int)g_object_get_data(G_OBJECT(box), "_dw_boxcount");
7608 int boxtype = (int)g_object_get_data(G_OBJECT(box), "_dw_boxtype");
7609
7610 /* If the item being packed is a box, then we use it's padding
7611 * instead of the padding specified on the pack line, this is
7612 * due to a bug in the OS/2 and Win32 renderer and a limitation
7613 * of the GtkTable class.
7614 */
7615 if(GTK_IS_TABLE(item) || (tmpitem && GTK_IS_TABLE(tmpitem)))
7616 {
7617 GtkWidget *eventbox = (GtkWidget *)g_object_get_data(G_OBJECT(item), "_dw_eventbox");
7618
7619 /* NOTE: I left in the ability to pack boxes with a size,
7620 * this eliminates that by forcing the size to 0.
7621 */
7622 height = width = 0;
7623
7624 if(eventbox)
7625 {
7626 int boxpad = (int)g_object_get_data(G_OBJECT(item), "_dw_boxpad");
7627 gtk_container_add(GTK_CONTAINER(eventbox), item);
7628 gtk_container_set_border_width(GTK_CONTAINER(eventbox), boxpad);
7629 item = eventbox;
7630 }
7631 }
7632 else
7633 {
7634 /* Only show warning if item is not a box */
7635 warn = TRUE;
7636 }
7637
7638 if(boxtype == DW_VERT)
7639 gtk_table_resize(GTK_TABLE(box), boxcount + 1, 1);
7640 else
7641 gtk_table_resize(GTK_TABLE(box), 1, boxcount + 1);
7642
7643 gtk_table_attach(GTK_TABLE(box), item, 0, 1, 0, 1, hsize ? DW_EXPAND : 0, vsize ? DW_EXPAND : 0, pad, pad);
7644 g_object_set_data(G_OBJECT(box), "_dw_boxcount", GINT_TO_POINTER(boxcount + 1));
7645 gtk_widget_set_size_request(item, width, height);
7646 if(GTK_IS_RADIO_BUTTON(item))
7647 {
7648 GSList *group;
7649 GtkWidget *groupstart = (GtkWidget *)g_object_get_data(G_OBJECT(box), "_dw_group");
7650
7651 if(groupstart)
7652 {
7653 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(groupstart));
7654 gtk_radio_button_set_group(GTK_RADIO_BUTTON(item), group);
7655 }
7656 else
7657 g_object_set_data(G_OBJECT(box), "_dw_group", (gpointer)item);
7658 }
7659 }
7660 else
7661 {
7662 GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
7663
7664 if(GTK_IS_TABLE(item) || (tmpitem && GTK_IS_TABLE(tmpitem)))
7665 {
7666 GtkWidget *eventbox = (GtkWidget *)g_object_get_data(G_OBJECT(item), "_dw_eventbox");
7667
7668 /* NOTE: I left in the ability to pack boxes with a size,
7669 * this eliminates that by forcing the size to 0.
7670 */
7671 height = width = 0;
7672
7673 if(eventbox)
7674 {
7675 int boxpad = (int)g_object_get_data(G_OBJECT(item), "_dw_boxpad");
7676 gtk_container_add(GTK_CONTAINER(eventbox), item);
7677 gtk_container_set_border_width(GTK_CONTAINER(eventbox), boxpad);
7678 item = eventbox;
7679 }
7680 }
7681 else
7682 {
7683 /* Only show warning if item is not a box */
7684 warn = TRUE;
7685 }
7686
7687 gtk_container_set_border_width(GTK_CONTAINER(box), pad);
7688 gtk_container_add(GTK_CONTAINER(box), vbox);
7689 gtk_box_pack_end(GTK_BOX(vbox), item, TRUE, TRUE, 0);
7690 gtk_widget_show(vbox);
7691
7692 gtk_widget_set_size_request(item, width, height);
7693 g_object_set_data(G_OBJECT(box), "_dw_user", vbox);
7694 }
7695 DW_MUTEX_UNLOCK;
7696
7697 if(warn)
7698 {
7699 if ( width == 0 && hsize == FALSE )
7700 dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item);
7701 if ( height == 0 && vsize == FALSE )
7702 dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item);
7703 }
7704 }
7705
7706 #ifdef GDK_WINDOWING_X11
7707 static void _size_allocate(GtkWindow *window)
7708 {
7709 XSizeHints sizehints;
7710
7711 sizehints.base_width = 1;
7712 sizehints.base_height = 1;
7713 sizehints.width_inc = 1;
7714 sizehints.height_inc = 1;
7715 sizehints.min_width = 8;
7716 sizehints.min_height = 8;
7717
7718 sizehints.flags = (PBaseSize|PMinSize|PResizeInc);
7719
7720 XSetWMNormalHints (gdk_x11_display_get_xdisplay(gdk_display_get_default()),
7721 GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(window))),&sizehints);
7722 gdk_flush ();
7723 }
7724 #endif
7725
7726 /*
7727 * Sets the size of a given window (widget).
7728 * Parameters:
7729 * handle: Window (widget) handle.
7730 * width: New width in pixels.
7731 * height: New height in pixels.
7732 */
7733 void dw_window_set_size(HWND handle, unsigned long width, unsigned long height)
7734 {
7735 int _locked_by_me = FALSE;
7736 long default_width = width - _dw_border_width;
7737 long default_height = height - _dw_border_height;
7738
7739 if(!handle)
7740 return;
7741
7742 DW_MUTEX_LOCK;
7743 if(GTK_IS_WINDOW(handle))
7744 {
7745 if ( width == 0 )
7746 default_width = -1;
7747 if ( height == 0 )
7748 default_height = -1;
7749
7750 #ifdef GDK_WINDOWING_X11
7751 _size_allocate(GTK_WINDOW(handle));
7752 #endif
7753
7754 if(gtk_widget_get_window(handle) && default_width > 0 && default_height > 0)
7755 gdk_window_resize(gtk_widget_get_window(handle), default_width , default_height );
7756
7757 gtk_window_set_default_size(GTK_WINDOW(handle), default_width , default_height );
7758 if(!g_object_get_data(G_OBJECT(handle), "_dw_size"))
7759 {
7760 g_object_set_data(G_OBJECT(handle), "_dw_width", GINT_TO_POINTER(default_width) );
7761 g_object_set_data(G_OBJECT(handle), "_dw_height", GINT_TO_POINTER(default_height) );
7762 }
7763 }
7764 else
7765 gtk_widget_set_size_request(handle, width, height);
7766 DW_MUTEX_UNLOCK;
7767 }
7768
7769 /*
7770 * Returns the width of the screen.
7771 */
7772 int dw_screen_width(void)
7773 {
7774 int retval;
7775 int _locked_by_me = FALSE;
7776
7777 DW_MUTEX_LOCK;
7778 retval = gdk_screen_width();
7779 DW_MUTEX_UNLOCK;
7780 return retval;
7781 }
7782
7783 /*
7784 * Returns the height of the screen.
7785 */
7786 int dw_screen_height(void)
7787 {
7788 int retval;
7789 int _locked_by_me = FALSE;
7790
7791 DW_MUTEX_UNLOCK;
7792 retval = gdk_screen_height();
7793 DW_MUTEX_UNLOCK;
7794 return retval;
7795 }
7796
7797 /* This should return the current color depth */
7798 unsigned long dw_color_depth_get(void)
7799 {
7800 int retval;
7801 GdkVisual *vis;
7802 int _locked_by_me = FALSE;
7803
7804 DW_MUTEX_UNLOCK;
7805 vis = gdk_visual_get_system();
7806 retval = gdk_visual_get_depth(vis);
7807 DW_MUTEX_UNLOCK;
7808 return retval;
7809 }
7810
7811 /*
7812 * Sets the position of a given window (widget).
7813 * Parameters:
7814 * handle: Window (widget) handle.
7815 * x: X location from the bottom left.
7816 * y: Y location from the bottom left.
7817 */
7818 void dw_window_set_pos(HWND handle, long x, long y)
7819 {
7820 int _locked_by_me = FALSE;
7821 GtkWidget *mdi;
7822
7823 DW_MUTEX_LOCK;
7824 if((mdi = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_mdi")) && GTK_IS_MDI(mdi))
7825 {
7826 gtk_mdi_move(GTK_MDI(mdi), handle, x, y);
7827 }
7828 else
7829 {
7830 if(handle && gtk_widget_get_window(handle))
7831 gdk_window_move(gtk_widget_get_window(handle), x, y);
7832 }
7833 DW_MUTEX_UNLOCK;
7834 }
7835
7836 /*
7837 * Sets the position and size of a given window (widget).
7838 * Parameters:
7839 * handle: Window (widget) handle.
7840 * x: X location from the bottom left.
7841 * y: Y location from the bottom left.
7842 * width: Width of the widget.
7843 * height: Height of the widget.
7844 */
7845 void dw_window_set_pos_size(HWND handle, long x, long y, unsigned long width, unsigned long height)
7846 {
7847 int _locked_by_me = FALSE;
7848 GtkWidget *mdi;
7849
7850 if(!handle)
7851 return;
7852 DW_MUTEX_LOCK;
7853 if((mdi = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_mdi")) && GTK_IS_MDI(mdi))
7854 {
7855 gtk_mdi_move(GTK_MDI(mdi), handle, x, y);
7856 }
7857 else
7858 {
7859 if(GTK_IS_WINDOW(handle))
7860 {
7861 dw_window_set_size(handle, width, height);
7862 #if 0 /* TODO: Deprecated with no replaced... what to do here? */
7863 gtk_widget_set_uposition(handle, x, y);
7864 #endif
7865 }
7866 else if(gtk_widget_get_window(handle))
7867 {
7868 gdk_window_resize(gtk_widget_get_window(handle), width, height);
7869 gdk_window_move(gtk_widget_get_window(handle), x, y);
7870 }
7871 }
7872 DW_MUTEX_UNLOCK;
7873 }
7874
7875 /*
7876 * Gets the position and size of a given window (widget).
7877 * Parameters:
7878 * handle: Window (widget) handle.
7879 * x: X location from the bottom left.
7880 * y: Y location from the bottom left.
7881 * width: Width of the widget.
7882 * height: Height of the widget.
7883 */
7884 void dw_window_get_pos_size(HWND handle, long *x, long *y, ULONG *width, ULONG *height)
7885 {
7886 int _locked_by_me = FALSE;
7887 gint gx, gy, gwidth, gheight;
7888 GtkWidget *mdi;
7889
7890 DW_MUTEX_LOCK;
7891 if((mdi = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_mdi")) && GTK_IS_MDI(mdi))
7892 {
7893 gint myx=0, myy=0;
7894
7895 gtk_mdi_get_pos(GTK_MDI(mdi), handle, &myx, &myy);
7896 *x = myx;
7897 *y = myy;
7898 }
7899 else
7900 {
7901 if(handle && gtk_widget_get_window(handle))
7902 {
7903
7904 gdk_window_get_geometry(gtk_widget_get_window(handle), &gx, &gy, &gwidth, &gheight);
7905 gdk_window_get_root_origin(gtk_widget_get_window(handle), &gx, &gy);
7906 if(x)
7907 *x = gx;
7908 if(y)
7909 *y = gy;
7910 if(GTK_IS_WINDOW(handle))
7911 {
7912 if(width)
7913 *width = gwidth + _dw_border_width;
7914 if(height)
7915 *height = gheight + _dw_border_height;
7916 }
7917 else
7918 {
7919 if(width)
7920 *width = gwidth;
7921 if(height)
7922 *height = gheight;
7923 }
7924 }
7925 }
7926 DW_MUTEX_UNLOCK;
7927 }
7928
7929 /*
7930 * Sets the style of a given window (widget).
7931 * Parameters:
7932 * handle: Window (widget) handle.
7933 * width: New width in pixels.
7934 * height: New height in pixels.
7935 */
7936 void dw_window_set_style(HWND handle, unsigned long style, unsigned long mask)
7937 {
7938 GtkWidget *handle2 = handle;
7939 int _locked_by_me = FALSE;
7940
7941 DW_MUTEX_LOCK;
7942 if(GTK_IS_SCROLLED_WINDOW(handle))
7943 {
7944 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
7945 if(tmp)
7946 handle2 = tmp;
7947 }
7948 else if(GTK_IS_FRAME(handle))
7949 {
7950 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_label");
7951 if(tmp && GTK_IS_LABEL(tmp))
7952 handle2 = tmp;
7953 }
7954 else if(GTK_IS_BUTTON(handle))
7955 {
7956 if(mask & DW_BS_NOBORDER)
7957 {
7958 if(style & DW_BS_NOBORDER)
7959 {
7960 gtk_button_set_relief((GtkButton *)handle, GTK_RELIEF_NONE);
7961 }
7962 else
7963 {
7964 gtk_button_set_relief((GtkButton *)handle, GTK_RELIEF_NORMAL);
7965 }
7966 }
7967 }
7968 if ( GTK_IS_LABEL(handle2) )
7969 {
7970 gfloat x=DW_LEFT, y=DW_CENTER;
7971 /* horizontal... */
7972 if ( style & DW_DT_CENTER )
7973 x = DW_CENTER;
7974 if ( style & DW_DT_RIGHT )
7975 x = DW_RIGHT;
7976 if ( style & DW_DT_LEFT )
7977 x = DW_LEFT;
7978 /* vertical... */
7979 if ( style & DW_DT_VCENTER )
7980 y = DW_CENTER;
7981 if ( style & DW_DT_TOP )
7982 y = DW_TOP;
7983 if ( style & DW_DT_BOTTOM )
7984 y = DW_BOTTOM;
7985 gtk_misc_set_alignment( GTK_MISC(handle2), x, y );
7986 if ( style & DW_DT_WORDBREAK )
7987 gtk_label_set_line_wrap( GTK_LABEL(handle), TRUE );
7988 }
7989 DW_MUTEX_UNLOCK;
7990 }
7991
7992 /*
7993 * Adds a new page to specified notebook.
7994 * Parameters:
7995 * handle: Window (widget) handle.
7996 * flags: Any additional page creation flags.
7997 * front: If TRUE page is added at the beginning.
7998 */
7999 unsigned long dw_notebook_page_new(HWND handle, unsigned long flags, int front)
8000 {
8001 int z;
8002 int _locked_by_me = FALSE;
8003 GtkWidget **pagearray;
8004
8005 DW_MUTEX_LOCK;
8006 pagearray = (GtkWidget **)g_object_get_data(G_OBJECT(handle), "_dw_pagearray");
8007
8008 if(pagearray)
8009 {
8010 for(z=0;z<256;z++)
8011 {
8012 if(!pagearray[z])
8013 {
8014 char text[100];
8015 int num = z;
8016
8017 if(front)
8018 num |= 1 << 16;
8019
8020 sprintf(text, "_dw_page%d", z);
8021 /* Save the real id and the creation flags */
8022 g_object_set_data(G_OBJECT(handle), text, GINT_TO_POINTER(num));
8023 DW_MUTEX_UNLOCK;
8024 return z;
8025 }
8026 }
8027 }
8028 DW_MUTEX_UNLOCK;
8029
8030 /* Hopefully this won't happen. */
8031 return 256;
8032 }
8033
8034 /* Return the physical page id from the logical page id */
8035 int _get_physical_page(HWND handle, unsigned long pageid)
8036 {
8037 int z;
8038 GtkWidget *thispage, **pagearray = g_object_get_data(G_OBJECT(handle), "_dw_pagearray");
8039
8040 if(pagearray)
8041 {
8042 for(z=0;z<256;z++)
8043 {
8044 if((thispage = gtk_notebook_get_nth_page(GTK_NOTEBOOK(handle), z)))
8045 {
8046 if(thispage == pagearray[pageid])
8047 return z;
8048 }
8049 }
8050 }
8051 return 256;
8052 }
8053
8054 /*
8055 * Remove a page from a notebook.
8056 * Parameters:
8057 * handle: Handle to the notebook widget.
8058 * pageid: ID of the page to be destroyed.
8059 */
8060 void dw_notebook_page_destroy(HWND handle, unsigned int pageid)
8061 {
8062 int realpage, _locked_by_me = FALSE;
8063 GtkWidget **pagearray;
8064
8065 DW_MUTEX_LOCK;
8066 realpage = _get_physical_page(handle, pageid);
8067 if(realpage > -1 && realpage < 256)
8068 {
8069 gtk_notebook_remove_page(GTK_NOTEBOOK(handle), realpage);
8070 if((pagearray = g_object_get_data(G_OBJECT(handle), "_dw_pagearray")))
8071 pagearray[pageid] = NULL;
8072 }
8073 DW_MUTEX_UNLOCK;
8074 }
8075
8076 /*
8077 * Queries the currently visible page ID.
8078 * Parameters:
8079 * handle: Handle to the notebook widget.
8080 */
8081 unsigned long dw_notebook_page_get(HWND handle)
8082 {
8083 int retval, phys;
8084 int _locked_by_me = FALSE;
8085
8086 DW_MUTEX_LOCK;
8087 phys = gtk_notebook_get_current_page(GTK_NOTEBOOK(handle));
8088 retval = _get_logical_page(handle, phys);
8089 DW_MUTEX_UNLOCK;
8090 return retval;
8091 }
8092
8093 /*
8094 * Sets the currently visibale page ID.
8095 * Parameters:
8096 * handle: Handle to the notebook widget.
8097 * pageid: ID of the page to be made visible.
8098 */
8099 void dw_notebook_page_set(HWND handle, unsigned int pageid)
8100 {
8101 int realpage, _locked_by_me = FALSE;
8102
8103 DW_MUTEX_LOCK;
8104 realpage = _get_physical_page(handle, pageid);
8105 if(realpage > -1 && realpage < 256)
8106 gtk_notebook_set_current_page(GTK_NOTEBOOK(handle), pageid);
8107 DW_MUTEX_UNLOCK;
8108 }
8109
8110
8111 /*
8112 * Sets the text on the specified notebook tab.
8113 * Parameters:
8114 * handle: Notebook handle.
8115 * pageid: Page ID of the tab to set.
8116 * text: Pointer to the text to set.
8117 */
8118 void dw_notebook_page_set_text(HWND handle, unsigned long pageid, char *text)
8119 {
8120 GtkWidget *child;
8121 int realpage, _locked_by_me = FALSE;
8122
8123 DW_MUTEX_LOCK;
8124 realpage = _get_physical_page(handle, pageid);
8125 if(realpage < 0 || realpage > 255)
8126 {
8127 char ptext[100];
8128 int num;
8129
8130 sprintf(ptext, "_dw_page%d", (int)pageid);
8131 num = (int)g_object_get_data(G_OBJECT(handle), ptext);
8132 realpage = 0xFF & num;
8133 }
8134
8135 if(realpage > -1 && realpage < 256)
8136 {
8137 child = gtk_notebook_get_nth_page(GTK_NOTEBOOK(handle), realpage);
8138 if(child)
8139 gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(handle), child, text);
8140 }
8141 DW_MUTEX_UNLOCK;
8142 }
8143
8144 /*
8145 * Sets the text on the specified notebook tab status area.
8146 * Parameters:
8147 * handle: Notebook handle.
8148 * pageid: Page ID of the tab to set.
8149 * text: Pointer to the text to set.
8150 */
8151 void dw_notebook_page_set_status_text(HWND handle, unsigned long pageid, char *text)
8152 {
8153 /* TODO (if possible) */
8154 }
8155
8156 /*
8157 * Packs the specified box into the notebook page.
8158 * Parameters:
8159 * handle: Handle to the notebook to be packed.
8160 * pageid: Page ID in the notebook which is being packed.
8161 * page: Box handle to be packed.
8162 */
8163 void dw_notebook_pack(HWND handle, unsigned long pageid, HWND page)
8164 {
8165 GtkWidget *label, *child, *oldlabel, **pagearray;
8166 gchar *text = NULL;
8167 int num, z, realpage = -1, pad, _locked_by_me = FALSE;
8168 char ptext[100];
8169
8170 DW_MUTEX_LOCK;
8171 sprintf(ptext, "_dw_page%d", (int)pageid);
8172 num = (int)g_object_get_data(G_OBJECT(handle), ptext);
8173 g_object_set_data(G_OBJECT(handle), ptext, NULL);
8174 pagearray = (GtkWidget **)g_object_get_data(G_OBJECT(handle), "_dw_pagearray");
8175
8176 if(!pagearray)
8177 {
8178 DW_MUTEX_UNLOCK;
8179 return;
8180 }
8181
8182 /* The page already exists... so get it's current page */
8183 if(pagearray[pageid])
8184 {
8185 for(z=0;z<256;z++)
8186 {
8187 child = gtk_notebook_get_nth_page(GTK_NOTEBOOK(handle), z);
8188 if(child == pagearray[pageid])
8189 {
8190 oldlabel = gtk_notebook_get_tab_label(GTK_NOTEBOOK(handle), child);
8191 #if 0 /* TODO: gtk_label_get is deprecated with no replacement */
8192 if(oldlabel)
8193 gtk_label_get(GTK_LABEL(oldlabel), &text);
8194 #endif
8195 gtk_notebook_remove_page(GTK_NOTEBOOK(handle), z);
8196 realpage = z;
8197 break;
8198 }
8199 }
8200 }
8201
8202 pagearray[pageid] = page;
8203
8204 label = gtk_label_new(text ? text : "");
8205
8206 if(GTK_IS_TABLE(page))
8207 {
8208 pad = (int)g_object_get_data(G_OBJECT(page), "_dw_boxpad");
8209 gtk_container_set_border_width(GTK_CONTAINER(page), pad);
8210 }
8211
8212 if(realpage != -1)
8213 gtk_notebook_insert_page(GTK_NOTEBOOK(handle), page, label, realpage);
8214 else if(num & ~(0xFF))
8215 gtk_notebook_insert_page(GTK_NOTEBOOK(handle), page, label, 0);
8216 else
8217 gtk_notebook_insert_page(GTK_NOTEBOOK(handle), page, label, 256);
8218 DW_MUTEX_UNLOCK;
8219 }
8220
8221 /*
8222 * Appends the specified text to the listbox's (or combobox) entry list.
8223 * Parameters:
8224 * handle: Handle to the listbox to be appended to.
8225 * text: Text to append into listbox.
8226 */
8227 void dw_listbox_append(HWND handle, char *text)
8228 {
8229 GtkWidget *handle2 = handle;
8230 int _locked_by_me = FALSE;
8231
8232 DW_MUTEX_LOCK;
8233 if(GTK_IS_SCROLLED_WINDOW(handle))
8234 {
8235 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8236 if(tmp)
8237 handle2 = tmp;
8238 }
8239 #if 0
8240 g_object_set_data(G_OBJECT(handle), "_dw_appending", GINT_TO_POINTER(1));
8241 if(GTK_IS_LIST(handle2))
8242 {
8243 GtkWidget *list_item;
8244 GList *tmp;
8245 char *font = (char *)g_object_get_data(G_OBJECT(handle), "_dw_font");
8246 GdkColor *fore = (GdkColor *)g_object_get_data(G_OBJECT(handle2), "_dw_foregdk");
8247 GdkColor *back = (GdkColor *)g_object_get_data(G_OBJECT(handle2), "_dw_backgdk");
8248
8249 list_item=gtk_list_item_new_with_label(text);
8250
8251 if(font)
8252 _set_font(GTK_LIST_ITEM(list_item)->item.bin.child, font);
8253 if(fore && back)
8254 _set_color(GTK_LIST_ITEM(list_item)->item.bin.child,
8255 DW_RGB(fore->red, fore->green, fore->blue),
8256 DW_RGB(back->red, back->green, back->blue));
8257
8258 tmp = g_list_append(NULL, list_item);
8259 gtk_widget_show(list_item);
8260 gtk_list_append_items(GTK_LIST(handle2),tmp);
8261 }
8262 else if(GTK_IS_COMBO_BOX(handle2))
8263 {
8264 GList *tmp = (GList *)gtk_object_get_user_data(GTK_OBJECT(handle2));
8265 char *addtext = strdup(text);
8266
8267 if(addtext)
8268 {
8269 char *defstr = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO_BOX(handle2)->entry));
8270 tmp = g_list_append(tmp, addtext);
8271 g_object_set_data(G_OBJECT(handle2), "_dw_user", tmp);
8272 gtk_combo_set_popdown_strings(GTK_COMBO_BOX(handle2), tmp);
8273 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO_BOX(handle2)->entry), defstr);
8274 }
8275 }
8276 g_object_set_data(G_OBJECT(handle), "_dw_appending", NULL);
8277 #endif
8278 DW_MUTEX_UNLOCK;
8279 }
8280
8281 /*
8282 * Inserts the specified text int the listbox's (or combobox) entry list at the
8283 * position indicated.
8284 * Parameters:
8285 * handle: Handle to the listbox to be appended to.
8286 * text: Text to insert into listbox.
8287 * pos: 0-based index into listbox. -1 will append
8288 */
8289 void dw_listbox_insert(HWND handle, char *text, int pos)
8290 {
8291 GtkWidget *handle2 = handle;
8292 int _locked_by_me = FALSE;
8293
8294 DW_MUTEX_LOCK;
8295 if(GTK_IS_SCROLLED_WINDOW(handle))
8296 {
8297 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8298 if(tmp)
8299 handle2 = tmp;
8300 }
8301 #if 0
8302 g_object_set_data(G_OBJECT(handle), "_dw_appending", GINT_TO_POINTER(1));
8303 if(GTK_IS_LIST(handle2))
8304 {
8305 GtkWidget *list_item;
8306 GList *tmp;
8307 char *font = (char *)g_object_get_data(G_OBJECT(handle), "_dw_font");
8308 GdkColor *fore = (GdkColor *)g_object_get_data(G_OBJECT(handle2), "_dw_foregdk");
8309 GdkColor *back = (GdkColor *)g_object_get_data(G_OBJECT(handle2), "_dw_backgdk");
8310
8311 list_item=gtk_list_item_new_with_label(text);
8312
8313 if(font)
8314 _set_font(GTK_LIST_ITEM(list_item)->item.bin.child, font);
8315 if(fore && back)
8316 _set_color(GTK_LIST_ITEM(list_item)->item.bin.child,
8317 DW_RGB(fore->red, fore->green, fore->blue),
8318 DW_RGB(back->red, back->green, back->blue));
8319
8320 tmp = g_list_insert(NULL, list_item, pos);
8321 gtk_widget_show(list_item);
8322 gtk_list_append_items(GTK_LIST(handle2),tmp);
8323 }
8324 else if(GTK_IS_COMBO_BOX(handle2))
8325 {
8326 GList *tmp = (GList *)gtk_object_get_user_data(GTK_OBJECT(handle2));
8327 char *addtext = strdup(text);
8328
8329 if(addtext)
8330 {
8331 tmp = g_list_insert(tmp, addtext, pos);
8332 g_object_set_data(GTK_OBJECT(handle2), "_dw_user", tmp);
8333 gtk_combo_set_popdown_strings(GTK_COMBO_BOX(handle2), tmp);
8334 }
8335 }
8336 g_object_set_data(G_OBJECT(handle), "_dw_appending", NULL);
8337 #endif
8338 DW_MUTEX_UNLOCK;
8339 }
8340
8341 /*
8342 * Appends the specified text items to the listbox's (or combobox) entry list.
8343 * Parameters:
8344 * handle: Handle to the listbox to be appended to.
8345 * text: Text strings to append into listbox.
8346 * count: Number of text strings to append
8347 */
8348 void dw_listbox_list_append(HWND handle, char **text, int count)
8349 {
8350 GtkWidget *handle2 = handle;
8351 int _locked_by_me = FALSE;
8352
8353 if ( count == 0 )
8354 return;
8355
8356 DW_MUTEX_LOCK;
8357 if(GTK_IS_SCROLLED_WINDOW(handle))
8358 {
8359 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8360 if(tmp)
8361 handle2 = tmp;
8362 }
8363 #if 0
8364 g_object_set_data(G_OBJECT(handle), "_dw_appending", GINT_TO_POINTER(1));
8365 if(GTK_IS_LIST(handle2))
8366 {
8367 GtkWidget *list_item;
8368 GList *tmp;
8369 char *font = (char *)g_object_get_data(G_OBJECT(handle), "_dw_font");
8370 GdkColor *fore = (GdkColor *)g_object_get_data(G_OBJECT(handle2), "_dw_foregdk");
8371 GdkColor *back = (GdkColor *)g_object_get_data(G_OBJECT(handle2), "_dw_backgdk");
8372
8373 list_item=gtk_list_item_new_with_label(*text);
8374
8375 if(font)
8376 _set_font(GTK_LIST_ITEM(list_item)->item.bin.child, font);
8377 if(fore && back)
8378 _set_color(GTK_LIST_ITEM(list_item)->item.bin.child,
8379 DW_RGB(fore->red, fore->green, fore->blue),
8380 DW_RGB(back->red, back->green, back->blue));
8381
8382 tmp = g_list_append(NULL, list_item);
8383 gtk_widget_show(list_item);
8384 gtk_list_append_items(GTK_LIST(handle2),tmp);
8385 }
8386 else if(GTK_IS_COMBO_BOX(handle2))
8387 {
8388 GList *tmp = (GList *)gtk_object_get_user_data(GTK_OBJECT(handle2));
8389 char *addtext;
8390 int i;
8391
8392 for (i=0;i<count;i++)
8393 {
8394 addtext = strdup(text[i]);
8395 tmp = g_list_append(tmp, addtext);
8396 }
8397 g_object_set_data(GTK_OBJECT(handle2), "_dw_user", tmp);
8398 gtk_combo_set_popdown_strings(GTK_COMBO_BOX(handle2), tmp);
8399 }
8400 g_object_set_data(G_OBJECT(handle), "_dw_appending", NULL);
8401 #endif
8402 DW_MUTEX_UNLOCK;
8403 }
8404
8405 /*
8406 * Clears the listbox's (or combobox) list of all entries.
8407 * Parameters:
8408 * handle: Handle to the listbox to be cleared.
8409 */
8410 void dw_listbox_clear(HWND handle)
8411 {
8412 GtkWidget *handle2 = handle;
8413 int _locked_by_me = FALSE;
8414
8415 DW_MUTEX_LOCK;
8416 if(GTK_IS_SCROLLED_WINDOW(handle))
8417 {
8418 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8419 if(tmp)
8420 handle2 = tmp;
8421 }
8422 #if 0
8423 if(GTK_IS_COMBO_BOX(handle2))
8424 {
8425 GList *list, *tmp = (GList *)g_object_get_data(G_OBJECT(handle2));
8426
8427 if(tmp)
8428 {
8429 list = tmp;
8430 while(list)
8431 {
8432 if(list->data)
8433 free(list->data);
8434 list=list->next;
8435 }
8436 g_list_free(tmp);
8437 }
8438 g_object_set_data(G_OBJECT(handle2), "_dw_user", NULL);
8439 }
8440 else if(GTK_IS_LIST(handle2))
8441 {
8442 int count = dw_listbox_count(handle);
8443
8444 gtk_list_clear_items(GTK_LIST(handle2), 0, count);
8445 }
8446 #endif
8447 DW_MUTEX_UNLOCK;
8448 }
8449
8450 /*
8451 * Returns the listbox's item count.
8452 * Parameters:
8453 * handle: Handle to the listbox to be counted
8454 */
8455 int dw_listbox_count(HWND handle)
8456 {
8457 GtkWidget *handle2 = handle;
8458 int retval = 0;
8459 int _locked_by_me = FALSE;
8460
8461 DW_MUTEX_LOCK;
8462 if(GTK_IS_SCROLLED_WINDOW(handle))
8463 {
8464 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8465 if(tmp)
8466 handle2 = tmp;
8467 }
8468 #if 0
8469 else if(GTK_IS_COMBO_BOX(handle))
8470 {
8471 handle2 = GTK_COMBO_BOX(handle)->list;
8472 }
8473 if(GTK_IS_LIST(handle2))
8474 {
8475 GList *list = GTK_LIST(handle2)->children;
8476 while(list)
8477 {
8478 list = list->next;
8479 retval++;
8480 }
8481 }
8482 #endif
8483 DW_MUTEX_UNLOCK;
8484 return retval;
8485 }
8486
8487 /*
8488 * Sets the topmost item in the viewport.
8489 * Parameters:
8490 * handle: Handle to the listbox to be cleared.
8491 * top: Index to the top item.
8492 */
8493 void dw_listbox_set_top(HWND handle, int top)
8494 {
8495 GtkWidget *handle2 = handle;
8496 int _locked_by_me = FALSE;
8497
8498 DW_MUTEX_LOCK;
8499 if(GTK_IS_SCROLLED_WINDOW(handle))
8500 {
8501 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8502 if(tmp)
8503 handle2 = tmp;
8504 }
8505 #if 0
8506 if(GTK_IS_LIST(handle2))
8507 {
8508 int count = dw_listbox_count(handle);
8509 GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(handle));
8510 float pos, ratio;
8511
8512 if(count)
8513 {
8514 ratio = (float)top/(float)count;
8515
8516 pos = (ratio * (float)(adj->upper - adj->lower)) + adj->lower;
8517
8518 gtk_adjustment_set_value(adj, pos);
8519 }
8520 }
8521 #endif
8522 DW_MUTEX_UNLOCK;
8523 }
8524
8525 /*
8526 * Copies the given index item's text into buffer.
8527 * Parameters:
8528 * handle: Handle to the listbox to be queried.
8529 * index: Index into the list to be queried.
8530 * buffer: Buffer where text will be copied.
8531 * length: Length of the buffer (including NULL).
8532 */
8533 void dw_listbox_get_text(HWND handle, unsigned int index, char *buffer, unsigned int length)
8534 {
8535 GtkWidget *handle2 = handle;
8536 int _locked_by_me = FALSE;
8537
8538 DW_MUTEX_LOCK;
8539 if(GTK_IS_SCROLLED_WINDOW(handle))
8540 {
8541 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8542 if(tmp)
8543 handle2 = tmp;
8544 }
8545 #if 0
8546 else if(GTK_IS_COMBO_BOX(handle))
8547 {
8548 handle2 = GTK_COMBO_BOX(handle)->list;
8549 }
8550 if(GTK_IS_LIST(handle2))
8551 {
8552 int counter = 0;
8553 GList *list = GTK_LIST(handle2)->children;
8554
8555 while(list)
8556 {
8557 if(counter == index)
8558 {
8559 gchar *text = "";
8560
8561 if(GTK_IS_LIST_ITEM(list->data))
8562 {
8563 GtkListItem *li = GTK_LIST_ITEM(list->data);
8564
8565 if(GTK_IS_ITEM(&(li->item)))
8566 {
8567 GtkItem *i = &(li->item);
8568
8569 if(GTK_IS_BIN(&(i->bin)))
8570 {
8571 GtkBin *b = &(i->bin);
8572
8573 if(GTK_IS_LABEL(b->child))
8574 gtk_label_get(GTK_LABEL(b->child), &text);
8575 }
8576 }
8577 }
8578 else if(GTK_IS_COMBO_BOX(handle) && list->data)
8579 text = (gchar *)list->data;
8580
8581 strncpy(buffer, (char *)text, length);
8582 break;
8583 }
8584 list = list->next;
8585 counter++;
8586 }
8587 }
8588 #endif
8589 DW_MUTEX_UNLOCK;
8590 }
8591
8592 /*
8593 * Sets the text of a given listbox entry.
8594 * Parameters:
8595 * handle: Handle to the listbox to be queried.
8596 * index: Index into the list to be queried.
8597 * buffer: Buffer where text will be copied.
8598 */
8599 void dw_listbox_set_text(HWND handle, unsigned int index, char *buffer)
8600 {
8601 GtkWidget *handle2 = handle;
8602 int _locked_by_me = FALSE;
8603
8604 DW_MUTEX_LOCK;
8605 if(GTK_IS_SCROLLED_WINDOW(handle))
8606 {
8607 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8608 if(tmp)
8609 handle2 = tmp;
8610 }
8611 #if 0
8612 else if(GTK_IS_COMBO_BOX(handle))
8613 {
8614 handle2 = GTK_COMBO_BOX(handle)->list;
8615 }
8616 if(GTK_IS_LIST(handle2))
8617 {
8618 int counter = 0;
8619 GList *list = GTK_LIST(handle2)->children;
8620
8621 while(list)
8622 {
8623 if(counter == index)
8624 {
8625
8626 if(GTK_IS_LIST_ITEM(list->data))
8627 {
8628 GtkListItem *li = GTK_LIST_ITEM(list->data);
8629
8630 if(GTK_IS_ITEM(&(li->item)))
8631 {
8632 GtkItem *i = &(li->item);
8633
8634 if(GTK_IS_BIN(&(i->bin)))
8635 {
8636 GtkBin *b = &(i->bin);
8637
8638 if(GTK_IS_LABEL(b->child))
8639 gtk_label_set_text(GTK_LABEL(b->child), buffer);
8640 }
8641 }
8642 }
8643 else if(GTK_IS_COMBO_BOX(handle))
8644 {
8645 if(list->data)
8646 g_free(list->data);
8647 list->data = g_strdup(buffer);
8648 }
8649 break;
8650 }
8651 list = list->next;
8652 counter++;
8653 }
8654 }
8655 #endif
8656 DW_MUTEX_UNLOCK;
8657 }
8658
8659 /*
8660 * Returns the index to the current selected item or -1 when done.
8661 * Parameters:
8662 * handle: Handle to the listbox to be queried.
8663 * where: Either the previous return or -1 to restart.
8664 */
8665 int dw_listbox_selected_multi(HWND handle, int where)
8666 {
8667 GtkWidget *handle2 = handle;
8668 int retval = DW_LIT_NONE;
8669 int _locked_by_me = FALSE;
8670
8671 DW_MUTEX_LOCK;
8672 if(GTK_IS_SCROLLED_WINDOW(handle))
8673 {
8674 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8675 if(tmp)
8676 handle2 = tmp;
8677 }
8678 #if 0
8679 if(GTK_IS_LIST(handle2))
8680 {
8681 int counter = 0;
8682 GList *list = GTK_LIST(handle2)->children;
8683
8684 while(list)
8685 {
8686 GtkItem *item = (GtkItem *)list->data;
8687
8688 if(item &&
8689 item->bin.container.widget.state == GTK_STATE_SELECTED
8690 && counter > where)
8691 {
8692 retval = counter;
8693 break;
8694 }
8695
8696
8697 list = list->next;
8698 counter++;
8699 }
8700 }
8701 #endif
8702 DW_MUTEX_UNLOCK;
8703 return retval;
8704 }
8705
8706 /*
8707 * Returns the index to the item in the list currently selected.
8708 * Parameters:
8709 * handle: Handle to the listbox to be queried.
8710 */
8711 unsigned int dw_listbox_selected(HWND handle)
8712 {
8713 GtkWidget *handle2 = handle;
8714 int retval = DW_LIT_NONE;
8715 int _locked_by_me = FALSE;
8716
8717 DW_MUTEX_LOCK;
8718 if(GTK_IS_SCROLLED_WINDOW(handle))
8719 {
8720 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8721 if(tmp)
8722 handle2 = tmp;
8723 }
8724 #if 0
8725 else if(GTK_IS_COMBO_BOX(handle))
8726 {
8727 retval = (unsigned int)g_object_get_data(G_OBJECT(handle), "_dw_item");
8728 DW_MUTEX_UNLOCK;
8729 return retval;
8730 }
8731 if(GTK_IS_LIST(handle2))
8732 {
8733 int counter = 0;
8734 GList *list = GTK_LIST(handle2)->children;
8735
8736 while(list)
8737 {
8738 GtkItem *item = (GtkItem *)list->data;
8739
8740 if(item && item->bin.container.widget.state == GTK_STATE_SELECTED)
8741 {
8742 retval = counter;
8743 break;
8744 }
8745
8746 list = list->next;
8747 counter++;
8748 }
8749 }
8750 #endif
8751 DW_MUTEX_UNLOCK;
8752 return retval;
8753 }
8754
8755 /*
8756 * Sets the selection state of a given index.
8757 * Parameters:
8758 * handle: Handle to the listbox to be set.
8759 * index: Item index.
8760 * state: TRUE if selected FALSE if unselected.
8761 */
8762 void dw_listbox_select(HWND handle, int index, int state)
8763 {
8764 GtkWidget *handle2 = handle;
8765 int _locked_by_me = FALSE;
8766
8767 DW_MUTEX_LOCK;
8768 if(GTK_IS_SCROLLED_WINDOW(handle))
8769 {
8770 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8771 if(tmp)
8772 handle2 = tmp;
8773 }
8774 #if 0
8775 else if(GTK_IS_COMBO_BOX(handle))
8776 {
8777 handle2 = GTK_COMBO_BOX(handle)->list;
8778 }
8779 if(GTK_IS_LIST(handle2))
8780 {
8781 if(state)
8782 gtk_list_select_item(GTK_LIST(handle2), index);
8783 else
8784 gtk_list_unselect_item(GTK_LIST(handle2), index);
8785 }
8786 #endif
8787 DW_MUTEX_UNLOCK;
8788 }
8789
8790 /*
8791 * Deletes the item with given index from the list.
8792 * Parameters:
8793 * handle: Handle to the listbox to be set.
8794 * index: Item index.
8795 */
8796 void dw_listbox_delete(HWND handle, int index)
8797 {
8798 GtkWidget *handle2 = handle;
8799 int _locked_by_me = FALSE;
8800
8801 DW_MUTEX_LOCK;
8802 if(GTK_IS_SCROLLED_WINDOW(handle))
8803 {
8804 GtkWidget *tmp = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_user");
8805 if(tmp)
8806 handle2 = tmp;
8807 }
8808 #if 0
8809 else if(GTK_IS_COMBO_BOX(handle))
8810 {
8811 handle2 = GTK_COMBO_BOX(handle)->list;
8812 }
8813 if(GTK_IS_LIST(handle2))
8814 {
8815 gtk_list_clear_items(GTK_LIST(handle2), index, index+1);
8816 }
8817 #endif
8818 DW_MUTEX_UNLOCK;
8819 }
8820
8821 /* Reposition the bar according to the percentage */
8822 static gint _splitbar_size_allocate(GtkWidget *widget, GtkAllocation *event, gpointer data)
8823 {
8824 float *percent = (float *)g_object_get_data(G_OBJECT(widget), "_dw_percent");
8825 int lastwidth = (int)g_object_get_data(G_OBJECT(widget), "_dw_lastwidth");
8826 int lastheight = (int)g_object_get_data(G_OBJECT(widget), "_dw_lastheight");
8827
8828 /* Prevent infinite recursion ;) */
8829 if(!percent || (lastwidth == event->width && lastheight == event->height))
8830 return FALSE;
8831
8832 lastwidth = event->width; lastheight = event->height;
8833
8834 g_object_set_data(G_OBJECT(widget), "_dw_lastwidth", GINT_TO_POINTER(lastwidth));
8835 g_object_set_data(G_OBJECT(widget), "_dw_lastheight", GINT_TO_POINTER(lastheight));
8836
8837 if(GTK_IS_HPANED(widget))
8838 gtk_paned_set_position(GTK_PANED(widget), (int)(event->width * (*percent / 100.0)));
8839 if(GTK_IS_VPANED(widget))
8840 gtk_paned_set_position(GTK_PANED(widget), (int)(event->height * (*percent / 100.0)));
8841 g_object_set_data(G_OBJECT(widget), "_dw_waiting", NULL);
8842 return FALSE;
8843 }
8844
8845 /* Figure out the new percentage */
8846 static void _splitbar_accept_position(GObject *object, GParamSpec *pspec, gpointer data)
8847 {
8848 GtkWidget *widget = (GtkWidget *)data;
8849 float *percent = (float *)g_object_get_data(G_OBJECT(widget), "_dw_percent");
8850 int size = 0, position = gtk_paned_get_position(GTK_PANED(widget));
8851
8852 if(!percent || g_object_get_data(G_OBJECT(widget), "_dw_waiting"))
8853 return;
8854
8855 if(GTK_IS_VPANED(widget))
8856 size = gtk_widget_get_allocated_height(widget);
8857 else if(GTK_IS_HPANED(widget))
8858 size = gtk_widget_get_allocated_width(widget);
8859
8860 if(size > 0)
8861 *percent = ((float)(position * 100) / (float)size);
8862 }
8863
8864 /*
8865 * Creates a splitbar window (widget) with given parameters.
8866 * Parameters:
8867 * type: Value can be DW_VERT or DW_HORZ.
8868 * topleft: Handle to the window to be top or left.
8869 * bottomright: Handle to the window to be bottom or right.
8870 * Returns:
8871 * A handle to a splitbar window or NULL on failure.
8872 */
8873 HWND dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id)
8874 {
8875 GtkWidget *tmp = NULL;
8876 int _locked_by_me = FALSE;
8877 float *percent = malloc(sizeof(float));
8878
8879 DW_MUTEX_LOCK;
8880 if(type == DW_HORZ)
8881 tmp = gtk_hpaned_new();
8882 else
8883 tmp = gtk_vpaned_new();
8884 gtk_paned_add1(GTK_PANED(tmp), topleft);
8885 gtk_paned_add2(GTK_PANED(tmp), bottomright);
8886 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
8887 *percent = 50.0;
8888 g_object_set_data(G_OBJECT(tmp), "_dw_percent", (gpointer)percent);
8889 g_object_set_data(G_OBJECT(tmp), "_dw_waiting", GINT_TO_POINTER(1));
8890 g_signal_connect(G_OBJECT(tmp), "size-allocate", G_CALLBACK(_splitbar_size_allocate), NULL);
8891 g_signal_connect(G_OBJECT(tmp), "notify::position", G_CALLBACK(_splitbar_accept_position), (gpointer)tmp);
8892 gtk_widget_show(tmp);
8893 DW_MUTEX_UNLOCK;
8894 return tmp;
8895 }
8896
8897 /*
8898 * Sets the position of a splitbar (pecentage).
8899 * Parameters:
8900 * handle: The handle to the splitbar returned by dw_splitbar_new().
8901 */
8902 void dw_splitbar_set(HWND handle, float percent)
8903 {
8904 float *mypercent = (float *)dw_window_get_data(handle, "_dw_percent");
8905 int size = 0, position;
8906
8907 if(GTK_IS_VPANED(handle))
8908 size = gtk_widget_get_allocated_height(handle);
8909 else if(GTK_IS_HPANED(handle))
8910 size = gtk_widget_get_allocated_width(handle);
8911
8912 if(mypercent)
8913 *mypercent = percent;
8914
8915 if(size > 10)
8916 {
8917 position = (int)((float)size * (percent / 100.0));
8918
8919 gtk_paned_set_position(GTK_PANED(handle), position);
8920 }
8921 }
8922
8923 /*
8924 * Gets the position of a splitbar (pecentage).
8925 * Parameters:
8926 * handle: The handle to the splitbar returned by dw_splitbar_new().
8927 */
8928 float dw_splitbar_get(HWND handle)
8929 {
8930 float *percent = (float *)dw_window_get_data(handle, "_dw_percent");
8931
8932 if(percent)
8933 return *percent;
8934 return 0.0;
8935 }
8936
8937 /*
8938 * Creates a calendar window (widget) with given parameters.
8939 * Parameters:
8940 * id: Unique identifier for calendar widget
8941 * Returns:
8942 * A handle to a calendar window or NULL on failure.
8943 */
8944 HWND dw_calendar_new(unsigned long id)
8945 {
8946 GtkWidget *tmp;
8947 int _locked_by_me = FALSE;
8948 GtkCalendarDisplayOptions flags;
8949 time_t now;
8950 struct tm *tmdata;
8951
8952 DW_MUTEX_LOCK;
8953 tmp = gtk_calendar_new();
8954 gtk_widget_show(tmp);
8955 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
8956 /* select today */
8957 flags = GTK_CALENDAR_SHOW_HEADING|GTK_CALENDAR_SHOW_DAY_NAMES;
8958 gtk_calendar_set_display_options( GTK_CALENDAR(tmp), flags );
8959 now = time( NULL );
8960 tmdata = localtime( & now );
8961 gtk_calendar_select_month( GTK_CALENDAR(tmp), tmdata->tm_mon, 1900+tmdata->tm_year );
8962 gtk_calendar_select_day( GTK_CALENDAR(tmp), tmdata->tm_mday );
8963
8964 DW_MUTEX_UNLOCK;
8965 return tmp;
8966 }
8967
8968 /*
8969 * Sets the current date of a calendar
8970 * Parameters:
8971 * handle: The handle to the calendar returned by dw_calendar_new().
8972 * year...
8973 */
8974 void dw_calendar_set_date(HWND handle, unsigned int year, unsigned int month, unsigned int day)
8975 {
8976 int _locked_by_me = FALSE;
8977
8978 DW_MUTEX_LOCK;
8979 if(GTK_IS_CALENDAR(handle))
8980 {
8981 gtk_calendar_select_month(GTK_CALENDAR(handle),month-1,year);
8982 gtk_calendar_select_day(GTK_CALENDAR(handle), day);
8983 }
8984 DW_MUTEX_UNLOCK;
8985 return;
8986 }
8987
8988 /*
8989 * Gets the position of a splitbar (pecentage).
8990 * Parameters:
8991 * handle: The handle to the splitbar returned by dw_splitbar_new().
8992 */
8993 void dw_calendar_get_date(HWND handle, unsigned int *year, unsigned int *month, unsigned int *day)
8994 {
8995 int _locked_by_me = FALSE;
8996
8997 DW_MUTEX_LOCK;
8998 if(GTK_IS_CALENDAR(handle))
8999 {
9000 gtk_calendar_get_date(GTK_CALENDAR(handle),year,month,day);
9001 *month = *month + 1;
9002 }
9003 DW_MUTEX_UNLOCK;
9004 return;
9005 }
9006
9007 /*
9008 * Pack windows (widgets) into a box from the start (or top).
9009 * Parameters:
9010 * box: Window handle of the box to be packed into.
9011 * item: Window handle of the item to be back.
9012 * width: Width in pixels of the item or -1 to be self determined.
9013 * height: Height in pixels of the item or -1 to be self determined.
9014 * hsize: TRUE if the window (widget) should expand horizontally to fill space given.
9015 * vsize: TRUE if the window (widget) should expand vertically to fill space given.
9016 * pad: Number of pixels of padding around the item.
9017 */
9018 void dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
9019 {
9020 int warn = FALSE, _locked_by_me = FALSE;
9021 GtkWidget *tmp, *tmpitem;
9022
9023 if ( !box )
9024 return;
9025
9026 /*
9027 * If you try and pack an item into itself VERY bad things can happen; like at least an
9028 * infinite loop on GTK! Lets be safe!
9029 */
9030 if ( box == item )
9031 {
9032 dw_messagebox( "dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!" );
9033 return;
9034 }
9035
9036 DW_MUTEX_LOCK;
9037
9038 if ((tmp = g_object_get_data(G_OBJECT(box), "_dw_boxhandle")))
9039 box = tmp;
9040
9041 if (!item)
9042 {
9043 item = gtk_label_new("");
9044 gtk_widget_show_all(item);
9045 }
9046
9047 tmpitem = (GtkWidget *)g_object_get_data(G_OBJECT(item), "_dw_boxhandle");
9048
9049 if (GTK_IS_TABLE(box))
9050 {
9051 int boxcount = (int)g_object_get_data(G_OBJECT(box), "_dw_boxcount");
9052 int boxtype = (int)g_object_get_data(G_OBJECT(box), "_dw_boxtype");
9053 int x, y;
9054
9055 /* If the item being packed is a box, then we use it's padding
9056 * instead of the padding specified on the pack line, this is
9057 * due to a bug in the OS/2 and Win32 renderer and a limitation
9058 * of the GtkTable class.
9059 */
9060 if (GTK_IS_TABLE(item) || (tmpitem && GTK_IS_TABLE(tmpitem)))
9061 {
9062 GtkWidget *eventbox = (GtkWidget *)g_object_get_data(G_OBJECT(item), "_dw_eventbox");
9063
9064 /* NOTE: I left in the ability to pack boxes with a size,
9065 * this eliminates that by forcing the size to 0.
9066 */
9067 height = width = 0;
9068
9069 if (eventbox)
9070 {
9071 int boxpad = (int)g_object_get_data(G_OBJECT(item), "_dw_boxpad");
9072 gtk_container_add(GTK_CONTAINER(eventbox), item);
9073 gtk_container_set_border_width(GTK_CONTAINER(eventbox), boxpad);
9074 item = eventbox;
9075 }
9076 }
9077 else
9078 {
9079 /* Only show warning if item is not a box */
9080 warn = TRUE;
9081 }
9082
9083 if (boxtype == DW_VERT)
9084 {
9085 x = 0;
9086 y = boxcount;
9087 gtk_table_resize(GTK_TABLE(box), boxcount + 1, 1);
9088 }
9089 else
9090 {
9091 x = boxcount;
9092 y = 0;
9093 gtk_table_resize(GTK_TABLE(box), 1, boxcount + 1);
9094 }
9095
9096 gtk_table_attach(GTK_TABLE(box), item, x, x + 1, y, y + 1, hsize ? DW_EXPAND : 0, vsize ? DW_EXPAND : 0, pad, pad);
9097 g_object_set_data(G_OBJECT(box), "_dw_boxcount", GINT_TO_POINTER(boxcount + 1));
9098 gtk_widget_set_size_request(item, width, height);
9099 if (GTK_IS_RADIO_BUTTON(item))
9100 {
9101 GSList *group;
9102 GtkWidget *groupstart = (GtkWidget *)g_object_get_data(G_OBJECT(box), "_dw_group");
9103
9104 if (groupstart)
9105 {
9106 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(groupstart));
9107 gtk_radio_button_set_group(GTK_RADIO_BUTTON(item), group);
9108 }
9109 else
9110 {
9111 g_object_set_data(G_OBJECT(box), "_dw_group", (gpointer)item);
9112 }
9113 }
9114 }
9115 else
9116 {
9117 GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
9118
9119 if (GTK_IS_TABLE(item) || (tmpitem && GTK_IS_TABLE(tmpitem)))
9120 {
9121 GtkWidget *eventbox = (GtkWidget *)g_object_get_data(G_OBJECT(item), "_dw_eventbox");
9122
9123 /* NOTE: I left in the ability to pack boxes with a size,
9124 * this eliminates that by forcing the size to 0.
9125 */
9126 height = width = 0;
9127
9128 if (eventbox)
9129 {
9130 int boxpad = (int)g_object_get_data(G_OBJECT(item), "_dw_boxpad");
9131 gtk_container_add(GTK_CONTAINER(eventbox), item);
9132 gtk_container_set_border_width(GTK_CONTAINER(eventbox), boxpad);
9133 item = eventbox;
9134 }
9135 }
9136 else
9137 {
9138 /* Only show warning if item is not a box */
9139 warn = TRUE;
9140 }
9141
9142 gtk_container_set_border_width(GTK_CONTAINER(box), pad);
9143 gtk_container_add(GTK_CONTAINER(box), vbox);
9144 gtk_box_pack_end(GTK_BOX(vbox), item, TRUE, TRUE, 0);
9145 gtk_widget_show(vbox);
9146
9147 gtk_widget_set_size_request(item, width, height);
9148 g_object_set_data(G_OBJECT(box), "_dw_user", vbox);
9149 }
9150 DW_MUTEX_UNLOCK;
9151
9152 if (warn)
9153 {
9154 if ( width == 0 && hsize == FALSE )
9155 dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item);
9156 if ( height == 0 && vsize == FALSE )
9157 dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item);
9158 }
9159 }
9160
9161 /*
9162 * Sets the default focus item for a window/dialog.
9163 * Parameters:
9164 * window: Toplevel window or dialog.
9165 * defaultitem: Handle to the dialog item to be default.
9166 */
9167 void dw_window_default(HWND window, HWND defaultitem)
9168 {
9169 int _locked_by_me = FALSE;
9170
9171 if(!window)
9172 return;
9173
9174 DW_MUTEX_LOCK;
9175 g_object_set_data(G_OBJECT(window), "_dw_defaultitem", (gpointer)defaultitem);
9176 DW_MUTEX_UNLOCK;
9177 }
9178
9179 /*
9180 * Sets window to click the default dialog item when an ENTER is pressed.
9181 * Parameters:
9182 * window: Window (widget) to look for the ENTER press.
9183 * next: Window (widget) to move to next (or click)
9184 */
9185 void dw_window_click_default(HWND window, HWND next)
9186 {
9187 int _locked_by_me = FALSE;
9188
9189 if(!window)
9190 return;
9191
9192 DW_MUTEX_LOCK;
9193 g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(_default_key_press_event), next);
9194 DW_MUTEX_UNLOCK;
9195 }
9196
9197 /*
9198 * Returns some information about the current operating environment.
9199 * Parameters:
9200 * env: Pointer to a DWEnv struct.
9201 */
9202 void dw_environment_query(DWEnv *env)
9203 {
9204 struct utsname name;
9205 char tempbuf[100];
9206 int len, z;
9207
9208 uname(&name);
9209 strcpy(env->osName, name.sysname);
9210 strcpy(tempbuf, name.release);
9211
9212 env->MajorBuild = env->MinorBuild = 0;
9213
9214 len = strlen(tempbuf);
9215
9216 strcpy(env->buildDate, __DATE__);
9217 strcpy(env->buildTime, __TIME__);
9218 env->DWMajorVersion = DW_MAJOR_VERSION;
9219 env->DWMinorVersion = DW_MINOR_VERSION;
9220 env->DWSubVersion = DW_SUB_VERSION;
9221
9222 for(z=1;z<len;z++)
9223 {
9224 if(tempbuf[z] == '.')
9225 {
9226 tempbuf[z] = '\0';
9227 env->MajorVersion = atoi(&tempbuf[z-1]);
9228 env->MinorVersion = atoi(&tempbuf[z+1]);
9229 return;
9230 }
9231 }
9232 env->MajorVersion = atoi(tempbuf);
9233 env->MinorVersion = 0;
9234 }
9235
9236 /*
9237 * Opens a file dialog and queries user selection.
9238 * Parameters:
9239 * title: Title bar text for dialog.
9240 * defpath: The default path of the open dialog.
9241 * ext: Default file extention.
9242 * flags: DW_FILE_OPEN or DW_FILE_SAVE or DW_DIRECTORY_OPEN
9243 * Returns:
9244 * NULL on error. A malloced buffer containing
9245 * the file path on success.
9246 *
9247 */
9248 char *dw_file_browse(char *title, char *defpath, char *ext, int flags)
9249 {
9250 GtkWidget *filew;
9251
9252 GtkFileChooserAction action;
9253 GtkFileFilter *filter1 = NULL;
9254 GtkFileFilter *filter2 = NULL;
9255 gchar *button;
9256 char *filename = NULL;
9257 char buf[1000];
9258 char mypath[PATH_MAX+1];
9259 char cwd[PATH_MAX+1];
9260
9261 switch (flags )
9262 {
9263 case DW_DIRECTORY_OPEN:
9264 action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
9265 button = GTK_STOCK_OPEN;
9266 break;
9267 case DW_FILE_OPEN:
9268 action = GTK_FILE_CHOOSER_ACTION_OPEN;
9269 button = GTK_STOCK_OPEN;
9270 break;
9271 case DW_FILE_SAVE:
9272 action = GTK_FILE_CHOOSER_ACTION_SAVE;
9273 button = GTK_STOCK_SAVE;
9274 break;
9275 default:
9276 dw_messagebox( "Coding error", DW_MB_OK|DW_MB_ERROR, "dw_file_browse() flags argument invalid.");
9277 return NULL;
9278 break;
9279 }
9280
9281 filew = gtk_file_chooser_dialog_new ( title,
9282 NULL,
9283 action,
9284 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
9285 button, GTK_RESPONSE_ACCEPT,
9286 NULL);
9287
9288 if ( flags == DW_FILE_SAVE )
9289 gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER( filew ), TRUE );
9290
9291 if ( ext )
9292 {
9293 filter1 = gtk_file_filter_new();
9294 sprintf( buf, "*.%s", ext );
9295 gtk_file_filter_add_pattern( filter1, (gchar *)buf );
9296 sprintf( buf, "\"%s\" files", ext );
9297 gtk_file_filter_set_name( filter1, (gchar *)buf );
9298 filter2 = gtk_file_filter_new();
9299 gtk_file_filter_add_pattern( filter2, (gchar *)"*" );
9300 gtk_file_filter_set_name( filter2, (gchar *)"All Files" );
9301 gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( filew ), filter1 );
9302 gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( filew ), filter2 );
9303 }
9304
9305 if ( defpath )
9306 {
9307 if ( g_path_is_absolute( defpath ) )
9308 {
9309 strcpy( mypath, defpath );
9310 }
9311 else
9312 {
9313 if ( !getcwd(cwd, PATH_MAX ) )
9314 {
9315 }
9316 else
9317 {
9318 if ( rel2abs( defpath, cwd, mypath, PATH_MAX ) )
9319 {
9320 }
9321 }
9322 }
9323 gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( filew ), mypath );
9324 }
9325
9326 if ( gtk_dialog_run( GTK_DIALOG( filew ) ) == GTK_RESPONSE_ACCEPT )
9327 {
9328 filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( filew ) );
9329 /*g_free (filename);*/
9330 }
9331
9332 gtk_widget_destroy( filew );
9333 return filename;
9334 }
9335
9336
9337 /*
9338 * Execute and external program in a seperate session.
9339 * Parameters:
9340 * program: Program name with optional path.
9341 * type: Either DW_EXEC_CON or DW_EXEC_GUI.
9342 * params: An array of pointers to string arguements.
9343 * Returns:
9344 * -1 on error.
9345 */
9346 int dw_exec(char *program, int type, char **params)
9347 {
9348 int ret = -1;
9349
9350 if((ret = fork()) == 0)
9351 {
9352 int i;
9353
9354 for (i = 3; i < 256; i++)
9355 close(i);
9356 setsid();
9357 if(type == DW_EXEC_GUI)
9358 {
9359 execvp(program, params);
9360 }
9361 else if(type == DW_EXEC_CON)
9362 {
9363 char **tmpargs;
9364
9365 if(!params)
9366 {
9367 tmpargs = malloc(sizeof(char *));
9368 tmpargs[0] = NULL;
9369 }
9370 else
9371 {
9372 int z = 0;
9373
9374 while(params[z])
9375 {
9376 z++;
9377 }
9378 tmpargs = malloc(sizeof(char *)*(z+3));
9379 z=0;
9380 tmpargs[0] = "xterm";
9381 tmpargs[1] = "-e";
9382 while(params[z])
9383 {
9384 tmpargs[z+2] = params[z];
9385 z++;
9386 }
9387 tmpargs[z+2] = NULL;
9388 }
9389 execvp("xterm", tmpargs);
9390 free(tmpargs);
9391 }
9392 /* If we got here exec failed */
9393 _exit(-1);
9394 }
9395 return ret;
9396 }
9397
9398 /*
9399 * Loads a web browser pointed at the given URL.
9400 * Parameters:
9401 * url: Uniform resource locator.
9402 */
9403 int dw_browse(char *url)
9404 {
9405 /* Is there a way to find the webbrowser in Unix? */
9406 char *execargs[3], *browser = "netscape", *tmp;
9407
9408 tmp = getenv( "DW_BROWSER" );
9409 if(tmp) browser = tmp;
9410 execargs[0] = browser;
9411 execargs[1] = url;
9412 execargs[2] = NULL;
9413
9414 return dw_exec(browser, DW_EXEC_GUI, execargs);
9415 }
9416
9417 /*
9418 * Causes the embedded HTML widget to take action.
9419 * Parameters:
9420 * handle: Handle to the window.
9421 * action: One of the DW_HTML_* constants.
9422 */
9423 void dw_html_action(HWND handle, int action)
9424 {
9425 #ifdef USE_GTKMOZEMBED
9426 int _locked_by_me = FALSE;
9427
9428 if(!_gtk_moz_embed_new)
9429 return;
9430
9431 DW_MUTEX_LOCK;
9432 switch(action)
9433 {
9434 case DW_HTML_GOBACK:
9435 _gtk_moz_embed_go_back(GTK_MOZ_EMBED(handle));
9436 break;
9437 case DW_HTML_GOFORWARD:
9438 _gtk_moz_embed_go_forward(GTK_MOZ_EMBED(handle));
9439 break;
9440 case DW_HTML_GOHOME:
9441 _gtk_moz_embed_load_url(GTK_MOZ_EMBED(handle), "http://dwindows.netlabs.org");
9442 break;
9443 case DW_HTML_RELOAD:
9444 _gtk_moz_embed_reload(GTK_MOZ_EMBED(handle), 0);
9445 break;
9446 case DW_HTML_STOP:
9447 _gtk_moz_embed_stop_load(GTK_MOZ_EMBED(handle));
9448 break;
9449 }
9450 DW_MUTEX_UNLOCK;
9451 #elif defined(USE_WEBKIT)
9452 int _locked_by_me = FALSE;
9453 WebKitWebView *web_view;
9454 WebKitWebFrame *frame;
9455
9456 if (!_webkit_web_view_open)
9457 return;
9458
9459 DW_MUTEX_LOCK;
9460 web_view = (WebKitWebView *)g_object_get_data(G_OBJECT(handle), "_dw_web_view");
9461 if ( web_view )
9462 {
9463 switch( action )
9464 {
9465 case DW_HTML_GOBACK:
9466 _webkit_web_view_go_back( web_view );
9467 break;
9468 case DW_HTML_GOFORWARD:
9469 _webkit_web_view_go_forward( web_view );
9470 break;
9471 case DW_HTML_GOHOME:
9472 _webkit_web_view_open( web_view, "http://dwindows.netlabs.org" );
9473 break;
9474 case DW_HTML_RELOAD:
9475 _webkit_web_view_reload( web_view );
9476 break;
9477 case DW_HTML_STOP:
9478 _webkit_web_view_stop_loading( web_view );
9479 break;
9480 # ifdef WEBKIT_CHECK_VERSION
9481 # if WEBKIT_CHECK_VERSION(1,1,5)
9482 case DW_HTML_PRINT:
9483 frame = _webkit_web_view_get_focused_frame( web_view );
9484 _webkit_web_frame_print( frame );
9485 break;
9486 # endif
9487 # endif
9488 }
9489 }
9490 DW_MUTEX_UNLOCK;
9491 #endif
9492 }
9493
9494 #ifdef USE_LIBGTKHTML2
9495 void _dw_html_render_data( HWND handle, char *string, int i )
9496 {
9497 HtmlDocument *document;
9498
9499 html_view_set_document (HTML_VIEW(handle), NULL);
9500 document = (HtmlDocument *)g_object_get_data(G_OBJECT(handle), "_dw_html_document" );
9501 /* html_document_clear (document);*/
9502 if ( document )
9503 {
9504 html_view_set_document (HTML_VIEW(handle), document);
9505 if ( html_document_open_stream( document, "text/html" ) )
9506 {
9507 html_document_write_stream( document, string, i );
9508 }
9509 html_document_close_stream (document);
9510 }
9511 }
9512 #endif
9513 /*
9514 * Render raw HTML code in the embedded HTML widget..
9515 * Parameters:
9516 * handle: Handle to the window.
9517 * string: String buffer containt HTML code to
9518 * be rendered.
9519 * Returns:
9520 * 0 on success.
9521 */
9522 int dw_html_raw(HWND handle, char *string)
9523 {
9524 #ifdef USE_GTKMOZEMBED
9525 int _locked_by_me = FALSE;
9526
9527 if (!_gtk_moz_embed_new)
9528 return -1;
9529
9530 DW_MUTEX_LOCK;
9531 _gtk_moz_embed_render_data(GTK_MOZ_EMBED(handle), string, strlen(string), "file:///", "text/html");
9532 gtk_widget_show(GTK_WIDGET(handle));
9533 DW_MUTEX_UNLOCK;
9534 return 0;
9535 #elif defined(USE_LIBGTKHTML2)
9536 int _locked_by_me = FALSE;
9537
9538 if ( !_html_document_new )
9539 return -1;
9540
9541 DW_MUTEX_LOCK;
9542 _dw_html_render_data( handle, string, strlen(string) );
9543 gtk_widget_show( GTK_WIDGET(handle) );
9544 DW_MUTEX_UNLOCK;
9545 return 0;
9546 #elif defined(USE_WEBKIT)
9547 int _locked_by_me = FALSE;
9548 WebKitWebView *web_view;
9549
9550 if (!_webkit_web_view_open)
9551 return -1;
9552
9553 DW_MUTEX_LOCK;
9554 web_view = (WebKitWebView *)g_object_get_data(G_OBJECT(handle), "_dw_web_view");
9555 if ( web_view )
9556 {
9557 _webkit_web_view_load_html_string( web_view, string, "file:///");
9558 gtk_widget_show( GTK_WIDGET(handle) );
9559 }
9560 DW_MUTEX_UNLOCK;
9561 return 0;
9562 #endif
9563 return -1;
9564 }
9565
9566 /*
9567 * Render file or web page in the embedded HTML widget..
9568 * Parameters:
9569 * handle: Handle to the window.
9570 * url: Universal Resource Locator of the web or
9571 * file object to be rendered.
9572 * Returns:
9573 * 0 on success.
9574 */
9575 int dw_html_url(HWND handle, char *url)
9576 {
9577 #ifdef USE_GTKMOZEMBED
9578 int _locked_by_me = FALSE;
9579
9580 if (!_gtk_moz_embed_new)
9581 return -1;
9582
9583 DW_MUTEX_LOCK;
9584 _gtk_moz_embed_load_url( GTK_MOZ_EMBED(handle), url );
9585 gtk_widget_show(GTK_WIDGET(handle));
9586 DW_MUTEX_UNLOCK;
9587 return 0;
9588 #elif defined( USE_WEBKIT )
9589 int _locked_by_me = FALSE;
9590 WebKitWebView *web_view;
9591
9592 if (!_webkit_web_view_open)
9593 return -1;
9594
9595 DW_MUTEX_LOCK;
9596 web_view = (WebKitWebView *)g_object_get_data(G_OBJECT(handle), "_dw_web_view");
9597 if ( web_view )
9598 {
9599 _webkit_web_view_open( web_view, url );
9600 gtk_widget_show(GTK_WIDGET(handle));
9601 }
9602 DW_MUTEX_UNLOCK;
9603 return 0;
9604 #endif
9605 return -1;
9606 }
9607
9608 #ifdef USE_GTKMOZEMBED
9609 /*
9610 * Callback for a HTML widget when the "Forward" menu item is selected
9611 */
9612 static int _dw_html_forward_callback(HWND window, void *data)
9613 {
9614 HWND handle=(HWND)data;
9615 dw_html_action( handle, DW_HTML_GOFORWARD );
9616 return TRUE;
9617 }
9618
9619 /*
9620 * Callback for a HTML widget when the "Back" menu item is selected
9621 */
9622 static int _dw_html_backward_callback(HWND window, void *data)
9623 {
9624 HWND handle=(HWND)data;
9625 dw_html_action( handle, DW_HTML_GOBACK );
9626 return TRUE;
9627 }
9628
9629 /*
9630 * Callback for a HTML widget when the "Reload" menu item is selected
9631 */
9632 static int _dw_html_reload_callback(HWND window, void *data)
9633 {
9634 HWND handle=(HWND)data;
9635 dw_html_action( handle, DW_HTML_RELOAD );
9636 return TRUE;
9637 }
9638
9639 /*
9640 * Callback for a HTML widget when a page has completed loading
9641 * Once the page has finished loading, show the widget.
9642 */
9643 void _dw_html_net_stop_cb( GtkMozEmbed *embed, gpointer data )
9644 {
9645 gtk_widget_show(GTK_WIDGET(data));
9646 }
9647
9648 /*
9649 * Callback for a HTML widget when a mouse button is clicked inside the widget
9650 * If the right mouse button is clicked, popup a context menu
9651 */
9652 static gint _dw_dom_mouse_click_cb (GtkMozEmbed *dummy, gpointer dom_event, gpointer embed)
9653 {
9654 gint button,rc;
9655 glong x,y;
9656 int flags;
9657
9658 button = mozilla_get_mouse_event_button( dom_event );
9659 if ( button == 2 )
9660 {
9661 HWND menuitem;
9662 HMENUI popup;
9663 /*
9664 * Right mouse button; display context menu
9665 */
9666 rc = mozilla_get_mouse_location( dom_event, &x, &y);
9667 popup = dw_menu_new( 0 );
9668 if ( _gtk_moz_embed_can_go_forward(GTK_MOZ_EMBED(embed) ) )
9669 flags = DW_MIS_ENABLED;
9670 else
9671 flags = DW_MIS_DISABLED;
9672 menuitem = dw_menu_append_item( popup, "Forward", 1, flags, TRUE, FALSE, 0 );
9673 dw_signal_connect( menuitem, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_html_forward_callback), embed );
9674
9675 if ( _gtk_moz_embed_can_go_back(GTK_MOZ_EMBED(embed) ) )
9676 flags = DW_MIS_ENABLED;
9677 else
9678 flags = DW_MIS_DISABLED;
9679 menuitem = dw_menu_append_item( popup, "Back", 2, flags, TRUE, FALSE, 0 );
9680 dw_signal_connect( menuitem, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_html_backward_callback), embed );
9681
9682 dw_menu_append_item( popup, DW_MENU_SEPARATOR, 99, 0, TRUE, FALSE, 0 );
9683
9684 menuitem = dw_menu_append_item( popup, "Reload", 3, 0, TRUE, FALSE, 0 );
9685 dw_signal_connect( menuitem, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_html_reload_callback), embed );
9686
9687 dw_menu_popup( &popup, embed, x, y );
9688 rc = TRUE;
9689 }
9690 else
9691 {
9692 rc = FALSE;
9693 }
9694 return rc;
9695 }
9696 #endif
9697
9698 #ifdef USE_LIBGTKHTML2
9699 static gboolean dom_mouse_down( HtmlDocument *doc, DomMouseEvent *event, gpointer data )
9700 {
9701 fprintf(stderr,"mouse down\n");
9702 return TRUE;
9703 }
9704 static gboolean dom_mouse_up( HtmlDocument *doc, DomMouseEvent *event, gpointer data )
9705 {
9706 fprintf(stderr,"mouse up\n");
9707 return TRUE;
9708 }
9709 static gboolean dom_mouse_click( HtmlDocument *doc, DomMouseEvent *event, gpointer data )
9710 {
9711 fprintf(stderr,"mouse click\n");
9712 return TRUE;
9713 }
9714 static gboolean url_requested (HtmlDocument *doc, const gchar *url, HtmlStream *stream)
9715 {
9716 fprintf(stderr,"URL IS REQUESTED: %s\n",url);
9717 return TRUE;
9718 }
9719 static void link_clicked (HtmlDocument *doc, const gchar *url)
9720 {
9721 fprintf(stderr,"link clicked: %s!\n", url);
9722 }
9723 #endif
9724
9725 #ifdef USE_WEBKIT
9726 # ifdef WEBKIT_CHECK_VERSION
9727 # if WEBKIT_CHECK_VERSION(1,1,5)
9728 static void _dw_html_print_cb( GtkWidget *widget, gpointer *data )
9729 {
9730 WebKitWebView *web_view = DW_WEBKIT_WEB_VIEW(data);
9731 WebKitWebFrame *frame;
9732
9733 frame = _webkit_web_view_get_focused_frame( web_view );
9734 _webkit_web_frame_print( frame );
9735 }
9736 /*
9737 * Fired when the user right-clicks to get the popup-menu on the HTML widget
9738 * We add a "Print" menu item to enable printing
9739 * user_data is not used
9740 */
9741 static void _dw_html_populate_popup_cb( WebKitWebView *web_view, GtkMenu *menu, gpointer user_data )
9742 {
9743 GtkWidget *image = gtk_image_new_from_stock( GTK_STOCK_PRINT, GTK_ICON_SIZE_MENU );
9744 GtkWidget *item = gtk_image_menu_item_new_with_label( "Print" );
9745
9746 gtk_image_menu_item_set_image( GTK_IMAGE_MENU_ITEM(item), image );
9747 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
9748 g_signal_connect( item, "activate", G_CALLBACK(_dw_html_print_cb), web_view );
9749 gtk_widget_show(item);
9750 }
9751 # endif
9752 # endif
9753 #endif
9754
9755 /*
9756 * Create a new Entryfield window (widget) to be packed.
9757 * Parameters:
9758 * text: The default text to be in the entryfield widget.
9759 * id: An ID to be used with dw_window_from_id() or 0L.
9760 */
9761 HWND dw_html_new(unsigned long id)
9762 {
9763 GtkWidget *widget,*stext;
9764 int _locked_by_me = FALSE;
9765
9766 DW_MUTEX_LOCK;
9767 #ifdef USE_GTKMOZEMBED
9768 if (!_gtk_moz_embed_new)
9769 {
9770 widget = dw_box_new(DW_HORZ, 0);
9771 stext = dw_text_new( "HTML widget not available; you do not have access to gtkmozembed.", 0);
9772 dw_box_pack_start(widget, stext, 0, 0, TRUE, TRUE, 10);
9773 }
9774 else
9775 {
9776 widget = _gtk_moz_embed_new();
9777 /*
9778 * Connect some signals
9779 */
9780 g_signal_connect( G_OBJECT(widget), "net-stop", G_CALLBACK(_dw_html_net_stop_cb), widget );
9781 g_signal_connect( G_OBJECT(widget), "dom_mouse_click", G_CALLBACK(_dw_dom_mouse_click_cb), widget );
9782 }
9783 #elif defined(USE_LIBGTKHTML2)
9784 if ( !_html_document_new )
9785 {
9786 widget = dw_box_new(DW_HORZ, 0);
9787 stext = dw_text_new( "HTML widget not available; you do not have access to libgtkhtml-2.", 0);
9788 dw_box_pack_start(widget, stext, 0, 0, TRUE, TRUE, 10);
9789 }
9790 else
9791 {
9792 HtmlDocument *document;
9793 document = html_document_new ();
9794 g_signal_connect (G_OBJECT (document), "dom_mouse_down", G_CALLBACK (dom_mouse_down), NULL);
9795 g_signal_connect (G_OBJECT (document), "dom_mouse_up", G_CALLBACK (dom_mouse_up), NULL);
9796 g_signal_connect (G_OBJECT (document), "dom_mouse_click", G_CALLBACK (dom_mouse_click), NULL);
9797 g_signal_connect (G_OBJECT (document), "request_url", G_CALLBACK (url_requested), NULL);
9798 g_signal_connect (G_OBJECT (document), "link_clicked", G_CALLBACK (link_clicked), NULL);
9799 widget = _html_view_new();
9800 g_object_set_data(G_OBJECT(widget), "_dw_html_document", (gpointer)document);
9801 }
9802 #elif defined(USE_WEBKIT)
9803 if (!_webkit_web_view_open)
9804 {
9805 widget = dw_box_new(DW_HORZ, 0);
9806 stext = dw_text_new( "HTML widget not available; you do not have access to webkit.", 0);
9807 dw_box_pack_start(widget, stext, 0, 0, TRUE, TRUE, 10);
9808 }
9809 else
9810 {
9811 WebKitWebView *web_view;
9812 widget = gtk_scrolled_window_new (NULL, NULL);
9813 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW (widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
9814 web_view = (WebKitWebView *)_webkit_web_view_new();
9815 /* web_view = WEBKIT_WEB_VIEW(_webkit_web_view_new() ); */
9816 gtk_container_add( GTK_CONTAINER (widget), GTK_WIDGET(web_view) );
9817 gtk_widget_show( GTK_WIDGET(web_view) );
9818 g_object_set_data(G_OBJECT(widget), "_dw_web_view", (gpointer)web_view);
9819 # ifdef WEBKIT_CHECK_VERSION
9820 # if WEBKIT_CHECK_VERSION(1,1,5)
9821 g_signal_connect( web_view, "populate-popup", G_CALLBACK(_dw_html_populate_popup_cb), NULL );
9822 # endif
9823 # endif
9824 }
9825 #else
9826 widget = dw_box_new(DW_HORZ, 0);
9827 stext = dw_text_new( "HTML widget not available; you do not have access to gtkmozembed.", 0);
9828 dw_box_pack_start(widget, stext, 0, 0, TRUE, TRUE, 10);
9829 #endif
9830 gtk_widget_show(widget);
9831 DW_MUTEX_UNLOCK;
9832 return widget;
9833 }
9834
9835 /*
9836 * Gets the contents of the default clipboard as text.
9837 * Parameters:
9838 * None.
9839 * Returns:
9840 * Pointer to an allocated string of text or NULL if clipboard empty or contents could not
9841 * be converted to text.
9842 */
9843 char *dw_clipboard_get_text()
9844 {
9845 int _locked_by_me = FALSE, index = _find_thread_index(dw_thread_id());
9846
9847 DW_MUTEX_LOCK;
9848 if ( _clipboard_object[index] == NULL )
9849 {
9850 _clipboard_object[index] = gtk_clipboard_get( GDK_SELECTION_CLIPBOARD );
9851 }
9852 if ( _clipboard_contents[index] != NULL )
9853 {
9854 g_free( _clipboard_contents[index] );
9855 }
9856 _clipboard_contents[index] = gtk_clipboard_wait_for_text( _clipboard_object[index] );
9857 DW_MUTEX_UNLOCK;
9858 return (char *)_clipboard_contents[index];
9859 }
9860
9861 /*
9862 * Sets the contents of the default clipboard to the supplied text.
9863 * Parameters:
9864 * Text.
9865 */
9866 void dw_clipboard_set_text( char *str, int len )
9867 {
9868 int _locked_by_me = FALSE, index = _find_thread_index(dw_thread_id());
9869
9870 DW_MUTEX_LOCK;
9871 if ( _clipboard_object[index] == NULL )
9872 {
9873 _clipboard_object[index] = gtk_clipboard_get( GDK_SELECTION_CLIPBOARD );
9874 }
9875 gtk_clipboard_set_text( _clipboard_object[index], str, len );
9876 DW_MUTEX_UNLOCK;
9877 }
9878
9879 /*
9880 * Returns a pointer to a static buffer which containes the
9881 * current user directory. Or the root directory (C:\ on
9882 * OS/2 and Windows).
9883 */
9884 char *dw_user_dir(void)
9885 {
9886 static char _user_dir[1024] = "";
9887
9888 if(!_user_dir[0])
9889 {
9890 char *home = getenv("HOME");
9891
9892 if(home)
9893 strcpy(_user_dir, home);
9894 else
9895 strcpy(_user_dir, "/");
9896 }
9897 return _user_dir;
9898 }
9899
9900 /*
9901 * Call a function from the window (widget)'s context.
9902 * Parameters:
9903 * handle: Window handle of the widget.
9904 * function: Function pointer to be called.
9905 * data: Pointer to the data to be passed to the function.
9906 */
9907 void dw_window_function(HWND handle, void *function, void *data)
9908 {
9909 void (* windowfunc)(void *);
9910
9911 windowfunc = function;
9912
9913 if(windowfunc)
9914 windowfunc(data);
9915 }
9916
9917 /*
9918 * Add a named user data item to a window handle.
9919 * Parameters:
9920 * window: Window handle of signal to be called back.
9921 * dataname: A string pointer identifying which signal to be hooked.
9922 * data: User data to be passed to the handler function.
9923 */
9924 void dw_window_set_data(HWND window, char *dataname, void *data)
9925 {
9926 int _locked_by_me = FALSE;
9927
9928 if(!window)
9929 return;
9930
9931 DW_MUTEX_LOCK;
9932 if(GTK_IS_SCROLLED_WINDOW(window))
9933 {
9934 HWND thiswindow = (HWND)g_object_get_data(G_OBJECT(window), "_dw_user");
9935
9936 if(thiswindow && G_IS_OBJECT(thiswindow))
9937 g_object_set_data(G_OBJECT(thiswindow), dataname, (gpointer)data);
9938 #if 0
9939 if(GTK_IS_COMBO_BOX(window))
9940 g_object_set_data(G_OBJECT(GTK_COMBO_BOX(window)->entry), dataname, (gpointer)data);
9941 #endif
9942 g_object_set_data(G_OBJECT(window), dataname, (gpointer)data);
9943 }
9944 DW_MUTEX_UNLOCK;
9945 }
9946
9947 /*
9948 * Gets a named user data item to a window handle.
9949 * Parameters:
9950 * window: Window handle of signal to be called back.
9951 * dataname: A string pointer identifying which signal to be hooked.
9952 * data: User data to be passed to the handler function.
9953 */
9954 void *dw_window_get_data(HWND window, char *dataname)
9955 {
9956 int _locked_by_me = FALSE;
9957 void *ret = NULL;
9958
9959 if(!window)
9960 return NULL;
9961
9962 DW_MUTEX_LOCK;
9963 if(G_IS_OBJECT(window))
9964 ret = (void *)g_object_get_data(G_OBJECT(window), dataname);
9965 DW_MUTEX_UNLOCK;
9966 return ret;
9967 }
9968
9969 /*
9970 * Add a callback to a timer event.
9971 * Parameters:
9972 * interval: Milliseconds to delay between calls.
9973 * sigfunc: The pointer to the function to be used as the callback.
9974 * data: User data to be passed to the handler function.
9975 * Returns:
9976 * Timer ID for use with dw_timer_disconnect(), 0 on error.
9977 */
9978 int API dw_timer_connect(int interval, void *sigfunc, void *data)
9979 {
9980 int tag, _locked_by_me = FALSE;
9981
9982 DW_MUTEX_LOCK;
9983 tag = g_timeout_add(interval, (GSourceFunc)sigfunc, data);
9984 DW_MUTEX_UNLOCK;
9985 return tag;
9986 }
9987
9988 /*
9989 * Removes timer callback.
9990 * Parameters:
9991 * id: Timer ID returned by dw_timer_connect().
9992 */
9993 void API dw_timer_disconnect(int id)
9994 {
9995 #if 0 /* TODO: Can't remove by ID anymore apparently...
9996 * need to rewrite it to return FALSE from the signal handler to stop.
9997 */
9998 int _locked_by_me = FALSE;
9999
10000 DW_MUTEX_LOCK;
10001 g_timeout_remove(id);
10002 DW_MUTEX_UNLOCK;
10003 #endif
10004 }
10005
10006 /* Get the actual signal window handle not the user window handle
10007 * Should mimic the code in dw_signal_connect() below.
10008 */
10009 static HWND _find_signal_window(HWND window, char *signame)
10010 {
10011 HWND thiswindow = window;
10012
10013 if(GTK_IS_SCROLLED_WINDOW(thiswindow))
10014 thiswindow = (HWND)g_object_get_data(G_OBJECT(window), "_dw_user");
10015 #if 0
10016 else if(GTK_IS_COMBO_BOX(thiswindow) && signame && strcmp(signame, DW_SIGNAL_LIST_SELECT) == 0)
10017 thiswindow = GTK_COMBO_BOX(thiswindow)->list;
10018 else if(GTK_IS_COMBO_BOX(thiswindow) && signame && strcmp(signame, DW_SIGNAL_SET_FOCUS) == 0)
10019 thiswindow = GTK_COMBO_BOX(thiswindow)->entry;
10020 #endif
10021 else if(GTK_IS_VSCALE(thiswindow) || GTK_IS_HSCALE(thiswindow) ||
10022 GTK_IS_VSCROLLBAR(thiswindow) || GTK_IS_HSCROLLBAR(thiswindow) ||
10023 GTK_IS_SPIN_BUTTON(thiswindow))
10024 thiswindow = (GtkWidget *)g_object_get_data(G_OBJECT(thiswindow), "_dw_adjustment");
10025 else if(GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_SELECT) == 0)
10026 thiswindow = (GtkWidget *)gtk_tree_view_get_selection(GTK_TREE_VIEW(thiswindow));
10027 return thiswindow;
10028 }
10029
10030 /*
10031 * Add a callback to a window event.
10032 * Parameters:
10033 * window: Window handle of signal to be called back.
10034 * signame: A string pointer identifying which signal to be hooked.
10035 * sigfunc: The pointer to the function to be used as the callback.
10036 * data: User data to be passed to the handler function.
10037 */
10038 void dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
10039 {
10040 void *thisfunc = _findsigfunc(signame);
10041 char *thisname = signame;
10042 HWND thiswindow = window;
10043 int sigid, _locked_by_me = FALSE;
10044 gint cid;
10045
10046 DW_MUTEX_LOCK;
10047 /*
10048 * If the window we are setting the signal on is a scrolled window we need to get
10049 * the "real" widget type. thiswindow is the "real" widget type
10050 */
10051 if (GTK_IS_SCROLLED_WINDOW(thiswindow))
10052 {
10053 thiswindow = (HWND)g_object_get_data(G_OBJECT(window), "_dw_user");
10054 }
10055
10056 if (GTK_IS_MENU_ITEM(thiswindow) && strcmp(signame, DW_SIGNAL_CLICKED) == 0)
10057 {
10058 thisname = "activate";
10059 thisfunc = _findsigfunc(thisname);
10060 }
10061 else if (GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_CONTEXT) == 0)
10062 {
10063 thisfunc = _findsigfunc("tree-context");
10064
10065 sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
10066 cid = g_signal_connect(G_OBJECT(thiswindow), "button_press_event", G_CALLBACK(thisfunc), (gpointer)sigid);
10067 _set_signal_handler_id(thiswindow, sigid, cid);
10068
10069 #if 0
10070 sigid = _set_signal_handler(window, window, sigfunc, data, thisfunc);
10071 cid = g_signal_connect(G_OBJECT(window), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), (gpointer)sigid);
10072 _set_signal_handler_id(window, sigid, cid);
10073 #endif
10074
10075 DW_MUTEX_UNLOCK;
10076 return;
10077 }
10078 else if (GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_SELECT) == 0)
10079 {
10080 GtkWidget *treeview = thiswindow;
10081
10082 thiswindow = (GtkWidget *)gtk_tree_view_get_selection(GTK_TREE_VIEW(thiswindow));
10083 thisname = "changed";
10084
10085 sigid = _set_signal_handler(treeview, window, sigfunc, data, thisfunc);
10086 cid = g_signal_connect(G_OBJECT(thiswindow), thisname, (GCallback)thisfunc, (gpointer)sigid);
10087 _set_signal_handler_id(treeview, sigid, cid);
10088 DW_MUTEX_UNLOCK;
10089 return;
10090 }
10091 else if (GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_TREE_EXPAND) == 0)
10092 {
10093 thisname = "row-expanded";
10094 }
10095 #if 0
10096 else if (GTK_IS_CLIST(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_ENTER) == 0)
10097 {
10098 sigid = _set_signal_handler(thiswindow, window, sigfunc, data, _container_enter_event);
10099 cid = g_signal_connect(G_OBJECT(thiswindow), "key_press_event", GTK_SIGNAL_FUNC(_container_enter_event), (gpointer)sigid);
10100 _set_signal_handler_id(thiswindow, sigid, cid);
10101
10102 thisname = "button_press_event";
10103 thisfunc = _findsigfunc(DW_SIGNAL_ITEM_ENTER);
10104 }
10105 else if (GTK_IS_CLIST(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_SELECT) == 0)
10106 {
10107 thisname = "select_row";
10108 thisfunc = (void *)_container_select_row;
10109 }
10110 else if (GTK_IS_CLIST(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_CONTEXT) == 0)
10111 {
10112 thisname = "button_press_event";
10113 thisfunc = _findsigfunc(DW_SIGNAL_ITEM_CONTEXT);
10114 }
10115 else if (GTK_IS_CLIST(thiswindow) && strcmp(signame, DW_SIGNAL_COLUMN_CLICK) == 0)
10116 {
10117 thisname = "click-column";
10118 }
10119 else if (GTK_IS_COMBO_BOX(thiswindow) && strcmp(signame, DW_SIGNAL_LIST_SELECT) == 0)
10120 {
10121 thisname = "select_child";
10122 thiswindow = GTK_COMBO_BOX(thiswindow)->list;
10123 }
10124 else if (GTK_IS_LIST(thiswindow) && strcmp(signame, DW_SIGNAL_LIST_SELECT) == 0)
10125 {
10126 thisname = "select_child";
10127 }
10128 else if (strcmp(signame, DW_SIGNAL_SET_FOCUS) == 0)
10129 {
10130 thisname = "focus-in-event";
10131 if (GTK_IS_COMBO_BOX(thiswindow))
10132 thiswindow = GTK_COMBO_BOX(thiswindow)->entry;
10133 }
10134 #endif
10135 #if 0
10136 else if (strcmp(signame, DW_SIGNAL_LOSE_FOCUS) == 0)
10137 {
10138 thisname = "focus-out-event";
10139 if(GTK_IS_COMBO_BOX(thiswindow))
10140 thiswindow = GTK_COMBO_BOX(thiswindow)->entry;
10141 }
10142 #endif
10143 else if (GTK_IS_VSCALE(thiswindow) || GTK_IS_HSCALE(thiswindow) ||
10144 GTK_IS_VSCROLLBAR(thiswindow) || GTK_IS_HSCROLLBAR(thiswindow) ||
10145 GTK_IS_SPIN_BUTTON(thiswindow) )
10146 {
10147 thiswindow = (GtkWidget *)g_object_get_data(G_OBJECT(thiswindow), "_dw_adjustment");
10148 }
10149 else if (GTK_IS_NOTEBOOK(thiswindow) && strcmp(signame, DW_SIGNAL_SWITCH_PAGE) == 0)
10150 {
10151 thisname = "switch-page";
10152 }
10153
10154 if (!thisfunc || !thiswindow)
10155 {
10156 DW_MUTEX_UNLOCK;
10157 return;
10158 }
10159
10160 sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
10161 cid = g_signal_connect(G_OBJECT(thiswindow), thisname, G_CALLBACK(thisfunc),(gpointer)sigid);
10162 _set_signal_handler_id(thiswindow, sigid, cid);
10163 DW_MUTEX_UNLOCK;
10164 }
10165
10166 /*
10167 * Removes callbacks for a given window with given name.
10168 * Parameters:
10169 * window: Window handle of callback to be removed.
10170 */
10171 void dw_signal_disconnect_by_name(HWND window, char *signame)
10172 {
10173 HWND thiswindow;
10174 int z, count;
10175 void *thisfunc;
10176 int _locked_by_me = FALSE;
10177
10178 DW_MUTEX_LOCK;
10179 thiswindow = _find_signal_window(window, signame);
10180 count = (int)g_object_get_data(G_OBJECT(thiswindow), "_dw_sigcounter");
10181 thisfunc = _findsigfunc(signame);
10182
10183 for(z=0;z<count;z++)
10184 {
10185 SignalHandler sh = _get_signal_handler(thiswindow, (gpointer)z);
10186
10187 if(sh.intfunc == thisfunc)
10188 _remove_signal_handler(thiswindow, z);
10189 }
10190 DW_MUTEX_UNLOCK;
10191 }
10192
10193 /*
10194 * Removes all callbacks for a given window.
10195 * Parameters:
10196 * window: Window handle of callback to be removed.
10197 */
10198 void dw_signal_disconnect_by_window(HWND window)
10199 {
10200 HWND thiswindow;
10201 int z, count;
10202 int _locked_by_me = FALSE;
10203
10204 DW_MUTEX_LOCK;
10205 thiswindow = _find_signal_window(window, NULL);
10206 count = (int)g_object_get_data(G_OBJECT(thiswindow), "_dw_sigcounter");
10207
10208 for(z=0;z<count;z++)
10209 _remove_signal_handler(thiswindow, z);
10210 g_object_set_data(G_OBJECT(thiswindow), "_dw_sigcounter", NULL);
10211 DW_MUTEX_UNLOCK;
10212 }
10213
10214 /*
10215 * Removes all callbacks for a given window with specified data.
10216 * Parameters:
10217 * window: Window handle of callback to be removed.
10218 * data: Pointer to the data to be compared against.
10219 */
10220 void dw_signal_disconnect_by_data(HWND window, void *data)
10221 {
10222 HWND thiswindow;
10223 int z, count;
10224 int _locked_by_me = FALSE;
10225
10226 DW_MUTEX_LOCK;
10227 thiswindow = _find_signal_window(window, NULL);
10228 count = (int)g_object_get_data(G_OBJECT(thiswindow), "_dw_sigcounter");
10229
10230 for(z=0;z<count;z++)
10231 {
10232 SignalHandler sh = _get_signal_handler(thiswindow, (gpointer)z);
10233
10234 if(sh.data == data)
10235 _remove_signal_handler(thiswindow, z);
10236 }
10237 DW_MUTEX_UNLOCK;
10238 }
10239