* mu-threader, mu-util: cleanups
This commit is contained in:
@ -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) {
|
||||||
|
|||||||
102
src/mu-util.c
102
src/mu-util.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user