tgtkport.c - vaccinewars - be a doctor and try to vaccinate the world
HTML git clone git://src.adamsgaard.dk/vaccinewars
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
tgtkport.c (162832B)
---
1 /************************************************************************
2 * gtkport.c Portable "almost-GTK+" for Unix/Win32 *
3 * Copyright (C) 1998-2021 Ben Webb *
4 * Email: benwebb@users.sf.net *
5 * WWW: https://dopewars.sourceforge.io/ *
6 * *
7 * This program is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU General Public License *
9 * as published by the Free Software Foundation; either version 2 *
10 * of the License, or (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, *
20 * MA 02111-1307, USA. *
21 ************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #ifndef CYGWIN
28 #include <sys/types.h> /* For pid_t (fork) */
29 #include <sys/wait.h> /* For wait */
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h> /* For fork and execv */
32 #endif
33 #endif /* !CYGWIN */
34
35 #include <string.h>
36 #include <stdlib.h>
37 #include <stdarg.h>
38 #include <ctype.h>
39 #include <glib.h>
40
41 #include "gtkport.h"
42 #include "nls.h"
43
44 #ifdef APPLE
45 #include "mac_helpers.h"
46 #endif
47
48 #ifdef CYGWIN
49 #include "unicodewrap.h"
50
51 #include <winsock2.h>
52 #include <windows.h>
53 #include <commctrl.h>
54 #include <richedit.h>
55 #include <uxtheme.h>
56 #include <shlwapi.h>
57
58 #define LISTITEMVPACK 0
59
60 #define PANED_STARTPOS 200
61
62 HICON mainIcon = NULL;
63 static WNDPROC customWndProc = NULL;
64 static gboolean HaveRichEdit = FALSE;
65 static const gchar *RichEditClass = "RichEdit20W";
66 static gboolean HaveXPControls = FALSE;
67
68 static guint RecurseLevel = 0;
69
70 static const gchar *WC_GTKSEP = "WC_GTKSEP";
71 static const gchar *WC_GTKVPANED = "WC_GTKVPANED";
72 static const gchar *WC_GTKHPANED = "WC_GTKHPANED";
73 static const gchar *WC_GTKDIALOG = "WC_GTKDIALOG";
74 static const gchar *WC_GTKURL = "WC_GTKURL";
75
76 static void gtk_button_size_request(GtkWidget *widget,
77 GtkRequisition *requisition);
78 static void gtk_entry_size_request(GtkWidget *widget,
79 GtkRequisition *requisition);
80 static void gtk_entry_set_size(GtkWidget *widget,
81 GtkAllocation *allocation);
82 static void gtk_text_size_request(GtkWidget *widget,
83 GtkRequisition *requisition);
84 static void gtk_text_destroy(GtkWidget *widget);
85 static void gtk_button_destroy(GtkWidget *widget);
86 static void gtk_check_button_size_request(GtkWidget *widget,
87 GtkRequisition *requisition);
88 static void gtk_check_button_toggled(GtkCheckButton *check_button,
89 gpointer data);
90 static void gtk_radio_button_clicked(GtkRadioButton *radio_button,
91 gpointer data);
92 static void gtk_radio_button_toggled(GtkRadioButton *radio_button,
93 gpointer data);
94 static void gtk_container_destroy(GtkWidget *widget);
95 static void gtk_container_size_request(GtkWidget *widget,
96 GtkRequisition *requisition);
97 static void gtk_container_show_all(GtkWidget *widget, gboolean hWndOnly);
98 static void gtk_window_size_request(GtkWidget *widget,
99 GtkRequisition *requisition);
100 static void gtk_window_set_size(GtkWidget *widget,
101 GtkAllocation *allocation);
102 static void gtk_window_destroy(GtkWidget *widget);
103 static void gtk_window_set_menu(GtkWindow *window, GtkMenuBar *menu_bar);
104 static GtkWidget *gtk_window_get_menu_ID(GtkWindow *window, gint ID);
105 static gboolean gtk_window_wndproc(GtkWidget *widget, UINT msg, WPARAM wParam,
106 LPARAM lParam, gboolean *dodef);
107 static void gtk_table_destroy(GtkWidget *widget);
108 static void gtk_table_size_request(GtkWidget *widget,
109 GtkRequisition *requisition);
110 static void gtk_table_set_size(GtkWidget *widget,
111 GtkAllocation *allocation);
112 static void gtk_table_realize(GtkWidget *widget);
113 static void gtk_box_destroy(GtkWidget *widget);
114 static void gtk_hbox_size_request(GtkWidget *widget,
115 GtkRequisition *requisition);
116 static void gtk_hbox_set_size(GtkWidget *widget,
117 GtkAllocation *allocation);
118 static void gtk_vbox_size_request(GtkWidget *widget,
119 GtkRequisition *requisition);
120 static void gtk_vbox_set_size(GtkWidget *widget,
121 GtkAllocation *allocation);
122 static gint gtk_window_delete_event(GtkWidget *widget, GdkEvent *event);
123 static void gtk_window_realize(GtkWidget *widget);
124 static void gtk_window_show(GtkWidget *widget);
125 static void gtk_window_hide(GtkWidget *widget);
126 static void gtk_button_realize(GtkWidget *widget);
127 static void gtk_entry_realize(GtkWidget *widget);
128 static void gtk_text_realize(GtkWidget *widget);
129 static void gtk_check_button_realize(GtkWidget *widget);
130 static void gtk_radio_button_realize(GtkWidget *widget);
131 static void gtk_radio_button_destroy(GtkWidget *widget);
132 static void gtk_box_realize(GtkWidget *widget);
133
134 static void gtk_label_size_request(GtkWidget *widget,
135 GtkRequisition *requisition);
136 static void gtk_label_set_size(GtkWidget *widget,
137 GtkAllocation *allocation);
138 static void gtk_url_size_request(GtkWidget *widget,
139 GtkRequisition *requisition);
140 static void gtk_label_destroy(GtkWidget *widget);
141 static void gtk_url_destroy(GtkWidget *widget);
142 static void gtk_label_realize(GtkWidget *widget);
143 static void gtk_url_realize(GtkWidget *widget);
144 static void gtk_frame_size_request(GtkWidget *widget,
145 GtkRequisition *requisition);
146 static void gtk_frame_set_size(GtkWidget *widget,
147 GtkAllocation *allocation);
148 static void gtk_frame_destroy(GtkWidget *widget);
149 static void gtk_frame_realize(GtkWidget *widget);
150 static void gtk_box_show_all(GtkWidget *widget, gboolean hWndOnly);
151 static void gtk_table_show_all(GtkWidget *widget, gboolean hWndOnly);
152 static void gtk_widget_show_all_full(GtkWidget *widget, gboolean hWndOnly);
153 static void gtk_widget_show_full(GtkWidget *widget, gboolean recurse);
154 static void gtk_widget_update(GtkWidget *widget, gboolean ForceResize);
155 static void gtk_container_hide_all(GtkWidget *widget, gboolean hWndOnly);
156 static void gtk_box_hide_all(GtkWidget *widget, gboolean hWndOnly);
157 static void gtk_table_hide_all(GtkWidget *widget, gboolean hWndOnly);
158 static void gtk_widget_hide_all_full(GtkWidget *widget, gboolean hWndOnly);
159 static void gtk_widget_hide_full(GtkWidget *widget, gboolean recurse);
160
161 static void gtk_menu_bar_realize(GtkWidget *widget);
162 static void gtk_menu_item_realize(GtkWidget *widget);
163 static void gtk_menu_item_enable(GtkWidget *widget);
164 static void gtk_menu_item_disable(GtkWidget *widget);
165 static void gtk_menu_realize(GtkWidget *widget);
166 static void gtk_menu_shell_realize(GtkWidget *widget);
167 static GtkWidget *gtk_menu_shell_get_menu_ID(GtkMenuShell *menu_shell,
168 gint ID);
169 static void gtk_widget_create(GtkWidget *widget);
170 static void gtk_notebook_realize(GtkWidget *widget);
171 static void gtk_notebook_destroy(GtkWidget *widget);
172 static void gtk_notebook_set_size(GtkWidget *widget,
173 GtkAllocation *allocation);
174 static void gtk_notebook_size_request(GtkWidget *widget,
175 GtkRequisition *requisition);
176 static void gtk_notebook_show_all(GtkWidget *widget, gboolean hWndOnly);
177 static void gtk_notebook_hide_all(GtkWidget *widget, gboolean hWndOnly);
178 static void gtk_spin_button_size_request(GtkWidget *widget,
179 GtkRequisition *requisition);
180 static void gtk_spin_button_set_size(GtkWidget *widget,
181 GtkAllocation *allocation);
182 static void gtk_spin_button_realize(GtkWidget *widget);
183 static void gtk_spin_button_destroy(GtkWidget *widget);
184 static void gtk_spin_button_show(GtkWidget *widget);
185 static void gtk_spin_button_hide(GtkWidget *widget);
186 static void gtk_separator_size_request(GtkWidget *widget,
187 GtkRequisition *requisition);
188 static void gtk_separator_realize(GtkWidget *widget);
189 static void gtk_paned_show_all(GtkWidget *widget, gboolean hWndOnly);
190 static void gtk_paned_hide_all(GtkWidget *widget, gboolean hWndOnly);
191 static void gtk_paned_realize(GtkWidget *widget);
192 static void gtk_vpaned_realize(GtkWidget *widget);
193 static void gtk_hpaned_realize(GtkWidget *widget);
194 static void gtk_vpaned_size_request(GtkWidget *widget,
195 GtkRequisition *requisition);
196 static void gtk_hpaned_size_request(GtkWidget *widget,
197 GtkRequisition *requisition);
198 static void gtk_vpaned_set_size(GtkWidget *widget,
199 GtkAllocation *allocation);
200 static void gtk_hpaned_set_size(GtkWidget *widget,
201 GtkAllocation *allocation);
202 static void gtk_combo_box_size_request(GtkWidget *widget,
203 GtkRequisition *requisition);
204 static void gtk_combo_box_set_size(GtkWidget *widget,
205 GtkAllocation *allocation);
206 static void gtk_combo_box_realize(GtkWidget *widget);
207 static void gtk_combo_box_destroy(GtkWidget *widget);
208 static void gtk_button_set_text(GtkButton *button, gchar *text);
209 static void gtk_menu_item_set_text(GtkMenuItem *menuitem, gchar *text);
210 static void gtk_editable_create(GtkWidget *widget);
211 static void gtk_combo_box_update_selection(GtkWidget *widget);
212 static void gtk_widget_set_focus(GtkWidget *widget);
213 static void gtk_widget_lose_focus(GtkWidget *widget);
214 static void gtk_window_update_focus(GtkWindow *window);
215 static void gtk_window_set_focus(GtkWindow *window);
216 static void gtk_window_handle_user_size(GtkWindow *window,
217 GtkAllocation *allocation);
218 static void gtk_window_handle_minmax_size(GtkWindow *window,
219 LPMINMAXINFO minmax);
220 static void gtk_window_handle_auto_size(GtkWindow *window,
221 GtkAllocation *allocation);
222 static void gtk_window_set_initial_position(GtkWindow *window,
223 GtkAllocation *allocation);
224 static void gtk_progress_bar_size_request(GtkWidget *widget,
225 GtkRequisition *requisition);
226 static void gtk_progress_bar_realize(GtkWidget *widget);
227 static void gtk_accel_group_set_id(GtkAccelGroup *accel_group, gint ind,
228 gint ID);
229 static void EnableParent(GtkWindow *window);
230
231 struct _OurSource {
232 guint id; /* Unique identifier */
233
234 /* Used for timeouts (dp_g_timeout_add()) */
235 GSourceFunc timeout_function;
236
237 /* Used for IO channels (dp_g_io_watch()) */
238 GIOChannel *io_channel;
239 GIOFunc io_function;
240 int socket;
241
242 gpointer data; /* Data passed to callback function */
243 };
244 typedef struct _OurSource OurSource;
245
246 static GtkSignalType GtkObjectSignals[] = {
247 {"create", gtk_marshal_VOID__VOID, NULL},
248 {"", NULL, NULL}
249 };
250
251 GtkClass GtkObjectClass = {
252 "object", NULL, sizeof(GObject), GtkObjectSignals, NULL
253 };
254
255 static GtkClass GtkAdjustmentClass = {
256 "adjustment", &GtkObjectClass, sizeof(GtkAdjustment), NULL, NULL
257 };
258
259 static GtkSignalType GtkWidgetSignals[] = {
260 {"create", gtk_marshal_VOID__VOID, gtk_widget_create},
261 {"size_request", gtk_marshal_VOID__GPOIN, NULL},
262 {"set_size", gtk_marshal_VOID__GPOIN, NULL},
263 {"realize", gtk_marshal_VOID__VOID, NULL},
264 {"destroy", gtk_marshal_VOID__VOID, NULL},
265 {"show", gtk_marshal_VOID__VOID, NULL},
266 {"hide", gtk_marshal_VOID__VOID, NULL},
267 {"show_all", gtk_marshal_VOID__BOOL, NULL},
268 {"hide_all", gtk_marshal_VOID__BOOL, NULL},
269 {"enable", gtk_marshal_VOID__VOID, NULL},
270 {"disable", gtk_marshal_VOID__VOID, NULL},
271 {"", NULL, NULL}
272 };
273
274 static GtkClass GtkWidgetClass = {
275 "widget", &GtkObjectClass, sizeof(GtkWidget), GtkWidgetSignals, NULL
276 };
277
278 static GtkSignalType GtkSeparatorSignals[] = {
279 {"size_request", gtk_marshal_VOID__GPOIN, gtk_separator_size_request},
280 {"realize", gtk_marshal_VOID__VOID, gtk_separator_realize},
281 {"", NULL, NULL}
282 };
283
284 static GtkSignalType GtkProgressBarSignals[] = {
285 {"size_request", gtk_marshal_VOID__GPOIN, gtk_progress_bar_size_request},
286 {"realize", gtk_marshal_VOID__VOID, gtk_progress_bar_realize},
287 {"", NULL, NULL}
288 };
289
290 static GtkClass GtkProgressBarClass = {
291 "progressbar", &GtkWidgetClass, sizeof(GtkProgressBar),
292 GtkProgressBarSignals, NULL
293 };
294
295 static GtkClass GtkSeparatorClass = {
296 "separator", &GtkWidgetClass, sizeof(GtkSeparator), GtkSeparatorSignals, NULL
297 };
298
299 static GtkClass GtkHSeparatorClass = {
300 "hseparator", &GtkSeparatorClass, sizeof(GtkHSeparator), NULL, NULL
301 };
302
303 static GtkClass GtkVSeparatorClass = {
304 "vseparator", &GtkSeparatorClass, sizeof(GtkVSeparator), NULL, NULL
305 };
306
307 static GtkClass GtkMenuShellClass = {
308 "menushell", &GtkWidgetClass, sizeof(GtkMenuShell), NULL, NULL
309 };
310
311 static GtkSignalType GtkMenuBarSignals[] = {
312 {"realize", gtk_marshal_VOID__VOID, gtk_menu_bar_realize},
313 {"", NULL, NULL}
314 };
315
316 static GtkClass GtkMenuBarClass = {
317 "menubar", &GtkMenuShellClass, sizeof(GtkMenuBar), GtkMenuBarSignals, NULL
318 };
319
320 static GtkSignalType GtkMenuItemSignals[] = {
321 {"realize", gtk_marshal_VOID__VOID, gtk_menu_item_realize},
322 {"set_text", gtk_marshal_VOID__GPOIN, gtk_menu_item_set_text},
323 {"activate", gtk_marshal_VOID__VOID, NULL},
324 {"enable", gtk_marshal_VOID__VOID, gtk_menu_item_enable},
325 {"disable", gtk_marshal_VOID__VOID, gtk_menu_item_disable},
326 {"", NULL, NULL}
327 };
328
329 static GtkClass GtkMenuItemClass = {
330 "menuitem", &GtkWidgetClass, sizeof(GtkMenuItem), GtkMenuItemSignals, NULL
331 };
332
333 static GtkSignalType GtkMenuSignals[] = {
334 {"realize", gtk_marshal_VOID__VOID, gtk_menu_realize},
335 {"", NULL, NULL}
336 };
337
338 static GtkClass GtkMenuClass = {
339 "menu", &GtkMenuShellClass, sizeof(GtkMenu), GtkMenuSignals, NULL
340 };
341
342 static GtkSignalType GtkEditableSignals[] = {
343 {"create", gtk_marshal_VOID__VOID, gtk_editable_create},
344 {"activate", gtk_marshal_VOID__VOID, NULL},
345 {"", NULL, NULL}
346 };
347
348 static GtkClass GtkEditableClass = {
349 "editable", &GtkWidgetClass, sizeof(GtkEditable), GtkEditableSignals, NULL
350 };
351
352 static GtkSignalType GtkEntrySignals[] = {
353 {"size_request", gtk_marshal_VOID__GPOIN, gtk_entry_size_request},
354 {"set_size", gtk_marshal_VOID__GPOIN, gtk_entry_set_size},
355 {"realize", gtk_marshal_VOID__VOID, gtk_entry_realize},
356 {"", NULL, NULL}
357 };
358
359 static GtkClass GtkEntryClass = {
360 "entry", &GtkEditableClass, sizeof(GtkEntry), GtkEntrySignals, NULL
361 };
362
363 static GtkSignalType GtkSpinButtonSignals[] = {
364 {"size_request", gtk_marshal_VOID__GPOIN, gtk_spin_button_size_request},
365 {"set_size", gtk_marshal_VOID__GPOIN, gtk_spin_button_set_size},
366 {"realize", gtk_marshal_VOID__VOID, gtk_spin_button_realize},
367 {"destroy", gtk_marshal_VOID__VOID, gtk_spin_button_destroy},
368 {"hide", gtk_marshal_VOID__VOID, gtk_spin_button_hide},
369 {"show", gtk_marshal_VOID__VOID, gtk_spin_button_show},
370 {"", NULL, NULL}
371 };
372
373 static GtkClass GtkSpinButtonClass = {
374 "spinbutton", &GtkEntryClass, sizeof(GtkSpinButton),
375 GtkSpinButtonSignals, NULL
376 };
377
378 static GtkSignalType GtkTextSignals[] = {
379 {"size_request", gtk_marshal_VOID__GPOIN, gtk_text_size_request},
380 {"realize", gtk_marshal_VOID__VOID, gtk_text_realize},
381 {"destroy", gtk_marshal_VOID__VOID, gtk_text_destroy},
382 {"", NULL, NULL}
383 };
384
385 static GtkClass GtkTextClass = {
386 "text", &GtkEditableClass, sizeof(GtkText), GtkTextSignals, NULL
387 };
388
389 static GtkSignalType GtkLabelSignals[] = {
390 {"size_request", gtk_marshal_VOID__GPOIN, gtk_label_size_request},
391 {"set_size", gtk_marshal_VOID__GPOIN, gtk_label_set_size},
392 {"set_text", gtk_marshal_VOID__GPOIN, gtk_label_set_text},
393 {"realize", gtk_marshal_VOID__VOID, gtk_label_realize},
394 {"destroy", gtk_marshal_VOID__VOID, gtk_label_destroy},
395 {"", NULL, NULL}
396 };
397
398 static GtkClass GtkLabelClass = {
399 "label", &GtkWidgetClass, sizeof(GtkLabel), GtkLabelSignals, NULL
400 };
401
402 static GtkSignalType GtkUrlSignals[] = {
403 {"size_request", gtk_marshal_VOID__GPOIN, gtk_url_size_request},
404 {"set_size", gtk_marshal_VOID__GPOIN, gtk_label_set_size},
405 {"realize", gtk_marshal_VOID__VOID, gtk_url_realize},
406 {"destroy", gtk_marshal_VOID__VOID, gtk_url_destroy},
407 {"", NULL, NULL}
408 };
409
410 static GtkClass GtkUrlClass = {
411 "URL", &GtkLabelClass, sizeof(GtkUrl), GtkUrlSignals, NULL
412 };
413
414 static GtkSignalType GtkButtonSignals[] = {
415 {"size_request", gtk_marshal_VOID__GPOIN, gtk_button_size_request},
416 {"set_text", gtk_marshal_VOID__GPOIN, gtk_button_set_text},
417 {"realize", gtk_marshal_VOID__VOID, gtk_button_realize},
418 {"destroy", gtk_marshal_VOID__VOID, gtk_button_destroy},
419 {"clicked", gtk_marshal_VOID__VOID, NULL},
420 {"", NULL, NULL}
421 };
422
423 static GtkClass GtkButtonClass = {
424 "button", &GtkWidgetClass, sizeof(GtkButton), GtkButtonSignals, NULL
425 };
426
427 static GtkSignalType GtkComboBoxSignals[] = {
428 {"size_request", gtk_marshal_VOID__GPOIN, gtk_combo_box_size_request},
429 {"set_size", gtk_marshal_VOID__GPOIN, gtk_combo_box_set_size},
430 {"realize", gtk_marshal_VOID__VOID, gtk_combo_box_realize},
431 {"destroy", gtk_marshal_VOID__VOID, gtk_combo_box_destroy},
432 {"changed", gtk_marshal_VOID__VOID, NULL},
433 {"", NULL, NULL}
434 };
435
436 static GtkClass GtkComboBoxClass = {
437 "combobox", &GtkWidgetClass, sizeof(GtkComboBox),
438 GtkComboBoxSignals, NULL
439 };
440
441 static GtkSignalType GtkToggleButtonSignals[] = {
442 {"toggled", gtk_marshal_VOID__VOID, NULL},
443 {"", NULL, NULL}
444 };
445
446 static GtkClass GtkToggleButtonClass = {
447 "toggle", &GtkButtonClass, sizeof(GtkToggleButton),
448 GtkToggleButtonSignals, NULL
449 };
450
451 static GtkSignalType GtkCheckButtonSignals[] = {
452 {"size_request", gtk_marshal_VOID__GPOIN, gtk_check_button_size_request},
453 {"realize", gtk_marshal_VOID__VOID, gtk_check_button_realize},
454 {"", NULL, NULL}
455 };
456
457 static GtkClass GtkCheckButtonClass = {
458 "check", &GtkToggleButtonClass, sizeof(GtkCheckButton),
459 GtkCheckButtonSignals, NULL
460 };
461
462 static GtkSignalType GtkRadioButtonSignals[] = {
463 {"realize", gtk_marshal_VOID__VOID, gtk_radio_button_realize},
464 {"destroy", gtk_marshal_VOID__VOID, gtk_radio_button_destroy},
465 {"", NULL, NULL}
466 };
467
468 static GtkClass GtkRadioButtonClass = {
469 "radio", &GtkCheckButtonClass, sizeof(GtkRadioButton),
470 GtkRadioButtonSignals, NULL
471 };
472
473 static GtkSignalType GtkContainerSignals[] = {
474 {"size_request", gtk_marshal_VOID__GPOIN, gtk_container_size_request},
475 {"set_size", gtk_marshal_VOID__GPOIN, gtk_container_set_size},
476 {"realize", gtk_marshal_VOID__VOID, gtk_container_realize},
477 {"destroy", gtk_marshal_VOID__VOID, gtk_container_destroy},
478 {"show_all", gtk_marshal_VOID__BOOL, gtk_container_show_all},
479 {"hide_all", gtk_marshal_VOID__BOOL, gtk_container_hide_all},
480 {"", NULL, NULL}
481 };
482
483 GtkClass GtkContainerClass = {
484 "container", &GtkWidgetClass, sizeof(GtkContainer), GtkContainerSignals, NULL
485 };
486
487 static GtkSignalType GtkPanedSignals[] = {
488 {"show_all", gtk_marshal_VOID__BOOL, gtk_paned_show_all},
489 {"hide_all", gtk_marshal_VOID__BOOL, gtk_paned_hide_all},
490 {"", NULL, NULL}
491 };
492
493 static GtkClass GtkPanedClass = {
494 "paned", &GtkContainerClass, sizeof(GtkPaned), GtkPanedSignals, NULL
495 };
496
497 static GtkSignalType GtkVPanedSignals[] = {
498 {"realize", gtk_marshal_VOID__VOID, gtk_vpaned_realize},
499 {"size_request", gtk_marshal_VOID__GPOIN, gtk_vpaned_size_request},
500 {"set_size", gtk_marshal_VOID__GPOIN, gtk_vpaned_set_size},
501 {"", NULL, NULL}
502 };
503
504 static GtkClass GtkVPanedClass = {
505 "vpaned", &GtkPanedClass, sizeof(GtkVPaned), GtkVPanedSignals, NULL
506 };
507
508 static GtkSignalType GtkHPanedSignals[] = {
509 {"realize", gtk_marshal_VOID__VOID, gtk_hpaned_realize},
510 {"size_request", gtk_marshal_VOID__GPOIN, gtk_hpaned_size_request},
511 {"set_size", gtk_marshal_VOID__GPOIN, gtk_hpaned_set_size},
512 {"", NULL, NULL}
513 };
514
515 static GtkClass GtkHPanedClass = {
516 "hpaned", &GtkPanedClass, sizeof(GtkHPaned), GtkHPanedSignals, NULL
517 };
518
519 static GtkSignalType GtkBoxSignals[] = {
520 {"realize", gtk_marshal_VOID__VOID, gtk_box_realize},
521 {"destroy", gtk_marshal_VOID__VOID, gtk_box_destroy},
522 {"show_all", gtk_marshal_VOID__BOOL, gtk_box_show_all},
523 {"hide_all", gtk_marshal_VOID__BOOL, gtk_box_hide_all},
524 {"", NULL, NULL}
525 };
526
527 static GtkClass GtkBoxClass = {
528 "box", &GtkContainerClass, sizeof(GtkBox), GtkBoxSignals, NULL
529 };
530
531 static GtkSignalType GtkNotebookSignals[] = {
532 {"realize", gtk_marshal_VOID__VOID, gtk_notebook_realize},
533 {"destroy", gtk_marshal_VOID__VOID, gtk_notebook_destroy},
534 {"size_request", gtk_marshal_VOID__GPOIN, gtk_notebook_size_request},
535 {"set_size", gtk_marshal_VOID__GPOIN, gtk_notebook_set_size},
536 {"show_all", gtk_marshal_VOID__BOOL, gtk_notebook_show_all},
537 {"hide_all", gtk_marshal_VOID__BOOL, gtk_notebook_hide_all},
538 {"", NULL, NULL}
539 };
540
541 static GtkClass GtkNotebookClass = {
542 "notebook", &GtkContainerClass, sizeof(GtkNotebook), GtkNotebookSignals, NULL
543 };
544
545 static GtkSignalType GtkTableSignals[] = {
546 {"size_request", gtk_marshal_VOID__GPOIN, gtk_table_size_request},
547 {"set_size", gtk_marshal_VOID__GPOIN, gtk_table_set_size},
548 {"realize", gtk_marshal_VOID__VOID, gtk_table_realize},
549 {"destroy", gtk_marshal_VOID__VOID, gtk_table_destroy},
550 {"show_all", gtk_marshal_VOID__BOOL, gtk_table_show_all},
551 {"hide_all", gtk_marshal_VOID__BOOL, gtk_table_hide_all},
552 {"", NULL, NULL}
553 };
554
555 static GtkClass GtkTableClass = {
556 "table", &GtkContainerClass, sizeof(GtkTable), GtkTableSignals, NULL
557 };
558
559 static GtkSignalType GtkHBoxSignals[] = {
560 {"size_request", gtk_marshal_VOID__GPOIN, gtk_hbox_size_request},
561 {"set_size", gtk_marshal_VOID__GPOIN, gtk_hbox_set_size},
562 {"", NULL, NULL}
563 };
564
565 static GtkClass GtkHBoxClass = {
566 "hbox", &GtkBoxClass, sizeof(GtkHBox), GtkHBoxSignals, NULL
567 };
568
569 static GtkSignalType GtkVBoxSignals[] = {
570 {"size_request", gtk_marshal_VOID__GPOIN, gtk_vbox_size_request},
571 {"set_size", gtk_marshal_VOID__GPOIN, gtk_vbox_set_size},
572 {"", NULL, NULL}
573 };
574
575 static GtkClass GtkVBoxClass = {
576 "vbox", &GtkBoxClass, sizeof(GtkVBox), GtkVBoxSignals, NULL
577 };
578
579 static GtkClass GtkBinClass = {
580 "bin", &GtkContainerClass, sizeof(GtkBin), NULL, NULL
581 };
582
583 static GtkSignalType GtkFrameSignals[] = {
584 {"size_request", gtk_marshal_VOID__GPOIN, gtk_frame_size_request},
585 {"set_size", gtk_marshal_VOID__GPOIN, gtk_frame_set_size},
586 {"realize", gtk_marshal_VOID__VOID, gtk_frame_realize},
587 {"destroy", gtk_marshal_VOID__VOID, gtk_frame_destroy},
588 {"", NULL, NULL}
589 };
590
591 static GtkClass GtkFrameClass = {
592 "frame", &GtkBinClass, sizeof(GtkFrame), GtkFrameSignals, NULL
593 };
594
595 static GtkSignalType GtkWindowSignals[] = {
596 {"size_request", gtk_marshal_VOID__GPOIN, gtk_window_size_request},
597 {"set_size", gtk_marshal_VOID__GPOIN, gtk_window_set_size},
598 {"realize", gtk_marshal_VOID__VOID, gtk_window_realize},
599 {"destroy", gtk_marshal_VOID__VOID, gtk_window_destroy},
600 {"show", gtk_marshal_VOID__VOID, gtk_window_show},
601 {"hide", gtk_marshal_VOID__VOID, gtk_window_hide},
602 {"delete_event", gtk_marshal_BOOL__GPOIN,
603 G_CALLBACK(gtk_window_delete_event)},
604 {"", NULL, NULL}
605 };
606
607 static GtkClass GtkWindowClass = {
608 "window", &GtkBinClass, sizeof(GtkWindow), GtkWindowSignals,
609 gtk_window_wndproc
610 };
611
612 const GtkType GTK_TYPE_WINDOW = &GtkWindowClass;
613 const GtkType GTK_TYPE_MENU_BAR = &GtkMenuBarClass;
614 const GtkType GTK_TYPE_NOTEBOOK = &GtkNotebookClass;
615
616 HINSTANCE hInst;
617 HFONT defFont;
618 static HFONT urlFont;
619 static GSList *WindowList = NULL;
620 static GSList *OurSources = NULL;
621 static HWND TopLevel = NULL;
622
623 static WNDPROC wpOrigEntryProc, wpOrigTextProc;
624
625 void gtk_set_default_font(HWND hWnd)
626 {
627 SendMessageW(hWnd, WM_SETFONT, (WPARAM)defFont, MAKELPARAM(FALSE, 0));
628 }
629
630 GObject *GtkNewObject(GtkClass *klass)
631 {
632 GObject *newObj;
633
634 newObj = g_malloc0(klass->Size);
635 newObj->klass = klass;
636 gtk_signal_emit(newObj, "create");
637
638 return newObj;
639 }
640
641 static void DispatchSocketEvent(SOCKET sock, long event)
642 {
643 GSList *list;
644 OurSource *s;
645
646 for (list = OurSources; list; list = g_slist_next(list)) {
647 s = (OurSource *)(list->data);
648 if (s->socket == sock) {
649 (*s->io_function) (s->io_channel,
650 (event & (FD_READ | FD_CLOSE | FD_ACCEPT) ?
651 G_IO_IN : 0) |
652 (event & (FD_WRITE | FD_CONNECT) ?
653 G_IO_OUT : 0), s->data);
654 break;
655 }
656 }
657 }
658
659 static void DispatchTimeoutEvent(UINT id)
660 {
661 GSList *list;
662 OurSource *s;
663
664 for (list = OurSources; list; list = g_slist_next(list)) {
665 s = (OurSource *)list->data;
666 if (s->id == id) {
667 if (s->timeout_function) {
668 if (!(*s->timeout_function) (s->data)) {
669 dp_g_source_remove(s->id);
670 }
671 }
672 break;
673 }
674 }
675 }
676
677 static HWND gtk_get_window_hwnd(GtkWidget *widget)
678 {
679 widget = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
680 if (widget) {
681 return widget->hWnd;
682 } else {
683 return NULL;
684 }
685 }
686
687 HWND gtk_get_parent_hwnd(GtkWidget *widget)
688 {
689 GtkWidget *child = NULL;
690 while (widget && G_OBJECT(widget)->klass != GTK_TYPE_WINDOW
691 && G_OBJECT(widget)->klass != GTK_TYPE_NOTEBOOK) {
692 child = widget;
693 widget = widget->parent;
694 }
695 if (widget) {
696 if (G_OBJECT(widget)->klass == GTK_TYPE_NOTEBOOK) {
697 GSList *children;
698 for (children = GTK_NOTEBOOK(widget)->children; children;
699 children = g_slist_next(children)) {
700 GtkNotebookChild *note_child;
701 note_child = (GtkNotebookChild *)(children->data);
702 if (note_child && note_child->child == child) {
703 return note_child->tabpage;
704 }
705 }
706 return NULL;
707 } else {
708 return widget->hWnd;
709 }
710 } else {
711 return NULL;
712 }
713 }
714
715 static void UpdatePanedGhostRect(GtkPaned *paned, RECT *OldRect,
716 RECT *NewRect, gint16 x, gint16 y)
717 {
718 HWND hWnd, parent;
719 RECT rect, clrect;
720 POINT MouseCoord;
721 HDC hDC;
722 GtkWidget *widget = GTK_WIDGET(paned);
723
724 if (!OldRect && !NewRect)
725 return;
726 parent = gtk_get_parent_hwnd(widget);
727 hWnd = widget->hWnd;
728 if (!parent || !hWnd)
729 return;
730
731 MouseCoord.x = x;
732 MouseCoord.y = y;
733 MapWindowPoints(hWnd, parent, &MouseCoord, 1);
734
735 rect.left = paned->true_alloc.x;
736 rect.top = paned->true_alloc.y;
737 GetClientRect(hWnd, &clrect);
738 if (clrect.right > clrect.bottom) {
739 rect.right = paned->true_alloc.x + paned->true_alloc.width;
740 rect.bottom = MouseCoord.y;
741 } else {
742 rect.bottom = paned->true_alloc.y + paned->true_alloc.height;
743 rect.right = MouseCoord.x;
744 }
745
746 if (OldRect && NewRect && OldRect->right == rect.right &&
747 OldRect->bottom == rect.bottom)
748 return;
749
750 hDC = GetDC(parent);
751
752 if (OldRect)
753 DrawFocusRect(hDC, OldRect);
754 if (NewRect) {
755 CopyRect(NewRect, &rect);
756 DrawFocusRect(hDC, NewRect);
757 }
758 ReleaseDC(parent, hDC);
759 }
760
761 LRESULT CALLBACK GtkPanedProc(HWND hwnd, UINT msg, WPARAM wParam,
762 LPARAM lParam)
763 {
764 PAINTSTRUCT ps;
765 HPEN oldpen, dkpen, ltpen;
766 RECT rect;
767 static RECT GhostRect;
768 HDC hDC;
769 gint newpos;
770 GtkPaned *paned;
771
772 paned = GTK_PANED(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
773 switch (msg) {
774 case WM_PAINT:
775 if (GetUpdateRect(hwnd, NULL, TRUE)) {
776 BeginPaint(hwnd, &ps);
777 GetClientRect(hwnd, &rect);
778 hDC = ps.hdc;
779 ltpen =
780 CreatePen(PS_SOLID, 0, (COLORREF)GetSysColor(COLOR_3DHILIGHT));
781 dkpen =
782 CreatePen(PS_SOLID, 0, (COLORREF)GetSysColor(COLOR_3DSHADOW));
783
784 if (rect.right > rect.bottom) {
785 oldpen = SelectObject(hDC, ltpen);
786 MoveToEx(hDC, rect.left, rect.top, NULL);
787 LineTo(hDC, rect.right, rect.top);
788
789 SelectObject(hDC, dkpen);
790 MoveToEx(hDC, rect.left, rect.bottom - 1, NULL);
791 LineTo(hDC, rect.right, rect.bottom - 1);
792 } else {
793 oldpen = SelectObject(hDC, ltpen);
794 MoveToEx(hDC, rect.left, rect.top, NULL);
795 LineTo(hDC, rect.left, rect.bottom);
796
797 SelectObject(hDC, ltpen);
798 MoveToEx(hDC, rect.right - 1, rect.top, NULL);
799 LineTo(hDC, rect.right - 1, rect.bottom);
800 }
801
802 SelectObject(hDC, oldpen);
803 DeleteObject(ltpen);
804 DeleteObject(dkpen);
805 EndPaint(hwnd, &ps);
806 }
807 return TRUE;
808 case WM_LBUTTONDOWN:
809 if (!paned)
810 break;
811 SetCapture(hwnd);
812 paned->Tracking = TRUE;
813 UpdatePanedGhostRect(paned, NULL, &GhostRect,
814 LOWORD(lParam), HIWORD(lParam));
815 return TRUE;
816 case WM_MOUSEMOVE:
817 if (!paned || !paned->Tracking)
818 break;
819 UpdatePanedGhostRect(paned, &GhostRect, &GhostRect,
820 LOWORD(lParam), HIWORD(lParam));
821 return TRUE;
822 case WM_LBUTTONUP:
823 if (!paned || !paned->Tracking)
824 break;
825 ReleaseCapture();
826 paned->Tracking = FALSE;
827 UpdatePanedGhostRect(paned, &GhostRect, NULL,
828 LOWORD(lParam), HIWORD(lParam));
829 GetClientRect(hwnd, &rect);
830 if (rect.right > rect.bottom) {
831 newpos = ((gint16)HIWORD(lParam) + GTK_WIDGET(paned)->allocation.y -
832 paned->true_alloc.y) * 100 / paned->true_alloc.height;
833 } else {
834 newpos = ((gint16)LOWORD(lParam) + GTK_WIDGET(paned)->allocation.x -
835 paned->true_alloc.x) * 100 / paned->true_alloc.width;
836 }
837 gtk_paned_set_position(paned, newpos);
838 return TRUE;
839 default:
840 return DefWindowProcW(hwnd, msg, wParam, lParam);
841 }
842 return FALSE;
843 }
844
845 void DisplayHTML(GtkWidget *parent, const gchar *bin, const gchar *target)
846 {
847 ShellExecute(parent->hWnd, "open", target, NULL, NULL, 0);
848 }
849
850 LRESULT CALLBACK GtkUrlProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
851 {
852 GtkWidget *widget;
853
854 if (msg == WM_PAINT) {
855 gchar *text;
856 RECT wndrect;
857 PAINTSTRUCT ps;
858 HDC hDC;
859 HFONT oldFont;
860
861 widget = GTK_WIDGET(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
862 text = GTK_LABEL(widget)->text;
863 if (text && BeginPaint(hwnd, &ps)) {
864 hDC = ps.hdc;
865 oldFont = SelectObject(hDC, urlFont);
866 SetTextColor(hDC, RGB(0, 0, 0xCC));
867 SetBkMode(hDC, TRANSPARENT);
868 GetClientRect(hwnd, &wndrect);
869 myDrawText(hDC, text, -1, &wndrect,
870 DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS);
871 SelectObject(hDC, oldFont);
872 EndPaint(hwnd, &ps);
873 }
874 return TRUE;
875 } else if (msg == WM_LBUTTONUP) {
876 widget = GTK_WIDGET(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
877
878 DisplayHTML(widget, NULL, GTK_URL(widget)->target);
879 return FALSE;
880 } else
881 return DefWindowProcW(hwnd, msg, wParam, lParam);
882 }
883
884 LRESULT CALLBACK GtkSepProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
885 {
886 PAINTSTRUCT ps;
887 HPEN oldpen, dkpen, ltpen;
888 RECT rect;
889 HDC hDC;
890
891 if (msg == WM_PAINT) {
892 if (GetUpdateRect(hwnd, NULL, TRUE)) {
893 BeginPaint(hwnd, &ps);
894 GetClientRect(hwnd, &rect);
895 hDC = ps.hdc;
896 ltpen =
897 CreatePen(PS_SOLID, 0, (COLORREF)GetSysColor(COLOR_3DHILIGHT));
898 dkpen =
899 CreatePen(PS_SOLID, 0, (COLORREF)GetSysColor(COLOR_3DSHADOW));
900
901 if (rect.right > rect.bottom) {
902 oldpen = SelectObject(hDC, dkpen);
903 MoveToEx(hDC, rect.left, rect.top, NULL);
904 LineTo(hDC, rect.right, rect.top);
905
906 SelectObject(hDC, ltpen);
907 MoveToEx(hDC, rect.left, rect.top + 1, NULL);
908 LineTo(hDC, rect.right, rect.top + 1);
909 } else {
910 oldpen = SelectObject(hDC, dkpen);
911 MoveToEx(hDC, rect.left, rect.top, NULL);
912 LineTo(hDC, rect.left, rect.bottom);
913
914 SelectObject(hDC, ltpen);
915 MoveToEx(hDC, rect.left + 1, rect.top, NULL);
916 LineTo(hDC, rect.left + 1, rect.bottom);
917 }
918
919 SelectObject(hDC, oldpen);
920 DeleteObject(ltpen);
921 DeleteObject(dkpen);
922 EndPaint(hwnd, &ps);
923 }
924 return TRUE;
925 } else
926 return DefWindowProcW(hwnd, msg, wParam, lParam);
927 }
928
929 gboolean gtk_window_wndproc(GtkWidget *widget, UINT msg, WPARAM wParam,
930 LPARAM lParam, gboolean *dodef)
931 {
932 RECT rect;
933 GtkAllocation alloc;
934 GtkWidget *menu;
935 gboolean signal_return;
936 GdkEvent event = 0;
937
938 switch(msg) {
939 case WM_SIZE:
940 GetWindowRect(widget->hWnd, &rect);
941 alloc.x = rect.left;
942 alloc.y = rect.top;
943 alloc.width = rect.right - rect.left;
944 alloc.height = rect.bottom - rect.top;
945 gtk_window_handle_user_size(GTK_WINDOW(widget), &alloc);
946 gtk_widget_set_size(widget, &alloc);
947 InvalidateRect(widget->hWnd, NULL, TRUE);
948 UpdateWindow(widget->hWnd);
949 return FALSE;
950 case WM_GETMINMAXINFO:
951 gtk_window_handle_minmax_size(GTK_WINDOW(widget), (LPMINMAXINFO)lParam);
952 return FALSE;
953 case WM_ACTIVATE:
954 case WM_ACTIVATEAPP:
955 if ((msg == WM_ACTIVATE && LOWORD(wParam) != WA_INACTIVE)
956 || (msg == WM_ACTIVATEAPP && wParam)) {
957 if (GTK_WINDOW(widget)->focus) {
958 gtk_widget_set_focus(GTK_WINDOW(widget)->focus);
959 }
960 if (!GTK_WINDOW(widget)->focus) {
961 gtk_window_set_focus(GTK_WINDOW(widget));
962 }
963 } else if (msg == WM_ACTIVATE && LOWORD(wParam) == WA_INACTIVE) {
964 gtk_window_update_focus(GTK_WINDOW(widget));
965 }
966 return FALSE;
967 case WM_CLOSE:
968 gtk_signal_emit(G_OBJECT(widget), "delete_event",
969 &event, &signal_return);
970 *dodef = FALSE;
971 return TRUE;
972 case WM_COMMAND:
973 if (HIWORD(wParam) == 0 || HIWORD(wParam) == 1) {
974 menu = gtk_window_get_menu_ID(GTK_WINDOW(widget), LOWORD(wParam));
975 if (menu) {
976 if (GTK_MENU_ITEM(menu)->check) {
977 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu),
978 !GTK_CHECK_MENU_ITEM(menu)->active);
979 }
980 gtk_signal_emit(G_OBJECT(menu), "activate");
981 return FALSE;
982 }
983 }
984 break;
985 }
986
987 return FALSE;
988 }
989
990 static BOOL HandleWinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
991 gboolean *dodef)
992 {
993 GtkWidget *widget;
994 GtkClass *klass;
995 LPMEASUREITEMSTRUCT lpmis;
996 HDC hDC;
997 TEXTMETRIC tm;
998 LPDRAWITEMSTRUCT lpdis;
999 NMHDR *nmhdr;
1000 gboolean retval = FALSE;
1001
1002 *dodef = TRUE;
1003
1004 if (customWndProc
1005 && CallWindowProcW(customWndProc, hwnd, msg, wParam, lParam))
1006 return TRUE;
1007
1008 widget = GTK_WIDGET(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
1009 if (widget && (klass = G_OBJECT(widget)->klass)
1010 && klass->wndproc) {
1011 retval = klass->wndproc(widget, msg, wParam, lParam, dodef);
1012 }
1013
1014 switch (msg) {
1015 case WM_DRAWITEM:
1016 if ((lpdis = (LPDRAWITEMSTRUCT)lParam)
1017 && (widget = GTK_WIDGET(GetWindowLongPtrW(lpdis->hwndItem,
1018 GWLP_USERDATA)))
1019 && (klass = G_OBJECT(widget)->klass)
1020 && klass->wndproc) {
1021 retval = klass->wndproc(widget, msg, wParam, lParam, dodef);
1022 }
1023 break;
1024 case WM_MEASUREITEM:
1025 lpmis = (LPMEASUREITEMSTRUCT)lParam;
1026 hDC = GetDC(hwnd);
1027 if (!GetTextMetrics(hDC, &tm))
1028 g_warning("GetTextMetrics failed");
1029 ReleaseDC(hwnd, hDC);
1030 if (lpmis) {
1031 lpmis->itemHeight = tm.tmHeight + LISTITEMVPACK * 2;
1032 return TRUE;
1033 }
1034 break;
1035 case WM_COMMAND:
1036 widget = GTK_WIDGET(GetWindowLongPtrW((HWND)lParam, GWLP_USERDATA));
1037 klass = NULL;
1038 if (widget && (klass = G_OBJECT(widget)->klass)
1039 && klass->wndproc) {
1040 retval = klass->wndproc(widget, msg, wParam, lParam, dodef);
1041 }
1042
1043 if (lParam && klass == &GtkComboBoxClass &&
1044 HIWORD(wParam) == CBN_SELENDOK) {
1045 gtk_combo_box_update_selection(widget);
1046 } else if (lParam && HIWORD(wParam) == BN_CLICKED) {
1047 gtk_signal_emit(G_OBJECT(widget), "clicked");
1048 } else
1049 return TRUE;
1050 break;
1051 case WM_NOTIFY:
1052 nmhdr = (NMHDR *)lParam;
1053 if (!nmhdr)
1054 break;
1055
1056 widget = GTK_WIDGET(GetWindowLongPtrW(nmhdr->hwndFrom, GWLP_USERDATA));
1057 if (widget && (klass = G_OBJECT(widget)->klass)
1058 && klass->wndproc) {
1059 retval = klass->wndproc(widget, msg, wParam, lParam, dodef);
1060 }
1061
1062 if (widget && nmhdr->code == TCN_SELCHANGE) {
1063 gtk_notebook_set_current_page(GTK_NOTEBOOK(widget),
1064 TabCtrl_GetCurSel(nmhdr->hwndFrom));
1065 return FALSE;
1066 }
1067 break;
1068 case MYWM_SOCKETDATA:
1069 /* Ignore network messages if in recursive message loops, to avoid
1070 * dodgy race conditions */
1071 if (RecurseLevel <= 1) {
1072 /* Make any error available by the usual WSAGetLastError() mechanism */
1073 WSASetLastError(WSAGETSELECTERROR(lParam));
1074 DispatchSocketEvent((SOCKET)wParam, WSAGETSELECTEVENT(lParam));
1075 }
1076 break;
1077 case WM_TIMER:
1078 DispatchTimeoutEvent((UINT)wParam);
1079 return FALSE;
1080 }
1081
1082 return retval;
1083 }
1084
1085 LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1086 {
1087 gboolean retval, dodef = TRUE;
1088
1089 retval = HandleWinMessage(hwnd, msg, wParam, lParam, &dodef);
1090 if (dodef) {
1091 return DefWindowProcW(hwnd, msg, wParam, lParam);
1092 } else {
1093 return retval;
1094 }
1095 }
1096
1097 INT_PTR APIENTRY MainDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1098 {
1099 gboolean dodef;
1100
1101 if (msg == WM_INITDIALOG) {
1102 return TRUE;
1103 } else {
1104 return HandleWinMessage(hwnd, msg, wParam, lParam, &dodef);
1105 }
1106 }
1107
1108 LRESULT APIENTRY EntryWndProc(HWND hwnd, UINT msg, WPARAM wParam,
1109 LPARAM lParam)
1110 {
1111 GtkWidget *widget;
1112
1113 if (msg == WM_KEYUP && wParam == VK_RETURN) {
1114 widget = GTK_WIDGET(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
1115 if (widget)
1116 gtk_signal_emit(G_OBJECT(widget), "activate");
1117 return FALSE;
1118 }
1119 return CallWindowProcW(wpOrigEntryProc, hwnd, msg, wParam, lParam);
1120 }
1121
1122 LRESULT APIENTRY TextWndProc(HWND hwnd, UINT msg, WPARAM wParam,
1123 LPARAM lParam)
1124 {
1125 GtkWidget *widget;
1126
1127 if (msg == WM_GETDLGCODE) {
1128 widget = GTK_WIDGET(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
1129 if (!GTK_EDITABLE(widget)->is_editable) {
1130 return DLGC_HASSETSEL | DLGC_WANTARROWS;
1131 }
1132 }
1133 return CallWindowProcW(wpOrigTextProc, hwnd, msg, wParam, lParam);
1134 }
1135
1136 void SetCustomWndProc(WNDPROC wndproc)
1137 {
1138 customWndProc = wndproc;
1139 }
1140
1141 /*
1142 * Returns TRUE if we are using version 6 of the Common Controls library
1143 * (as shipped with Windows XP) and thus need to worry about visual themes
1144 */
1145 static gboolean CheckForXPControls(void)
1146 {
1147 HINSTANCE hDll;
1148 BOOL retval = FALSE;
1149
1150 hDll = LoadLibrary("COMCTL32.DLL");
1151 if (hDll) {
1152 DLLGETVERSIONPROC getverproc;
1153 getverproc = (DLLGETVERSIONPROC)GetProcAddress(hDll, "DllGetVersion");
1154 if (getverproc) {
1155 DLLVERSIONINFO dvi;
1156 HRESULT hr;
1157 ZeroMemory(&dvi, sizeof(dvi));
1158 dvi.cbSize = sizeof(dvi);
1159 hr = getverproc(&dvi);
1160 if (SUCCEEDED(hr) && dvi.dwMajorVersion >= 6) {
1161 retval = TRUE;
1162 }
1163 }
1164 FreeLibrary(hDll);
1165 }
1166 return retval;
1167 }
1168
1169 void win32_init(HINSTANCE hInstance, HINSTANCE hPrevInstance,
1170 char *MainIcon)
1171 {
1172 WNDCLASS wc;
1173
1174 hInst = hInstance;
1175 defFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
1176 urlFont = CreateFont(14, 0, 0, 0, FW_SEMIBOLD, FALSE, TRUE, FALSE,
1177 ANSI_CHARSET, OUT_DEFAULT_PRECIS,
1178 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
1179 FF_SWISS | DEFAULT_PITCH, NULL);
1180 WindowList = NULL;
1181 RecurseLevel = 0;
1182 customWndProc = NULL;
1183 if (MainIcon) {
1184 mainIcon = LoadIcon(hInstance, MainIcon);
1185 } else {
1186 mainIcon = LoadIcon(NULL, IDI_APPLICATION);
1187 }
1188
1189 InitCommonControls();
1190 LoadLibrary("RICHED20.DLL");
1191 HaveRichEdit = GetClassInfo(hInstance, RichEditClass, &wc);
1192
1193 HaveXPControls = CheckForXPControls();
1194
1195 if (!hPrevInstance) {
1196 wc.style = 0;
1197 wc.lpfnWndProc = MainWndProc;
1198 wc.cbClsExtra = 0;
1199 wc.cbWndExtra = 0;
1200 wc.hInstance = hInstance;
1201 wc.hIcon = mainIcon;
1202 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
1203 wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
1204 wc.lpszMenuName = NULL;
1205 wc.lpszClassName = "mainwin";
1206 myRegisterClass(&wc);
1207
1208 wc.style = 0;
1209 wc.lpfnWndProc = MainWndProc;
1210 wc.cbClsExtra = 0;
1211 wc.cbWndExtra = 0;
1212 wc.hInstance = hInstance;
1213 wc.hIcon = NULL;
1214 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
1215 wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
1216 wc.lpszMenuName = NULL;
1217 wc.lpszClassName = WC_GTKDIALOG;
1218 myRegisterClass(&wc);
1219
1220 wc.style = 0;
1221 wc.lpfnWndProc = GtkPanedProc;
1222 wc.cbClsExtra = 0;
1223 wc.cbWndExtra = 0;
1224 wc.hInstance = hInstance;
1225 wc.hIcon = NULL;
1226 wc.hCursor = LoadCursor(NULL, IDC_SIZEWE);
1227 wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
1228 wc.lpszMenuName = NULL;
1229 wc.lpszClassName = WC_GTKHPANED;
1230 myRegisterClass(&wc);
1231
1232 wc.style = 0;
1233 wc.lpfnWndProc = GtkPanedProc;
1234 wc.cbClsExtra = 0;
1235 wc.cbWndExtra = 0;
1236 wc.hInstance = hInstance;
1237 wc.hIcon = NULL;
1238 wc.hCursor = LoadCursor(NULL, IDC_SIZENS);
1239 wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
1240 wc.lpszMenuName = NULL;
1241 wc.lpszClassName = WC_GTKVPANED;
1242 myRegisterClass(&wc);
1243
1244 wc.style = 0;
1245 wc.lpfnWndProc = GtkSepProc;
1246 wc.cbClsExtra = 0;
1247 wc.cbWndExtra = 0;
1248 wc.hInstance = hInstance;
1249 wc.hIcon = NULL;
1250 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
1251 wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
1252 wc.lpszMenuName = NULL;
1253 wc.lpszClassName = WC_GTKSEP;
1254 myRegisterClass(&wc);
1255
1256 wc.style = 0;
1257 wc.lpfnWndProc = GtkUrlProc;
1258 wc.cbClsExtra = 0;
1259 wc.cbWndExtra = 0;
1260 wc.hInstance = hInstance;
1261 wc.hIcon = NULL;
1262 wc.hCursor = LoadCursor(NULL, IDC_HAND);
1263 wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
1264 wc.lpszMenuName = NULL;
1265 wc.lpszClassName = WC_GTKURL;
1266 myRegisterClass(&wc);
1267
1268 InitTreeViewClass(hInstance);
1269 }
1270 }
1271
1272 guint gtk_main_level(void)
1273 {
1274 return RecurseLevel;
1275 }
1276
1277 void gtk_widget_update(GtkWidget *widget, gboolean ForceResize)
1278 {
1279 GtkRequisition req;
1280 GtkWidget *window;
1281 GtkAllocation alloc;
1282
1283 if (!GTK_WIDGET_REALIZED(widget))
1284 return;
1285
1286 gtk_widget_size_request(widget, &req);
1287 window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
1288 if (window) {
1289 alloc.x = alloc.y = 0;
1290 alloc.width = window->requisition.width;
1291 alloc.height = window->requisition.height;
1292 gtk_window_handle_auto_size(GTK_WINDOW(window), &alloc);
1293 if (alloc.width != window->allocation.width
1294 || alloc.height != window->allocation.height || ForceResize) {
1295 gtk_widget_set_size(window, &alloc);
1296 }
1297 }
1298 }
1299
1300 void gtk_widget_show(GtkWidget *widget)
1301 {
1302 gtk_widget_show_full(widget, TRUE);
1303 }
1304
1305 gboolean gtk_widget_get_visible(GtkWidget *widget)
1306 {
1307 return (GTK_WIDGET_FLAGS(widget) & GTK_VISIBLE) != 0;
1308 }
1309
1310 void gtk_widget_show_full(GtkWidget *widget, gboolean recurse)
1311 {
1312 GtkAllocation alloc;
1313
1314 if (gtk_widget_get_visible(widget))
1315 return;
1316 GTK_WIDGET_SET_FLAGS(widget, GTK_VISIBLE);
1317
1318 if (recurse)
1319 gtk_widget_show_all_full(widget, TRUE);
1320 else
1321 gtk_signal_emit(G_OBJECT(widget), "show");
1322
1323 if (!GTK_WIDGET_REALIZED(widget)
1324 && G_OBJECT(widget)->klass == &GtkWindowClass) {
1325 gtk_widget_realize(widget);
1326 alloc.x = alloc.y = 0;
1327 alloc.width = widget->requisition.width;
1328 alloc.height = widget->requisition.height;
1329 gtk_window_set_initial_position(GTK_WINDOW(widget), &alloc);
1330 gtk_widget_set_size(widget, &alloc);
1331 ShowWindow(widget->hWnd, SW_SHOWNORMAL);
1332 UpdateWindow(widget->hWnd);
1333 } else if (GTK_WIDGET_REALIZED(widget)
1334 && G_OBJECT(widget)->klass != &GtkWindowClass) {
1335 gtk_widget_update(widget, TRUE);
1336 if (!recurse)
1337 ShowWindow(widget->hWnd, SW_SHOWNORMAL);
1338 }
1339 // g_print("widget show - set focus\n");
1340 gtk_widget_set_focus(widget);
1341 }
1342
1343 void gtk_widget_hide(GtkWidget *widget)
1344 {
1345 gtk_widget_hide_all_full(widget, FALSE);
1346 }
1347
1348 void gtk_widget_hide_full(GtkWidget *widget, gboolean recurse)
1349 {
1350 GtkAllocation alloc;
1351 GtkRequisition req;
1352 GtkWidget *window;
1353
1354 if (!gtk_widget_get_visible(widget))
1355 return;
1356
1357 if (recurse)
1358 gtk_widget_hide_all_full(widget, TRUE);
1359 else {
1360 gtk_signal_emit(G_OBJECT(widget), "hide");
1361 if (widget->hWnd)
1362 ShowWindow(widget->hWnd, SW_HIDE);
1363 }
1364
1365 GTK_WIDGET_UNSET_FLAGS(widget, GTK_VISIBLE);
1366
1367 gtk_widget_lose_focus(widget);
1368
1369 gtk_widget_size_request(widget, &req);
1370 if (GTK_WIDGET_REALIZED(widget)) {
1371 window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
1372 if (window) {
1373 alloc.x = alloc.y = 0;
1374 alloc.width = window->requisition.width;
1375 alloc.height = window->requisition.height;
1376 gtk_window_handle_auto_size(GTK_WINDOW(window), &alloc);
1377 gtk_widget_set_size(window, &alloc);
1378 }
1379 }
1380 }
1381
1382 void gtk_widget_set_focus(GtkWidget *widget)
1383 {
1384 GtkWidget *window;
1385
1386 if (!widget || !GTK_WIDGET_CAN_FOCUS(widget)
1387 || !GTK_WIDGET_SENSITIVE(widget) || !gtk_widget_get_visible(widget))
1388 return;
1389 window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
1390 gtk_window_update_focus(GTK_WINDOW(window));
1391 if (!window || GTK_WINDOW(window)->focus)
1392 return;
1393
1394 // g_print("Window %p focus set to widget %p
1395 // (%s)\n",window,widget,G_OBJECT(widget)->klass->Name);
1396 GTK_WINDOW(window)->focus = widget;
1397 if (widget->hWnd) {
1398 // if (!SetFocus(widget->hWnd)) g_print("SetFocus failed on widget
1399 // %p\n",widget);
1400 SetFocus(widget->hWnd);
1401 }
1402 // else g_print("Cannot call SetFocus - no hWnd\n");
1403 }
1404
1405 static BOOL CALLBACK SetFocusEnum(HWND hWnd, LPARAM data)
1406 {
1407 GtkWidget *widget;
1408 GtkWindow *window = GTK_WINDOW(data);
1409
1410 widget = GTK_WIDGET(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
1411 if (!widget || !GTK_WIDGET_CAN_FOCUS(widget) ||
1412 !GTK_WIDGET_SENSITIVE(widget) || !gtk_widget_get_visible(widget) ||
1413 window->focus == widget) {
1414 return TRUE;
1415 } else {
1416 // g_print("gtk_window_set_focus: focus set to widget %p\n",widget);
1417 window->focus = widget;
1418 SetFocus(widget->hWnd);
1419 return FALSE;
1420 }
1421 }
1422
1423 void gtk_window_set_focus(GtkWindow *window)
1424 {
1425 if (!window || !GTK_WIDGET(window)->hWnd)
1426 return;
1427 EnumChildWindows(GTK_WIDGET(window)->hWnd, SetFocusEnum, (LPARAM)window);
1428 }
1429
1430 void gtk_widget_lose_focus(GtkWidget *widget)
1431 {
1432 GtkWidget *window;
1433
1434 if (!widget || !GTK_WIDGET_CAN_FOCUS(widget))
1435 return;
1436 window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
1437 gtk_window_update_focus(GTK_WINDOW(window));
1438 if (GTK_WINDOW(window)->focus == widget) {
1439 gtk_window_set_focus(GTK_WINDOW(window));
1440 }
1441 }
1442
1443 void gtk_window_update_focus(GtkWindow *window)
1444 {
1445 GtkWidget *widget;
1446 HWND FocusWnd;
1447
1448 if (GTK_WIDGET(window)->hWnd != GetActiveWindow())
1449 return;
1450 FocusWnd = GetFocus();
1451 window->focus = NULL;
1452 if (FocusWnd) {
1453 widget = GTK_WIDGET(GetWindowLongPtrW(FocusWnd, GWLP_USERDATA));
1454 if (widget && GTK_WIDGET(window)->hWnd &&
1455 IsChild(GTK_WIDGET(window)->hWnd, FocusWnd)) {
1456 window->focus = widget;
1457 }
1458 }
1459 }
1460
1461 void gtk_widget_realize(GtkWidget *widget)
1462 {
1463 GtkRequisition req;
1464
1465 if (GTK_WIDGET_REALIZED(widget))
1466 return;
1467 gtk_signal_emit(G_OBJECT(widget), "realize", &req);
1468 if (widget->hWnd)
1469 SetWindowLongPtrW(widget->hWnd, GWLP_USERDATA, (LONG_PTR)widget);
1470 GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
1471 gtk_widget_set_sensitive(widget, GTK_WIDGET_SENSITIVE(widget));
1472
1473 gtk_widget_size_request(widget, &req);
1474 }
1475
1476 void gtk_widget_create(GtkWidget *widget)
1477 {
1478 GTK_WIDGET_SET_FLAGS(widget, GTK_SENSITIVE);
1479 widget->usize.width = 0;
1480 widget->usize.height = 0;
1481 }
1482
1483 void gtk_widget_destroy(GtkWidget *widget)
1484 {
1485 if (!widget)
1486 return;
1487
1488 /* If we're closing a modal window, reactivate the parent _before_
1489 * calling DestroyWindow, to avoid annoying flicker caused if Windows
1490 * chooses to reactivate another application when we close the modal
1491 * dialog */
1492 if (G_OBJECT(widget)->klass == &GtkWindowClass) {
1493 EnableParent(GTK_WINDOW(widget));
1494 }
1495
1496 gtk_widget_lose_focus(widget);
1497 if (widget->hWnd)
1498 DestroyWindow(widget->hWnd);
1499 widget->hWnd = NULL;
1500 gtk_signal_emit(G_OBJECT(widget), "destroy");
1501 g_free(widget);
1502 }
1503
1504 void gtk_widget_set_sensitive(GtkWidget *widget, gboolean sensitive)
1505 {
1506 if (sensitive) {
1507 GTK_WIDGET_SET_FLAGS(widget, GTK_SENSITIVE);
1508 if (widget->hWnd)
1509 EnableWindow(widget->hWnd, sensitive);
1510 gtk_widget_set_focus(widget);
1511 } else {
1512 GTK_WIDGET_UNSET_FLAGS(widget, GTK_SENSITIVE);
1513 gtk_widget_lose_focus(widget);
1514 if (widget->hWnd)
1515 EnableWindow(widget->hWnd, sensitive);
1516 }
1517
1518 gtk_signal_emit(G_OBJECT(widget), sensitive ? "enable" : "disable");
1519 if (sensitive && widget->hWnd
1520 && G_OBJECT(widget)->klass == &GtkWindowClass)
1521 SetActiveWindow(widget->hWnd);
1522 }
1523
1524 void gtk_widget_size_request(GtkWidget *widget,
1525 GtkRequisition *requisition)
1526 {
1527 GtkRequisition req;
1528
1529 requisition->width = requisition->height = 0;
1530 if (gtk_widget_get_visible(widget)) {
1531 gtk_signal_emit(G_OBJECT(widget), "size_request", requisition);
1532 }
1533 if (requisition->width < widget->usize.width)
1534 requisition->width = widget->usize.width;
1535 if (requisition->height < widget->usize.height)
1536 requisition->height = widget->usize.height;
1537 if (requisition->width != widget->requisition.width ||
1538 requisition->height != widget->requisition.height) {
1539 memcpy(&widget->requisition, requisition, sizeof(GtkRequisition));
1540 if (widget->parent)
1541 gtk_widget_size_request(widget->parent, &req);
1542 }
1543 }
1544
1545 void MapWidgetOrigin(GtkWidget *widget, POINT *pt)
1546 {
1547 HWND imm_parent, window_parent;
1548
1549 imm_parent = GetParent(widget->hWnd);
1550 window_parent = gtk_get_window_hwnd(widget);
1551 if (imm_parent && window_parent && imm_parent != window_parent) {
1552 MapWindowPoints(window_parent, imm_parent, pt, 1);
1553 }
1554 }
1555
1556 void gtk_widget_set_size(GtkWidget *widget, GtkAllocation *allocation)
1557 {
1558 gtk_signal_emit(G_OBJECT(widget), "set_size", allocation);
1559 memcpy(&widget->allocation, allocation, sizeof(GtkAllocation));
1560 if (widget->hWnd) {
1561 POINT pt;
1562
1563 pt.x = allocation->x;
1564 pt.y = allocation->y;
1565 MapWidgetOrigin(widget, &pt);
1566 SetWindowPos(widget->hWnd, HWND_TOP, pt.x, pt.y,
1567 allocation->width, allocation->height,
1568 SWP_NOZORDER |
1569 (G_OBJECT(widget)->klass ==
1570 &GtkWindowClass ? SWP_NOMOVE : 0));
1571 }
1572 }
1573
1574 GtkWidget *gtk_window_new(GtkWindowType type)
1575 {
1576 GtkWindow *win;
1577
1578 win = GTK_WINDOW(GtkNewObject(&GtkWindowClass));
1579
1580 win->title = g_strdup("");
1581 win->type = type;
1582 win->allow_grow = TRUE;
1583
1584 return GTK_WIDGET(win);
1585 }
1586
1587 void gtk_window_set_title(GtkWindow *window, const gchar *title)
1588 {
1589 g_free(window->title);
1590 window->title = g_strdup(title);
1591 }
1592
1593 gint gtk_window_delete_event(GtkWidget *widget, GdkEvent *event)
1594 {
1595 gtk_widget_destroy(widget);
1596 return TRUE;
1597 }
1598
1599 void gtk_window_set_default_size(GtkWindow *window, gint width,
1600 gint height)
1601 {
1602 window->default_width = width;
1603 window->default_height = height;
1604 }
1605
1606 void gtk_window_set_transient_for(GtkWindow *window, GtkWindow *parent)
1607 {
1608 if (window && parent) {
1609 GTK_WIDGET(window)->parent = GTK_WIDGET(parent);
1610 if (GTK_WIDGET(window)->hWnd && GTK_WIDGET(parent)->hWnd) {
1611 SetParent(GTK_WIDGET(window)->hWnd, GTK_WIDGET(parent)->hWnd);
1612 }
1613 }
1614 }
1615
1616 void gtk_window_set_policy(GtkWindow *window, gint allow_shrink,
1617 gint allow_grow, gint auto_shrink)
1618 {
1619 window->allow_shrink = allow_shrink;
1620 window->allow_grow = allow_grow;
1621 window->auto_shrink = auto_shrink;
1622 }
1623
1624 void gtk_window_set_menu(GtkWindow *window, GtkMenuBar *menu_bar)
1625 {
1626 HWND hWnd;
1627 HMENU hMenu;
1628
1629 hWnd = GTK_WIDGET(window)->hWnd;
1630 hMenu = GTK_MENU_SHELL(menu_bar)->menu;
1631
1632 if (hWnd && hMenu)
1633 SetMenu(hWnd, hMenu);
1634 window->menu_bar = menu_bar;
1635 }
1636
1637 void gtk_container_set_size(GtkWidget *widget, GtkAllocation *allocation)
1638 {
1639 GtkContainer *container;
1640 GtkAllocation child_alloc;
1641
1642 container = GTK_CONTAINER(widget);
1643 if (container->child) {
1644 child_alloc.x = allocation->x + container->border_width;
1645 child_alloc.y = allocation->y + container->border_width;
1646 child_alloc.width = allocation->width - container->border_width * 2;
1647 child_alloc.height = allocation->height - container->border_width * 2;
1648 gtk_widget_set_size(container->child, &child_alloc);
1649 }
1650 }
1651
1652 void gtk_frame_set_size(GtkWidget *widget, GtkAllocation *allocation)
1653 {
1654 GtkFrame *frame;
1655 GtkContainer *container;
1656
1657 frame = GTK_FRAME(widget);
1658 container = GTK_CONTAINER(widget);
1659 allocation->x += container->border_width;
1660 allocation->y += container->border_width;
1661 allocation->width -= container->border_width * 2;
1662 allocation->height -= container->border_width * 2;
1663
1664 if (container->child) {
1665 GtkAllocation child_alloc;
1666
1667 child_alloc.x = allocation->x + 3;
1668 child_alloc.y = allocation->y + 3 + frame->label_req.height;
1669 child_alloc.width = allocation->width - 6;
1670 child_alloc.height = allocation->height - frame->label_req.height - 6;
1671 gtk_widget_set_size(container->child, &child_alloc);
1672 }
1673 }
1674
1675 void gtk_frame_set_shadow_type(GtkFrame *frame, GtkShadowType type)
1676 {
1677 }
1678
1679 void gtk_container_size_request(GtkWidget *widget,
1680 GtkRequisition *requisition)
1681 {
1682 GtkContainer *container;
1683
1684 container = GTK_CONTAINER(widget);
1685 if (container->child) {
1686 requisition->width = container->child->requisition.width +
1687 container->border_width * 2;
1688 requisition->height = container->child->requisition.height +
1689 container->border_width * 2;
1690 }
1691 }
1692
1693 void gtk_window_size_request(GtkWidget *widget,
1694 GtkRequisition *requisition)
1695 {
1696 gtk_container_size_request(widget, requisition);
1697 requisition->width += GetSystemMetrics(SM_CXSIZEFRAME) * 2;
1698 requisition->height += GetSystemMetrics(SM_CYSIZEFRAME) * 2 +
1699 GetSystemMetrics(SM_CYCAPTION);
1700 if (GTK_WINDOW(widget)->menu_bar) {
1701 requisition->height += GetSystemMetrics(SM_CYMENU);
1702 }
1703 }
1704
1705 void gtk_window_set_size(GtkWidget *widget, GtkAllocation *allocation)
1706 {
1707 GtkAllocation child_alloc;
1708 GtkWindow *window = GTK_WINDOW(widget);
1709
1710 child_alloc.x = child_alloc.y = 0;
1711 child_alloc.width =
1712 allocation->width - GetSystemMetrics(SM_CXSIZEFRAME) * 2;
1713 child_alloc.height =
1714 allocation->height - GetSystemMetrics(SM_CYSIZEFRAME) * 2 -
1715 GetSystemMetrics(SM_CYCAPTION);
1716 if (window->menu_bar) {
1717 child_alloc.height -= GetSystemMetrics(SM_CYMENU);
1718 }
1719 gtk_container_set_size(widget, &child_alloc);
1720 }
1721
1722 void gtk_button_size_request(GtkWidget *widget,
1723 GtkRequisition *requisition)
1724 {
1725 SIZE size, minsize;
1726 GtkButton *but = GTK_BUTTON(widget);
1727
1728 gtk_container_size_request(widget, requisition);
1729
1730 /* Without minsize, an unexpanded "OK" button looks silly... */
1731 if (GetTextSize(widget->hWnd, but->text, &size, defFont)
1732 && GetTextSize(widget->hWnd, "Cancel", &minsize, defFont)) {
1733 size.cx = MAX(size.cx, minsize.cx);
1734 size.cy = MAX(size.cy, minsize.cy);
1735 requisition->width = size.cx + 15;
1736 requisition->height = size.cy + 10;
1737 }
1738 }
1739
1740 BOOL GetTextSize(HWND hWnd, char *text, LPSIZE lpSize, HFONT hFont)
1741 {
1742 HDC hDC;
1743 BOOL RetVal = 0;
1744 SIZE LineSize;
1745 HFONT oldFont;
1746 char *endpt, *startpt;
1747
1748 hDC = GetDC(hWnd);
1749 oldFont = SelectObject(hDC, hFont);
1750
1751 startpt = text;
1752 lpSize->cx = lpSize->cy = 0;
1753
1754 while (startpt) {
1755 endpt = startpt;
1756 while (endpt && *endpt != '\n' && *endpt)
1757 endpt++;
1758 if (endpt) {
1759 if ((endpt == startpt
1760 && GetTextExtentPoint32(hDC, "W", 1, &LineSize))
1761 || (endpt != startpt
1762 && GetTextExtentPoint32(hDC, startpt, endpt - startpt,
1763 &LineSize))) {
1764 RetVal = 1;
1765 if (LineSize.cx > lpSize->cx)
1766 lpSize->cx = LineSize.cx;
1767 lpSize->cy += LineSize.cy;
1768 }
1769 if (*endpt == '\0')
1770 break;
1771 startpt = endpt + 1;
1772 } else
1773 break;
1774 }
1775 SelectObject(hDC, oldFont);
1776 ReleaseDC(hWnd, hDC);
1777 return RetVal;
1778 }
1779
1780 void gtk_entry_size_request(GtkWidget *widget, GtkRequisition *requisition)
1781 {
1782 SIZE size;
1783
1784 if (GetTextSize(widget->hWnd, "text", &size, defFont)) {
1785 requisition->width = size.cx * 6;
1786 requisition->height = size.cy + 8;
1787 }
1788 }
1789
1790 void gtk_text_size_request(GtkWidget *widget, GtkRequisition *requisition)
1791 {
1792 SIZE size;
1793
1794 if (GetTextSize(widget->hWnd, "Sample text", &size, defFont)) {
1795 requisition->width = size.cx;
1796 requisition->height = size.cy * 2 + 8;
1797 }
1798 }
1799
1800 void gtk_frame_size_request(GtkWidget *widget, GtkRequisition *requisition)
1801 {
1802 SIZE size;
1803 GtkFrame *frame = GTK_FRAME(widget);
1804
1805 gtk_container_size_request(widget, requisition);
1806
1807 if (GetTextSize(widget->hWnd, frame->text, &size, defFont)) {
1808 frame->label_req.width = size.cx;
1809 frame->label_req.height = size.cy;
1810 if (size.cx > requisition->width)
1811 requisition->width = size.cx;
1812 requisition->width += 6;
1813 requisition->height += size.cy + 6;
1814 }
1815 }
1816
1817
1818 void gtk_check_button_size_request(GtkWidget *widget,
1819 GtkRequisition *requisition)
1820 {
1821 gtk_button_size_request(widget, requisition);
1822 requisition->width += 10;
1823 }
1824
1825 GtkWidget *gtk_button_new_with_label(const gchar *label)
1826 {
1827 GtkButton *but;
1828
1829 but = GTK_BUTTON(GtkNewObject(&GtkButtonClass));
1830 but->text = g_strdup(label);
1831 g_strdelimit(but->text, "_", '&');
1832
1833 return GTK_WIDGET(but);
1834 }
1835
1836 GtkWidget *gtk_check_button_new_with_label(const gchar *label)
1837 {
1838 GtkButton *but;
1839
1840 but = GTK_BUTTON(GtkNewObject(&GtkCheckButtonClass));
1841 but->text = g_strdup(label);
1842 g_strdelimit(but->text, "_", '&');
1843
1844 return GTK_WIDGET(but);
1845 }
1846
1847 GtkWidget *gtk_radio_button_new_with_label_from_widget(GtkRadioButton *group,
1848 const gchar *label)
1849 {
1850 GSList *list;
1851
1852 list = gtk_radio_button_get_group(group);
1853 return (gtk_radio_button_new_with_label(list, label));
1854 }
1855
1856 GtkWidget *gtk_radio_button_new_with_label(GSList *group,
1857 const gchar *label)
1858 {
1859 GtkButton *but;
1860 GtkRadioButton *radio;
1861 GSList *listpt;
1862
1863 but = GTK_BUTTON(GtkNewObject(&GtkRadioButtonClass));
1864 but->text = g_strdup(label);
1865 g_strdelimit(but->text, "_", '&');
1866
1867 if (group == NULL)
1868 GTK_TOGGLE_BUTTON(but)->toggled = TRUE;
1869
1870 group = g_slist_append(group, GTK_RADIO_BUTTON(but));
1871 for (listpt = group; listpt; listpt = g_slist_next(listpt)) {
1872 radio = GTK_RADIO_BUTTON(listpt->data);
1873 radio->group = group;
1874 }
1875
1876 return GTK_WIDGET(but);
1877 }
1878
1879 GtkWidget *gtk_label_new(const gchar *text)
1880 {
1881 GtkLabel *label;
1882
1883 label = GTK_LABEL(GtkNewObject(&GtkLabelClass));
1884 gtk_label_set_text(label, text);
1885
1886 return GTK_WIDGET(label);
1887 }
1888
1889 GtkWidget *gtk_url_new(const gchar *text, const gchar *target,
1890 const gchar *bin)
1891 {
1892 GtkUrl *url;
1893
1894 url = GTK_URL(GtkNewObject(&GtkUrlClass));
1895
1896 GTK_LABEL(url)->text = g_strdup(text);
1897 url->target = g_strdup(target);
1898
1899 /* N.B. "bin" argument is ignored under Win32 */
1900
1901 return GTK_WIDGET(url);
1902 }
1903
1904 GtkWidget *gtk_box_new(GtkOrientation orientation, gint spacing)
1905 {
1906 GtkBox *box;
1907
1908 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
1909 box = GTK_BOX(GtkNewObject(&GtkHBoxClass));
1910 } else {
1911 box = GTK_BOX(GtkNewObject(&GtkVBoxClass));
1912 }
1913
1914 box->spacing = spacing;
1915 box->homogeneous = FALSE;
1916 return GTK_WIDGET(box);
1917 }
1918
1919 void gtk_box_set_homogeneous(GtkBox *box, gboolean homogeneous)
1920 {
1921 box->homogeneous = homogeneous;
1922 }
1923
1924 GtkWidget *gtk_frame_new(const gchar *text)
1925 {
1926 GtkFrame *frame;
1927
1928 frame = GTK_FRAME(GtkNewObject(&GtkFrameClass));
1929 frame->text = g_strdup(text);
1930
1931 return GTK_WIDGET(frame);
1932 }
1933
1934 GtkWidget *gtk_text_new(GtkAdjustment *hadj, GtkAdjustment *vadj)
1935 {
1936 GtkText *text;
1937
1938 text = GTK_TEXT(GtkNewObject(&GtkTextClass));
1939 text->buffer = g_new(GtkTextBuffer, 1);
1940 g_datalist_init(&text->buffer->tags);
1941 return GTK_WIDGET(text);
1942 }
1943
1944 GtkWidget *gtk_scrolled_text_view_new(GtkWidget **pack_widg)
1945 {
1946 GtkWidget *text;
1947
1948 text = gtk_text_new(NULL, NULL);
1949 *pack_widg = text;
1950 return text;
1951 }
1952
1953 GtkWidget *gtk_entry_new()
1954 {
1955 GtkEntry *entry;
1956
1957 entry = GTK_ENTRY(GtkNewObject(&GtkEntryClass));
1958 entry->is_visible = TRUE;
1959
1960 return GTK_WIDGET(entry);
1961 }
1962
1963 GSList *gtk_radio_button_get_group(GtkRadioButton *radio_button)
1964 {
1965 return radio_button->group;
1966 }
1967
1968 static void gtk_editable_sync_text(GtkEditable *editable)
1969 {
1970 HWND hWnd;
1971 gchar *buffer;
1972
1973 hWnd = GTK_WIDGET(editable)->hWnd;
1974 if (!hWnd) {
1975 return;
1976 }
1977
1978 buffer = myGetWindowText(hWnd);
1979 g_string_assign(editable->text, buffer);
1980 g_free(buffer);
1981 }
1982
1983 void gtk_editable_insert_text(GtkEditable *editable, const gchar *new_text,
1984 gint new_text_length, gint *position)
1985 {
1986 GtkWidget *widget = GTK_WIDGET(editable);
1987 HWND hWnd;
1988 gint i;
1989 GString *newstr;
1990
1991 gtk_editable_sync_text(editable);
1992
1993 /* Convert Unix-style lone '\n' to Windows-style '\r\n' */
1994 newstr = g_string_new("");
1995 for (i = 0; i < new_text_length && new_text[i]; i++) {
1996 if (new_text[i] == '\n' && (i == 0 || new_text[i - 1] != '\r')) {
1997 g_string_append_c(newstr, '\r');
1998 }
1999 g_string_append_c(newstr, new_text[i]);
2000 }
2001 g_string_insert(editable->text, *position, newstr->str);
2002
2003 hWnd = widget->hWnd;
2004 if (hWnd) {
2005 SendMessageW(hWnd, EM_SETSEL, (WPARAM)*position, (LPARAM)*position);
2006 myEditReplaceSel(hWnd, FALSE, newstr->str);
2007 *position += newstr->len;
2008 gtk_editable_set_position(editable, *position);
2009 }
2010 g_string_free(newstr, TRUE);
2011 }
2012
2013 static void gtk_text_view_set_format(GtkTextView *textview,
2014 const gchar *tagname, guint len,
2015 gint endpos)
2016 {
2017 CHARFORMAT *cf, cfdef;
2018 GtkWidget *widget = GTK_WIDGET(textview);
2019 GtkTextBuffer *buffer;
2020 DWORD st, end;
2021
2022 if (!GTK_WIDGET_REALIZED(widget)) {
2023 return;
2024 }
2025
2026 /* RichEdit controls do something odd behind the scenes with line ends,
2027 * so we use our guess for the last character position, and then read
2028 * back the resultant selection to get the true "length" of the control */
2029 SendMessageW(widget->hWnd, EM_SETSEL, (WPARAM)endpos, (LPARAM)endpos);
2030 SendMessageW(widget->hWnd, EM_GETSEL, (WPARAM)&st, (LPARAM)&end);
2031 endpos = (gint)end;
2032
2033 SendMessageW(widget->hWnd, EM_SETSEL, (WPARAM)(endpos - len),
2034 (LPARAM)endpos);
2035
2036 if (!tagname || !(buffer = gtk_text_view_get_buffer(textview))
2037 || !(cf = g_datalist_get_data(&buffer->tags, tagname))) {
2038 cfdef.cbSize = sizeof(CHARFORMAT);
2039 cfdef.dwMask = CFM_COLOR;
2040 cfdef.dwEffects = CFE_AUTOCOLOR;
2041 cf = &cfdef;
2042 }
2043 SendMessageW(widget->hWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)cf);
2044 }
2045
2046 void gtk_editable_delete_text(GtkEditable *editable,
2047 gint start_pos, gint end_pos)
2048 {
2049 GtkWidget *widget = GTK_WIDGET(editable);
2050 HWND hWnd;
2051
2052 gtk_editable_sync_text(editable);
2053 if (end_pos < 0 || end_pos >= editable->text->len)
2054 end_pos = editable->text->len;
2055 g_string_erase(editable->text, start_pos, end_pos - start_pos);
2056
2057 hWnd = widget->hWnd;
2058 if (hWnd) {
2059 mySetWindowText(hWnd, editable->text->str);
2060 }
2061 }
2062
2063 gchar *gtk_editable_get_chars(GtkEditable *editable,
2064 gint start_pos, gint end_pos)
2065 {
2066 gchar *retbuf;
2067 gint copylen;
2068
2069 gtk_editable_sync_text(editable);
2070 if (end_pos < 0 || end_pos >= editable->text->len)
2071 end_pos = editable->text->len;
2072 copylen = end_pos - start_pos;
2073 retbuf = g_new(gchar, copylen + 1);
2074
2075 memcpy(retbuf, &editable->text->str[start_pos], copylen);
2076 retbuf[copylen] = '\0';
2077 return retbuf;
2078 }
2079
2080 void gtk_editable_set_editable(GtkEditable *editable, gboolean is_editable)
2081 {
2082 GtkWidget *widget = GTK_WIDGET(editable);
2083 HWND hWnd;
2084
2085 editable->is_editable = is_editable;
2086 hWnd = widget->hWnd;
2087 if (hWnd)
2088 SendMessageW(hWnd, EM_SETREADONLY, (WPARAM)(!is_editable), (LPARAM)0);
2089 }
2090
2091 void gtk_editable_set_position(GtkEditable *editable, gint position)
2092 {
2093 GtkWidget *widget = GTK_WIDGET(editable);
2094 HWND hWnd;
2095
2096 if (!GTK_WIDGET_REALIZED(widget))
2097 return;
2098 hWnd = widget->hWnd;
2099
2100 /* RichEdit 2.0 doesn't appear to show the caret unless we show the
2101 * selection */
2102 SendMessageW(hWnd, EM_HIDESELECTION, 0, 0);
2103 SendMessageW(hWnd, EM_SETSEL, (WPARAM)position, (LPARAM)position);
2104 SendMessageW(hWnd, EM_SCROLLCARET, 0, 0);
2105 SendMessageW(hWnd, EM_HIDESELECTION, 1, 0);
2106 }
2107
2108 gint gtk_editable_get_position(GtkEditable *editable)
2109 {
2110 GtkWidget *widget = GTK_WIDGET(editable);
2111 HWND hWnd;
2112 DWORD EndPos;
2113
2114 if (!GTK_WIDGET_REALIZED(widget))
2115 return 0;
2116 hWnd = widget->hWnd;
2117 SendMessageW(hWnd, EM_GETSEL, (WPARAM)NULL, (LPARAM)&EndPos);
2118 return (gint)EndPos;
2119 }
2120
2121 guint gtk_text_get_length(GtkText *text)
2122 {
2123 return GTK_EDITABLE(text)->text->len;
2124 }
2125
2126 void gtk_box_pack_start(GtkBox *box, GtkWidget *child, gboolean Expand,
2127 gboolean Fill, gint Padding)
2128 {
2129 GtkBoxChild *newChild;
2130
2131 newChild = g_new0(GtkBoxChild, 1);
2132
2133 newChild->widget = child;
2134 newChild->expand = Expand;
2135 newChild->fill = Fill;
2136
2137 box->children = g_list_append(box->children, (gpointer)newChild);
2138 child->parent = GTK_WIDGET(box);
2139 if (GTK_WIDGET_REALIZED(GTK_WIDGET(box))) {
2140 gtk_widget_realize(child);
2141 gtk_widget_update(GTK_WIDGET(box), TRUE);
2142 }
2143 }
2144
2145 void gtk_button_destroy(GtkWidget *widget)
2146 {
2147 g_free(GTK_BUTTON(widget)->text);
2148 }
2149
2150 void gtk_frame_destroy(GtkWidget *widget)
2151 {
2152 gtk_container_destroy(widget);
2153 g_free(GTK_FRAME(widget)->text);
2154 }
2155
2156 void gtk_container_destroy(GtkWidget *widget)
2157 {
2158 GtkWidget *child = GTK_CONTAINER(widget)->child;
2159
2160 if (child)
2161 gtk_widget_destroy(child);
2162 }
2163
2164 void gtk_box_destroy(GtkWidget *widget)
2165 {
2166 GtkBoxChild *child;
2167 GList *children;
2168
2169 gtk_container_destroy(widget);
2170
2171 for (children = GTK_BOX(widget)->children; children;
2172 children = g_list_next(children)) {
2173 child = (GtkBoxChild *)(children->data);
2174 if (child && child->widget)
2175 gtk_widget_destroy(child->widget);
2176 g_free(child);
2177 }
2178 g_list_free(GTK_BOX(widget)->children);
2179 }
2180
2181 static void gtk_text_destroy(GtkWidget *widget)
2182 {
2183 GtkText *text = GTK_TEXT(widget);
2184 GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
2185
2186 if (buffer) {
2187 g_datalist_clear(&buffer->tags);
2188 g_free(buffer);
2189 }
2190 }
2191
2192 static void EnableParent(GtkWindow *window)
2193 {
2194 GtkWidget *parent;
2195
2196 parent = GTK_WIDGET(window)->parent;
2197
2198 if (window->modal && parent) {
2199 GSList *list;
2200 GtkWindow *listwin;
2201 HWND ourhWnd, parenthWnd;
2202
2203 ourhWnd = GTK_WIDGET(window)->hWnd;
2204 parenthWnd = parent->hWnd;
2205 for (list = WindowList; list; list = g_slist_next(list)) {
2206 listwin = GTK_WINDOW(list->data);
2207 if (listwin != window && listwin->modal
2208 && gtk_widget_get_visible(GTK_WIDGET(listwin))
2209 && GTK_WIDGET(listwin)->parent == parent)
2210 return;
2211 }
2212 gtk_widget_set_sensitive(parent, TRUE);
2213
2214 if (ourhWnd && parenthWnd && ourhWnd == GetActiveWindow()) {
2215 SetActiveWindow(parenthWnd);
2216 }
2217 }
2218 }
2219
2220 void gtk_window_destroy(GtkWidget *widget)
2221 {
2222 GtkWindow *window = GTK_WINDOW(widget);
2223
2224 WindowList = g_slist_remove(WindowList, (gpointer)window);
2225 gtk_container_destroy(widget);
2226 if (window->accel_group)
2227 gtk_accel_group_destroy(window->accel_group);
2228 if (window->hAccel)
2229 DestroyAcceleratorTable(window->hAccel);
2230 g_free(window->title);
2231 }
2232
2233 void gtk_window_show(GtkWidget *widget)
2234 {
2235 GtkWindow *window = GTK_WINDOW(widget);
2236
2237 if (window->modal && widget->parent)
2238 gtk_widget_set_sensitive(widget->parent, FALSE);
2239 }
2240
2241 void gtk_window_hide(GtkWidget *widget)
2242 {
2243 GtkWindow *window = GTK_WINDOW(widget);
2244
2245 EnableParent(window);
2246 }
2247
2248 void gtk_hbox_size_request(GtkWidget *widget, GtkRequisition *requisition)
2249 {
2250 GtkBoxChild *child;
2251 GList *children;
2252 GtkRequisition *child_req;
2253 gint spacing = GTK_BOX(widget)->spacing, numchildren = 0;
2254 gint maxreq = 0;
2255 gboolean homogeneous = GTK_BOX(widget)->homogeneous;
2256 gboolean first = TRUE;
2257
2258 for (children = GTK_BOX(widget)->children; children;
2259 children = g_list_next(children)) {
2260 child = (GtkBoxChild *)(children->data);
2261 if (child && child->widget && gtk_widget_get_visible(child->widget)) {
2262 if (first) {
2263 first = FALSE;
2264 } else {
2265 requisition->width += spacing;
2266 }
2267 child_req = &child->widget->requisition;
2268 if (homogeneous) {
2269 numchildren++;
2270 if (child_req->width > maxreq)
2271 maxreq = child_req->width;
2272 } else {
2273 requisition->width += child_req->width;
2274 }
2275 if (child_req->height > requisition->height)
2276 requisition->height = child_req->height;
2277 }
2278 }
2279 if (homogeneous)
2280 requisition->width += numchildren * maxreq;
2281 GTK_BOX(widget)->maxreq = maxreq;
2282 requisition->width += 2 * GTK_CONTAINER(widget)->border_width;
2283 requisition->height += 2 * GTK_CONTAINER(widget)->border_width;
2284 }
2285
2286 void gtk_vbox_size_request(GtkWidget *widget, GtkRequisition *requisition)
2287 {
2288 GtkBoxChild *child;
2289 GList *children;
2290 GtkRequisition *child_req;
2291 gint spacing = GTK_BOX(widget)->spacing, numchildren = 0;
2292 gint maxreq = 0;
2293 gboolean homogeneous = GTK_BOX(widget)->homogeneous;
2294 gboolean first = TRUE;
2295
2296 for (children = GTK_BOX(widget)->children; children;
2297 children = g_list_next(children)) {
2298 child = (GtkBoxChild *)(children->data);
2299 if (child && child->widget && gtk_widget_get_visible(child->widget)) {
2300 if (first) {
2301 first = FALSE;
2302 } else {
2303 requisition->height += spacing;
2304 }
2305 child_req = &child->widget->requisition;
2306 child_req = &child->widget->requisition;
2307 if (homogeneous) {
2308 numchildren++;
2309 if (child_req->height > maxreq)
2310 maxreq = child_req->height;
2311 } else {
2312 requisition->height += child_req->height;
2313 }
2314 if (child_req->width > requisition->width)
2315 requisition->width = child_req->width;
2316 }
2317 }
2318 if (homogeneous)
2319 requisition->height += numchildren * maxreq;
2320 GTK_BOX(widget)->maxreq = maxreq;
2321 requisition->width += 2 * GTK_CONTAINER(widget)->border_width;
2322 requisition->height += 2 * GTK_CONTAINER(widget)->border_width;
2323 }
2324
2325 static void gtk_box_count_children(GtkBox *box, gint16 allocation,
2326 gint16 requisition, gint *extra)
2327 {
2328 GtkBoxChild *child;
2329 GList *children;
2330 gint NumCanExpand = 0;
2331
2332 for (children = box->children; children;
2333 children = g_list_next(children)) {
2334 child = (GtkBoxChild *)(children->data);
2335 if (child && child->widget && gtk_widget_get_visible(child->widget) &&
2336 child->expand)
2337 NumCanExpand++;
2338 }
2339
2340 *extra = allocation - requisition;
2341 if (NumCanExpand > 0)
2342 *extra /= NumCanExpand;
2343 }
2344
2345 static void gtk_box_size_child(GtkBox *box, GtkBoxChild *child,
2346 gint extra, gint16 maxpos,
2347 gint16 requisition, gint16 *pos,
2348 gint16 *size, GList *listpt, gint16 *curpos)
2349 {
2350 gboolean TooSmall = FALSE;
2351
2352 *pos = *curpos;
2353 if (extra < 0) {
2354 extra = 0;
2355 TooSmall = TRUE;
2356 }
2357 if (child->expand && child->fill) {
2358 *size = requisition + extra;
2359 *curpos += requisition + extra;
2360 } else if (child->expand) {
2361 *size = requisition;
2362 *pos += extra / 2;
2363 *curpos += requisition + extra;
2364 } else {
2365 *size = requisition;
2366 *curpos += requisition;
2367 }
2368 *curpos += box->spacing;
2369 if (TooSmall) {
2370 if (*pos >= maxpos) {
2371 *pos = *size = 0;
2372 } else if (*pos + *size > maxpos) {
2373 *size = maxpos - *pos;
2374 }
2375 }
2376 }
2377
2378 void gtk_hbox_set_size(GtkWidget *widget, GtkAllocation *allocation)
2379 {
2380 GtkBox *box;
2381 GtkBoxChild *child;
2382 GList *children;
2383 GtkAllocation child_alloc;
2384 gint extra;
2385 gint16 curpos;
2386 gint maxpos, height, border_width;
2387
2388 border_width = GTK_CONTAINER(widget)->border_width;
2389 maxpos = allocation->x + allocation->width - border_width;
2390 height = allocation->height - 2 * border_width;
2391
2392 box = GTK_BOX(widget);
2393
2394 curpos = allocation->x + border_width;
2395 gtk_box_count_children(box, allocation->width, widget->requisition.width,
2396 &extra);
2397
2398 for (children = box->children; children;
2399 children = g_list_next(children)) {
2400 child = (GtkBoxChild *)(children->data);
2401 if (child && child->widget && gtk_widget_get_visible(child->widget)) {
2402 gtk_box_size_child(box, child, extra, maxpos,
2403 box->homogeneous ? box->maxreq :
2404 child->widget->requisition.width,
2405 &child_alloc.x, &child_alloc.width,
2406 children, &curpos);
2407 child_alloc.y = allocation->y + border_width;
2408 child_alloc.height = height;
2409 gtk_widget_set_size(child->widget, &child_alloc);
2410 }
2411 }
2412 }
2413
2414 void gtk_vbox_set_size(GtkWidget *widget, GtkAllocation *allocation)
2415 {
2416 GtkBox *box;
2417 GtkBoxChild *child;
2418 GList *children;
2419 GtkAllocation child_alloc;
2420 gint extra;
2421 gint16 curpos;
2422 gint width, maxpos, border_width;
2423
2424 border_width = GTK_CONTAINER(widget)->border_width;
2425 width = allocation->width - 2 * border_width;
2426 maxpos = allocation->y + allocation->height - border_width;
2427
2428 box = GTK_BOX(widget);
2429
2430 curpos = allocation->y + border_width;
2431 gtk_box_count_children(box, allocation->height,
2432 widget->requisition.height, &extra);
2433
2434 for (children = box->children; children;
2435 children = g_list_next(children)) {
2436 child = (GtkBoxChild *)(children->data);
2437 if (child && child->widget && gtk_widget_get_visible(child->widget)) {
2438 gtk_box_size_child(box, child, extra, maxpos,
2439 box->homogeneous ? box->maxreq :
2440 child->widget->requisition.height,
2441 &child_alloc.y, &child_alloc.height,
2442 children, &curpos);
2443 child_alloc.x = allocation->x + border_width;
2444 child_alloc.width = width;
2445 gtk_widget_set_size(child->widget, &child_alloc);
2446 }
2447 }
2448 }
2449
2450 void gtk_window_realize(GtkWidget *widget)
2451 {
2452 GtkWindow *win = GTK_WINDOW(widget);
2453 HWND Parent;
2454 DWORD resize = 0;
2455
2456 if (win->allow_shrink || win->allow_grow)
2457 resize = WS_SIZEBOX;
2458
2459 Parent = gtk_get_parent_hwnd(widget->parent);
2460 if (Parent) {
2461 widget->hWnd = myCreateDialog(hInst, "gtkdialog", Parent, MainDlgProc);
2462 mySetWindowText(widget->hWnd, win->title);
2463 } else {
2464 widget->hWnd = myCreateWindow("mainwin", win->title,
2465 WS_OVERLAPPEDWINDOW | CS_HREDRAW |
2466 CS_VREDRAW | resize, CW_USEDEFAULT, 0, 0,
2467 0, Parent, NULL, hInst, NULL);
2468 if (!TopLevel)
2469 TopLevel = widget->hWnd;
2470 }
2471 WindowList = g_slist_append(WindowList, (gpointer)win);
2472 gtk_set_default_font(widget->hWnd);
2473 gtk_container_realize(widget);
2474
2475 if (win->accel_group && win->accel_group->numaccel) {
2476 win->hAccel = CreateAcceleratorTable(win->accel_group->accel,
2477 win->accel_group->numaccel);
2478 }
2479 }
2480
2481 void gtk_container_realize(GtkWidget *widget)
2482 {
2483 GtkWidget *child = GTK_CONTAINER(widget)->child;
2484
2485 if (child)
2486 gtk_widget_realize(child);
2487 }
2488
2489 void gtk_box_realize(GtkWidget *widget)
2490 {
2491 GtkBoxChild *child;
2492 GList *children;
2493
2494 gtk_container_realize(widget);
2495
2496 for (children = GTK_BOX(widget)->children; children;
2497 children = g_list_next(children)) {
2498 child = (GtkBoxChild *)(children->data);
2499 if (child && child->widget)
2500 gtk_widget_realize(child->widget);
2501 }
2502 }
2503
2504 void gtk_button_realize(GtkWidget *widget)
2505 {
2506 GtkButton *but = GTK_BUTTON(widget);
2507 HWND Parent;
2508
2509 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
2510 Parent = gtk_get_parent_hwnd(widget);
2511 widget->hWnd = myCreateWindow("BUTTON", but->text,
2512 WS_CHILD | WS_TABSTOP |
2513 (GTK_WIDGET_FLAGS(widget) & GTK_IS_DEFAULT ?
2514 BS_DEFPUSHBUTTON : BS_PUSHBUTTON),
2515 widget->allocation.x, widget->allocation.y,
2516 widget->allocation.width,
2517 widget->allocation.height, Parent, NULL,
2518 hInst, NULL);
2519 gtk_set_default_font(widget->hWnd);
2520 }
2521
2522 void gtk_entry_realize(GtkWidget *widget)
2523 {
2524 HWND Parent;
2525
2526 Parent = gtk_get_parent_hwnd(widget);
2527 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
2528 widget->hWnd = myCreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
2529 WS_CHILD | WS_TABSTOP | ES_AUTOHSCROLL,
2530 widget->allocation.x, widget->allocation.y,
2531 widget->allocation.width,
2532 widget->allocation.height, Parent, NULL,
2533 hInst, NULL);
2534 /* Subclass the window (we assume that all edit boxes have the same
2535 * window procedure) */
2536 wpOrigEntryProc = (WNDPROC)SetWindowLongPtrW(widget->hWnd,
2537 GWLP_WNDPROC,
2538 (LONG_PTR)EntryWndProc);
2539 gtk_set_default_font(widget->hWnd);
2540 gtk_editable_set_editable(GTK_EDITABLE(widget),
2541 GTK_EDITABLE(widget)->is_editable);
2542 gtk_entry_set_visibility(GTK_ENTRY(widget),
2543 GTK_ENTRY(widget)->is_visible);
2544 mySetWindowText(widget->hWnd, GTK_EDITABLE(widget)->text->str);
2545 }
2546
2547 void gtk_text_realize(GtkWidget *widget)
2548 {
2549 HWND Parent;
2550 gboolean editable;
2551
2552 Parent = gtk_get_parent_hwnd(widget);
2553 editable = GTK_EDITABLE(widget)->is_editable;
2554 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
2555 widget->hWnd = myCreateWindowEx(WS_EX_CLIENTEDGE,
2556 HaveRichEdit ? RichEditClass : "EDIT", "",
2557 WS_CHILD | (editable ? WS_TABSTOP : 0) |
2558 ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL |
2559 (GTK_TEXT(widget)->word_wrap ?
2560 0 : ES_AUTOHSCROLL), 0, 0, 0,
2561 0, Parent, NULL, hInst, NULL);
2562 /* Subclass the window (we assume that all multiline edit boxes have the
2563 * same window procedure) */
2564 wpOrigTextProc = (WNDPROC)SetWindowLongPtrW(widget->hWnd,
2565 GWLP_WNDPROC,
2566 (LONG_PTR)TextWndProc);
2567 gtk_set_default_font(widget->hWnd);
2568 gtk_editable_set_editable(GTK_EDITABLE(widget),
2569 GTK_EDITABLE(widget)->is_editable);
2570 mySetWindowText(widget->hWnd, GTK_EDITABLE(widget)->text->str);
2571 }
2572
2573 void gtk_frame_realize(GtkWidget *widget)
2574 {
2575 HWND Parent;
2576 GtkFrame *frame = GTK_FRAME(widget);
2577
2578 Parent = gtk_get_parent_hwnd(widget);
2579 widget->hWnd = myCreateWindow("BUTTON", frame->text,
2580 WS_CHILD | BS_GROUPBOX,
2581 widget->allocation.x, widget->allocation.y,
2582 widget->allocation.width,
2583 widget->allocation.height,
2584 Parent, NULL, hInst, NULL);
2585 gtk_set_default_font(widget->hWnd);
2586 gtk_container_realize(widget);
2587 }
2588
2589 void gtk_check_button_realize(GtkWidget *widget)
2590 {
2591 GtkButton *but = GTK_BUTTON(widget);
2592 HWND Parent;
2593 gboolean toggled;
2594
2595 Parent = gtk_get_parent_hwnd(widget);
2596 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
2597 widget->hWnd = myCreateWindow("BUTTON", but->text,
2598 WS_CHILD | WS_TABSTOP | BS_CHECKBOX,
2599 widget->allocation.x, widget->allocation.y,
2600 widget->allocation.width,
2601 widget->allocation.height, Parent, NULL,
2602 hInst, NULL);
2603 gtk_set_default_font(widget->hWnd);
2604 g_signal_connect(G_OBJECT(widget), "clicked",
2605 gtk_toggle_button_toggled, NULL);
2606 g_signal_connect(G_OBJECT(widget), "toggled",
2607 gtk_check_button_toggled, NULL);
2608 toggled = GTK_TOGGLE_BUTTON(widget)->toggled;
2609 GTK_TOGGLE_BUTTON(widget)->toggled = !toggled;
2610 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), toggled);
2611 }
2612
2613 void gtk_radio_button_realize(GtkWidget *widget)
2614 {
2615 GtkButton *but = GTK_BUTTON(widget);
2616 HWND Parent;
2617 gboolean toggled;
2618
2619 Parent = gtk_get_parent_hwnd(widget);
2620 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
2621 widget->hWnd = myCreateWindow("BUTTON", but->text,
2622 WS_CHILD | WS_TABSTOP | BS_RADIOBUTTON,
2623 widget->allocation.x, widget->allocation.y,
2624 widget->allocation.width,
2625 widget->allocation.height, Parent, NULL,
2626 hInst, NULL);
2627 gtk_set_default_font(widget->hWnd);
2628 g_signal_connect(G_OBJECT(widget), "clicked",
2629 gtk_radio_button_clicked, NULL);
2630 g_signal_connect(G_OBJECT(widget), "toggled",
2631 gtk_radio_button_toggled, NULL);
2632 toggled = GTK_TOGGLE_BUTTON(widget)->toggled;
2633 GTK_TOGGLE_BUTTON(widget)->toggled = !toggled;
2634 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), toggled);
2635 }
2636
2637 void gtk_radio_button_destroy(GtkWidget *widget)
2638 {
2639 GSList *group, *listpt;
2640 GtkRadioButton *radio;
2641
2642 gtk_button_destroy(widget);
2643 group = GTK_RADIO_BUTTON(widget)->group;
2644 group = g_slist_remove(group, GTK_RADIO_BUTTON(widget));
2645 for (listpt = group; listpt; listpt = g_slist_next(listpt)) {
2646 radio = GTK_RADIO_BUTTON(listpt->data);
2647 radio->group = group;
2648 }
2649 }
2650
2651 void gtk_container_show_all(GtkWidget *widget, gboolean hWndOnly)
2652 {
2653 GtkContainer *container = GTK_CONTAINER(widget);
2654
2655 if (container->child)
2656 gtk_widget_show_all_full(container->child, hWndOnly);
2657 }
2658
2659 void gtk_container_hide_all(GtkWidget *widget, gboolean hWndOnly)
2660 {
2661 GtkContainer *container = GTK_CONTAINER(widget);
2662
2663 if (container->child)
2664 gtk_widget_hide_all_full(container->child, hWndOnly);
2665 }
2666
2667 void gtk_box_show_all(GtkWidget *widget, gboolean hWndOnly)
2668 {
2669 GtkBoxChild *child;
2670 GList *children;
2671
2672 gtk_container_show_all(widget, hWndOnly);
2673
2674 for (children = GTK_BOX(widget)->children; children;
2675 children = g_list_next(children)) {
2676 child = (GtkBoxChild *)(children->data);
2677 if (child && child->widget)
2678 gtk_widget_show_all_full(child->widget, hWndOnly);
2679 }
2680 }
2681
2682 void gtk_box_hide_all(GtkWidget *widget, gboolean hWndOnly)
2683 {
2684 GtkBoxChild *child;
2685 GList *children;
2686
2687 gtk_container_hide_all(widget, hWndOnly);
2688
2689 for (children = GTK_BOX(widget)->children; children;
2690 children = g_list_next(children)) {
2691 child = (GtkBoxChild *)(children->data);
2692 if (child && child->widget)
2693 gtk_widget_hide_all_full(child->widget, hWndOnly);
2694 }
2695 }
2696
2697 void gtk_table_show_all(GtkWidget *widget, gboolean hWndOnly)
2698 {
2699 GList *children;
2700 GtkTableChild *child;
2701
2702 gtk_container_show_all(widget, hWndOnly);
2703 for (children = GTK_TABLE(widget)->children; children;
2704 children = g_list_next(children)) {
2705 child = (GtkTableChild *)(children->data);
2706 if (child && child->widget)
2707 gtk_widget_show_all_full(child->widget, hWndOnly);
2708 }
2709 }
2710
2711 void gtk_table_hide_all(GtkWidget *widget, gboolean hWndOnly)
2712 {
2713 GList *children;
2714 GtkTableChild *child;
2715
2716 gtk_container_hide_all(widget, hWndOnly);
2717 for (children = GTK_TABLE(widget)->children; children;
2718 children = g_list_next(children)) {
2719 child = (GtkTableChild *)(children->data);
2720 if (child && child->widget)
2721 gtk_widget_hide_all_full(child->widget, hWndOnly);
2722 }
2723 }
2724
2725 void gtk_widget_hide_all(GtkWidget *widget)
2726 {
2727 gtk_widget_hide_all_full(widget, FALSE);
2728 }
2729
2730 void gtk_widget_hide_all_full(GtkWidget *widget, gboolean hWndOnly)
2731 {
2732 gtk_signal_emit(G_OBJECT(widget), "hide_all", hWndOnly);
2733 if (hWndOnly) {
2734 gtk_signal_emit(G_OBJECT(widget), "hide");
2735 if (widget->hWnd)
2736 ShowWindow(widget->hWnd, SW_HIDE);
2737 } else
2738 gtk_widget_hide_full(widget, FALSE);
2739 }
2740
2741 void gtk_widget_show_all(GtkWidget *widget)
2742 {
2743 gtk_widget_show_all_full(widget, FALSE);
2744 }
2745
2746 void gtk_widget_show_all_full(GtkWidget *widget, gboolean hWndOnly)
2747 {
2748 GtkAllocation alloc;
2749 gboolean InitWindow = FALSE;
2750
2751 if (!GTK_WIDGET_REALIZED(widget) &&
2752 G_OBJECT(widget)->klass == &GtkWindowClass)
2753 InitWindow = TRUE;
2754
2755 if (InitWindow)
2756 gtk_widget_realize(widget);
2757
2758 gtk_signal_emit(G_OBJECT(widget), "show_all", hWndOnly);
2759
2760 if (hWndOnly) {
2761 if (gtk_widget_get_visible(widget)) {
2762 gtk_signal_emit(G_OBJECT(widget), "show");
2763 if (widget->hWnd)
2764 ShowWindow(widget->hWnd, SW_SHOWNORMAL);
2765 }
2766 } else {
2767 gtk_widget_show_full(widget, FALSE);
2768 }
2769
2770 if (InitWindow) {
2771 gtk_widget_update(widget, TRUE);
2772 alloc.x = alloc.y = 0;
2773 alloc.width = widget->requisition.width;
2774 alloc.height = widget->requisition.height;
2775 gtk_window_set_initial_position(GTK_WINDOW(widget), &alloc);
2776 ShowWindow(widget->hWnd, SW_SHOWNORMAL);
2777 UpdateWindow(widget->hWnd);
2778 }
2779 }
2780
2781 GtkWidget *gtk_widget_get_ancestor(GtkWidget *widget, GtkType type)
2782 {
2783 if (!widget)
2784 return NULL;
2785 while (widget && G_OBJECT(widget)->klass != type) {
2786 widget = widget->parent;
2787 }
2788 return widget;
2789 }
2790
2791 void gtk_label_size_request(GtkWidget *widget, GtkRequisition *requisition)
2792 {
2793 SIZE size;
2794 GtkLabel *label = GTK_LABEL(widget);
2795
2796 if (GetTextSize(widget->hWnd, label->text, &size, defFont)) {
2797 requisition->width = size.cx;
2798 requisition->height = size.cy;
2799 }
2800 }
2801
2802 void gtk_url_size_request(GtkWidget *widget, GtkRequisition *requisition)
2803 {
2804 SIZE size;
2805 GtkLabel *label = GTK_LABEL(widget);
2806
2807 if (GetTextSize(widget->hWnd, label->text, &size, urlFont)) {
2808 requisition->width = size.cx;
2809 requisition->height = size.cy;
2810 }
2811 }
2812
2813 void gtk_label_set_size(GtkWidget *widget, GtkAllocation *allocation)
2814 {
2815 gint yexcess;
2816
2817 yexcess = allocation->height - widget->requisition.height;
2818 if (yexcess > 0) {
2819 allocation->y += yexcess / 2;
2820 allocation->height -= yexcess;
2821 }
2822 }
2823
2824 void gtk_entry_set_size(GtkWidget *widget, GtkAllocation *allocation)
2825 {
2826 gint yexcess;
2827
2828 yexcess = allocation->height - widget->requisition.height;
2829 if (yexcess > 0) {
2830 allocation->y += yexcess / 2;
2831 allocation->height -= yexcess;
2832 }
2833 }
2834
2835 void gtk_label_destroy(GtkWidget *widget)
2836 {
2837 g_free(GTK_LABEL(widget)->text);
2838 }
2839
2840 void gtk_url_destroy(GtkWidget *widget)
2841 {
2842 g_free(GTK_LABEL(widget)->text);
2843 g_free(GTK_URL(widget)->target);
2844 }
2845
2846 void gtk_label_realize(GtkWidget *widget)
2847 {
2848 GtkLabel *label = GTK_LABEL(widget);
2849 HWND Parent;
2850
2851 Parent = gtk_get_parent_hwnd(widget);
2852 widget->hWnd = myCreateWindow("STATIC", label->text,
2853 WS_CHILD | SS_CENTER,
2854 widget->allocation.x, widget->allocation.y,
2855 widget->allocation.width,
2856 widget->allocation.height, Parent, NULL,
2857 hInst, NULL);
2858 gtk_set_default_font(widget->hWnd);
2859 }
2860
2861 void gtk_url_realize(GtkWidget *widget)
2862 {
2863 HWND Parent;
2864
2865 Parent = gtk_get_parent_hwnd(widget);
2866 widget->hWnd = myCreateWindow(WC_GTKURL, GTK_LABEL(widget)->text,
2867 WS_CHILD,
2868 widget->allocation.x, widget->allocation.y,
2869 widget->allocation.width,
2870 widget->allocation.height, Parent, NULL,
2871 hInst, NULL);
2872 }
2873
2874 void gtk_container_add(GtkContainer *container, GtkWidget *widget)
2875 {
2876 container->child = widget;
2877 widget->parent = GTK_WIDGET(container);
2878 if (GTK_WIDGET_REALIZED(GTK_WIDGET(container))) {
2879 gtk_widget_realize(widget);
2880 gtk_widget_update(GTK_WIDGET(container), TRUE);
2881 }
2882 }
2883
2884 void gtk_container_set_border_width(GtkContainer *container,
2885 guint border_width)
2886 {
2887 container->border_width = border_width;
2888 }
2889
2890 GtkWidget *gtk_table_new(guint rows, guint cols, gboolean homogeneous)
2891 {
2892 GtkTable *table;
2893
2894 table = GTK_TABLE(GtkNewObject(&GtkTableClass));
2895
2896 table->nrows = rows;
2897 table->ncols = cols;
2898 table->homogeneous = homogeneous;
2899
2900 table->rows = g_new0(GtkTableRowCol, rows);
2901 table->cols = g_new0(GtkTableRowCol, cols);
2902
2903 return GTK_WIDGET(table);
2904 }
2905
2906 void gtk_table_resize(GtkTable *table, guint rows, guint cols)
2907 {
2908 gint i;
2909
2910 table->rows = g_realloc(table->rows, sizeof(GtkTableRowCol) * rows);
2911 table->cols = g_realloc(table->cols, sizeof(GtkTableRowCol) * cols);
2912
2913 for (i = table->nrows; i < rows; i++) {
2914 table->rows[i].requisition = 0;
2915 table->rows[i].allocation = 0;
2916 table->rows[i].spacing = table->row_spacing;
2917 }
2918 for (i = table->ncols; i < cols; i++) {
2919 table->cols[i].requisition = 0;
2920 table->cols[i].allocation = 0;
2921 table->cols[i].spacing = table->column_spacing;
2922 }
2923 table->nrows = rows;
2924 table->ncols = cols;
2925 gtk_widget_update(GTK_WIDGET(table), FALSE);
2926 }
2927
2928 void gtk_table_attach_defaults(GtkTable *table, GtkWidget *widget,
2929 guint left_attach, guint right_attach,
2930 guint top_attach, guint bottom_attach)
2931 {
2932 gtk_table_attach(table, widget, left_attach, right_attach, top_attach,
2933 bottom_attach, GTK_EXPAND, GTK_EXPAND, 0, 0);
2934 }
2935
2936 void gtk_table_attach(GtkTable *table, GtkWidget *widget,
2937 guint left_attach, guint right_attach,
2938 guint top_attach, guint bottom_attach,
2939 GtkAttachOptions xoptions, GtkAttachOptions yoptions,
2940 guint xpadding, guint ypadding)
2941 {
2942 GtkTableChild *newChild;
2943
2944 newChild = g_new0(GtkTableChild, 1);
2945
2946 newChild->widget = widget;
2947 newChild->left_attach = left_attach;
2948 newChild->right_attach = right_attach;
2949 newChild->top_attach = top_attach;
2950 newChild->bottom_attach = bottom_attach;
2951 newChild->xoptions = xoptions;
2952 newChild->yoptions = yoptions;
2953
2954 table->children = g_list_append(table->children, (gpointer)newChild);
2955 widget->parent = GTK_WIDGET(table);
2956 if (GTK_WIDGET_REALIZED(GTK_WIDGET(table))) {
2957 gtk_widget_realize(widget);
2958 gtk_widget_update(GTK_WIDGET(table), TRUE);
2959 }
2960 }
2961
2962 void gtk_table_destroy(GtkWidget *widget)
2963 {
2964 GList *children;
2965 GtkTableChild *child;
2966
2967 gtk_container_destroy(widget);
2968 for (children = GTK_TABLE(widget)->children; children;
2969 children = g_list_next(children)) {
2970 child = (GtkTableChild *)(children->data);
2971 if (child->widget)
2972 gtk_widget_destroy(child->widget);
2973 g_free(child);
2974 }
2975 g_list_free(GTK_TABLE(widget)->children);
2976 }
2977
2978 static void gtk_table_get_size_children(GtkTable *table,
2979 GtkAttachOptions colopts,
2980 GtkAttachOptions *cols)
2981 {
2982 GList *children;
2983
2984 for (children = table->children; children;
2985 children = g_list_next(children)) {
2986 GtkRequisition child_req;
2987 GtkWidget *child_wid;
2988 int i;
2989 GtkTableChild *child = (GtkTableChild *)(children->data);
2990
2991 if (!child)
2992 continue;
2993 if (colopts) {
2994 if (child->xoptions & colopts) {
2995 for (i = child->left_attach; i < child->right_attach; i++) {
2996 cols[i] = colopts;
2997 }
2998 } else {
2999 continue;
3000 }
3001 } else if (child->xoptions & GTK_SHRINK) {
3002 continue;
3003 }
3004 child_wid = child->widget;
3005 if (child_wid && child->left_attach < child->right_attach
3006 && child->top_attach < child->bottom_attach
3007 && gtk_widget_get_visible(child_wid)) {
3008 child_req.width = child_wid->requisition.width;
3009 child_req.height = child_wid->requisition.height;
3010 child_req.height /= (child->bottom_attach - child->top_attach);
3011 if (colopts) {
3012 child_req.width /= (child->right_attach - child->left_attach);
3013 for (i = child->left_attach; i < child->right_attach; i++) {
3014 if (child_req.width > table->cols[i].requisition)
3015 table->cols[i].requisition = child_req.width;
3016 }
3017 } else {
3018 for (i = child->left_attach; i < child->right_attach; i++) {
3019 child_req.width -= table->cols[i].requisition;
3020 }
3021 if (child_req.width > 0) {
3022 int nexpand = 0, ntotal = child->right_attach - child->left_attach;
3023 for (i = child->left_attach; i < child->right_attach; i++) {
3024 if (cols[i] == 0) {
3025 nexpand++;
3026 }
3027 }
3028 if (nexpand) {
3029 for (i = child->left_attach; i < child->right_attach; i++) {
3030 if (cols[i] == 0) {
3031 table->cols[i].requisition += child_req.width / nexpand;
3032 }
3033 }
3034 } else {
3035 for (i = child->left_attach; i < child->right_attach; i++) {
3036 table->cols[i].requisition += child_req.width / ntotal;
3037 }
3038 }
3039 }
3040 }
3041 for (i = child->top_attach; i < child->bottom_attach; i++) {
3042 if (child_req.height > table->rows[i].requisition)
3043 table->rows[i].requisition = child_req.height;
3044 }
3045 }
3046 }
3047 }
3048
3049 void gtk_table_size_request(GtkWidget *widget, GtkRequisition *requisition)
3050 {
3051 GtkTable *table;
3052 gint16 MaxReq;
3053 int i;
3054 GtkAttachOptions *cols;
3055
3056 table = GTK_TABLE(widget);
3057 for (i = 0; i < table->ncols; i++)
3058 table->cols[i].requisition = 0;
3059 for (i = 0; i < table->nrows; i++)
3060 table->rows[i].requisition = 0;
3061
3062 gtk_container_size_request(widget, requisition);
3063 cols = g_new0(GtkAttachOptions, table->ncols);
3064 if (!table->homogeneous) {
3065 gtk_table_get_size_children(table, GTK_SHRINK, cols);
3066 }
3067 gtk_table_get_size_children(table, 0, cols);
3068 g_free(cols);
3069
3070 if (table->homogeneous) {
3071 MaxReq = 0;
3072 for (i = 0; i < table->ncols; i++)
3073 if (table->cols[i].requisition > MaxReq) {
3074 MaxReq = table->cols[i].requisition;
3075 }
3076 for (i = 0; i < table->ncols; i++)
3077 table->cols[i].requisition = MaxReq;
3078
3079 MaxReq = 0;
3080 for (i = 0; i < table->nrows; i++)
3081 if (table->rows[i].requisition > MaxReq) {
3082 MaxReq = table->rows[i].requisition;
3083 }
3084 for (i = 0; i < table->nrows; i++)
3085 table->rows[i].requisition = MaxReq;
3086 }
3087
3088 requisition->width = requisition->height =
3089 2 * GTK_CONTAINER(widget)->border_width;
3090
3091 for (i = 0; i < table->ncols; i++)
3092 requisition->width += table->cols[i].requisition;
3093 for (i = 0; i < table->ncols - 1; i++)
3094 requisition->width += table->cols[i].spacing;
3095 for (i = 0; i < table->nrows; i++)
3096 requisition->height += table->rows[i].requisition;
3097 for (i = 0; i < table->nrows - 1; i++)
3098 requisition->height += table->rows[i].spacing;
3099
3100 }
3101
3102 void gtk_table_set_size(GtkWidget *widget, GtkAllocation *allocation)
3103 {
3104 GtkTable *table;
3105 gint row_extra = 0, col_extra = 0, i, row_expand = 0, col_expand = 0;
3106 GtkAllocation child_alloc;
3107 GList *children;
3108 GtkTableChild *child;
3109 gint border_width;
3110 GtkAttachOptions *rowopt, *colopt;
3111
3112 table = GTK_TABLE(widget);
3113 border_width = GTK_CONTAINER(widget)->border_width;
3114
3115 rowopt = g_new0(GtkAttachOptions, table->nrows);
3116 colopt = g_new0(GtkAttachOptions, table->ncols);
3117 for (children = table->children; children;
3118 children = g_list_next(children)) {
3119 GtkTableChild *child = (GtkTableChild *)(children->data);
3120 GtkWidget *child_wid;
3121
3122 if (!child)
3123 continue;
3124 child_wid = child->widget;
3125 if (child_wid && child->left_attach < child->right_attach &&
3126 child->top_attach < child->bottom_attach &&
3127 gtk_widget_get_visible(child_wid)) {
3128 if (child->xoptions & GTK_SHRINK) {
3129 for (i = child->left_attach; i < child->right_attach; i++) {
3130 colopt[i] |= GTK_SHRINK;
3131 }
3132 }
3133 if (child->yoptions & GTK_EXPAND) {
3134 for (i = child->top_attach; i < child->bottom_attach; i++) {
3135 rowopt[i] |= GTK_EXPAND;
3136 }
3137 }
3138 }
3139 }
3140
3141 for (i = 0; i < table->ncols; i++) {
3142 if (!(colopt[i] & GTK_SHRINK)) {
3143 col_expand++;
3144 }
3145 }
3146 for (i = 0; i < table->nrows; i++) {
3147 if (rowopt[i] & GTK_EXPAND) {
3148 row_expand++;
3149 }
3150 }
3151
3152 if (col_expand) {
3153 col_extra =
3154 (allocation->width - widget->requisition.width) / col_expand;
3155 }
3156 if (row_expand) {
3157 row_extra =
3158 (allocation->height - widget->requisition.height) / row_expand;
3159 }
3160 for (i = 0; i < table->ncols; i++) {
3161 table->cols[i].allocation = table->cols[i].requisition +
3162 (colopt[i] & GTK_SHRINK ? 0 : col_extra);
3163 }
3164 for (i = 0; i < table->nrows; i++) {
3165 table->rows[i].allocation = table->rows[i].requisition +
3166 (rowopt[i] & GTK_SHRINK ? 0 : row_extra);
3167 }
3168 g_free(rowopt);
3169 g_free(colopt);
3170 for (children = table->children; children;
3171 children = g_list_next(children)) {
3172 child = (GtkTableChild *)(children->data);
3173 if (!child || !child->widget || !gtk_widget_get_visible(child->widget))
3174 continue;
3175 child_alloc.x = allocation->x + border_width;
3176 child_alloc.y = allocation->y + border_width;
3177 child_alloc.width = child_alloc.height = 0;
3178 for (i = 0; i < child->left_attach; i++) {
3179 child_alloc.x += table->cols[i].allocation + table->cols[i].spacing;
3180 }
3181 for (i = 0; i < child->top_attach; i++) {
3182 child_alloc.y += table->rows[i].allocation + table->rows[i].spacing;
3183 }
3184 for (i = child->left_attach; i < child->right_attach; i++) {
3185 child_alloc.width += table->cols[i].allocation;
3186 if (i < child->right_attach - 1) {
3187 child_alloc.width += table->cols[i].spacing;
3188 }
3189 }
3190 for (i = child->top_attach; i < child->bottom_attach; i++) {
3191 child_alloc.height += table->rows[i].allocation;
3192 if (i < child->bottom_attach - 1) {
3193 child_alloc.height += table->rows[i].spacing;
3194 }
3195 }
3196 gtk_widget_set_size(child->widget, &child_alloc);
3197 }
3198 }
3199
3200 void gtk_table_realize(GtkWidget *widget)
3201 {
3202 GList *children;
3203 GtkTableChild *child;
3204
3205 gtk_container_realize(widget);
3206 for (children = GTK_TABLE(widget)->children; children;
3207 children = g_list_next(children)) {
3208 child = (GtkTableChild *)(children->data);
3209 if (child->widget)
3210 gtk_widget_realize(child->widget);
3211 }
3212 }
3213
3214 void gtk_table_set_row_spacing(GtkTable *table, guint row, guint spacing)
3215 {
3216 if (table && row >= 0 && row < table->nrows) {
3217 table->rows[row].spacing = spacing;
3218 }
3219 }
3220
3221 void gtk_table_set_col_spacing(GtkTable *table, guint column,
3222 guint spacing)
3223 {
3224 if (table && column >= 0 && column < table->ncols) {
3225 table->cols[column].spacing = spacing;
3226 }
3227 }
3228
3229 void gtk_table_set_row_spacings(GtkTable *table, guint spacing)
3230 {
3231 int i;
3232
3233 table->row_spacing = spacing;
3234 for (i = 0; i < table->nrows; i++)
3235 table->rows[i].spacing = spacing;
3236 }
3237
3238 void gtk_table_set_col_spacings(GtkTable *table, guint spacing)
3239 {
3240 int i;
3241
3242 table->column_spacing = spacing;
3243 for (i = 0; i < table->ncols; i++)
3244 table->cols[i].spacing = spacing;
3245 }
3246
3247 void gtk_toggle_button_toggled(GtkToggleButton *toggle_button)
3248 {
3249 toggle_button->toggled = !toggle_button->toggled;
3250 gtk_signal_emit(G_OBJECT(toggle_button), "toggled");
3251 }
3252
3253 void gtk_check_button_toggled(GtkCheckButton *check_button, gpointer data)
3254 {
3255 HWND hWnd;
3256 gboolean is_active = GTK_TOGGLE_BUTTON(check_button)->toggled;
3257
3258 hWnd = GTK_WIDGET(check_button)->hWnd;
3259 if (hWnd) {
3260 SendMessageW(hWnd, BM_SETCHECK,
3261 is_active ? BST_CHECKED : BST_UNCHECKED, 0);
3262 }
3263 }
3264
3265 void gtk_radio_button_clicked(GtkRadioButton *radio_button, gpointer data)
3266 {
3267 GtkToggleButton *toggle = GTK_TOGGLE_BUTTON(radio_button);
3268
3269 if (toggle->toggled)
3270 return;
3271 else
3272 gtk_toggle_button_toggled(toggle);
3273 }
3274
3275 void gtk_radio_button_toggled(GtkRadioButton *radio_button, gpointer data)
3276 {
3277 HWND hWnd;
3278 GSList *group;
3279 GtkRadioButton *radio;
3280 gboolean is_active = GTK_TOGGLE_BUTTON(radio_button)->toggled;
3281
3282 hWnd = GTK_WIDGET(radio_button)->hWnd;
3283 if (hWnd) {
3284 SendMessageW(hWnd, BM_SETCHECK,
3285 is_active ? BST_CHECKED : BST_UNCHECKED, 0);
3286 }
3287 if (is_active) {
3288 for (group = radio_button->group; group; group = g_slist_next(group)) {
3289 radio = GTK_RADIO_BUTTON(group->data);
3290 if (radio && radio != radio_button) {
3291 GTK_TOGGLE_BUTTON(radio)->toggled = FALSE;
3292 hWnd = GTK_WIDGET(radio)->hWnd;
3293 if (hWnd)
3294 SendMessageW(hWnd, BM_SETCHECK, BST_UNCHECKED, 0);
3295 }
3296 }
3297 }
3298 }
3299
3300 gboolean gtk_toggle_button_get_active(GtkToggleButton *toggle_button)
3301 {
3302 return (toggle_button->toggled);
3303 }
3304
3305 void gtk_toggle_button_set_active(GtkToggleButton *toggle_button,
3306 gboolean is_active)
3307 {
3308 if (toggle_button->toggled == is_active)
3309 return;
3310 else
3311 gtk_toggle_button_toggled(toggle_button);
3312 }
3313
3314 void gtk_main_quit()
3315 {
3316 PostQuitMessage(0);
3317 }
3318
3319 void gtk_main()
3320 {
3321 MSG msg;
3322 GSList *list;
3323 BOOL MsgDone;
3324 GtkWidget *widget, *window;
3325 HACCEL hAccel;
3326
3327 RecurseLevel++;
3328
3329 while (GetMessageW(&msg, NULL, 0, 0)) {
3330 MsgDone = FALSE;
3331 widget = GTK_WIDGET(GetWindowLongPtrW(msg.hwnd, GWLP_USERDATA));
3332 window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
3333 if (window) {
3334 hAccel = GTK_WINDOW(window)->hAccel;
3335 if (hAccel) {
3336 MsgDone = TranslateAccelerator(window->hWnd, hAccel, &msg);
3337 }
3338 }
3339 if (!MsgDone)
3340 for (list = WindowList; list && !MsgDone; list = g_slist_next(list)) {
3341 widget = GTK_WIDGET(list->data);
3342 if (widget && widget->hWnd
3343 && (MsgDone = IsDialogMessageW(widget->hWnd, &msg)) == TRUE)
3344 break;
3345 }
3346 if (!MsgDone) {
3347 TranslateMessage(&msg);
3348 DispatchMessageW(&msg);
3349 }
3350 }
3351 RecurseLevel--;
3352 }
3353
3354 typedef struct _GtkSignal GtkSignal;
3355
3356 struct _GtkSignal {
3357 GCallback func;
3358 GObject *slot_object;
3359 gpointer func_data;
3360 };
3361
3362 typedef gint (*GtkGIntSignalFunc) ();
3363
3364 void gtk_marshal_BOOL__GINT(GObject *object, GSList *actions,
3365 GCallback default_action, va_list args)
3366 {
3367 gboolean *retval;
3368 gint arg1;
3369 GtkSignal *signal;
3370 GtkGIntSignalFunc sigfunc;
3371
3372 arg1 = va_arg(args, gint);
3373 retval = va_arg(args, gboolean *);
3374
3375 if (!retval) {
3376 g_warning("gtk_marshal_BOOL__GINT: retval NULL");
3377 return;
3378 }
3379
3380 while (actions) {
3381 signal = (GtkSignal *)actions->data;
3382 sigfunc = (GtkGIntSignalFunc)signal->func;
3383 if (signal->slot_object) {
3384 *retval = (*sigfunc) (signal->slot_object, arg1);
3385 } else
3386 *retval = (*sigfunc) (object, arg1, signal->func_data);
3387 if (*retval)
3388 return;
3389 actions = g_slist_next(actions);
3390 }
3391 sigfunc = (GtkGIntSignalFunc)default_action;
3392 if (sigfunc)
3393 *retval = (*sigfunc) (object, arg1);
3394 }
3395
3396 void gtk_marshal_BOOL__GPOIN(GObject *object, GSList *actions,
3397 GCallback default_action, va_list args)
3398 {
3399 gboolean *retval;
3400 gpointer arg1;
3401 GtkSignal *signal;
3402 GtkGIntSignalFunc sigfunc;
3403
3404 arg1 = va_arg(args, gpointer);
3405 retval = va_arg(args, gboolean *);
3406
3407 if (!retval) {
3408 g_warning("gtk_marshal_BOOL__GPOIN: retval NULL");
3409 return;
3410 }
3411
3412 while (actions) {
3413 signal = (GtkSignal *)actions->data;
3414 sigfunc = (GtkGIntSignalFunc)signal->func;
3415 if (signal->slot_object) {
3416 *retval = (*sigfunc) (signal->slot_object, arg1);
3417 } else
3418 *retval = (*sigfunc) (object, arg1, signal->func_data);
3419 if (*retval)
3420 return;
3421 actions = g_slist_next(actions);
3422 }
3423 sigfunc = (GtkGIntSignalFunc)default_action;
3424 if (sigfunc)
3425 *retval = (*sigfunc) (object, arg1);
3426 }
3427
3428 void gtk_marshal_VOID__VOID(GObject *object, GSList *actions,
3429 GCallback default_action, va_list args)
3430 {
3431 GtkSignal *signal;
3432
3433 while (actions) {
3434 signal = (GtkSignal *)actions->data;
3435 if (signal->slot_object) {
3436 (*signal->func) (signal->slot_object);
3437 } else
3438 (*signal->func) (object, signal->func_data);
3439 actions = g_slist_next(actions);
3440 }
3441 if (default_action)
3442 (*default_action) (object);
3443 }
3444
3445 void gtk_marshal_VOID__GINT(GObject *object, GSList *actions,
3446 GCallback default_action, va_list args)
3447 {
3448 gint arg1;
3449 GtkSignal *signal;
3450
3451 arg1 = va_arg(args, gint);
3452
3453 while (actions) {
3454 signal = (GtkSignal *)actions->data;
3455 if (signal->slot_object) {
3456 (*signal->func) (signal->slot_object, arg1);
3457 } else
3458 (*signal->func) (object, arg1, signal->func_data);
3459 actions = g_slist_next(actions);
3460 }
3461 if (default_action)
3462 (*default_action) (object, arg1);
3463 }
3464
3465 void gtk_marshal_VOID__GPOIN(GObject *object, GSList *actions,
3466 GCallback default_action, va_list args)
3467 {
3468 gpointer arg1;
3469 GtkSignal *signal;
3470
3471 arg1 = va_arg(args, gpointer);
3472
3473 while (actions) {
3474 signal = (GtkSignal *)actions->data;
3475 if (signal->slot_object) {
3476 (*signal->func) (signal->slot_object, arg1);
3477 } else
3478 (*signal->func) (object, arg1, signal->func_data);
3479 actions = g_slist_next(actions);
3480 }
3481 if (default_action)
3482 (*default_action) (object, arg1);
3483 }
3484
3485 void gtk_marshal_VOID__BOOL(GObject *object, GSList *actions,
3486 GCallback default_action, va_list args)
3487 {
3488 gboolean arg1;
3489 GtkSignal *signal;
3490
3491 arg1 = va_arg(args, gboolean);
3492
3493 while (actions) {
3494 signal = (GtkSignal *)actions->data;
3495 if (signal->slot_object) {
3496 (*signal->func) (signal->slot_object, arg1);
3497 } else
3498 (*signal->func) (object, arg1, signal->func_data);
3499 actions = g_slist_next(actions);
3500 }
3501 if (default_action)
3502 (*default_action) (object, arg1);
3503 }
3504
3505 void gtk_marshal_VOID__GINT_GINT_EVENT(GObject *object, GSList *actions,
3506 GCallback default_action,
3507 va_list args)
3508 {
3509 gint arg1, arg2;
3510 GdkEvent *arg3;
3511 GtkSignal *signal;
3512
3513 arg1 = va_arg(args, gint);
3514 arg2 = va_arg(args, gint);
3515 arg3 = va_arg(args, GdkEvent *);
3516
3517 while (actions) {
3518 signal = (GtkSignal *)actions->data;
3519 if (signal->slot_object) {
3520 (*signal->func) (signal->slot_object, arg1, arg2, arg3);
3521 } else
3522 (*signal->func) (object, arg1, arg2, arg3, signal->func_data);
3523 actions = g_slist_next(actions);
3524 }
3525 if (default_action)
3526 (*default_action) (object, arg1, arg2, arg3);
3527 }
3528
3529 static GtkSignalType *gtk_get_signal_type(GObject *object,
3530 const gchar *name)
3531 {
3532 GtkClass *klass;
3533 GtkSignalType *signals;
3534
3535 for (klass = object->klass; klass; klass = klass->parent) {
3536 for (signals = klass->signals; signals && signals->name[0]; signals++) {
3537 if (strcmp(signals->name, name) == 0)
3538 return signals;
3539 }
3540 }
3541 return NULL;
3542 }
3543
3544 void gtk_signal_emit(GObject *object, const gchar *name, ...)
3545 {
3546 GSList *signal_list;
3547 GtkSignalType *signal_type;
3548 va_list ap;
3549
3550 if (!object)
3551 return;
3552
3553 va_start(ap, name);
3554 signal_list = (GSList *)g_datalist_get_data(&object->signals, name);
3555 signal_type = gtk_get_signal_type(object, name);
3556 if (signal_type && signal_type->marshaller) {
3557 (*signal_type->marshaller) (object, signal_list,
3558 signal_type->default_action, ap);
3559 }
3560 va_end(ap);
3561 if (!signal_type)
3562 g_warning("gtk_signal_emit: unknown signal %s", name);
3563 }
3564
3565 guint g_signal_connect(GObject *object, const gchar *name,
3566 GCallback func, gpointer func_data)
3567 {
3568 GtkSignal *signal;
3569 GtkSignalType *signal_type;
3570 GSList *signal_list;
3571
3572 if (!object)
3573 return 0;
3574 signal_type = gtk_get_signal_type(object, name);
3575 if (!signal_type) {
3576 g_warning("g_signal_connect: unknown signal %s", name);
3577 return 0;
3578 }
3579 signal_list = (GSList *)g_datalist_get_data(&object->signals, name);
3580 signal = g_new0(GtkSignal, 1);
3581
3582 signal->func = func;
3583 signal->func_data = func_data;
3584 signal_list = g_slist_append(signal_list, signal);
3585 g_datalist_set_data(&object->signals, name, signal_list);
3586 return 0;
3587 }
3588
3589 guint g_signal_connect_swapped(GObject *object, const gchar *name,
3590 GCallback func, GObject *slot_object)
3591 {
3592 GtkSignal *signal;
3593 GtkSignalType *signal_type;
3594 GSList *signal_list;
3595
3596 if (!object)
3597 return 0;
3598 signal_type = gtk_get_signal_type(object, name);
3599 if (!signal_type) {
3600 g_warning("g_signal_connect_swapped: unknown signal %s", name);
3601 return 0;
3602 }
3603 signal_list = (GSList *)g_datalist_get_data(&object->signals, name);
3604 signal = g_new0(GtkSignal, 1);
3605
3606 signal->func = func;
3607 signal->slot_object = slot_object;
3608 signal_list = g_slist_append(signal_list, signal);
3609 g_datalist_set_data(&object->signals, name, signal_list);
3610 return 0;
3611 }
3612
3613 void gtk_menu_shell_insert(GtkMenuShell *menu_shell, GtkWidget *child,
3614 gint position)
3615 {
3616 menu_shell->children =
3617 g_slist_insert(menu_shell->children, (gpointer)child, position);
3618 child->parent = GTK_WIDGET(menu_shell);
3619 }
3620
3621 void gtk_menu_shell_append(GtkMenuShell *menu_shell, GtkWidget *child)
3622 {
3623 gtk_menu_shell_insert(menu_shell, child, -1);
3624 }
3625
3626 void gtk_menu_shell_prepend(GtkMenuShell *menu_shell, GtkWidget *child)
3627 {
3628 gtk_menu_shell_insert(menu_shell, child, 0);
3629 }
3630
3631 GtkWidget *gtk_menu_bar_new()
3632 {
3633 GtkMenuBar *menu_bar;
3634
3635 menu_bar = GTK_MENU_BAR(GtkNewObject(&GtkMenuBarClass));
3636 return GTK_WIDGET(menu_bar);
3637 }
3638
3639 void gtk_menu_bar_insert(GtkMenuBar *menu_bar, GtkWidget *child,
3640 gint position)
3641 {
3642 gtk_menu_shell_insert(GTK_MENU_SHELL(menu_bar), child, position);
3643 }
3644
3645 void gtk_menu_bar_append(GtkMenuBar *menu_bar, GtkWidget *child)
3646 {
3647 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), child);
3648 }
3649
3650 void gtk_menu_bar_prepend(GtkMenuBar *menu_bar, GtkWidget *child)
3651 {
3652 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu_bar), child);
3653 }
3654
3655 GtkWidget *gtk_menu_new()
3656 {
3657 GtkMenu *menu;
3658
3659 menu = GTK_MENU(GtkNewObject(&GtkMenuClass));
3660 return GTK_WIDGET(menu);
3661 }
3662
3663 void gtk_menu_insert(GtkMenu *menu, GtkWidget *child, gint position)
3664 {
3665 gtk_menu_shell_insert(GTK_MENU_SHELL(menu), child, position);
3666 }
3667
3668 void gtk_menu_append(GtkMenu *menu, GtkWidget *child)
3669 {
3670 gtk_menu_shell_append(GTK_MENU_SHELL(menu), child);
3671 }
3672
3673 void gtk_menu_prepend(GtkMenu *menu, GtkWidget *child)
3674 {
3675 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), child);
3676 }
3677
3678 GtkWidget *gtk_menu_item_new_with_label(const gchar *label)
3679 {
3680 GtkMenuItem *menu_item;
3681
3682 menu_item = GTK_MENU_ITEM(GtkNewObject(&GtkMenuItemClass));
3683 menu_item->accelind = -1;
3684 menu_item->text = g_strdup(label);
3685 menu_item->check = 0;
3686 menu_item->active = 0;
3687 g_strdelimit(menu_item->text, "_", '&');
3688 return GTK_WIDGET(menu_item);
3689 }
3690
3691 void gtk_menu_item_set_submenu(GtkMenuItem *menu_item, GtkWidget *submenu)
3692 {
3693 menu_item->submenu = GTK_MENU(submenu);
3694 submenu->parent = GTK_WIDGET(menu_item);
3695 }
3696
3697 GtkMenu *gtk_menu_item_get_submenu(GtkMenuItem *menu_item)
3698 {
3699 return menu_item->submenu;
3700 }
3701
3702 gboolean gtk_check_menu_item_get_active(GtkMenuItem *menu_item)
3703 {
3704 return menu_item->active;
3705 }
3706
3707 void gtk_check_menu_item_set_active(GtkMenuItem *menu_item, gboolean active)
3708 {
3709 GtkWidget *widget = GTK_WIDGET(menu_item);
3710 menu_item->check = 1;
3711 menu_item->active = active;
3712
3713 if (GTK_WIDGET_REALIZED(widget)) {
3714 MENUITEMINFO mii;
3715 HMENU parent_menu;
3716
3717 parent_menu = GTK_MENU_SHELL(widget->parent)->menu;
3718 mii.cbSize = sizeof(MENUITEMINFO);
3719 mii.fMask = MIIM_STATE;
3720 mii.fState = active ? MFS_CHECKED : MFS_UNCHECKED;
3721 mySetMenuItemInfo(parent_menu, menu_item->ID, FALSE, &mii);
3722 }
3723 }
3724
3725 static GtkWidget *gtk_menu_item_get_menu_ID(GtkMenuItem *menu_item,
3726 gint ID)
3727 {
3728 if (menu_item->ID == ID) {
3729 return GTK_WIDGET(menu_item);
3730 } else if (menu_item->submenu) {
3731 return gtk_menu_shell_get_menu_ID(GTK_MENU_SHELL(menu_item->submenu),
3732 ID);
3733 } else
3734 return NULL;
3735 }
3736
3737 GtkWidget *gtk_menu_shell_get_menu_ID(GtkMenuShell *menu_shell, gint ID)
3738 {
3739 GSList *list;
3740 GtkWidget *menu_item;
3741
3742 for (list = menu_shell->children; list; list = list->next) {
3743 menu_item = gtk_menu_item_get_menu_ID(GTK_MENU_ITEM(list->data), ID);
3744 if (menu_item)
3745 return menu_item;
3746 }
3747 return NULL;
3748 }
3749
3750 GtkWidget *gtk_window_get_menu_ID(GtkWindow *window, gint ID)
3751 {
3752 if (window->menu_bar) {
3753 return gtk_menu_shell_get_menu_ID(GTK_MENU_SHELL(window->menu_bar),
3754 ID);
3755 } else
3756 return NULL;
3757 }
3758
3759 void gtk_menu_bar_realize(GtkWidget *widget)
3760 {
3761 GtkMenuBar *menu_bar = GTK_MENU_BAR(widget);
3762 GtkWidget *window;
3763
3764 GTK_MENU_SHELL(widget)->menu = CreateMenu();
3765 menu_bar->LastID = 1000;
3766
3767 gtk_menu_shell_realize(widget);
3768
3769 window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
3770 gtk_window_set_menu(GTK_WINDOW(window), menu_bar);
3771 }
3772
3773 void gtk_menu_item_realize(GtkWidget *widget)
3774 {
3775 GtkMenuItem *menu_item = GTK_MENU_ITEM(widget);
3776 MENUITEMINFO mii;
3777 GtkWidget *menu_bar, *window;
3778 HMENU parent_menu;
3779 gint pos;
3780
3781 menu_bar = gtk_widget_get_ancestor(widget, GTK_TYPE_MENU_BAR);
3782 if (menu_bar)
3783 menu_item->ID = GTK_MENU_BAR(menu_bar)->LastID++;
3784
3785 if (menu_item->accelind >= 0) {
3786 window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
3787 if (window && GTK_WINDOW(window)->accel_group) {
3788 gtk_accel_group_set_id(GTK_WINDOW(window)->accel_group,
3789 menu_item->accelind, menu_item->ID);
3790 }
3791 }
3792
3793 if (menu_item->submenu)
3794 gtk_widget_realize(GTK_WIDGET(menu_item->submenu));
3795
3796 parent_menu = GTK_MENU_SHELL(widget->parent)->menu;
3797 pos = g_slist_index(GTK_MENU_SHELL(widget->parent)->children, widget);
3798
3799 mii.cbSize = sizeof(MENUITEMINFO);
3800 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
3801 if (menu_item->submenu) {
3802 mii.fMask |= MIIM_SUBMENU;
3803 mii.hSubMenu = GTK_MENU_SHELL(menu_item->submenu)->menu;
3804 }
3805 mii.fType = MFT_STRING;
3806 if (GTK_WIDGET_SENSITIVE(widget)) {
3807 mii.fState = MFS_ENABLED;
3808 } else {
3809 mii.fState = MFS_GRAYED;
3810 }
3811 if (menu_item->check) {
3812 mii.fState |= (menu_item->active ? MFS_CHECKED : MFS_UNCHECKED);
3813 }
3814 mii.wID = menu_item->ID;
3815 mii.dwTypeData = (LPTSTR)menu_item->text;
3816 mii.cch = myw32strlen(menu_item->text);
3817 myInsertMenuItem(parent_menu, pos, TRUE, &mii);
3818 }
3819
3820 void gtk_menu_realize(GtkWidget *widget)
3821 {
3822 GTK_MENU_SHELL(widget)->menu = CreatePopupMenu();
3823 gtk_menu_shell_realize(widget);
3824 }
3825
3826 void gtk_menu_set_active(GtkMenu *menu, guint index)
3827 {
3828 menu->active = index;
3829 }
3830
3831 void gtk_menu_shell_realize(GtkWidget *widget)
3832 {
3833 GSList *children;
3834 GtkMenuShell *menu = GTK_MENU_SHELL(widget);
3835
3836 for (children = menu->children; children;
3837 children = g_slist_next(children)) {
3838 gtk_widget_realize(GTK_WIDGET(children->data));
3839 }
3840 }
3841
3842 void gtk_menu_item_enable(GtkWidget *widget)
3843 {
3844 GtkWidget *parent;
3845 HMENU hMenu;
3846 HWND hWnd;
3847
3848 parent = widget->parent;
3849 if (!parent)
3850 return;
3851 hMenu = GTK_MENU_SHELL(parent)->menu;
3852 if (hMenu)
3853 EnableMenuItem(hMenu, GTK_MENU_ITEM(widget)->ID,
3854 MF_BYCOMMAND | MF_ENABLED);
3855 hWnd = gtk_get_parent_hwnd(widget);
3856 if (hWnd)
3857 DrawMenuBar(hWnd);
3858 }
3859
3860 void gtk_menu_item_disable(GtkWidget *widget)
3861 {
3862 GtkWidget *parent;
3863 HMENU hMenu;
3864 HWND hWnd;
3865
3866 parent = widget->parent;
3867 if (!parent)
3868 return;
3869 hMenu = GTK_MENU_SHELL(parent)->menu;
3870 if (hMenu)
3871 EnableMenuItem(hMenu, GTK_MENU_ITEM(widget)->ID,
3872 MF_BYCOMMAND | MF_GRAYED);
3873 hWnd = gtk_get_parent_hwnd(widget);
3874 if (hWnd)
3875 DrawMenuBar(hWnd);
3876 }
3877
3878 GtkWidget *gtk_notebook_new()
3879 {
3880 GtkNotebook *notebook;
3881
3882 notebook = GTK_NOTEBOOK(GtkNewObject(&GtkNotebookClass));
3883 return GTK_WIDGET(notebook);
3884 }
3885
3886 void gtk_notebook_append_page(GtkNotebook *notebook, GtkWidget *child,
3887 GtkWidget *tab_label)
3888 {
3889 gtk_notebook_insert_page(notebook, child, tab_label, -1);
3890 }
3891
3892 void gtk_notebook_insert_page(GtkNotebook *notebook, GtkWidget *child,
3893 GtkWidget *tab_label, gint position)
3894 {
3895 GtkNotebookChild *note_child;
3896 GtkWidget *widget = GTK_WIDGET(notebook);
3897
3898 note_child = g_new0(GtkNotebookChild, 1);
3899
3900 note_child->child = child;
3901 note_child->tab_label = tab_label;
3902 note_child->tabpage = myCreateDialog(hInst, "tabpage",
3903 gtk_get_parent_hwnd(widget->parent),
3904 MainDlgProc);
3905 EnableThemeDialogTexture(note_child->tabpage, ETDT_ENABLETAB);
3906 notebook->children =
3907 g_slist_insert(notebook->children, note_child, position);
3908 child->parent = GTK_WIDGET(notebook);
3909 }
3910
3911 void gtk_notebook_set_current_page(GtkNotebook *notebook, gint page_num)
3912 {
3913 GSList *children;
3914 GtkNotebookChild *note_child;
3915 GtkWidget *widget = GTK_WIDGET(notebook);
3916 gint pos = 0;
3917
3918 if (page_num < 0)
3919 page_num = g_slist_length(notebook->children) - 1;
3920 notebook->selection = page_num;
3921
3922 if (GTK_WIDGET_REALIZED(widget)) {
3923 if (widget->hWnd)
3924 TabCtrl_SetCurSel(widget->hWnd, page_num);
3925 for (children = notebook->children; children;
3926 children = g_slist_next(children)) {
3927 note_child = (GtkNotebookChild *)(children->data);
3928 if (note_child && note_child->child) {
3929 if (pos == page_num) {
3930 ShowWindow(note_child->tabpage, SW_SHOW);
3931 } else {
3932 ShowWindow(note_child->tabpage, SW_HIDE);
3933 }
3934 pos++;
3935 }
3936 }
3937 }
3938 }
3939
3940 gint gtk_notebook_get_current_page(GtkNotebook *notebook)
3941 {
3942 return notebook->selection;
3943 }
3944
3945 void gtk_notebook_realize(GtkWidget *widget)
3946 {
3947 GSList *children;
3948 GtkNotebookChild *note_child;
3949 HWND Parent;
3950 gint tab_pos = 0;
3951 TC_ITEM tie;
3952
3953 Parent = gtk_get_parent_hwnd(widget->parent);
3954 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
3955 widget->hWnd = myCreateWindow(WC_TABCONTROL, "",
3956 WS_CHILD | WS_TABSTOP, 0, 0, 0, 0,
3957 Parent, NULL, hInst, NULL);
3958 if (widget->hWnd == NULL)
3959 g_print("Error creating window!\n");
3960 gtk_set_default_font(widget->hWnd);
3961
3962 tie.mask = TCIF_TEXT | TCIF_IMAGE;
3963 tie.iImage = -1;
3964
3965 for (children = GTK_NOTEBOOK(widget)->children; children;
3966 children = g_slist_next(children)) {
3967 note_child = (GtkNotebookChild *)(children->data);
3968 if (note_child) {
3969 if (note_child->tab_label)
3970 tie.pszText = GTK_LABEL(note_child->tab_label)->text;
3971 else
3972 tie.pszText = "No label";
3973 myTabCtrl_InsertItem(widget->hWnd, tab_pos++, &tie);
3974 note_child->tabpage = myCreateDialog(hInst, "tabpage",
3975 gtk_get_parent_hwnd(widget->parent),
3976 MainDlgProc);
3977 EnableThemeDialogTexture(note_child->tabpage, ETDT_ENABLETAB);
3978 if (note_child->child) {
3979 gtk_widget_realize(note_child->child);
3980 }
3981 }
3982 }
3983 gtk_notebook_set_current_page(GTK_NOTEBOOK(widget),
3984 GTK_NOTEBOOK(widget)->selection);
3985 }
3986
3987 void gtk_notebook_show_all(GtkWidget *widget, gboolean hWndOnly)
3988 {
3989 GSList *children;
3990 GtkNotebookChild *note_child;
3991
3992 if (!hWndOnly)
3993 for (children = GTK_NOTEBOOK(widget)->children; children;
3994 children = g_slist_next(children)) {
3995 note_child = (GtkNotebookChild *)(children->data);
3996 if (note_child && note_child->child)
3997 gtk_widget_show_all_full(note_child->child, hWndOnly);
3998 }
3999 gtk_notebook_set_current_page(GTK_NOTEBOOK(widget),
4000 GTK_NOTEBOOK(widget)->selection);
4001 }
4002
4003 void gtk_notebook_hide_all(GtkWidget *widget, gboolean hWndOnly)
4004 {
4005 GSList *children;
4006 GtkNotebookChild *note_child;
4007
4008 for (children = GTK_NOTEBOOK(widget)->children; children;
4009 children = g_slist_next(children)) {
4010 note_child = (GtkNotebookChild *)(children->data);
4011 if (note_child && note_child->child)
4012 gtk_widget_hide_all_full(note_child->child, hWndOnly);
4013 ShowWindow(note_child->tabpage, SW_HIDE);
4014 }
4015 }
4016
4017 void gtk_notebook_destroy(GtkWidget *widget)
4018 {
4019 GSList *children;
4020 GtkNotebookChild *note_child;
4021
4022 for (children = GTK_NOTEBOOK(widget)->children; children;
4023 children = g_slist_next(children)) {
4024 note_child = (GtkNotebookChild *)(children->data);
4025 if (note_child) {
4026 gtk_widget_destroy(note_child->child);
4027 gtk_widget_destroy(note_child->tab_label);
4028 DestroyWindow(note_child->tabpage);
4029 }
4030 g_free(note_child);
4031 }
4032 g_slist_free(GTK_NOTEBOOK(widget)->children);
4033 }
4034
4035 void gtk_notebook_set_size(GtkWidget *widget, GtkAllocation *allocation)
4036 {
4037 GSList *children;
4038 RECT rect;
4039
4040 gtk_container_set_size(widget, allocation);
4041 rect.left = allocation->x;
4042 rect.top = allocation->y;
4043 rect.right = allocation->x + allocation->width;
4044 rect.bottom = allocation->y + allocation->height;
4045 TabCtrl_AdjustRect(widget->hWnd, FALSE, &rect);
4046
4047 for (children = GTK_NOTEBOOK(widget)->children; children;
4048 children = g_slist_next(children)) {
4049 GtkNotebookChild *note_child = (GtkNotebookChild *)(children->data);
4050 if (note_child && note_child->child) {
4051 GtkAllocation child_alloc;
4052
4053 child_alloc.x = rect.left + GTK_CONTAINER(widget)->border_width;
4054 child_alloc.y = rect.top + GTK_CONTAINER(widget)->border_width;
4055 child_alloc.width = rect.right - rect.left
4056 - 2 * GTK_CONTAINER(widget)->border_width;
4057 child_alloc.height = rect.bottom - rect.top
4058 - 2 * GTK_CONTAINER(widget)->border_width;
4059 SetWindowPos(note_child->tabpage, HWND_TOP,
4060 rect.left, rect.top, rect.right - rect.left,
4061 rect.bottom - rect.top, SWP_NOZORDER);
4062 gtk_widget_set_size(note_child->child, &child_alloc);
4063 }
4064 }
4065 }
4066
4067 void gtk_notebook_size_request(GtkWidget *widget,
4068 GtkRequisition *requisition)
4069 {
4070 GSList *children;
4071 GtkNotebookChild *note_child;
4072 GtkRequisition *child_req;
4073 RECT rect;
4074
4075 requisition->width = requisition->height = 0;
4076 for (children = GTK_NOTEBOOK(widget)->children; children;
4077 children = g_slist_next(children)) {
4078 note_child = (GtkNotebookChild *)(children->data);
4079 if (note_child && note_child->child &&
4080 gtk_widget_get_visible(note_child->child)) {
4081 child_req = ¬e_child->child->requisition;
4082 if (child_req->width > requisition->width)
4083 requisition->width = child_req->width;
4084 if (child_req->height > requisition->height)
4085 requisition->height = child_req->height;
4086 }
4087 }
4088 requisition->width += GTK_CONTAINER(widget)->border_width * 2;
4089 requisition->height += GTK_CONTAINER(widget)->border_width * 2;
4090 rect.left = rect.top = 0;
4091 rect.right = requisition->width;
4092 rect.bottom = requisition->height;
4093 TabCtrl_AdjustRect(widget->hWnd, TRUE, &rect);
4094 requisition->width = rect.right - rect.left;
4095 requisition->height = rect.bottom - rect.top;
4096 }
4097
4098 GObject *gtk_adjustment_new(gfloat value, gfloat lower, gfloat upper,
4099 gfloat step_increment, gfloat page_increment,
4100 gfloat page_size)
4101 {
4102 GtkAdjustment *adj;
4103
4104 adj = (GtkAdjustment *)(GtkNewObject(&GtkAdjustmentClass));
4105
4106 adj->value = value;
4107 adj->lower = lower;
4108 adj->upper = upper;
4109 adj->step_increment = step_increment;
4110 adj->page_increment = page_increment;
4111 adj->page_size = page_size;
4112
4113 return G_OBJECT(adj);
4114 }
4115
4116 GtkWidget *gtk_spin_button_new(GtkAdjustment *adjustment,
4117 gfloat climb_rate, guint digits)
4118 {
4119 GtkSpinButton *spin;
4120
4121 spin = GTK_SPIN_BUTTON(GtkNewObject(&GtkSpinButtonClass));
4122 GTK_ENTRY(spin)->is_visible = TRUE;
4123
4124 gtk_spin_button_set_adjustment(spin, adjustment);
4125
4126 return GTK_WIDGET(spin);
4127 }
4128
4129 void gtk_spin_button_size_request(GtkWidget *widget,
4130 GtkRequisition *requisition)
4131 {
4132 gtk_entry_size_request(widget, requisition);
4133 }
4134
4135 void gtk_spin_button_set_size(GtkWidget *widget, GtkAllocation *allocation)
4136 {
4137 int udwidth;
4138 HWND updown;
4139
4140 udwidth = GetSystemMetrics(SM_CXVSCROLL);
4141 allocation->width -= udwidth;
4142
4143 updown = GTK_SPIN_BUTTON(widget)->updown;
4144 if (updown) {
4145 POINT pt;
4146 pt.x = allocation->x;
4147 pt.y = allocation->y;
4148 MapWidgetOrigin(widget, &pt);
4149 SetWindowPos(updown, HWND_TOP, pt.x + allocation->width, pt.y,
4150 udwidth, allocation->height, SWP_NOZORDER);
4151 }
4152 }
4153
4154 gint gtk_spin_button_get_value_as_int(GtkSpinButton *spin_button)
4155 {
4156 HWND hWnd;
4157 LRESULT lres;
4158
4159 hWnd = spin_button->updown;
4160 if (hWnd) {
4161 lres = SendMessageW(hWnd, UDM_GETPOS, 0, 0);
4162 if (HIWORD(lres) != 0)
4163 return 0;
4164 else
4165 return (gint)LOWORD(lres);
4166 } else
4167 return (gint)spin_button->adj->value;
4168 }
4169
4170 void gtk_spin_button_set_value(GtkSpinButton *spin_button, gfloat value)
4171 {
4172 HWND hWnd;
4173
4174 spin_button->adj->value = value;
4175 hWnd = spin_button->updown;
4176 if (hWnd)
4177 SendMessageW(hWnd, UDM_SETPOS, 0, (LPARAM)MAKELONG((short)value, 0));
4178 }
4179
4180 void gtk_spin_button_set_adjustment(GtkSpinButton *spin_button,
4181 GtkAdjustment *adjustment)
4182 {
4183 HWND hWnd;
4184
4185 spin_button->adj = adjustment;
4186 hWnd = spin_button->updown;
4187 if (hWnd) {
4188 SendMessageW(hWnd, UDM_SETRANGE, 0,
4189 (LPARAM)MAKELONG((short)adjustment->upper,
4190 (short)adjustment->lower));
4191 SendMessageW(hWnd, UDM_SETPOS, 0,
4192 (LPARAM)MAKELONG((short)adjustment->value, 0));
4193 }
4194 }
4195
4196 void gtk_spin_button_realize(GtkWidget *widget)
4197 {
4198 GtkSpinButton *spin = GTK_SPIN_BUTTON(widget);
4199 HWND Parent;
4200
4201 gtk_entry_realize(widget);
4202
4203 Parent = gtk_get_parent_hwnd(widget->parent);
4204 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
4205 spin->updown = CreateUpDownControl(WS_CHILD | WS_BORDER | WS_TABSTOP |
4206 UDS_SETBUDDYINT | UDS_NOTHOUSANDS |
4207 UDS_ARROWKEYS, 0, 0, 0, 0, Parent, 0,
4208 hInst, widget->hWnd, 20, 10, 15);
4209 gtk_set_default_font(spin->updown);
4210 gtk_spin_button_set_adjustment(spin, spin->adj);
4211 }
4212
4213 void gtk_spin_button_destroy(GtkWidget *widget)
4214 {
4215 g_free(GTK_SPIN_BUTTON(widget)->adj);
4216 }
4217
4218 void gtk_spin_button_show(GtkWidget *widget)
4219 {
4220 HWND updown;
4221
4222 updown = GTK_SPIN_BUTTON(widget)->updown;
4223 if (updown)
4224 ShowWindow(updown, SW_SHOWNORMAL);
4225 }
4226
4227 void gtk_spin_button_hide(GtkWidget *widget)
4228 {
4229 HWND updown;
4230
4231 updown = GTK_SPIN_BUTTON(widget)->updown;
4232 if (updown)
4233 ShowWindow(updown, SW_HIDE);
4234 }
4235
4236 void gtk_spin_button_update(GtkSpinButton *spin_button)
4237 {
4238 }
4239
4240 GtkWidget *gtk_separator_new(GtkOrientation orientation)
4241 {
4242 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
4243 return GTK_WIDGET(GtkNewObject(&GtkHSeparatorClass));
4244 } else {
4245 return GTK_WIDGET(GtkNewObject(&GtkVSeparatorClass));
4246 }
4247 }
4248
4249 void gtk_separator_size_request(GtkWidget *widget,
4250 GtkRequisition *requisition)
4251 {
4252 requisition->height = requisition->width = 2;
4253 }
4254
4255 void gtk_separator_realize(GtkWidget *widget)
4256 {
4257 HWND Parent;
4258
4259 Parent = gtk_get_parent_hwnd(widget);
4260 widget->hWnd = myCreateWindow(WC_GTKSEP, "", WS_CHILD,
4261 0, 0, 0, 0, Parent, NULL, hInst, NULL);
4262 }
4263
4264 void g_object_set_data(GObject *object, const gchar *key,
4265 gpointer data)
4266 {
4267 g_datalist_set_data(&object->object_data, key, data);
4268 }
4269
4270 gpointer g_object_get_data(GObject *object, const gchar *key)
4271 {
4272 return g_datalist_get_data(&object->object_data, key);
4273 }
4274
4275 GtkAccelGroup *gtk_accel_group_new()
4276 {
4277 GtkAccelGroup *new_accel;
4278
4279 new_accel = g_new0(GtkAccelGroup, 1);
4280 new_accel->accel = NULL;
4281 new_accel->numaccel = 0;
4282 return new_accel;
4283 }
4284
4285 gint gtk_accel_group_add(GtkAccelGroup *accel_group, ACCEL *newaccel)
4286 {
4287 accel_group->numaccel++;
4288 accel_group->accel = g_realloc(accel_group->accel,
4289 accel_group->numaccel * sizeof(ACCEL));
4290 memcpy(&accel_group->accel[accel_group->numaccel - 1], newaccel,
4291 sizeof(ACCEL));
4292 return (accel_group->numaccel - 1);
4293 }
4294
4295 void gtk_accel_group_set_id(GtkAccelGroup *accel_group, gint ind, gint ID)
4296 {
4297 if (ind < accel_group->numaccel)
4298 accel_group->accel[ind].cmd = ID;
4299 }
4300
4301 void gtk_accel_group_destroy(GtkAccelGroup *accel_group)
4302 {
4303 g_free(accel_group->accel);
4304 g_free(accel_group);
4305 }
4306
4307 void gtk_widget_grab_default(GtkWidget *widget)
4308 {
4309 GTK_WIDGET_SET_FLAGS(widget, GTK_IS_DEFAULT);
4310 }
4311
4312 void gtk_widget_grab_focus(GtkWidget *widget)
4313 {
4314 if (widget->hWnd && GTK_WIDGET_CAN_FOCUS(widget)) {
4315 SetFocus(widget->hWnd);
4316 }
4317 }
4318
4319 void gtk_window_set_modal(GtkWindow *window, gboolean modal)
4320 {
4321 window->modal = modal;
4322 }
4323
4324 void gtk_window_add_accel_group(GtkWindow *window,
4325 GtkAccelGroup *accel_group)
4326 {
4327 window->accel_group = accel_group;
4328 }
4329
4330 void gtk_entry_set_text(GtkEntry *entry, const gchar *text)
4331 {
4332 int pos = 0;
4333
4334 gtk_editable_delete_text(GTK_EDITABLE(entry), 0, -1);
4335 gtk_editable_insert_text(GTK_EDITABLE(entry), text, strlen(text), &pos);
4336 }
4337
4338 void gtk_entry_set_visibility(GtkEntry *entry, gboolean visible)
4339 {
4340 HWND hWnd;
4341
4342 entry->is_visible = visible;
4343 hWnd = GTK_WIDGET(entry)->hWnd;
4344 if (hWnd)
4345 SendMessageW(hWnd, EM_SETPASSWORDCHAR, visible ? 0 : (WPARAM)'*', 0);
4346 }
4347
4348 guint SetAccelerator(GtkWidget *labelparent, gchar *Text,
4349 GtkWidget *sendto, gchar *signal,
4350 GtkAccelGroup *accel_group, gboolean needalt)
4351 {
4352 gtk_signal_emit(G_OBJECT(labelparent), "set_text", Text);
4353 return 0;
4354 }
4355
4356 void gtk_widget_add_accelerator(GtkWidget *widget,
4357 const gchar *accel_signal,
4358 GtkAccelGroup *accel_group,
4359 guint accel_key, guint accel_mods,
4360 GtkAccelFlags accel_flags)
4361 {
4362 }
4363
4364 void gtk_widget_remove_accelerator(GtkWidget *widget,
4365 GtkAccelGroup *accel_group,
4366 guint accel_key, guint accel_mods)
4367 {
4368 }
4369
4370 GtkWidget *gtk_paned_new(GtkOrientation orientation)
4371 {
4372 GtkPaned *paned;
4373
4374 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
4375 paned = GTK_PANED(GtkNewObject(&GtkHPanedClass));
4376 } else {
4377 paned = GTK_PANED(GtkNewObject(&GtkVPanedClass));
4378 }
4379 GTK_PANED(paned)->handle_size = 5;
4380 GTK_PANED(paned)->handle_pos = PANED_STARTPOS;
4381 return GTK_WIDGET(paned);
4382 }
4383
4384 static void gtk_paned_pack(GtkPaned *paned, gint pos, GtkWidget *child,
4385 gboolean resize, gboolean shrink)
4386 {
4387 paned->children[pos].widget = child;
4388 paned->children[pos].resize = resize;
4389 paned->children[pos].shrink = shrink;
4390 child->parent = GTK_WIDGET(paned);
4391 }
4392
4393 void gtk_paned_pack1(GtkPaned *paned, GtkWidget *child, gboolean resize,
4394 gboolean shrink)
4395 {
4396 gtk_paned_pack(paned, 0, child, resize, shrink);
4397 }
4398
4399 void gtk_paned_pack2(GtkPaned *paned, GtkWidget *child, gboolean resize,
4400 gboolean shrink)
4401 {
4402 gtk_paned_pack(paned, 1, child, resize, shrink);
4403 }
4404
4405 void gtk_paned_add1(GtkPaned *paned, GtkWidget *child)
4406 {
4407 gtk_paned_pack1(paned, child, FALSE, TRUE);
4408 }
4409
4410 void gtk_paned_add2(GtkPaned *paned, GtkWidget *child)
4411 {
4412 gtk_paned_pack2(paned, child, FALSE, TRUE);
4413 }
4414
4415 void gtk_paned_show_all(GtkWidget *widget, gboolean hWndOnly)
4416 {
4417 GtkPaned *paned = GTK_PANED(widget);
4418 gint i;
4419
4420 for (i = 0; i < 2; i++)
4421 if (paned->children[i].widget) {
4422 gtk_widget_show_all_full(paned->children[i].widget, hWndOnly);
4423 }
4424 }
4425
4426 void gtk_paned_hide_all(GtkWidget *widget, gboolean hWndOnly)
4427 {
4428 GtkPaned *paned = GTK_PANED(widget);
4429 gint i;
4430
4431 for (i = 0; i < 2; i++)
4432 if (paned->children[i].widget)
4433 gtk_widget_hide_all_full(paned->children[i].widget, hWndOnly);
4434 }
4435
4436 void gtk_paned_realize(GtkWidget *widget)
4437 {
4438 GtkPaned *paned = GTK_PANED(widget);
4439 gint i;
4440
4441 for (i = 0; i < 2; i++)
4442 if (paned->children[i].widget) {
4443 gtk_widget_realize(paned->children[i].widget);
4444 }
4445 }
4446
4447 void gtk_vpaned_realize(GtkWidget *widget)
4448 {
4449 HWND Parent;
4450
4451 gtk_paned_realize(widget);
4452 Parent = gtk_get_parent_hwnd(widget);
4453 widget->hWnd = myCreateWindow(WC_GTKVPANED, "", WS_CHILD,
4454 0, 0, 0, 0, Parent, NULL, hInst, NULL);
4455 }
4456
4457 void gtk_hpaned_realize(GtkWidget *widget)
4458 {
4459 HWND Parent;
4460
4461 gtk_paned_realize(widget);
4462 Parent = gtk_get_parent_hwnd(widget);
4463 widget->hWnd = myCreateWindow(WC_GTKHPANED, "", WS_CHILD,
4464 0, 0, 0, 0, Parent, NULL, hInst, NULL);
4465 }
4466
4467 static void gtk_paned_set_handle_percent(GtkPaned *paned, gint16 req[2])
4468 {
4469 if (req[0] + req[1])
4470 paned->handle_pos = req[0] * 100 / (req[0] + req[1]);
4471 else
4472 paned->handle_pos = 0;
4473 }
4474
4475 void gtk_vpaned_size_request(GtkWidget *widget,
4476 GtkRequisition *requisition)
4477 {
4478 GtkPaned *paned = GTK_PANED(widget);
4479 gint i;
4480 gint16 req[2] = { 0, 0 };
4481
4482 requisition->width = requisition->height = 0;
4483 for (i = 0; i < 2; i++)
4484 if (paned->children[i].widget) {
4485 if (paned->children[i].widget->requisition.width >
4486 requisition->width)
4487 requisition->width = paned->children[i].widget->requisition.width;
4488 req[i] = paned->children[i].widget->requisition.height;
4489 requisition->height += req[i];
4490 }
4491 requisition->height += paned->handle_size;
4492 gtk_paned_set_handle_percent(paned, req);
4493 }
4494
4495 void gtk_hpaned_size_request(GtkWidget *widget,
4496 GtkRequisition *requisition)
4497 {
4498 GtkPaned *paned = GTK_PANED(widget);
4499 gint i;
4500 gint16 req[2] = { 0, 0 };
4501
4502 requisition->width = requisition->height = 0;
4503 for (i = 0; i < 2; i++)
4504 if (paned->children[i].widget) {
4505 if (paned->children[i].widget->requisition.height >
4506 requisition->height)
4507 requisition->height =
4508 paned->children[i].widget->requisition.height;
4509 req[i] = paned->children[i].widget->requisition.width;
4510 requisition->width += req[i];
4511 }
4512 requisition->width += paned->handle_size;
4513 gtk_paned_set_handle_percent(paned, req);
4514 }
4515
4516 void gtk_vpaned_set_size(GtkWidget *widget, GtkAllocation *allocation)
4517 {
4518 GtkPaned *paned = GTK_PANED(widget);
4519 GtkWidget *child;
4520 gint16 alloc;
4521 GtkAllocation child_alloc;
4522
4523 memcpy(&paned->true_alloc, allocation, sizeof(GtkAllocation));
4524
4525 alloc = allocation->height - paned->handle_size;
4526
4527 child = paned->children[0].widget;
4528 if (child) {
4529 child_alloc.x = allocation->x;
4530 child_alloc.y = allocation->y;
4531 child_alloc.width = allocation->width;
4532 child_alloc.height = alloc * paned->handle_pos / 100;
4533 gtk_widget_set_size(child, &child_alloc);
4534 }
4535
4536 child = paned->children[1].widget;
4537 if (child) {
4538 child_alloc.x = allocation->x;
4539 child_alloc.width = allocation->width;
4540 child_alloc.height = alloc * (100 - paned->handle_pos) / 100;
4541 child_alloc.y =
4542 allocation->y + allocation->height - child_alloc.height;
4543 gtk_widget_set_size(child, &child_alloc);
4544 }
4545
4546 allocation->y += alloc * paned->handle_pos / 100;
4547 allocation->height = paned->handle_size;
4548 }
4549
4550 void gtk_hpaned_set_size(GtkWidget *widget, GtkAllocation *allocation)
4551 {
4552 GtkPaned *paned = GTK_PANED(widget);
4553 GtkWidget *child;
4554 gint16 alloc;
4555 GtkAllocation child_alloc;
4556
4557 memcpy(&paned->true_alloc, allocation, sizeof(GtkAllocation));
4558 alloc = allocation->width - paned->handle_size;
4559
4560 child = paned->children[0].widget;
4561 if (child) {
4562 child_alloc.x = allocation->x;
4563 child_alloc.y = allocation->y;
4564 child_alloc.height = allocation->height;
4565 child_alloc.width = alloc * paned->handle_pos / 100;
4566 gtk_widget_set_size(child, &child_alloc);
4567 }
4568
4569 child = paned->children[1].widget;
4570 if (child) {
4571 child_alloc.x = allocation->x;
4572 child_alloc.height = allocation->height;
4573 child_alloc.width = alloc * (100 - paned->handle_pos) / 100;
4574 child_alloc.x = allocation->x + allocation->width - child_alloc.width;
4575 gtk_widget_set_size(child, &child_alloc);
4576 }
4577
4578 allocation->x += alloc * paned->handle_pos / 100;
4579 allocation->width = paned->handle_size;
4580 }
4581
4582 void gtk_text_set_editable(GtkText *text, gboolean is_editable)
4583 {
4584 gtk_editable_set_editable(GTK_EDITABLE(text), is_editable);
4585 }
4586
4587 void gtk_text_set_word_wrap(GtkText *text, gboolean word_wrap)
4588 {
4589 text->word_wrap = word_wrap;
4590 }
4591
4592 void gtk_text_freeze(GtkText *text)
4593 {
4594 }
4595
4596 void gtk_text_thaw(GtkText *text)
4597 {
4598 }
4599
4600 GtkTextBuffer *gtk_text_view_get_buffer(GtkText *text)
4601 {
4602 return text->buffer;
4603 }
4604
4605 static int parse_colcomp(const gchar *hexval)
4606 {
4607 int col = 0, i, ch;
4608
4609 for (i = 0; i < 4; ++i) {
4610 col <<= 4;
4611 ch = toupper(hexval[i]);
4612 if (ch >= '0' && ch <= '9') {
4613 col |= (ch - '0');
4614 } else if (ch >= 'A' && ch <= 'F') {
4615 col |= (ch - 'A' + 10);
4616 }
4617 }
4618 return col / 257; /* Scale from 0-65535 to 0-255 */
4619 }
4620
4621 static gboolean parse_color(const gchar *name, COLORREF *color)
4622 {
4623 int red, green, blue, i, ch;
4624
4625 if (!name || strlen(name) != 13 || name[0] != '#') {
4626 return FALSE;
4627 }
4628 for (i = strlen(name) - 1; i >= 1; --i) {
4629 ch = toupper(name[i]);
4630 if (!((ch >= '0' && ch <= '9')
4631 || (ch >= 'A' && ch <= 'F'))) {
4632 return FALSE;
4633 }
4634 }
4635 red = parse_colcomp(&name[1]);
4636 green = parse_colcomp(&name[5]);
4637 blue = parse_colcomp(&name[9]);
4638 if (color) {
4639 *color = RGB(red, green, blue);
4640 }
4641 return TRUE;
4642 }
4643
4644 void gtk_text_buffer_create_tag(GtkTextBuffer *buffer, const gchar *name, ...)
4645 {
4646 va_list ap;
4647 gchar *attr, *data;
4648 CHARFORMAT *cf;
4649
4650 va_start(ap, name);
4651 cf = g_new(CHARFORMAT, 1);
4652 cf->cbSize = sizeof(CHARFORMAT);
4653 cf->dwMask = 0;
4654 do {
4655 attr = va_arg(ap, gchar *);
4656 if (attr) {
4657 if (strcmp(attr, "foreground") == 0) {
4658 data = va_arg(ap, gchar *);
4659 cf->dwMask |= CFM_COLOR;
4660 cf->dwEffects = 0;
4661 if (!parse_color(data, &cf->crTextColor)) {
4662 cf->dwEffects = CFE_AUTOCOLOR;
4663 }
4664 }
4665 }
4666 } while (attr);
4667
4668 g_datalist_set_data_full(&buffer->tags, name, cf, g_free);
4669 va_end(ap);
4670 }
4671
4672 GtkWidget *gtk_combo_box_new_with_model(GtkTreeModel *model)
4673 {
4674 GtkComboBox *combo_box;
4675
4676 combo_box = GTK_COMBO_BOX(GtkNewObject(&GtkComboBoxClass));
4677 combo_box->active = -1;
4678 combo_box->model_column = -1;
4679 gtk_combo_box_set_model(combo_box, model);
4680 return GTK_WIDGET(combo_box);
4681 }
4682
4683 void gtk_cell_layout_set_attributes(GtkCellLayout *cell_layout,
4684 GtkCellRenderer *cell, ...)
4685 {
4686 const char *name;
4687 va_list args;
4688
4689 va_start(args, cell);
4690 /* Currently we only support the "text" attribute to point to the
4691 ListStore column */
4692 while ((name = va_arg(args, const char *)) != NULL) {
4693 if (strcmp(name, "text") == 0) {
4694 cell_layout->model_column = va_arg(args, int);
4695 }
4696 }
4697 va_end(args);
4698 }
4699
4700 void gtk_combo_box_set_model(GtkComboBox *combo_box, GtkTreeModel *model)
4701 {
4702 HWND hWnd;
4703
4704 if (!model)
4705 return;
4706 combo_box->model = model;
4707 hWnd = GTK_WIDGET(combo_box)->hWnd;
4708
4709 /* For now we work only with a single column of string type */
4710 if (hWnd) {
4711 SendMessageW(hWnd, CB_RESETCONTENT, 0, 0);
4712 }
4713 if (hWnd && combo_box->model_column >= 0) {
4714 int nrow;
4715 int col = combo_box->model_column;
4716 g_assert(model->coltype[col] == G_TYPE_STRING);
4717 for (nrow = 0; nrow < combo_box->model->rows->len; ++nrow) {
4718 GtkListStoreRow *row = &g_array_index(combo_box->model->rows,
4719 GtkListStoreRow, nrow);
4720 myComboBox_AddString(hWnd, row->data[col]);
4721 }
4722 SendMessageW(hWnd, CB_SETCURSEL, (WPARAM)combo_box->active, 0);
4723 }
4724 }
4725
4726 GtkTreeModel *gtk_combo_box_get_model(GtkComboBox *combo_box)
4727 {
4728 return combo_box->model;
4729 }
4730
4731 void gtk_combo_box_set_active(GtkComboBox *combo_box, gint index)
4732 {
4733 combo_box->active = index;
4734 }
4735
4736 gboolean gtk_combo_box_get_active_iter(GtkComboBox *combo_box,
4737 GtkTreeIter *iter)
4738 {
4739 if (combo_box->active >= 0) {
4740 *iter = combo_box->active;
4741 return TRUE;
4742 } else {
4743 return FALSE;
4744 }
4745 }
4746
4747 void gtk_combo_box_size_request(GtkWidget *widget,
4748 GtkRequisition *requisition)
4749 {
4750 SIZE size;
4751
4752 if (GetTextSize(widget->hWnd, "Sample text", &size, defFont)) {
4753 requisition->width = size.cx + 40;
4754 requisition->height = size.cy + 4;
4755 }
4756 }
4757
4758 void gtk_combo_box_set_size(GtkWidget *widget, GtkAllocation *allocation)
4759 {
4760 allocation->height *= 6;
4761 }
4762
4763 void gtk_combo_box_realize(GtkWidget *widget)
4764 {
4765 HWND Parent;
4766 GtkComboBox *combo_box = GTK_COMBO_BOX(widget);
4767
4768 Parent = gtk_get_parent_hwnd(widget);
4769 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
4770 widget->hWnd = myCreateWindowEx(WS_EX_CLIENTEDGE, "COMBOBOX", "",
4771 WS_CHILD | WS_TABSTOP | WS_VSCROLL |
4772 CBS_HASSTRINGS | CBS_DROPDOWNLIST,
4773 0, 0, 0, 0, Parent, NULL, hInst, NULL);
4774 gtk_set_default_font(widget->hWnd);
4775 gtk_combo_box_set_model(combo_box, combo_box->model);
4776 }
4777
4778 void gtk_combo_box_destroy(GtkWidget *widget)
4779 {
4780 GtkComboBox *combo_box = GTK_COMBO_BOX(widget);
4781 if (combo_box->model) {
4782 gtk_tree_model_free(combo_box->model);
4783 }
4784 combo_box->model = NULL;
4785 }
4786
4787 void gtk_label_set_text(GtkLabel *label, const gchar *str)
4788 {
4789 HWND hWnd;
4790
4791 g_free(label->text);
4792 label->text = g_strdup(str ? str : "");
4793 g_strdelimit(label->text, "_", '&');
4794 hWnd = GTK_WIDGET(label)->hWnd;
4795 if (hWnd) {
4796 gtk_widget_update(GTK_WIDGET(label), FALSE);
4797 mySetWindowText(hWnd, label->text);
4798 }
4799 }
4800
4801 void gtk_button_set_text(GtkButton *button, gchar *text)
4802 {
4803 HWND hWnd;
4804
4805 g_free(button->text);
4806 button->text = g_strdup(text ? text : "");
4807 g_strdelimit(button->text, "_", '&');
4808 hWnd = GTK_WIDGET(button)->hWnd;
4809 if (hWnd) {
4810 gtk_widget_update(GTK_WIDGET(button), FALSE);
4811 mySetWindowText(hWnd, button->text);
4812 }
4813 }
4814
4815 static void gtk_menu_item_set_text(GtkMenuItem *menuitem, gchar *text)
4816 {
4817 GtkWidget *widget = GTK_WIDGET(menuitem);
4818
4819 g_free(menuitem->text);
4820 menuitem->text = g_strdup(text ? text : "");
4821 g_strdelimit(menuitem->text, "_", '&');
4822
4823 if (GTK_WIDGET_REALIZED(widget)) {
4824 MENUITEMINFO mii;
4825 HMENU parent_menu;
4826
4827 parent_menu = GTK_MENU_SHELL(widget->parent)->menu;
4828 mii.cbSize = sizeof(MENUITEMINFO);
4829 mii.fMask = MIIM_TYPE;
4830 mii.fType = MFT_STRING;
4831 mii.dwTypeData = (LPTSTR)menuitem->text;
4832 mii.cch = myw32strlen(menuitem->text);
4833 mySetMenuItemInfo(parent_menu, menuitem->ID, FALSE, &mii);
4834 }
4835 }
4836
4837 const char *gtk_label_get_text(GtkLabel *label)
4838 {
4839 return label->text;
4840 }
4841
4842 void gtk_text_set_point(GtkText *text, guint index)
4843 {
4844 gtk_editable_set_position(GTK_EDITABLE(text), index);
4845 }
4846
4847 void gtk_widget_set_size_request(GtkWidget *widget, gint width, gint height)
4848 {
4849 widget->usize.width = width;
4850 widget->usize.height = height;
4851 }
4852
4853 void gtk_editable_create(GtkWidget *widget)
4854 {
4855 GtkEditable *editable = GTK_EDITABLE(widget);
4856
4857 gtk_widget_create(widget);
4858 editable->is_editable = TRUE;
4859 editable->text = g_string_new("");
4860 }
4861
4862 void gtk_combo_box_update_selection(GtkWidget *widget)
4863 {
4864 LRESULT lres;
4865
4866 if (widget->hWnd == NULL)
4867 return;
4868 lres = SendMessageW(widget->hWnd, CB_GETCURSEL, 0, 0);
4869 if (lres == CB_ERR)
4870 return;
4871
4872 GTK_COMBO_BOX(widget)->active = lres;
4873 gtk_signal_emit(G_OBJECT(widget), "changed");
4874 }
4875
4876 void gtk_window_handle_user_size(GtkWindow *window,
4877 GtkAllocation *allocation)
4878 {
4879 }
4880
4881 void gtk_window_handle_minmax_size(GtkWindow *window, LPMINMAXINFO minmax)
4882 {
4883 GtkRequisition *req;
4884
4885 req = >K_WIDGET(window)->requisition;
4886 if (!window->allow_shrink) {
4887 minmax->ptMinTrackSize.x = req->width;
4888 minmax->ptMinTrackSize.y = req->height;
4889 }
4890 if (!window->allow_grow) {
4891 minmax->ptMaxTrackSize.x = req->width;
4892 minmax->ptMaxTrackSize.y = req->height;
4893 }
4894 }
4895
4896 void gtk_window_set_initial_position(GtkWindow *window,
4897 GtkAllocation *allocation)
4898 {
4899 RECT rect;
4900 GtkWidget *widget = GTK_WIDGET(window);
4901
4902 GetWindowRect(GetDesktopWindow(), &rect);
4903
4904 if (widget->parent) {
4905 allocation->x =
4906 rect.left + (rect.right - rect.left - allocation->width) / 2;
4907 allocation->y =
4908 rect.top + (rect.bottom - rect.top - allocation->height) / 2;
4909 if (allocation->x < 0)
4910 allocation->x = 0;
4911 if (allocation->y < 0)
4912 allocation->y = 0;
4913 if (widget->hWnd)
4914 SetWindowPos(widget->hWnd, HWND_TOP, allocation->x,
4915 allocation->y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
4916 }
4917 }
4918
4919 void gtk_window_handle_auto_size(GtkWindow *window,
4920 GtkAllocation *allocation)
4921 {
4922 GtkWidget *widget = GTK_WIDGET(window);
4923
4924 if (allocation->width < window->default_width) {
4925 allocation->width = window->default_width;
4926 }
4927 if (allocation->height < window->default_height) {
4928 allocation->height = window->default_height;
4929 }
4930 if (allocation->width < widget->allocation.width) {
4931 allocation->width = widget->allocation.width;
4932 }
4933 if (allocation->height < widget->allocation.height) {
4934 allocation->height = widget->allocation.height;
4935 }
4936 }
4937
4938 void gtk_paned_set_position(GtkPaned *paned, gint position)
4939 {
4940 GtkAllocation allocation;
4941
4942 if (position < 0)
4943 position = 0;
4944 if (position > 100)
4945 position = 100;
4946 paned->handle_pos = position;
4947 memcpy(&allocation, &paned->true_alloc, sizeof(GtkAllocation));
4948 gtk_widget_set_size(GTK_WIDGET(paned), &allocation);
4949 }
4950
4951 void gtk_misc_set_alignment(GtkMisc *misc, gfloat xalign, gfloat yalign)
4952 {
4953 }
4954
4955 GtkWidget *gtk_progress_bar_new()
4956 {
4957 GtkProgressBar *prog;
4958
4959 prog = GTK_PROGRESS_BAR(GtkNewObject(&GtkProgressBarClass));
4960 prog->orient = GTK_PROGRESS_LEFT_TO_RIGHT;
4961 prog->position = 0;
4962
4963 return GTK_WIDGET(prog);
4964 }
4965
4966 void gtk_progress_bar_set_fraction(GtkProgressBar *pbar, gfloat percentage)
4967 {
4968 GtkWidget *widget;
4969
4970 widget = GTK_WIDGET(pbar);
4971 pbar->position = percentage;
4972 if (GTK_WIDGET_REALIZED(widget)) {
4973 SendMessageW(widget->hWnd, PBM_SETPOS,
4974 (WPARAM)(10000.0 * pbar->position), 0);
4975 }
4976 }
4977
4978 void gtk_progress_bar_size_request(GtkWidget *widget,
4979 GtkRequisition *requisition)
4980 {
4981 SIZE size;
4982
4983 if (GetTextSize(widget->hWnd, "Sample", &size, defFont)) {
4984 requisition->width = size.cx;
4985 requisition->height = size.cy;
4986 }
4987 }
4988
4989 void gtk_progress_bar_realize(GtkWidget *widget)
4990 {
4991 HWND Parent;
4992 GtkProgressBar *prog;
4993
4994 prog = GTK_PROGRESS_BAR(widget);
4995 Parent = gtk_get_parent_hwnd(widget);
4996 widget->hWnd = myCreateWindowEx(WS_EX_CLIENTEDGE, PROGRESS_CLASS, "",
4997 WS_CHILD,
4998 widget->allocation.x, widget->allocation.y,
4999 widget->allocation.width,
5000 widget->allocation.height, Parent, NULL,
5001 hInst, NULL);
5002 gtk_set_default_font(widget->hWnd);
5003 SendMessageW(widget->hWnd, PBM_SETRANGE, 0, MAKELPARAM(0, 10000));
5004 SendMessageW(widget->hWnd, PBM_SETPOS, (WPARAM)(10000.0 * prog->position),
5005 0);
5006 }
5007
5008 gint GtkMessageBox(GtkWidget *parent, const gchar *Text,
5009 const gchar *Title, GtkMessageType type, gint Options)
5010 {
5011 gint retval;
5012
5013 RecurseLevel++;
5014
5015 switch(type) {
5016 case GTK_MESSAGE_WARNING:
5017 Options |= MB_ICONWARNING; break;
5018 case GTK_MESSAGE_ERROR:
5019 Options |= MB_ICONERROR; break;
5020 case GTK_MESSAGE_QUESTION:
5021 Options |= MB_ICONQUESTION; break;
5022 default: break;
5023 }
5024
5025 retval = myMessageBox(parent && parent->hWnd ? parent->hWnd : NULL,
5026 Text, Title, Options);
5027 RecurseLevel--;
5028
5029 return retval;
5030 }
5031
5032
5033 /* Add a new source and return a unique ID */
5034 static guint add_our_source(OurSource *source)
5035 {
5036 GSList *list;
5037 guint id = 1;
5038
5039 /* Get an unused ID */
5040 list = OurSources;
5041 while (list) {
5042 OurSource *s = (OurSource *)list->data;
5043 if (s->id == id) {
5044 id++;
5045 list = OurSources; /* Back to the start */
5046 } else {
5047 list = g_slist_next(list);
5048 }
5049 }
5050
5051 source->id = id;
5052 OurSources = g_slist_append(OurSources, source);
5053 return source->id;
5054 }
5055
5056 /* Like g_timeout_add(), but uses the Windows event loop */
5057 guint dp_g_timeout_add(guint interval, GSourceFunc function, gpointer data)
5058 {
5059 guint id;
5060 OurSource *source = g_new0(OurSource, 1);
5061 source->timeout_function = function;
5062 source->data = data;
5063 id = add_our_source(source);
5064 if (SetTimer(TopLevel, id, interval, NULL) == 0) {
5065 g_warning("Failed to create timer!");
5066 }
5067 return id;
5068 }
5069
5070 /* Like g_io_add_watch(), but uses the Windows event loop */
5071 guint dp_g_io_add_watch(GIOChannel *channel, GIOCondition condition,
5072 GIOFunc func, gpointer user_data)
5073 {
5074 OurSource *source = g_new0(OurSource, 1);
5075 source->io_channel = channel;
5076 source->io_function = func;
5077 source->socket = g_io_channel_unix_get_fd(channel);
5078 source->data = user_data;
5079 WSAAsyncSelect(source->socket, TopLevel, MYWM_SOCKETDATA,
5080 (condition & G_IO_IN ? FD_READ | FD_CLOSE | FD_ACCEPT : 0)
5081 | (condition & G_IO_OUT ? FD_WRITE | FD_CONNECT : 0));
5082 return add_our_source(source);
5083 }
5084
5085 /* Like g_source_remove(), but uses the Windows event loop */
5086 gboolean dp_g_source_remove(guint tag)
5087 {
5088 GSList *list;
5089 OurSource *s;
5090 for (list = OurSources; list; list = g_slist_next(list)) {
5091 s = (OurSource *)list->data;
5092 if (s->id == tag) {
5093 if (s->timeout_function) {
5094 if (KillTimer(TopLevel, s->id) == 0) {
5095 g_warning("Failed to kill timer!");
5096 }
5097 } else {
5098 WSAAsyncSelect(s->socket, TopLevel, 0, 0);
5099 }
5100 OurSources = g_slist_remove(OurSources, s);
5101 g_free(s);
5102 break;
5103 }
5104 }
5105 return TRUE;
5106 }
5107
5108 GtkWidget *gtk_button_new_with_mnemonic(const gchar *label)
5109 {
5110 return gtk_button_new_with_label(label);
5111 }
5112
5113 /* We don't really handle styles, so these are just placeholder functions */
5114 static GtkStyle statstyle;
5115 GtkStyle *gtk_style_new(void)
5116 {
5117 return &statstyle;
5118 }
5119
5120 void gtk_widget_set_style(GtkWidget *widget, GtkStyle *style)
5121 {
5122 }
5123
5124 GtkWidget *gtk_button_box_new(GtkOrientation orientation)
5125 {
5126 GtkWidget *bbox, *spacer;
5127
5128 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
5129 bbox = gtk_box_new(orientation, 0);
5130 } else {
5131 bbox = gtk_box_new(orientation, 5);
5132 }
5133 gtk_box_set_homogeneous(GTK_BOX(bbox), TRUE);
5134 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
5135 /* Add a spacer so that all hboxes are right-aligned */
5136 spacer = gtk_label_new("");
5137 gtk_box_pack_start(GTK_BOX(bbox), spacer, TRUE, TRUE, 0);
5138 }
5139 return bbox;
5140 }
5141
5142 void gtk_box_set_spacing(GtkBox *box, gint spacing)
5143 {
5144 box->spacing = spacing;
5145 }
5146
5147 /*
5148 * Win32 doesn't use a window manager, so this is just a placeholder.
5149 */
5150 void gtk_window_set_type_hint(GtkWindow *window, GdkWindowTypeHint hint)
5151 {
5152 }
5153
5154 void gtk_window_set_position(GtkWindow *window, GtkWindowPosition position)
5155 {
5156 }
5157
5158 #define GTK_GET_FILE_LEN 800
5159 gchar *GtkGetFile(const GtkWidget *parent, const gchar *oldname,
5160 const gchar *title)
5161 {
5162 OPENFILENAMEW ofn;
5163 gunichar2 *title2, file[GTK_GET_FILE_LEN];
5164
5165 file[0] = 0;
5166 title2 = strtow32(title, -1);
5167 /* Convert from our (UTF-8) representation to Windows Unicode */
5168 if (oldname) {
5169 glong nwritten;
5170 char *abspath = NULL;
5171 gunichar2 *oldname2;
5172 /* Make absolute if necessary; OpenFileName does not work with
5173 relative paths */
5174 if (!g_path_is_absolute(oldname)) {
5175 abspath = g_canonicalize_filename(oldname, NULL);
5176 }
5177 oldname2 = g_utf8_to_utf16(abspath ? abspath : oldname, -1, NULL,
5178 &nwritten, NULL);
5179 if (oldname2) {
5180 memcpy(file, oldname2,
5181 MIN(GTK_GET_FILE_LEN, nwritten) * sizeof(gunichar2));
5182 /* Ensure null terminated */
5183 file[GTK_GET_FILE_LEN - 1] = 0;
5184 g_free(oldname2);
5185 }
5186 g_free(abspath);
5187 }
5188 ofn.lStructSize = sizeof(OPENFILENAMEW);
5189 ofn.hwndOwner = parent ? parent->hWnd : NULL;
5190 ofn.hInstance = NULL;
5191 ofn.lpstrFilter = NULL;
5192 ofn.lpstrCustomFilter = NULL;
5193 ofn.nFilterIndex = 1;
5194 ofn.lpstrFile = file;
5195 ofn.nMaxFile = GTK_GET_FILE_LEN;
5196 ofn.lpstrFileTitle = NULL;
5197 ofn.nMaxFileTitle = 0;
5198 ofn.lpstrInitialDir = NULL;
5199 ofn.lpstrTitle = title2;
5200 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
5201 ofn.lpstrDefExt = NULL;
5202 if (GetOpenFileNameW(&ofn)) {
5203 g_free(title2);
5204 return w32tostr(file, -1);
5205 } else {
5206 g_free(title2);
5207 return NULL;
5208 }
5209 }
5210
5211 void gtk_widget_set_can_default(GtkWidget *wid, gboolean flag)
5212 {
5213 if (flag) {
5214 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
5215 } else {
5216 GTK_WIDGET_UNSET_FLAGS(wid, GTK_CAN_DEFAULT);
5217 }
5218 }
5219
5220 #else /* CYGWIN */
5221
5222 #if GTK_MAJOR_VERSION == 2
5223 GtkWidget *gtk_button_box_new(GtkOrientation orientation)
5224 {
5225 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
5226 return gtk_hbutton_box_new();
5227 } else {
5228 return gtk_vbutton_box_new();
5229 }
5230 }
5231
5232 GtkWidget *gtk_box_new(GtkOrientation orientation, gint spacing)
5233 {
5234 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
5235 return gtk_hbox_new(FALSE, spacing);
5236 } else {
5237 return gtk_vbox_new(FALSE, spacing);
5238 }
5239 }
5240
5241 GtkWidget *gtk_separator_new(GtkOrientation orientation)
5242 {
5243 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
5244 return gtk_hseparator_new();
5245 } else {
5246 return gtk_vseparator_new();
5247 }
5248 }
5249
5250 GtkWidget *gtk_paned_new(GtkOrientation orientation)
5251 {
5252 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
5253 return gtk_hpaned_new();
5254 } else {
5255 return gtk_vpaned_new();
5256 }
5257 }
5258
5259 #endif
5260
5261 guint SetAccelerator(GtkWidget *labelparent, gchar *Text,
5262 GtkWidget *sendto, gchar *signal,
5263 GtkAccelGroup *accel_group, gboolean needalt)
5264 {
5265 #if GTK_MAJOR_VERSION == 2
5266 guint AccelKey;
5267
5268 AccelKey =
5269 gtk_label_parse_uline(GTK_LABEL(GTK_BIN(labelparent)->child), Text);
5270 if (sendto && AccelKey) {
5271 gtk_widget_add_accelerator(sendto, signal, accel_group, AccelKey,
5272 needalt ? GDK_MOD1_MASK : 0,
5273 GTK_ACCEL_VISIBLE);
5274 }
5275 return AccelKey;
5276 #else
5277 gtk_label_set_text_with_mnemonic(
5278 GTK_LABEL(gtk_bin_get_child(GTK_BIN(labelparent))), Text);
5279 if (sendto) {
5280 gtk_label_set_mnemonic_widget(
5281 GTK_LABEL(gtk_bin_get_child(GTK_BIN(labelparent))), sendto);
5282 }
5283 return 0;
5284 #endif
5285 }
5286
5287 GtkWidget *gtk_scrolled_text_view_new(GtkWidget **pack_widg)
5288 {
5289 GtkWidget *textview, *scrollwin, *frame;
5290
5291 textview = gtk_text_view_new();
5292
5293 frame = gtk_frame_new(NULL);
5294 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
5295
5296 scrollwin = gtk_scrolled_window_new(NULL, NULL);
5297 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
5298 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
5299 gtk_container_add(GTK_CONTAINER(scrollwin), textview);
5300 gtk_container_add(GTK_CONTAINER(frame), scrollwin);
5301
5302 *pack_widg = frame;
5303 return textview;
5304 }
5305
5306 void TextViewAppend(GtkTextView *textview, const gchar *text,
5307 const gchar *tagname, gboolean scroll)
5308 {
5309 GtkTextBuffer *buffer;
5310 GtkTextIter iter;
5311 GtkTextMark *insert;
5312
5313 buffer = gtk_text_view_get_buffer(textview);
5314
5315 gtk_text_buffer_get_end_iter(buffer, &iter);
5316 gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, text, -1,
5317 tagname, NULL);
5318 if (scroll) {
5319 gtk_text_buffer_place_cursor(buffer, &iter);
5320 insert = gtk_text_buffer_get_mark(buffer, "insert");
5321 gtk_text_view_scroll_mark_onscreen(textview, insert);
5322 }
5323 }
5324
5325 void TextViewClear(GtkTextView *textview)
5326 {
5327 GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
5328
5329 gtk_text_buffer_set_text(buffer, "", -1);
5330 }
5331
5332 static void DestroyGtkMessageBox(GtkWidget *widget, gpointer data)
5333 {
5334 gtk_main_quit();
5335 }
5336
5337 static void GtkMessageBoxCallback(GtkWidget *widget, gpointer data)
5338 {
5339 gint *retval;
5340 GtkWidget *dialog;
5341
5342 dialog = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
5343 retval = (gint *)g_object_get_data(G_OBJECT(widget), "retval");
5344 if (retval)
5345 *retval = GPOINTER_TO_INT(data);
5346 gtk_widget_destroy(dialog);
5347 }
5348
5349 gint OldGtkMessageBox(GtkWidget *parent, const gchar *Text,
5350 const gchar *Title, gint Options)
5351 {
5352 GtkWidget *dialog, *button, *label, *vbox, *hbbox, *hsep;
5353 GtkAccelGroup *accel_group;
5354 gint i;
5355 static gint retval;
5356 gboolean imm_return;
5357 const gchar *ButtonData[MB_MAX] = {
5358 N_("_OK"), N_("_Cancel"), N_("_Yes"), N_("_No")
5359 };
5360
5361 imm_return = Options & MB_IMMRETURN;
5362 dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
5363 accel_group = gtk_accel_group_new();
5364 gtk_window_add_accel_group(GTK_WINDOW(dialog), accel_group);
5365 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
5366 gtk_container_set_border_width(GTK_CONTAINER(dialog), 7);
5367 if (parent)
5368 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent));
5369 if (!imm_return) {
5370 g_signal_connect(G_OBJECT(dialog), "destroy",
5371 G_CALLBACK(DestroyGtkMessageBox), NULL);
5372 }
5373 if (Title)
5374 gtk_window_set_title(GTK_WINDOW(dialog), Title);
5375
5376 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 7);
5377
5378 if (Text) {
5379 label = gtk_label_new(Text);
5380 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
5381 }
5382
5383 hsep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
5384 gtk_box_pack_start(GTK_BOX(vbox), hsep, FALSE, FALSE, 0);
5385
5386 retval = MB_CANCEL;
5387
5388 hbbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
5389 for (i = 0; i < MB_MAX; i++) {
5390 if (Options & (1 << i)) {
5391 button = gtk_button_new_with_mnemonic(_(ButtonData[i]));
5392 if (!imm_return) {
5393 g_object_set_data(G_OBJECT(button), "retval", &retval);
5394 }
5395 g_signal_connect(G_OBJECT(button), "clicked",
5396 G_CALLBACK(GtkMessageBoxCallback),
5397 GINT_TO_POINTER(1 << i));
5398 gtk_box_pack_start(GTK_BOX(hbbox), button, TRUE, TRUE, 0);
5399 }
5400 }
5401 gtk_box_pack_start(GTK_BOX(vbox), hbbox, TRUE, TRUE, 0);
5402 gtk_container_add(GTK_CONTAINER(dialog), vbox);
5403 gtk_widget_show_all(dialog);
5404 if (!imm_return)
5405 gtk_main();
5406 return retval;
5407 }
5408
5409 gint GtkMessageBox(GtkWidget *parent, const gchar *Text,
5410 const gchar *Title, GtkMessageType type, gint Options)
5411 {
5412 GtkWidget *dialog;
5413 gint retval;
5414 GtkButtonsType buttons = GTK_BUTTONS_NONE;
5415
5416 if (Options & MB_IMMRETURN || !parent) {
5417 return OldGtkMessageBox(parent, Text, Title, Options);
5418 }
5419
5420 if (Options & MB_CANCEL) buttons = GTK_BUTTONS_OK_CANCEL;
5421 else if (Options & MB_OK) buttons = GTK_BUTTONS_OK;
5422 else if (Options & MB_YESNO) buttons = GTK_BUTTONS_YES_NO;
5423
5424 dialog = gtk_message_dialog_new(GTK_WINDOW(parent),
5425 GTK_DIALOG_MODAL,
5426 type, buttons, "%s", Text);
5427 if (Title) gtk_window_set_title(GTK_WINDOW(dialog), Title);
5428
5429 retval = gtk_dialog_run(GTK_DIALOG(dialog));
5430 gtk_widget_destroy(dialog);
5431 return retval;
5432 }
5433
5434 void DisplayHTML(GtkWidget *parent, const gchar *bin, const gchar *target)
5435 {
5436 #ifdef APPLE
5437 mac_open_url(target);
5438 #elif defined(HAVE_FORK)
5439 char *args[3];
5440 pid_t pid;
5441 int status;
5442
5443 if (target && target[0] && bin && bin[0]) {
5444 args[0] = (char *)bin;
5445 args[1] = (char *)target;
5446 args[2] = NULL;
5447 /* Fork twice so that the spawned process gets init as its parent */
5448 pid = fork();
5449 if (pid > 0) {
5450 wait(&status);
5451 } else if (pid == 0) {
5452 pid = fork();
5453 if (pid == 0) {
5454 execv(bin, args);
5455 g_print("dopewars: cannot execute %s\n", bin);
5456 _exit(EXIT_FAILURE);
5457 } else {
5458 _exit(EXIT_SUCCESS);
5459 }
5460 }
5461 }
5462 #endif
5463 }
5464
5465 GtkWidget *gtk_url_new(const gchar *text, const gchar *target,
5466 const gchar *bin)
5467 {
5468 GtkWidget *button;
5469 button = gtk_link_button_new(text);
5470 gtk_link_button_set_uri(GTK_LINK_BUTTON(button), target);
5471 return button;
5472 }
5473
5474 gchar *GtkGetFile(const GtkWidget *parent, const gchar *oldname,
5475 const gchar *title)
5476 {
5477 GtkWidget *dialog;
5478 GtkFileChooser *chooser;
5479 gint res;
5480 gchar *ret;
5481
5482 dialog = gtk_file_chooser_dialog_new(
5483 title, GTK_WINDOW(parent), GTK_FILE_CHOOSER_ACTION_OPEN,
5484 _("_Cancel"), GTK_RESPONSE_CANCEL,
5485 _("_Select"), GTK_RESPONSE_ACCEPT, NULL);
5486 chooser = GTK_FILE_CHOOSER(dialog);
5487 gtk_file_chooser_set_filename(chooser, oldname);
5488 res = gtk_dialog_run(GTK_DIALOG(dialog));
5489 ret = NULL;
5490 if (res == GTK_RESPONSE_ACCEPT) {
5491 ret = gtk_file_chooser_get_filename(chooser);
5492 }
5493 gtk_widget_destroy(dialog);
5494 return ret;
5495 }
5496
5497 #endif /* CYGWIN */
5498
5499 /* Make a new GtkLabel, with the text possibly bold */
5500 GtkWidget *make_bold_label(const char *text, gboolean bold)
5501 {
5502 #ifdef CYGWIN
5503 /* We don't support bold text on Windows yet */
5504 return gtk_label_new(text);
5505 #else
5506 if (bold) {
5507 GtkWidget *label = gtk_label_new(NULL);
5508 gchar *markup = g_markup_printf_escaped(
5509 "<span font_weight=\"bold\" fgcolor=\"#0000DD\">%s</span>", text);
5510 gtk_label_set_markup(GTK_LABEL(label), markup);
5511 g_free(markup);
5512 return label;
5513 } else {
5514 return gtk_label_new(text);
5515 }
5516 #endif
5517 }
5518
5519 #if !CYGWIN && \
5520 (GTK_MAJOR_VERSION > 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 4))
5521 /* GtkGrid does not take a size, unlike GtkTable */
5522 GtkWidget *dp_gtk_grid_new(guint rows, guint cols, gboolean homogeneous)
5523 {
5524 GtkWidget *grid = gtk_grid_new();
5525 if (homogeneous) {
5526 gtk_grid_set_row_homogeneous(GTK_GRID(grid), TRUE);
5527 gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE);
5528 }
5529 return grid;
5530 }
5531
5532 void dp_gtk_grid_attach(GtkGrid *grid, GtkWidget *child,
5533 gint left, gint top,
5534 gint width, gint height, gboolean expand)
5535 {
5536 gtk_grid_attach(grid, child, left, top, width, height);
5537 if (expand) {
5538 gtk_widget_set_hexpand(child, TRUE);
5539 }
5540 }
5541 #else
5542 /* Implementation for older GTK or Win32, using GtkTable */
5543 GtkWidget *dp_gtk_grid_new(guint rows, guint columns, gboolean homogeneous)
5544 {
5545 GtkWidget *table = gtk_table_new(rows, columns, homogeneous);
5546 return table;
5547 }
5548
5549 void dp_gtk_grid_attach(GtkGrid *grid, GtkWidget *child,
5550 gint left, gint top,
5551 gint width, gint height, gboolean expand)
5552 {
5553 gtk_table_attach(grid, child, left, left + width, top, top + height,
5554 expand ? (GTK_EXPAND | GTK_FILL) : GTK_SHRINK,
5555 expand ? (GTK_EXPAND | GTK_FILL) : GTK_SHRINK, 0, 0);
5556 }
5557 #endif
5558
5559 #if !CYGWIN && \
5560 (GTK_MAJOR_VERSION > 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 2))
5561 void set_label_alignment(GtkWidget *widget, gfloat xalign, gfloat yalign)
5562 {
5563 gtk_label_set_xalign(GTK_LABEL(widget), xalign);
5564 gtk_label_set_yalign(GTK_LABEL(widget), yalign);
5565 }
5566 #else
5567 void set_label_alignment(GtkWidget *widget, gfloat xalign, gfloat yalign)
5568 {
5569 gtk_misc_set_alignment(GTK_MISC(widget), xalign, yalign);
5570 }
5571 #endif
5572
5573 #if CYGWIN
5574 void TextViewAppend(GtkTextView *textview, const gchar *text,
5575 const gchar *tagname, gboolean scroll)
5576 {
5577 gint editpos;
5578
5579 editpos = gtk_text_get_length(GTK_TEXT(textview));
5580 gtk_editable_insert_text(GTK_EDITABLE(textview), text, strlen(text),
5581 &editpos);
5582 #ifdef CYGWIN
5583 gtk_text_view_set_format(textview, tagname, myw32strlen(text), editpos);
5584 #endif
5585 if (scroll) {
5586 gtk_editable_set_position(GTK_EDITABLE(textview), editpos);
5587 }
5588 }
5589
5590 void TextViewClear(GtkTextView *textview)
5591 {
5592 gtk_editable_delete_text(GTK_EDITABLE(textview), 0, -1);
5593 }
5594 #endif