URI:
       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 = &note_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 = &GTK_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