Fix build issues with goffice imported sources

- Remove unused includes and functions
- Some small cleanups
This commit is contained in:
Geert Janssens 2016-01-26 17:13:36 +01:00 committed by Geert Janssens
parent d858c7d51d
commit baf10bb7a5
5 changed files with 11 additions and 1073 deletions

View File

@ -10,8 +10,10 @@ REALHDRS = go-optionmenu.h \
libgnc_goffice_la_SOURCES = ${REALSRCS}
noinst_HEADERS = ${REALHDRS}
libgnc_goffice_la_LIBADD = $(GTK_LIBS)
libgnc_goffice_la_LIBADD = $(GTK_LIBS) \
${LIBXML2_LIBS}
AM_CPPFLAGS = $(GTK_CFLAGS)
AM_CPPFLAGS = $(GTK_CFLAGS) \
${LIBXML2_CFLAGS}
EXTRA_DIST = $(REALSRCS) $(REALHDRS)

View File

@ -23,12 +23,11 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <goffice/goffice-config.h>
#include "config.h"
#include "go-charmap-sel.h"
#include "go-optionmenu.h"
#include <goffice/utils/go-glib-extras.h>
#include "go-glib-extras.h"
#include <glib/gi18n-lib.h>
#include <gsf/gsf-impl-utils.h>
#include <string.h>
#include <stdlib.h>
@ -425,8 +424,7 @@ cs_build_menu (GOCharmapSel *cs)
set_menu_to_default (cs, lg_cnt);
}
static void
cs_class_init (GtkWidgetClass *widget_klass)
static void cs_class_init(GtkWidgetClass *widget_klass)
{
CharsetInfo *ci;
size_t i;
@ -552,9 +550,6 @@ cs_class_init (GtkWidgetClass *widget_klass)
}
}
GSF_CLASS (GOCharmapSel, go_charmap_sel,
cs_class_init, cs_init, GTK_TYPE_HBOX)
GtkWidget *
go_charmap_sel_new (GOCharmapSelTestDirection test)
{

View File

@ -8,13 +8,10 @@
* Zbigniew Chyla (cyba@gnome.pl)
* Morten Welinder (terra@gnome.org)
*/
#include <goffice/goffice-config.h>
#include "config.h"
#include "go-glib-extras.h"
#include "go-locale.h"
#include <goffice/app/go-cmd-context.h>
#include <glib/gi18n-lib.h>
#include <gsf/gsf-impl-utils.h>
#include <libxml/encoding.h>
#include <stdlib.h>
@ -29,208 +26,6 @@
#include <fcntl.h>
#include <errno.h>
static void
cb_hash_collect_keys (gpointer key, gpointer value, GSList **accum)
{
*accum = g_slist_prepend (*accum, key);
}
/**
* go_hash_keys :
* @hash : #GHashTable
*
* Collects an unordered list of the keys in @hash.
*
* Returns: a list which the caller needs to free.
* The content has not additional references added
**/
GSList *
go_hash_keys (GHashTable *hash)
{
GSList *accum = NULL;
g_hash_table_foreach (hash,
(GHFunc )cb_hash_collect_keys, &accum);
return accum;
}
static void
cb_hash_collect_values (gpointer key, gpointer value, GSList **accum)
{
*accum = g_slist_prepend (*accum, value);
}
/**
* go_hash_values :
* @hash : #GHashTable
*
* Collects an unordered list of the values in @hash.
*
* Returns: a list which the caller needs to free.
* The content has not additional references added
**/
GSList *
go_hash_values (GHashTable *hash)
{
GSList *accum = NULL;
g_hash_table_foreach (hash,
(GHFunc )cb_hash_collect_values, &accum);
return accum;
}
/***************************************************************************/
void
go_ptr_array_insert (GPtrArray *array, gpointer value, int index)
{
if (index < (int)array->len) {
int i = array->len - 1;
gpointer last = g_ptr_array_index (array, i);
g_ptr_array_add (array, last);
while (i-- > index) {
gpointer tmp = g_ptr_array_index (array, i);
g_ptr_array_index (array, i + 1) = tmp;
}
g_ptr_array_index (array, index) = value;
} else
g_ptr_array_add (array, value);
}
/**
* go_slist_create:
* @item1: itionally %NULL
* @Varargs : %NULL terminated list of additional items
*
* Creates a GList from NULL-terminated list of arguments.
*
* Returns: created list.
**/
GSList *
go_slist_create (gpointer item1, ...)
{
va_list args;
GSList *list = NULL;
gpointer item;
va_start (args, item1);
for (item = item1; item != NULL; item = va_arg (args, gpointer)) {
list = g_slist_prepend (list, item);
}
va_end (args);
return g_slist_reverse (list);
}
/**
* go_slist_map:
* @list : list of some items
* @map_func : mapping function
*
**/
GSList *
go_slist_map (GSList const *list, GOMapFunc map_func)
{
GSList *list_copy = NULL;
GO_SLIST_FOREACH (list, void, value,
GO_SLIST_PREPEND (list_copy, map_func (value))
);
return g_slist_reverse (list_copy);
}
/**
* go_slist_free_custom:
* @list: list of some items
* @free_func: function freeing list item
*
* Clears a list, calling @free_func for each list item.
**/
void
go_slist_free_custom (GSList *list, GFreeFunc free_func)
{
GSList *l;
for (l = list; l != NULL; l = l->next) {
free_func (l->data);
}
g_slist_free (list);
}
gint
go_list_index_custom (GList *list, gpointer data, GCompareFunc cmp_func)
{
GList *l;
gint i;
for (l = list, i = 0; l != NULL; l = l->next, i++) {
if (cmp_func (l->data, data) == 0) {
return i;
}
}
return -1;
}
/**
* go_list_free_custom:
* @list: list of some items
* @free_func: function freeing list item
*
* Clears a list, calling @free_func for each list item.
*
*/
void
go_list_free_custom (GList *list, GFreeFunc free_func)
{
GList *l;
for (l = list; l != NULL; l = l->next) {
free_func (l->data);
}
g_list_free (list);
}
/**
* go_strsplit_to_slist:
* @str: String to split
* @delimiter: Token delimiter
*
* Splits up string into tokens at delim and returns a string list.
*
* Returns: string list which you should free after use using function
* e_free_string_list().
**/
GSList *
go_strsplit_to_slist (gchar const *string, gchar delimiter)
{
gchar **token_v;
GSList *string_list = NULL;
char buf[2] = { '\0', '\0' };
gint i;
buf[0] = delimiter;
token_v = g_strsplit (string, buf, 0);
if (token_v != NULL) {
for (i = 0; token_v[i] != NULL; i++) {
string_list = g_slist_prepend (string_list, token_v[i]);
}
string_list = g_slist_reverse (string_list);
g_free (token_v);
}
return string_list;
}
gint
go_utf8_collate_casefold (const char *a, const char *b)
{
char *a2 = g_utf8_casefold (a, -1);
char *b2 = g_utf8_casefold (b, -1);
int res = g_utf8_collate (a2, b2);
g_free (a2);
g_free (b2);
return res;
}
gint
go_ascii_strcase_equal (gconstpointer v1, gconstpointer v2)
@ -257,441 +52,6 @@ go_ascii_strcase_hash (gconstpointer v)
return h /* % M */;
}
/* ------------------------------------------------------------------------- */
/*
* Escapes all backslashes and quotes in a string. It is based on glib's
* g_strescape.
*
* Also adds quotes around the result.
*/
void
go_strescape (GString *target, char const *string)
{
g_string_append_c (target, '"');
/* This loop should be UTF-8 safe. */
for (; *string; string++) {
switch (*string) {
case '"':
case '\\':
g_string_append_c (target, '\\');
default:
g_string_append_c (target, *string);
}
}
g_string_append_c (target, '"');
}
/*
* The reverse operation of go_strescape. Returns a pointer to the
* first char after the string on success or NULL on failure.
*
* First character of the string should be an ASCII character used
* for quoting.
*/
const char *
go_strunescape (GString *target, const char *string)
{
char quote = *string++;
size_t oldlen = target->len;
/* This should be UTF-8 safe as long as quote is ASCII. */
while (*string != quote) {
if (*string == 0)
goto error;
else if (*string == '\\') {
string++;
if (*string == 0)
goto error;
}
g_string_append_c (target, *string);
string++;
}
return ++string;
error:
g_string_truncate (target, oldlen);
return NULL;
}
void
go_string_append_gstring (GString *target, const GString *source)
{
g_string_append_len (target, source->str, source->len);
}
void
go_string_append_c_n (GString *target, char c, gsize n)
{
gsize len = target->len;
g_string_set_size (target, len + n);
memset (target->str + len, c, n);
}
void
go_string_replace (GString *target,
gsize pos, gssize oldlen,
const char *txt, gssize newlen)
{
gsize cplen;
g_return_if_fail (target != NULL);
g_return_if_fail (pos >= 0);
g_return_if_fail (pos <= target->len);
if (oldlen < 0)
oldlen = target->len - pos;
if (newlen < 0)
newlen = strlen (txt);
cplen = MIN (oldlen, newlen);
memcpy (target->str + pos, txt, cplen);
pos += cplen;
oldlen -= cplen;
txt += cplen;
newlen -= cplen;
/*
* At least one of oldlen and newlen is zero now. We could call
* both erase and insert unconditionally, but erase does not appear
* to handle zero length efficiently.
*/
if (oldlen > 0)
g_string_erase (target, pos, oldlen);
else if (newlen > 0)
g_string_insert_len (target, pos, txt, newlen);
}
/* ------------------------------------------------------------------------- */
/**
* go_utf8_strcapital:
* @p: pointer to UTF-8 string
* @len: length in bytes, or -1.
*
* Similar to g_utf8_strup and g_utf8_strup, except that this function
* creates a string "Very Much Like: This, One".
*
* Return value: newly allocated string.
**/
char *
go_utf8_strcapital (const char *p, gssize len)
{
const char *pend = (len < 0 ? NULL : p + len);
GString *res = g_string_sized_new (len < 0 ? 1 : len + 1);
gboolean up = TRUE;
/*
* This does a simple character-by-character mapping and probably
* is not linguistically correct.
*/
for (; (len < 0 || p < pend) && *p; p = g_utf8_next_char (p)) {
gunichar c = g_utf8_get_char (p);
if (g_unichar_isalpha (c)) {
if (up ? g_unichar_isupper (c) : g_unichar_islower (c))
/* Correct case -- keep the char. */
g_string_append_unichar (res, c);
else {
char *tmp = up
? g_utf8_strup (p, 1)
: g_utf8_strdown (p, 1);
g_string_append (res, tmp);
g_free (tmp);
}
up = FALSE;
} else {
g_string_append_unichar (res, c);
up = TRUE;
}
}
return g_string_free (res, FALSE);
}
/* ------------------------------------------------------------------------- */
#undef DEBUG_CHUNK_ALLOCATOR
typedef struct _go_mem_chunk_freeblock go_mem_chunk_freeblock;
typedef struct _go_mem_chunk_block go_mem_chunk_block;
struct _go_mem_chunk_freeblock {
go_mem_chunk_freeblock *next;
};
struct _go_mem_chunk_block {
gpointer data;
int freecount, nonalloccount;
go_mem_chunk_freeblock *freelist;
#ifdef DEBUG_CHUNK_ALLOCATOR
int id;
#endif
};
struct _GOMemChunk {
char *name;
size_t atom_size, user_atom_size, chunk_size, alignment;
int atoms_per_block;
/* List of all blocks. */
GSList *blocklist;
/* List of blocks that are not full. */
GList *freeblocks;
#ifdef DEBUG_CHUNK_ALLOCATOR
int blockid;
#endif
};
GOMemChunk *
go_mem_chunk_new (char const *name, size_t user_atom_size, size_t chunk_size)
{
int atoms_per_block;
GOMemChunk *res;
size_t user_alignment, alignment, atom_size;
size_t maxalign = 1 + ((sizeof (void *) - 1) |
(sizeof (long) - 1) |
(sizeof (double) - 1));
/*
* The alignment that the caller can expect is 2^(lowest_bit_in_size).
* The fancy bit math computes this. Think it over.
*
* We don't go lower than pointer-size, so this always comes out as
* 4 or 8. Sometimes, when user_atom_size is a multiple of 8, this
* alignment is bigger than really needed, but we don't know if the
* structure has elements with 8-byte alignment. In those cases we
* waste memory.
*/
user_alignment = ((user_atom_size ^ (user_atom_size - 1)) + 1) / 2;
alignment = MIN (MAX (user_alignment, sizeof (go_mem_chunk_block *)), maxalign);
atom_size = alignment + MAX (user_atom_size, sizeof (go_mem_chunk_freeblock));
atoms_per_block = MAX (1, chunk_size / atom_size);
chunk_size = atoms_per_block * atom_size;
#ifdef DEBUG_CHUNK_ALLOCATOR
g_print ("Created %s with alignment=%d, atom_size=%d (%d), chunk_size=%d.\n",
name, alignment, atom_size, user_atom_size,
chunk_size);
#endif
res = g_new (GOMemChunk, 1);
res->alignment = alignment;
res->name = g_strdup (name);
res->user_atom_size = user_atom_size;
res->atom_size = atom_size;
res->chunk_size = chunk_size;
res->atoms_per_block = atoms_per_block;
res->blocklist = NULL;
res->freeblocks = NULL;
#ifdef DEBUG_CHUNK_ALLOCATOR
res->blockid = 0;
#endif
return res;
}
void
go_mem_chunk_destroy (GOMemChunk *chunk, gboolean expect_leaks)
{
GSList *l;
g_return_if_fail (chunk != NULL);
#ifdef DEBUG_CHUNK_ALLOCATOR
g_print ("Destroying %s.\n", chunk->name);
#endif
/*
* Since this routine frees all memory allocated for the pool,
* it is sometimes convenient not to free at all. For such
* cases, don't report leaks.
*/
if (!expect_leaks) {
GSList *l;
int leaked = 0;
for (l = chunk->blocklist; l; l = l->next) {
go_mem_chunk_block *block = l->data;
leaked += chunk->atoms_per_block - (block->freecount + block->nonalloccount);
}
if (leaked) {
g_warning ("Leaked %d nodes from %s.",
leaked, chunk->name);
}
}
for (l = chunk->blocklist; l; l = l->next) {
go_mem_chunk_block *block = l->data;
g_free (block->data);
g_free (block);
}
g_slist_free (chunk->blocklist);
g_list_free (chunk->freeblocks);
g_free (chunk->name);
g_free (chunk);
}
gpointer
go_mem_chunk_alloc (GOMemChunk *chunk)
{
go_mem_chunk_block *block;
char *res;
/* First try the freelist. */
if (chunk->freeblocks) {
go_mem_chunk_freeblock *res;
block = chunk->freeblocks->data;
res = block->freelist;
if (res) {
block->freelist = res->next;
block->freecount--;
if (block->freecount == 0 && block->nonalloccount == 0) {
/* Block turned full -- remove it from freeblocks. */
chunk->freeblocks = g_list_delete_link (chunk->freeblocks,
chunk->freeblocks);
}
return res;
}
/*
* If we get here, the block has free space that was never
* allocated.
*/
} else {
block = g_new (go_mem_chunk_block, 1);
#ifdef DEBUG_CHUNK_ALLOCATOR
block->id = chunk->blockid++;
g_print ("Allocating new chunk %d for %s.\n", block->id, chunk->name);
#endif
block->nonalloccount = chunk->atoms_per_block;
block->freecount = 0;
block->data = g_malloc (chunk->chunk_size);
block->freelist = NULL;
chunk->blocklist = g_slist_prepend (chunk->blocklist, block);
chunk->freeblocks = g_list_prepend (chunk->freeblocks, block);
}
res = (char *)block->data +
(chunk->atoms_per_block - block->nonalloccount--) * chunk->atom_size;
*((go_mem_chunk_block **)res) = block;
if (block->nonalloccount == 0 && block->freecount == 0) {
/* Block turned full -- remove it from freeblocks. */
chunk->freeblocks = g_list_delete_link (chunk->freeblocks, chunk->freeblocks);
}
return res + chunk->alignment;
}
gpointer
go_mem_chunk_alloc0 (GOMemChunk *chunk)
{
gpointer res = go_mem_chunk_alloc (chunk);
memset (res, 0, chunk->user_atom_size);
return res;
}
void
go_mem_chunk_free (GOMemChunk *chunk, gpointer mem)
{
go_mem_chunk_freeblock *fb = mem;
go_mem_chunk_block *block =
*((go_mem_chunk_block **)((char *)mem - chunk->alignment));
#if 0
/*
* This is useful when the exact location of a leak needs to be
* pin-pointed.
*/
memset (mem, 0, chunk->user_atom_size);
#endif
fb->next = block->freelist;
block->freelist = fb;
block->freecount++;
if (block->freecount == 1 && block->nonalloccount == 0) {
/* Block turned non-full. */
chunk->freeblocks = g_list_prepend (chunk->freeblocks, block);
} else if (block->freecount == chunk->atoms_per_block) {
/* Block turned all-free. */
#ifdef DEBUG_CHUNK_ALLOCATOR
g_print ("Releasing chunk %d for %s.\n", block->id, chunk->name);
#endif
/*
* FIXME -- this could be faster if we rolled our own lists.
* Hopefully, however, (a) the number of blocks is small,
* and (b) the freed block might be near the beginning ("top")
* of the stacks.
*/
chunk->blocklist = g_slist_remove (chunk->blocklist, block);
chunk->freeblocks = g_list_remove (chunk->freeblocks, block);
g_free (block->data);
g_free (block);
}
}
/*
* Loop over all non-freed memory in the chunk. It's safe to allocate or free
* from the chunk in the callback.
*/
void
go_mem_chunk_foreach_leak (GOMemChunk *chunk, GFunc cb, gpointer user)
{
GSList *l, *leaks = NULL;
for (l = chunk->blocklist; l; l = l->next) {
go_mem_chunk_block *block = l->data;
if (chunk->atoms_per_block - (block->freecount + block->nonalloccount) > 0) {
char *freed = g_new0 (char, chunk->atoms_per_block);
go_mem_chunk_freeblock *fb = block->freelist;
int i;
while (fb) {
char *atom = (char *)fb - chunk->alignment;
int no = (atom - (char *)block->data) / chunk->atom_size;
freed[no] = 1;
fb = fb->next;
}
for (i = chunk->atoms_per_block - block->nonalloccount - 1; i >= 0; i--) {
if (!freed[i]) {
char *atom = (char *)block->data + i * chunk->atom_size;
leaks = g_slist_prepend (leaks, atom + chunk->alignment);
}
}
g_free (freed);
}
}
g_slist_foreach (leaks, cb, user);
g_slist_free (leaks);
}
int
go_str_compare (void const *x, void const *y)
{
if (x == y)
return 0;
if (x == NULL || y == NULL)
return x ? -1 : 1;
return strcmp (x, y);
}
const char *
go_guess_encoding (const char *raw, size_t len, const char *user_guess,
@ -763,320 +123,3 @@ go_guess_encoding (const char *raw, size_t len, const char *user_guess,
g_error_free (error);
}
}
/**
* go_get_real_name :
*
* Returns: a utf8 encoded string with the current user name.
* Caller should _NOT_ free the result.
**/
char const *
go_get_real_name (void)
{
/* We will leak this. */
static char *go_real_name = NULL;
if (go_real_name == NULL) {
char const *name = getenv ("NAME");
if (name == NULL)
name = g_get_real_name ();
if (name == NULL)
name = g_get_user_name ();
if (name != NULL)
(void) go_guess_encoding (name, strlen (name),
NULL, &go_real_name);
else
go_real_name = (char *)"unknown";
}
return go_real_name;
}
/**
* go_destroy_password :
* @passwd : The buffer to clear
*
* Overwrite a string holding a password. This is a separate routine to
* ensure that the compiler does not try to outsmart us.
*
* Note: this does not free the memory.
**/
void
go_destroy_password (char *passwd)
{
memset (passwd, 0, strlen (passwd));
}
/**
* go_object_toggle:
* @object : #GObject
* @property_name : name
*
* Toggle a boolean object property.
**/
void
go_object_toggle (gpointer object, const gchar *property_name)
{
gboolean value = FALSE;
GParamSpec *pspec;
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (property_name != NULL);
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
if (!pspec ||
!G_IS_PARAM_SPEC_BOOLEAN (pspec) ||
((pspec->flags & (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)) !=
G_PARAM_READWRITE)) {
g_warning ("%s: object class `%s' has no boolean property named `%s' that can be both read and written.",
G_STRFUNC,
G_OBJECT_TYPE_NAME (object),
property_name);
return;
}
/* And now, the actual action. */
g_object_get (object, property_name, &value, NULL);
g_object_set (object, property_name, !value, NULL);
}
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)
{
GParamSpec *pspec;
if (err) *err = NULL;
g_return_val_if_fail (G_IS_OBJECT (obj), TRUE);
g_return_val_if_fail (property_name != NULL, TRUE);
g_return_val_if_fail (user_prop_name != NULL, TRUE);
g_return_val_if_fail (value != NULL, TRUE);
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (obj),
property_name);
g_return_val_if_fail (pspec != NULL, TRUE);
if (G_IS_PARAM_SPEC_STRING (pspec)) {
g_object_set (obj, property_name, value, NULL);
return FALSE;
}
if (G_IS_PARAM_SPEC_BOOLEAN (pspec)) {
gboolean b;
if (go_utf8_collate_casefold (value, go_locale_boolean_name (TRUE)) == 0 ||
go_utf8_collate_casefold (value, _("yes")) == 0 ||
g_ascii_strcasecmp (value, "TRUE") == 0 ||
g_ascii_strcasecmp (value, "yes") == 0 ||
strcmp (value, "1") == 0)
b = TRUE;
else if (go_utf8_collate_casefold (value, go_locale_boolean_name (FALSE)) == 0 ||
go_utf8_collate_casefold (value, _("no")) == 0 ||
g_ascii_strcasecmp (value, "FALSE") == 0 ||
g_ascii_strcasecmp (value, "no") == 0 ||
strcmp (value, "0") == 0)
b = FALSE;
else
goto error;
g_object_set (obj, property_name, b, NULL);
return FALSE;
}
if (G_IS_PARAM_SPEC_ENUM (pspec)) {
GEnumClass *eclass = ((GParamSpecEnum *)pspec)->enum_class;
GEnumValue *ev;
ev = g_enum_get_value_by_name (eclass, value);
if (!ev) ev = g_enum_get_value_by_nick (eclass, value);
if (!ev)
goto error;
g_object_set (obj, property_name, ev->value, NULL);
return FALSE;
}
error:
if (err)
*err = g_error_new (go_error_invalid (), 0,
error_template,
user_prop_name,
value);
return TRUE;
}
/*
* Collect all rw properties and their values.
*/
GSList *
go_object_properties_collect (GObject *obj)
{
GSList *res = NULL;
guint n;
GParamSpec **pspecs =
g_object_class_list_properties (G_OBJECT_GET_CLASS (obj),
&n);
while (n--) {
GParamSpec *pspec = pspecs[n];
if ((pspec->flags & (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)) ==
G_PARAM_READWRITE) {
GValue *value = g_new0 (GValue, 1);
g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
g_object_get_property (obj, pspec->name, value);
res = g_slist_prepend (res, value);
res = g_slist_prepend (res, pspec);
}
}
g_free (pspecs);
return res;
}
void
go_object_properties_apply (GObject *obj, GSList *props, gboolean changed_only)
{
GValue current = { 0, };
for (; props; props = props->next->next) {
GParamSpec *pspec = props->data;
const GValue *value = props->next->data;
gboolean doit;
if (changed_only) {
g_value_init (&current,
G_PARAM_SPEC_VALUE_TYPE (pspec));
g_object_get_property (obj, pspec->name, &current);
doit = g_param_values_cmp (pspec, &current, value);
#if 0
g_print ("%2d: old: [%s] new: [%s]\n",
g_param_values_cmp (pspec, &current, value),
g_strdup_value_contents (value),
g_strdup_value_contents (&current));
#endif
g_value_unset (&current);
} else
doit = TRUE;
if (doit)
g_object_set_property (obj, pspec->name, value);
}
}
void
go_object_properties_free (GSList *props)
{
GSList *l;
for (l = props; l; l = l->next->next) {
GValue *value = l->next->data;
g_value_unset (value);
g_free (value);
}
g_slist_free (props);
}
/**
* go_parse_key_value:
* @options: Options string.
* @err: Reference to store GError if parsing fails.
* @handler: Handler to call for each key-value pair.
* @user: user pointer.
*/
gboolean
go_parse_key_value (const char *options,
GError **err,
gboolean (*handler) (const char *name,
const char *value,
GError **err,
gpointer user),
gpointer user)
{
GString *sname = g_string_new (NULL);
GString *svalue = g_string_new (NULL);
gboolean res = FALSE;
if (err) *err = NULL;
while (1) {
const char *p;
g_string_truncate (sname, 0);
g_string_truncate (svalue, 0);
while (g_unichar_isspace (g_utf8_get_char (options)))
options = g_utf8_next_char (options);
if (*options == 0)
break;
if (*options == '"' || *options == '\'') {
options = go_strunescape (sname, options);
if (!options)
goto open_string;
} else {
p = options;
while (strchr ("-!_.,:;|/$%#@~", *options) ||
g_unichar_isalnum (g_utf8_get_char (options)))
options = g_utf8_next_char (options);
g_string_append_len (sname, p, options - p);
if (p == options)
goto syntax;
}
while (g_unichar_isspace (g_utf8_get_char (options)))
options = g_utf8_next_char (options);
if (*options != '=')
goto syntax;
options++;
while (g_unichar_isspace (g_utf8_get_char (options)))
options = g_utf8_next_char (options);
if (*options == '"' || *options == '\'') {
options = go_strunescape (svalue, options);
if (!options)
goto open_string;
} else {
p = options;
while (*options && !
g_unichar_isspace (g_utf8_get_char (options)))
options = g_utf8_next_char (options);
g_string_append_len (svalue, p, options - p);
}
if (handler (sname->str, svalue->str, err, user)) {
res = TRUE;
break;
}
}
done:
g_string_free (sname, TRUE);
g_string_free (svalue, TRUE);
return res;
open_string:
if (err)
*err = g_error_new (go_error_invalid (), 0,
_("Quoted string not terminated"));
res = TRUE;
goto done;
syntax:
if (err)
*err = g_error_new (go_error_invalid (), 0,
_("Syntax error"));
res = TRUE;
goto done;
}

View File

@ -1,119 +1,18 @@
#ifndef GO_GLIB_EXTRAS_H
#define GO_GLIB_EXTRAS_H
#include <goffice/goffice.h>
#include <glib.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 */

View File

@ -31,9 +31,8 @@
* USA.
*/
#include <goffice/goffice-config.h>
#include "config.h"
#include "go-optionmenu.h"
#include <goffice/gtk/go-gtk-compat.h>
#include <gdk/gdkkeysyms.h>
#include <glib/gi18n-lib.h>
@ -265,7 +264,7 @@ go_option_menu_set_menu (GOOptionMenu *option_menu,
return;
if (option_menu->menu) {
if (gtk_menu_shell_get_active (option_menu->menu))
if (option_menu->menu->active)
gtk_menu_shell_cancel (option_menu->menu);
handle_menu_signals (option_menu, FALSE);