aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-util.c
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2012-12-10 21:09:59 +0800
committerMatthew Barnes <mbarnes@redhat.com>2012-12-13 03:33:43 +0800
commitd09d8de870b6697c8a8b262e7e077b871a69b315 (patch)
tree3b718882e7a0bb0a996daf2967a033d91714c9b5 /e-util/e-util.c
parentb61331ed03ac1c7a9b8614e25510040b9c60ae02 (diff)
downloadgsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.gz
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.bz2
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.lz
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.xz
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.zst
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.zip
Consolidate base utility libraries into libeutil.
Evolution consists of entirely too many small utility libraries, which increases linking and loading time, places a burden on higher layers of the application (e.g. modules) which has to remember to link to all the small in-tree utility libraries, and makes it difficult to generate API documentation for these utility libraries in one Gtk-Doc module. Merge the following utility libraries under the umbrella of libeutil, and enforce a single-include policy on libeutil so we can reorganize the files as desired without disrupting its pseudo-public API. libemail-utils/libemail-utils.la libevolution-utils/libevolution-utils.la filter/libfilter.la widgets/e-timezone-dialog/libetimezonedialog.la widgets/menus/libmenus.la widgets/misc/libemiscwidgets.la widgets/table/libetable.la widgets/text/libetext.la This also merges libedataserverui from the Evolution-Data-Server module, since Evolution is its only consumer nowadays, and I'd like to make some improvements to those APIs without concern for backward-compatibility. And finally, start a Gtk-Doc module for libeutil. It's going to be a project just getting all the symbols _listed_ much less _documented_. But the skeletal structure is in place and I'm off to a good start.
Diffstat (limited to 'e-util/e-util.c')
-rw-r--r--e-util/e-util.c1519
1 files changed, 0 insertions, 1519 deletions
diff --git a/e-util/e-util.c b/e-util/e-util.c
deleted file mode 100644
index 8d47da2186..0000000000
--- a/e-util/e-util.c
+++ /dev/null
@@ -1,1519 +0,0 @@
-/*
- * This program 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) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Chris Lahey <clahey@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-/**
- * SECTION: e-util
- * @include: e-util/e-util.h
- **/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <math.h>
-#include <string.h>
-#include <locale.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <gio/gio.h>
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-#include <glib/gstdio.h>
-
-#ifdef G_OS_WIN32
-#include <windows.h>
-#endif
-
-#include <camel/camel.h>
-#include <libedataserver/libedataserver.h>
-
-#include "filter/e-filter-option.h"
-
-#include "e-util.h"
-#include "e-util-private.h"
-
-typedef struct _WindowData WindowData;
-
-struct _WindowData {
- GtkWindow *window;
- GSettings *settings;
- ERestoreWindowFlags flags;
- gint premax_width;
- gint premax_height;
- guint timeout_id;
-};
-
-static void
-window_data_free (WindowData *data)
-{
- if (data->settings != NULL)
- g_object_unref (data->settings);
-
- if (data->timeout_id > 0)
- g_source_remove (data->timeout_id);
-
- g_slice_free (WindowData, data);
-}
-
-static gboolean
-window_update_settings (WindowData *data)
-{
- GSettings *settings = data->settings;
-
- if (data->flags & E_RESTORE_WINDOW_SIZE) {
- GdkWindowState state;
- GdkWindow *window;
- gboolean maximized;
-
- window = gtk_widget_get_window (GTK_WIDGET (data->window));
- state = gdk_window_get_state (window);
- maximized = ((state & GDK_WINDOW_STATE_MAXIMIZED) != 0);
-
- g_settings_set_boolean (settings, "maximized", maximized);
-
- if (!maximized) {
- gint width, height;
-
- gtk_window_get_size (data->window, &width, &height);
-
- g_settings_set_int (settings, "width", width);
- g_settings_set_int (settings, "height", height);
- }
- }
-
- if (data->flags & E_RESTORE_WINDOW_POSITION) {
- gint x, y;
-
- gtk_window_get_position (data->window, &x, &y);
-
- g_settings_set_int (settings, "x", x);
- g_settings_set_int (settings, "y", y);
- }
-
- data->timeout_id = 0;
-
- return FALSE;
-}
-
-static void
-window_delayed_update_settings (WindowData *data)
-{
- if (data->timeout_id > 0)
- g_source_remove (data->timeout_id);
-
- data->timeout_id = g_timeout_add_seconds (
- 1, (GSourceFunc) window_update_settings, data);
-}
-
-static gboolean
-window_configure_event_cb (GtkWindow *window,
- GdkEventConfigure *event,
- WindowData *data)
-{
- window_delayed_update_settings (data);
-
- return FALSE;
-}
-
-static gboolean
-window_state_event_cb (GtkWindow *window,
- GdkEventWindowState *event,
- WindowData *data)
-{
- gboolean window_was_unmaximized;
-
- if (data->timeout_id > 0)
- g_source_remove (data->timeout_id);
-
- window_was_unmaximized =
- ((event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) != 0) &&
- ((event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) == 0);
-
- if (window_was_unmaximized) {
- gint width, height;
-
- width = data->premax_width;
- data->premax_width = 0;
-
- height = data->premax_height;
- data->premax_height = 0;
-
- /* This only applies when the window is initially restored
- * as maximized and is then unmaximized. GTK+ handles the
- * unmaximized window size thereafter. */
- if (width > 0 && height > 0)
- gtk_window_resize (window, width, height);
- }
-
- window_delayed_update_settings (data);
-
- return FALSE;
-}
-
-static gboolean
-window_unmap_cb (GtkWindow *window,
- WindowData *data)
-{
- if (data->timeout_id > 0)
- g_source_remove (data->timeout_id);
-
- /* It's too late to record the window position.
- * gtk_window_get_position() will report (0, 0). */
- data->flags &= ~E_RESTORE_WINDOW_POSITION;
-
- window_update_settings (data);
-
- return FALSE;
-}
-
-/**
- * e_get_accels_filename:
- *
- * Returns the name of the user data file containing custom keyboard
- * accelerator specifications.
- *
- * Returns: filename for accelerator specifications
- **/
-const gchar *
-e_get_accels_filename (void)
-{
- static gchar *filename = NULL;
-
- if (G_UNLIKELY (filename == NULL)) {
- const gchar *config_dir = e_get_user_config_dir ();
- filename = g_build_filename (config_dir, "accels", NULL);
- }
-
- return filename;
-}
-
-/**
- * e_show_uri:
- * @parent: a parent #GtkWindow or %NULL
- * @uri: the URI to show
- *
- * Launches the default application to show the given URI. The URI must
- * be of a form understood by GIO. If the URI cannot be shown, it presents
- * a dialog describing the error. The dialog is set as transient to @parent
- * if @parent is non-%NULL.
- **/
-void
-e_show_uri (GtkWindow *parent,
- const gchar *uri)
-{
- GtkWidget *dialog;
- GdkScreen *screen = NULL;
- GError *error = NULL;
- guint32 timestamp;
-
- g_return_if_fail (uri != NULL);
-
- timestamp = gtk_get_current_event_time ();
-
- if (parent != NULL)
- screen = gtk_widget_get_screen (GTK_WIDGET (parent));
-
- if (gtk_show_uri (screen, uri, timestamp, &error))
- return;
-
- dialog = gtk_message_dialog_new_with_markup (
- parent, GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
- "<big><b>%s</b></big>",
- _("Could not open the link."));
-
- gtk_message_dialog_format_secondary_text (
- GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
-
- gtk_widget_destroy (dialog);
- g_error_free (error);
-}
-
-/**
- * e_display_help:
- * @parent: a parent #GtkWindow or %NULL
- * @link_id: help section to present or %NULL
- *
- * Opens the user documentation to the section given by @link_id, or to the
- * table of contents if @link_id is %NULL. If the user documentation cannot
- * be opened, it presents a dialog describing the error. The dialog is set
- * as transient to @parent if @parent is non-%NULL.
- **/
-void
-e_display_help (GtkWindow *parent,
- const gchar *link_id)
-{
- GString *uri;
- GtkWidget *dialog;
- GdkScreen *screen = NULL;
- GError *error = NULL;
- guint32 timestamp;
-
- uri = g_string_new ("help:" PACKAGE);
- timestamp = gtk_get_current_event_time ();
-
- if (parent != NULL)
- screen = gtk_widget_get_screen (GTK_WIDGET (parent));
-
- if (link_id != NULL)
- g_string_append_printf (uri, "?%s", link_id);
-
- if (gtk_show_uri (screen, uri->str, timestamp, &error))
- goto exit;
-
- dialog = gtk_message_dialog_new_with_markup (
- parent, GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
- "<big><b>%s</b></big>",
- _("Could not display help for Evolution."));
-
- gtk_message_dialog_format_secondary_text (
- GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
-
- gtk_widget_destroy (dialog);
- g_error_free (error);
-
-exit:
- g_string_free (uri, TRUE);
-}
-
-/**
- * e_restore_window:
- * @window: a #GtkWindow
- * @settings_path: a #GSettings path
- * @flags: flags indicating which window features to restore
- *
- * This function can restore one of or both a window's size and position
- * using #GSettings keys at @settings_path which conform to the relocatable
- * schema "org.gnome.evolution.window".
- *
- * If #E_RESTORE_WINDOW_SIZE is present in @flags, restore @window's
- * previously recorded size and maximize state.
- *
- * If #E_RESTORE_WINDOW_POSITION is present in @flags, move @window to
- * the previously recorded screen coordinates.
- *
- * The respective #GSettings values will be updated when the window is
- * resized and/or moved.
- **/
-void
-e_restore_window (GtkWindow *window,
- const gchar *settings_path,
- ERestoreWindowFlags flags)
-{
- WindowData *data;
- GSettings *settings;
- const gchar *schema;
-
- g_return_if_fail (GTK_IS_WINDOW (window));
- g_return_if_fail (settings_path != NULL);
-
- schema = "org.gnome.evolution.window";
- settings = g_settings_new_with_path (schema, settings_path);
-
- data = g_slice_new0 (WindowData);
- data->window = window;
- data->settings = g_object_ref (settings);
- data->flags = flags;
-
- if (flags & E_RESTORE_WINDOW_SIZE) {
- gint width, height;
-
- width = g_settings_get_int (settings, "width");
- height = g_settings_get_int (settings, "height");
-
- if (width > 0 && height > 0)
- gtk_window_resize (window, width, height);
-
- if (g_settings_get_boolean (settings, "maximized")) {
- GdkScreen *screen;
- GdkRectangle monitor_area;
- gint x, y, monitor;
-
- x = g_settings_get_int (settings, "x");
- y = g_settings_get_int (settings, "y");
-
- screen = gtk_window_get_screen (window);
- gtk_window_get_size (window, &width, &height);
-
- data->premax_width = width;
- data->premax_height = height;
-
- monitor = gdk_screen_get_monitor_at_point (screen, x, y);
- if (monitor < 0 || monitor >= gdk_screen_get_n_monitors (screen))
- monitor = 0;
-
- gdk_screen_get_monitor_workarea (screen, monitor, &monitor_area);
-
- gtk_window_resize (window, monitor_area.width, monitor_area.height);
- gtk_window_maximize (window);
- }
- }
-
- if (flags & E_RESTORE_WINDOW_POSITION) {
- gint x, y;
-
- x = g_settings_get_int (settings, "x");
- y = g_settings_get_int (settings, "y");
-
- gtk_window_move (window, x, y);
- }
-
- g_object_set_data_full (
- G_OBJECT (window),
- "e-util-window-data", data,
- (GDestroyNotify) window_data_free);
-
- g_signal_connect (
- window, "configure-event",
- G_CALLBACK (window_configure_event_cb), data);
-
- g_signal_connect (
- window, "window-state-event",
- G_CALLBACK (window_state_event_cb), data);
-
- g_signal_connect (
- window, "unmap",
- G_CALLBACK (window_unmap_cb), data);
-
- g_object_unref (settings);
-}
-
-/**
- * e_lookup_action:
- * @ui_manager: a #GtkUIManager
- * @action_name: the name of an action
- *
- * Returns the first #GtkAction named @action_name by traversing the
- * list of action groups in @ui_manager. If no such action exists, the
- * function emits a critical warning before returning %NULL, since this
- * probably indicates a programming error and most code is not prepared
- * to deal with lookup failures.
- *
- * Returns: the first #GtkAction named @action_name
- **/
-GtkAction *
-e_lookup_action (GtkUIManager *ui_manager,
- const gchar *action_name)
-{
- GtkAction *action = NULL;
- GList *iter;
-
- g_return_val_if_fail (GTK_IS_UI_MANAGER (ui_manager), NULL);
- g_return_val_if_fail (action_name != NULL, NULL);
-
- iter = gtk_ui_manager_get_action_groups (ui_manager);
-
- while (iter != NULL) {
- GtkActionGroup *action_group = iter->data;
-
- action = gtk_action_group_get_action (
- action_group, action_name);
- if (action != NULL)
- return action;
-
- iter = g_list_next (iter);
- }
-
- g_critical ("%s: action '%s' not found", G_STRFUNC, action_name);
-
- return NULL;
-}
-
-/**
- * e_lookup_action_group:
- * @ui_manager: a #GtkUIManager
- * @group_name: the name of an action group
- *
- * Returns the #GtkActionGroup in @ui_manager named @group_name. If no
- * such action group exists, the function emits a critical warnings before
- * returning %NULL, since this probably indicates a programming error and
- * most code is not prepared to deal with lookup failures.
- *
- * Returns: the #GtkActionGroup named @group_name
- **/
-GtkActionGroup *
-e_lookup_action_group (GtkUIManager *ui_manager,
- const gchar *group_name)
-{
- GList *iter;
-
- g_return_val_if_fail (GTK_IS_UI_MANAGER (ui_manager), NULL);
- g_return_val_if_fail (group_name != NULL, NULL);
-
- iter = gtk_ui_manager_get_action_groups (ui_manager);
-
- while (iter != NULL) {
- GtkActionGroup *action_group = iter->data;
- const gchar *name;
-
- name = gtk_action_group_get_name (action_group);
- if (strcmp (name, group_name) == 0)
- return action_group;
-
- iter = g_list_next (iter);
- }
-
- g_critical ("%s: action group '%s' not found", G_STRFUNC, group_name);
-
- return NULL;
-}
-
-/**
- * e_action_compare_by_label:
- * @action1: a #GtkAction
- * @action2: a #GtkAction
- *
- * Compares the labels for @action1 and @action2 using g_utf8_collate().
- *
- * Returns: &lt; 0 if @action1 compares before @action2, 0 if they
- * compare equal, &gt; 0 if @action1 compares after @action2
- **/
-gint
-e_action_compare_by_label (GtkAction *action1,
- GtkAction *action2)
-{
- gchar *label1;
- gchar *label2;
- gint result;
-
- /* XXX This is horribly inefficient but will generally only be
- * used on short lists of actions during UI construction. */
-
- if (action1 == action2)
- return 0;
-
- g_object_get (action1, "label", &label1, NULL);
- g_object_get (action2, "label", &label2, NULL);
-
- result = g_utf8_collate (label1, label2);
-
- g_free (label1);
- g_free (label2);
-
- return result;
-}
-
-/**
- * e_action_group_remove_all_actions:
- * @action_group: a #GtkActionGroup
- *
- * Removes all actions from the action group.
- **/
-void
-e_action_group_remove_all_actions (GtkActionGroup *action_group)
-{
- GList *list, *iter;
-
- /* XXX I've proposed this function for inclusion in GTK+.
- * GtkActionGroup stores actions in an internal hash
- * table and can do this more efficiently by calling
- * g_hash_table_remove_all().
- *
- * http://bugzilla.gnome.org/show_bug.cgi?id=550485 */
-
- g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
-
- list = gtk_action_group_list_actions (action_group);
- for (iter = list; iter != NULL; iter = iter->next)
- gtk_action_group_remove_action (action_group, iter->data);
- g_list_free (list);
-}
-
-/**
- * e_radio_action_get_current_action:
- * @radio_action: a #GtkRadioAction
- *
- * Returns the currently active member of the group to which @radio_action
- * belongs.
- *
- * Returns: the currently active group member
- **/
-GtkRadioAction *
-e_radio_action_get_current_action (GtkRadioAction *radio_action)
-{
- GSList *group;
- gint current_value;
-
- g_return_val_if_fail (GTK_IS_RADIO_ACTION (radio_action), NULL);
-
- group = gtk_radio_action_get_group (radio_action);
- current_value = gtk_radio_action_get_current_value (radio_action);
-
- while (group != NULL) {
- gint value;
-
- radio_action = GTK_RADIO_ACTION (group->data);
- g_object_get (radio_action, "value", &value, NULL);
-
- if (value == current_value)
- return radio_action;
-
- group = g_slist_next (group);
- }
-
- return NULL;
-}
-
-/**
- * e_action_group_add_actions_localized:
- * @action_group: a #GtkActionGroup to add @entries to
- * @translation_domain: a translation domain to use
- * to translate label and tooltip strings in @entries
- * @entries: (array length=n_entries): an array of action descriptions
- * @n_entries: the number of entries
- * @user_data: data to pass to the action callbacks
- *
- * Adds #GtkAction-s defined by @entries to @action_group, with action's
- * label and tooltip localized in the given translation domain, instead
- * of the domain set on the @action_group.
- *
- * Since: 3.4
- **/
-void
-e_action_group_add_actions_localized (GtkActionGroup *action_group,
- const gchar *translation_domain,
- const GtkActionEntry *entries,
- guint n_entries,
- gpointer user_data)
-{
- GtkActionGroup *tmp_group;
- GList *list, *iter;
- gint ii;
-
- g_return_if_fail (action_group != NULL);
- g_return_if_fail (entries != NULL);
- g_return_if_fail (n_entries > 0);
- g_return_if_fail (translation_domain != NULL);
- g_return_if_fail (*translation_domain);
-
- tmp_group = gtk_action_group_new ("temporary-group");
- gtk_action_group_set_translation_domain (tmp_group, translation_domain);
- gtk_action_group_add_actions (tmp_group, entries, n_entries, user_data);
-
- list = gtk_action_group_list_actions (tmp_group);
- for (iter = list; iter != NULL; iter = iter->next) {
- GtkAction *action = GTK_ACTION (iter->data);
- const gchar *action_name;
-
- g_object_ref (action);
-
- action_name = gtk_action_get_name (action);
-
- for (ii = 0; ii < n_entries; ii++) {
- if (g_strcmp0 (entries[ii].name, action_name) == 0) {
- gtk_action_group_remove_action (
- tmp_group, action);
- gtk_action_group_add_action_with_accel (
- action_group, action,
- entries[ii].accelerator);
- break;
- }
- }
-
- g_object_unref (action);
- }
-
- g_list_free (list);
- g_object_unref (tmp_group);
-}
-
-/* Helper for e_categories_add_change_hook() */
-static void
-categories_changed_cb (GObject *useless_opaque_object,
- GHookList *hook_list)
-{
- /* e_categories_register_change_listener() is broken because
- * it requires callbacks to allow for some opaque GObject as
- * the first argument (not does it document this). */
- g_hook_list_invoke (hook_list, FALSE);
-}
-
-/* Helper for e_categories_add_change_hook() */
-static void
-categories_weak_notify_cb (GHookList *hook_list,
- gpointer where_the_object_was)
-{
- GHook *hook;
-
- /* This should not happen, but if we fail to find the hook for
- * some reason, g_hook_destroy_link() will warn about the NULL
- * pointer, which is all we would do anyway so no need to test
- * for it ourselves. */
- hook = g_hook_find_data (hook_list, TRUE, where_the_object_was);
- g_hook_destroy_link (hook_list, hook);
-}
-
-/**
- * e_categories_add_change_hook:
- * @func: a hook function
- * @object: a #GObject to be passed to @func, or %NULL
- *
- * A saner alternative to e_categories_register_change_listener().
- *
- * Adds a hook function to be called when a category is added, removed or
- * modified. If @object is not %NULL, the hook function is automatically
- * removed when @object is finalized.
- **/
-void
-e_categories_add_change_hook (GHookFunc func,
- gpointer object)
-{
- static gboolean initialized = FALSE;
- static GHookList hook_list;
- GHook *hook;
-
- g_return_if_fail (func != NULL);
-
- if (object != NULL)
- g_return_if_fail (G_IS_OBJECT (object));
-
- if (!initialized) {
- g_hook_list_init (&hook_list, sizeof (GHook));
- e_categories_register_change_listener (
- G_CALLBACK (categories_changed_cb), &hook_list);
- initialized = TRUE;
- }
-
- hook = g_hook_alloc (&hook_list);
-
- hook->func = func;
- hook->data = object;
-
- if (object != NULL)
- g_object_weak_ref (
- G_OBJECT (object), (GWeakNotify)
- categories_weak_notify_cb, &hook_list);
-
- g_hook_append (&hook_list, hook);
-}
-
-/**
- * e_str_without_underscores:
- * @string: the string to strip underscores from
- *
- * Strips underscores from a string in the same way
- * @gtk_label_new_with_mnemonics does. The returned string should be freed
- * using g_free().
- *
- * Returns: a newly-allocated string without underscores
- */
-gchar *
-e_str_without_underscores (const gchar *string)
-{
- gchar *new_string;
- const gchar *sp;
- gchar *dp;
-
- new_string = g_malloc (strlen (string) + 1);
-
- dp = new_string;
- for (sp = string; *sp != '\0'; sp++) {
- if (*sp != '_') {
- *dp = *sp;
- dp++;
- } else if (sp[1] == '_') {
- /* Translate "__" in "_". */
- *dp = '_';
- dp++;
- sp++;
- }
- }
- *dp = 0;
-
- return new_string;
-}
-
-gint
-e_str_compare (gconstpointer x,
- gconstpointer y)
-{
- if (x == NULL || y == NULL) {
- if (x == y)
- return 0;
- else
- return x ? -1 : 1;
- }
-
- return strcmp (x, y);
-}
-
-gint
-e_str_case_compare (gconstpointer x,
- gconstpointer y)
-{
- gchar *cx, *cy;
- gint res;
-
- if (x == NULL || y == NULL) {
- if (x == y)
- return 0;
- else
- return x ? -1 : 1;
- }
-
- cx = g_utf8_casefold (x, -1);
- cy = g_utf8_casefold (y, -1);
-
- res = g_utf8_collate (cx, cy);
-
- g_free (cx);
- g_free (cy);
-
- return res;
-}
-
-gint
-e_collate_compare (gconstpointer x,
- gconstpointer y)
-{
- if (x == NULL || y == NULL) {
- if (x == y)
- return 0;
- else
- return x ? -1 : 1;
- }
-
- return g_utf8_collate (x, y);
-}
-
-gint
-e_int_compare (gconstpointer x,
- gconstpointer y)
-{
- gint nx = GPOINTER_TO_INT (x);
- gint ny = GPOINTER_TO_INT (y);
-
- return (nx == ny) ? 0 : (nx < ny) ? -1 : 1;
-}
-
-/**
- * e_color_to_value:
- * @color: a #GdkColor
- *
- * Converts a #GdkColor to a 24-bit RGB color value.
- *
- * Returns: a 24-bit color value
- **/
-guint32
-e_color_to_value (GdkColor *color)
-{
- GdkRGBA rgba;
-
- g_return_val_if_fail (color != NULL, 0);
-
- rgba.red = color->red / 65535.0;
- rgba.green = color->green / 65535.0;
- rgba.blue = color->blue / 65535.0;
- rgba.alpha = 0.0;
-
- return e_rgba_to_value (&rgba);
-}
-
-/**
- * e_rgba_to_value:
- * @rgba: a #GdkRGBA
- *
- *
- * Converts #GdkRGBA to a 24-bit RGB color value
- *
- * Returns: a 24-bit color value
- **/
-guint32
-e_rgba_to_value (GdkRGBA *rgba)
-{
- guint16 red;
- guint16 green;
- guint16 blue;
-
- g_return_val_if_fail (rgba != NULL, 0);
-
- red = 255 * rgba->red;
- green = 255 * rgba->green;
- blue = 255 * rgba->blue;
-
- return (guint32)
- ((((red & 0xFF) << 16) |
- ((green & 0xFF) << 8) |
- (blue & 0xFF)) & 0xffffff);
-}
-
-static gint
-epow10 (gint number)
-{
- gint value = 1;
-
- while (number-- > 0)
- value *= 10;
-
- return value;
-}
-
-gchar *
-e_format_number (gint number)
-{
- GList *iterator, *list = NULL;
- struct lconv *locality;
- gint char_length = 0;
- gint group_count = 0;
- gchar *grouping;
- gint last_count = 3;
- gint divider;
- gchar *value;
- gchar *value_iterator;
-
- locality = localeconv ();
- grouping = locality->grouping;
- while (number) {
- gchar *group;
- switch (*grouping) {
- default:
- last_count = *grouping;
- grouping++;
- case 0:
- divider = epow10 (last_count);
- if (number >= divider) {
- group = g_strdup_printf (
- "%0*d", last_count, number % divider);
- } else {
- group = g_strdup_printf (
- "%d", number % divider);
- }
- number /= divider;
- break;
- case CHAR_MAX:
- group = g_strdup_printf ("%d", number);
- number = 0;
- break;
- }
- char_length += strlen (group);
- list = g_list_prepend (list, group);
- group_count++;
- }
-
- if (list) {
- value = g_new (
- gchar, 1 + char_length + (group_count - 1) *
- strlen (locality->thousands_sep));
-
- iterator = list;
- value_iterator = value;
-
- strcpy (value_iterator, iterator->data);
- value_iterator += strlen (iterator->data);
- for (iterator = iterator->next; iterator; iterator = iterator->next) {
- strcpy (value_iterator, locality->thousands_sep);
- value_iterator += strlen (locality->thousands_sep);
-
- strcpy (value_iterator, iterator->data);
- value_iterator += strlen (iterator->data);
- }
- g_list_foreach (list, (GFunc) g_free, NULL);
- g_list_free (list);
- return value;
- } else {
- return g_strdup ("0");
- }
-}
-
-/* Perform a binary search for key in base which has nmemb elements
- * of size bytes each. The comparisons are done by (*compare)(). */
-void
-e_bsearch (gconstpointer key,
- gconstpointer base,
- gsize nmemb,
- gsize size,
- ESortCompareFunc compare,
- gpointer closure,
- gsize *start,
- gsize *end)
-{
- gsize l, u, idx;
- gconstpointer p;
- gint comparison;
- if (!(start || end))
- return;
-
- l = 0;
- u = nmemb;
- while (l < u) {
- idx = (l + u) / 2;
- p = (((const gchar *) base) + (idx * size));
- comparison = (*compare) (key, p, closure);
- if (comparison < 0)
- u = idx;
- else if (comparison > 0)
- l = idx + 1;
- else {
- gsize lsave, usave;
- lsave = l;
- usave = u;
- if (start) {
- while (l < u) {
- idx = (l + u) / 2;
- p = (((const gchar *) base) + (idx * size));
- comparison = (*compare) (key, p, closure);
- if (comparison <= 0)
- u = idx;
- else
- l = idx + 1;
- }
- *start = l;
-
- l = lsave;
- u = usave;
- }
- if (end) {
- while (l < u) {
- idx = (l + u) / 2;
- p = (((const gchar *) base) + (idx * size));
- comparison = (*compare) (key, p, closure);
- if (comparison < 0)
- u = idx;
- else
- l = idx + 1;
- }
- *end = l;
- }
- return;
- }
- }
-
- if (start)
- *start = l;
- if (end)
- *end = l;
-}
-
-/* Function to do a last minute fixup of the AM/PM stuff if the locale
- * and gettext haven't done it right. Most English speaking countries
- * except the USA use the 24 hour clock (UK, Australia etc). However
- * since they are English nobody bothers to write a language
- * translation (gettext) file. So the locale turns off the AM/PM, but
- * gettext does not turn on the 24 hour clock. Leaving a mess.
- *
- * This routine checks if AM/PM are defined in the locale, if not it
- * forces the use of the 24 hour clock.
- *
- * The function itself is a front end on strftime and takes exactly
- * the same arguments.
- *
- * TODO: Actually remove the '%p' from the fixed up string so that
- * there isn't a stray space.
- */
-
-gsize
-e_strftime_fix_am_pm (gchar *str,
- gsize max,
- const gchar *fmt,
- const struct tm *tm)
-{
- gchar buf[10];
- gchar *sp;
- gchar *ffmt;
- gsize ret;
-
- if (strstr (fmt, "%p") == NULL && strstr (fmt, "%P") == NULL) {
- /* No AM/PM involved - can use the fmt string directly */
- ret = e_strftime (str, max, fmt, tm);
- } else {
- /* Get the AM/PM symbol from the locale */
- e_strftime (buf, 10, "%p", tm);
-
- if (buf[0]) {
- /* AM/PM have been defined in the locale
- * so we can use the fmt string directly. */
- ret = e_strftime (str, max, fmt, tm);
- } else {
- /* No AM/PM defined by locale
- * must change to 24 hour clock. */
- ffmt = g_strdup (fmt);
- for (sp = ffmt; (sp = strstr (sp, "%l")); sp++) {
- /* Maybe this should be 'k', but I have never
- * seen a 24 clock actually use that format. */
- sp[1]='H';
- }
- for (sp = ffmt; (sp = strstr (sp, "%I")); sp++) {
- sp[1]='H';
- }
- ret = e_strftime (str, max, ffmt, tm);
- g_free (ffmt);
- }
- }
-
- return (ret);
-}
-
-gsize
-e_utf8_strftime_fix_am_pm (gchar *str,
- gsize max,
- const gchar *fmt,
- const struct tm *tm)
-{
- gsize sz, ret;
- gchar *locale_fmt, *buf;
-
- locale_fmt = g_locale_from_utf8 (fmt, -1, NULL, &sz, NULL);
- if (!locale_fmt)
- return 0;
-
- ret = e_strftime_fix_am_pm (str, max, locale_fmt, tm);
- if (!ret) {
- g_free (locale_fmt);
- return 0;
- }
-
- buf = g_locale_to_utf8 (str, ret, NULL, &sz, NULL);
- if (!buf) {
- g_free (locale_fmt);
- return 0;
- }
-
- if (sz >= max) {
- gchar *tmp = buf + max - 1;
- tmp = g_utf8_find_prev_char (buf, tmp);
- if (tmp)
- sz = tmp - buf;
- else
- sz = 0;
- }
- memcpy (str, buf, sz);
- str[sz] = '\0';
- g_free (locale_fmt);
- g_free (buf);
- return sz;
-}
-
-/**
- * e_get_month_name:
- * @month: month index
- * @abbreviated: if %TRUE, abbreviate the month name
- *
- * Returns the localized name for @month. If @abbreviated is %TRUE,
- * returns the locale's abbreviated month name.
- *
- * Returns: localized month name
- **/
-const gchar *
-e_get_month_name (GDateMonth month,
- gboolean abbreviated)
-{
- /* Make the indices correspond to the enum values. */
- static const gchar *abbr_names[G_DATE_DECEMBER + 1];
- static const gchar *full_names[G_DATE_DECEMBER + 1];
- static gboolean first_time = TRUE;
-
- g_return_val_if_fail (month >= G_DATE_JANUARY, NULL);
- g_return_val_if_fail (month <= G_DATE_DECEMBER, NULL);
-
- if (G_UNLIKELY (first_time)) {
- gchar buffer[256];
- GDateMonth ii;
- GDate date;
-
- memset (abbr_names, 0, sizeof (abbr_names));
- memset (full_names, 0, sizeof (full_names));
-
- /* First Julian day was in January. */
- g_date_set_julian (&date, 1);
-
- for (ii = G_DATE_JANUARY; ii <= G_DATE_DECEMBER; ii++) {
- g_date_strftime (buffer, sizeof (buffer), "%b", &date);
- abbr_names[ii] = g_intern_string (buffer);
- g_date_strftime (buffer, sizeof (buffer), "%B", &date);
- full_names[ii] = g_intern_string (buffer);
- g_date_add_months (&date, 1);
- }
-
- first_time = FALSE;
- }
-
- return abbreviated ? abbr_names[month] : full_names[month];
-}
-
-/**
- * e_get_weekday_name:
- * @weekday: weekday index
- * @abbreviated: if %TRUE, abbreviate the weekday name
- *
- * Returns the localized name for @weekday. If @abbreviated is %TRUE,
- * returns the locale's abbreviated weekday name.
- *
- * Returns: localized weekday name
- **/
-const gchar *
-e_get_weekday_name (GDateWeekday weekday,
- gboolean abbreviated)
-{
- /* Make the indices correspond to the enum values. */
- static const gchar *abbr_names[G_DATE_SUNDAY + 1];
- static const gchar *full_names[G_DATE_SUNDAY + 1];
- static gboolean first_time = TRUE;
-
- g_return_val_if_fail (weekday >= G_DATE_MONDAY, NULL);
- g_return_val_if_fail (weekday <= G_DATE_SUNDAY, NULL);
-
- if (G_UNLIKELY (first_time)) {
- gchar buffer[256];
- GDateWeekday ii;
- GDate date;
-
- memset (abbr_names, 0, sizeof (abbr_names));
- memset (full_names, 0, sizeof (full_names));
-
- /* First Julian day was a Monday. */
- g_date_set_julian (&date, 1);
-
- for (ii = G_DATE_MONDAY; ii <= G_DATE_SUNDAY; ii++) {
- g_date_strftime (buffer, sizeof (buffer), "%a", &date);
- abbr_names[ii] = g_intern_string (buffer);
- g_date_strftime (buffer, sizeof (buffer), "%A", &date);
- full_names[ii] = g_intern_string (buffer);
- g_date_add_days (&date, 1);
- }
-
- first_time = FALSE;
- }
-
- return abbreviated ? abbr_names[weekday] : full_names[weekday];
-}
-
-/* Evolution Locks for crash recovery */
-static const gchar *
-get_lock_filename (void)
-{
- static gchar *filename = NULL;
-
- if (G_UNLIKELY (filename == NULL))
- filename = g_build_filename (
- e_get_user_config_dir (), ".running", NULL);
-
- return filename;
-}
-
-gboolean
-e_file_lock_create (void)
-{
- const gchar *filename = get_lock_filename ();
- gboolean status = FALSE;
- FILE *file;
-
- file = g_fopen (filename, "w");
- if (file != NULL) {
- /* The lock file also serves as a PID file. */
- g_fprintf (
- file, "%" G_GINT64_FORMAT "\n",
- (gint64) getpid ());
- fclose (file);
- status = TRUE;
- } else {
- const gchar *errmsg = g_strerror (errno);
- g_warning ("Lock file creation failed: %s", errmsg);
- }
-
- return status;
-}
-
-void
-e_file_lock_destroy (void)
-{
- const gchar *filename = get_lock_filename ();
-
- if (g_unlink (filename) == -1) {
- const gchar *errmsg = g_strerror (errno);
- g_warning ("Lock file deletion failed: %s", errmsg);
- }
-}
-
-gboolean
-e_file_lock_exists (void)
-{
- const gchar *filename = get_lock_filename ();
-
- return g_file_test (filename, G_FILE_TEST_EXISTS);
-}
-
-/**
- * e_util_guess_mime_type:
- * @filename: a local file name, or URI
- * @localfile: %TRUE to check the file content, FALSE to check only the name
- *
- * Tries to determine the MIME type for @filename. Free the returned
- * string with g_free().
- *
- * Returns: the MIME type of @filename, or %NULL if the the MIME type could
- * not be determined
- **/
-gchar *
-e_util_guess_mime_type (const gchar *filename,
- gboolean localfile)
-{
- gchar *mime_type = NULL;
-
- g_return_val_if_fail (filename != NULL, NULL);
-
- if (localfile) {
- GFile *file;
- GFileInfo *fi;
-
- if (strstr (filename, "://"))
- file = g_file_new_for_uri (filename);
- else
- file = g_file_new_for_path (filename);
-
- fi = g_file_query_info (
- file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
- G_FILE_QUERY_INFO_NONE, NULL, NULL);
- if (fi) {
- mime_type = g_content_type_get_mime_type (
- g_file_info_get_content_type (fi));
- g_object_unref (fi);
- }
-
- g_object_unref (file);
- }
-
- if (!mime_type) {
- /* file doesn't exists locally, thus guess based on the filename */
- gboolean uncertain = FALSE;
- gchar *content_type;
-
- content_type = g_content_type_guess (filename, NULL, 0, &uncertain);
- if (content_type) {
- mime_type = g_content_type_get_mime_type (content_type);
- g_free (content_type);
- }
- }
-
- return mime_type;
-}
-
-/* XXX: Should e-util/ really depend on filter/ ?? */
-GSList *
-e_util_get_category_filter_options (void)
-{
- GSList *res = NULL;
- GList *clist, *l;
-
- clist = e_categories_get_list ();
- for (l = clist; l; l = l->next) {
- const gchar *cname = l->data;
- struct _filter_option *fo;
-
- if (!e_categories_is_searchable (cname))
- continue;
-
- fo = g_new0 (struct _filter_option, 1);
-
- fo->title = g_strdup (cname);
- fo->value = g_strdup (cname);
- res = g_slist_prepend (res, fo);
- }
-
- g_list_free (clist);
-
- return g_slist_reverse (res);
-}
-
-/**
- * e_util_get_searchable_categories:
- *
- * Returns list of searchable categories only. The list should
- * be freed with g_list_free() when done with it, but the items
- * are internal strings, names of categories, which should not
- * be touched in other than read-only way, in other words the same
- * restrictions as for e_categories_get_list() applies here too.
- **/
-GList *
-e_util_get_searchable_categories (void)
-{
- GList *res = NULL, *all_categories, *l;
-
- all_categories = e_categories_get_list ();
- for (l = all_categories; l; l = l->next) {
- const gchar *cname = l->data;
-
- if (e_categories_is_searchable (cname))
- res = g_list_prepend (res, (gpointer) cname);
- }
-
- g_list_free (all_categories);
-
- return g_list_reverse (res);
-}
-
-/**
- * e_binding_transform_color_to_string:
- * @binding: a #GBinding
- * @source_value: a #GValue of type #GDK_TYPE_COLOR
- * @target_value: a #GValue of type #G_TYPE_STRING
- * @not_used: not used
- *
- * Transforms a #GdkColor value to a color string specification.
- *
- * Returns: %TRUE always
- **/
-gboolean
-e_binding_transform_color_to_string (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer not_used)
-{
- const GdkColor *color;
- gchar *string;
-
- g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
-
- color = g_value_get_boxed (source_value);
- if (!color) {
- g_value_set_string (target_value, "");
- } else {
- /* encode color manually, because css styles expect colors in #rrggbb,
- * not in #rrrrggggbbbb, which is a result of gdk_color_to_string()
- */
- string = g_strdup_printf (
- "#%02x%02x%02x",
- (gint) color->red * 256 / 65536,
- (gint) color->green * 256 / 65536,
- (gint) color->blue * 256 / 65536);
- g_value_set_string (target_value, string);
- g_free (string);
- }
-
- return TRUE;
-}
-
-/**
- * e_binding_transform_string_to_color:
- * @binding: a #GBinding
- * @source_value: a #GValue of type #G_TYPE_STRING
- * @target_value: a #GValue of type #GDK_TYPE_COLOR
- * @not_used: not used
- *
- * Transforms a color string specification to a #GdkColor.
- *
- * Returns: %TRUE if color string specification was valid
- **/
-gboolean
-e_binding_transform_string_to_color (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- gpointer not_used)
-{
- GdkColor color;
- const gchar *string;
- gboolean success = FALSE;
-
- g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
-
- string = g_value_get_string (source_value);
- if (gdk_color_parse (string, &color)) {
- g_value_set_boxed (target_value, &color);
- success = TRUE;
- }
-
- return success;
-}
-
-/**
- * e_binding_transform_source_to_uid:
- * @binding: a #GBinding
- * @source_value: a #GValue of type #E_TYPE_SOURCE
- * @target_value: a #GValue of type #G_TYPE_STRING
- * @registry: an #ESourceRegistry
- *
- * Transforms an #ESource object to its UID string.
- *
- * Returns: %TRUE if @source_value was an #ESource object
- **/
-gboolean
-e_binding_transform_source_to_uid (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- ESourceRegistry *registry)
-{
- ESource *source;
- const gchar *string;
- gboolean success = FALSE;
-
- g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
- g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
-
- source = g_value_get_object (source_value);
- if (E_IS_SOURCE (source)) {
- string = e_source_get_uid (source);
- g_value_set_string (target_value, string);
- success = TRUE;
- }
-
- return success;
-}
-
-/**
- * e_binding_transform_uid_to_source:
- * @binding: a #GBinding
- * @source_value: a #GValue of type #G_TYPE_STRING
- * @target_value: a #GValue of type #E_TYPE_SOURCe
- * @registry: an #ESourceRegistry
- *
- * Transforms an #ESource UID string to the corresponding #ESource object
- * in @registry.
- *
- * Returns: %TRUE if @registry had an #ESource object with a matching
- * UID string
- **/
-gboolean
-e_binding_transform_uid_to_source (GBinding *binding,
- const GValue *source_value,
- GValue *target_value,
- ESourceRegistry *registry)
-{
- ESource *source;
- const gchar *string;
- gboolean success = FALSE;
-
- g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
- g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
-
- string = g_value_get_string (source_value);
- if (string == NULL || *string == '\0')
- return FALSE;
-
- source = e_source_registry_ref_source (registry, string);
- if (source != NULL) {
- g_value_take_object (target_value, source);
- success = TRUE;
- }
-
- return success;
-}