tUse our GtkItemFactory even on non-Win32 systems - vaccinewars - be a doctor a… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 407fd240b1d9ecce669deaa14fac7c82c0490799 | |
parent 2182939206935c97309c8656cfdd140a1cf696da | |
Author: Ben Webb <[email protected]> | |
Date: Thu, 19 Nov 2020 22:23:01 -0800 | |
Use our GtkItemFactory even on non-Win32 systems | |
GtkItemFactory has been removed from GTK+3, but we | |
already have an implementation in gtkport for Win32 | |
systems. Adapt this to work on Unix too, so we don't | |
have to rework the setup of our menus for GTK+3. | |
Diffstat: | |
M src/gtkport/Makefile.am | 3 ++- | |
M src/gtkport/gtkport.c | 224 -----------------------------… | |
M src/gtkport/gtkport.h | 41 ++---------------------------… | |
A src/gtkport/itemfactory.c | 290 +++++++++++++++++++++++++++++… | |
A src/gtkport/itemfactory.h | 93 +++++++++++++++++++++++++++++… | |
M src/gui_client/gtk_client.c | 66 ++++++++++++++++-------------… | |
6 files changed, 420 insertions(+), 297 deletions(-) | |
--- | |
diff --git a/src/gtkport/Makefile.am b/src/gtkport/Makefile.am | |
t@@ -1,5 +1,6 @@ | |
noinst_LIBRARIES = libgtkport.a | |
libgtkport_a_SOURCES = gtkport.c gtkport.h clist.c clist.h gtkenums.h \ | |
- unicodewrap.c unicodewrap.h treeview.h treeview.c | |
+ unicodewrap.c unicodewrap.h treeview.h treeview.c \ | |
+ itemfactory.c itemfactory.h | |
AM_CPPFLAGS= -I../../intl -I${srcdir} -I${srcdir}/.. -I../.. @GTK_CFLAGS@ @GLI… | |
DEFS = @DEFS@ | |
diff --git a/src/gtkport/gtkport.c b/src/gtkport/gtkport.c | |
t@@ -254,13 +254,6 @@ struct _OurSource { | |
}; | |
typedef struct _OurSource OurSource; | |
-typedef struct _GtkItemFactoryChild GtkItemFactoryChild; | |
- | |
-struct _GtkItemFactoryChild { | |
- gchar *path; | |
- GtkWidget *widget; | |
-}; | |
- | |
static GtkSignalType GtkObjectSignals[] = { | |
{"create", gtk_marshal_VOID__VOID, NULL}, | |
{"", NULL, NULL} | |
t@@ -274,10 +267,6 @@ static GtkClass GtkAdjustmentClass = { | |
"adjustment", &GtkObjectClass, sizeof(GtkAdjustment), NULL, NULL | |
}; | |
-static GtkClass GtkItemFactoryClass = { | |
- "itemfactory", &GtkObjectClass, sizeof(GtkItemFactory), NULL, NULL | |
-}; | |
- | |
static GtkSignalType GtkWidgetSignals[] = { | |
{"create", gtk_marshal_VOID__VOID, gtk_widget_create}, | |
{"size_request", gtk_marshal_VOID__GPOIN, NULL}, | |
t@@ -3641,210 +3630,6 @@ guint gtk_signal_connect_object(GtkObject *object, con… | |
return 0; | |
} | |
-GtkItemFactory *gtk_item_factory_new(GtkType container_type, | |
- const gchar *path, | |
- GtkAccelGroup *accel_group) | |
-{ | |
- 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(); | |
- new_fac->translate_func = NULL; | |
- return new_fac; | |
-} | |
- | |
-static gint PathCmp(const gchar *path1, const gchar *path2) | |
-{ | |
- gint Match = 1; | |
- | |
- if (!path1 || !path2) | |
- return 0; | |
- | |
- while (*path1 && *path2 && Match) { | |
- while (*path1 == '_') | |
- path1++; | |
- while (*path2 == '_') | |
- path2++; | |
- if (*path1 == *path2) { | |
- path1++; | |
- path2++; | |
- } else | |
- Match = 0; | |
- } | |
- if (*path1 || *path2) | |
- Match = 0; | |
- return Match; | |
-} | |
- | |
-static gchar *TransPath(GtkItemFactory *ifactory, gchar *path) | |
-{ | |
- gchar *transpath = NULL; | |
- | |
- if (ifactory->translate_func) { | |
- transpath = | |
- (*ifactory->translate_func) (path, ifactory->translate_data); | |
- } | |
- | |
- return transpath ? transpath : path; | |
-} | |
- | |
-static void gtk_item_factory_parse_path(GtkItemFactory *ifactory, | |
- gchar *path, | |
- GtkItemFactoryChild **parent, | |
- GString *menu_title) | |
-{ | |
- GSList *list; | |
- GtkItemFactoryChild *child; | |
- gchar *root, *pt, *transpath; | |
- | |
- transpath = TransPath(ifactory, path); | |
- pt = strrchr(transpath, '/'); | |
- if (pt) | |
- g_string_assign(menu_title, pt + 1); | |
- | |
- pt = strrchr(path, '/'); | |
- if (!pt) | |
- return; | |
- root = g_strdup(path); | |
- root[pt - path] = '\0'; | |
- | |
- for (list = ifactory->children; list; list = g_slist_next(list)) { | |
- child = (GtkItemFactoryChild *)list->data; | |
- if (PathCmp(child->path, root) == 1) { | |
- *parent = child; | |
- break; | |
- } | |
- } | |
- 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; | |
- GString *menu_title; | |
- GtkWidget *menu_item, *menu; | |
- ACCEL accel; | |
- gboolean haveaccel; | |
- | |
- new_child = g_new0(GtkItemFactoryChild, 1); | |
- | |
- new_child->path = g_strdup(entry->path); | |
- | |
- 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); | |
- if (entry->item_type && strcmp(entry->item_type, "<CheckItem>") == 0) { | |
- GTK_CHECK_MENU_ITEM(menu_item)->check = 1; | |
- } | |
- new_child->widget = menu_item; | |
- if (entry->callback) { | |
- gtk_signal_connect(GTK_OBJECT(menu_item), "activate", | |
- entry->callback, callback_data); | |
- } | |
- | |
- if (parent) { | |
- menu = GTK_WIDGET(GTK_MENU_ITEM(parent->widget)->submenu); | |
- if (!menu) { | |
- menu = gtk_menu_new(); | |
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(parent->widget), menu); | |
- } | |
- gtk_menu_append(GTK_MENU(menu), menu_item); | |
- } else { | |
- gtk_menu_bar_append(GTK_MENU_BAR(ifactory->top_widget), menu_item); | |
- } | |
- | |
- 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); | |
-} | |
- | |
-void gtk_item_factory_create_items(GtkItemFactory *ifactory, | |
- guint n_entries, | |
- GtkItemFactoryEntry *entries, | |
- gpointer callback_data) | |
-{ | |
- gint i; | |
- | |
- for (i = 0; i < n_entries; i++) { | |
- gtk_item_factory_create_item(ifactory, &entries[i], callback_data, 0); | |
- } | |
-} | |
- | |
-GtkWidget *gtk_item_factory_get_widget(GtkItemFactory *ifactory, | |
- const gchar *path) | |
-{ | |
- gint root_len; | |
- GSList *list; | |
- GtkItemFactoryChild *child; | |
- | |
- root_len = strlen(ifactory->path); | |
- if (!path || strlen(path) < root_len) | |
- return NULL; | |
- | |
- if (strncmp(ifactory->path, path, root_len) != 0) | |
- return NULL; | |
- if (strlen(path) == root_len) | |
- return ifactory->top_widget; | |
- | |
- for (list = ifactory->children; list; list = g_slist_next(list)) { | |
- child = (GtkItemFactoryChild *)list->data; | |
- if (PathCmp(child->path, &path[root_len]) == 1) | |
- return child->widget; | |
- } | |
- return NULL; | |
-} | |
- | |
void gtk_menu_shell_insert(GtkMenuShell *menu_shell, GtkWidget *child, | |
gint position) | |
{ | |
t@@ -4534,15 +4319,6 @@ void gtk_accel_group_destroy(GtkAccelGroup *accel_group) | |
g_free(accel_group); | |
} | |
-void gtk_item_factory_set_translate_func(GtkItemFactory *ifactory, | |
- GtkTranslateFunc func, | |
- gpointer data, | |
- GtkDestroyNotify notify) | |
-{ | |
- ifactory->translate_func = func; | |
- ifactory->translate_data = data; | |
-} | |
- | |
void gtk_widget_grab_default(GtkWidget *widget) | |
{ | |
GTK_WIDGET_SET_FLAGS(widget, GTK_IS_DEFAULT); | |
diff --git a/src/gtkport/gtkport.h b/src/gtkport/gtkport.h | |
t@@ -27,6 +27,8 @@ | |
#include <config.h> | |
#endif | |
+#include "itemfactory.h" | |
+ | |
#ifdef CYGWIN | |
/* GTK+ emulation prototypes etc. for Win32 platform */ | |
t@@ -60,7 +62,6 @@ extern HICON mainIcon; | |
#define GDK_KP_9 0xFFB9 | |
typedef gint (*GtkFunction) (gpointer data); | |
-typedef gchar *(*GtkTranslateFunc) (const gchar *path, gpointer func_data); | |
typedef void (*GtkDestroyNotify) (gpointer data); | |
#define GTK_VISIBLE 1 | |
t@@ -75,7 +76,6 @@ typedef struct _GtkSignalType GtkSignalType; | |
typedef struct _GtkContainer GtkContainer; | |
typedef void (*GtkSignalFunc) (); | |
-typedef void (*GtkItemFactoryCallback) (); | |
typedef void (*GtkSignalMarshaller) (GtkObject *object, GSList *actions, | |
GtkSignalFunc default_action, | |
va_list args); | |
t@@ -298,26 +298,6 @@ typedef struct _GtkHBox GtkHBox; | |
typedef struct _GtkVBox GtkVBox; | |
typedef struct _GtkNotebookChild GtkNotebookChild; | |
typedef struct _GtkNotebook GtkNotebook; | |
-typedef struct _GtkItemFactoryEntry GtkItemFactoryEntry; | |
-typedef struct _GtkItemFactory GtkItemFactory; | |
- | |
-struct _GtkItemFactoryEntry { | |
- gchar *path; | |
- gchar *accelerator; | |
- GtkItemFactoryCallback callback; | |
- guint callback_action; | |
- gchar *item_type; | |
-}; | |
- | |
-struct _GtkItemFactory { | |
- GtkObject object; | |
- GSList *children; | |
- gchar *path; | |
- GtkAccelGroup *accel_group; | |
- GtkWidget *top_widget; | |
- GtkTranslateFunc translate_func; | |
- gpointer translate_data; | |
-}; | |
struct _GtkBoxChild { | |
GtkWidget *widget; | |
t@@ -525,19 +505,6 @@ GtkWidget *gtk_entry_new(); | |
void gtk_entry_set_visibility(GtkEntry *entry, gboolean visible); | |
GtkWidget *gtk_table_new(guint rows, guint cols, gboolean homogeneous); | |
void gtk_table_resize(GtkTable *table, guint rows, guint cols); | |
-GtkItemFactory *gtk_item_factory_new(GtkType container_type, | |
- const gchar *path, | |
- GtkAccelGroup *accel_group); | |
-void gtk_item_factory_create_item(GtkItemFactory *ifactory, | |
- GtkItemFactoryEntry *entry, | |
- gpointer callback_data, | |
- guint callback_type); | |
-void gtk_item_factory_create_items(GtkItemFactory *ifactory, | |
- guint n_entries, | |
- GtkItemFactoryEntry *entries, | |
- gpointer callback_data); | |
-GtkWidget *gtk_item_factory_get_widget(GtkItemFactory *ifactory, | |
- const gchar *path); | |
GSList *gtk_radio_button_group(GtkRadioButton *radio_button); | |
void gtk_editable_insert_text(GtkEditable *editable, const gchar *new_text, | |
gint new_text_length, gint *position); | |
t@@ -631,10 +598,6 @@ void gtk_object_set_data(GtkObject *object, const gchar *… | |
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, | |
- GtkDestroyNotify notify); | |
void gtk_widget_grab_default(GtkWidget *widget); | |
void gtk_widget_grab_focus(GtkWidget *widget); | |
void gtk_window_set_modal(GtkWindow *window, gboolean modal); | |
diff --git a/src/gtkport/itemfactory.c b/src/gtkport/itemfactory.c | |
t@@ -0,0 +1,290 @@ | |
+/************************************************************************ | |
+ * itemfactory.c GtkItemFactory and friends for Unix/Win32 * | |
+ * Copyright (C) 1998-2020 Ben Webb * | |
+ * Email: [email protected] * | |
+ * WWW: https://dopewars.sourceforge.io/ * | |
+ * * | |
+ * This program is free software; you can redistribute it and/or * | |
+ * modify it under the terms of the GNU General Public License * | |
+ * as published by the Free Software Foundation; either version 2 * | |
+ * of the License, or (at your option) any later version. * | |
+ * * | |
+ * This program is distributed in the hope that it will be useful, * | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
+ * GNU General Public License for more details. * | |
+ * * | |
+ * You should have received a copy of the GNU General Public License * | |
+ * along with this program; if not, write to the Free Software * | |
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * | |
+ * MA 02111-1307, USA. * | |
+ ************************************************************************/ | |
+ | |
+#ifdef HAVE_CONFIG_H | |
+#include <config.h> | |
+#endif | |
+ | |
+#include "gtkport.h" | |
+ | |
+/* No need to reimplement functions if we have GTK+2 */ | |
+#if defined(CYGWIN) || GTK_MAJOR_VERSION > 2 | |
+ | |
+#ifdef CYGWIN | |
+ | |
+#define OurAccel ACCEL | |
+ | |
+#else | |
+typedef struct _OurAccel OurAccel; | |
+struct _OurAccel { | |
+ guint key; | |
+ GdkModifierType mods; | |
+ GtkAccelFlags flags; | |
+}; | |
+#endif | |
+ | |
+typedef struct _DPGtkItemFactoryChild DPGtkItemFactoryChild; | |
+ | |
+struct _DPGtkItemFactoryChild { | |
+ gchar *path; | |
+ GtkWidget *widget; | |
+}; | |
+ | |
+DPGtkItemFactory *dp_gtk_item_factory_new(GtkType container_type, | |
+ const gchar *path, | |
+ GtkAccelGroup *accel_group) | |
+{ | |
+ DPGtkItemFactory *new_fac; | |
+ | |
+ new_fac = g_new0(DPGtkItemFactory, 1); | |
+ new_fac->path = g_strdup(path); | |
+ new_fac->accel_group = accel_group; | |
+ new_fac->top_widget = gtk_menu_bar_new(); | |
+ new_fac->translate_func = NULL; | |
+ return new_fac; | |
+} | |
+ | |
+static gint PathCmp(const gchar *path1, const gchar *path2) | |
+{ | |
+ gint Match = 1; | |
+ | |
+ if (!path1 || !path2) | |
+ return 0; | |
+ | |
+ while (*path1 && *path2 && Match) { | |
+ while (*path1 == '_') | |
+ path1++; | |
+ while (*path2 == '_') | |
+ path2++; | |
+ if (*path1 == *path2) { | |
+ path1++; | |
+ path2++; | |
+ } else | |
+ Match = 0; | |
+ } | |
+ if (*path1 || *path2) | |
+ Match = 0; | |
+ return Match; | |
+} | |
+ | |
+static gchar *TransPath(DPGtkItemFactory *ifactory, gchar *path) | |
+{ | |
+ gchar *transpath = NULL; | |
+ | |
+ if (ifactory->translate_func) { | |
+ transpath = | |
+ (*ifactory->translate_func) (path, ifactory->translate_data); | |
+ } | |
+ | |
+ return transpath ? transpath : path; | |
+} | |
+ | |
+static void gtk_item_factory_parse_path(DPGtkItemFactory *ifactory, | |
+ gchar *path, | |
+ DPGtkItemFactoryChild **parent, | |
+ GString *menu_title) | |
+{ | |
+ GSList *list; | |
+ DPGtkItemFactoryChild *child; | |
+ gchar *root, *pt, *transpath; | |
+ | |
+ transpath = TransPath(ifactory, path); | |
+ pt = strrchr(transpath, '/'); | |
+ if (pt) | |
+ g_string_assign(menu_title, pt + 1); | |
+ | |
+ pt = strrchr(path, '/'); | |
+ if (!pt) | |
+ return; | |
+ root = g_strdup(path); | |
+ root[pt - path] = '\0'; | |
+ | |
+ for (list = ifactory->children; list; list = g_slist_next(list)) { | |
+ child = (DPGtkItemFactoryChild *)list->data; | |
+ if (PathCmp(child->path, root) == 1) { | |
+ *parent = child; | |
+ break; | |
+ } | |
+ } | |
+ g_free(root); | |
+} | |
+ | |
+static gboolean gtk_item_factory_parse_accel(DPGtkItemFactory *ifactory, | |
+ gchar *accelerator, | |
+ GString *menu_title, | |
+ OurAccel *accel) | |
+{ | |
+ gchar *apt; | |
+ | |
+ if (!accelerator) | |
+ return FALSE; | |
+ | |
+ apt = accelerator; | |
+#ifdef CYGWIN | |
+ accel->fVirt = 0; | |
+ accel->key = 0; | |
+ accel->cmd = 0; | |
+ g_string_append(menu_title, "\t"); | |
+#else | |
+ accel->key = 0; | |
+ accel->mods = 0; | |
+ accel->flags = GTK_ACCEL_VISIBLE; | |
+#endif | |
+ | |
+ if (strncmp(apt, "<control>", 9) == 0) { | |
+#ifdef CYGWIN | |
+ accel->fVirt |= FCONTROL; | |
+ g_string_append(menu_title, "Ctrl+"); | |
+#else | |
+ accel->mods |= GDK_CONTROL_MASK; | |
+#endif | |
+ apt += 9; | |
+ } | |
+ | |
+ if (strlen(apt) == 1) { | |
+ accel->key = *apt; | |
+#ifdef CYGWIN | |
+ g_string_append_c(menu_title, *apt); | |
+ accel->fVirt |= FVIRTKEY; | |
+#endif | |
+ } else if (strcmp(apt, "F1") == 0) { | |
+#ifdef CYGWIN | |
+ g_string_append(menu_title, apt); | |
+ accel->fVirt |= FVIRTKEY; | |
+ accel->key = VK_F1; | |
+#else | |
+ accel->key = GDK_KEY_F1; | |
+#endif | |
+ } | |
+ return (accel->key != 0); | |
+} | |
+ | |
+void dp_gtk_item_factory_create_item(DPGtkItemFactory *ifactory, | |
+ DPGtkItemFactoryEntry *entry, | |
+ gpointer callback_data, | |
+ guint callback_type) | |
+{ | |
+ DPGtkItemFactoryChild *new_child, *parent = NULL; | |
+ GString *menu_title; | |
+ GtkWidget *menu_item, *menu; | |
+ OurAccel accel; | |
+ gboolean haveaccel; | |
+ | |
+ new_child = g_new0(DPGtkItemFactoryChild, 1); | |
+ | |
+ new_child->path = g_strdup(entry->path); | |
+ | |
+ 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); | |
+ | |
+ if (entry->item_type && strcmp(entry->item_type, "<CheckItem>") == 0) { | |
+ menu_item = gtk_check_menu_item_new_with_mnemonic(menu_title->str); | |
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item), TRUE); | |
+ } else { | |
+ menu_item = gtk_menu_item_new_with_mnemonic(menu_title->str); | |
+ if (entry->item_type && strcmp(entry->item_type, "<LastBranch>") == 0) { | |
+ gtk_menu_item_set_right_justified(GTK_MENU_ITEM(menu_item), TRUE); | |
+ } | |
+ } | |
+ new_child->widget = menu_item; | |
+ if (entry->callback) { | |
+ gtk_signal_connect(GTK_OBJECT(menu_item), "activate", | |
+ entry->callback, callback_data); | |
+ } | |
+ | |
+ if (parent) { | |
+ menu = GTK_WIDGET(GTK_MENU_ITEM(parent->widget)->submenu); | |
+ if (!menu) { | |
+ menu = gtk_menu_new(); | |
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(parent->widget), menu); | |
+ } | |
+ gtk_menu_append(GTK_MENU(menu), menu_item); | |
+ } else { | |
+ gtk_menu_bar_append(GTK_MENU_BAR(ifactory->top_widget), menu_item); | |
+ } | |
+ | |
+ if (haveaccel && ifactory->accel_group) { | |
+#ifdef CYGWIN | |
+ GTK_MENU_ITEM(menu_item)->accelind = | |
+ gtk_accel_group_add(ifactory->accel_group, &accel); | |
+#else | |
+ gtk_widget_add_accelerator(menu_item, "activate", ifactory->accel_group, | |
+ accel.key, accel.mods, accel.flags); | |
+#endif | |
+ } | |
+ | |
+ g_string_free(menu_title, TRUE); | |
+ | |
+ ifactory->children = g_slist_append(ifactory->children, new_child); | |
+} | |
+ | |
+void dp_gtk_item_factory_create_items(DPGtkItemFactory *ifactory, | |
+ guint n_entries, | |
+ DPGtkItemFactoryEntry *entries, | |
+ gpointer callback_data) | |
+{ | |
+ gint i; | |
+ | |
+ for (i = 0; i < n_entries; i++) { | |
+ dp_gtk_item_factory_create_item(ifactory, &entries[i], callback_data, 0); | |
+ } | |
+} | |
+ | |
+GtkWidget *dp_gtk_item_factory_get_widget(DPGtkItemFactory *ifactory, | |
+ const gchar *path) | |
+{ | |
+ gint root_len; | |
+ GSList *list; | |
+ DPGtkItemFactoryChild *child; | |
+ | |
+ root_len = strlen(ifactory->path); | |
+ if (!path || strlen(path) < root_len) | |
+ return NULL; | |
+ | |
+ if (strncmp(ifactory->path, path, root_len) != 0) | |
+ return NULL; | |
+ if (strlen(path) == root_len) | |
+ return ifactory->top_widget; | |
+ | |
+ for (list = ifactory->children; list; list = g_slist_next(list)) { | |
+ child = (DPGtkItemFactoryChild *)list->data; | |
+ if (PathCmp(child->path, &path[root_len]) == 1) | |
+ return child->widget; | |
+ } | |
+ return NULL; | |
+} | |
+ | |
+void dp_gtk_item_factory_set_translate_func(DPGtkItemFactory *ifactory, | |
+ DPGtkTranslateFunc func, | |
+ gpointer data, | |
+ GtkDestroyNotify notify) | |
+{ | |
+ ifactory->translate_func = func; | |
+ ifactory->translate_data = data; | |
+} | |
+ | |
+#endif /* defined(CYGWIN) || GTK_MAJOR_VERSION > 2 */ | |
diff --git a/src/gtkport/itemfactory.h b/src/gtkport/itemfactory.h | |
t@@ -0,0 +1,93 @@ | |
+/************************************************************************ | |
+ * itemfactory.h GtkItemFactory and friends for Unix/Win32 * | |
+ * Copyright (C) 1998-2020 Ben Webb * | |
+ * Email: [email protected] * | |
+ * WWW: https://dopewars.sourceforge.io/ * | |
+ * * | |
+ * When using GTK+3, which has removed GtkItemFactory, or Win32, * | |
+ * provide our own implementation; on GTK+2, use the implementation in * | |
+ * GTK+ itself. * | |
+ * * | |
+ * This program is free software; you can redistribute it and/or * | |
+ * modify it under the terms of the GNU General Public License * | |
+ * as published by the Free Software Foundation; either version 2 * | |
+ * of the License, or (at your option) any later version. * | |
+ * * | |
+ * This program is distributed in the hope that it will be useful, * | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
+ * GNU General Public License for more details. * | |
+ * * | |
+ * You should have received a copy of the GNU General Public License * | |
+ * along with this program; if not, write to the Free Software * | |
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * | |
+ * MA 02111-1307, USA. * | |
+ ************************************************************************/ | |
+ | |
+#ifndef __ITEM_FACTORY_H__ | |
+#define __ITEM_FACTORY_H__ | |
+ | |
+#ifdef HAVE_CONFIG_H | |
+#include <config.h> | |
+#endif | |
+ | |
+#include <glib.h> | |
+#include <gtk/gtk.h> | |
+ | |
+/* Use GTK+2's own implementation of these functions */ | |
+#if GTK_MAJOR_VERSION == 2 | |
+#define DPGtkTranslateFunc GtkTranslateFunc | |
+#define DPGtkItemFactoryCallback GtkItemFactoryCallback | |
+#define DPGtkItemFactoryEntry GtkItemFactoryEntry | |
+#define DPGtkItemFactory GtkItemFactory | |
+#define dp_gtk_item_factory_new gtk_item_factory_new | |
+#define dp_gtk_item_factory_create_items gtk_item_factory_create_items | |
+#define dp_gtk_item_factory_create_item gtk_item_factory_create_item | |
+#define dp_gtk_item_factory_get_widget gtk_item_factory_get_widget | |
+#define dp_gtk_item_factory_set_translate_func gtk_item_factory_set_translate_… | |
+#else | |
+ | |
+typedef gchar *(*DPGtkTranslateFunc) (const gchar *path, gpointer func_data); | |
+ | |
+typedef void (*DPGtkItemFactoryCallback) (); | |
+ | |
+typedef struct _DPGtkItemFactoryEntry DPGtkItemFactoryEntry; | |
+typedef struct _DPGtkItemFactory DPGtkItemFactory; | |
+ | |
+struct _DPGtkItemFactoryEntry { | |
+ gchar *path; | |
+ gchar *accelerator; | |
+ DPGtkItemFactoryCallback callback; | |
+ guint callback_action; | |
+ gchar *item_type; | |
+}; | |
+ | |
+struct _DPGtkItemFactory { | |
+ GSList *children; | |
+ gchar *path; | |
+ GtkAccelGroup *accel_group; | |
+ GtkWidget *top_widget; | |
+ DPGtkTranslateFunc translate_func; | |
+ gpointer translate_data; | |
+}; | |
+ | |
+DPGtkItemFactory *dp_gtk_item_factory_new(GtkType container_type, | |
+ const gchar *path, | |
+ GtkAccelGroup *accel_group); | |
+void dp_gtk_item_factory_create_item(DPGtkItemFactory *ifactory, | |
+ DPGtkItemFactoryEntry *entry, | |
+ gpointer callback_data, | |
+ guint callback_type); | |
+void dp_gtk_item_factory_create_items(DPGtkItemFactory *ifactory, | |
+ guint n_entries, | |
+ DPGtkItemFactoryEntry *entries, | |
+ gpointer callback_data); | |
+GtkWidget *dp_gtk_item_factory_get_widget(DPGtkItemFactory *ifactory, | |
+ const gchar *path); | |
+void dp_gtk_item_factory_set_translate_func(DPGtkItemFactory *ifactory, | |
+ DPGtkTranslateFunc func, | |
+ gpointer data, | |
+ GtkDestroyNotify notify); | |
+#endif /* GTK+2 */ | |
+ | |
+#endif /* __ITEM_FACTORY_H__ */ | |
diff --git a/src/gui_client/gtk_client.c b/src/gui_client/gtk_client.c | |
t@@ -67,7 +67,7 @@ struct StatusWidgets { | |
struct ClientDataStruct { | |
GtkWidget *window, *messages; | |
Player *Play; | |
- GtkItemFactory *Menu; | |
+ DPGtkItemFactory *Menu; | |
struct StatusWidgets Status; | |
struct InventoryWidgets Drug, Gun, InvenDrug, InvenGun; | |
GtkWidget *JetButton, *vbox, *PlayerList, *TalkList; | |
t@@ -157,7 +157,7 @@ static void CreateInventory(GtkWidget *hbox, gchar *Object… | |
static void GetSpyReports(GtkWidget *widget, gpointer data); | |
static void DisplaySpyReports(Player *Play); | |
-static GtkItemFactoryEntry menu_items[] = { | |
+static DPGtkItemFactoryEntry menu_items[] = { | |
/* The names of the the menus and their items in the GTK+ client */ | |
{N_("/_Game"), NULL, NULL, 0, "<Branch>"}, | |
{N_("/Game/_New..."), "<control>N", NewGame, 0, NULL}, | |
t@@ -287,8 +287,8 @@ void ToggleSound(GtkWidget *widget, gpointer data) | |
{ | |
gboolean enable; | |
- widget = gtk_item_factory_get_widget(ClientData.Menu, | |
- "<main>/Game/Enable sound"); | |
+ widget = dp_gtk_item_factory_get_widget(ClientData.Menu, | |
+ "<main>/Game/Enable sound"); | |
if (widget) { | |
enable = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); | |
SoundEnable(enable); | |
t@@ -539,8 +539,8 @@ void HandleClientMessage(char *pt, Player *Play) | |
SoundPlay(Sounds.Jet); | |
break; | |
case C_ENDLIST: | |
- MenuItem = gtk_item_factory_get_widget(ClientData.Menu, | |
- "<main>/Errands/Sack Bitch..."); | |
+ MenuItem = dp_gtk_item_factory_get_widget(ClientData.Menu, | |
+ "<main>/Errands/Sack Bitch..."); | |
/* Text for the Errands/Sack Bitch menu item */ | |
text = dpg_strdup_printf(_("%/Sack Bitch menu item/S_ack %Tde..."), | |
t@@ -548,8 +548,8 @@ void HandleClientMessage(char *pt, Player *Play) | |
SetAccelerator(MenuItem, text, NULL, NULL, NULL, FALSE); | |
g_free(text); | |
- MenuItem = gtk_item_factory_get_widget(ClientData.Menu, | |
- "<main>/Errands/Spy..."); | |
+ MenuItem = dp_gtk_item_factory_get_widget(ClientData.Menu, | |
+ "<main>/Errands/Spy..."); | |
/* Text to update the Errands/Spy menu item with the price for spying */ | |
text = dpg_strdup_printf(_("_Spy (%P)"), Prices.Spy); | |
t@@ -559,8 +559,8 @@ void HandleClientMessage(char *pt, Player *Play) | |
/* Text to update the Errands/Tipoff menu item with the price for a | |
tipoff */ | |
text = dpg_strdup_printf(_("_Tipoff (%P)"), Prices.Tipoff); | |
- MenuItem = gtk_item_factory_get_widget(ClientData.Menu, | |
- "<main>/Errands/Tipoff..."); | |
+ MenuItem = dp_gtk_item_factory_get_widget(ClientData.Menu, | |
+ "<main>/Errands/Tipoff..."); | |
SetAccelerator(MenuItem, text, NULL, NULL, NULL, FALSE); | |
g_free(text); | |
if (FirstClient->next) | |
t@@ -2032,33 +2032,33 @@ void UpdateMenus(void) | |
MultiPlayer = (FirstClient && FirstClient->next != NULL); | |
Bitches = InGame && ClientData.Play ? ClientData.Play->Bitches.Carried : 0; | |
- gtk_widget_set_sensitive(gtk_item_factory_get_widget(ClientData.Menu, | |
- "<main>/Talk"), | |
+ gtk_widget_set_sensitive(dp_gtk_item_factory_get_widget(ClientData.Menu, | |
+ "<main>/Talk"), | |
InGame && Network); | |
- gtk_widget_set_sensitive(gtk_item_factory_get_widget | |
+ gtk_widget_set_sensitive(dp_gtk_item_factory_get_widget | |
(ClientData.Menu, "<main>/Game/Options..."), | |
!InGame); | |
- gtk_widget_set_sensitive(gtk_item_factory_get_widget | |
+ gtk_widget_set_sensitive(dp_gtk_item_factory_get_widget | |
(ClientData.Menu, "<main>/Game/Abandon..."), | |
InGame); | |
- gtk_widget_set_sensitive(gtk_item_factory_get_widget | |
+ gtk_widget_set_sensitive(dp_gtk_item_factory_get_widget | |
(ClientData.Menu, "<main>/List/Inventory..."), | |
InGame); | |
- gtk_widget_set_sensitive(gtk_item_factory_get_widget | |
+ gtk_widget_set_sensitive(dp_gtk_item_factory_get_widget | |
(ClientData.Menu, "<main>/List/Players..."), | |
InGame && Network); | |
- gtk_widget_set_sensitive(gtk_item_factory_get_widget | |
+ gtk_widget_set_sensitive(dp_gtk_item_factory_get_widget | |
(ClientData.Menu, "<main>/Errands"), InGame); | |
- gtk_widget_set_sensitive(gtk_item_factory_get_widget | |
+ gtk_widget_set_sensitive(dp_gtk_item_factory_get_widget | |
(ClientData.Menu, "<main>/Errands/Spy..."), | |
InGame && MultiPlayer); | |
- gtk_widget_set_sensitive(gtk_item_factory_get_widget | |
+ gtk_widget_set_sensitive(dp_gtk_item_factory_get_widget | |
(ClientData.Menu, "<main>/Errands/Tipoff..."), | |
InGame && MultiPlayer); | |
- gtk_widget_set_sensitive(gtk_item_factory_get_widget | |
+ gtk_widget_set_sensitive(dp_gtk_item_factory_get_widget | |
(ClientData.Menu, | |
"<main>/Errands/Sack Bitch..."), Bitches > 0); | |
- gtk_widget_set_sensitive(gtk_item_factory_get_widget | |
+ gtk_widget_set_sensitive(dp_gtk_item_factory_get_widget | |
(ClientData.Menu, | |
"<main>/Errands/Get spy reports..."), InGame | |
&& MultiPlayer); | |
t@@ -2191,7 +2191,7 @@ gboolean GtkLoop(int *argc, char **argv[], | |
GtkWidget *window, *vbox, *vbox2, *hbox, *frame, *table, *menubar, *text, | |
*vpaned, *button, *clist, *widget; | |
GtkAccelGroup *accel_group; | |
- GtkItemFactory *item_factory; | |
+ DPGtkItemFactory *item_factory; | |
gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]); | |
#ifdef CYGWIN | |
t@@ -2256,24 +2256,24 @@ gboolean GtkLoop(int *argc, char **argv[], | |
accel_group = gtk_accel_group_new(); | |
gtk_object_set_data(GTK_OBJECT(window), "accel_group", accel_group); | |
- item_factory = ClientData.Menu = gtk_item_factory_new(GTK_TYPE_MENU_BAR, | |
- "<main>", | |
- accel_group); | |
- gtk_item_factory_set_translate_func(item_factory, MenuTranslate, NULL, | |
- NULL); | |
- | |
- gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, | |
- NULL); | |
+ item_factory = ClientData.Menu = dp_gtk_item_factory_new(GTK_TYPE_MENU_BAR, | |
+ "<main>", | |
+ accel_group); | |
+ dp_gtk_item_factory_set_translate_func(item_factory, MenuTranslate, NULL, | |
+ NULL); | |
+ | |
+ dp_gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, | |
+ NULL); | |
gtk_window_add_accel_group(GTK_WINDOW(window), accel_group); | |
- menubar = gtk_item_factory_get_widget(item_factory, "<main>"); | |
+ menubar = dp_gtk_item_factory_get_widget(item_factory, "<main>"); | |
vbox2 = gtk_vbox_new(FALSE, 0); | |
gtk_box_pack_start(GTK_BOX(vbox2), menubar, FALSE, FALSE, 0); | |
gtk_widget_show_all(menubar); | |
UpdateMenus(); | |
SoundEnable(UseSounds); | |
- widget = gtk_item_factory_get_widget(ClientData.Menu, | |
- "<main>/Game/Enable sound"); | |
+ widget = dp_gtk_item_factory_get_widget(ClientData.Menu, | |
+ "<main>/Game/Enable sound"); | |
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), UseSounds); | |
vbox = ClientData.vbox = gtk_vbox_new(FALSE, 5); |