Internalize parts of the goffice code

We're using only a tiny fraction of that library.
Adding it directly in the gnucash source saves a large dependency chain.

Note this is a verbatim copy of these files from
https://github.com/GNOME/goffice/tree/GOFFICE_0_8_17
to preserve a clean link with it's origin.
It will only build correctly after the next commit.
This commit is contained in:
Geert Janssens
2016-01-28 09:12:43 +01:00
committed by Geert Janssens
parent 20eecb05da
commit d858c7d51d
10 changed files with 2540 additions and 1 deletions

View File

@@ -1697,6 +1697,7 @@ AC_CONFIG_FILES(
doc/Makefile
doc/examples/Makefile
lib/Makefile
lib/goffice/Makefile
lib/libc/Makefile
lib/stf/Makefile
packaging/Makefile

View File

@@ -1,5 +1,5 @@
if GNUCASH_ENABLE_GUI
SUBDIRS = libc stf
SUBDIRS = libc stf goffice
else
SUBDIRS = libc
endif

17
lib/goffice/Makefile.am Normal file
View File

@@ -0,0 +1,17 @@
noinst_LTLIBRARIES = libgnc-goffice.la
REALSRCS = go-optionmenu.c \
go-charmap-sel.c \
go-glib-extras.c
REALHDRS = go-optionmenu.h \
go-charmap-sel.h \
go-glib-extras.h
libgnc_goffice_la_SOURCES = ${REALSRCS}
noinst_HEADERS = ${REALHDRS}
libgnc_goffice_la_LIBADD = $(GTK_LIBS)
AM_CPPFLAGS = $(GTK_CFLAGS)
EXTRA_DIST = $(REALSRCS) $(REALHDRS)

13
lib/goffice/README Normal file
View File

@@ -0,0 +1,13 @@
This code is extracted from goffice.
In particular,
- go-charmap-sel is a widget to allow the user to select an encoding
- go-option-menu is a widget used by go-charmap-sel to add manu items
with a radio button.
- go-glib-extras is copied because we use a few functions from it:
- go_ascii_strcase_equal and go_ascii_strcase_hash
- go_guess_encoding
This code is currently used by the csv importer, but could be useful
in several interfaces that require the user to select an encoding
(various importers and exporters mostly).

View File

@@ -0,0 +1,691 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* A charmap selector widget.
*
* Copyright (C) 2003-2005 Andreas J. Guelzow
*
* based on code by:
* Copyright (C) 2000 Marco Pesenti Gritti
* from the galeon code base
*
* 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, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <goffice/goffice-config.h>
#include "go-charmap-sel.h"
#include "go-optionmenu.h"
#include <goffice/utils/go-glib-extras.h>
#include <glib/gi18n-lib.h>
#include <gsf/gsf-impl-utils.h>
#include <string.h>
#include <stdlib.h>
#define CS(x) GO_CHARMAP_SEL (x)
#define CHARMAP_NAME_KEY "Name of Character Encoding"
/* ------------------------------------------------------------------------- */
typedef enum {
LG_ARABIC,
LG_BALTIC,
LG_CENTRAL_EUROPEAN,
LG_CHINESE,
LG_CYRILLIC,
LG_GREEK,
LG_HEBREW,
LG_INDIAN,
LG_JAPANESE,
LG_KOREAN,
LG_TURKISH,
LG_UNICODE,
LG_VIETNAMESE,
LG_WESTERN,
LG_OTHER,
LG_LAST
} LanguageGroup;
typedef struct {
char const *group_name;
LanguageGroup const lgroup;
/* Generated stuff follows. */
char *collate_key;
} LGroupInfo;
static LGroupInfo lgroups[] = {
{N_("Arabic"), LG_ARABIC},
{N_("Baltic"), LG_BALTIC},
{N_("Central European"), LG_CENTRAL_EUROPEAN},
{N_("Chinese"), LG_CHINESE},
{N_("Cyrillic"), LG_CYRILLIC},
{N_("Greek"), LG_GREEK},
{N_("Hebrew"), LG_HEBREW},
{N_("Indian"), LG_INDIAN},
{N_("Japanese"), LG_JAPANESE},
{N_("Korean"), LG_KOREAN},
{N_("Turkish"), LG_TURKISH},
{N_("Unicode"), LG_UNICODE},
{N_("Vietnamese"), LG_VIETNAMESE},
{N_("Western"), LG_WESTERN},
{N_("Other"), LG_OTHER},
{NULL, LG_LAST}
};
static int
lgroups_order (const void *_a, const void *_b)
{
const LGroupInfo *a = (const LGroupInfo *)_a;
const LGroupInfo *b = (const LGroupInfo *)_b;
return strcmp (a->collate_key, b->collate_key);
}
/* ------------------------------------------------------------------------- */
typedef enum {
CI_MINOR,
CI_MAJOR
} CharsetImportance;
typedef struct {
gchar const *charset_title;
gchar const *aliases;
LanguageGroup const lgroup;
CharsetImportance const imp;
/* Generated stuff follows. */
char *collate_key;
char *to_utf8_iconv_name, *from_utf8_iconv_name;
} CharsetInfo;
static CharsetInfo charset_trans_array[] = {
{N_("Arabic (IBM-864)"), "IBM864", LG_ARABIC, CI_MINOR},
{N_("Arabic (IBM-864-I)"), "IBM864i", LG_ARABIC, CI_MINOR},
{N_("Arabic (ISO-8859-6)"), "ISO-8859-6", LG_ARABIC, CI_MINOR},
{N_("Arabic (ISO-8859-6-E)"), "ISO-8859-6-E", LG_ARABIC, CI_MINOR},
{N_("Arabic (ISO-8859-6-I)"), "ISO-8859-6-I", LG_ARABIC, CI_MINOR},
{N_("Arabic (MacArabic)"), "x-mac-arabic", LG_ARABIC, CI_MINOR},
{N_("Arabic (Windows-1256)"), "windows-1256", LG_ARABIC, CI_MINOR},
{N_("Armenian (ARMSCII-8)"), "armscii-8", LG_OTHER, CI_MINOR},
{N_("Baltic (ISO-8859-13)"), "ISO-8859-13", LG_BALTIC, CI_MINOR},
{N_("Baltic (ISO-8859-4)"), "ISO-8859-4", LG_BALTIC, CI_MINOR},
{N_("Baltic (Windows-1257)"), "windows-1257", LG_BALTIC, CI_MINOR},
{N_("Celtic (ISO-8859-14)"), "ISO-8859-14", LG_OTHER, CI_MINOR},
{N_("Central European (IBM-852)"), "IBM852", LG_CENTRAL_EUROPEAN, CI_MINOR},
{N_("Central European (ISO-8859-2)"), "ISO-8859-2", LG_CENTRAL_EUROPEAN, CI_MINOR},
{N_("Central European (MacCE)"), "x-mac-ce", LG_CENTRAL_EUROPEAN, CI_MINOR},
{N_("Central European (Windows-1250)"), "windows-1250", LG_CENTRAL_EUROPEAN, CI_MINOR},
{N_("Chinese Simplified (GB18030)"), "gb18030", LG_CHINESE, CI_MINOR},
{N_("Chinese Simplified (GB2312)"), "GB2312", LG_CHINESE, CI_MINOR},
{N_("Chinese Simplified (GBK)"), "x-gbk", LG_CHINESE, CI_MINOR},
{N_("Chinese Simplified (HZ)"), "HZ-GB-2312", LG_CHINESE, CI_MINOR},
{N_("Chinese Simplified (Windows-936)"), "windows-936", LG_CHINESE, CI_MINOR},
{N_("Chinese Traditional (Big5)"), "Big5", LG_CHINESE, CI_MINOR},
{N_("Chinese Traditional (Big5-HKSCS)"), "Big5-HKSCS", LG_CHINESE, CI_MINOR},
{N_("Chinese Traditional (EUC-TW)"), "x-euc-tw", LG_CHINESE, CI_MINOR},
{N_("Croatian (MacCroatian)"), "x-mac-croatian", LG_CENTRAL_EUROPEAN, CI_MINOR},
{N_("Cyrillic (IBM-855)"), "IBM855", LG_CYRILLIC, CI_MINOR},
{N_("Cyrillic (ISO-8859-5)"), "ISO-8859-5", LG_CYRILLIC, CI_MINOR},
{N_("Cyrillic (ISO-IR-111)"), "ISO-IR-111", LG_CYRILLIC, CI_MINOR},
{N_("Cyrillic (KOI8-R)"), "KOI8-R", LG_CYRILLIC, CI_MINOR},
{N_("Cyrillic (MacCyrillic)"), "x-mac-cyrillic", LG_CYRILLIC, CI_MINOR},
{N_("Cyrillic (Windows-1251)"), "windows-1251", LG_CYRILLIC, CI_MINOR},
{N_("Russian (CP-866)"), "IBM866", LG_CYRILLIC, CI_MINOR},
{N_("Ukrainian (KOI8-U)"), "KOI8-U", LG_CYRILLIC, CI_MINOR},
{N_("Ukrainian (MacUkrainian)"), "x-mac-ukrainian", LG_CYRILLIC, CI_MINOR},
{N_("English (ASCII)"), "ANSI_X3.4-1968#ASCII", LG_WESTERN, CI_MAJOR},
{N_("Farsi (MacFarsi)"), "x-mac-farsi", LG_OTHER, CI_MINOR},
{N_("Georgian (GEOSTD8)"), "geostd8", LG_OTHER, CI_MINOR},
{N_("Greek (ISO-8859-7)"), "ISO-8859-7", LG_GREEK, CI_MINOR},
{N_("Greek (MacGreek)"), "x-mac-greek", LG_GREEK, CI_MINOR},
{N_("Greek (Windows-1253)"), "windows-1253", LG_GREEK, CI_MINOR},
{N_("Gujarati (MacGujarati)"), "x-mac-gujarati", LG_INDIAN, CI_MINOR},
{N_("Gurmukhi (MacGurmukhi)"), "x-mac-gurmukhi", LG_INDIAN, CI_MINOR},
{N_("Hebrew (IBM-862)"), "IBM862", LG_HEBREW, CI_MINOR},
{N_("Hebrew (ISO-8859-8-E)"), "ISO-8859-8-E", LG_HEBREW, CI_MINOR},
{N_("Hebrew (ISO-8859-8-I)"), "ISO-8859-8-I", LG_HEBREW, CI_MINOR},
{N_("Hebrew (MacHebrew)"), "x-mac-hebrew", LG_HEBREW, CI_MINOR},
{N_("Hebrew (Windows-1255)"), "windows-1255", LG_HEBREW, CI_MINOR},
{N_("Hindi (MacDevanagari)"), "x-mac-devanagari", LG_INDIAN, CI_MINOR},
{N_("Icelandic (MacIcelandic)"), "x-mac-icelandic", LG_OTHER, CI_MINOR},
{N_("Japanese (EUC-JP)"), "EUC-JP", LG_JAPANESE, CI_MINOR},
{N_("Japanese (ISO-2022-JP)"), "ISO-2022-JP", LG_JAPANESE, CI_MINOR},
{N_("Japanese (Shift_JIS)"), "CP932", LG_JAPANESE, CI_MINOR},
{N_("Korean (EUC-KR)"), "EUC-KR", LG_KOREAN, CI_MINOR},
{N_("Korean (ISO-2022-KR)"), "ISO-2022-KR", LG_KOREAN, CI_MINOR},
{N_("Korean (JOHAB)"), "x-johab", LG_KOREAN, CI_MINOR},
{N_("Korean (UHC)"), "x-windows-949", LG_KOREAN, CI_MINOR},
{N_("Nordic (ISO-8859-10)"), "ISO-8859-10", LG_OTHER, CI_MINOR},
{N_("Romanian (MacRomanian)"), "x-mac-romanian", LG_OTHER, CI_MINOR},
{N_("Romanian (ISO-8859-16)"), "ISO-8859-16", LG_OTHER, CI_MINOR},
{N_("South European (ISO-8859-3)"), "ISO-8859-3", LG_OTHER, CI_MINOR},
{N_("Thai (TIS-620)"), "TIS-620", LG_OTHER, CI_MINOR},
{N_("Turkish (IBM-857)"), "IBM857", LG_TURKISH, CI_MINOR},
{N_("Turkish (ISO-8859-9)"), "ISO-8859-9", LG_TURKISH, CI_MINOR},
{N_("Turkish (MacTurkish)"), "x-mac-turkish", LG_TURKISH, CI_MINOR},
{N_("Turkish (Windows-1254)"), "windows-1254", LG_TURKISH, CI_MINOR},
{N_("Unicode (UTF-7)"), "UTF-7", LG_UNICODE, CI_MINOR},
{N_("Unicode (UTF-8)"), "UTF-8", LG_UNICODE, CI_MAJOR},
{N_("Unicode (UTF-16BE)"), "UTF-16BE", LG_UNICODE, CI_MINOR},
{N_("Unicode (UTF-16LE)"), "UTF-16LE", LG_UNICODE, CI_MINOR},
{N_("Unicode (UTF-32BE)"), "UTF-32BE", LG_UNICODE, CI_MINOR},
{N_("Unicode (UTF-32LE)"), "UTF-32LE", LG_UNICODE, CI_MINOR},
{N_("User Defined"), "x-user-defined", LG_OTHER, CI_MINOR},
{N_("Vietnamese (TCVN)"), "x-viet-tcvn5712", LG_VIETNAMESE, CI_MINOR},
{N_("Vietnamese (VISCII)"), "VISCII", LG_VIETNAMESE, CI_MINOR},
{N_("Vietnamese (VPS)"), "x-viet-vps", LG_VIETNAMESE, CI_MINOR},
{N_("Vietnamese (Windows-1258)"), "windows-1258", LG_VIETNAMESE, CI_MINOR},
{N_("Visual Hebrew (ISO-8859-8)"), "ISO-8859-8", LG_HEBREW, CI_MINOR},
{N_("Western (IBM-850)"), "IBM850", LG_WESTERN, CI_MINOR},
{N_("Western (ISO-8859-1)"), "ISO-8859-1", LG_WESTERN, CI_MAJOR},
{N_("Western (ISO-8859-15)"), "ISO-8859-15", LG_WESTERN, CI_MINOR},
{N_("Western (MacRoman)"), "x-mac-roman", LG_WESTERN, CI_MINOR},
{N_("Western (Windows-1252)"), "windows-1252", LG_WESTERN, CI_MINOR},
/* charsets without possibly translatable names */
{"T61.8bit", "T61.8bit", LG_OTHER, CI_MINOR},
{"x-imap4-modified-utf7", "x-imap4-modified-utf7", LG_UNICODE, CI_MINOR},
{"x-u-escaped", "x-u-escaped", LG_OTHER, CI_MINOR},
{NULL, NULL, LG_LAST, 0}
};
static int
charset_order (const void *_a, const void *_b)
{
const CharsetInfo *a = (const CharsetInfo *)_a;
const CharsetInfo *b = (const CharsetInfo *)_b;
if (a->lgroup != b->lgroup)
return (int)b->lgroup - (int)a->lgroup;
if (a->imp != b->imp)
return (int)b->imp - (int)a->imp;
return strcmp (a->collate_key, b->collate_key);
}
/* ------------------------------------------------------------------------- */
/* name -> CharsetInfo* mapping */
static GHashTable *encoding_hash;
struct _GOCharmapSel {
GtkHBox box;
GOOptionMenu *encodings;
GtkMenu *encodings_menu;
GOCharmapSelTestDirection test;
};
typedef struct {
GtkHBoxClass parent_class;
gboolean (* charmap_changed) (GOCharmapSel *cs, char const *new_charmap);
} GOCharmapSelClass;
typedef GOCharmapSel Cs;
typedef GOCharmapSelClass CsClass;
/* Signals we emit */
enum {
CHARMAP_CHANGED,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_TEST_DIRECTION
};
static guint cs_signals[LAST_SIGNAL] = { 0 };
static void cs_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void cs_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static gboolean
iconv_supported (const char *to, const char *from)
{
GIConv ic = g_iconv_open (to, from);
if (ic == NULL || ic == (GIConv)-1)
return FALSE;
g_iconv_close (ic);
return TRUE;
}
const char *
go_charmap_sel_get_encoding_name (G_GNUC_UNUSED GOCharmapSel *cs,
const char *encoding)
{
CharsetInfo const *ci;
g_return_val_if_fail (encoding != NULL, NULL);
ci = g_hash_table_lookup (encoding_hash, encoding);
return ci ? _(ci->charset_title) : NULL;
}
static char const *
get_locale_encoding_name (GOCharmapSel *cs)
{
char const *locale_encoding;
char const *name;
g_get_charset (&locale_encoding);
name = go_charmap_sel_get_encoding_name (cs, locale_encoding);
return name ? name : locale_encoding;
}
static void
encodings_changed_cb (GOOptionMenu *optionmenu, GOCharmapSel *cs)
{
g_return_if_fail (GO_IS_CHARMAP_SEL (cs));
g_return_if_fail (optionmenu == cs->encodings);
g_signal_emit (G_OBJECT (cs),
cs_signals[CHARMAP_CHANGED],
0,
go_charmap_sel_get_encoding (cs));
}
static void
set_menu_to_default (GOCharmapSel *cs, gint item)
{
GSList sel = { GINT_TO_POINTER (item - 1), NULL};
g_return_if_fail (cs != NULL && GO_IS_CHARMAP_SEL (cs));
go_option_menu_set_history (cs->encodings, &sel);
}
static gboolean
cs_mnemonic_activate (GtkWidget *w, gboolean group_cycling)
{
GOCharmapSel *cs = GO_CHARMAP_SEL (w);
gtk_widget_grab_focus (GTK_WIDGET (cs->encodings));
return TRUE;
}
static void
cs_emphasize_label (GtkLabel *label)
{
char *text = g_markup_printf_escaped ("<b>%s</b>",
gtk_label_get_label (label));
gtk_label_set_use_markup (label, TRUE);
gtk_label_set_label (label, text);
g_free (text);
}
static void
cs_init (GOCharmapSel *cs)
{
cs->test = GO_CHARMAP_SEL_TO_UTF8;
cs->encodings = GO_OPTION_MENU (go_option_menu_new ());
g_signal_connect (G_OBJECT (cs->encodings), "changed",
G_CALLBACK (encodings_changed_cb), cs);
gtk_box_pack_start (GTK_BOX (cs), GTK_WIDGET (cs->encodings),
TRUE, TRUE, 0);
}
static void
cs_build_menu (GOCharmapSel *cs)
{
GtkWidget *item;
GtkMenu *menu;
LGroupInfo const *lgroup = lgroups;
gint lg_cnt = 0;
menu = GTK_MENU (gtk_menu_new ());
while (lgroup->group_name) {
CharsetInfo const *charset_trans;
GtkMenu *submenu = NULL;
charset_trans = charset_trans_array;
while (charset_trans->lgroup != LG_LAST) {
GtkWidget *subitem;
if (charset_trans->lgroup == lgroup->lgroup) {
const char *name = (cs->test == GO_CHARMAP_SEL_TO_UTF8)
? charset_trans->to_utf8_iconv_name
: charset_trans->from_utf8_iconv_name;
if (name) {
if (!submenu)
submenu = GTK_MENU (gtk_menu_new ());
subitem = gtk_check_menu_item_new_with_label
(_(charset_trans->charset_title));
gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (subitem), TRUE);
gtk_widget_show (subitem);
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), subitem);
if (charset_trans->imp == CI_MAJOR)
cs_emphasize_label (GTK_LABEL (gtk_bin_get_child (GTK_BIN (subitem))));
g_object_set_data (G_OBJECT (subitem), CHARMAP_NAME_KEY,
(gpointer)name);
} else if (0) {
g_print ("Unsupported: %s\n", charset_trans->aliases);
}
}
charset_trans++;
}
if (submenu) {
GtkWidget *item =
gtk_menu_item_new_with_label (_(lgroup->group_name));
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), GTK_WIDGET (submenu));
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
lg_cnt++;
}
lgroup++;
}
item = gtk_separator_menu_item_new ();
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
lg_cnt++;
{
char *locale_encoding_menu_title = g_strconcat (_("Locale: "),
get_locale_encoding_name (cs),
NULL);
item = gtk_check_menu_item_new_with_label (locale_encoding_menu_title);
gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item), TRUE);
g_free (locale_encoding_menu_title);
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
lg_cnt++;
cs_emphasize_label (GTK_LABEL (gtk_bin_get_child (GTK_BIN (item))));
}
go_option_menu_set_menu (cs->encodings, GTK_WIDGET (menu));
cs->encodings_menu = menu;
set_menu_to_default (cs, lg_cnt);
}
static void
cs_class_init (GtkWidgetClass *widget_klass)
{
CharsetInfo *ci;
size_t i;
GObjectClass *gobject_class = G_OBJECT_CLASS (widget_klass);
widget_klass->mnemonic_activate = cs_mnemonic_activate;
gobject_class->set_property = cs_set_property;
gobject_class->get_property = cs_get_property;
cs_signals[CHARMAP_CHANGED] =
g_signal_new ("charmap_changed",
GO_TYPE_CHARMAP_SEL,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GOCharmapSelClass, charmap_changed),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);
g_object_class_install_property (gobject_class,
PROP_TEST_DIRECTION,
g_param_spec_uint ("TestDirection",
_("Conversion Direction"),
_("This value determines which iconv test to perform."),
(guint)GO_CHARMAP_SEL_TO_UTF8,
(guint)GO_CHARMAP_SEL_FROM_UTF8,
(guint)GO_CHARMAP_SEL_TO_UTF8,
G_PARAM_READWRITE));
/* ---------------------------------------- */
/* Sort the groups by translated name. */
for (i = 0; i < G_N_ELEMENTS (lgroups) - 2; i++) {
const char *cgroup_name = lgroups[i].group_name;
const char *group_name = _(cgroup_name);
lgroups[i].collate_key = g_utf8_collate_key (group_name, -1);
if (!lgroups[i].collate_key) {
g_warning ("Failed to generate collation key for [%s] [%s]",
cgroup_name, group_name);
lgroups[i].collate_key = g_strdup (group_name);
}
}
qsort (lgroups, G_N_ELEMENTS (lgroups) - 2, sizeof (lgroups[0]),
lgroups_order);
for (i = 0; i < G_N_ELEMENTS (lgroups) - 2; i++) {
g_free (lgroups[i].collate_key);
lgroups[i].collate_key = NULL;
}
/* ---------------------------------------- */
/* Sort charsets by group/importance/title. */
for (i = 0; i < G_N_ELEMENTS (charset_trans_array) - 1; i++) {
const char *ctitle = charset_trans_array[i].charset_title;
const char *title = _(ctitle);
charset_trans_array[i].collate_key = g_utf8_collate_key (title, -1);
if (!charset_trans_array[i].collate_key) {
g_warning ("Failed to generate collation key for [%s] [%s]",
ctitle, title);
charset_trans_array[i].collate_key = g_strdup (title);
}
}
qsort (charset_trans_array, G_N_ELEMENTS (charset_trans_array) - 1,
sizeof (charset_trans_array[0]), charset_order);
for (i = 0; i < G_N_ELEMENTS (charset_trans_array) - 1; i++) {
g_free (charset_trans_array[i].collate_key);
charset_trans_array[i].collate_key = NULL;
}
/* ---------------------------------------- */
encoding_hash =
g_hash_table_new_full (go_ascii_strcase_hash,
go_ascii_strcase_equal,
(GDestroyNotify)g_free,
NULL);
for (ci = charset_trans_array; ci->charset_title; ci++) {
const char *aliases = ci->aliases;
char *autoaliases = NULL;
if (strchr (aliases, '#') == NULL) {
/* Sigh. This sucks quite a lot. */
if (strncmp (aliases, "ISO-", 4) == 0) {
autoaliases =
g_strconcat (aliases,
"#ISO", aliases + 4,
"#ISO_", aliases + 4,
NULL);
}
if (autoaliases)
aliases = autoaliases;
}
ci->to_utf8_iconv_name = ci->from_utf8_iconv_name = NULL;
while (aliases) {
const char *sep = strchr (aliases, '#');
char *alias;
if (sep) {
alias = g_strndup (aliases, sep - aliases);
aliases = sep + 1;
} else {
alias = g_strdup (aliases);
aliases = NULL;
}
if (ci->to_utf8_iconv_name == NULL &&
iconv_supported ("UTF-8", alias)) {
ci->to_utf8_iconv_name = g_strdup (alias);
}
if (ci->from_utf8_iconv_name == NULL &&
iconv_supported (alias, "UTF-8")) {
ci->from_utf8_iconv_name = g_strdup (alias);
}
g_hash_table_insert (encoding_hash, alias, ci);
}
g_free (autoaliases);
}
}
GSF_CLASS (GOCharmapSel, go_charmap_sel,
cs_class_init, cs_init, GTK_TYPE_HBOX)
GtkWidget *
go_charmap_sel_new (GOCharmapSelTestDirection test)
{
return g_object_new (GO_TYPE_CHARMAP_SEL, "TestDirection", test, NULL);
}
gchar const *
go_charmap_sel_get_encoding (GOCharmapSel *cs)
{
GtkMenuItem *selection;
char const *locale_encoding;
char const *encoding;
g_get_charset (&locale_encoding);
g_return_val_if_fail (GO_IS_CHARMAP_SEL (cs), locale_encoding);
selection = GTK_MENU_ITEM (go_option_menu_get_history (cs->encodings));
encoding = (char const *) g_object_get_data (G_OBJECT (selection),
CHARMAP_NAME_KEY);
return encoding ? encoding : locale_encoding;
}
struct cb_find_entry {
const char *enc;
gboolean found;
int i;
GSList *path;
};
static void
cb_find_entry (GtkMenuItem *w, struct cb_find_entry *cl)
{
GtkWidget *sub;
if (cl->found)
return;
sub = gtk_menu_item_get_submenu (w);
if (sub) {
GSList *tmp = cl->path = g_slist_prepend (cl->path, GINT_TO_POINTER (cl->i));
cl->i = 0;
gtk_container_foreach (GTK_CONTAINER (sub), (GtkCallback)cb_find_entry, cl);
if (cl->found)
return;
cl->i = GPOINTER_TO_INT (cl->path->data);
cl->path = cl->path->next;
g_slist_free_1 (tmp);
} else {
const char *this_enc =
g_object_get_data (G_OBJECT (w), CHARMAP_NAME_KEY);
if (this_enc && strcmp (this_enc, cl->enc) == 0) {
cl->found = TRUE;
cl->path = g_slist_prepend (cl->path, GINT_TO_POINTER (cl->i));
cl->path = g_slist_reverse (cl->path);
return;
}
}
cl->i++;
}
gboolean
go_charmap_sel_set_encoding (GOCharmapSel *cs, const char *enc)
{
struct cb_find_entry cl;
CharsetInfo const *ci;
g_return_val_if_fail (GO_IS_CHARMAP_SEL (cs), FALSE);
g_return_val_if_fail (enc != NULL, FALSE);
ci = g_hash_table_lookup (encoding_hash, enc);
if (!ci)
return FALSE;
enc = ci->to_utf8_iconv_name;
if (!enc)
return FALSE;
cl.enc = enc;
cl.found = FALSE;
cl.i = 0;
cl.path = NULL;
gtk_container_foreach (GTK_CONTAINER (cs->encodings_menu),
(GtkCallback)cb_find_entry,
&cl);
if (!cl.found)
return FALSE;
go_option_menu_set_history (cs->encodings, cl.path);
g_slist_free (cl.path);
return TRUE;
}
static void
cs_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GOCharmapSel *cs = GO_CHARMAP_SEL (object);
switch (prop_id) {
case PROP_TEST_DIRECTION:
cs->test = g_value_get_uint (value);
cs_build_menu (cs);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
cs_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GOCharmapSel *cs = GO_CHARMAP_SEL (object);
switch (prop_id) {
case PROP_TEST_DIRECTION:
g_value_set_uint (value, (guint)cs->test);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}

View File

@@ -0,0 +1,53 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2003 Andreas J. Guelzow
*
* based on code by:
* Copyright (C) 2000 Marco Pesenti Gritti
* from the galeon code base
*
* 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, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _GO_CHARMAP_SEL_H_
#define _GO_CHARMAP_SEL_H_
#include <glib-object.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define GO_TYPE_CHARMAP_SEL (go_charmap_sel_get_type ())
#define GO_CHARMAP_SEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GO_TYPE_CHARMAP_SEL, GOCharmapSel))
#define GO_IS_CHARMAP_SEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GO_TYPE_CHARMAP_SEL))
typedef struct _GOCharmapSel GOCharmapSel;
typedef enum {
GO_CHARMAP_SEL_TO_UTF8 = 0,
GO_CHARMAP_SEL_FROM_UTF8
} GOCharmapSelTestDirection;
GType go_charmap_sel_get_type (void);
GtkWidget * go_charmap_sel_new (GOCharmapSelTestDirection test);
gchar const *go_charmap_sel_get_encoding (GOCharmapSel *cs);
gboolean go_charmap_sel_set_encoding (GOCharmapSel *cs, const char *enc);
const char *go_charmap_sel_get_encoding_name (GOCharmapSel *cs, const char *enc);
G_END_DECLS
#endif /* _GO_CHARMAP_SEL_H_ */

1082
lib/goffice/go-glib-extras.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,119 @@
#ifndef GO_GLIB_EXTRAS_H
#define GO_GLIB_EXTRAS_H
#include <goffice/goffice.h>
G_BEGIN_DECLS
/* Misc convenience routines that would be nice to have in glib */
typedef gpointer (*GOMapFunc) (gpointer value);
void go_ptr_array_insert (GPtrArray *array, gpointer value, int index);
GSList *go_hash_keys (GHashTable *hash);
GSList *go_hash_values (GHashTable *hash);
GSList *go_slist_map (GSList const *list, GOMapFunc map_func);
GSList *go_slist_create (gpointer item1, ...);
void go_slist_free_custom (GSList *list, GFreeFunc free_func);
#define go_string_slist_copy(list) go_slist_map (list, (GOMapFunc) g_strdup)
GSList *go_strsplit_to_slist (char const *str, gchar delimiter);
#define GO_SLIST_FOREACH(list,valtype,val,stmnt) \
G_STMT_START { \
GSList const *go_l; \
for (go_l = (list); go_l != NULL; go_l = go_l->next) { \
valtype *val = go_l->data; \
stmnt \
; \
} \
} G_STMT_END
#define GO_SLIST_PREPEND(list,item) \
(list = g_slist_prepend (list, item))
#define GO_SLIST_APPEND(list,item) \
(list = g_slist_append (list, item))
#define GO_SLIST_REMOVE(list,item) \
(list = g_slist_remove (list, item))
#define GO_SLIST_CONCAT(list_a,list_b) \
(list_a = g_slist_concat (list_a, list_b))
#define GO_SLIST_REVERSE(list) \
(list = g_slist_reverse (list))
#define GO_SLIST_SORT(list,cmp_func) \
(list = g_slist_sort (list, cmp_func))
gint go_list_index_custom (GList *list, gpointer data, GCompareFunc cmp_func);
void go_list_free_custom (GList *list, GFreeFunc free_func);
#define GO_LIST_FOREACH(list,valtype,val,stmnt) \
G_STMT_START { \
GList *go_l; \
for (go_l = (list); go_l != NULL; go_l = go_l->next) { \
valtype *val = go_l->data; \
stmnt \
; \
} \
} G_STMT_END
#define GO_LIST_PREPEND(list,item) \
(list = g_list_prepend (list, item))
#define GO_LIST_APPEND(list,item) \
(list = g_list_append (list, item))
#define GO_LIST_REMOVE(list,item) \
(list = g_list_remove (list, item))
#define GO_LIST_CONCAT(list_a,list_b) \
(list_a = g_list_concat (list_a, list_b))
#define GO_LIST_REVERSE(list) \
(list = g_list_reverse (list))
#define GO_LIST_SORT(list,cmp_func) \
(list = g_list_sort (list, cmp_func))
int go_str_compare (void const *x, void const *y);
guint go_ascii_strcase_hash (gconstpointer v);
gint go_ascii_strcase_equal (gconstpointer v, gconstpointer v2);
gint go_utf8_collate_casefold (char const *a, char const *b);
char *go_utf8_strcapital (char const *p, gssize len);
void go_strescape (GString *target, char const *str);
char const *go_strunescape (GString *target, char const *str);
void go_string_append_gstring (GString *target, const GString *src);
void go_string_append_c_n (GString *target, char c, gsize n);
void go_string_replace (GString *target,
gsize pos, gssize oldlen,
const char *txt, gssize newlen);
char const *go_guess_encoding (char const *raw, gsize len,
char const *user_guess,
char **utf8_str);
char const *go_get_real_name (void);
void go_destroy_password (char *passwd);
GOMemChunk *go_mem_chunk_new (char const *name, gsize user_atom_size, gsize chunk_size);
void go_mem_chunk_destroy (GOMemChunk *chunk, gboolean expect_leaks);
gpointer go_mem_chunk_alloc (GOMemChunk *chunk);
gpointer go_mem_chunk_alloc0 (GOMemChunk *chunk);
void go_mem_chunk_free (GOMemChunk *chunk, gpointer mem);
void go_mem_chunk_foreach_leak (GOMemChunk *chunk, GFunc cb, gpointer user);
void go_object_toggle (gpointer object,
const gchar *property_name);
gboolean go_object_set_property (GObject *obj, const char *property_name,
const char *user_prop_name, const char *value,
GError **err,
const char *error_template);
GSList *go_object_properties_collect (GObject *obj);
void go_object_properties_apply (GObject *obj,
GSList *props,
gboolean changed_only);
void go_object_properties_free (GSList *props);
typedef gboolean (*GOParseKeyValueFunc) (const char *name,
const char *value,
GError **err,
gpointer user);
gboolean go_parse_key_value (const char *options,
GError **err,
GOParseKeyValueFunc handler,
gpointer user);
G_END_DECLS
#endif /* GO_GLIB_EXTRAS_H */

478
lib/goffice/go-optionmenu.c Normal file
View File

@@ -0,0 +1,478 @@
/*
* go-optionmenu.c
*
* Copyright (C) 2002 Andreas J. Guelzow <aguelzow@taliesin.ca>
* Copyright (C) 2006 Morten Welinder (terra@gnome.org)
*
* based extensively on:
*
* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* Modified by the GTK+ Team and others 1997-2000. See the GTK AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA.
*/
#include <goffice/goffice-config.h>
#include "go-optionmenu.h"
#include <goffice/gtk/go-gtk-compat.h>
#include <gdk/gdkkeysyms.h>
#include <glib/gi18n-lib.h>
enum {
CHANGED,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_MENU
};
static GtkButtonClass *parent_class = NULL;
static guint signals[LAST_SIGNAL] = { 0 };
GtkWidget*
go_option_menu_new (void)
{
return g_object_new (GO_TYPE_OPTION_MENU, NULL);
}
static void
go_option_menu_detacher (GtkWidget *widget, GtkMenu *menu)
{
#if 0
GOOptionMenu *option_menu = GO_OPTION_MENU (widget);
/* What? */
#endif
}
static void
go_option_menu_update_contents (GOOptionMenu *option_menu)
{
const char *text;
GtkWidget *w;
g_return_if_fail (GO_IS_OPTION_MENU (option_menu));
w = gtk_bin_get_child (GTK_BIN (option_menu->selected));
text = g_object_get_data (G_OBJECT (w), "option-menu-text");
if (!text && GTK_IS_LABEL (w))
text = gtk_label_get_text (GTK_LABEL (w));
if (!text)
text = "";
#if 0
g_print ("text = \"%s\"\n", text);
#endif
gtk_label_set_text (option_menu->button_label, text);
}
static void
go_option_menu_select_item (GOOptionMenu *option_menu, GtkMenuItem *item)
{
if (item == option_menu->selected)
return;
if (GTK_IS_CHECK_MENU_ITEM (option_menu->selected))
gtk_check_menu_item_set_active
(GTK_CHECK_MENU_ITEM (option_menu->selected),
FALSE);
option_menu->selected = item;
if (GTK_IS_CHECK_MENU_ITEM (item))
gtk_check_menu_item_set_active
(GTK_CHECK_MENU_ITEM (option_menu->selected),
TRUE);
go_option_menu_update_contents (option_menu);
}
static void
go_option_menu_position (GtkMenu *menu,
gint *x,
gint *y,
gboolean *push_in,
gpointer user_data)
{
GOOptionMenu *option_menu = user_data;
GtkWidget *widget;
GtkRequisition requisition;
GList *children;
gint screen_width;
gint menu_xpos;
gint menu_ypos;
gint menu_width;
GtkAllocation allocation;
widget = GTK_WIDGET (option_menu);
gtk_widget_get_child_requisition (GTK_WIDGET (menu), &requisition);
menu_width = requisition.width;
gdk_window_get_origin (gtk_widget_get_window (widget), &menu_xpos, &menu_ypos);
gtk_widget_get_allocation (widget, &allocation);
menu_xpos += allocation.x;
menu_ypos += allocation.y + allocation.height / 2 - 2;
children = gtk_container_get_children (GTK_CONTAINER (option_menu->menu));
while (children) {
GtkWidget *child = children->data;
if (GTK_IS_CHECK_MENU_ITEM (child) &&
gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (child))) {
gtk_widget_get_child_requisition (child, &requisition);
menu_ypos -= requisition.height / 2;
break;
}
if (gtk_widget_get_visible (child)) {
gtk_widget_get_child_requisition (child, &requisition);
menu_ypos -= requisition.height;
}
children = children->next;
}
screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
if (menu_xpos + menu_width > screen_width)
menu_xpos -= (menu_xpos + menu_width) - screen_width;
if (menu_xpos < 0)
menu_xpos = 0;
*x = menu_xpos;
*y = menu_ypos;
*push_in = TRUE;
}
static gint
go_option_menu_button_press (GtkWidget *widget,
GdkEventButton *event)
{
GOOptionMenu *option_menu;
g_return_val_if_fail (GO_IS_OPTION_MENU (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
option_menu = GO_OPTION_MENU (widget);
if (event->type == GDK_BUTTON_PRESS && event->button == 1) {
gtk_menu_popup (GTK_MENU (option_menu->menu), NULL, NULL,
go_option_menu_position, option_menu,
event->button, event->time);
return TRUE;
}
return FALSE;
}
static gint
go_option_menu_key_press (GtkWidget *widget,
GdkEventKey *event)
{
GOOptionMenu *option_menu = GO_OPTION_MENU (widget);
switch (event->keyval) {
case GDK_KP_Space:
case GDK_space:
gtk_menu_popup (GTK_MENU (option_menu->menu), NULL, NULL,
go_option_menu_position, option_menu,
0, event->time);
return TRUE;
}
return FALSE;
}
static void
cb_select (GtkMenuItem *item, GOOptionMenu *option_menu)
{
go_option_menu_select_item (option_menu, item);
g_signal_emit (option_menu, signals[CHANGED], 0);
}
static void
handle_menu_signals (GOOptionMenu *option_menu, gboolean connect)
{
GList *children = gtk_container_get_children
(GTK_CONTAINER (option_menu->menu));
while (children) {
GtkWidget *child = children->data;
children = g_list_remove (children, child);
if (GTK_IS_MENU_ITEM (child)) {
GtkWidget *sub =
gtk_menu_item_get_submenu (GTK_MENU_ITEM (child));
if (sub)
children = g_list_concat (children,
gtk_container_get_children (GTK_CONTAINER (sub)));
else if (connect)
g_signal_connect (child, "activate",
G_CALLBACK (cb_select),
option_menu);
else
g_signal_handlers_disconnect_by_func
(child, G_CALLBACK (cb_select), option_menu);
}
}
}
void
go_option_menu_set_menu (GOOptionMenu *option_menu,
GtkWidget *menu)
{
GtkMenuShell *shell;
g_return_if_fail (GO_IS_OPTION_MENU (option_menu));
g_return_if_fail (GTK_IS_MENU_SHELL (menu));
shell = (GtkMenuShell *)menu;
if (option_menu->menu == shell)
return;
if (option_menu->menu) {
if (gtk_menu_shell_get_active (option_menu->menu))
gtk_menu_shell_cancel (option_menu->menu);
handle_menu_signals (option_menu, FALSE);
gtk_menu_detach (GTK_MENU (option_menu->menu));
g_object_unref (option_menu->menu);
}
option_menu->menu = shell;
if (shell) {
g_object_ref (shell);
gtk_menu_attach_to_widget (GTK_MENU (shell),
GTK_WIDGET (option_menu),
go_option_menu_detacher);
handle_menu_signals (option_menu, TRUE);
go_option_menu_select_item (option_menu,
GTK_MENU_ITEM (gtk_menu_get_active (GTK_MENU (shell))));
}
g_object_notify (G_OBJECT (option_menu), "menu");
}
void
go_option_menu_set_history (GOOptionMenu *option_menu, GSList *selection)
{
g_return_if_fail (selection != NULL);
g_return_if_fail (GO_IS_OPTION_MENU (option_menu));
if (option_menu->menu) {
GtkMenuShell *menu = option_menu->menu;
while (1) {
int n = GPOINTER_TO_INT (selection->data);
GtkMenuItem *item = g_list_nth_data (gtk_container_get_children (GTK_CONTAINER (menu)), n);
selection = selection->next;
if (selection)
menu = GTK_MENU_SHELL (gtk_menu_item_get_submenu (item));
else {
go_option_menu_select_item (option_menu, item);
break;
}
}
}
}
/**
* go_option_menu_get_history:
* @option_menu: a #GOOptionMenu
*
* Retrieves the currently selected menu item.
*
* Return value: the selected menu_item
**/
GtkWidget *
go_option_menu_get_history (GOOptionMenu *option_menu)
{
return GTK_WIDGET (option_menu->selected);
}
static void
go_option_menu_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GOOptionMenu *option_menu = GO_OPTION_MENU (object);
switch (prop_id) {
case PROP_MENU:
go_option_menu_set_menu (option_menu, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
go_option_menu_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GOOptionMenu *option_menu = GO_OPTION_MENU (object);
switch (prop_id) {
case PROP_MENU:
g_value_set_object (value, option_menu->menu);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
go_option_menu_destroy (GtkObject *object)
{
GOOptionMenu *option_menu;
g_return_if_fail (GO_IS_OPTION_MENU (object));
option_menu = GO_OPTION_MENU (object);
if (option_menu->menu) {
gtk_widget_destroy (GTK_WIDGET (option_menu->menu));
g_object_unref (option_menu->menu);
option_menu->menu = NULL;
}
option_menu->selected = NULL;
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
static void
go_option_menu_class_init (GOOptionMenuClass *class)
{
GObjectClass *gobject_class = (GObjectClass*) class;
GtkObjectClass *object_class = (GtkObjectClass*) class;
GtkWidgetClass *widget_class = (GtkWidgetClass*) class;
parent_class = g_type_class_peek_parent (class);
signals[CHANGED] =
g_signal_new ("changed",
G_OBJECT_CLASS_TYPE (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GOOptionMenuClass, changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
gobject_class->set_property = go_option_menu_set_property;
gobject_class->get_property = go_option_menu_get_property;
object_class->destroy = go_option_menu_destroy;
widget_class->button_press_event = go_option_menu_button_press;
widget_class->key_press_event = go_option_menu_key_press;
g_object_class_install_property (gobject_class,
PROP_MENU,
g_param_spec_object ("menu",
_("Menu"),
_("The menu of options"),
GTK_TYPE_MENU,
G_PARAM_READABLE | G_PARAM_WRITABLE));
}
static void
go_option_menu_init (GOOptionMenu *option_menu)
{
GtkBox *box;
GtkWidget *arrow, *sep;
gtk_widget_set_can_focus (GTK_WIDGET (option_menu), TRUE);
gtk_widget_set_can_default (GTK_WIDGET (option_menu), FALSE);
gtk_widget_set_receives_default (GTK_WIDGET (option_menu), FALSE);
box = GTK_BOX (gtk_hbox_new (FALSE, FALSE));
option_menu->menu = NULL;
option_menu->selected = NULL;
option_menu->button_label = GTK_LABEL (gtk_label_new (""));
gtk_box_pack_start (box, GTK_WIDGET (option_menu->button_label),
FALSE, TRUE, 0);
arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
g_object_set (arrow, "xalign", 0.75, NULL);
gtk_box_pack_end (box, arrow, FALSE, FALSE, 0);
sep = gtk_vseparator_new ();
gtk_box_pack_end (box, sep, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (option_menu), GTK_WIDGET (box));
}
GType
go_option_menu_get_type (void)
{
static GType option_menu_type = 0;
if (!option_menu_type) {
static const GTypeInfo option_menu_info =
{
sizeof (GOOptionMenuClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) go_option_menu_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GOOptionMenu),
0, /* n_preallocs */
(GInstanceInitFunc) go_option_menu_init,
};
option_menu_type =
g_type_register_static (GTK_TYPE_BUTTON, "GOOptionMenu",
&option_menu_info, 0);
}
return option_menu_type;
}

View File

@@ -0,0 +1,85 @@
/*
* go-optionmenu.h
*
* Copyright (C) 2002-2005 Andreas J. Guelzow <aguelzow@taliesin.ca>
*
* based extensively on:
*
* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* Modified by the GTK+ Team and others 1997-2000. See the GTK AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA.
*/
#ifndef _GO_OPTIONMENU_H_
#define _GO_OPTIONMENU_H_
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define GO_TYPE_OPTION_MENU (go_option_menu_get_type ())
#define GO_OPTION_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GO_TYPE_OPTION_MENU, GOOptionMenu))
#define GO_OPTION_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GO_TYPE_OPTION_MENU, GOOptionMenuClass))
#define GO_IS_OPTION_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GO_TYPE_OPTION_MENU))
#define GO_IS_OPTION_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GO_TYPE_OPTION_MENU))
#define GO_OPTION_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GO_TYPE_OPTION_MENU, GOOptionMenuClass))
typedef struct _GOOptionMenu GOOptionMenu;
typedef struct _GOOptionMenuClass GOOptionMenuClass;
struct _GOOptionMenu
{
GtkButton button;
/*< private >*/
GtkMenuShell *menu;
GtkMenuItem *selected;
GtkLabel *button_label;
};
struct _GOOptionMenuClass
{
GtkButtonClass parent_class;
void (*changed) (GOOptionMenu *option_menu);
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
};
GType go_option_menu_get_type (void) G_GNUC_CONST;
GtkWidget* go_option_menu_new (void);
void go_option_menu_set_menu (GOOptionMenu *option_menu,
GtkWidget *menu);
void go_option_menu_set_history (GOOptionMenu *option_menu,
GSList *selection);
GtkWidget *go_option_menu_get_history (GOOptionMenu *option_menu);
G_END_DECLS
#endif /* _GO_OPTIONMENU_H_ */