* mu-threader, mu-util: cleanups

This commit is contained in:
Dirk-Jan C. Binnema
2011-08-30 22:02:49 +03:00
parent 6a13866235
commit 846d2da27f
3 changed files with 113 additions and 99 deletions

View File

@ -41,11 +41,11 @@
* Msg4 (child of Msg2) => 00001:00001 * Msg4 (child of Msg2) => 00001:00001
* Msg5 (child of Msg4) => 00001:00001:00000 * Msg5 (child of Msg4) => 00001:00001:00000
* Msg6 => 00002 * Msg6 => 00002
* *
* the padding-0's are added to make them easy to sort using strcmp; * the padding-0's are added to make them easy to sort using strcmp;
* the number hexadecimal numbers, and the length of the 'segments' * the number hexadecimal numbers, and the length of the 'segments'
* (the parts separated by the ':') is equal to ceil(log_16(matchnum)) * (the parts separated by the ':') is equal to ceil(log_16(matchnum))
* *
*/ */
@ -67,10 +67,10 @@ mu_threader_calculate (MuMsgIter *iter, size_t matchnum, MuMsgFieldId sortfield)
g_return_val_if_fail (mu_msg_field_id_is_valid (sortfield) || g_return_val_if_fail (mu_msg_field_id_is_valid (sortfield) ||
sortfield == MU_MSG_FIELD_ID_NONE, sortfield == MU_MSG_FIELD_ID_NONE,
FALSE); FALSE);
/* step 1 */ /* step 1 */
id_table = create_containers (iter); id_table = create_containers (iter);
/* step 2 -- the root_set is the list of children without parent */ /* step 2 -- the root_set is the list of children without parent */
root_set = find_root_set (id_table); root_set = find_root_set (id_table);
@ -78,22 +78,22 @@ mu_threader_calculate (MuMsgIter *iter, size_t matchnum, MuMsgFieldId sortfield)
/* step 4: prune empty containers */ /* step 4: prune empty containers */
root_set = prune_empty_containers (root_set); root_set = prune_empty_containers (root_set);
/* sort root set */ /* sort root set */
if (sortfield != MU_MSG_FIELD_ID_NONE) if (sortfield != MU_MSG_FIELD_ID_NONE)
root_set = mu_container_sort (root_set, sortfield, root_set = mu_container_sort (root_set, sortfield,
NULL, FALSE); NULL, FALSE);
/* step 5: group root set by subject */ /* step 5: group root set by subject */
//group_root_set_by_subject (root_set); //group_root_set_by_subject (root_set);
/* sort */ /* sort */
mu_msg_iter_reset (iter); /* go all the way back */ mu_msg_iter_reset (iter); /* go all the way back */
/* finally, deliver the docid => thread-path hash */ /* finally, deliver the docid => thread-path hash */
thread_ids = mu_container_thread_info_hash_new (root_set, thread_ids = mu_container_thread_info_hash_new (root_set,
matchnum); matchnum);
g_hash_table_destroy (id_table); /* step 3*/ g_hash_table_destroy (id_table); /* step 3*/
return thread_ids; return thread_ids;
@ -119,11 +119,11 @@ assert_no_duplicates (GHashTable *ids)
GHashTable *hash; GHashTable *hash;
hash = g_hash_table_new (g_direct_hash, g_direct_equal); hash = g_hash_table_new (g_direct_hash, g_direct_equal);
g_hash_table_foreach (ids, g_hash_table_foreach (ids,
(GHFunc)check_dup, (GHFunc)check_dup,
hash); hash);
g_hash_table_destroy (hash); g_hash_table_destroy (hash);
} }
@ -140,7 +140,7 @@ find_or_create_referred (GHashTable *id_table, const char *msgid,
g_return_val_if_fail (msgid, NULL); g_return_val_if_fail (msgid, NULL);
c = g_hash_table_lookup (id_table, msgid); c = g_hash_table_lookup (id_table, msgid);
*created = !c; *created = !c;
if (!c) { if (!c) {
c = mu_container_new (NULL, 0, msgid); c = mu_container_new (NULL, 0, msgid);
@ -148,7 +148,7 @@ find_or_create_referred (GHashTable *id_table, const char *msgid,
/* assert_no_duplicates (id_table); */ /* assert_no_duplicates (id_table); */
} }
return c; return c;
} }
@ -162,13 +162,13 @@ find_or_create (GHashTable *id_table, MuMsg *msg, guint docid)
g_return_val_if_fail (msg, NULL); g_return_val_if_fail (msg, NULL);
g_return_val_if_fail (docid != 0, NULL); g_return_val_if_fail (docid != 0, NULL);
msgid = mu_msg_get_msgid (msg); msgid = mu_msg_get_msgid (msg);
if (!msgid) if (!msgid)
msgid = mu_msg_get_path (msg); /* fake it */ msgid = mu_msg_get_path (msg); /* fake it */
c = g_hash_table_lookup (id_table, msgid); c = g_hash_table_lookup (id_table, msgid);
/* If id_table contains an empty MuContainer for this ID: * * /* If id_table contains an empty MuContainer for this ID: * *
* Store this message in the MuContainer's message slot. */ * Store this message in the MuContainer's message slot. */
if (c) { if (c) {
@ -200,14 +200,14 @@ find_or_create (GHashTable *id_table, MuMsg *msg, guint docid)
c = mu_container_new (msg, docid, msgid); c = mu_container_new (msg, docid, msgid);
g_hash_table_insert (id_table, (gpointer)msgid, c); g_hash_table_insert (id_table, (gpointer)msgid, c);
/* assert_no_duplicates (id_table); */ /* assert_no_duplicates (id_table); */
return c; return c;
} }
} }
static gboolean static gboolean
child_elligible (MuContainer *parent, MuContainer *child, gboolean created) child_elligible (MuContainer *parent, MuContainer *child, gboolean created)
{ {
if (!parent || !child) if (!parent || !child)
return FALSE; return FALSE;
if (child->parent) if (child->parent)
@ -230,25 +230,25 @@ handle_references (GHashTable *id_table, MuContainer *c)
const GSList *refs, *cur; const GSList *refs, *cur;
MuContainer *parent; MuContainer *parent;
gboolean created; gboolean created;
refs = mu_msg_get_references (c->msg); refs = mu_msg_get_references (c->msg);
if (!refs) if (!refs)
return; /* nothing to do */ return; /* nothing to do */
/* For each element in the message's References field: /* For each element in the message's References field:
Find a MuContainer object for the given Message-ID: If Find a MuContainer object for the given Message-ID: If
there's one in id_table use that; Otherwise, make (and there's one in id_table use that; Otherwise, make (and
index) one with a null Message. */ index) one with a null Message. */
/* go over over our list of refs, until 1 before the last... */ /* go over over our list of refs, until 1 before the last... */
created = FALSE; created = FALSE;
for (parent = NULL, cur = refs; cur; cur = g_slist_next (cur)) { for (parent = NULL, cur = refs; cur; cur = g_slist_next (cur)) {
MuContainer *child; MuContainer *child;
child = find_or_create_referred (id_table, (gchar*)cur->data, child = find_or_create_referred (id_table, (gchar*)cur->data,
&created); &created);
/*Link the References field's MuContainers together in /*Link the References field's MuContainers together in
* the order implied by the References header. * the order implied by the References header.
@ -261,13 +261,13 @@ handle_references (GHashTable *id_table, MuContainer *c)
as a child of the other, don't add the link. */ as a child of the other, don't add the link. */
if (child_elligible (parent, child, created)) if (child_elligible (parent, child, created))
parent = mu_container_append_children (parent, child); parent = mu_container_append_children (parent, child);
parent = child; parent = child;
} }
/* 'parent' points to the last ref: our direct parent; /* 'parent' points to the last ref: our direct parent;
Set the parent of this message to be the last element in Set the parent of this message to be the last element in
References. Note that this message may have a parent References. Note that this message may have a parent
already: this can happen because we saw this ID in a already: this can happen because we saw this ID in a
@ -276,12 +276,12 @@ handle_references (GHashTable *id_table, MuContainer *c)
we can be more definitive, so throw away the old parent and we can be more definitive, so throw away the old parent and
use this new one. Find this MuContainer in the parent's use this new one. Find this MuContainer in the parent's
children list, and unlink it. children list, and unlink it.
Note that this could cause this message to now have no Note that this could cause this message to now have no
parent, if it has no references field, but some message parent, if it has no references field, but some message
referred to it as the non-first element of its referred to it as the non-first element of its
references. (Which would have been some kind of lie...) references. (Which would have been some kind of lie...)
Note that at all times, the various ``parent'' and ``child'' fields Note that at all times, the various ``parent'' and ``child'' fields
must be kept inter-consistent. */ must be kept inter-consistent. */
@ -302,24 +302,24 @@ create_containers (MuMsgIter *iter)
g_str_equal, g_str_equal,
NULL, NULL,
(GDestroyNotify)mu_container_destroy); (GDestroyNotify)mu_container_destroy);
for (mu_msg_iter_reset (iter); !mu_msg_iter_is_done (iter); for (mu_msg_iter_reset (iter); !mu_msg_iter_is_done (iter);
mu_msg_iter_next (iter)) { mu_msg_iter_next (iter)) {
MuContainer *c; MuContainer *c;
MuMsg *msg; MuMsg *msg;
unsigned docid; unsigned docid;
/* 1.A */ /* 1.A */
msg = mu_msg_iter_get_msg (iter, NULL); msg = mu_msg_iter_get_msg_floating (iter); /* don't unref */
docid = mu_msg_iter_get_docid (iter); docid = mu_msg_iter_get_docid (iter);
c = find_or_create (id_table, msg, docid); c = find_or_create (id_table, msg, docid);
/* 1.B and C */ /* 1.B and C */
if (c) if (c)
handle_references (id_table, c); handle_references (id_table, c);
} }
return id_table; return id_table;
} }
@ -330,7 +330,7 @@ static void
filter_root_set (const gchar *msgid, MuContainer *c, MuContainer **root_set) filter_root_set (const gchar *msgid, MuContainer *c, MuContainer **root_set)
{ {
if (c->parent) if (c->parent)
return; return;
if (*root_set == NULL) { if (*root_set == NULL) {
*root_set = c; *root_set = c;
@ -358,25 +358,25 @@ static gboolean
prune_maybe (MuContainer *c) prune_maybe (MuContainer *c)
{ {
MuContainer *cur; MuContainer *cur;
for (cur = c->child; cur; cur = cur->next) { for (cur = c->child; cur; cur = cur->next) {
if (cur->flags & MU_CONTAINER_FLAG_DELETE) if (cur->flags & MU_CONTAINER_FLAG_DELETE)
c = mu_container_remove_child (c, cur); c = mu_container_remove_child (c, cur);
else if (cur->flags & MU_CONTAINER_FLAG_SPLICE) else if (cur->flags & MU_CONTAINER_FLAG_SPLICE)
c = mu_container_splice_children (c, cur); c = mu_container_splice_children (c, cur);
} }
/* don't touch containers with messages */ /* don't touch containers with messages */
if (c->msg) if (c->msg)
return TRUE; return TRUE;
/* A. If it is an msg-less container with no children, mark it /* A. If it is an msg-less container with no children, mark it
* for deletion. */ * for deletion. */
if (!c->child) { if (!c->child) {
c->flags |= MU_CONTAINER_FLAG_DELETE; c->flags |= MU_CONTAINER_FLAG_DELETE;
return TRUE; return TRUE;
} }
/* B. If the MuContainer has no Message, but does have /* B. If the MuContainer has no Message, but does have
* children, remove this container but promote its * children, remove this container but promote its
* children to this level (that is, splice them in to * children to this level (that is, splice them in to
@ -388,9 +388,9 @@ prune_maybe (MuContainer *c)
*/ */
if (c->child->next) /* ie., > 1 child */ if (c->child->next) /* ie., > 1 child */
return TRUE; return TRUE;
c->flags |= MU_CONTAINER_FLAG_SPLICE; c->flags |= MU_CONTAINER_FLAG_SPLICE;
return TRUE; return TRUE;
} }
@ -401,11 +401,11 @@ prune_empty_containers (MuContainer *root_set)
MuContainer *cur; MuContainer *cur;
mu_container_foreach (root_set, (MuContainerForeachFunc)prune_maybe, NULL); mu_container_foreach (root_set, (MuContainerForeachFunc)prune_maybe, NULL);
/* and prune the root_set itself... */ /* and prune the root_set itself... */
for (cur = root_set; cur; cur = cur->next) { for (cur = root_set; cur; cur = cur->next) {
if (cur->flags & MU_CONTAINER_FLAG_DELETE) if (cur->flags & MU_CONTAINER_FLAG_DELETE)
root_set = mu_container_remove_sibling (root_set, cur); root_set = mu_container_remove_sibling (root_set, cur);
else if (cur->flags & MU_CONTAINER_FLAG_SPLICE) { else if (cur->flags & MU_CONTAINER_FLAG_SPLICE) {

View File

@ -1,6 +1,6 @@
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ /* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
/* /*
** **
** Copyright (C) 2008-2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ** Copyright (C) 2008-2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** **
** This program is free software; you can redistribute it and/or modify ** This program is free software; you can redistribute it and/or modify
@ -63,12 +63,12 @@ do_wordexp (const char *path)
/* g_debug ("%s: path is empty", __FUNCTION__); */ /* g_debug ("%s: path is empty", __FUNCTION__); */
return NULL; return NULL;
} }
if (wordexp (path, &wexp, 0) != 0) { if (wordexp (path, &wexp, 0) != 0) {
/* g_debug ("%s: expansion failed for %s", __FUNCTION__, path); */ /* g_debug ("%s: expansion failed for %s", __FUNCTION__, path); */
return NULL; return NULL;
} }
/* we just pick the first one */ /* we just pick the first one */
dir = g_strdup (wexp.we_wordv[0]); dir = g_strdup (wexp.we_wordv[0]);
@ -76,7 +76,7 @@ do_wordexp (const char *path)
so we have to allow for a tiny leak here on that so we have to allow for a tiny leak here on that
platform... maybe instead of __APPLE__ it should be platform... maybe instead of __APPLE__ it should be
__BSD__?*/ __BSD__?*/
#ifndef __APPLE__ #ifndef __APPLE__
wordfree (&wexp); wordfree (&wexp);
#endif /*__APPLE__*/ #endif /*__APPLE__*/
@ -102,16 +102,16 @@ mu_util_dir_expand (const char *path)
/* don't try realpath if the dir does not exist */ /* don't try realpath if the dir does not exist */
if (access (dir, F_OK) != 0) if (access (dir, F_OK) != 0)
return dir; return dir;
/* now resolve any symlinks, .. etc. */ /* now resolve any symlinks, .. etc. */
if (realpath (dir, resolved) == NULL) { if (realpath (dir, resolved) == NULL) {
g_debug ("%s: could not get realpath for '%s': %s", g_debug ("%s: could not get realpath for '%s': %s",
__FUNCTION__, dir, strerror(errno)); __FUNCTION__, dir, strerror(errno));
g_free (dir); g_free (dir);
return NULL; return NULL;
} else } else
g_free (dir); g_free (dir);
return g_strdup (resolved); return g_strdup (resolved);
} }
@ -120,7 +120,7 @@ char*
mu_util_create_tmpdir (void) mu_util_create_tmpdir (void)
{ {
gchar *dirname; gchar *dirname;
dirname = g_strdup_printf ("%s%cmu-%d%c%x", dirname = g_strdup_printf ("%s%cmu-%d%c%x",
g_get_tmp_dir(), g_get_tmp_dir(),
G_DIR_SEPARATOR, G_DIR_SEPARATOR,
@ -141,7 +141,7 @@ const char*
mu_util_cache_dir (void) mu_util_cache_dir (void)
{ {
static char cachedir [PATH_MAX]; static char cachedir [PATH_MAX];
snprintf (cachedir, sizeof(cachedir), "%s%cmu-%u", snprintf (cachedir, sizeof(cachedir), "%s%cmu-%u",
g_get_tmp_dir(), G_DIR_SEPARATOR, g_get_tmp_dir(), G_DIR_SEPARATOR,
getuid()); getuid());
@ -170,9 +170,9 @@ mu_util_init_system (void)
} }
/* g_debug ("setting G_SLICE to always-malloc"); */ /* g_debug ("setting G_SLICE to always-malloc"); */
#endif /*!__linux__*/ #endif /*!__linux__*/
g_type_init (); g_type_init ();
return TRUE; return TRUE;
} }
@ -182,10 +182,10 @@ mu_util_check_dir (const gchar* path, gboolean readable, gboolean writeable)
{ {
int mode; int mode;
struct stat statbuf; struct stat statbuf;
if (!path) if (!path)
return FALSE; return FALSE;
mode = F_OK | (readable ? R_OK : 0) | (writeable ? W_OK : 0); mode = F_OK | (readable ? R_OK : 0) | (writeable ? W_OK : 0);
if (access (path, mode) != 0) { if (access (path, mode) != 0) {
@ -197,7 +197,7 @@ mu_util_check_dir (const gchar* path, gboolean readable, gboolean writeable)
g_debug ("Cannot stat %s: %s", path, strerror (errno)); g_debug ("Cannot stat %s: %s", path, strerror (errno));
return FALSE; return FALSE;
} }
return S_ISDIR(statbuf.st_mode) ? TRUE: FALSE; return S_ISDIR(statbuf.st_mode) ? TRUE: FALSE;
} }
@ -207,18 +207,18 @@ mu_util_guess_maildir (void)
{ {
const gchar *mdir1; const gchar *mdir1;
gchar *mdir2; gchar *mdir2;
/* first, try MAILDIR */ /* first, try MAILDIR */
mdir1 = g_getenv ("MAILDIR"); mdir1 = g_getenv ("MAILDIR");
if (mdir1 && mu_util_check_dir (mdir1, TRUE, FALSE)) if (mdir1 && mu_util_check_dir (mdir1, TRUE, FALSE))
return g_strdup (mdir1); return g_strdup (mdir1);
/* then, try ~/Maildir */ /* then, try ~/Maildir */
mdir2 = mu_util_dir_expand ("~/Maildir"); mdir2 = mu_util_dir_expand ("~/Maildir");
if (mu_util_check_dir (mdir2, TRUE, FALSE)) if (mu_util_check_dir (mdir2, TRUE, FALSE))
return mdir2; return mdir2;
/* nope; nothing found */ /* nope; nothing found */
return NULL; return NULL;
} }
@ -235,7 +235,7 @@ mu_util_guess_mu_homedir (void)
if (!home) if (!home)
MU_WRITE_LOG ("failed to determine homedir"); MU_WRITE_LOG ("failed to determine homedir");
return g_strdup_printf ("%s%c%s", home ? home : ".", G_DIR_SEPARATOR, return g_strdup_printf ("%s%c%s", home ? home : ".", G_DIR_SEPARATOR,
".mu"); ".mu");
} }
@ -244,10 +244,10 @@ gboolean
mu_util_create_dir_maybe (const gchar *path, mode_t mode, gboolean nowarn) mu_util_create_dir_maybe (const gchar *path, mode_t mode, gboolean nowarn)
{ {
struct stat statbuf; struct stat statbuf;
g_return_val_if_fail (path, FALSE); g_return_val_if_fail (path, FALSE);
/* if it exists, it must be a readable dir */ /* if it exists, it must be a readable dir */
if (stat (path, &statbuf) == 0) { if (stat (path, &statbuf) == 0) {
if ((!S_ISDIR(statbuf.st_mode)) || if ((!S_ISDIR(statbuf.st_mode)) ||
(access (path, W_OK|R_OK) != 0)) { (access (path, W_OK|R_OK) != 0)) {
@ -256,8 +256,8 @@ mu_util_create_dir_maybe (const gchar *path, mode_t mode, gboolean nowarn)
"directory: %s", path); "directory: %s", path);
return FALSE; return FALSE;
} }
} }
if (g_mkdir_with_parents (path, mode) != 0) { if (g_mkdir_with_parents (path, mode) != 0) {
if (!nowarn) if (!nowarn)
g_warning ("failed to create %s: %s", g_warning ("failed to create %s: %s",
@ -274,22 +274,22 @@ mu_util_str_from_strv (const gchar **params)
{ {
GString *str; GString *str;
int i; int i;
g_return_val_if_fail (params, NULL); g_return_val_if_fail (params, NULL);
if (!params[0]) if (!params[0])
return g_strdup (""); return g_strdup ("");
str = g_string_sized_new (64); /* just a guess */ str = g_string_sized_new (64); /* just a guess */
for (i = 0; params[i]; ++i) { for (i = 0; params[i]; ++i) {
if (i>0) if (i>0)
g_string_append_c (str, ' '); g_string_append_c (str, ' ');
g_string_append (str, params[i]); g_string_append (str, params[i]);
} }
return g_string_free (str, FALSE); return g_string_free (str, FALSE);
} }
@ -299,7 +299,7 @@ mu_util_create_writeable_fd (const char* path, mode_t mode,
{ {
errno = 0; /* clear! */ errno = 0; /* clear! */
g_return_val_if_fail (path, -1); g_return_val_if_fail (path, -1);
if (overwrite) if (overwrite)
return open (path, O_WRONLY|O_CREAT|O_TRUNC, mode); return open (path, O_WRONLY|O_CREAT|O_TRUNC, mode);
else else
@ -315,11 +315,11 @@ mu_util_is_local_file (const char* path)
* still considered local) */ * still considered local) */
if (g_ascii_strncasecmp ("file://", path, strlen("file://")) == 0) if (g_ascii_strncasecmp ("file://", path, strlen("file://")) == 0)
return TRUE; return TRUE;
if (access (path, R_OK) == 0) if (access (path, R_OK) == 0)
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
@ -329,11 +329,11 @@ mu_util_play (const char *path, gboolean allow_local, gboolean allow_remote)
#ifndef XDGOPEN #ifndef XDGOPEN
g_warning ("opening files not supported (xdg-open missing)"); g_warning ("opening files not supported (xdg-open missing)");
return FALSE; return FALSE;
#else #else
gboolean rv; gboolean rv;
GError *err; GError *err;
const gchar *argv[3]; const gchar *argv[3];
g_return_val_if_fail (path, FALSE); g_return_val_if_fail (path, FALSE);
g_return_val_if_fail (mu_util_is_local_file (path) || allow_remote, g_return_val_if_fail (mu_util_is_local_file (path) || allow_remote,
FALSE); FALSE);
@ -342,11 +342,11 @@ mu_util_play (const char *path, gboolean allow_local, gboolean allow_remote)
argv[0] = XDGOPEN; argv[0] = XDGOPEN;
argv[1] = path; argv[1] = path;
argv[2] = NULL; argv[2] = NULL;
err = NULL; err = NULL;
rv = g_spawn_async (NULL, (gchar**)&argv, NULL, 0, rv = g_spawn_async (NULL, (gchar**)&argv, NULL, 0,
NULL, NULL, NULL, &err); NULL, NULL, NULL, &err);
if (!rv) { if (!rv) {
g_warning ("failed to spawn xdg-open: %s", g_warning ("failed to spawn xdg-open: %s",
err->message ? err->message : "error"); err->message ? err->message : "error");
@ -362,14 +362,14 @@ unsigned char
mu_util_get_dtype_with_lstat (const char *path) mu_util_get_dtype_with_lstat (const char *path)
{ {
struct stat statbuf; struct stat statbuf;
g_return_val_if_fail (path, DT_UNKNOWN); g_return_val_if_fail (path, DT_UNKNOWN);
if (lstat (path, &statbuf) != 0) { if (lstat (path, &statbuf) != 0) {
g_warning ("stat failed on %s: %s", path, strerror(errno)); g_warning ("stat failed on %s: %s", path, strerror(errno));
return DT_UNKNOWN; return DT_UNKNOWN;
} }
/* we only care about dirs, regular files and links */ /* we only care about dirs, regular files and links */
if (S_ISREG (statbuf.st_mode)) if (S_ISREG (statbuf.st_mode))
return DT_REG; return DT_REG;
@ -387,10 +387,10 @@ mu_util_locale_is_utf8 (void)
{ {
const gchar *dummy; const gchar *dummy;
static int is_utf8 = -1; static int is_utf8 = -1;
if (G_UNLIKELY(is_utf8 == -1)) if (G_UNLIKELY(is_utf8 == -1))
is_utf8 = g_get_charset(&dummy) ? 1 : 0; is_utf8 = g_get_charset(&dummy) ? 1 : 0;
return is_utf8 ? TRUE : FALSE; return is_utf8 ? TRUE : FALSE;
} }
@ -399,19 +399,19 @@ mu_util_fputs_encoded (const char *str, FILE *stream)
{ {
char *conv; char *conv;
int rv; int rv;
g_return_val_if_fail (str, FALSE); g_return_val_if_fail (str, FALSE);
g_return_val_if_fail (stream, FALSE); g_return_val_if_fail (stream, FALSE);
/* g_get_charset return TRUE when the locale is UTF8 */ /* g_get_charset return TRUE when the locale is UTF8 */
if (mu_util_locale_is_utf8()) if (mu_util_locale_is_utf8())
rv = fputs (str, stream); rv = fputs (str, stream);
else { /* charset is _not_ utf8, so we actually have to else { /* charset is _not_ utf8, so we actually have to
* convert it..*/ * convert it..*/
GError *err; GError *err;
unsigned bytes; unsigned bytes;
err = NULL; err = NULL;
conv = g_locale_from_utf8 (str, -1, &bytes, NULL, &err); conv = g_locale_from_utf8 (str, -1, &bytes, NULL, &err);
if (err) { if (err) {
/* conversion failed; this happens because is /* conversion failed; this happens because is
@ -427,7 +427,7 @@ mu_util_fputs_encoded (const char *str, FILE *stream)
rv = fputs (conv, stream); rv = fputs (conv, stream);
g_free (conv); g_free (conv);
} }
if (rv == EOF) { /* note, apparently, does not set errno */ if (rv == EOF) { /* note, apparently, does not set errno */
g_printerr ("fputs failed"); g_printerr ("fputs failed");
return FALSE; return FALSE;
@ -442,7 +442,7 @@ print_args (FILE *stream, const char *frm, va_list args)
{ {
gchar *str; gchar *str;
gboolean rv; gboolean rv;
str = g_strdup_vprintf (frm, args); str = g_strdup_vprintf (frm, args);
rv = mu_util_fputs_encoded (str, stream); rv = mu_util_fputs_encoded (str, stream);
@ -460,7 +460,7 @@ mu_util_print_encoded (const char *frm, ...)
gboolean rv; gboolean rv;
g_return_val_if_fail (frm, FALSE); g_return_val_if_fail (frm, FALSE);
va_start (args, frm); va_start (args, frm);
rv = print_args (stdout, frm, args); rv = print_args (stdout, frm, args);
va_end (args); va_end (args);
@ -475,10 +475,12 @@ mu_util_printerr_encoded (const char *frm, ...)
gboolean rv; gboolean rv;
g_return_val_if_fail (frm, FALSE); g_return_val_if_fail (frm, FALSE);
va_start (args, frm); va_start (args, frm);
rv = print_args (stderr, frm, args); rv = print_args (stderr, frm, args);
va_end (args); va_end (args);
return rv; return rv;
} }

View File

@ -255,6 +255,18 @@ typedef gpointer XapianDocument;
typedef gpointer XapianEnquire; typedef gpointer XapianEnquire;
/* print a warning for a GError, and free it */
#define MU_HANDLE_G_ERROR(GE) \
do { \
if (!(GE)) \
g_warning ("%s:%u: an error occured in %s", \
__FILE__, __LINE__, __FUNCTION__); \
else { \
g_warning ("error %u: %s", (GE)->code, (GE)->message); \
g_error_free ((GE)); \
} \
} while (0)
/** /**