tWindows client now supports menu keyboard shortcuts; Win2K "bank" bug (hopefully) fixed - vaccinewars - be a doctor and try to vaccinate the world
 (HTM) git clone git://src.adamsgaard.dk/vaccinewars
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit c36da537a319cbf1fe6096f8ddf214655a298a66
 (DIR) parent 00e4b2e2bdfc603f8ce07ec3b8b98c2cd6af22c1
 (HTM) Author: Ben Webb <ben@salilab.org>
       Date:   Sun, 21 Oct 2001 18:36:03 +0000
       
       Windows client now supports menu keyboard shortcuts; Win2K "bank" bug (hopefully) fixed
       
       
       Diffstat:
         M src/gtkport.c                       |     133 ++++++++++++++++++++++++++-----
         M src/gtkport.h                       |       9 +++++++--
       
       2 files changed, 119 insertions(+), 23 deletions(-)
       ---
 (DIR) diff --git a/src/gtkport.c b/src/gtkport.c
       t@@ -219,6 +219,8 @@ static void gtk_window_set_initial_position(GtkWindow *window,
        static void gtk_progress_bar_size_request(GtkWidget *widget,
                                                  GtkRequisition *requisition);
        static void gtk_progress_bar_realize(GtkWidget *widget);
       +static gint gtk_accel_group_add(GtkAccelGroup *accel_group,ACCEL *newaccel);
       +static void gtk_accel_group_set_id(GtkAccelGroup *accel_group,gint ind,gint ID);
        
        typedef struct _GdkInput GdkInput;
        
       t@@ -873,7 +875,7 @@ LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,UINT wParam,LONG lParam) {
                    gtk_option_menu_update_selection(widget);
                 } else if (lParam && HIWORD(wParam)==BN_CLICKED) {
                    gtk_signal_emit(GTK_OBJECT(widget),"clicked");
       -         } else if (HIWORD(wParam)==0) {
       +         } else if (HIWORD(wParam)==0 || HIWORD(wParam)==1) {
                    window=GTK_WIDGET(GetWindowLong(hwnd,GWL_USERDATA));
                    widget=gtk_window_get_menu_ID(GTK_WINDOW(window),LOWORD(wParam));
                    if (widget) gtk_signal_emit(GTK_OBJECT(widget),"activate");
       t@@ -1211,6 +1213,8 @@ void gtk_widget_create(GtkWidget *widget) {
        void gtk_widget_destroy(GtkWidget *widget) {
           if (!widget) return;
           gtk_widget_lose_focus(widget);
       +   if (widget->hWnd) DestroyWindow(widget->hWnd);
       +   widget->hWnd=NULL;
        // g_print("gtk_widget_destroy on widget %p\n",widget);
           gtk_signal_emit(GTK_OBJECT(widget),"destroy");
        // g_print("Freeing widget\n");
       t@@ -1778,10 +1782,12 @@ void gtk_window_destroy(GtkWidget *widget) {
        // g_print("gtk_window_destroy on widget %p\n",widget);
           WindowList=g_slist_remove(WindowList,(gpointer)window);
           gtk_container_destroy(widget);
       -   g_free(GTK_WINDOW(widget)->title);
       +   if (window->accel_group) gtk_accel_group_destroy(window->accel_group);
       +   if (window->hAccel) DestroyAcceleratorTable(window->hAccel);
       +   g_free(window->title);
           EnableParent(window);
       -   if (widget->hWnd) DestroyWindow(widget->hWnd);
       -   widget->hWnd=NULL;
       +// if (widget->hWnd) DestroyWindow(widget->hWnd);
       +// widget->hWnd=NULL;
        }
        
        void gtk_window_show(GtkWidget *widget) {
       t@@ -1987,6 +1993,11 @@ void gtk_window_realize(GtkWidget *widget) {
           gtk_set_default_font(widget->hWnd);
        /* g_print("Window window %p created\n",widget->hWnd);*/
           gtk_container_realize(widget);
       +
       +   if (win->accel_group && win->accel_group->numaccel) {
       +     win->hAccel = CreateAcceleratorTable(win->accel_group->accel,
       +                                          win->accel_group->numaccel);
       +   }
        // if (win->focus && win->focus->hWnd) SetFocus(win->focus->hWnd);
        }
        
       t@@ -2023,7 +2034,9 @@ void gtk_button_realize(GtkWidget *widget) {
           GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS);
           Parent=gtk_get_parent_hwnd(widget);
           widget->hWnd = CreateWindow("BUTTON",but->text,
       -                            WS_CHILD|WS_TABSTOP|BS_PUSHBUTTON,
       +                            WS_CHILD|WS_TABSTOP|
       +                            (GTK_WIDGET_FLAGS(widget)&GTK_IS_DEFAULT ?
       +                             BS_DEFPUSHBUTTON : BS_PUSHBUTTON),
                                    widget->allocation.x,widget->allocation.y,
                                    widget->allocation.width,widget->allocation.height,
                                    Parent,NULL,hInst,NULL);
       t@@ -2867,6 +2880,7 @@ void gtk_radio_button_toggled(GtkRadioButton *radio_button,gpointer data) {
           GtkRadioButton *radio;
           gboolean is_active = GTK_TOGGLE_BUTTON(radio_button)->toggled;
           hWnd=GTK_WIDGET(radio_button)->hWnd;
       +g_print("radio_button_toggled\n");
           if (hWnd) {
              SendMessage(hWnd,BM_SETCHECK,is_active ? BST_CHECKED : BST_UNCHECKED,0);
           }
       t@@ -2900,23 +2914,27 @@ void gtk_main() {
           MSG msg;
           GSList *list;
           BOOL MsgDone;
       -   GtkWidget *widget;
       +   GtkWidget *widget,*window;
           HACCEL hAccel;
        
           RecurseLevel++;
        
           while (GetMessage(&msg,NULL,0,0)) {
              MsgDone=FALSE;
       -      for (list=WindowList;list && !MsgDone;list=g_slist_next(list)) {
       +      widget=GTK_WIDGET(GetWindowLong(msg.hwnd,GWL_USERDATA));
       +      window=gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW);
       +      if (window) {
       +        hAccel=GTK_WINDOW(window)->hAccel;
       +        if (hAccel) {
       +          MsgDone=TranslateAccelerator(window->hWnd,hAccel,&msg);
       +        }
       +      }
       +      if (!MsgDone) for (list=WindowList;list && !MsgDone;
       +                         list=g_slist_next(list)) {
                 widget=GTK_WIDGET(list->data);
                 if (widget && widget->hWnd &&
                     (MsgDone=IsDialogMessage(widget->hWnd,&msg))==TRUE) break;
              }
       -      widget=GTK_WIDGET(GetWindowLong(msg.hwnd,GWL_USERDATA));
       -      if (!MsgDone && widget && GTK_OBJECT(widget)->klass==&GtkWindowClass) {
       -         hAccel=GTK_WINDOW(widget)->hAccel;
       -         if (hAccel) MsgDone=TranslateAccelerator(widget->hWnd,hAccel,&msg);
       -      }
              if (!MsgDone) {
                 TranslateMessage(&msg);
                 DispatchMessage(&msg);
       t@@ -3144,6 +3162,7 @@ GtkItemFactory *gtk_item_factory_new(GtkType container_type,
           GtkItemFactory *new_fac;
           new_fac=(GtkItemFactory *)GtkNewObject(&GtkItemFactoryClass);
           new_fac->path=g_strdup(path);
       +   new_fac->accel_group = accel_group;
           new_fac->top_widget=gtk_menu_bar_new();
           return new_fac;
        }
       t@@ -3166,14 +3185,14 @@ static gint PathCmp(const gchar *path1,const gchar *path2) {
        static void gtk_item_factory_parse_path(GtkItemFactory *ifactory,
                                                gchar *path,
                                                GtkItemFactoryChild **parent,
       -                                        gchar **menu_title) {
       +                                        GString *menu_title) {
           GSList *list;
           GtkItemFactoryChild *child;
       -   gchar *root,*pt,*title;
       +   gchar *root,*pt;
        
           pt=strrchr(path,'/');
           if (!pt) return;
       -   title=g_strdup(pt+1);
       +   g_string_assign(menu_title,pt+1);
           root=g_strdup(path);
           root[pt-path]='\0';
        
       t@@ -3182,22 +3201,60 @@ static void gtk_item_factory_parse_path(GtkItemFactory *ifactory,
              child=(GtkItemFactoryChild *)list->data;
              if (PathCmp(child->path,root)==1) { *parent=child; break; }
           }
       -   *menu_title=title;
           g_free(root);
        }
        
       +static gboolean gtk_item_factory_parse_accel(GtkItemFactory *ifactory,
       +                                             gchar *accelerator,
       +                                             GString *menu_title,ACCEL *accel) {
       +  gchar *apt;
       +
       +  if (!accelerator) return FALSE;
       +
       +  apt=accelerator;
       +  accel->fVirt=0;
       +  accel->key=0;
       +  accel->cmd=0;
       +
       +  g_string_append(menu_title,"\t");
       +
       +  if (strncmp(apt,"<control>",9)==0) {
       +    accel->fVirt |= FCONTROL;
       +    g_string_append(menu_title,"Ctrl+");
       +    apt+=9;
       +  }
       +
       +  if (strlen(apt)==1) {
       +    g_string_append_c(menu_title,*apt);
       +    accel->key = *apt;
       +    accel->fVirt |= FVIRTKEY;
       +  } else if (strcmp(apt,"F1")==0) {
       +    g_string_append(menu_title,apt);
       +    accel->fVirt |= FVIRTKEY;
       +    accel->key = VK_F1;
       +  }
       +  return (accel->key!=0);
       +}
       +
        void gtk_item_factory_create_item(GtkItemFactory *ifactory,
                                          GtkItemFactoryEntry *entry,
                                          gpointer callback_data,guint callback_type) {
           GtkItemFactoryChild *new_child,*parent=NULL;
       -   gchar *menu_title=NULL;
       +   GString *menu_title;
           GtkWidget *menu_item,*menu;
       +   ACCEL accel;
       +   gboolean haveaccel;
        
           new_child=g_new0(GtkItemFactoryChild,1);
           new_child->path=g_strdup(entry->path);
        
       -   gtk_item_factory_parse_path(ifactory,new_child->path,&parent,&menu_title);
       -   menu_item=gtk_menu_item_new_with_label(menu_title);
       +   menu_title = g_string_new("");
       +
       +   gtk_item_factory_parse_path(ifactory,new_child->path,&parent,menu_title);
       +   haveaccel = gtk_item_factory_parse_accel(ifactory,entry->accelerator,
       +                                            menu_title,&accel);
       +
       +   menu_item=gtk_menu_item_new_with_label(menu_title->str);
           new_child->widget=menu_item;
           if (entry->callback) {
              gtk_signal_connect(GTK_OBJECT(menu_item),"activate",
       t@@ -3215,7 +3272,12 @@ void gtk_item_factory_create_item(GtkItemFactory *ifactory,
              gtk_menu_bar_append(GTK_MENU_BAR(ifactory->top_widget),menu_item);
           }
        
       -   g_free(menu_title);
       +   if (haveaccel && ifactory->accel_group) {
       +     GTK_MENU_ITEM(menu_item)->accelind=
       +             gtk_accel_group_add(ifactory->accel_group,&accel);
       +   }
       +
       +   g_string_free(menu_title,TRUE);
        
           ifactory->children=g_slist_append(ifactory->children,new_child);
        }
       t@@ -3304,6 +3366,7 @@ GtkWidget *gtk_menu_item_new_with_label(const gchar *label) {
           gint i;
        
           menu_item=GTK_MENU_ITEM(GtkNewObject(&GtkMenuItemClass));
       +   menu_item->accelind=-1;
           menu_item->text=g_strdup(label);
           for (i=0;i<strlen(menu_item->text);i++) {
              if (menu_item->text[i]=='_') menu_item->text[i]='&';
       t@@ -3357,13 +3420,21 @@ void gtk_menu_bar_realize(GtkWidget *widget) {
        void gtk_menu_item_realize(GtkWidget *widget) {
           GtkMenuItem *menu_item=GTK_MENU_ITEM(widget);
           MENUITEMINFO mii;
       -   GtkWidget *menu_bar;
       +   GtkWidget *menu_bar,*window;
           HMENU parent_menu;
           gint pos;
        
           menu_bar=gtk_widget_get_ancestor(widget,GTK_TYPE_MENU_BAR);
           if (menu_bar) menu_item->ID=GTK_MENU_BAR(menu_bar)->LastID++;
        
       +   if (menu_item->accelind>=0) {
       +     window=gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW);
       +     if (window && GTK_WINDOW(window)->accel_group) {
       +       gtk_accel_group_set_id(GTK_WINDOW(window)->accel_group,
       +                              menu_item->accelind,menu_item->ID);
       +     }
       +   }
       +
           if (menu_item->submenu) gtk_widget_realize(GTK_WIDGET(menu_item->submenu));
        
           parent_menu=GTK_MENU_SHELL(widget->parent)->menu;
       t@@ -3783,9 +3854,28 @@ gpointer gtk_object_get_data(GtkObject *object,const gchar *key) {
        GtkAccelGroup *gtk_accel_group_new() {
           GtkAccelGroup *new_accel;
           new_accel=g_new0(GtkAccelGroup,1);
       +   new_accel->accel = NULL;
       +   new_accel->numaccel = 0;
           return new_accel;
        }
        
       +gint gtk_accel_group_add(GtkAccelGroup *accel_group,ACCEL *newaccel) {
       +  accel_group->numaccel++;
       +  accel_group->accel = g_realloc(accel_group->accel,
       +                                 accel_group->numaccel*sizeof(ACCEL));
       +  memcpy(&accel_group->accel[accel_group->numaccel-1],newaccel,sizeof(ACCEL));
       +  return (accel_group->numaccel-1);
       +}
       +
       +void gtk_accel_group_set_id(GtkAccelGroup *accel_group,gint ind,gint ID) {
       +  if (ind < accel_group->numaccel) accel_group->accel[ind].cmd = ID;
       +}
       +
       +void gtk_accel_group_destroy(GtkAccelGroup *accel_group) {
       +  g_free(accel_group->accel);
       +  g_free(accel_group);
       +}
       +
        void gtk_item_factory_set_translate_func(GtkItemFactory *ifactory,
                                                 GtkTranslateFunc func,
                                                 gpointer data,
       t@@ -3793,6 +3883,7 @@ void gtk_item_factory_set_translate_func(GtkItemFactory *ifactory,
        }
        
        void gtk_widget_grab_default(GtkWidget *widget) {
       +  GTK_WIDGET_SET_FLAGS(widget,GTK_IS_DEFAULT);
        }
        
        void gtk_widget_grab_focus(GtkWidget *widget) {
 (DIR) diff --git a/src/gtkport.h b/src/gtkport.h
       t@@ -99,7 +99,8 @@ typedef enum {
           GTK_SENSITIVE   = 1 << 10,
           GTK_CAN_FOCUS   = 1 << 11,
           GTK_HAS_FOCUS   = 1 << 12,
       -   GTK_CAN_DEFAULT = 1 << 13
       +   GTK_CAN_DEFAULT = 1 << 13,
       +   GTK_IS_DEFAULT =  1 << 14
        } GtkWidgetFlags;
        
        #define GTK_VISIBLE 1
       t@@ -135,7 +136,8 @@ typedef struct _GtkHPaned GtkHPaned;
        typedef struct _GtkOptionMenu GtkOptionMenu;
        
        struct _GtkAccelGroup {
       -   GSList *accel;
       +   ACCEL *accel;    /* list of ACCEL structures */
       +   gint numaccel;
        };
        
        struct _GtkSignalType {
       t@@ -209,6 +211,7 @@ struct _GtkMenuItem {
           GtkWidget widget;
           GtkMenu *submenu;
           gint ID;
       +   gint accelind;
           gchar *text;
        };
        
       t@@ -320,6 +323,7 @@ struct _GtkItemFactory {
           GtkObject object;
           GSList *children;
           gchar *path;
       +   GtkAccelGroup *accel_group;
           GtkWidget *top_widget;
        };
        
       t@@ -640,6 +644,7 @@ GtkWidget *gtk_vseparator_new();
        void gtk_object_set_data(GtkObject *object,const gchar *key,gpointer data);
        gpointer gtk_object_get_data(GtkObject *object,const gchar *key);
        GtkAccelGroup *gtk_accel_group_new();
       +void gtk_accel_group_destroy(GtkAccelGroup *accel_group);
        void gtk_item_factory_set_translate_func(GtkItemFactory *ifactory,
                                                 GtkTranslateFunc func,
                                                 gpointer data,